nitrogen 0.2.24 → 0.29.5

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 (241) hide show
  1. package/README.md +18 -108
  2. package/lib/Logger.js +56 -0
  3. package/lib/autolinking/Autolinking.js +1 -0
  4. package/lib/autolinking/android/createCMakeExtension.js +109 -0
  5. package/lib/autolinking/android/createGradleExtension.js +36 -0
  6. package/lib/autolinking/android/createHybridObjectInitializer.js +159 -0
  7. package/lib/autolinking/createAndroidAutolinking.js +13 -0
  8. package/lib/autolinking/createIOSAutolinking.js +19 -0
  9. package/lib/autolinking/ios/createHybridObjectInitializer.js +97 -0
  10. package/lib/autolinking/ios/createPodspecRubyExtension.js +69 -0
  11. package/lib/autolinking/ios/createSwiftCxxBridge.js +117 -0
  12. package/lib/autolinking/ios/createSwiftUmbrellaHeader.js +74 -0
  13. package/lib/config/NitroConfig.js +112 -0
  14. package/lib/config/NitroUserConfig.js +88 -0
  15. package/lib/config/getConfig.js +84 -0
  16. package/lib/createGitAttributes.js +11 -0
  17. package/lib/createPlatformSpec.js +127 -0
  18. package/lib/getFiles.js +28 -0
  19. package/lib/getPlatformSpecs.js +153 -0
  20. package/lib/index.js +113 -10
  21. package/lib/init.js +123 -0
  22. package/lib/nitrogen.js +165 -0
  23. package/lib/prettifyDirectory.js +27 -0
  24. package/lib/syntax/BridgedType.js +1 -0
  25. package/lib/syntax/CodeNode.js +1 -0
  26. package/lib/syntax/HybridObjectSpec.js +1 -0
  27. package/lib/syntax/Method.js +108 -0
  28. package/lib/syntax/Parameter.js +65 -0
  29. package/lib/syntax/Property.js +147 -0
  30. package/lib/syntax/SourceFile.js +7 -0
  31. package/lib/syntax/c++/CppEnum.js +110 -0
  32. package/lib/syntax/c++/CppHybridObject.js +146 -0
  33. package/lib/syntax/c++/CppHybridObjectRegistration.js +18 -0
  34. package/lib/syntax/c++/CppStruct.js +108 -0
  35. package/lib/syntax/c++/CppUnion.js +88 -0
  36. package/lib/syntax/c++/getForwardDeclaration.js +14 -0
  37. package/lib/syntax/c++/includeNitroHeader.js +34 -0
  38. package/lib/syntax/createType.js +303 -0
  39. package/lib/syntax/getAllTypes.js +11 -0
  40. package/lib/syntax/getCustomTypeConfig.js +53 -0
  41. package/lib/syntax/getHybridObjectName.d.ts +36 -0
  42. package/lib/syntax/getHybridObjectName.js +10 -0
  43. package/lib/syntax/getInterfaceProperties.js +9 -0
  44. package/lib/syntax/getReferencedTypes.js +47 -0
  45. package/lib/syntax/helpers.js +53 -0
  46. package/lib/syntax/isCoreType.js +47 -0
  47. package/lib/syntax/kotlin/FbjniHybridObject.js +261 -0
  48. package/lib/syntax/kotlin/JNINativeRegistrations.js +7 -0
  49. package/lib/syntax/kotlin/KotlinBoxedPrimitive.js +17 -0
  50. package/lib/syntax/kotlin/KotlinCxxBridgedType.js +893 -0
  51. package/lib/syntax/kotlin/KotlinEnum.js +113 -0
  52. package/lib/syntax/kotlin/KotlinFunction.js +256 -0
  53. package/lib/syntax/kotlin/KotlinHybridObject.js +177 -0
  54. package/lib/syntax/kotlin/KotlinHybridObjectRegistration.js +26 -0
  55. package/lib/syntax/kotlin/KotlinStruct.js +172 -0
  56. package/lib/syntax/kotlin/KotlinVariant.js +191 -0
  57. package/lib/syntax/swift/SwiftCxxBridgedType.js +819 -0
  58. package/lib/syntax/swift/SwiftCxxTypeHelper.js +613 -0
  59. package/lib/syntax/swift/SwiftEnum.js +52 -0
  60. package/lib/syntax/swift/SwiftFunction.js +83 -0
  61. package/lib/syntax/swift/SwiftHybridObject.js +103 -0
  62. package/lib/syntax/swift/SwiftHybridObjectBridge.js +451 -0
  63. package/lib/syntax/swift/SwiftHybridObjectRegistration.js +42 -0
  64. package/lib/syntax/swift/SwiftStruct.js +75 -0
  65. package/lib/syntax/swift/SwiftVariant.js +58 -0
  66. package/lib/syntax/types/ArrayBufferType.js +37 -0
  67. package/lib/syntax/types/ArrayType.d.ts +12 -0
  68. package/lib/syntax/types/ArrayType.js +52 -0
  69. package/lib/syntax/types/BigIntType.js +27 -0
  70. package/lib/syntax/types/BooleanType.js +27 -0
  71. package/lib/syntax/types/CustomType.d.ts +14 -0
  72. package/lib/syntax/types/CustomType.js +36 -0
  73. package/lib/syntax/types/DateType.js +35 -0
  74. package/lib/syntax/types/EnumType.js +101 -0
  75. package/lib/syntax/types/ErrorType.js +37 -0
  76. package/lib/syntax/types/FunctionType.js +147 -0
  77. package/lib/syntax/types/HybridObjectBaseType.js +38 -0
  78. package/lib/syntax/types/HybridObjectType.js +131 -0
  79. package/lib/syntax/types/MapType.js +37 -0
  80. package/lib/syntax/types/NamedWrappingType.js +27 -0
  81. package/lib/syntax/types/NullType.js +23 -0
  82. package/lib/syntax/types/NumberType.js +27 -0
  83. package/lib/syntax/types/OptionalType.js +59 -0
  84. package/lib/syntax/types/PromiseType.js +62 -0
  85. package/lib/syntax/types/RecordType.js +47 -0
  86. package/lib/syntax/types/ResultWrappingType.js +44 -0
  87. package/lib/syntax/types/StringType.js +35 -0
  88. package/lib/syntax/types/StructType.js +61 -0
  89. package/lib/syntax/types/TupleType.js +39 -0
  90. package/lib/syntax/types/Type.js +1 -0
  91. package/lib/syntax/types/VariantType.js +75 -0
  92. package/lib/syntax/types/VoidType.js +27 -0
  93. package/lib/syntax/types/getTypeAs.js +12 -0
  94. package/lib/utils.js +126 -0
  95. package/lib/views/CppHybridViewComponent.js +256 -0
  96. package/lib/views/createHostComponentJs.js +27 -0
  97. package/lib/views/kotlin/KotlinHybridViewManager.js +229 -0
  98. package/lib/views/swift/SwiftHybridViewManager.js +131 -0
  99. package/lib/writeFile.js +19 -0
  100. package/package.json +58 -29
  101. package/src/Logger.ts +63 -0
  102. package/src/autolinking/Autolinking.ts +9 -0
  103. package/src/autolinking/android/createCMakeExtension.ts +126 -0
  104. package/src/autolinking/android/createGradleExtension.ts +43 -0
  105. package/src/autolinking/android/createHybridObjectInitializer.ts +174 -0
  106. package/src/autolinking/createAndroidAutolinking.ts +28 -0
  107. package/src/autolinking/createIOSAutolinking.ts +24 -0
  108. package/src/autolinking/ios/createHybridObjectInitializer.ts +112 -0
  109. package/src/autolinking/ios/createPodspecRubyExtension.ts +76 -0
  110. package/src/autolinking/ios/createSwiftCxxBridge.ts +137 -0
  111. package/src/autolinking/ios/createSwiftUmbrellaHeader.ts +90 -0
  112. package/src/config/NitroConfig.ts +139 -0
  113. package/src/config/NitroUserConfig.ts +105 -0
  114. package/src/config/getConfig.ts +91 -0
  115. package/src/createGitAttributes.ts +15 -0
  116. package/src/createPlatformSpec.ts +176 -0
  117. package/src/getFiles.ts +31 -0
  118. package/src/getPlatformSpecs.ts +202 -0
  119. package/src/index.ts +146 -0
  120. package/src/init.ts +186 -0
  121. package/src/nitrogen.ts +246 -0
  122. package/src/prettifyDirectory.ts +32 -0
  123. package/src/syntax/BridgedType.ts +59 -0
  124. package/src/syntax/CodeNode.ts +24 -0
  125. package/src/syntax/HybridObjectSpec.ts +14 -0
  126. package/src/syntax/Method.ts +154 -0
  127. package/src/syntax/Parameter.ts +81 -0
  128. package/src/syntax/Property.ts +203 -0
  129. package/src/syntax/SourceFile.ts +80 -0
  130. package/src/syntax/c++/CppEnum.ts +128 -0
  131. package/src/syntax/c++/CppHybridObject.ts +165 -0
  132. package/src/syntax/c++/CppHybridObjectRegistration.ts +39 -0
  133. package/src/syntax/c++/CppStruct.ts +129 -0
  134. package/src/syntax/c++/CppUnion.ts +105 -0
  135. package/src/syntax/c++/getForwardDeclaration.ts +19 -0
  136. package/src/syntax/c++/includeNitroHeader.ts +40 -0
  137. package/src/syntax/createType.ts +365 -0
  138. package/src/syntax/getAllTypes.ts +18 -0
  139. package/src/syntax/getCustomTypeConfig.ts +71 -0
  140. package/src/syntax/getHybridObjectName.ts +48 -0
  141. package/src/syntax/getInterfaceProperties.ts +21 -0
  142. package/src/syntax/getReferencedTypes.ts +57 -0
  143. package/src/syntax/helpers.ts +79 -0
  144. package/src/syntax/isCoreType.ts +60 -0
  145. package/src/syntax/kotlin/FbjniHybridObject.ts +313 -0
  146. package/src/syntax/kotlin/JNINativeRegistrations.ts +19 -0
  147. package/src/syntax/kotlin/KotlinBoxedPrimitive.ts +19 -0
  148. package/src/syntax/kotlin/KotlinCxxBridgedType.ts +942 -0
  149. package/src/syntax/kotlin/KotlinEnum.ts +130 -0
  150. package/src/syntax/kotlin/KotlinFunction.ts +277 -0
  151. package/src/syntax/kotlin/KotlinHybridObject.ts +205 -0
  152. package/src/syntax/kotlin/KotlinHybridObjectRegistration.ts +51 -0
  153. package/src/syntax/kotlin/KotlinStruct.ts +198 -0
  154. package/src/syntax/kotlin/KotlinVariant.ts +212 -0
  155. package/src/syntax/swift/SwiftCxxBridgedType.ts +874 -0
  156. package/src/syntax/swift/SwiftCxxTypeHelper.ts +674 -0
  157. package/src/syntax/swift/SwiftEnum.ts +65 -0
  158. package/src/syntax/swift/SwiftFunction.ts +91 -0
  159. package/src/syntax/swift/SwiftHybridObject.ts +121 -0
  160. package/src/syntax/swift/SwiftHybridObjectBridge.ts +522 -0
  161. package/src/syntax/swift/SwiftHybridObjectRegistration.ts +75 -0
  162. package/src/syntax/swift/SwiftStruct.ts +85 -0
  163. package/src/syntax/swift/SwiftVariant.ts +67 -0
  164. package/src/syntax/types/ArrayBufferType.ts +49 -0
  165. package/src/syntax/types/ArrayType.ts +62 -0
  166. package/src/syntax/types/BigIntType.ts +35 -0
  167. package/src/syntax/types/BooleanType.ts +35 -0
  168. package/src/syntax/types/CustomType.ts +47 -0
  169. package/src/syntax/types/DateType.ts +43 -0
  170. package/src/syntax/types/EnumType.ts +130 -0
  171. package/src/syntax/types/ErrorType.ts +44 -0
  172. package/src/syntax/types/FunctionType.ts +167 -0
  173. package/src/syntax/types/HybridObjectBaseType.ts +54 -0
  174. package/src/syntax/types/HybridObjectType.ts +198 -0
  175. package/src/syntax/types/MapType.ts +49 -0
  176. package/src/syntax/types/NamedWrappingType.ts +33 -0
  177. package/src/syntax/types/NullType.ts +30 -0
  178. package/src/syntax/types/NumberType.ts +34 -0
  179. package/src/syntax/types/OptionalType.ts +66 -0
  180. package/src/syntax/types/PromiseType.ts +72 -0
  181. package/src/syntax/types/RecordType.ts +56 -0
  182. package/src/syntax/types/ResultWrappingType.ts +53 -0
  183. package/src/syntax/types/StringType.ts +44 -0
  184. package/src/syntax/types/StructType.ts +83 -0
  185. package/src/syntax/types/TupleType.ts +53 -0
  186. package/src/syntax/types/Type.ts +82 -0
  187. package/src/syntax/types/VariantType.ts +92 -0
  188. package/src/syntax/types/VoidType.ts +34 -0
  189. package/src/syntax/types/getTypeAs.ts +15 -0
  190. package/src/utils.ts +162 -0
  191. package/src/views/CppHybridViewComponent.ts +304 -0
  192. package/src/views/createHostComponentJs.ts +34 -0
  193. package/src/views/kotlin/KotlinHybridViewManager.ts +258 -0
  194. package/src/views/swift/SwiftHybridViewManager.ts +153 -0
  195. package/src/writeFile.ts +27 -0
  196. package/.jshintignore +0 -6
  197. package/.jshintrc +0 -3
  198. package/.npmignore +0 -3
  199. package/.travis.yml +0 -13
  200. package/LICENSE +0 -13
  201. package/browser/nitrogen-min.js +0 -3
  202. package/browser/nitrogen.js +0 -6369
  203. package/lib/apiKey.js +0 -67
  204. package/lib/blob.js +0 -57
  205. package/lib/commandManager.js +0 -350
  206. package/lib/device.js +0 -19
  207. package/lib/memoryStore.js +0 -24
  208. package/lib/message.js +0 -298
  209. package/lib/permission.js +0 -121
  210. package/lib/principal.js +0 -330
  211. package/lib/service.js +0 -347
  212. package/lib/session.js +0 -494
  213. package/lib/user.js +0 -20
  214. package/publish +0 -2
  215. package/scripts/build-documentation +0 -4
  216. package/scripts/build-module +0 -27
  217. package/scripts/module.js +0 -12
  218. package/scripts/postamble.js +0 -1
  219. package/scripts/preamble.js +0 -2
  220. package/scripts/run-test-server +0 -9
  221. package/test/config.js +0 -12
  222. package/test/fixtures/images/image.jpg +0 -0
  223. package/test/fixtures/images/motion0.jpg +0 -0
  224. package/test/fixtures/images/motion1.jpg +0 -0
  225. package/test/fixtures/images/motion2.jpg +0 -0
  226. package/test/fixtures/index.js +0 -76
  227. package/test/main.js +0 -5
  228. package/test/memoryStore.js +0 -22
  229. package/test/mocha.opts +0 -3
  230. package/test/units/apiKey.js +0 -46
  231. package/test/units/blob.js +0 -35
  232. package/test/units/commandManager.js +0 -67
  233. package/test/units/device.js +0 -26
  234. package/test/units/heartbeat.js +0 -28
  235. package/test/units/message.js +0 -79
  236. package/test/units/permissions.js +0 -43
  237. package/test/units/principal.js +0 -116
  238. package/test/units/service.js +0 -92
  239. package/test/units/session.js +0 -97
  240. package/test/units/user.js +0 -48
  241. package/yuidoc.json +0 -8
@@ -0,0 +1,75 @@
1
+ import { escapeCppName, isNotDuplicate } from '../helpers.js';
2
+ import {} from '../SourceFile.js';
3
+ export const VariantLabels = [
4
+ 'first',
5
+ 'second',
6
+ 'third',
7
+ 'fourth',
8
+ 'fifth',
9
+ 'sixth',
10
+ 'seventh',
11
+ 'eigth',
12
+ 'ninth',
13
+ 'tenth',
14
+ ];
15
+ export class VariantType {
16
+ variants;
17
+ aliasName;
18
+ constructor(variants, aliasName) {
19
+ this.variants = variants;
20
+ this.aliasName = aliasName;
21
+ }
22
+ get canBePassedByReference() {
23
+ // It's a variant<..> - heavy to copy
24
+ return true;
25
+ }
26
+ get kind() {
27
+ return 'variant';
28
+ }
29
+ get jsType() {
30
+ return this.variants.map((v) => v.kind).join(' | ');
31
+ }
32
+ get cases() {
33
+ return this.variants.map((v, i) => {
34
+ const label = VariantLabels[i];
35
+ if (label == null)
36
+ throw new Error(`Variant<...> (\`${this.jsType}\`) does not support ${i} cases!`);
37
+ return [label, v];
38
+ });
39
+ }
40
+ getAliasName(language, options) {
41
+ if (this.aliasName == null) {
42
+ const variants = this.variants.map((v) => v.getCode(language, options));
43
+ return escapeCppName(`Variant_${variants.join('_')}`);
44
+ }
45
+ return this.aliasName;
46
+ }
47
+ getCode(language, options) {
48
+ const types = this.variants
49
+ .map((v) => v.getCode(language, options))
50
+ .filter(isNotDuplicate);
51
+ switch (language) {
52
+ case 'c++':
53
+ return `std::variant<${types.join(', ')}>`;
54
+ case 'swift':
55
+ case 'kotlin':
56
+ return this.getAliasName(language, options);
57
+ default:
58
+ throw new Error(`Language ${language} is not yet supported for VariantType!`);
59
+ }
60
+ }
61
+ getExtraFiles() {
62
+ return this.variants.flatMap((v) => v.getExtraFiles());
63
+ }
64
+ getRequiredImports(language) {
65
+ const imports = this.variants.flatMap((v) => v.getRequiredImports(language));
66
+ if (language === 'c++') {
67
+ imports.push({
68
+ language: 'c++',
69
+ name: 'variant',
70
+ space: 'system',
71
+ });
72
+ }
73
+ return imports;
74
+ }
75
+ }
@@ -0,0 +1,27 @@
1
+ export class VoidType {
2
+ get canBePassedByReference() {
3
+ // It's void.
4
+ return false;
5
+ }
6
+ get kind() {
7
+ return 'void';
8
+ }
9
+ getCode(language) {
10
+ switch (language) {
11
+ case 'c++':
12
+ return 'void';
13
+ case 'swift':
14
+ return 'Void';
15
+ case 'kotlin':
16
+ return 'Unit';
17
+ default:
18
+ throw new Error(`Language ${language} is not yet supported for VoidType!`);
19
+ }
20
+ }
21
+ getExtraFiles() {
22
+ return [];
23
+ }
24
+ getRequiredImports() {
25
+ return [];
26
+ }
27
+ }
@@ -0,0 +1,12 @@
1
+ import { NamedWrappingType } from './NamedWrappingType.js';
2
+ export function getTypeAs(type, classReference) {
3
+ if (type instanceof classReference) {
4
+ return type;
5
+ }
6
+ else if (type instanceof NamedWrappingType) {
7
+ return getTypeAs(type.type, classReference);
8
+ }
9
+ else {
10
+ throw new Error(`Type of kind "${type.kind}" is not a ${classReference}!`);
11
+ }
12
+ }
package/lib/utils.js ADDED
@@ -0,0 +1,126 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ import { isNotDuplicate } from './syntax/helpers.js';
4
+ import { readUserConfig } from './config/getConfig.js';
5
+ import { NitroConfig } from './config/NitroConfig.js';
6
+ export const NITROGEN_VERSION = process.env.npm_package_version ?? '?.?.?';
7
+ export function capitalizeName(name) {
8
+ if (name.length === 0)
9
+ return name;
10
+ return name.charAt(0).toUpperCase() + name.slice(1);
11
+ }
12
+ export function createIndentation(spacesCount) {
13
+ return Array.from(Array(spacesCount)).fill(' ').join('');
14
+ }
15
+ export function indent(string, indentation) {
16
+ let spaces;
17
+ if (typeof indentation === 'number') {
18
+ spaces = createIndentation(indentation);
19
+ }
20
+ else {
21
+ spaces = indentation;
22
+ }
23
+ return string.replaceAll('\n', `\n${spaces}`);
24
+ }
25
+ export function errorToString(error) {
26
+ if (error == null) {
27
+ return `null`;
28
+ }
29
+ if (typeof error !== 'object') {
30
+ return `${error}`;
31
+ }
32
+ if (error instanceof Error) {
33
+ let message = `${error.name}: ${error.message}`;
34
+ if (error.cause != null) {
35
+ message += ` (cause: ${JSON.stringify(error.cause)})`;
36
+ }
37
+ return message;
38
+ }
39
+ if ('toString' in error) {
40
+ return error.toString();
41
+ }
42
+ return JSON.stringify(error);
43
+ }
44
+ export function escapeComments(string) {
45
+ return string
46
+ .replace(/\/\*/g, '/ *') // Escape start of comment
47
+ .replace(/\*\//g, '* /') // Escape end of comment
48
+ .replace(/\/\//g, '/ /'); // Escape single-line comment
49
+ }
50
+ const HAS_UNIX_PATHS = path.join('a', 'b').includes('/');
51
+ export function toUnixPath(p) {
52
+ if (HAS_UNIX_PATHS)
53
+ return p;
54
+ return p.replaceAll('\\', '/');
55
+ }
56
+ const sep = path.sep;
57
+ export function unsafeFastJoin(...segments) {
58
+ // this function should really not take any unsafe strings like `/` or `\`.
59
+ return segments.join(sep);
60
+ }
61
+ function getFullPath(file) {
62
+ return unsafeFastJoin(file.platform, file.language, ...file.subdirectory, file.name);
63
+ }
64
+ /**
65
+ * Deduplicates all files via their full path.
66
+ * If content differs, you are f*cked.
67
+ */
68
+ export function deduplicateFiles(files) {
69
+ const map = new Map();
70
+ for (const file of files) {
71
+ const filePath = getFullPath(file);
72
+ if (!map.has(filePath)) {
73
+ map.set(filePath, file);
74
+ }
75
+ }
76
+ return [...map.values()];
77
+ }
78
+ export function filterDuplicateHelperBridges(bridge, i, array) {
79
+ const otherIndex = array.findIndex((f2) => bridge.specializationName === f2.specializationName);
80
+ return otherIndex === i;
81
+ }
82
+ export function toLowerCamelCase(string) {
83
+ const parts = string.split('_').filter((part) => part !== '');
84
+ if (parts.length === 0)
85
+ return '';
86
+ const camelCaseString = parts[0].toLowerCase();
87
+ const camelCased = parts
88
+ .slice(1)
89
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase());
90
+ return camelCaseString + camelCased.join('');
91
+ }
92
+ export function getBaseTypes(type) {
93
+ const baseTypes = type.getBaseTypes();
94
+ const symbol = type.getSymbol();
95
+ if (symbol != null) {
96
+ baseTypes.push(...symbol.getDeclaredType().getBaseTypes());
97
+ }
98
+ const recursive = baseTypes.flatMap((b) => [b, ...getBaseTypes(b)]);
99
+ return recursive.filter(isNotDuplicate);
100
+ }
101
+ export function getHybridObjectNitroModuleConfig(type) {
102
+ const symbol = type.getSymbol() ?? type.getAliasSymbol();
103
+ if (!symbol)
104
+ return undefined;
105
+ const declarations = symbol.getValueDeclaration() || symbol.getDeclarations()[0];
106
+ if (!declarations)
107
+ return undefined;
108
+ const sourceFile = declarations.getSourceFile();
109
+ let filePath = sourceFile.getFilePath();
110
+ while (true) {
111
+ // go up one dir
112
+ const newFilePath = path.resolve(path.join(filePath, '..'));
113
+ if (filePath === newFilePath) {
114
+ // going 'cd ..' in that path didn't change a thing - so we
115
+ // reached the root directory. we didn't find a nitro.json anywhere.
116
+ return undefined;
117
+ }
118
+ filePath = newFilePath;
119
+ const nitroJsonPath = path.join(filePath, 'nitro.json');
120
+ const hasNitroJson = fs.existsSync(nitroJsonPath);
121
+ if (hasNitroJson) {
122
+ const config = readUserConfig(nitroJsonPath);
123
+ return new NitroConfig(config);
124
+ }
125
+ }
126
+ }
@@ -0,0 +1,256 @@
1
+ import { createIndentation, indent } from '../utils.js';
2
+ import { createFileMetadataString, escapeCppName, isFunction, isNotDuplicate, } from '../syntax/helpers.js';
3
+ import { getHybridObjectName } from '../syntax/getHybridObjectName.js';
4
+ import { includeHeader } from '../syntax/c++/includeNitroHeader.js';
5
+ import { createHostComponentJs } from './createHostComponentJs.js';
6
+ import { Property } from '../syntax/Property.js';
7
+ import { FunctionType } from '../syntax/types/FunctionType.js';
8
+ import { VoidType } from '../syntax/types/VoidType.js';
9
+ import { HybridObjectType } from '../syntax/types/HybridObjectType.js';
10
+ import { NamedWrappingType } from '../syntax/types/NamedWrappingType.js';
11
+ import { OptionalType } from '../syntax/types/OptionalType.js';
12
+ export function getViewComponentNames(spec) {
13
+ const name = getHybridObjectName(spec.name);
14
+ return {
15
+ propsClassName: `${name.HybridT}Props`,
16
+ stateClassName: `${name.HybridT}State`,
17
+ nameVariable: `${name.HybridT}ComponentName`,
18
+ shadowNodeClassName: `${name.HybridT}ShadowNode`,
19
+ descriptorClassName: `${name.HybridT}ComponentDescriptor`,
20
+ component: `${name.HybridT}Component`,
21
+ manager: `${name.HybridT}Manager`,
22
+ };
23
+ }
24
+ function getHybridRefProperty(spec) {
25
+ const hybrid = new HybridObjectType(spec);
26
+ const type = new FunctionType(new VoidType(), [
27
+ new NamedWrappingType('ref', hybrid),
28
+ ]);
29
+ return new Property('hybridRef', new OptionalType(type), false);
30
+ }
31
+ export function createViewComponentShadowNodeFiles(spec) {
32
+ if (!spec.isHybridView) {
33
+ throw new Error(`Cannot create View Component ShadowNode code for ${spec.name} - it's not a HybridView!`);
34
+ }
35
+ const { T, HybridT } = getHybridObjectName(spec.name);
36
+ const { propsClassName, stateClassName, nameVariable, shadowNodeClassName, descriptorClassName, component, } = getViewComponentNames(spec);
37
+ const namespace = spec.config.getCxxNamespace('c++', 'views');
38
+ const props = [...spec.properties, getHybridRefProperty(spec)];
39
+ const properties = props.map((p) => `CachedProp<${p.type.getCode('c++')}> ${escapeCppName(p.name)};`);
40
+ const cases = props.map((p) => `case hashString("${p.name}"): return true;`);
41
+ const includes = props
42
+ .flatMap((p) => p.getRequiredImports('c++').map((i) => includeHeader(i, true)))
43
+ .filter(isNotDuplicate);
44
+ // .hpp code
45
+ const shadowIndent = createIndentation(shadowNodeClassName.length);
46
+ const componentHeaderCode = `
47
+ ${createFileMetadataString(`${component}.hpp`)}
48
+
49
+ #pragma once
50
+
51
+ #include <optional>
52
+ #include <NitroModules/NitroDefines.hpp>
53
+ #include <NitroModules/NitroHash.hpp>
54
+ #include <NitroModules/CachedProp.hpp>
55
+ #include <react/renderer/core/ConcreteComponentDescriptor.h>
56
+ #include <react/renderer/core/PropsParserContext.h>
57
+ #include <react/renderer/components/view/ConcreteViewShadowNode.h>
58
+ #include <react/renderer/components/view/ViewProps.h>
59
+
60
+ ${includes.join('\n')}
61
+
62
+ namespace ${namespace} {
63
+
64
+ using namespace facebook;
65
+
66
+ /**
67
+ * The name of the actual native View.
68
+ */
69
+ extern const char ${nameVariable}[];
70
+
71
+ /**
72
+ * Props for the "${spec.name}" View.
73
+ */
74
+ class ${propsClassName} final: public react::ViewProps {
75
+ public:
76
+ ${propsClassName}() = default;
77
+ ${propsClassName}(const ${propsClassName}&);
78
+ ${propsClassName}(const react::PropsParserContext& context,
79
+ ${createIndentation(propsClassName.length)} const ${propsClassName}& sourceProps,
80
+ ${createIndentation(propsClassName.length)} const react::RawProps& rawProps);
81
+
82
+ public:
83
+ ${indent(properties.join('\n'), ' ')}
84
+
85
+ private:
86
+ static bool filterObjectKeys(const std::string& propName);
87
+ };
88
+
89
+ /**
90
+ * State for the "${spec.name}" View.
91
+ */
92
+ class ${stateClassName} final {
93
+ public:
94
+ ${stateClassName}() = default;
95
+
96
+ public:
97
+ void setProps(const ${propsClassName}& props) { _props.emplace(props); }
98
+ const std::optional<${propsClassName}>& getProps() const { return _props; }
99
+
100
+ public:
101
+ #ifdef ANDROID
102
+ ${stateClassName}(const ${stateClassName}& /* previousState */, folly::dynamic /* data */) {}
103
+ folly::dynamic getDynamic() const {
104
+ throw std::runtime_error("${stateClassName} does not support folly!");
105
+ }
106
+ react::MapBuffer getMapBuffer() const {
107
+ throw std::runtime_error("${stateClassName} does not support MapBuffer!");
108
+ };
109
+ #endif
110
+
111
+ private:
112
+ std::optional<${propsClassName}> _props;
113
+ };
114
+
115
+ /**
116
+ * The Shadow Node for the "${spec.name}" View.
117
+ */
118
+ using ${shadowNodeClassName} = react::ConcreteViewShadowNode<${nameVariable} /* "${HybridT}" */,
119
+ ${shadowIndent} ${propsClassName} /* custom props */,
120
+ ${shadowIndent} react::ViewEventEmitter /* default */,
121
+ ${shadowIndent} ${stateClassName} /* custom state */>;
122
+
123
+ /**
124
+ * The Component Descriptor for the "${spec.name}" View.
125
+ */
126
+ class ${descriptorClassName} final: public react::ConcreteComponentDescriptor<${shadowNodeClassName}> {
127
+ public:
128
+ ${descriptorClassName}(const react::ComponentDescriptorParameters& parameters);
129
+
130
+ public:
131
+ /**
132
+ * A faster path for cloning props - reuses the caching logic from \`${propsClassName}\`.
133
+ */
134
+ std::shared_ptr<const react::Props> cloneProps(const react::PropsParserContext& context,
135
+ const std::shared_ptr<const react::Props>& props,
136
+ react::RawProps rawProps) const override;
137
+ #ifdef ANDROID
138
+ void adopt(react::ShadowNode& shadowNode) const override;
139
+ #endif
140
+ };
141
+
142
+ /* The actual view for "${spec.name}" needs to be implemented in platform-specific code. */
143
+
144
+ } // namespace ${namespace}
145
+ `.trim();
146
+ // .cpp code
147
+ const propInitializers = [
148
+ 'react::ViewProps(context, sourceProps, rawProps, filterObjectKeys)',
149
+ ];
150
+ const propCopyInitializers = ['react::ViewProps()'];
151
+ for (const prop of props) {
152
+ const name = escapeCppName(prop.name);
153
+ const type = prop.type.getCode('c++');
154
+ let valueConversion = `value`;
155
+ if (isFunction(prop.type)) {
156
+ // Due to a React limitation, functions cannot be passed to native directly,
157
+ // because RN converts them to booleans (`true`). Nitro knows this and just
158
+ // wraps functions as objects - the original function is stored in `f`.
159
+ valueConversion = `value.asObject(*runtime).getProperty(*runtime, "f")`;
160
+ }
161
+ propInitializers.push(`
162
+ ${name}([&]() -> CachedProp<${type}> {
163
+ try {
164
+ const react::RawValue* rawValue = rawProps.at("${prop.name}", nullptr, nullptr);
165
+ if (rawValue == nullptr) return sourceProps.${name};
166
+ const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
167
+ return CachedProp<${type}>::fromRawValue(*runtime, ${valueConversion}, sourceProps.${name});
168
+ } catch (const std::exception& exc) {
169
+ throw std::runtime_error(std::string("${spec.name}.${prop.name}: ") + exc.what());
170
+ }
171
+ }())`.trim());
172
+ propCopyInitializers.push(`${name}(other.${name})`);
173
+ }
174
+ const ctorIndent = createIndentation(propsClassName.length * 2);
175
+ const descriptorIndent = createIndentation(descriptorClassName.length);
176
+ const componentCode = `
177
+ ${createFileMetadataString(`${component}.cpp`)}
178
+
179
+ #include "${component}.hpp"
180
+
181
+ #include <string>
182
+ #include <exception>
183
+ #include <utility>
184
+ #include <NitroModules/NitroDefines.hpp>
185
+ #include <NitroModules/JSIConverter.hpp>
186
+ #include <react/renderer/core/RawValue.h>
187
+ #include <react/renderer/core/ShadowNode.h>
188
+ #include <react/renderer/core/ComponentDescriptor.h>
189
+ #include <react/renderer/components/view/ViewProps.h>
190
+
191
+ namespace ${namespace} {
192
+
193
+ extern const char ${nameVariable}[] = "${T}";
194
+
195
+ ${propsClassName}::${propsClassName}(const react::PropsParserContext& context,
196
+ ${ctorIndent} const ${propsClassName}& sourceProps,
197
+ ${ctorIndent} const react::RawProps& rawProps):
198
+ ${indent(propInitializers.join(',\n'), ' ')} { }
199
+
200
+ ${propsClassName}::${propsClassName}(const ${propsClassName}& other):
201
+ ${indent(propCopyInitializers.join(',\n'), ' ')} { }
202
+
203
+ bool ${propsClassName}::filterObjectKeys(const std::string& propName) {
204
+ switch (hashString(propName)) {
205
+ ${indent(cases.join('\n'), ' ')}
206
+ default: return false;
207
+ }
208
+ }
209
+
210
+ ${descriptorClassName}::${descriptorClassName}(const react::ComponentDescriptorParameters& parameters)
211
+ : ConcreteComponentDescriptor(parameters,
212
+ react::RawPropsParser(/* enableJsiParser */ true)) {}
213
+
214
+ std::shared_ptr<const react::Props> ${descriptorClassName}::cloneProps(const react::PropsParserContext& context,
215
+ ${descriptorIndent} const std::shared_ptr<const react::Props>& props,
216
+ ${descriptorIndent} react::RawProps rawProps) const {
217
+ // 1. Prepare raw props parser
218
+ rawProps.parse(rawPropsParser_);
219
+ // 2. Copy props with Nitro's cached copy constructor
220
+ return ${shadowNodeClassName}::Props(context, /* & */ rawProps, props);
221
+ }
222
+
223
+ #ifdef ANDROID
224
+ void ${descriptorClassName}::adopt(react::ShadowNode& shadowNode) const {
225
+ // This is called immediately after \`ShadowNode\` is created, cloned or in progress.
226
+ // On Android, we need to wrap props in our state, which gets routed through Java and later unwrapped in JNI/C++.
227
+ auto& concreteShadowNode = dynamic_cast<${shadowNodeClassName}&>(shadowNode);
228
+ const ${propsClassName}& props = concreteShadowNode.getConcreteProps();
229
+ ${stateClassName} state;
230
+ state.setProps(props);
231
+ concreteShadowNode.setStateData(std::move(state));
232
+ }
233
+ #endif
234
+
235
+ } // namespace ${namespace}
236
+ `.trim();
237
+ const files = [
238
+ {
239
+ name: `${component}.hpp`,
240
+ content: componentHeaderCode,
241
+ language: 'c++',
242
+ platform: 'shared',
243
+ subdirectory: ['views'],
244
+ },
245
+ {
246
+ name: `${component}.cpp`,
247
+ content: componentCode,
248
+ language: 'c++',
249
+ platform: 'shared',
250
+ subdirectory: ['views'],
251
+ },
252
+ ];
253
+ const jsFiles = createHostComponentJs(spec);
254
+ files.push(...jsFiles);
255
+ return files;
256
+ }
@@ -0,0 +1,27 @@
1
+ import { getHybridObjectName } from '../syntax/getHybridObjectName.js';
2
+ import { indent } from '../utils.js';
3
+ export function createHostComponentJs(spec) {
4
+ const { T } = getHybridObjectName(spec.name);
5
+ const props = spec.properties.map((p) => `"${p.name}": true`);
6
+ props.push(`"hybridRef": true`);
7
+ const code = `
8
+ {
9
+ "uiViewClassName": "${T}",
10
+ "supportsRawText": false,
11
+ "bubblingEventTypes": {},
12
+ "directEventTypes": {},
13
+ "validAttributes": {
14
+ ${indent(props.join(',\n'), ' ')}
15
+ }
16
+ }
17
+ `.trim();
18
+ return [
19
+ {
20
+ content: code,
21
+ language: 'json',
22
+ name: `${T}Config.json`,
23
+ platform: 'shared',
24
+ subdirectory: [],
25
+ },
26
+ ];
27
+ }