@react-native/codegen 0.72.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +21 -0
  2. package/lib/CodegenSchema.js +11 -0
  3. package/lib/CodegenSchema.js.flow +351 -0
  4. package/lib/SchemaValidator.js +54 -0
  5. package/lib/SchemaValidator.js.flow +67 -0
  6. package/lib/cli/combine/combine-js-to-schema-cli.js +50 -0
  7. package/lib/cli/combine/combine-js-to-schema-cli.js.flow +49 -0
  8. package/lib/cli/combine/combine-js-to-schema.js +110 -0
  9. package/lib/cli/combine/combine-js-to-schema.js.flow +48 -0
  10. package/lib/cli/combine/combine-utils.js +118 -0
  11. package/lib/cli/combine/combine-utils.js.flow +85 -0
  12. package/lib/cli/generators/generate-all.js +65 -0
  13. package/lib/cli/generators/generate-all.js.flow +66 -0
  14. package/lib/cli/parser/parser-cli.js +55 -0
  15. package/lib/cli/parser/parser-cli.js.flow +18 -0
  16. package/lib/cli/parser/parser.js +35 -0
  17. package/lib/cli/parser/parser.js.flow +37 -0
  18. package/lib/cli/parser/parser.sh +15 -0
  19. package/lib/generators/RNCodegen.js +207 -0
  20. package/lib/generators/RNCodegen.js.flow +284 -0
  21. package/lib/generators/Utils.js +31 -0
  22. package/lib/generators/Utils.js.flow +33 -0
  23. package/lib/generators/__test_fixtures__/fixtures.js +79 -0
  24. package/lib/generators/__test_fixtures__/fixtures.js.flow +82 -0
  25. package/lib/generators/components/ComponentsGeneratorUtils.js +217 -0
  26. package/lib/generators/components/ComponentsGeneratorUtils.js.flow +304 -0
  27. package/lib/generators/components/CppHelpers.js +188 -0
  28. package/lib/generators/components/CppHelpers.js.flow +228 -0
  29. package/lib/generators/components/GenerateComponentDescriptorH.js +75 -0
  30. package/lib/generators/components/GenerateComponentDescriptorH.js.flow +95 -0
  31. package/lib/generators/components/GenerateComponentHObjCpp.js +327 -0
  32. package/lib/generators/components/GenerateComponentHObjCpp.js.flow +418 -0
  33. package/lib/generators/components/GenerateEventEmitterCpp.js +199 -0
  34. package/lib/generators/components/GenerateEventEmitterCpp.js.flow +273 -0
  35. package/lib/generators/components/GenerateEventEmitterH.js +224 -0
  36. package/lib/generators/components/GenerateEventEmitterH.js.flow +315 -0
  37. package/lib/generators/components/GeneratePropsCpp.js +126 -0
  38. package/lib/generators/components/GeneratePropsCpp.js.flow +161 -0
  39. package/lib/generators/components/GeneratePropsH.js +606 -0
  40. package/lib/generators/components/GeneratePropsH.js.flow +778 -0
  41. package/lib/generators/components/GeneratePropsJavaDelegate.js +287 -0
  42. package/lib/generators/components/GeneratePropsJavaDelegate.js.flow +348 -0
  43. package/lib/generators/components/GeneratePropsJavaInterface.js +237 -0
  44. package/lib/generators/components/GeneratePropsJavaInterface.js.flow +288 -0
  45. package/lib/generators/components/GeneratePropsJavaPojo/PojoCollector.js +157 -0
  46. package/lib/generators/components/GeneratePropsJavaPojo/PojoCollector.js.flow +187 -0
  47. package/lib/generators/components/GeneratePropsJavaPojo/index.js +66 -0
  48. package/lib/generators/components/GeneratePropsJavaPojo/index.js.flow +80 -0
  49. package/lib/generators/components/GeneratePropsJavaPojo/serializePojo.js +273 -0
  50. package/lib/generators/components/GeneratePropsJavaPojo/serializePojo.js.flow +296 -0
  51. package/lib/generators/components/GenerateShadowNodeCpp.js +73 -0
  52. package/lib/generators/components/GenerateShadowNodeCpp.js.flow +95 -0
  53. package/lib/generators/components/GenerateShadowNodeH.js +91 -0
  54. package/lib/generators/components/GenerateShadowNodeH.js.flow +124 -0
  55. package/lib/generators/components/GenerateStateCpp.js +70 -0
  56. package/lib/generators/components/GenerateStateCpp.js.flow +92 -0
  57. package/lib/generators/components/GenerateStateH.js +93 -0
  58. package/lib/generators/components/GenerateStateH.js.flow +111 -0
  59. package/lib/generators/components/GenerateTests.js +165 -0
  60. package/lib/generators/components/GenerateTests.js.flow +219 -0
  61. package/lib/generators/components/GenerateThirdPartyFabricComponentsProviderH.js +91 -0
  62. package/lib/generators/components/GenerateThirdPartyFabricComponentsProviderH.js.flow +107 -0
  63. package/lib/generators/components/GenerateThirdPartyFabricComponentsProviderObjCpp.js +89 -0
  64. package/lib/generators/components/GenerateThirdPartyFabricComponentsProviderObjCpp.js.flow +105 -0
  65. package/lib/generators/components/GenerateViewConfigJs.js +410 -0
  66. package/lib/generators/components/GenerateViewConfigJs.js.flow +484 -0
  67. package/lib/generators/components/JavaHelpers.js +87 -0
  68. package/lib/generators/components/JavaHelpers.js.flow +119 -0
  69. package/lib/generators/components/__test_fixtures__/fixtures.js +1641 -0
  70. package/lib/generators/components/__test_fixtures__/fixtures.js.flow +1672 -0
  71. package/lib/generators/modules/GenerateModuleCpp.js +299 -0
  72. package/lib/generators/modules/GenerateModuleCpp.js.flow +278 -0
  73. package/lib/generators/modules/GenerateModuleH.js +373 -0
  74. package/lib/generators/modules/GenerateModuleH.js.flow +355 -0
  75. package/lib/generators/modules/GenerateModuleJavaSpec.js +571 -0
  76. package/lib/generators/modules/GenerateModuleJavaSpec.js.flow +553 -0
  77. package/lib/generators/modules/GenerateModuleJniCpp.js +505 -0
  78. package/lib/generators/modules/GenerateModuleJniCpp.js.flow +523 -0
  79. package/lib/generators/modules/GenerateModuleJniH.js +138 -0
  80. package/lib/generators/modules/GenerateModuleJniH.js.flow +148 -0
  81. package/lib/generators/modules/GenerateModuleObjCpp/StructCollector.js +262 -0
  82. package/lib/generators/modules/GenerateModuleObjCpp/StructCollector.js.flow +208 -0
  83. package/lib/generators/modules/GenerateModuleObjCpp/Utils.js +25 -0
  84. package/lib/generators/modules/GenerateModuleObjCpp/Utils.js.flow +32 -0
  85. package/lib/generators/modules/GenerateModuleObjCpp/header/serializeConstantsStruct.js +337 -0
  86. package/lib/generators/modules/GenerateModuleObjCpp/header/serializeConstantsStruct.js.flow +288 -0
  87. package/lib/generators/modules/GenerateModuleObjCpp/header/serializeRegularStruct.js +330 -0
  88. package/lib/generators/modules/GenerateModuleObjCpp/header/serializeRegularStruct.js.flow +279 -0
  89. package/lib/generators/modules/GenerateModuleObjCpp/header/serializeStruct.js +25 -0
  90. package/lib/generators/modules/GenerateModuleObjCpp/header/serializeStruct.js.flow +35 -0
  91. package/lib/generators/modules/GenerateModuleObjCpp/index.js +185 -0
  92. package/lib/generators/modules/GenerateModuleObjCpp/index.js.flow +219 -0
  93. package/lib/generators/modules/GenerateModuleObjCpp/serializeMethod.js +529 -0
  94. package/lib/generators/modules/GenerateModuleObjCpp/serializeMethod.js.flow +510 -0
  95. package/lib/generators/modules/GenerateModuleObjCpp/source/serializeModule.js +96 -0
  96. package/lib/generators/modules/GenerateModuleObjCpp/source/serializeModule.js.flow +121 -0
  97. package/lib/generators/modules/Utils.js +34 -0
  98. package/lib/generators/modules/Utils.js.flow +53 -0
  99. package/lib/generators/modules/__test_fixtures__/fixtures.js +1658 -0
  100. package/lib/generators/modules/__test_fixtures__/fixtures.js.flow +1669 -0
  101. package/lib/parsers/consistency/compareSnaps.js +84 -0
  102. package/lib/parsers/error-utils.js +284 -0
  103. package/lib/parsers/error-utils.js.flow +295 -0
  104. package/lib/parsers/errors.js +350 -0
  105. package/lib/parsers/errors.js.flow +439 -0
  106. package/lib/parsers/flow/components/__test_fixtures__/failures.js +583 -0
  107. package/lib/parsers/flow/components/__test_fixtures__/failures.js.flow +600 -0
  108. package/lib/parsers/flow/components/__test_fixtures__/fixtures.js +1001 -0
  109. package/lib/parsers/flow/components/__test_fixtures__/fixtures.js.flow +1016 -0
  110. package/lib/parsers/flow/components/commands.js +104 -0
  111. package/lib/parsers/flow/components/commands.js.flow +123 -0
  112. package/lib/parsers/flow/components/componentsUtils.js +446 -0
  113. package/lib/parsers/flow/components/componentsUtils.js.flow +496 -0
  114. package/lib/parsers/flow/components/events.js +233 -0
  115. package/lib/parsers/flow/components/events.js.flow +262 -0
  116. package/lib/parsers/flow/components/extends.js +52 -0
  117. package/lib/parsers/flow/components/extends.js.flow +66 -0
  118. package/lib/parsers/flow/components/index.js +267 -0
  119. package/lib/parsers/flow/components/index.js.flow +226 -0
  120. package/lib/parsers/flow/components/options.js +72 -0
  121. package/lib/parsers/flow/components/options.js.flow +87 -0
  122. package/lib/parsers/flow/components/props.js +47 -0
  123. package/lib/parsers/flow/components/props.js.flow +60 -0
  124. package/lib/parsers/flow/components/schema.js +106 -0
  125. package/lib/parsers/flow/components/schema.js.flow +62 -0
  126. package/lib/parsers/flow/index.js +80 -0
  127. package/lib/parsers/flow/index.js.flow +85 -0
  128. package/lib/parsers/flow/modules/__test_fixtures__/failures.js +215 -0
  129. package/lib/parsers/flow/modules/__test_fixtures__/failures.js.flow +223 -0
  130. package/lib/parsers/flow/modules/__test_fixtures__/fixtures.js +724 -0
  131. package/lib/parsers/flow/modules/__test_fixtures__/fixtures.js.flow +747 -0
  132. package/lib/parsers/flow/modules/index.js +528 -0
  133. package/lib/parsers/flow/modules/index.js.flow +420 -0
  134. package/lib/parsers/flow/parser.js +109 -0
  135. package/lib/parsers/flow/parser.js.flow +83 -0
  136. package/lib/parsers/flow/utils.js +108 -0
  137. package/lib/parsers/flow/utils.js.flow +123 -0
  138. package/lib/parsers/parser.js +11 -0
  139. package/lib/parsers/parser.js.flow +70 -0
  140. package/lib/parsers/parserMock.js +96 -0
  141. package/lib/parsers/parserMock.js.flow +68 -0
  142. package/lib/parsers/parsers-commons.js +448 -0
  143. package/lib/parsers/parsers-commons.js.flow +447 -0
  144. package/lib/parsers/parsers-primitives.js +387 -0
  145. package/lib/parsers/parsers-primitives.js.flow +383 -0
  146. package/lib/parsers/parsers-utils.js +18 -0
  147. package/lib/parsers/parsers-utils.js.flow +19 -0
  148. package/lib/parsers/schema/index.js +23 -0
  149. package/lib/parsers/schema/index.js.flow +26 -0
  150. package/lib/parsers/typescript/components/__test_fixtures__/failures.js +489 -0
  151. package/lib/parsers/typescript/components/__test_fixtures__/failures.js.flow +505 -0
  152. package/lib/parsers/typescript/components/__test_fixtures__/fixtures.js +1151 -0
  153. package/lib/parsers/typescript/components/__test_fixtures__/fixtures.js.flow +1168 -0
  154. package/lib/parsers/typescript/components/commands.js +132 -0
  155. package/lib/parsers/typescript/components/commands.js.flow +151 -0
  156. package/lib/parsers/typescript/components/componentsUtils.js +471 -0
  157. package/lib/parsers/typescript/components/componentsUtils.js.flow +521 -0
  158. package/lib/parsers/typescript/components/events.js +240 -0
  159. package/lib/parsers/typescript/components/events.js.flow +262 -0
  160. package/lib/parsers/typescript/components/extends.js +88 -0
  161. package/lib/parsers/typescript/components/extends.js.flow +103 -0
  162. package/lib/parsers/typescript/components/index.js +277 -0
  163. package/lib/parsers/typescript/components/index.js.flow +239 -0
  164. package/lib/parsers/typescript/components/options.js +72 -0
  165. package/lib/parsers/typescript/components/options.js.flow +87 -0
  166. package/lib/parsers/typescript/components/props.js +39 -0
  167. package/lib/parsers/typescript/components/props.js.flow +48 -0
  168. package/lib/parsers/typescript/components/schema.js +106 -0
  169. package/lib/parsers/typescript/components/schema.js.flow +62 -0
  170. package/lib/parsers/typescript/index.js +85 -0
  171. package/lib/parsers/typescript/index.js.flow +94 -0
  172. package/lib/parsers/typescript/modules/__test_fixtures__/failures.js +160 -0
  173. package/lib/parsers/typescript/modules/__test_fixtures__/failures.js.flow +167 -0
  174. package/lib/parsers/typescript/modules/__test_fixtures__/fixtures.js +701 -0
  175. package/lib/parsers/typescript/modules/__test_fixtures__/fixtures.js.flow +727 -0
  176. package/lib/parsers/typescript/modules/index.js +543 -0
  177. package/lib/parsers/typescript/modules/index.js.flow +435 -0
  178. package/lib/parsers/typescript/parseTopLevelType.js +203 -0
  179. package/lib/parsers/typescript/parseTopLevelType.js.flow +243 -0
  180. package/lib/parsers/typescript/parser.js +105 -0
  181. package/lib/parsers/typescript/parser.js.flow +87 -0
  182. package/lib/parsers/typescript/utils.js +101 -0
  183. package/lib/parsers/typescript/utils.js.flow +115 -0
  184. package/lib/parsers/utils.js +273 -0
  185. package/lib/parsers/utils.js.flow +266 -0
  186. package/package.json +45 -0
@@ -0,0 +1,521 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ 'use strict';
12
+ import type {ASTNode} from '../utils';
13
+ import type {NamedShape} from '../../../CodegenSchema.js';
14
+ const {
15
+ parseTopLevelType,
16
+ flattenIntersectionType,
17
+ } = require('../parseTopLevelType');
18
+ import type {TypeDeclarationMap} from '../../utils';
19
+
20
+ function getProperties(
21
+ typeName: string,
22
+ types: TypeDeclarationMap,
23
+ ): $FlowFixMe {
24
+ const alias = types[typeName];
25
+ if (!alias) {
26
+ throw new Error(
27
+ `Failed to find definition for "${typeName}", please check that you have a valid codegen typescript file`,
28
+ );
29
+ }
30
+ const aliasKind =
31
+ alias.type === 'TSInterfaceDeclaration' ? 'interface' : 'type';
32
+
33
+ try {
34
+ if (aliasKind === 'interface') {
35
+ return [...(alias.extends ?? []), ...alias.body.body];
36
+ }
37
+
38
+ return (
39
+ alias.typeAnnotation.members ||
40
+ alias.typeAnnotation.typeParameters.params[0].members ||
41
+ alias.typeAnnotation.typeParameters.params
42
+ );
43
+ } catch (e) {
44
+ throw new Error(
45
+ `Failed to find ${aliasKind} definition for "${typeName}", please check that you have a valid codegen typescript file`,
46
+ );
47
+ }
48
+ }
49
+
50
+ function getUnionOfLiterals(
51
+ name: string,
52
+ forArray: boolean,
53
+ elementTypes: $FlowFixMe[],
54
+ defaultValue: $FlowFixMe | void,
55
+ types: TypeDeclarationMap,
56
+ ) {
57
+ elementTypes.reduce((lastType, currType) => {
58
+ const lastFlattenedType =
59
+ lastType && lastType.type === 'TSLiteralType'
60
+ ? lastType.literal.type
61
+ : lastType.type;
62
+ const currFlattenedType =
63
+ currType.type === 'TSLiteralType' ? currType.literal.type : currType.type;
64
+
65
+ if (lastFlattenedType && currFlattenedType !== lastFlattenedType) {
66
+ throw new Error(`Mixed types are not supported (see "${name}")`);
67
+ }
68
+ return currType;
69
+ });
70
+
71
+ if (defaultValue === undefined) {
72
+ throw new Error(`A default enum value is required for "${name}"`);
73
+ }
74
+
75
+ const unionType = elementTypes[0].type;
76
+ if (
77
+ unionType === 'TSLiteralType' &&
78
+ elementTypes[0].literal?.type === 'StringLiteral'
79
+ ) {
80
+ return {
81
+ type: 'StringEnumTypeAnnotation',
82
+ default: (defaultValue: string),
83
+ options: elementTypes.map(option => option.literal.value),
84
+ };
85
+ } else if (
86
+ unionType === 'TSLiteralType' &&
87
+ elementTypes[0].literal?.type === 'NumericLiteral'
88
+ ) {
89
+ if (forArray) {
90
+ throw new Error(`Arrays of int enums are not supported (see: "${name}")`);
91
+ } else {
92
+ return {
93
+ type: 'Int32EnumTypeAnnotation',
94
+ default: (defaultValue: number),
95
+ options: elementTypes.map(option => option.literal.value),
96
+ };
97
+ }
98
+ } else {
99
+ throw new Error(
100
+ `Unsupported union type for "${name}", received "${
101
+ unionType === 'TSLiteralType'
102
+ ? elementTypes[0].literal?.type
103
+ : unionType
104
+ }"`,
105
+ );
106
+ }
107
+ }
108
+
109
+ function detectArrayType<T>(
110
+ name: string,
111
+ typeAnnotation: $FlowFixMe | ASTNode,
112
+ defaultValue: $FlowFixMe | void,
113
+ types: TypeDeclarationMap,
114
+ buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape<T>,
115
+ ): $FlowFixMe {
116
+ // Covers: readonly T[]
117
+ if (
118
+ typeAnnotation.type === 'TSTypeOperator' &&
119
+ typeAnnotation.operator === 'readonly' &&
120
+ typeAnnotation.typeAnnotation.type === 'TSArrayType'
121
+ ) {
122
+ return {
123
+ type: 'ArrayTypeAnnotation',
124
+ elementType: getTypeAnnotationForArray(
125
+ name,
126
+ typeAnnotation.typeAnnotation.elementType,
127
+ defaultValue,
128
+ types,
129
+ buildSchema,
130
+ ),
131
+ };
132
+ }
133
+
134
+ // Covers: T[]
135
+ if (typeAnnotation.type === 'TSArrayType') {
136
+ return {
137
+ type: 'ArrayTypeAnnotation',
138
+ elementType: getTypeAnnotationForArray(
139
+ name,
140
+ typeAnnotation.elementType,
141
+ defaultValue,
142
+ types,
143
+ buildSchema,
144
+ ),
145
+ };
146
+ }
147
+
148
+ // Covers: Array<T> and ReadonlyArray<T>
149
+ if (
150
+ typeAnnotation.type === 'TSTypeReference' &&
151
+ (typeAnnotation.typeName.name === 'ReadonlyArray' ||
152
+ typeAnnotation.typeName.name === 'Array')
153
+ ) {
154
+ return {
155
+ type: 'ArrayTypeAnnotation',
156
+ elementType: getTypeAnnotationForArray(
157
+ name,
158
+ typeAnnotation.typeParameters.params[0],
159
+ defaultValue,
160
+ types,
161
+ buildSchema,
162
+ ),
163
+ };
164
+ }
165
+
166
+ return null;
167
+ }
168
+
169
+ function buildObjectType<T>(
170
+ rawProperties: Array<$FlowFixMe>,
171
+ types: TypeDeclarationMap,
172
+ buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape<T>,
173
+ ): $FlowFixMe {
174
+ const flattenedProperties = flattenProperties(rawProperties, types);
175
+ const properties = flattenedProperties
176
+ .map(prop => buildSchema(prop, types))
177
+ .filter(Boolean);
178
+
179
+ return {
180
+ type: 'ObjectTypeAnnotation',
181
+ properties,
182
+ };
183
+ }
184
+
185
+ function getCommonTypeAnnotation<T>(
186
+ name: string,
187
+ forArray: boolean,
188
+ type: string,
189
+ typeAnnotation: $FlowFixMe,
190
+ defaultValue: $FlowFixMe | void,
191
+ types: TypeDeclarationMap,
192
+ buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape<T>,
193
+ ): $FlowFixMe {
194
+ switch (type) {
195
+ case 'TSTypeLiteral':
196
+ return buildObjectType(typeAnnotation.members, types, buildSchema);
197
+ case 'TSInterfaceDeclaration':
198
+ return buildObjectType([typeAnnotation], types, buildSchema);
199
+ case 'TSIntersectionType':
200
+ return buildObjectType(
201
+ flattenIntersectionType(typeAnnotation, types),
202
+ types,
203
+ buildSchema,
204
+ );
205
+ case 'ImageSource':
206
+ return {
207
+ type: 'ReservedPropTypeAnnotation',
208
+ name: 'ImageSourcePrimitive',
209
+ };
210
+ case 'ImageRequest':
211
+ return {
212
+ type: 'ReservedPropTypeAnnotation',
213
+ name: 'ImageRequestPrimitive',
214
+ };
215
+ case 'ColorValue':
216
+ case 'ProcessedColorValue':
217
+ return {
218
+ type: 'ReservedPropTypeAnnotation',
219
+ name: 'ColorPrimitive',
220
+ };
221
+ case 'PointValue':
222
+ return {
223
+ type: 'ReservedPropTypeAnnotation',
224
+ name: 'PointPrimitive',
225
+ };
226
+ case 'EdgeInsetsValue':
227
+ return {
228
+ type: 'ReservedPropTypeAnnotation',
229
+ name: 'EdgeInsetsPrimitive',
230
+ };
231
+ case 'TSUnionType':
232
+ return getUnionOfLiterals(
233
+ name,
234
+ forArray,
235
+ typeAnnotation.types,
236
+ defaultValue,
237
+ types,
238
+ );
239
+ case 'Int32':
240
+ return {
241
+ type: 'Int32TypeAnnotation',
242
+ };
243
+ case 'Double':
244
+ return {
245
+ type: 'DoubleTypeAnnotation',
246
+ };
247
+ case 'Float':
248
+ return {
249
+ type: 'FloatTypeAnnotation',
250
+ };
251
+ case 'TSBooleanKeyword':
252
+ return {
253
+ type: 'BooleanTypeAnnotation',
254
+ };
255
+ case 'Stringish':
256
+ case 'TSStringKeyword':
257
+ return {
258
+ type: 'StringTypeAnnotation',
259
+ };
260
+ default:
261
+ return undefined;
262
+ }
263
+ }
264
+
265
+ function getTypeAnnotationForArray<T>(
266
+ name: string,
267
+ typeAnnotation: $FlowFixMe,
268
+ defaultValue: $FlowFixMe | void,
269
+ types: TypeDeclarationMap,
270
+ buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape<T>,
271
+ ): $FlowFixMe {
272
+ // unpack WithDefault, (T) or T|U
273
+ const topLevelType = parseTopLevelType(typeAnnotation, types);
274
+ if (topLevelType.defaultValue !== undefined) {
275
+ throw new Error(
276
+ 'Nested optionals such as "ReadonlyArray<boolean | null | undefined>" are not supported, please declare optionals at the top level of value definitions as in "ReadonlyArray<boolean> | null | undefined"',
277
+ );
278
+ }
279
+ if (topLevelType.optional) {
280
+ throw new Error(
281
+ 'Nested optionals such as "ReadonlyArray<boolean | null | undefined>" are not supported, please declare optionals at the top level of value definitions as in "ReadonlyArray<boolean> | null | undefined"',
282
+ );
283
+ }
284
+
285
+ const extractedTypeAnnotation = topLevelType.type;
286
+ const arrayType = detectArrayType(
287
+ name,
288
+ extractedTypeAnnotation,
289
+ defaultValue,
290
+ types,
291
+ buildSchema,
292
+ );
293
+ if (arrayType) {
294
+ if (arrayType.elementType.type !== 'ObjectTypeAnnotation') {
295
+ throw new Error(
296
+ `Only array of array of object is supported for "${name}".`,
297
+ );
298
+ }
299
+ return arrayType;
300
+ }
301
+
302
+ const type =
303
+ extractedTypeAnnotation.elementType === 'TSTypeReference'
304
+ ? extractedTypeAnnotation.elementType.typeName.name
305
+ : extractedTypeAnnotation.elementType?.type ||
306
+ extractedTypeAnnotation.typeName?.name ||
307
+ extractedTypeAnnotation.type;
308
+
309
+ const common = getCommonTypeAnnotation(
310
+ name,
311
+ true,
312
+ type,
313
+ extractedTypeAnnotation,
314
+ defaultValue,
315
+ types,
316
+ buildSchema,
317
+ );
318
+ if (common) {
319
+ return common;
320
+ }
321
+
322
+ switch (type) {
323
+ case 'TSNumberKeyword':
324
+ return {
325
+ type: 'FloatTypeAnnotation',
326
+ };
327
+ default:
328
+ (type: empty);
329
+ throw new Error(`Unknown prop type for "${name}": ${type}`);
330
+ }
331
+ }
332
+
333
+ function setDefaultValue(
334
+ common: $FlowFixMe,
335
+ defaultValue: $FlowFixMe | void,
336
+ ): void {
337
+ switch (common.type) {
338
+ case 'Int32TypeAnnotation':
339
+ case 'DoubleTypeAnnotation':
340
+ common.default = ((defaultValue ? defaultValue : 0): number);
341
+ break;
342
+ case 'FloatTypeAnnotation':
343
+ common.default = ((defaultValue === null
344
+ ? null
345
+ : defaultValue
346
+ ? defaultValue
347
+ : 0): number | null);
348
+ break;
349
+ case 'BooleanTypeAnnotation':
350
+ common.default = defaultValue === null ? null : !!defaultValue;
351
+ break;
352
+ case 'StringTypeAnnotation':
353
+ common.default = ((defaultValue === undefined ? null : defaultValue):
354
+ | string
355
+ | null);
356
+ break;
357
+ }
358
+ }
359
+
360
+ function getTypeAnnotation<T>(
361
+ name: string,
362
+ annotation: $FlowFixMe | ASTNode,
363
+ defaultValue: $FlowFixMe | void,
364
+ types: TypeDeclarationMap,
365
+ buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape<T>,
366
+ ): $FlowFixMe {
367
+ // unpack WithDefault, (T) or T|U
368
+ const topLevelType = parseTopLevelType(annotation, types);
369
+ const typeAnnotation = topLevelType.type;
370
+ const arrayType = detectArrayType(
371
+ name,
372
+ typeAnnotation,
373
+ defaultValue,
374
+ types,
375
+ buildSchema,
376
+ );
377
+ if (arrayType) {
378
+ return arrayType;
379
+ }
380
+
381
+ const type =
382
+ typeAnnotation.type === 'TSTypeReference' ||
383
+ typeAnnotation.type === 'TSTypeAliasDeclaration'
384
+ ? typeAnnotation.typeName.name
385
+ : typeAnnotation.type;
386
+
387
+ const common = getCommonTypeAnnotation(
388
+ name,
389
+ false,
390
+ type,
391
+ typeAnnotation,
392
+ defaultValue,
393
+ types,
394
+ buildSchema,
395
+ );
396
+ if (common) {
397
+ setDefaultValue(common, defaultValue);
398
+ return common;
399
+ }
400
+
401
+ switch (type) {
402
+ case 'ColorArrayValue':
403
+ return {
404
+ type: 'ArrayTypeAnnotation',
405
+ elementType: {
406
+ type: 'ReservedPropTypeAnnotation',
407
+ name: 'ColorPrimitive',
408
+ },
409
+ };
410
+ case 'TSNumberKeyword':
411
+ throw new Error(
412
+ `Cannot use "${type}" type annotation for "${name}": must use a specific numeric type like Int32, Double, or Float`,
413
+ );
414
+ default:
415
+ (type: empty);
416
+ throw new Error(`Unknown prop type for "${name}": "${type}"`);
417
+ }
418
+ }
419
+
420
+ type SchemaInfo = {
421
+ name: string,
422
+ optional: boolean,
423
+ typeAnnotation: $FlowFixMe,
424
+ defaultValue: $FlowFixMe,
425
+ };
426
+
427
+ function getSchemaInfo(
428
+ property: PropAST,
429
+ types: TypeDeclarationMap,
430
+ ): SchemaInfo {
431
+ // unpack WithDefault, (T) or T|U
432
+ const topLevelType = parseTopLevelType(
433
+ property.typeAnnotation.typeAnnotation,
434
+ types,
435
+ );
436
+
437
+ const name = property.key.name;
438
+
439
+ if (!property.optional && topLevelType.defaultValue !== undefined) {
440
+ throw new Error(
441
+ `key ${name} must be optional if used with WithDefault<> annotation`,
442
+ );
443
+ }
444
+
445
+ return {
446
+ name,
447
+ optional: property.optional || topLevelType.optional,
448
+ typeAnnotation: topLevelType.type,
449
+ defaultValue: topLevelType.defaultValue,
450
+ };
451
+ }
452
+
453
+ // $FlowFixMe[unclear-type] TODO(T108222691): Use flow-types for @babel/parser
454
+ type PropAST = Object;
455
+
456
+ function verifyPropNotAlreadyDefined(
457
+ props: $ReadOnlyArray<PropAST>,
458
+ needleProp: PropAST,
459
+ ) {
460
+ const propName = needleProp.key.name;
461
+ const foundProp = props.some(prop => prop.key.name === propName);
462
+ if (foundProp) {
463
+ throw new Error(`A prop was already defined with the name ${propName}`);
464
+ }
465
+ }
466
+
467
+ function flattenProperties(
468
+ typeDefinition: $ReadOnlyArray<PropAST>,
469
+ types: TypeDeclarationMap,
470
+ ): $ReadOnlyArray<PropAST> {
471
+ return typeDefinition
472
+ .map(property => {
473
+ if (property.type === 'TSPropertySignature') {
474
+ return property;
475
+ } else if (property.type === 'TSTypeReference') {
476
+ return flattenProperties(
477
+ getProperties(property.typeName.name, types),
478
+ types,
479
+ );
480
+ } else if (
481
+ property.type === 'TSExpressionWithTypeArguments' ||
482
+ property.type === 'TSInterfaceHeritage'
483
+ ) {
484
+ return flattenProperties(
485
+ getProperties(property.expression.name, types),
486
+ types,
487
+ );
488
+ } else if (property.type === 'TSTypeLiteral') {
489
+ return flattenProperties(property.members, types);
490
+ } else if (property.type === 'TSInterfaceDeclaration') {
491
+ return flattenProperties(getProperties(property.id.name, types), types);
492
+ } else if (property.type === 'TSIntersectionType') {
493
+ return flattenProperties(property.types, types);
494
+ } else {
495
+ throw new Error(
496
+ `${property.type} is not a supported object literal type.`,
497
+ );
498
+ }
499
+ })
500
+ .filter(Boolean)
501
+ .reduce((acc: Array<PropAST>, item) => {
502
+ if (Array.isArray(item)) {
503
+ item.forEach((prop: PropAST) => {
504
+ verifyPropNotAlreadyDefined(acc, prop);
505
+ });
506
+ return acc.concat(item);
507
+ } else {
508
+ verifyPropNotAlreadyDefined(acc, item);
509
+ acc.push(item);
510
+ return acc;
511
+ }
512
+ }, [])
513
+ .filter(Boolean);
514
+ }
515
+
516
+ module.exports = {
517
+ getProperties,
518
+ getSchemaInfo,
519
+ getTypeAnnotation,
520
+ flattenProperties,
521
+ };