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,108 @@
1
+ import {} from './SourceFile.js';
2
+ import { Parameter } from './Parameter.js';
3
+ import { indent } from '../utils.js';
4
+ export class Method {
5
+ name;
6
+ returnType;
7
+ parameters;
8
+ constructor(name, returnType, parameters) {
9
+ this.name = name;
10
+ this.returnType = returnType;
11
+ this.parameters = parameters;
12
+ if (this.name.startsWith('__')) {
13
+ throw new Error(`Method names are not allowed to start with two underscores (__)! (In ${this.jsSignature})`);
14
+ }
15
+ }
16
+ get jsSignature() {
17
+ const returnType = this.returnType.kind;
18
+ const params = this.parameters.map((p) => `${p.name}: ${p.type.kind}`);
19
+ return `${this.name}(${params.join(', ')}): ${returnType}`;
20
+ }
21
+ getCode(language, modifiers, body) {
22
+ body = body?.trim();
23
+ switch (language) {
24
+ case 'c++': {
25
+ const returnType = this.returnType.getCode('c++');
26
+ const params = this.parameters.map((p) => p.getCode('c++'));
27
+ // C++ modifiers start in the beginning
28
+ const name = modifiers?.classDefinitionName
29
+ ? `${modifiers.classDefinitionName}::${this.name}`
30
+ : this.name;
31
+ let signature = `${returnType} ${name}(${params.join(', ')})`;
32
+ if (modifiers?.inline)
33
+ signature = `inline ${signature}`;
34
+ if (modifiers?.virtual)
35
+ signature = `virtual ${signature}`;
36
+ if (modifiers?.noexcept)
37
+ signature = `${signature} noexcept`;
38
+ if (modifiers?.override)
39
+ signature = `${signature} override`;
40
+ if (body == null) {
41
+ // It's a function declaration (no body)
42
+ if (modifiers?.virtual) {
43
+ // if it is a virtual function, we have no implementation (= 0)
44
+ signature = `${signature} = 0`;
45
+ }
46
+ return `${signature};`;
47
+ }
48
+ else {
49
+ return `
50
+ ${signature} {
51
+ ${indent(body, ' ')}
52
+ }`.trim();
53
+ }
54
+ }
55
+ case 'swift': {
56
+ const params = this.parameters.map((p) => p.getCode('swift'));
57
+ const returnType = this.returnType.getCode('swift');
58
+ let signature = `func ${this.name}(${params.join(', ')}) throws -> ${returnType}`;
59
+ if (modifiers?.inline)
60
+ signature = `@inline(__always)\n${signature}`;
61
+ if (body == null) {
62
+ return signature;
63
+ }
64
+ else {
65
+ return `
66
+ ${signature} {
67
+ ${indent(body, ' ')}
68
+ }`.trim();
69
+ }
70
+ }
71
+ case 'kotlin': {
72
+ const params = this.parameters.map((p) => p.getCode('kotlin'));
73
+ const returnType = this.returnType.getCode('kotlin');
74
+ let signature = `fun ${this.name}(${params.join(', ')}): ${returnType}`;
75
+ if (modifiers?.inline)
76
+ signature = `inline ${signature}`;
77
+ if (modifiers?.override)
78
+ signature = `override ${signature}`;
79
+ if (modifiers?.virtual)
80
+ signature = `abstract ${signature}`;
81
+ if (modifiers?.doNotStrip)
82
+ signature = `@DoNotStrip\n@Keep\n${signature}`;
83
+ if (body == null) {
84
+ return signature;
85
+ }
86
+ else {
87
+ return `
88
+ ${signature} {
89
+ ${indent(body, ' ')}
90
+ }
91
+ `.trim();
92
+ }
93
+ }
94
+ default:
95
+ throw new Error(`Language ${language} is not yet supported for property getters!`);
96
+ }
97
+ }
98
+ getExtraFiles() {
99
+ const returnTypeExtraFiles = this.returnType.getExtraFiles();
100
+ const paramsExtraFiles = this.parameters.flatMap((p) => p.getExtraFiles());
101
+ return [...returnTypeExtraFiles, ...paramsExtraFiles];
102
+ }
103
+ getRequiredImports(language) {
104
+ const returnTypeFiles = this.returnType.getRequiredImports(language);
105
+ const paramsImports = this.parameters.flatMap((p) => p.getRequiredImports(language));
106
+ return [...returnTypeFiles, ...paramsImports];
107
+ }
108
+ }
@@ -0,0 +1,65 @@
1
+ import { escapeCppName, toReferenceType } from './helpers.js';
2
+ import {} from './SourceFile.js';
3
+ import { NamedWrappingType } from './types/NamedWrappingType.js';
4
+ import { createNamedType } from './createType.js';
5
+ export class Parameter {
6
+ type;
7
+ constructor(...args) {
8
+ if (typeof args[0] === 'string' && typeof args[1] === 'object') {
9
+ // constructor(...) #1
10
+ if (args.length !== 2)
11
+ throw new Error(`Missing arguments for new Parameter(...) overload #1!`);
12
+ const [name, type] = args;
13
+ this.type = new NamedWrappingType(name, type);
14
+ }
15
+ else if (typeof args[0] === 'object' && typeof args[1] === 'string') {
16
+ // constructor(...) #2
17
+ const [param, language] = args;
18
+ const name = param.getSymbolOrThrow().getEscapedName();
19
+ const type = param.getType();
20
+ const isOptional = param.hasQuestionToken() || param.isOptional() || type.isNullable();
21
+ this.type = createNamedType(language, name, type, isOptional);
22
+ }
23
+ else {
24
+ // constructor(...)???
25
+ throw new Error(`Invalid constructor! Arguments: ${args}`);
26
+ }
27
+ if (this.type.name.startsWith('__')) {
28
+ throw new Error(`Parameter names are not allowed to start with two underscores (__)! (In ${this.jsSignature})`);
29
+ }
30
+ }
31
+ get jsSignature() {
32
+ return `${this.type.name}: ${this.type.kind}`;
33
+ }
34
+ get name() {
35
+ return this.type.name;
36
+ }
37
+ getCode(language) {
38
+ const name = escapeCppName(this.name);
39
+ switch (language) {
40
+ case 'c++':
41
+ let cppType = this.type.getCode('c++');
42
+ if (this.type.canBePassedByReference) {
43
+ // T -> const T&
44
+ cppType = toReferenceType(cppType);
45
+ }
46
+ return `${cppType} ${name}`;
47
+ case 'swift':
48
+ let flags = '';
49
+ if (this.type.kind === 'function') {
50
+ flags = '@escaping ';
51
+ }
52
+ return `${name}: ${flags + this.type.getCode('swift')}`;
53
+ case 'kotlin':
54
+ return `${name}: ${this.type.getCode('kotlin')}`;
55
+ default:
56
+ throw new Error(`Language ${language} is not yet supported for parameters!`);
57
+ }
58
+ }
59
+ getExtraFiles() {
60
+ return this.type.getExtraFiles();
61
+ }
62
+ getRequiredImports(language) {
63
+ return this.type.getRequiredImports(language);
64
+ }
65
+ }
@@ -0,0 +1,147 @@
1
+ import { capitalizeName } from '../utils.js';
2
+ import {} from './SourceFile.js';
3
+ import { Method } from './Method.js';
4
+ import { VoidType } from './types/VoidType.js';
5
+ import { Parameter } from './Parameter.js';
6
+ import { isBooleanPropertyPrefix } from './helpers.js';
7
+ export class Property {
8
+ name;
9
+ type;
10
+ isReadonly;
11
+ constructor(name, type, isReadonly) {
12
+ this.name = name;
13
+ this.type = type;
14
+ this.isReadonly = isReadonly;
15
+ if (this.name.startsWith('__')) {
16
+ throw new Error(`Property names are not allowed to start with two underscores (__)! (In ${this.jsSignature})`);
17
+ }
18
+ }
19
+ get jsSignature() {
20
+ return `${this.name}: ${this.type.kind}`;
21
+ }
22
+ getExtraFiles() {
23
+ return this.type.getExtraFiles();
24
+ }
25
+ getRequiredImports(language) {
26
+ return this.type.getRequiredImports(language);
27
+ }
28
+ getGetterName(environment) {
29
+ if (this.type.kind === 'boolean' && isBooleanPropertyPrefix(this.name)) {
30
+ // Boolean accessors where the property starts with "is" or "has" are renamed in JVM and Swift
31
+ switch (environment) {
32
+ case 'jvm':
33
+ case 'swift':
34
+ // isSomething -> isSomething()
35
+ return this.name;
36
+ default:
37
+ break;
38
+ }
39
+ }
40
+ // isSomething -> getIsSomething()
41
+ return `get${capitalizeName(this.name)}`;
42
+ }
43
+ getSetterName(environment) {
44
+ if (this.type.kind === 'boolean' && this.name.startsWith('is')) {
45
+ // Boolean accessors where the property starts with "is" are renamed in JVM
46
+ if (environment === 'jvm') {
47
+ // isSomething -> setSomething()
48
+ const cleanName = this.name.replace('is', '');
49
+ return `set${capitalizeName(cleanName)}`;
50
+ }
51
+ }
52
+ // isSomething -> setIsSomething()
53
+ return `set${capitalizeName(this.name)}`;
54
+ }
55
+ get cppGetter() {
56
+ return new Method(this.getGetterName('other'), this.type, []);
57
+ }
58
+ get cppSetter() {
59
+ if (this.isReadonly)
60
+ return undefined;
61
+ const parameter = new Parameter(this.name, this.type);
62
+ return new Method(this.getSetterName('other'), new VoidType(), [parameter]);
63
+ }
64
+ getCppMethods() {
65
+ if (this.cppSetter != null) {
66
+ // get + set
67
+ return [this.cppGetter, this.cppSetter];
68
+ }
69
+ else {
70
+ // get
71
+ return [this.cppGetter];
72
+ }
73
+ }
74
+ getCode(language, modifiers, body) {
75
+ if (body != null) {
76
+ body.getter = body.getter.trim();
77
+ body.setter = body.setter.trim();
78
+ }
79
+ switch (language) {
80
+ case 'c++': {
81
+ const methods = this.getCppMethods();
82
+ const [getter, setter] = methods;
83
+ const lines = [];
84
+ lines.push(getter.getCode('c++', modifiers, body?.getter));
85
+ if (setter != null) {
86
+ lines.push(setter.getCode('c++', modifiers, body?.setter));
87
+ }
88
+ return lines.join('\n');
89
+ }
90
+ case 'swift': {
91
+ const type = this.type.getCode('swift');
92
+ let accessors;
93
+ if (body == null) {
94
+ accessors = this.isReadonly ? `get` : `get set`;
95
+ }
96
+ else {
97
+ const lines = [];
98
+ lines.push(`
99
+ get {
100
+ ${body.getter}
101
+ }
102
+ `);
103
+ if (!this.isReadonly) {
104
+ lines.push(`
105
+ set {
106
+ ${body.setter}
107
+ }
108
+ `);
109
+ }
110
+ accessors = '\n' + lines.join('\n') + '\n';
111
+ }
112
+ return `var ${this.name}: ${type} { ${accessors} }`;
113
+ }
114
+ case 'kotlin': {
115
+ const type = this.type.getCode('kotlin');
116
+ let keyword = this.isReadonly ? 'val' : 'var';
117
+ if (modifiers?.virtual)
118
+ keyword = `abstract ${keyword}`;
119
+ const lines = [];
120
+ if (modifiers?.doNotStrip) {
121
+ lines.push('@get:DoNotStrip', '@get:Keep');
122
+ if (!this.isReadonly) {
123
+ lines.push('@set:DoNotStrip', '@set:Keep');
124
+ }
125
+ }
126
+ lines.push(`${keyword} ${this.name}: ${type}`);
127
+ if (body != null) {
128
+ lines.push(`
129
+ get() {
130
+ ${body.getter}
131
+ }
132
+ `);
133
+ if (!this.isReadonly) {
134
+ lines.push(`
135
+ set(value) {
136
+ ${body.setter}
137
+ }
138
+ `);
139
+ }
140
+ }
141
+ return lines.join('\n');
142
+ }
143
+ default:
144
+ throw new Error(`Language ${language} is not yet supported for properties!`);
145
+ }
146
+ }
147
+ }
@@ -0,0 +1,7 @@
1
+ export function groupByPlatform(files) {
2
+ const result = { shared: [], ios: [], android: [] };
3
+ for (const file of files) {
4
+ result[file.platform].push(file);
5
+ }
6
+ return result;
7
+ }
@@ -0,0 +1,110 @@
1
+ import { NitroConfig } from '../../config/NitroConfig.js';
2
+ import { indent, toLowerCamelCase } from '../../utils.js';
3
+ import { createFileMetadataString } from '../helpers.js';
4
+ import { includeNitroHeader } from './includeNitroHeader.js';
5
+ function getEnumMinValue(enumMembers) {
6
+ return Math.min(...enumMembers.map((m) => m.value));
7
+ }
8
+ function getEnumMaxValue(enumMembers) {
9
+ return Math.max(...enumMembers.map((m) => m.value));
10
+ }
11
+ function isIncrementingEnum(enumMembers) {
12
+ let lastValue = getEnumMinValue(enumMembers) - 1;
13
+ for (const enumMember of enumMembers) {
14
+ if (enumMember.value !== lastValue + 1) {
15
+ // it is not just one higher than the last value!
16
+ return false;
17
+ }
18
+ lastValue = enumMember.value;
19
+ }
20
+ // all enum values were incrementing!
21
+ return true;
22
+ }
23
+ /**
24
+ * Creates a C++ enum that converts to a JS enum (aka just int)
25
+ */
26
+ export function createCppEnum(typename, enumMembers) {
27
+ // Namespace typename
28
+ const fullyQualifiedTypename = NitroConfig.current.getCxxNamespace('c++', typename);
29
+ // Map enum to C++ code
30
+ const cppEnumMembers = enumMembers
31
+ .map((m) => `${m.name} SWIFT_NAME(${toLowerCamelCase(m.name)}) = ${m.value},`)
32
+ .join('\n');
33
+ const cxxNamespace = NitroConfig.current.getCxxNamespace('c++');
34
+ let isInsideValidValues;
35
+ if (isIncrementingEnum(enumMembers)) {
36
+ // It's just incrementing one after another, so we can simplify this to a bounds check
37
+ const minValue = getEnumMinValue(enumMembers);
38
+ const maxValue = getEnumMaxValue(enumMembers);
39
+ isInsideValidValues = `
40
+ // Check if we are within the bounds of the enum.
41
+ return integer >= ${minValue} && integer <= ${maxValue};
42
+ `.trim();
43
+ }
44
+ else {
45
+ const cases = enumMembers.map((m) => `case ${m.value} /* ${m.name} */: return true;`);
46
+ isInsideValidValues = `
47
+ switch (integer) {
48
+ ${indent(cases.join('\n'), ' ')}
49
+ default: return false;
50
+ }
51
+ `.trim();
52
+ }
53
+ // Create entire C++ file
54
+ const cppCode = `
55
+ ${createFileMetadataString(`${typename}.hpp`)}
56
+
57
+ #pragma once
58
+
59
+ ${includeNitroHeader('JSIConverter.hpp')}
60
+ ${includeNitroHeader('NitroDefines.hpp')}
61
+
62
+ namespace ${cxxNamespace} {
63
+
64
+ /**
65
+ * An enum which can be represented as a JavaScript enum (${typename}).
66
+ */
67
+ enum class ${typename} {
68
+ ${indent(cppEnumMembers, ' ')}
69
+ } CLOSED_ENUM;
70
+
71
+ } // namespace ${cxxNamespace}
72
+
73
+ namespace margelo::nitro {
74
+
75
+ // C++ ${typename} <> JS ${typename} (enum)
76
+ template <>
77
+ struct JSIConverter<${fullyQualifiedTypename}> final {
78
+ static inline ${fullyQualifiedTypename} fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
79
+ int enumValue = JSIConverter<int>::fromJSI(runtime, arg);
80
+ return static_cast<${fullyQualifiedTypename}>(enumValue);
81
+ }
82
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, ${fullyQualifiedTypename} arg) {
83
+ int enumValue = static_cast<int>(arg);
84
+ return JSIConverter<int>::toJSI(runtime, enumValue);
85
+ }
86
+ static inline bool canConvert(jsi::Runtime&, const jsi::Value& value) {
87
+ if (!value.isNumber()) {
88
+ return false;
89
+ }
90
+ double number = value.getNumber();
91
+ int integer = static_cast<int>(number);
92
+ if (number != integer) {
93
+ // The integer is not the same value as the double - we truncated floating points.
94
+ // Enums are all integers, so the input floating point number is obviously invalid.
95
+ return false;
96
+ }
97
+ ${indent(isInsideValidValues, ' ')}
98
+ }
99
+ };
100
+
101
+ } // namespace margelo::nitro
102
+ `;
103
+ return {
104
+ content: cppCode,
105
+ subdirectory: [],
106
+ name: `${typename}.hpp`,
107
+ language: 'c++',
108
+ platform: 'shared',
109
+ };
110
+ }
@@ -0,0 +1,146 @@
1
+ import { createFileMetadataString, isNotDuplicate } from '../helpers.js';
2
+ import { indent } from '../../utils.js';
3
+ import { includeHeader, includeNitroHeader } from './includeNitroHeader.js';
4
+ import { getHybridObjectName } from '../getHybridObjectName.js';
5
+ import { HybridObjectType } from '../types/HybridObjectType.js';
6
+ export function createCppHybridObject(spec) {
7
+ // Extra includes
8
+ const extraFiles = [
9
+ ...spec.properties.flatMap((p) => p.getExtraFiles()),
10
+ ...spec.methods.flatMap((m) => m.getExtraFiles()),
11
+ ];
12
+ const extraIncludes = [
13
+ ...spec.properties.flatMap((p) => p.getRequiredImports('c++')),
14
+ ...spec.methods.flatMap((m) => m.getRequiredImports('c++')),
15
+ ...spec.baseTypes.flatMap((b) => new HybridObjectType(b).getRequiredImports('c++')),
16
+ ];
17
+ const cppForwardDeclarations = extraIncludes
18
+ .map((i) => i.forwardDeclaration)
19
+ .filter((v) => v != null)
20
+ .filter(isNotDuplicate);
21
+ const cppExtraIncludes = extraIncludes
22
+ .map((i) => includeHeader(i))
23
+ .filter(isNotDuplicate);
24
+ const cxxNamespace = spec.config.getCxxNamespace('c++');
25
+ const name = getHybridObjectName(spec.name);
26
+ const bases = ['public virtual HybridObject'];
27
+ for (const base of spec.baseTypes) {
28
+ const baseName = getHybridObjectName(base.name).HybridTSpec;
29
+ const fullName = base.config.isExternalConfig
30
+ ? base.config.getCxxNamespace('c++', baseName)
31
+ : baseName;
32
+ bases.push(`public virtual ${fullName}`);
33
+ }
34
+ // Generate the full header / code
35
+ const cppHeaderCode = `
36
+ ${createFileMetadataString(`${name.HybridTSpec}.hpp`)}
37
+
38
+ #pragma once
39
+
40
+ ${includeNitroHeader('HybridObject.hpp')}
41
+
42
+ ${cppForwardDeclarations.join('\n')}
43
+
44
+ ${cppExtraIncludes.join('\n')}
45
+
46
+ namespace ${cxxNamespace} {
47
+
48
+ using namespace margelo::nitro;
49
+
50
+ /**
51
+ * An abstract base class for \`${spec.name}\`
52
+ * Inherit this class to create instances of \`${name.HybridTSpec}\` in C++.
53
+ * You must explicitly call \`HybridObject\`'s constructor yourself, because it is virtual.
54
+ * @example
55
+ * \`\`\`cpp
56
+ * class ${name.HybridT}: public ${name.HybridTSpec} {
57
+ * public:
58
+ * ${name.HybridT}(...): HybridObject(TAG) { ... }
59
+ * // ...
60
+ * };
61
+ * \`\`\`
62
+ */
63
+ class ${name.HybridTSpec}: ${bases.join(', ')} {
64
+ public:
65
+ // Constructor
66
+ explicit ${name.HybridTSpec}(): HybridObject(TAG) { }
67
+
68
+ // Destructor
69
+ ~${name.HybridTSpec}() override = default;
70
+
71
+ public:
72
+ // Properties
73
+ ${indent(spec.properties.map((p) => p.getCode('c++', { virtual: true })).join('\n'), ' ')}
74
+
75
+ public:
76
+ // Methods
77
+ ${indent(spec.methods.map((m) => m.getCode('c++', { virtual: true })).join('\n'), ' ')}
78
+
79
+ protected:
80
+ // Hybrid Setup
81
+ void loadHybridMethods() override;
82
+
83
+ protected:
84
+ // Tag for logging
85
+ static constexpr auto TAG = "${spec.name}";
86
+ };
87
+
88
+ } // namespace ${cxxNamespace}
89
+ `;
90
+ // Each C++ method needs to be registered in the HybridObject - that's getters, setters and normal methods.
91
+ const registrations = [];
92
+ for (const property of spec.properties) {
93
+ const getterMethod = property.getGetterName('other');
94
+ const setterMethod = property.getSetterName('other');
95
+ // getter
96
+ registrations.push(`prototype.registerHybridGetter("${property.name}", &${name.HybridTSpec}::${getterMethod});`);
97
+ if (!property.isReadonly) {
98
+ // setter
99
+ registrations.push(`prototype.registerHybridSetter("${property.name}", &${name.HybridTSpec}::${setterMethod});`);
100
+ }
101
+ }
102
+ for (const method of spec.methods) {
103
+ // method
104
+ registrations.push(`prototype.registerHybridMethod("${method.name}", &${name.HybridTSpec}::${method.name});`);
105
+ }
106
+ const basePrototypeRegistrations = ['HybridObject::loadHybridMethods();'];
107
+ for (const base of spec.baseTypes) {
108
+ const hybridObjectName = getHybridObjectName(base.name);
109
+ basePrototypeRegistrations.push(`${hybridObjectName.HybridTSpec}::loadHybridMethods();`);
110
+ }
111
+ const cppBodyCode = `
112
+ ${createFileMetadataString(`${name.HybridTSpec}.cpp`)}
113
+
114
+ #include "${name.HybridTSpec}.hpp"
115
+
116
+ namespace ${cxxNamespace} {
117
+
118
+ void ${name.HybridTSpec}::loadHybridMethods() {
119
+ // load base methods/properties
120
+ ${indent(basePrototypeRegistrations.join('\n'), ' ')}
121
+ // load custom methods/properties
122
+ registerHybrids(this, [](Prototype& prototype) {
123
+ ${indent(registrations.join('\n'), ' ')}
124
+ });
125
+ }
126
+
127
+ } // namespace ${cxxNamespace}
128
+ `;
129
+ const files = [];
130
+ files.push({
131
+ content: cppHeaderCode,
132
+ name: `${name.HybridTSpec}.hpp`,
133
+ subdirectory: [],
134
+ language: 'c++',
135
+ platform: 'shared',
136
+ });
137
+ files.push({
138
+ content: cppBodyCode,
139
+ name: `${name.HybridTSpec}.cpp`,
140
+ subdirectory: [],
141
+ language: 'c++',
142
+ platform: 'shared',
143
+ });
144
+ files.push(...extraFiles);
145
+ return files;
146
+ }
@@ -0,0 +1,18 @@
1
+ export function createCppHybridObjectRegistration({ hybridObjectName, cppClassName, }) {
2
+ return {
3
+ requiredImports: [
4
+ { name: `${cppClassName}.hpp`, language: 'c++', space: 'user' },
5
+ ],
6
+ cppCode: `
7
+ HybridObjectRegistry::registerHybridObjectConstructor(
8
+ "${hybridObjectName}",
9
+ []() -> std::shared_ptr<HybridObject> {
10
+ static_assert(std::is_default_constructible_v<${cppClassName}>,
11
+ "The HybridObject \\"${cppClassName}\\" is not default-constructible! "
12
+ "Create a public constructor that takes zero arguments to be able to autolink this HybridObject.");
13
+ return std::make_shared<${cppClassName}>();
14
+ }
15
+ );
16
+ `.trim(),
17
+ };
18
+ }