Socket
Socket
Sign inDemoInstall

react-native-tscodegen

Package Overview
Dependencies
Maintainers
3
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-native-tscodegen - npm Package Compare versions

Comparing version 0.66.1 to 0.67.0

lib/rncodegen/scripts/build.js

16

CHANGELOG.json

@@ -5,3 +5,17 @@ {

{
"date": "Wed, 12 Aug 2020 22:27:19 GMT",
"date": "Sat, 27 Feb 2021 02:56:20 GMT",
"tag": "react-native-tscodegen_v0.67.0",
"version": "0.67.0",
"comments": {
"minor": [
{
"comment": "catch up to react-native 0.64",
"author": "zihanc@microsoft.com",
"commit": "a15efdc739c0941922c5f9807eefa2541bf026ee"
}
]
}
},
{
"date": "Wed, 12 Aug 2020 22:27:25 GMT",
"tag": "react-native-tscodegen_v0.66.1",

@@ -8,0 +22,0 @@ "version": "0.66.1",

10

CHANGELOG.md
# Change Log - react-native-tscodegen
This log was last generated on Wed, 12 Aug 2020 22:27:19 GMT and should not be manually modified.
This log was last generated on Sat, 27 Feb 2021 02:56:20 GMT and should not be manually modified.
## 0.67.0
Sat, 27 Feb 2021 02:56:20 GMT
### Minor changes
- catch up to react-native 0.64 (zihanc@microsoft.com)
## 0.66.1
Wed, 12 Aug 2020 22:27:19 GMT
Wed, 12 Aug 2020 22:27:25 GMT

@@ -8,0 +14,0 @@ ### Patches

@@ -20,3 +20,5 @@ "use strict";

'shadow-nodes',
'modules'
'modulesAndroid',
'modulesCxx',
'modulesIOS'
];

@@ -23,0 +25,0 @@ var config = JSON.parse(fs_1.readFileSync(process.argv[2], { encoding: 'utf-8' }));

@@ -0,1 +1,2 @@

export declare type PlatformType = 'iOS' | 'android';
export declare type CommandsFunctionTypeAnnotation = Readonly<{

@@ -9,3 +10,7 @@ type: 'FunctionTypeAnnotation';

}>;
export declare type CommandsTypeAnnotation = BooleanTypeAnnotation | Int32TypeAnnotation | DoubleTypeAnnotation | FloatTypeAnnotation | StringTypeAnnotation;
export declare type CommandsTypeAnnotation = ReservedFunctionValueTypeAnnotation | BooleanTypeAnnotation | Int32TypeAnnotation | DoubleTypeAnnotation | FloatTypeAnnotation | StringTypeAnnotation;
export declare type ReservedFunctionValueTypeAnnotation = Readonly<{
type: 'ReservedFunctionValueTypeAnnotation';
name: ReservedFunctionValueTypeName;
}>;
export declare type DoubleTypeAnnotation = Readonly<{

@@ -26,3 +31,3 @@ type: 'DoubleTypeAnnotation';

}>;
export declare type ObjectPropertyType = Readonly<{
export declare type EventObjectPropertyType = Readonly<{
type: 'BooleanTypeAnnotation';

@@ -58,3 +63,3 @@ name: string;

optional: boolean;
properties: ReadonlyArray<ObjectPropertyType>;
properties: ReadonlyArray<EventObjectPropertyType>;
}>;

@@ -131,55 +136,2 @@ export declare type PropTypeTypeAnnotation = Readonly<{

}>;
export declare type PrimitiveTypeAnnotationType = 'StringTypeAnnotation' | 'NumberTypeAnnotation' | 'Int32TypeAnnotation' | 'DoubleTypeAnnotation' | 'FloatTypeAnnotation' | 'BooleanTypeAnnotation' | 'GenericObjectTypeAnnotation';
export declare type PrimitiveTypeAnnotation = Readonly<{
type: PrimitiveTypeAnnotationType;
}>;
export declare type ReservedFunctionValueTypeName = 'RootTag';
export declare type FunctionTypeAnnotationParamTypeAnnotation = Readonly<{
type: 'AnyTypeAnnotation' | 'FunctionTypeAnnotation' | PrimitiveTypeAnnotationType;
}> | Readonly<{
type: 'ArrayTypeAnnotation';
elementType: (undefined | FunctionTypeAnnotationParamTypeAnnotation);
}> | Readonly<{
type: 'ObjectTypeAnnotation';
properties: (undefined | ReadonlyArray<ObjectParamTypeAnnotation>);
}> | Readonly<{
type: 'ReservedFunctionValueTypeAnnotation';
name: ReservedFunctionValueTypeName;
}>;
export declare type FunctionTypeAnnotationReturnArrayElementType = FunctionTypeAnnotationParamTypeAnnotation;
export declare type ObjectParamTypeAnnotation = Readonly<{
optional: boolean;
name: string;
typeAnnotation: FunctionTypeAnnotationParamTypeAnnotation;
}>;
export declare type FunctionTypeAnnotationReturn = Readonly<{
nullable: boolean;
type: PrimitiveTypeAnnotationType | 'VoidTypeAnnotation' | 'GenericPromiseTypeAnnotation';
}> | Readonly<{
nullable: boolean;
type: 'ArrayTypeAnnotation';
elementType: (undefined | FunctionTypeAnnotationReturnArrayElementType);
}> | Readonly<{
nullable: boolean;
type: 'ObjectTypeAnnotation';
properties: (undefined | ReadonlyArray<ObjectParamTypeAnnotation>);
}>;
export declare type FunctionTypeAnnotationParam = Readonly<{
nullable: boolean;
name: string;
typeAnnotation: FunctionTypeAnnotationParamTypeAnnotation;
}>;
export declare type FunctionTypeAnnotation = Readonly<{
type: 'FunctionTypeAnnotation';
params: ReadonlyArray<FunctionTypeAnnotationParam>;
returnTypeAnnotation: FunctionTypeAnnotationReturn;
optional: boolean;
}>;
export declare type MethodTypeShape = Readonly<{
name: string;
typeAnnotation: FunctionTypeAnnotation;
}>;
export declare type NativeModuleShape = Readonly<{
properties: ReadonlyArray<MethodTypeShape>;
}>;
export declare type EventTypeShape = Readonly<{

@@ -194,3 +146,3 @@ name: string;

type: 'ObjectTypeAnnotation';
properties: ReadonlyArray<ObjectPropertyType>;
properties: ReadonlyArray<EventObjectPropertyType>;
}>;

@@ -207,3 +159,3 @@ }>;

paperComponentName?: string;
excludedPlatform?: 'iOS' | 'android';
excludedPlatforms?: ReadonlyArray<PlatformType>;
paperComponentNameDeprecated?: string;

@@ -223,11 +175,98 @@ }>;

modules: Readonly<{
[module: string]: Readonly<{
components?: Readonly<{
[component: string]: ComponentShape;
}>;
nativeModules?: Readonly<{
[nativeModule: string]: NativeModuleShape;
}>;
}>;
[hasteModuleName: string]: ComponentSchema | NativeModuleSchema;
}>;
}>;
export declare type ComponentSchema = Readonly<{
type: 'Component';
components: Readonly<{
[componentName: string]: ComponentShape;
}>;
}>;
export declare type Nullable<T extends NativeModuleTypeAnnotation> = NullableTypeAnnotation<T> | T;
export declare type NullableTypeAnnotation<T extends NativeModuleTypeAnnotation> = Readonly<{
type: 'NullableTypeAnnotation';
typeAnnotation: T;
}>;
export declare type NativeModuleSchema = Readonly<{
type: 'NativeModule';
aliases: NativeModuleAliasMap;
spec: NativeModuleSpec;
moduleNames: ReadonlyArray<string>;
excludedPlatforms?: ReadonlyArray<PlatformType>;
}>;
export declare type NativeModuleSpec = Readonly<{
properties: ReadonlyArray<NativeModulePropertySchema>;
}>;
export declare type NativeModulePropertySchema = Readonly<{
name: string;
optional: boolean;
typeAnnotation: Nullable<NativeModuleFunctionTypeAnnotation>;
}>;
export declare type NativeModuleAliasMap = Readonly<{
[aliasName: string]: NativeModuleObjectTypeAnnotation;
}>;
export declare type NativeModuleFunctionTypeAnnotation = Readonly<{
type: 'FunctionTypeAnnotation';
params: ReadonlyArray<NativeModuleMethodParamSchema>;
returnTypeAnnotation: Nullable<NativeModuleReturnTypeAnnotation>;
}>;
export declare type NativeModuleMethodParamSchema = Readonly<{
name: string;
optional: boolean;
typeAnnotation: Nullable<NativeModuleParamTypeAnnotation>;
}>;
export declare type NativeModuleObjectTypeAnnotation = Readonly<{
type: 'ObjectTypeAnnotation';
properties: ReadonlyArray<NativeModuleObjectTypeAnnotationPropertySchema>;
}>;
export declare type NativeModuleObjectTypeAnnotationPropertySchema = Readonly<{
name: string;
optional: boolean;
typeAnnotation: Nullable<NativeModuleBaseTypeAnnotation>;
}>;
export declare type NativeModuleArrayTypeAnnotation = Readonly<{
type: 'ArrayTypeAnnotation';
elementType?: Nullable<NativeModuleBaseTypeAnnotation>;
}>;
export declare type NativeModuleStringTypeAnnotation = Readonly<{
type: 'StringTypeAnnotation';
}>;
export declare type NativeModuleNumberTypeAnnotation = Readonly<{
type: 'NumberTypeAnnotation';
}>;
export declare type NativeModuleInt32TypeAnnotation = Readonly<{
type: 'Int32TypeAnnotation';
}>;
export declare type NativeModuleDoubleTypeAnnotation = Readonly<{
type: 'DoubleTypeAnnotation';
}>;
export declare type NativeModuleFloatTypeAnnotation = Readonly<{
type: 'FloatTypeAnnotation';
}>;
export declare type NativeModuleBooleanTypeAnnotation = Readonly<{
type: 'BooleanTypeAnnotation';
}>;
export declare type NativeModuleGenericObjectTypeAnnotation = Readonly<{
type: 'GenericObjectTypeAnnotation';
}>;
export declare type NativeModuleReservedFunctionValueTypeAnnotation = Readonly<{
type: 'ReservedFunctionValueTypeAnnotation';
name: ReservedFunctionValueTypeName;
}>;
export declare type NativeModuleTypeAliasTypeAnnotation = Readonly<{
type: 'TypeAliasTypeAnnotation';
name: string;
}>;
export declare type NativeModulePromiseTypeAnnotation = Readonly<{
type: 'PromiseTypeAnnotation';
}>;
export declare type NativeModuleVoidTypeAnnotation = Readonly<{
type: 'VoidTypeAnnotation';
}>;
export declare type NativeModuleBaseTypeAnnotation = NativeModuleStringTypeAnnotation | NativeModuleNumberTypeAnnotation | NativeModuleInt32TypeAnnotation | NativeModuleDoubleTypeAnnotation | NativeModuleFloatTypeAnnotation | NativeModuleBooleanTypeAnnotation | NativeModuleGenericObjectTypeAnnotation | NativeModuleReservedFunctionValueTypeAnnotation | NativeModuleTypeAliasTypeAnnotation | NativeModuleArrayTypeAnnotation | NativeModuleObjectTypeAnnotation;
export declare type NativeModuleParamTypeAnnotation = NativeModuleBaseTypeAnnotation | NativeModuleParamOnlyTypeAnnotation;
export declare type NativeModuleReturnTypeAnnotation = NativeModuleBaseTypeAnnotation | NativeModuleReturnOnlyTypeAnnotation;
export declare type NativeModuleTypeAnnotation = NativeModuleBaseTypeAnnotation | NativeModuleParamOnlyTypeAnnotation | NativeModuleReturnOnlyTypeAnnotation;
export declare type NativeModuleParamOnlyTypeAnnotation = NativeModuleFunctionTypeAnnotation;
export declare type NativeModuleReturnOnlyTypeAnnotation = NativeModulePromiseTypeAnnotation | NativeModuleVoidTypeAnnotation;
export declare type ReservedFunctionValueTypeName = 'RootTag';
import * as cs from './CodegenSchema';
import { ExportCommandInfo } from './ExportParser';
export declare function parseCommands(info: ExportCommandInfo): cs.CommandTypeShape[];
export declare function parseCommands(info?: ExportCommandInfo): cs.CommandTypeShape[];

@@ -5,2 +5,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.parseCommands = void 0;
var ts = require("typescript");

@@ -10,3 +11,3 @@ var ExportParser_1 = require("./ExportParser");

function typeNodeToCommandsTypeAnnotation(typeNode, sourceFile) {
var rawType = TypeChecker_1.typeToRNRawType(typeNode, sourceFile, false);
var rawType = TypeChecker_1.typeToRNRawType(typeNode, sourceFile, { allowObject: false });
switch (rawType.kind) {

@@ -18,2 +19,3 @@ case 'String': return { type: 'StringTypeAnnotation' };

case 'Boolean': return { type: 'BooleanTypeAnnotation' };
case 'rn:RootTag': return { type: 'ReservedFunctionValueTypeAnnotation', name: 'RootTag' };
default:

@@ -24,2 +26,5 @@ }

function parseCommands(info) {
if (info === undefined) {
return [];
}
var validMembers = ExportParser_1.getMembersFromType(info.typeNode, info.sourceFile);

@@ -26,0 +31,0 @@ if (validMembers === undefined) {

import * as ts from 'typescript';
import * as cs from './CodegenSchema';
import { ExportComponentInfo } from './ExportParser';
export declare function tryParseEvent(info: ExportComponentInfo, propDecl: ts.PropertySignature | ts.PropertyDeclaration): cs.EventTypeShape | undefined;
export interface ComponentEventInfo {
optional: boolean;
eventType: ts.TypeNode;
eventTypeName: string;
paperTopLevelNameDeprecated?: string;
}
export declare function checkEventType(eventType: ts.TypeNode, info: ExportComponentInfo, propDecl: ts.PropertySignature | ts.PropertyDeclaration): ComponentEventInfo | undefined;
export declare function parseEvent(info: ExportComponentInfo, propDecl: ts.PropertySignature | ts.PropertyDeclaration, eventInfo: ComponentEventInfo): cs.EventTypeShape;

@@ -5,2 +5,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.parseEvent = exports.checkEventType = void 0;
var ts = require("typescript");

@@ -27,3 +28,3 @@ var TypeChecker_1 = require("./TypeChecker");

if (result !== undefined) {
result[0] = true;
result.optional = true;
}

@@ -44,6 +45,15 @@ return result;

if (ts.isLiteralTypeNode(nameArgument) && ts.isStringLiteral(nameArgument.literal)) {
return [false, typeArguments[0], typeName, nameArgument.literal.text];
return {
optional: false,
eventType: typeArguments[0],
eventTypeName: typeName,
paperTopLevelNameDeprecated: nameArgument.literal.text
};
}
}
return [false, typeArguments[0], typeName, undefined];
return {
optional: false,
eventType: typeArguments[0],
eventTypeName: typeName
};
}

@@ -54,2 +64,3 @@ else {

}
exports.checkEventType = checkEventType;
function rnRawTypeToObjectPropertyType(typeNode, rawType) {

@@ -76,5 +87,14 @@ var namePlaceholder = undefined;

prop.name = rawProp.name;
if (rawProp.optional) {
prop.optional = true;
}
return prop;
})
};
case 'Null': return {
type: 'ObjectTypeAnnotation',
name: namePlaceholder,
optional: rawType.isNullable,
properties: []
};
default:

@@ -84,10 +104,5 @@ }

}
function tryParseEvent(info, propDecl) {
function parseEvent(info, propDecl, eventInfo) {
var propType = propDecl.type;
var eventTypeTuple = checkEventType(propType, info, propDecl);
if (eventTypeTuple === undefined) {
return undefined;
}
var optional = eventTypeTuple[0], eventType = eventTypeTuple[1], eventTypeName = eventTypeTuple[2], paperTopLevelNameDeprecated = eventTypeTuple[3];
var rawType = TypeChecker_1.typeToRNRawType(eventType, info.sourceFile, true);
var rawType = TypeChecker_1.typeToRNRawType(eventInfo.eventType, info.sourceFile, { allowObject: true });
var eventProperties = [];

@@ -105,4 +120,4 @@ if (rawType.kind !== 'Null') {

name: propDecl.name.getText(),
bubblingType: eventTypeName === 'DirectEventHandler' ? 'direct' : 'bubble',
optional: (propDecl.questionToken !== undefined) || optional,
bubblingType: eventInfo.eventTypeName === 'DirectEventHandler' ? 'direct' : 'bubble',
optional: (propDecl.questionToken !== undefined) || eventInfo.optional,
typeAnnotation: {

@@ -116,8 +131,8 @@ type: 'EventTypeAnnotation',

};
if (paperTopLevelNameDeprecated !== undefined) {
result.paperTopLevelNameDeprecated = paperTopLevelNameDeprecated;
if (eventInfo.paperTopLevelNameDeprecated !== undefined) {
result.paperTopLevelNameDeprecated = eventInfo.paperTopLevelNameDeprecated;
}
return result;
}
exports.tryParseEvent = tryParseEvent;
exports.parseEvent = parseEvent;
//# sourceMappingURL=ComponentEventParser.js.map
import * as cs from './CodegenSchema';
import { ExportCommandInfo, ExportComponentInfo } from './ExportParser';
export declare function processComponent(info: ExportComponentInfo, commandsInfo: ExportCommandInfo | undefined): cs.ComponentShape;
export declare function processComponent(info: ExportComponentInfo, commandsInfo?: ExportCommandInfo): cs.ComponentSchema;

@@ -5,2 +5,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.processComponent = void 0;
var ts = require("typescript");

@@ -35,8 +36,8 @@ var ComponentCommandParser_1 = require("./ComponentCommandParser");

function processComponent(info, commandsInfo) {
var _a;
var extendsProps = [];
var events = [];
var props = [];
var commands = [];
if (commandsInfo !== undefined) {
commands = ComponentCommandParser_1.parseCommands(commandsInfo);
}
commands = ComponentCommandParser_1.parseCommands(commandsInfo);
var validMembers = ExportParser_1.getMembersFromType(info.typeNode, info.sourceFile);

@@ -51,18 +52,8 @@ if (validMembers === undefined) {

if (ts.isPropertySignature(propDecl) || ts.isPropertyDeclaration(propDecl)) {
try {
var eventShape = ComponentEventParser_1.tryParseEvent(info, propDecl);
if (eventShape !== undefined) {
events.push(eventShape);
}
else {
props.push(ComponentPropertyParser_1.parseProperty(info, propDecl));
}
var eventInfo = ComponentEventParser_1.checkEventType(propDecl.type, info, propDecl);
if (eventInfo === undefined) {
props.push(ComponentPropertyParser_1.parseProperty(info, propDecl));
}
catch (err) {
if (err instanceof Error) {
err.message = propertyName + ": " + err.message;
}
else {
throw err;
}
else {
events.push(ComponentEventParser_1.parseEvent(info, propDecl, eventInfo));
}

@@ -75,4 +66,7 @@ }

}
var result = {
extendsProps: [],
if (importExists(info.sourceFile, 'ViewProps')) {
extendsProps.push({ knownTypeName: 'ReactNativeCoreViewProps', type: 'ReactNativeBuiltInType' });
}
var shape = {
extendsProps: extendsProps,
events: events,

@@ -82,11 +76,8 @@ props: props,

};
if (importExists(info.sourceFile, 'ViewProps')) {
result.extendsProps.push({ knownTypeName: 'ReactNativeCoreViewProps', type: 'ReactNativeBuiltInType' });
}
Object.getOwnPropertyNames(info.options).forEach(function (key) {
result[key] = info.options[key];
shape[key] = info.options[key];
});
return result;
return { type: 'Component', components: (_a = {}, _a[info.name] = shape, _a) };
}
exports.processComponent = processComponent;
//# sourceMappingURL=ComponentParser.js.map

@@ -5,2 +5,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.parseProperty = void 0;
var TypeChecker_1 = require("./TypeChecker");

@@ -14,3 +15,3 @@ function rnRawTypeToObjectTypeAnnotation(rawType, typeNode) {

name: value.name,
optional: optional,
optional: value.optional || optional,
typeAnnotation: typeAnnotation

@@ -153,3 +154,3 @@ };

var propType = propDecl.type;
var rawType = TypeChecker_1.typeToRNRawType(propType, info.sourceFile, true);
var rawType = TypeChecker_1.typeToRNRawType(propType, info.sourceFile, { allowObject: true });
var _a = rnRawTypeToPropTypeTypeAnnotation(rawType, propType), optional = _a[0], typeAnnotation = _a[1];

@@ -156,0 +157,0 @@ return {

@@ -14,3 +14,3 @@ import * as ts from 'typescript';

options: {
[key: string]: boolean | string;
[key: string]: boolean | string | string[];
};

@@ -17,0 +17,0 @@ }

@@ -5,2 +5,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.tryParseExportCommand = exports.tryParseExportComponent = exports.tryParseExportNativeModule = exports.tryParseExport = exports.tryParseExportedCallExpression = exports.getMembersFromType = exports.resolveType = void 0;
var ts = require("typescript");

@@ -188,2 +189,12 @@ function resolveType(typeNode, sourceFile) {

}
else if (ts.isArrayLiteralExpression(optionItem.initializer)) {
var strings = [];
for (var _i = 0, _a = optionItem.initializer.elements; _i < _a.length; _i++) {
var element = _a[_i];
if (ts.isStringLiteral(element)) {
strings.push(element.text);
}
}
result.options[optionItem.name.getText()] = strings;
}
}

@@ -190,0 +201,0 @@ });

@@ -8,3 +8,3 @@ import { SchemaType } from './CodegenSchema';

}>;
export declare type Generators = 'descriptors' | 'events' | 'props' | 'tests' | 'shadow-nodes' | 'modules';
export declare type Generators = 'descriptors' | 'events' | 'props' | 'tests' | 'shadow-nodes' | 'modulesAndroid' | 'modulesCxx' | 'modulesIOS';
export declare type Config = Readonly<{

@@ -11,0 +11,0 @@ generators: Generators[];

@@ -5,3 +5,4 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.generate = void 0;
exports.generate = (require('./rncodegen/src/generators/RNCodegen.js').generate);
//# sourceMappingURL=ExportRNCodegen.js.map
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generator = exports.typeScriptToCodeSchema = void 0;
var path = require("path");

@@ -10,2 +21,3 @@ var ts = require("typescript");

var NativeModuleParser_1 = require("./NativeModuleParser");
var TypeChecker_1 = require("./TypeChecker");
function messageChainToString(chain, indent) {

@@ -88,6 +100,24 @@ var message = '';

}
// find out all type aliases in this file
var aliases_1 = { aliases: {} };
var knownAliases_1 = [];
program.getSourceFiles().forEach(function (sourceFile) {
if (path.basename(fileName) === path.basename(sourceFile.fileName)) {
sourceFile.statements.forEach(function (node) {
if (ts.isTypeAliasDeclaration(node)) {
if (node.typeParameters === undefined || node.typeParameters.length === 0) {
var rnRawType = TypeChecker_1.typeToRNRawType(node.type, sourceFile, { allowObject: true, knownAliases: knownAliases_1 });
if (rnRawType.kind === 'Object') {
var aliasName = node.name.text;
aliases_1.aliases[aliasName] = rnRawType;
knownAliases_1.push(aliasName);
}
}
}
});
}
});
var info = nativeModuleInfos[0];
var result = { modules: {} };
result.modules[moduleName] = { nativeModules: {} };
result.modules[moduleName].nativeModules[targetName === undefined ? info.name : targetName] = NativeModuleParser_1.processNativeModule(info);
result.modules[moduleName] = NativeModuleParser_1.processNativeModule(info, aliases_1);
return result;

@@ -101,4 +131,3 @@ }

var result = { modules: {} };
result.modules[moduleName] = { components: {} };
result.modules[moduleName].components[targetName === undefined ? info.name : targetName] = ComponentParser_1.processComponent(info, commandInfos[0]);
result.modules[info.name] = ComponentParser_1.processComponent(info, commandInfos[0]);
return result;

@@ -108,2 +137,3 @@ }

exports.typeScriptToCodeSchema = typeScriptToCodeSchema;
__exportStar(require("./CodegenSchema"), exports);
var rncodegen = require("./ExportRNCodegen");

@@ -110,0 +140,0 @@ var generator;

import * as cs from './CodegenSchema';
import { ExportNativeModuleInfo } from './ExportParser';
export declare function processNativeModule(info: ExportNativeModuleInfo): cs.NativeModuleShape;
import { RNRawType } from './RNRawType';
export interface NativeModuleAliases {
aliases: {
[key: string]: RNRawType;
};
}
export declare function processNativeModule(info: ExportNativeModuleInfo, nativeModuleAliases: NativeModuleAliases): cs.NativeModuleSchema;

@@ -5,4 +5,5 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.processNativeModule = void 0;
var TypeChecker_1 = require("./TypeChecker");
function rawTypeToParamType(rawType) {
function rawTypeToBaseType(rawType, usedAliases) {
switch (rawType.kind) {

@@ -16,10 +17,9 @@ case 'String': return { type: 'StringTypeAnnotation' };

case 'js:Object': return { type: 'GenericObjectTypeAnnotation' };
case 'Any': return { type: 'AnyTypeAnnotation' };
case 'rn:RootTag': return { type: 'ReservedFunctionValueTypeAnnotation', name: 'RootTag' };
case 'Array': {
if (rawType.elementType.kind === 'Union' || rawType.elementType.kind === 'Tuple') {
var result = { type: 'ArrayTypeAnnotation' };
return result;
if (rawType.elementType.kind === 'Union' || rawType.elementType.kind === 'Tuple' || rawType.elementType.kind === 'Any') {
return { type: 'ArrayTypeAnnotation' };
}
else {
return { type: 'ArrayTypeAnnotation', elementType: rawTypeToParamType(rawType.elementType) };
return { type: 'ArrayTypeAnnotation', elementType: rawTypeToBaseType(rawType.elementType, usedAliases) };
}

@@ -30,24 +30,17 @@ }

properties: rawType.properties.map(function (param) {
var propertyType = rawTypeToBaseType(param.propertyType, usedAliases);
return {
optional: param.propertyType.isNullable,
optional: param.optional,
name: param.name,
typeAnnotation: rawTypeToParamType(param.propertyType)
typeAnnotation: param.propertyType.isNullable ? { type: 'NullableTypeAnnotation', typeAnnotation: propertyType } : propertyType
};
})
};
// What happened?
// case 'Function': return {
// type: 'FunctionTypeAnnotation',
// params: rawType.parameters.map((param: { name: string; parameterType: RNRawType }) => {
// return {
// nullable: param.parameterType.isNullable,
// name: param.name,
// typeAnnotation: rawTypeToParamType(param.parameterType)
// };
// }),
// returnTypeAnnotation: rawTypeToReturnType(rawType.returnType)
// };
case 'Function': return {
type: 'FunctionTypeAnnotation'
};
case 'Alias': {
usedAliases.push(rawType.name);
return {
type: 'TypeAliasTypeAnnotation',
name: rawType.name
};
}
default:

@@ -62,20 +55,38 @@ }

}
function rawTypeToReturnType(rawType) {
function rawTypeToParamType(rawType, usedAliases) {
switch (rawType.kind) {
case 'String': return { type: 'StringTypeAnnotation', nullable: rawType.isNullable };
case 'Number': return { type: 'NumberTypeAnnotation', nullable: rawType.isNullable };
case 'Int32': return { type: 'Int32TypeAnnotation', nullable: rawType.isNullable };
case 'Float': return { type: 'FloatTypeAnnotation', nullable: rawType.isNullable };
case 'Double': return { type: 'DoubleTypeAnnotation', nullable: rawType.isNullable };
case 'Boolean': return { type: 'BooleanTypeAnnotation', nullable: rawType.isNullable };
case 'js:Object': return { type: 'GenericObjectTypeAnnotation', nullable: rawType.isNullable };
case 'Function': return {
type: 'FunctionTypeAnnotation',
params: rawType.parameters.map(function (param) {
var parameterType = rawTypeToParamType(param.parameterType, usedAliases);
return {
optional: param.optional,
name: param.name,
typeAnnotation: param.parameterType.isNullable ? { type: 'NullableTypeAnnotation', typeAnnotation: parameterType } : parameterType
};
}),
returnTypeAnnotation: rawTypeToReturnType(rawType.returnType, usedAliases)
};
default:
return rawTypeToBaseType(rawType, usedAliases);
}
}
function rawTypeToReturnType(rawType, usedAliases) {
switch (rawType.kind) {
case 'String': return { type: 'StringTypeAnnotation' };
case 'Number': return { type: 'NumberTypeAnnotation' };
case 'Int32': return { type: 'Int32TypeAnnotation' };
case 'Float': return { type: 'FloatTypeAnnotation' };
case 'Double': return { type: 'DoubleTypeAnnotation' };
case 'Boolean': return { type: 'BooleanTypeAnnotation' };
case 'js:Object': return { type: 'GenericObjectTypeAnnotation' };
case 'rn:RootTag': return { type: 'ReservedFunctionValueTypeAnnotation', name: 'RootTag' };
case 'Void':
case 'Null': return { type: 'VoidTypeAnnotation', nullable: rawType.isNullable };
case 'Null': return { type: 'VoidTypeAnnotation' };
case 'Array': {
if (rawType.elementType.kind === 'Union' || rawType.elementType.kind === 'Tuple') {
var result = { type: 'ArrayTypeAnnotation', nullable: rawType.isNullable };
return result;
if (rawType.elementType.kind === 'Union' || rawType.elementType.kind === 'Tuple' || rawType.elementType.kind === 'Any') {
return { type: 'ArrayTypeAnnotation' };
}
else {
return { type: 'ArrayTypeAnnotation', nullable: rawType.isNullable, elementType: rawTypeToParamType(rawType.elementType) };
return { type: 'ArrayTypeAnnotation', elementType: rawTypeToBaseType(rawType.elementType, usedAliases) };
}

@@ -85,6 +96,5 @@ }

// case 'js:Promise': return { type: 'GenericPromiseTypeAnnotation', nullable: rawType.isNullable, resolvedType: rawTypeToReturnType(rawType.elementType) };
case 'js:Promise': return { type: 'GenericPromiseTypeAnnotation', nullable: rawType.isNullable };
case 'js:Promise': return { type: 'PromiseTypeAnnotation' };
case 'Object': return {
type: 'ObjectTypeAnnotation',
nullable: rawType.isNullable,
properties: rawType.properties.map(function (param) {

@@ -94,6 +104,13 @@ return {

name: param.name,
typeAnnotation: rawTypeToParamType(param.propertyType)
typeAnnotation: rawTypeToBaseType(param.propertyType, usedAliases)
};
})
};
case 'Alias': {
usedAliases.push(rawType.name);
return {
type: 'TypeAliasTypeAnnotation',
name: rawType.name
};
}
default:

@@ -108,21 +125,4 @@ }

}
function rawTypeToFunctionTypeAnnotation(rawType, propName, typeNode) {
if (rawType.kind !== 'Function') {
throw new Error("Member " + propName + " in a native module type " + typeNode.getText() + " is expected to be a function.");
}
return {
type: 'FunctionTypeAnnotation',
params: rawType.parameters.map(function (param) {
return {
nullable: param.parameterType.isNullable,
name: param.name,
typeAnnotation: rawTypeToParamType(param.parameterType)
};
}),
returnTypeAnnotation: rawTypeToReturnType(rawType.returnType),
optional: rawType.isNullable
};
}
function processNativeModule(info) {
var rawType = TypeChecker_1.typeToRNRawType(info.typeNode, info.sourceFile, true);
function processNativeModule(info, nativeModuleAliases) {
var rawType = TypeChecker_1.typeToRNRawType(info.typeNode, info.sourceFile, { allowObject: true, knownAliases: Object.keys(nativeModuleAliases.aliases) });
if (rawType.kind !== 'Object') {

@@ -132,2 +132,3 @@ throw new Error("An object type is expected as a native module: " + info.typeNode.getText() + ".");

var properties = [];
var usedAliases = [];
for (var _i = 0, _a = rawType.properties; _i < _a.length; _i++) {

@@ -144,10 +145,41 @@ var prop = _a[_i];

}
if (prop.propertyType.kind !== 'Function') {
throw new Error("Member " + prop.name + " in a native module type " + info.typeNode.getText() + " is expected to be a function.");
}
properties.push({
name: prop.name,
typeAnnotation: rawTypeToFunctionTypeAnnotation(prop.propertyType, prop.name, info.typeNode)
optional: prop.optional,
typeAnnotation: rawTypeToParamType(prop.propertyType, usedAliases)
});
}
return { properties: properties };
var aliases = {};
var writableAliases = aliases;
Object.keys(nativeModuleAliases.aliases).forEach(function (key) {
var rnRawType = nativeModuleAliases.aliases[key];
if (rnRawType !== undefined) {
writableAliases[key] = rawTypeToParamType(rnRawType, usedAliases);
}
});
Object.keys(nativeModuleAliases.aliases).forEach(function (key) {
if (usedAliases.indexOf(key) === -1) {
delete writableAliases[key];
}
});
var spec = { properties: properties };
var moduleNames = [info.name];
var excludedPlatforms = [];
if (info.name.endsWith('Android')) {
excludedPlatforms.push('iOS');
}
if (info.name.endsWith('IOS')) {
excludedPlatforms.push('android');
}
if (excludedPlatforms.length === 0) {
return { type: 'NativeModule', aliases: aliases, spec: spec, moduleNames: moduleNames };
}
else {
return { type: 'NativeModule', aliases: aliases, spec: spec, moduleNames: moduleNames, excludedPlatforms: excludedPlatforms };
}
}
exports.processNativeModule = processNativeModule;
//# sourceMappingURL=NativeModuleParser.js.map

@@ -13,2 +13,4 @@ /**

@@ -198,92 +200,3 @@

// Union with more custom types.

@@ -314,4 +227,4 @@

@@ -337,12 +250,164 @@

/**
* NativeModule Types
*/
// Union with more custom types.

@@ -70,3 +70,3 @@ /**

case 'ImageSourcePrimitive':
imports.add('#include <react/components/image/conversions.h>');
imports.add('#include <react/renderer/components/image/conversions.h>');
return;

@@ -73,0 +73,0 @@ default:

@@ -24,2 +24,4 @@ /**

* LICENSE file in the root directory of this source tree.
*
* ${'@'}generated by codegen project: GenerateComponentDescriptorH.js
*/

@@ -29,4 +31,4 @@

#include <react/components/::_LIBRARY_::/ShadowNodes.h>
#include <react/core/ConcreteComponentDescriptor.h>
#include <react/renderer/components/::_LIBRARY_::/ShadowNodes.h>
#include <react/renderer/core/ConcreteComponentDescriptor.h>

@@ -51,2 +53,3 @@ namespace facebook {

moduleSpecName ,
packageName ,
) {

@@ -57,3 +60,8 @@ const fileName = 'ComponentDescriptors.h';

.map(moduleName => {
const components = schema.modules[moduleName].components;
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module

@@ -60,0 +68,0 @@ if (components == null) {

@@ -91,2 +91,4 @@ /**

* LICENSE file in the root directory of this source tree.
*
* ${'@'}generated by codegen project: GenerateComponentHObjCpp.js
*/

@@ -327,2 +329,3 @@

moduleSpecName ,
packageName ,
) {

@@ -333,3 +336,8 @@ const fileName = 'RCTComponentViewHelpers.h';

.map(moduleName => {
const components = schema.modules[moduleName].components;
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module

@@ -343,3 +351,6 @@ if (components == null) {

const component = components[componentName];
return component.excludedPlatform !== 'iOS';
return !(
component.excludedPlatforms &&
component.excludedPlatforms.includes('iOS')
);
})

@@ -346,0 +357,0 @@ .map(componentName => {

@@ -35,5 +35,7 @@ /**

* LICENSE file in the root directory of this source tree.
*
* ${'@'}generated by codegen project: GenerateEventEmitterCpp.js
*/
#include <react/components/::_LIBRARY_::/EventEmitters.h>
#include <react/renderer/components/::_LIBRARY_::/EventEmitters.h>

@@ -170,6 +172,12 @@ namespace facebook {

moduleSpecName ,
packageName ,
) {
const moduleComponents = Object.keys(schema.modules)
.map(moduleName => {
const components = schema.modules[moduleName].components;
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module

@@ -176,0 +184,0 @@ if (components == null) {

@@ -43,6 +43,8 @@ /**

* LICENSE file in the root directory of this source tree.
*
* ${'@'}generated by codegen project: GenerateEventEmitterH.js
*/
#pragma once
#include <react/components/view/ViewEventEmitter.h>
#include <react/renderer/components/view/ViewEventEmitter.h>

@@ -238,6 +240,12 @@ namespace facebook {

moduleSpecName ,
packageName ,
) {
const moduleComponents = Object.keys(schema.modules)
.map(moduleName => {
const components = schema.modules[moduleName].components;
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module

@@ -244,0 +252,0 @@ if (components == null) {

@@ -25,5 +25,7 @@ /**

* LICENSE file in the root directory of this source tree.
*
* ${'@'}generated by codegen project: GeneratePropsCpp.js
*/
#include <react/components/::_LIBRARY_::/Props.h>
#include <react/renderer/components/::_LIBRARY_::/Props.h>
::_IMPORTS_::

@@ -88,6 +90,7 @@

moduleSpecName ,
packageName ,
) {
const fileName = 'Props.cpp';
const allImports = new Set([
'#include <react/core/propsConversions.h>',
'#include <react/renderer/core/propsConversions.h>',
]);

@@ -97,3 +100,8 @@

.map(moduleName => {
const components = schema.modules[moduleName].components;
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module

@@ -107,3 +115,6 @@ if (components == null) {

const component = components[componentName];
return component.excludedPlatform !== 'iOS';
return !(
component.excludedPlatforms &&
component.excludedPlatforms.includes('iOS')
);
})

@@ -110,0 +121,0 @@ .map(componentName => {

@@ -40,2 +40,4 @@ /**

* LICENSE file in the root directory of this source tree.
*
* ${'@'}generated by codegen project: GeneratePropsH.js
*/

@@ -471,3 +473,5 @@ #pragma once

case 'ReactNativeCoreViewProps':
imports.add('#include <react/components/view/ViewProps.h>');
imports.add(
'#include <react/renderer/components/view/ViewProps.h>',
);
return;

@@ -495,12 +499,12 @@ default:

case 'ColorPrimitive':
imports.add('#include <react/graphics/Color.h>');
imports.add('#include <react/renderer/graphics/Color.h>');
return;
case 'ImageSourcePrimitive':
imports.add('#include <react/imagemanager/primitives.h>');
imports.add('#include <react/renderer/imagemanager/primitives.h>');
return;
case 'PointPrimitive':
imports.add('#include <react/graphics/Geometry.h>');
imports.add('#include <react/renderer/graphics/Geometry.h>');
return;
case 'EdgeInsetsPrimitive':
imports.add('#include <react/graphics/Geometry.h>');
imports.add('#include <react/renderer/graphics/Geometry.h>');
return;

@@ -546,3 +550,3 @@ default:

if (typeAnnotation.type === 'ObjectTypeAnnotation') {
imports.add('#include <react/core/propsConversions.h>');
imports.add('#include <react/renderer/core/propsConversions.h>');
const objectImports = getImports(typeAnnotation.properties);

@@ -759,2 +763,3 @@ const localImports = getLocalImports(typeAnnotation.properties);

moduleSpecName ,
packageName ,
) {

@@ -767,3 +772,8 @@ const fileName = 'Props.h';

.map(moduleName => {
const components = schema.modules[moduleName].components;
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module

@@ -777,3 +787,6 @@ if (components == null) {

const component = components[componentName];
return component.excludedPlatform !== 'iOS';
return !(
component.excludedPlatforms &&
component.excludedPlatforms.includes('iOS')
);
})

@@ -780,0 +793,0 @@ .map(componentName => {

@@ -58,3 +58,4 @@ /**

const commandsTemplate = `
public void receiveCommand(::_INTERFACE_CLASSNAME_::<T> viewManager, T view, String commandName, ReadableArray args) {
@Override
public void receiveCommand(T view, String commandName, ReadableArray args) {
switch (commandName) {

@@ -202,3 +203,3 @@ ::_COMMAND_CASES_::

return `case "${command.name}":
viewManager.${toSafeJavaString(
mViewManager.${toSafeJavaString(
command.name,

@@ -267,6 +268,12 @@ false,

moduleSpecName ,
packageName ,
) {
const files = new Map();
Object.keys(schema.modules).forEach(moduleName => {
const components = schema.modules[moduleName].components;
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module

@@ -280,3 +287,6 @@ if (components == null) {

const component = components[componentName];
return component.excludedPlatform !== 'android';
return !(
component.excludedPlatforms &&
component.excludedPlatforms.includes('android')
);
})

@@ -283,0 +293,0 @@ .forEach(componentName => {

@@ -212,6 +212,13 @@ /**

moduleSpecName ,
packageName ,
) {
const files = new Map();
Object.keys(schema.modules).forEach(moduleName => {
const components = schema.modules[moduleName].components;
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module

@@ -225,3 +232,6 @@ if (components == null) {

const component = components[componentName];
return component.excludedPlatform !== 'android';
return !(
component.excludedPlatforms &&
component.excludedPlatforms.includes('android')
);
})

@@ -228,0 +238,0 @@ .forEach(componentName => {

@@ -24,5 +24,7 @@ /**

* LICENSE file in the root directory of this source tree.
*
* ${'@'}generated by codegen project: GenerateShadowNodeCpp.js
*/
#include <react/components/::_LIBRARY_::/ShadowNodes.h>
#include <react/renderer/components/::_LIBRARY_::/ShadowNodes.h>

@@ -47,2 +49,3 @@ namespace facebook {

moduleSpecName ,
packageName ,
) {

@@ -53,3 +56,8 @@ const fileName = 'ShadowNodes.cpp';

.map(moduleName => {
const components = schema.modules[moduleName].components;
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module

@@ -56,0 +64,0 @@ if (components == null) {

@@ -24,2 +24,4 @@ /**

* LICENSE file in the root directory of this source tree.
*
* ${'@'}generated by codegen project: GenerateShadowNodeH.js
*/

@@ -29,4 +31,4 @@

::_IMPORTS_::#include <react/components/::_LIBRARY_::/Props.h>
#include <react/components/view/ConcreteViewShadowNode.h>
::_IMPORTS_::#include <react/renderer/components/::_LIBRARY_::/Props.h>
#include <react/renderer/components/view/ConcreteViewShadowNode.h>

@@ -58,2 +60,3 @@ namespace facebook {

moduleSpecName ,
packageName ,
) {

@@ -66,3 +69,8 @@ const fileName = 'ShadowNodes.h';

.map(moduleName => {
const components = schema.modules[moduleName].components;
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module

@@ -101,3 +109,3 @@ if (components == null) {

const eventEmitterImport = `#include <react/components/${libraryName}/EventEmitters.h>\n`;
const eventEmitterImport = `#include <react/renderer/components/${libraryName}/EventEmitters.h>\n`;

@@ -104,0 +112,0 @@ const replacedTemplate = template

@@ -32,6 +32,8 @@ /**

* LICENSE file in the root directory of this source tree.
*/
*
* ${'@'}generated by codegen project: GenerateTests.js
* */
#include <gtest/gtest.h>
#include <react/components/::_LIBRARY_NAME_::/Props.h>
#include <react/renderer/components/::_LIBRARY_NAME_::/Props.h>
::_IMPORTS_::

@@ -77,2 +79,3 @@

});
// $FlowFixMe[incompatible-type]
} else if (typeAnnotation.type === 'IntegerTypeAnnotation') {

@@ -142,8 +145,9 @@ cases.push({

moduleSpecName ,
packageName ,
) {
const fileName = 'Tests.cpp';
const allImports = new Set([
'#include <react/core/propsConversions.h>',
'#include <react/core/RawProps.h>',
'#include <react/core/RawPropsParser.h>',
'#include <react/renderer/core/propsConversions.h>',
'#include <react/renderer/core/RawProps.h>',
'#include <react/renderer/core/RawPropsParser.h>',
]);

@@ -153,3 +157,8 @@

.map(moduleName => {
const components = schema.modules[moduleName].components;
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const {components} = module;
if (components == null) {

@@ -156,0 +165,0 @@ return null;

@@ -28,2 +28,4 @@ /**

* @flow
*
* ${'@'}generated by codegen project: GenerateViewConfigJs.js
*/

@@ -339,10 +341,11 @@

.map(moduleName => {
const components = schema.modules[moduleName].components;
// No components in this module
if (components == null) {
return null;
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const {components} = module;
return Object.keys(components)
.map(componentName => {
.map((componentName ) => {
const component = components[componentName];

@@ -349,0 +352,0 @@

@@ -13,43 +13,79 @@ /**

const {createAliasResolver, getModules} = require('./Utils');
const {unwrapNullable} = require('../../parsers/flow/modules/utils');
const propertyHeaderTemplate =
'static jsi::Value __hostFunction_Native::_MODULE_NAME_::CxxSpecJSI_::_PROPERTY_NAME_::(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {';
const HostFunctionTemplate = ({
hasteModuleName,
methodName,
isVoid,
args,
}
) => {
const methodCallArgs = ['rt', ...args].join(', ');
const methodCall = `static_cast<${hasteModuleName}CxxSpecJSI *>(&turboModule)->${methodName}(${methodCallArgs});`;
const propertyCastTemplate =
'static_cast<Native::_MODULE_NAME_::CxxSpecJSI *>(&turboModule)->::_PROPERTY_NAME_::(rt::_ARGS_::);';
return `static jsi::Value __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {${
isVoid ? `\n ${methodCall}` : ''
}
return ${isVoid ? 'jsi::Value::undefined();' : methodCall}
}`;
};
const nonvoidPropertyTemplate = `
${propertyHeaderTemplate}
return ${propertyCastTemplate}
}`.trim();
const ModuleTemplate = ({
hasteModuleName,
hostFunctions,
moduleName,
methods,
}
) => {
return `${hostFunctions.join('\n')}
const voidPropertyTemplate = `
${propertyHeaderTemplate}
${propertyCastTemplate}
return jsi::Value::undefined();
${hasteModuleName}CxxSpecJSI::${hasteModuleName}CxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule("${moduleName}", jsInvoker) {
${methods
.map(({methodName, paramCount}) => {
return ` methodMap_["${methodName}"] = MethodMetadata {${paramCount}, __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}};`;
})
.join('\n')}
}`;
};
const proprertyDefTemplate =
' methodMap_["::_PROPERTY_NAME_::"] = MethodMetadata {::_ARGS_COUNT_::, __hostFunction_Native::_MODULE_NAME_::CxxSpecJSI_::_PROPERTY_NAME_::};';
const moduleTemplate = `
::_MODULE_PROPERTIES_::
Native::_MODULE_NAME_::CxxSpecJSI::Native::_MODULE_NAME_::CxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule("::_MODULE_NAME_::", jsInvoker) {
::_PROPERTIES_MAP_::
}`.trim();
const template = `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
const FileTemplate = ({
libraryName,
modules,
}
) => {
return `/**
* ${'C'}opyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* ${'@'}generated by codegen project: GenerateModuleH.js
*/
#include <react/modules/::_LIBRARY_NAME_::/NativeModules.h>
#include <react/modules/${libraryName}/NativeModules.h>

@@ -59,3 +95,3 @@ namespace facebook {

::_MODULES_::
${modules}

@@ -66,17 +102,31 @@

`;
};
function traverseArg(arg, index) {
function serializeArg(
arg ,
index ,
resolveAlias ,
) {
function wrap(suffix) {
return `args[${index}]${suffix}`;
}
const {typeAnnotation} = arg;
switch (typeAnnotation.type) {
const {typeAnnotation: nullableTypeAnnotation} = arg;
const [typeAnnotation] = unwrapNullable (
nullableTypeAnnotation,
);
let realTypeAnnotation = typeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {
realTypeAnnotation = resolveAlias(realTypeAnnotation.name);
}
switch (realTypeAnnotation.type) {
case 'ReservedFunctionValueTypeAnnotation':
switch (typeAnnotation.name) {
switch (realTypeAnnotation.name) {
case 'RootTag':
return wrap('.getNumber()');
default:
(typeAnnotation.name );
(realTypeAnnotation.name );
throw new Error(
`Unknown prop type for "${arg.name}, found: ${typeAnnotation.name}"`,
`Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.name}"`,
);

@@ -89,3 +139,7 @@ }

case 'NumberTypeAnnotation':
return wrap('.getNumber()');
case 'FloatTypeAnnotation':
return wrap('.getNumber()');
case 'DoubleTypeAnnotation':
return wrap('.getNumber()');
case 'Int32TypeAnnotation':

@@ -98,11 +152,9 @@ return wrap('.getNumber()');

case 'GenericObjectTypeAnnotation':
return wrap('.getObject(rt)');
case 'ObjectTypeAnnotation':
return wrap('.getObject(rt)');
case 'AnyTypeAnnotation':
throw new Error(`Any type is not allowed in params for "${arg.name}"`);
default:
// TODO (T65847278): Figure out why this does not work.
// (typeAnnotation.type: empty);
(realTypeAnnotation.type );
throw new Error(
`Unknown prop type for "${arg.name}, found: ${typeAnnotation.type}"`,
`Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.type}"`,
);

@@ -112,13 +164,23 @@ }

function traverseProperty(property) {
const propertyTemplate =
property.typeAnnotation.returnTypeAnnotation.type === 'VoidTypeAnnotation'
? voidPropertyTemplate
: nonvoidPropertyTemplate;
const traversedArgs = property.typeAnnotation.params
.map(traverseArg)
.join(', ');
return propertyTemplate
.replace(/::_PROPERTY_NAME_::/g, property.name)
.replace(/::_ARGS_::/g, traversedArgs === '' ? '' : ', ' + traversedArgs);
function serializePropertyIntoHostFunction(
hasteModuleName ,
property ,
resolveAlias ,
) {
const [
propertyTypeAnnotation,
] = unwrapNullable (
property.typeAnnotation,
);
const isVoid =
propertyTypeAnnotation.returnTypeAnnotation.type === 'VoidTypeAnnotation';
return HostFunctionTemplate({
hasteModuleName,
methodName: property.name,
isVoid,
args: propertyTypeAnnotation.params.map((p, i) =>
serializeArg(p, i, resolveAlias),
),
});
}

@@ -131,34 +193,38 @@

moduleSpecName ,
packageName ,
) {
const nativeModules = Object.keys(schema.modules)
.map(moduleName => {
const modules = schema.modules[moduleName].nativeModules;
if (modules == null) {
return null;
}
const nativeModules = getModules(schema);
return modules;
})
.filter(Boolean)
.reduce((acc, modules) => Object.assign(acc, modules), {});
const modules = Object.keys(nativeModules)
.map((hasteModuleName ) => {
const nativeModule = nativeModules[hasteModuleName];
const {
aliases,
spec: {properties},
moduleNames,
} = nativeModule;
const resolveAlias = createAliasResolver(aliases);
const hostFunctions = properties.map(property =>
serializePropertyIntoHostFunction(
hasteModuleName,
property,
resolveAlias,
),
);
const modules = Object.keys(nativeModules)
.map(name => {
const {properties} = nativeModules[name];
const traversedProperties = properties
.map(property => traverseProperty(property))
.join('\n');
return moduleTemplate
.replace(/::_MODULE_PROPERTIES_::/g, traversedProperties)
.replace(
'::_PROPERTIES_MAP_::',
properties
.map(({name: propertyName, typeAnnotation: {params}}) =>
proprertyDefTemplate
.replace(/::_PROPERTY_NAME_::/g, propertyName)
.replace(/::_ARGS_COUNT_::/g, params.length.toString()),
)
.join('\n'),
)
.replace(/::_MODULE_NAME_::/g, name);
return ModuleTemplate({
hasteModuleName,
hostFunctions,
// TODO: What happens when there are more than one NativeModule requires?
moduleName: moduleNames[0],
methods: properties.map(
({name: propertyName, typeAnnotation: nullableTypeAnnotation}) => {
const [{params}] = unwrapNullable(nullableTypeAnnotation);
return {
methodName: propertyName,
paramCount: params.length,
};
},
),
});
})

@@ -168,7 +234,8 @@ .join('\n');

const fileName = 'NativeModules.cpp';
const replacedTemplate = template
.replace(/::_MODULES_::/g, modules)
.replace(/::_LIBRARY_NAME_::/g, libraryName);
const replacedTemplate = FileTemplate({
modules,
libraryName,
});
return new Map([[fileName, replacedTemplate]]);
},
};

@@ -14,25 +14,40 @@ /**

const {createAliasResolver, getModules} = require('./Utils');
const {unwrapNullable} = require('../../parsers/flow/modules/utils');
const moduleTemplate = `
class JSI_EXPORT Native::_MODULE_NAME_::CxxSpecJSI : public TurboModule {
const ModuleClassDeclarationTemplate = ({
hasteModuleName,
moduleProperties,
} ) => {
return `class JSI_EXPORT ${hasteModuleName}CxxSpecJSI : public TurboModule {
protected:
Native::_MODULE_NAME_::CxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker);
${hasteModuleName}CxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker);
public:
::_MODULE_PROPERTIES_::
${moduleProperties}
};`;
};
const template = `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
const FileTemplate = ({
modules,
}
) => {
return `/**
* ${'C'}opyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* ${'@'}generated by codegen project: GenerateModuleH.js
*/

@@ -46,3 +61,3 @@

namespace react {
::_MODULES_::
${modules}

@@ -52,17 +67,25 @@ } // namespace react

`;
};
function translatePrimitiveJSTypeToCpp(
typeAnnotation
,
nullableTypeAnnotation ,
createErrorMessage ,
resolveAlias ,
) {
switch (typeAnnotation.type) {
const [typeAnnotation] = unwrapNullable (
nullableTypeAnnotation,
);
let realTypeAnnotation = typeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {
realTypeAnnotation = resolveAlias(realTypeAnnotation.name);
}
switch (realTypeAnnotation.type) {
case 'ReservedFunctionValueTypeAnnotation':
switch (typeAnnotation.name) {
switch (realTypeAnnotation.name) {
case 'RootTag':
return 'double';
default:
(typeAnnotation.name );
throw new Error(createErrorMessage(typeAnnotation.name));
(realTypeAnnotation.name );
throw new Error(createErrorMessage(realTypeAnnotation.name));
}

@@ -74,2 +97,5 @@ case 'VoidTypeAnnotation':

case 'NumberTypeAnnotation':
return 'double';
case 'DoubleTypeAnnotation':
return 'double';
case 'FloatTypeAnnotation':

@@ -82,2 +108,3 @@ return 'double';

case 'GenericObjectTypeAnnotation':
return 'jsi::Object';
case 'ObjectTypeAnnotation':

@@ -89,8 +116,7 @@ return 'jsi::Object';

return 'jsi::Function';
case 'GenericPromiseTypeAnnotation':
case 'PromiseTypeAnnotation':
return 'jsi::Value';
default:
// TODO (T65847278): Figure out why this does not work.
// (typeAnnotation.type: empty);
throw new Error(createErrorMessage(typeAnnotation.type));
(realTypeAnnotation.type );
throw new Error(createErrorMessage(realTypeAnnotation.type));
}

@@ -107,21 +133,22 @@ }

moduleSpecName ,
packageName ,
) {
const nativeModules = Object.keys(schema.modules)
.map(moduleName => {
const modules = schema.modules[moduleName].nativeModules;
if (modules == null) {
return null;
}
const nativeModules = getModules(schema);
return modules;
})
.filter(Boolean)
.reduce((acc, components) => Object.assign(acc, components), {});
const modules = Object.keys(nativeModules)
.map(hasteModuleName => {
const {
aliases,
spec: {properties},
} = nativeModules[hasteModuleName];
const resolveAlias = createAliasResolver(aliases);
const modules = Object.keys(nativeModules)
.map(name => {
const {properties} = nativeModules[name];
const traversedProperties = properties
.map(prop => {
const traversedArgs = prop.typeAnnotation.params
const [
propTypeAnnotation,
] = unwrapNullable (
prop.typeAnnotation,
);
const traversedArgs = propTypeAnnotation.params
.map(param => {

@@ -132,2 +159,3 @@ const translatedParam = translatePrimitiveJSTypeToCpp(

`Unsupported type for param "${param.name}" in ${prop.name}. Found: ${typeName}`,
resolveAlias,
);

@@ -147,5 +175,6 @@ const isObject = translatedParam.startsWith('jsi::');

translatePrimitiveJSTypeToCpp(
prop.typeAnnotation.returnTypeAnnotation,
propTypeAnnotation.returnTypeAnnotation,
typeName =>
`Unsupported return type for ${prop.name}. Found: ${typeName}`,
resolveAlias,
),

@@ -159,6 +188,7 @@ )

.join('\n');
return moduleTemplate
.replace(/::_MODULE_PROPERTIES_::/g, traversedProperties)
.replace(/::_MODULE_NAME_::/g, name)
.replace('::_PROPERTIES_MAP_::', '');
return ModuleClassDeclarationTemplate({
hasteModuleName,
moduleProperties: traversedProperties,
});
})

@@ -168,3 +198,3 @@ .join('\n');

const fileName = 'NativeModules.h';
const replacedTemplate = template.replace(/::_MODULES_::/g, modules);
const replacedTemplate = FileTemplate({modules});

@@ -171,0 +201,0 @@ return new Map([[fileName, replacedTemplate]]);

@@ -28,4 +28,6 @@ /**

const generateModuleCpp = require('./modules/GenerateModuleCpp.js');
const generateModuleHObjCpp = require('./modules/GenerateModuleHObjCpp.js');
const generateModuleMm = require('./modules/GenerateModuleMm.js');
const generateModuleObjCpp = require('./modules/GenerateModuleObjCpp');
const generateModuleJavaSpec = require('./modules/GenerateModuleJavaSpec.js');
const GenerateModuleJniCpp = require('./modules/GenerateModuleJniCpp.js');
const GenerateModuleJniH = require('./modules/GenerateModuleJniH.js');
const generatePropsJavaInterface = require('./components/GeneratePropsJavaInterface.js');

@@ -47,2 +49,3 @@ const generatePropsJavaDelegate = require('./components/GeneratePropsJavaDelegate.js');

@@ -56,3 +59,5 @@

@@ -66,8 +71,3 @@

descriptors: [generateComponentDescriptorH.generate],
events: [
generateEventEmitterCpp.generate,
generateEventEmitterH.generate,
generateModuleHObjCpp.generate,
generateModuleMm.generate,
],
events: [generateEventEmitterCpp.generate, generateEventEmitterH.generate],
props: [

@@ -80,3 +80,10 @@ generateComponentHObjCpp.generate,

],
modules: [generateModuleCpp.generate, generateModuleH.generate],
// TODO: Refactor this to consolidate various C++ output variation instead of forking per platform.
modulesAndroid: [
GenerateModuleJniCpp.generate,
GenerateModuleJniH.generate,
generateModuleJavaSpec.generate,
],
modulesCxx: [generateModuleCpp.generate, generateModuleH.generate],
modulesIOS: [generateModuleObjCpp.generate],
tests: [generateTests.generate],

@@ -94,2 +101,6 @@ 'shadow-nodes': [

const location = path.join(outputDir, fileName);
const dirName = path.dirname(location);
if (!fs.existsSync(dirName)) {
fs.mkdirSync(dirName, {recursive: true});
}
fs.writeFileSync(location, contents);

@@ -126,3 +137,9 @@ } catch (error) {

generate(
{libraryName, schema, outputDirectory, moduleSpecName} ,
{
libraryName,
schema,
outputDirectory,
moduleSpecName,
packageName,
} ,
{generators, test} ,

@@ -135,3 +152,5 @@ ) {

for (const generator of GENERATORS[name]) {
generatedFiles.push(...generator(libraryName, schema, moduleSpecName));
generatedFiles.push(
...generator(libraryName, schema, moduleSpecName, packageName),
);
}

@@ -138,0 +157,0 @@ }

@@ -14,3 +14,3 @@ /**

@@ -21,3 +21,3 @@ const {getValueFromTypes} = require('../utils.js');

function buildCommandSchema(property, types ) {
function buildCommandSchema(property, types ) {
const name = property.key.name;

@@ -103,3 +103,3 @@ const optional = property.optional;

commandTypeAST ,
types ,
types ,
) {

@@ -106,0 +106,0 @@ return commandTypeAST

@@ -55,2 +55,8 @@ /**

};
case '$ReadOnly':
return getPropertyType(
name,
optional,
typeAnnotation.typeParameters.params[0],
);
case 'ObjectTypeAnnotation':

@@ -57,0 +63,0 @@ return {

@@ -14,5 +14,5 @@ /**

function extendsForProp(prop , types ) {
function extendsForProp(prop , types ) {
if (!prop.argument) {

@@ -42,3 +42,3 @@ console.log('null', prop);

typeDefinition ,
types ,
types ,
) {

@@ -57,3 +57,3 @@ return typeDefinition.filter(

typeDefinition ,
types ,
types ,
) {

@@ -60,0 +60,0 @@ return typeDefinition

@@ -19,2 +19,3 @@ /**

const {getExtendsProps, removeKnownExtends} = require('./extends');
const {getTypes} = require('../utils');

@@ -171,3 +172,3 @@ function findComponentConfig(ast) {

// $FlowFixMe there's no flowtype for AST
function processComponent(ast, types) {
function buildComponentSchema(ast) {
const {

@@ -181,2 +182,4 @@ componentName,

const types = getTypes(ast);
const propProperties = getPropProperties(propsTypeName, types);

@@ -211,3 +214,3 @@ const commandOptions = getCommandOptions(commandOptionsExpression);

module.exports = {
processComponent,
buildComponentSchema,
};

@@ -57,3 +57,9 @@ /**

foundOptions = optionsExpression.properties.reduce((options, prop) => {
options[prop.key.name] = prop.value.value;
if (prop.value.type === 'ArrayExpression') {
options[prop.key.name] = prop.value.elements.map(
element => element.value,
);
} else {
options[prop.key.name] = prop.value.value;
}
return options;

@@ -60,0 +66,0 @@ }, {});

@@ -16,5 +16,8 @@ /**

function getPropProperties(propsTypeName , types ) {
function getPropProperties(
propsTypeName ,
types ,
) {
const typeAlias = types[propsTypeName];

@@ -325,3 +328,3 @@ try {

function buildPropSchema(property, types ) {
function buildPropSchema(property, types ) {
const name = property.key.name;

@@ -431,3 +434,3 @@

typeDefinition ,
types ,
types ,
) {

@@ -462,3 +465,3 @@ return typeDefinition

typeDefinition ,
types ,
types ,
) {

@@ -465,0 +468,0 @@ return flattenProperties(typeDefinition, types)

@@ -32,3 +32,3 @@ /**

function buildComponentSchema({
function wrapComponentSchema({
filename,

@@ -45,2 +45,3 @@ componentName,

[filename]: {
type: 'Component',
components: {

@@ -61,3 +62,3 @@ [componentName]: {

module.exports = {
buildComponentSchema,
wrapComponentSchema,
};

@@ -18,24 +18,10 @@ /**

const path = require('path');
const {buildModuleSchema} = require('./modules/schema');
const {buildComponentSchema} = require('./components/schema');
const {processComponent} = require('./components');
const {processModule} = require('./modules');
const {buildComponentSchema} = require('./components');
const {wrapComponentSchema} = require('./components/schema');
const {buildModuleSchema} = require('./modules');
const {wrapModuleSchema} = require('./modules/schema');
const {createParserErrorCapturer} = require('./utils');
const invariant = require('invariant');
function getTypes(ast) {
return ast.body.reduce((types, node) => {
if (node.type === 'ExportNamedDeclaration') {
if (node.declaration && node.declaration.type !== 'VariableDeclaration') {
types[node.declaration.id.name] = node.declaration;
}
} else if (
node.type === 'TypeAlias' ||
node.type === 'InterfaceDeclaration'
) {
types[node.id.name] = node;
}
return types;
}, {});
}
function getConfigType(ast, types) {
function isComponent(ast) {
const defaultExports = ast.body.filter(

@@ -45,36 +31,71 @@ node => node.type === 'ExportDefaultDeclaration',

let isComponent = false;
if (defaultExports.length === 0) {
return false;
}
if (defaultExports.length > 0) {
let declaration = defaultExports[0].declaration;
// codegenNativeComponent can be nested inside a cast
// expression so we need to go one level deeper
if (declaration.type === 'TypeCastExpression') {
declaration = declaration.expression;
}
let declaration = defaultExports[0].declaration;
// codegenNativeComponent can be nested inside a cast
// expression so we need to go one level deeper
if (declaration.type === 'TypeCastExpression') {
declaration = declaration.expression;
}
isComponent =
declaration &&
declaration.callee &&
declaration.callee.name === 'codegenNativeComponent';
if (declaration.type !== 'CallExpression') {
return false;
}
const typesExtendingTurboModule = Object.keys(types)
.map(typeName => types[typeName])
.filter(
type =>
type.extends &&
type.extends[0] &&
type.extends[0].id.name === 'TurboModule',
);
return (
declaration.callee.type === 'Identifier' &&
declaration.callee.name === 'codegenNativeComponent'
);
}
if (typesExtendingTurboModule.length > 1) {
function isModule(
// TODO(T71778680): Flow-type this node.
ast ,
) {
const moduleInterfaces = ast.body
.map(node => {
if (
node.type === 'ExportNamedDeclaration' &&
node.exportKind === 'type' &&
node.declaration.type === 'InterfaceDeclaration'
) {
return node.declaration;
}
return node;
})
.filter(declaration => {
return (
declaration.type === 'InterfaceDeclaration' &&
declaration.extends.length === 1 &&
declaration.extends[0].type === 'InterfaceExtends' &&
declaration.extends[0].id.name === 'TurboModule'
);
})
.map(declaration => declaration.id.name);
if (moduleInterfaces.length === 0) {
return false;
}
if (moduleInterfaces.length > 1) {
throw new Error(
'Found two types extending "TurboModule" is one file. Split them into separated files.',
'File contains declarations of more than one module: ' +
moduleInterfaces.join(', ') +
'. Please declare exactly one module in this file.',
);
}
const isModule = typesExtendingTurboModule.length === 1;
return true;
}
if (isModule && isComponent) {
function getConfigType(
// TODO(T71778680): Flow-type this node.
ast ,
) {
const isConfigAComponent = isComponent(ast);
const isConfigAModule = isModule(ast);
if (isConfigAModule && isConfigAComponent) {
throw new Error(

@@ -85,10 +106,11 @@ 'Found type extending "TurboModule" and exported "codegenNativeComponent" declaration in one file. Split them into separated files.',

if (isModule) {
if (isConfigAModule) {
return 'module';
} else if (isComponent) {
} else if (isConfigAComponent) {
return 'component';
} else {
throw new Error(
`Default export for module specified incorrectly. It should containts
either type extending "TurboModule" or "codegenNativeComponent".`,
'File neither contains a module declaration, nor a component declaration. ' +
'For module declarations, please make sure your file has an InterfaceDeclaration extending TurboModule. ' +
'For component declarations, please make sure your file has a default export calling the codegenNativeComponent<Props>(...) macro.',
);

@@ -98,11 +120,29 @@ }

function buildSchema(contents , filename ) {
const withSpace = (...args) => args.join('\\s*');
/**
* Parse the TurboModuleRegistry.get(Enforcing)? call using RegExp.
* Why? This call can appear anywhere in the NativeModule spec. Currently,
* there is no good way of traversing the AST to find the MemberExpression
* responsible for the call.
*/
const TURBO_MODULE_REGISTRY_REQUIRE_REGEX_STRING = withSpace(
'TurboModuleRegistry',
'\\.',
'get(Enforcing)?',
'<',
'Spec',
'>',
'\\(',
'[\'"](?<nativeModuleName>[A-Za-z$_0-9]+)[\'"]',
',?',
'\\)',
);
function buildSchema(contents , filename ) {
const ast = flowParser.parse(contents);
const types = getTypes(ast);
const configType = getConfigType(ast);
const configType = getConfigType(ast, types);
if (configType === 'component') {
return buildComponentSchema(processComponent(ast, types));
return wrapComponentSchema(buildComponentSchema(ast));
} else {

@@ -112,8 +152,57 @@ if (filename === undefined || filename === null) {

}
const moduleName = path.basename(filename).slice(6, -3);
return buildModuleSchema(processModule(types), moduleName);
const hasteModuleName = path.basename(filename).replace(/\.js$/, '');
const regex = new RegExp(TURBO_MODULE_REGISTRY_REQUIRE_REGEX_STRING, 'g');
let match = regex.exec(contents);
const errorHeader = `Error while parsing Module '${hasteModuleName}'`;
if (match == null) {
throw new Error(
`${errorHeader}: No call to TurboModuleRegistry.get<Spec>('...') detected.`,
);
}
const moduleNames = [];
while (match != null) {
const resultGroups = match.groups;
invariant(
resultGroups != null,
`Couldn't parse TurboModuleRegistry.(get|getEnforcing)<Spec> call in module '${hasteModuleName}'.`,
);
if (!moduleNames.includes(resultGroups.nativeModuleName)) {
moduleNames.push(resultGroups.nativeModuleName);
}
match = regex.exec(contents);
}
const [parsingErrors, guard] = createParserErrorCapturer();
const schema = guard(() =>
buildModuleSchema(hasteModuleName, moduleNames, ast, guard),
);
if (parsingErrors.length > 0) {
/**
* TODO(T77968131): We have two options:
* - Throw the first error, but indicate there are more then one errors.
* - Display all errors, nicely formatted.
*
* For the time being, we're just throw the first error.
**/
throw parsingErrors[0];
}
invariant(
schema != null,
'When there are no parsing errors, the schema should not be null',
);
return wrapModuleSchema(schema, hasteModuleName);
}
}
function parseFile(filename ) {
function parseFile(filename ) {
const contents = fs.readFileSync(filename, 'utf8');

@@ -124,3 +213,3 @@

function parseModuleFixture(filename ) {
function parseModuleFixture(filename ) {
const contents = fs.readFileSync(filename, 'utf8');

@@ -131,4 +220,4 @@

function parseString(contents ) {
return buildSchema(contents);
function parseString(contents , filename ) {
return buildSchema(contents, filename);
}

@@ -135,0 +224,0 @@

@@ -13,36 +13,584 @@ /**

const {getMethods} = require('./methods');
function getModuleProperties(types, interfaceName) {
if (types[interfaceName] && types[interfaceName].body) {
return types[interfaceName].body.properties;
const {resolveTypeAnnotation, getTypes} = require('../utils.js');
const {unwrapNullable, wrapNullable} = require('./utils');
const {
IncorrectlyParameterizedFlowGenericParserError,
MisnamedModuleFlowInterfaceParserError,
ModuleFlowInterfaceNotParserError,
UnnamedFunctionParamParserError,
UnsupportedArrayElementTypeAnnotationParserError,
UnsupportedFlowGenericParserError,
UnsupportedFlowTypeAnnotationParserError,
UnsupportedFunctionParamTypeAnnotationParserError,
UnsupportedFunctionReturnTypeAnnotationParserError,
UnsupportedModulePropertyParserError,
UnsupportedObjectPropertyTypeAnnotationParserError,
UnsupportedObjectPropertyValueTypeAnnotationParserError,
} = require('./errors.js');
const invariant = require('invariant');
function nullGuard (fn ) {
return fn();
}
function translateTypeAnnotation(
hasteModuleName ,
/**
* TODO(T71778680): Flow-type this node.
*/
flowTypeAnnotation ,
types ,
aliasMap ,
guard ,
) {
const {
nullable,
typeAnnotation,
typeAliasResolutionStatus,
} = resolveTypeAnnotation(flowTypeAnnotation, types);
switch (typeAnnotation.type) {
case 'GenericTypeAnnotation': {
switch (typeAnnotation.id.name) {
case 'RootTag': {
return wrapNullable(nullable, {
type: 'ReservedFunctionValueTypeAnnotation',
name: 'RootTag',
});
}
case 'Promise': {
assertGenericTypeAnnotationHasExactlyOneTypeParameter(
hasteModuleName,
typeAnnotation,
);
return wrapNullable(nullable, {
type: 'PromiseTypeAnnotation',
});
}
case 'Array':
case '$ReadOnlyArray': {
assertGenericTypeAnnotationHasExactlyOneTypeParameter(
hasteModuleName,
typeAnnotation,
);
try {
/**
* TODO(T72031674): Migrate all our NativeModule specs to not use
* invalid Array ElementTypes. Then, make the elementType a required
* parameter.
*/
const [elementType, isElementTypeNullable] = unwrapNullable(
translateTypeAnnotation(
hasteModuleName,
typeAnnotation.typeParameters.params[0],
types,
aliasMap,
/**
* TODO(T72031674): Ensure that all ParsingErrors that are thrown
* while parsing the array element don't get captured and collected.
* Why? If we detect any parsing error while parsing the element,
* we should default it to null down the line, here. This is
* the correct behaviour until we migrate all our NativeModule specs
* to be parseable.
*/
nullGuard,
),
);
if (elementType.type === 'VoidTypeAnnotation') {
throw new UnsupportedArrayElementTypeAnnotationParserError(
hasteModuleName,
typeAnnotation.typeParameters.params[0],
typeAnnotation.type,
'void',
);
}
if (elementType.type === 'PromiseTypeAnnotation') {
throw new UnsupportedArrayElementTypeAnnotationParserError(
hasteModuleName,
typeAnnotation.typeParameters.params[0],
typeAnnotation.type,
'Promise',
);
}
if (elementType.type === 'FunctionTypeAnnotation') {
throw new UnsupportedArrayElementTypeAnnotationParserError(
hasteModuleName,
typeAnnotation.typeParameters.params[0],
typeAnnotation.type,
'FunctionTypeAnnotation',
);
}
const finalTypeAnnotation
= {
type: 'ArrayTypeAnnotation',
elementType: wrapNullable(isElementTypeNullable, elementType),
};
return wrapNullable(nullable, finalTypeAnnotation);
} catch (ex) {
return wrapNullable(nullable, {
type: 'ArrayTypeAnnotation',
});
}
}
case '$ReadOnly': {
assertGenericTypeAnnotationHasExactlyOneTypeParameter(
hasteModuleName,
typeAnnotation,
);
return translateTypeAnnotation(
hasteModuleName,
typeAnnotation.typeParameters.params[0],
types,
aliasMap,
guard,
);
}
case 'Stringish': {
return wrapNullable(nullable, {
type: 'StringTypeAnnotation',
});
}
case 'Int32': {
return wrapNullable(nullable, {
type: 'Int32TypeAnnotation',
});
}
case 'Double': {
return wrapNullable(nullable, {
type: 'DoubleTypeAnnotation',
});
}
case 'Float': {
return wrapNullable(nullable, {
type: 'FloatTypeAnnotation',
});
}
case 'Object': {
return wrapNullable(nullable, {
type: 'GenericObjectTypeAnnotation',
});
}
default: {
throw new UnsupportedFlowGenericParserError(
hasteModuleName,
typeAnnotation,
);
}
}
}
case 'ObjectTypeAnnotation': {
const objectTypeAnnotation = {
type: 'ObjectTypeAnnotation',
properties: (typeAnnotation.properties )
.map (property => {
return guard(() => {
if (property.type !== 'ObjectTypeProperty') {
throw new UnsupportedObjectPropertyTypeAnnotationParserError(
hasteModuleName,
property,
property.type,
);
}
const {optional, key} = property;
const [
propertyTypeAnnotation,
isPropertyNullable,
] = unwrapNullable(
translateTypeAnnotation(
hasteModuleName,
property.value,
types,
aliasMap,
guard,
),
);
if (propertyTypeAnnotation.type === 'FunctionTypeAnnotation') {
throw new UnsupportedObjectPropertyValueTypeAnnotationParserError(
hasteModuleName,
property.value,
property.key,
propertyTypeAnnotation.type,
);
}
if (propertyTypeAnnotation.type === 'VoidTypeAnnotation') {
throw new UnsupportedObjectPropertyValueTypeAnnotationParserError(
hasteModuleName,
property.value,
property.key,
'void',
);
}
if (propertyTypeAnnotation.type === 'PromiseTypeAnnotation') {
throw new UnsupportedObjectPropertyValueTypeAnnotationParserError(
hasteModuleName,
property.value,
property.key,
'Promise',
);
}
return {
name: key.name,
optional,
typeAnnotation: wrapNullable(
isPropertyNullable,
propertyTypeAnnotation,
),
};
});
})
.filter(Boolean),
};
if (!typeAliasResolutionStatus.successful) {
return wrapNullable(nullable, objectTypeAnnotation);
}
/**
* All aliases RHS are required.
*/
aliasMap[typeAliasResolutionStatus.aliasName] = objectTypeAnnotation;
/**
* Nullability of type aliases is transitive.
*
* Consider this case:
*
* type Animal = ?{|
* name: string,
* |};
*
* type B = Animal
*
* export interface Spec extends TurboModule {
* +greet: (animal: B) => void;
* }
*
* In this case, we follow B to Animal, and then Animal to ?{|name: string|}.
*
* We:
* 1. Replace `+greet: (animal: B) => void;` with `+greet: (animal: ?Animal) => void;`,
* 2. Pretend that Animal = {|name: string|}.
*
* Why do we do this?
* 1. In ObjC, we need to generate a struct called Animal, not B.
* 2. This design is simpler than managing nullability within both the type alias usage, and the type alias RHS.
* 3. What does it mean for a C++ struct, which is what this type alias RHS will generate, to be nullable? ¯\_(ツ)_/¯
* Nullability is a concept that only makes sense when talking about instances (i.e: usages) of the C++ structs.
* Hence, it's better to manage nullability within the actual TypeAliasTypeAnnotation nodes, and not the
* associated ObjectTypeAnnotations.
*/
return wrapNullable(nullable, {
type: 'TypeAliasTypeAnnotation',
name: typeAliasResolutionStatus.aliasName,
});
}
case 'BooleanTypeAnnotation': {
return wrapNullable(nullable, {
type: 'BooleanTypeAnnotation',
});
}
case 'NumberTypeAnnotation': {
return wrapNullable(nullable, {
type: 'NumberTypeAnnotation',
});
}
case 'VoidTypeAnnotation': {
return wrapNullable(nullable, {
type: 'VoidTypeAnnotation',
});
}
case 'StringTypeAnnotation': {
return wrapNullable(nullable, {
type: 'StringTypeAnnotation',
});
}
case 'FunctionTypeAnnotation': {
return wrapNullable(
nullable,
translateFunctionTypeAnnotation(
hasteModuleName,
typeAnnotation,
types,
aliasMap,
guard,
),
);
}
default: {
throw new UnsupportedFlowTypeAnnotationParserError(
hasteModuleName,
typeAnnotation,
);
}
}
throw new Error(
`Interface properties for "${interfaceName}" has been specified incorrectly.`,
}
function assertGenericTypeAnnotationHasExactlyOneTypeParameter(
moduleName: st /**
* TODO(T71778680): This is a GenericTypeAnnotation. Flow type this node
*/
typeAnnotation: $F {
if (typeAnnotation.typeParameters == null) {
throw new IncorrectlyParameterizedFlowGenericParserError(
moduleName,
typeAnnotation,
);
}
invariant(
typeAnnotation.typeParameters.type === 'TypeParameterInstantiation',
"assertGenericTypeAnnotationHasExactlyOneTypeParameter: Type parameters must be an AST node of type 'TypeParameterInstantiation'",
);
if (typeAnnotation.typeParameters.params.length !== 1) {
throw new IncorrectlyParameterizedFlowGenericParserError(
moduleName,
typeAnnotation,
);
}
}
function findInterfaceName(types) {
return Object.keys(types)
.map(typeName => types[typeName])
.filter(
type =>
type.extends &&
type.extends[0] &&
type.extends[0].id.name === 'TurboModule',
)[0].id.name;
function translateFunctionTypeAnnotation(
hasteModuleName: st // TODO(T71778680): This is a FunctionTypeAnnotation. Type this.
flowFunctionTypeAnnotation: $F types: Ty aliasMap: {. guard: Pa Na const params: Ar ];
for (const flowParam of (flowFunctionTypeAnnotation.params: $R
const parsedParam = guard(() => {
if (flowParam.name == null) {
throw new UnnamedFunctionParamParserError(flowParam, hasteModuleName);
}
const paramName = flowParam.name.name;
const [
paramTypeAnnotation,
isParamTypeAnnotationNullable,
] = unwrapNullable(
translateTypeAnnotation(
hasteModuleName,
flowParam.typeAnnotation,
types,
aliasMap,
guard,
),
);
if (paramTypeAnnotation.type === 'VoidTypeAnnotation') {
throw new UnsupportedFunctionParamTypeAnnotationParserError(
hasteModuleName,
flowParam.typeAnnotation,
paramName,
'void',
);
}
if (paramTypeAnnotation.type === 'PromiseTypeAnnotation') {
throw new UnsupportedFunctionParamTypeAnnotationParserError(
hasteModuleName,
flowParam.typeAnnotation,
paramName,
'Promise',
);
}
return {
name: flowParam.name.name,
optional: flowParam.optional,
typeAnnotation: wrapNullable(
isParamTypeAnnotationNullable,
paramTypeAnnotation,
),
};
});
if (parsedParam != null) {
params.push(parsedParam);
}
}
const [returnTypeAnnotation, isReturnTypeAnnotationNullable] = unwrapNullable(
translateTypeAnnotation(
hasteModuleName,
flowFunctionTypeAnnotation.returnType,
types,
aliasMap,
guard,
),
);
if (returnTypeAnnotation.type === 'FunctionTypeAnnotation') {
throw new UnsupportedFunctionReturnTypeAnnotationParserError(
hasteModuleName,
flowFunctionTypeAnnotation.returnType,
'FunctionTypeAnnotation',
);
}
return {
type: 'FunctionTypeAnnotation',
returnTypeAnnotation: wrapNullable(
isReturnTypeAnnotationNullable,
returnTypeAnnotation,
),
params,
};
}
// $FlowFixMe there's no flowtype for AST
function processModule(types) {
const interfaceName = findInterfaceName(types);
function buildPropertySchema(
hasteModuleName: st // TODO(T71778680): This is an ObjectTypeProperty containing either:
// - a FunctionTypeAnnotation or GenericTypeAnnotation
// - a NullableTypeAnnoation containing a FunctionTypeAnnotation or GenericTypeAnnotation
// Flow type this node
property: $F types: Ty aliasMap: {. guard: Pa Na let nullable = false;
let {key, value} = property;
const moduleProperties = getModuleProperties(types, interfaceName);
const properties = getMethods(moduleProperties, types);
return {properties};
const methodName: st ey.name;
({nullable, typeAnnotation: value} = resolveTypeAnnotation(value, types));
if (value.type !== 'FunctionTypeAnnotation') {
throw new UnsupportedModulePropertyParserError(
hasteModuleName,
property.value,
property.key.name,
value.type,
);
}
return {
name: methodName,
optional: property.optional,
typeAnnotation: wrapNullable(
nullable,
translateFunctionTypeAnnotation(
hasteModuleName,
value,
types,
aliasMap,
guard,
),
),
};
}
function buildModuleSchema(
hasteModuleName: st moduleNames: $R /**
* TODO(T71778680): Flow-type this node.
*/
ast: $F guard: Pa Na const types = getTypes(ast);
const moduleInterfaceNames = (Object.keys(
types,
): $R lter((typeName: st {
const declaration = types[typeName];
return (
declaration.type === 'InterfaceDeclaration' &&
declaration.extends.length === 1 &&
declaration.extends[0].type === 'InterfaceExtends' &&
declaration.extends[0].id.name === 'TurboModule'
);
});
if (moduleInterfaceNames.length !== 1) {
throw new ModuleFlowInterfaceNotParserError(hasteModuleName, ast);
}
const [moduleInterfaceName] = moduleInterfaceNames;
if (moduleInterfaceName !== 'Spec') {
throw new MisnamedModuleFlowInterfaceParserError(
hasteModuleName,
types[moduleInterfaceName].id,
);
}
// Some module names use platform suffix to indicate platform-exclusive modules.
// Eventually this should be made explicit in the Flow type itself.
// Also check the hasteModuleName for platform suffix.
// Note: this shape is consistent with ComponentSchema.
const excludedPlatforms = [];
const namesToValidate = [...moduleNames, hasteModuleName];
namesToValidate.forEach(name => {
if (name.endsWith('Android')) {
excludedPlatforms.push('iOS');
} else if (name.endsWith('IOS')) {
excludedPlatforms.push('android');
}
});
const declaration = types[moduleInterfaceName];
return (declaration.body.properties: $R .filter(property => property.type === 'ObjectTypeProperty')
.map<?{|
perty => {
const aliasMap: {. };
return guard(() => ({
aliasMap: aliasMap,
propertySchema: buildPropertySchema(
hasteModuleName,
property,
types,
aliasMap,
guard,
),
}));
})
.filter(Boolean)
.reduce(
(moduleSchema: Na liasMap, propertySchema}) => {
return {
type: 'NativeModule',
aliases: {...moduleSchema.aliases, ...aliasMap},
spec: {
properties: [...moduleSchema.spec.properties, propertySchema],
},
moduleNames: moduleSchema.moduleNames,
excludedPlatforms: moduleSchema.excludedPlatforms,
};
},
{
type: 'NativeModule',
aliases: {},
spec: {properties: []},
moduleNames: moduleNames,
excludedPlatforms:
excludedPlatforms.length !== 0 ? [...excludedPlatforms] : undefined,
},
);
}
module.exports = {
processModule,
buildModuleSchema,
};

@@ -8,3 +8,3 @@ /**

* @format
* strict-local
* strict
*/

@@ -14,24 +14,11 @@

function buildModuleSchema(
{properties} ,
moduleName ,
function wrapModuleSchema(
nativeModuleSchema ,
hasteModuleName ,
) {
return {
modules: {
[`Native${moduleName}`]: {
nativeModules: {
[moduleName]: {
properties,
},
},
},
[hasteModuleName]: nativeModuleSchema,
},

@@ -42,3 +29,3 @@ };

module.exports = {
buildModuleSchema,
wrapModuleSchema,
};

@@ -13,9 +13,100 @@ /**

// $FlowFixMe there's no flowtype for ASTs
const {ParserError} = require('./errors');
/**
* This FlowFixMe is supposed to refer to an InterfaceDeclaration or TypeAlias
* declaration type. Unfortunately, we don't have those types, because flow-parser
* generates them, and flow-parser is not type-safe. In the future, we should find
* a way to get these types from our flow parser library.
*
* TODO(T71778680): Flow type AST Nodes
*/
function getTypes(ast ) {
return ast.body.reduce((types, node) => {
if (node.type === 'ExportNamedDeclaration' && node.exportKind === 'type') {
if (
node.declaration.type === 'TypeAlias' ||
node.declaration.type === 'InterfaceDeclaration'
) {
types[node.declaration.id.name] = node.declaration;
}
} else if (
node.type === 'TypeAlias' ||
node.type === 'InterfaceDeclaration'
) {
types[node.id.name] = node;
}
return types;
}, {});
}
// $FlowFixMe there's no flowtype for ASTs
function getValueFromTypes(value , types ) {
const invariant = require('invariant');
function resolveTypeAnnotation(
// TODO(T71778680): This is an Flow TypeAnnotation. Flow-type this
typeAnnotation ,
types ,
)
{
invariant(
typeAnnotation != null,
'resolveTypeAnnotation(): typeAnnotation cannot be null',
);
let node = typeAnnotation;
let nullable = false;
let typeAliasResolutionStatus = {
successful: false,
};
for (;;) {
if (node.type === 'NullableTypeAnnotation') {
nullable = true;
node = node.typeAnnotation;
} else if (node.type === 'GenericTypeAnnotation') {
typeAliasResolutionStatus = {
successful: true,
aliasName: node.id.name,
};
const resolvedTypeAnnotation = types[node.id.name];
if (resolvedTypeAnnotation == null) {
break;
}
invariant(
resolvedTypeAnnotation.type === 'TypeAlias',
`GenericTypeAnnotation '${node.id.name}' must resolve to a TypeAlias. Instead, it resolved to a '${resolvedTypeAnnotation.type}'`,
);
node = resolvedTypeAnnotation.right;
} else {
break;
}
}
return {
nullable: nullable,
typeAnnotation: node,
typeAliasResolutionStatus,
};
}
function getValueFromTypes(value , types ) {
if (value.type === 'GenericTypeAnnotation' && types[value.id.name]) {

@@ -27,4 +118,30 @@ return getValueFromTypes(types[value.id.name].right, types);

function createParserErrorCapturer()
{
const errors = [];
function guard (fn ) {
try {
return fn();
} catch (error) {
if (!(error instanceof ParserError)) {
throw error;
}
errors.push(error);
return null;
}
}
return [errors, guard];
}
module.exports = {
getValueFromTypes,
resolveTypeAnnotation,
createParserErrorCapturer,
getTypes,
};

@@ -9,9 +9,16 @@ declare type WritablePropType<T> = T extends ReadonlyArray<infer E1> ? WritableObjectType<E1>[] : T extends (infer E2)[] ? WritableObjectType<E2>[] : WritableObjectType<T>;

}
export interface RNRawObjectProperty {
name: string;
optional: boolean;
propertyType: RNRawType;
}
export interface RNRawObjectType {
kind: 'Object';
properties: {
name: string;
propertyType: RNRawType;
}[];
properties: RNRawObjectProperty[];
}
export interface RNRawFunctionParameter {
name: string;
optional: boolean;
parameterType: RNRawType;
}
export declare type RNRawType = ({

@@ -26,3 +33,3 @@ kind: 'StringLiterals';

} | {
kind: 'rn:ColorPrimitive' | 'rn:ImageSourcePrimitive' | 'rn:PointPrimitive' | 'rn:EdgeInsetsPrimitive';
kind: 'rn:ColorPrimitive' | 'rn:ImageSourcePrimitive' | 'rn:PointPrimitive' | 'rn:EdgeInsetsPrimitive' | 'rn:RootTag';
} | {

@@ -43,10 +50,10 @@ kind: 'Array';

returnType: RNRawType;
parameters: {
name: string;
parameterType: RNRawType;
}[];
parameters: RNRawFunctionParameter[];
} | {
kind: 'Union' | 'Tuple';
types: RNRawType[];
} | {
kind: 'Alias';
name: string;
}) & RNRawTypeCommon;
export {};
import * as ts from 'typescript';
import { RNRawType } from './RNRawType';
export declare function typeToRNRawType(typeNode: ts.TypeNode, sourceFile: ts.SourceFile, allowObject: boolean): RNRawType;
export interface RNRawTypeOptions {
allowObject: boolean;
knownAliases?: string[];
}
export declare function typeToRNRawType(typeNode: ts.TypeNode, sourceFile: ts.SourceFile, options: RNRawTypeOptions): RNRawType;

@@ -5,6 +5,7 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.typeToRNRawType = void 0;
// tslint:disable:no-conditional-assignment
var ts = require("typescript");
var ExportParser_1 = require("./ExportParser");
function functionToRNRawType(typeNode, sourceFile, allowObject) {
function functionToRNRawType(typeNode, sourceFile, options) {
if (typeNode.typeParameters !== undefined && typeNode.typeParameters.length !== 0) {

@@ -18,12 +19,13 @@ throw new Error("Type is not supported: " + typeNode.getText() + ".");

? { kind: 'Void', isNullable: false }
: typeToRNRawType(typeNode.type, sourceFile, allowObject),
: typeToRNRawType(typeNode.type, sourceFile, options),
parameters: typeNode.parameters.map(function (decl) { return ({
name: decl.name.getText(),
optional: decl.questionToken !== undefined,
parameterType: decl.type === undefined
? { kind: 'Any', isNullable: false }
: typeToRNRawType(decl.type, sourceFile, allowObject)
: typeToRNRawType(decl.type, sourceFile, options)
}); })
};
}
function typeToRNRawType(typeNode, sourceFile, allowObject) {
function typeToRNRawType(typeNode, sourceFile, options) {
var itemNullable = false;

@@ -72,2 +74,5 @@ var itemDefaultValue;

break;
case 'RootTag':
itemOthers.push({ kind: 'rn:RootTag', isNullable: false });
break;
case 'Object':

@@ -80,3 +85,3 @@ itemOthers.push({ kind: 'js:Object', isNullable: false });

}
itemOthers.push({ kind: 'js:Promise', isNullable: false, elementType: typeToRNRawType(item.typeArguments[0], sourceFile, allowObject) });
itemOthers.push({ kind: 'js:Promise', isNullable: false, elementType: typeToRNRawType(item.typeArguments[0], sourceFile, options) });
break;

@@ -89,3 +94,3 @@ }

}
var eventType = typeToRNRawType(item.typeArguments[0], sourceFile, true);
var eventType = typeToRNRawType(item.typeArguments[0], sourceFile, { allowObject: true, knownAliases: options.knownAliases });
var nameType = void 0;

@@ -114,3 +119,3 @@ if (item.typeArguments.length === 2) {

itemNullable = true;
itemOthers.push(typeToRNRawType(item.typeArguments[0], sourceFile, allowObject));
itemOthers.push(typeToRNRawType(item.typeArguments[0], sourceFile, options));
var defaultValue = item.typeArguments[1];

@@ -168,3 +173,3 @@ switch (defaultValue.kind) {

}
itemOthers.push(typeToRNRawType(item.typeArguments[0], sourceFile, allowObject));
itemOthers.push(typeToRNRawType(item.typeArguments[0], sourceFile, options));
break;

@@ -177,12 +182,17 @@ }

}
itemOthers.push({ kind: 'Array', isNullable: false, elementType: typeToRNRawType(item.typeArguments[0], sourceFile, allowObject) });
itemOthers.push({ kind: 'Array', isNullable: false, elementType: typeToRNRawType(item.typeArguments[0], sourceFile, options) });
break;
}
default: {
var resolvedType = ExportParser_1.resolveType(item, sourceFile);
if (resolvedType !== item) {
scannedItems.push(resolvedType);
if (options.knownAliases !== undefined && options.knownAliases.indexOf(typeReferenceName) !== -1) {
itemOthers.push({ kind: 'Alias', isNullable: false, name: typeReferenceName });
}
else {
recognized = false;
var resolvedType = ExportParser_1.resolveType(item, sourceFile);
if (resolvedType !== item) {
scannedItems.push(resolvedType);
}
else {
recognized = false;
}
}

@@ -202,3 +212,3 @@ }

else if (ts.isArrayTypeNode(item)) {
itemOthers.push({ kind: 'Array', isNullable: false, elementType: typeToRNRawType(item.elementType, sourceFile, allowObject) });
itemOthers.push({ kind: 'Array', isNullable: false, elementType: typeToRNRawType(item.elementType, sourceFile, options) });
}

@@ -215,2 +225,5 @@ else if (ts.isLiteralTypeNode(item)) {

}
else if (item.literal.kind === ts.SyntaxKind.NullKeyword) {
itemNullable = true;
}
else {

@@ -221,3 +234,3 @@ throw new Error("Type is not supported: " + typeNode.getText() + ", because " + item.literal + " is not a valid literal type.");

else if (ts.isFunctionTypeNode(item)) {
itemOthers.push(functionToRNRawType(item, sourceFile, allowObject));
itemOthers.push(functionToRNRawType(item, sourceFile, options));
}

@@ -228,3 +241,3 @@ else if (ts.isTupleTypeNode(item)) {

isNullable: false,
types: item.elementTypes.map(function (elementType) { return typeToRNRawType(elementType, sourceFile, allowObject); })
types: item.elements.map(function (elementType) { return typeToRNRawType(elementType, sourceFile, options); })
});

@@ -258,3 +271,3 @@ }

if (!recognized) {
if (allowObject) {
if (options.allowObject) {
var members = ExportParser_1.getMembersFromType(item, sourceFile);

@@ -275,3 +288,3 @@ if (members === undefined) {

if (ts.isMethodSignature(member) || ts.isCallSignatureDeclaration(member)) {
propertyType = functionToRNRawType(member, sourceFile, allowObject);
propertyType = functionToRNRawType(member, sourceFile, options);
}

@@ -281,10 +294,8 @@ else if (ts.isPropertySignature(member) || ts.isPropertyDeclaration(member)) {

? { kind: 'Any', isNullable: false }
: typeToRNRawType(member.type, sourceFile, allowObject);
: typeToRNRawType(member.type, sourceFile, options);
}
if (propertyType !== undefined) {
if (member.questionToken !== undefined) {
propertyType.isNullable = true;
}
rawObjectType.properties.push({
name: name,
optional: member.questionToken !== undefined,
propertyType: propertyType

@@ -291,0 +302,0 @@ });

{
"name": "react-native-tscodegen",
"version": "0.66.1",
"version": "0.67.0",
"description": "TypeScript Code Generation for React Native Turbo Module",

@@ -28,3 +28,3 @@ "main": "./lib/index.js",

"dependencies": {
"typescript": "^3.5.3",
"typescript": "^4.1.5",
"jscodeshift": "0.6.4",

@@ -31,0 +31,0 @@ "nullthrows": "1.1.1"

@@ -45,4 +45,6 @@ # Welcome to react-native-tscodegen (alpha)!

"tests",
"shadow-nodes",
"modules"
"shadow-nodes",
"modulesAndroid"
"modulesCxx"
"modulesIOS"
],

@@ -49,0 +51,0 @@ "inputFile": "./src/turboModule.ts"

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc