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,246 @@
1
+ import { Project } from 'ts-morph'
2
+ import {
3
+ extendsHybridObject,
4
+ isHybridView,
5
+ getHybridObjectPlatforms,
6
+ getHybridViewPlatforms,
7
+ type Platform,
8
+ } from './getPlatformSpecs.js'
9
+ import { generatePlatformFiles } from './createPlatformSpec.js'
10
+ import path from 'path'
11
+ import { prettifyDirectory } from './prettifyDirectory.js'
12
+ import {
13
+ capitalizeName,
14
+ deduplicateFiles,
15
+ errorToString,
16
+ indent,
17
+ NITROGEN_VERSION,
18
+ } from './utils.js'
19
+ import { writeFile } from './writeFile.js'
20
+ import chalk from 'chalk'
21
+ import { groupByPlatform, type SourceFile } from './syntax/SourceFile.js'
22
+ import { Logger } from './Logger.js'
23
+ import { NitroConfig } from './config/NitroConfig.js'
24
+ import { createIOSAutolinking } from './autolinking/createIOSAutolinking.js'
25
+ import { createAndroidAutolinking } from './autolinking/createAndroidAutolinking.js'
26
+ import type { Autolinking } from './autolinking/Autolinking.js'
27
+ import { createGitAttributes } from './createGitAttributes.js'
28
+ import type { PlatformSpec } from 'react-native-nitro-modules'
29
+
30
+ interface NitrogenOptions {
31
+ baseDirectory: string
32
+ outputDirectory: string
33
+ }
34
+
35
+ interface NitrogenResult {
36
+ generatedFiles: string[]
37
+ targetSpecsCount: number
38
+ generatedSpecsCount: number
39
+ }
40
+
41
+ export async function runNitrogen({
42
+ baseDirectory,
43
+ outputDirectory,
44
+ }: NitrogenOptions): Promise<NitrogenResult> {
45
+ let targetSpecs = 0
46
+ let generatedSpecs = 0
47
+
48
+ // Create the TS project
49
+ const project = new Project({
50
+ compilerOptions: {
51
+ strict: true,
52
+ strictNullChecks: true,
53
+ noUncheckedIndexedAccess: true,
54
+ },
55
+ })
56
+
57
+ const ignorePaths = NitroConfig.current.getIgnorePaths()
58
+ const globPattern = [path.join(baseDirectory, '**', '*.nitro.ts')]
59
+ ignorePaths.forEach((ignorePath) => {
60
+ globPattern.push('!' + path.join(baseDirectory, ignorePath))
61
+ })
62
+ project.addSourceFilesAtPaths(globPattern)
63
+
64
+ // Loop through all source files to log them
65
+ Logger.info(
66
+ chalk.reset(
67
+ `🚀 Nitrogen ${chalk.bold(NITROGEN_VERSION)} runs at ${chalk.underline(prettifyDirectory(baseDirectory))}`
68
+ )
69
+ )
70
+ for (const dir of project.getDirectories()) {
71
+ const specs = dir.getSourceFiles().length
72
+ const relativePath = prettifyDirectory(dir.getPath())
73
+ Logger.info(
74
+ ` 🔍 Nitrogen found ${specs} spec${specs === 1 ? '' : 's'} in ${chalk.underline(relativePath)}`
75
+ )
76
+ }
77
+
78
+ // If no source files are found, we can exit
79
+ if (project.getSourceFiles().length === 0) {
80
+ const searchDir = prettifyDirectory(
81
+ path.join(path.resolve(baseDirectory), '**', '*.nitro.ts')
82
+ )
83
+ Logger.error(
84
+ `❌ Nitrogen didn't find any spec files in ${chalk.underline(searchDir)}! ` +
85
+ `To create a Nitro Module, create a TypeScript file with the "${chalk.underline('.nitro.ts')}" suffix ` +
86
+ 'and export an interface that extends HybridObject<T>.'
87
+ )
88
+ process.exit()
89
+ }
90
+
91
+ const usedPlatforms: Platform[] = []
92
+ const filesAfter: string[] = []
93
+ const writtenFiles: SourceFile[] = []
94
+
95
+ for (const sourceFile of project.getSourceFiles()) {
96
+ Logger.info(`⏳ Parsing ${sourceFile.getBaseName()}...`)
97
+
98
+ const startedWithSpecs = generatedSpecs
99
+
100
+ // Find all interfaceDeclarations in the given file
101
+ const declarations = [
102
+ ...sourceFile.getInterfaces(),
103
+ ...sourceFile.getTypeAliases(),
104
+ ]
105
+ for (const declaration of declarations) {
106
+ let typeName = declaration.getName()
107
+ try {
108
+ let platformSpec: PlatformSpec
109
+ if (isHybridView(declaration.getType())) {
110
+ // Hybrid View Props
111
+ const targetPlatforms = getHybridViewPlatforms(declaration)
112
+ if (targetPlatforms == null) {
113
+ // It does not extend HybridView, continue..
114
+ continue
115
+ }
116
+ platformSpec = targetPlatforms
117
+ } else if (extendsHybridObject(declaration.getType(), true)) {
118
+ // Hybrid View
119
+ const targetPlatforms = getHybridObjectPlatforms(declaration)
120
+ if (targetPlatforms == null) {
121
+ // It does not extend HybridObject, continue..
122
+ continue
123
+ }
124
+ platformSpec = targetPlatforms
125
+ } else {
126
+ continue
127
+ }
128
+
129
+ const platforms = Object.keys(platformSpec) as Platform[]
130
+
131
+ if (platforms.length === 0) {
132
+ Logger.warn(
133
+ `⚠️ ${typeName} does not declare any platforms in HybridObject<T> - nothing can be generated.`
134
+ )
135
+ continue
136
+ }
137
+
138
+ targetSpecs++
139
+
140
+ Logger.info(
141
+ ` ⚙️ Generating specs for HybridObject "${chalk.bold(typeName)}"...`
142
+ )
143
+
144
+ // Create all files and throw it into a big list
145
+ let allFiles = platforms.flatMap((p) => {
146
+ usedPlatforms.push(p)
147
+ const language = platformSpec[p]!
148
+ const r = generatePlatformFiles(declaration.getType(), language)
149
+ return r
150
+ })
151
+ allFiles = deduplicateFiles(allFiles)
152
+ // Group the files by platform ({ ios: [], android: [], shared: [] })
153
+ const filesPerPlatform = groupByPlatform(allFiles)
154
+ // Loop through each platform one by one so that it has some kind of order (per-platform)
155
+ for (const [p, files] of Object.entries(filesPerPlatform)) {
156
+ const platform = p as SourceFile['platform']
157
+ const language =
158
+ platform === 'shared' ? 'c++' : platformSpec[platform]
159
+ if (language == null) {
160
+ // if the language was never specified in the spec, skip it
161
+ continue
162
+ }
163
+ if (files.length === 0) {
164
+ // if no files exist on this platform, skip it
165
+ continue
166
+ }
167
+
168
+ Logger.info(
169
+ ` ${chalk.dim(platform)}: Generating ${capitalizeName(language)} code...`
170
+ )
171
+ // Write the actual files for this specific platform.
172
+ for (const file of files) {
173
+ const basePath = path.join(
174
+ outputDirectory,
175
+ file.platform,
176
+ file.language
177
+ )
178
+ const actualPath = await writeFile(basePath, file)
179
+ filesAfter.push(actualPath)
180
+ writtenFiles.push(file)
181
+ }
182
+ }
183
+
184
+ // Done!
185
+ generatedSpecs++
186
+ } catch (error) {
187
+ const message = indent(errorToString(error), ' ')
188
+ Logger.error(
189
+ chalk.redBright(
190
+ ` ❌ Failed to generate spec for ${typeName}! ${message}`
191
+ )
192
+ )
193
+ process.exitCode = 1
194
+ }
195
+ }
196
+
197
+ if (generatedSpecs === startedWithSpecs) {
198
+ Logger.error(
199
+ chalk.redBright(
200
+ ` ❌ No specs found in ${sourceFile.getBaseName()}!`
201
+ )
202
+ )
203
+ }
204
+ }
205
+
206
+ // Autolinking
207
+ Logger.info(`⛓️ Setting up build configs for autolinking...`)
208
+
209
+ const autolinkingFiles: Autolinking[] = []
210
+
211
+ if (usedPlatforms.includes('ios')) {
212
+ autolinkingFiles.push(createIOSAutolinking())
213
+ }
214
+ if (usedPlatforms.includes('android')) {
215
+ autolinkingFiles.push(createAndroidAutolinking(writtenFiles))
216
+ }
217
+
218
+ for (const autolinking of autolinkingFiles) {
219
+ Logger.info(
220
+ ` Creating autolinking build setup for ${chalk.dim(autolinking.platform)}...`
221
+ )
222
+ for (const file of autolinking.sourceFiles) {
223
+ const basePath = path.join(outputDirectory, file.platform)
224
+ const actualPath = await writeFile(
225
+ basePath,
226
+ file as unknown as SourceFile
227
+ )
228
+ filesAfter.push(actualPath)
229
+ }
230
+ }
231
+
232
+ try {
233
+ // write a .gitattributes file
234
+ const markAsGenerated = NitroConfig.current.getGitAttributesGeneratedFlag()
235
+ const file = await createGitAttributes(markAsGenerated, outputDirectory)
236
+ filesAfter.push(file)
237
+ } catch {
238
+ Logger.error(`❌ Failed to write ${chalk.dim(`.gitattributes`)}!`)
239
+ }
240
+
241
+ return {
242
+ generatedFiles: filesAfter,
243
+ targetSpecsCount: targetSpecs,
244
+ generatedSpecsCount: generatedSpecs,
245
+ }
246
+ }
@@ -0,0 +1,32 @@
1
+ import os from 'os'
2
+ import path from 'path'
3
+
4
+ export function prettifyDirectory(directory: string): string {
5
+ let relativePath = path.relative(process.cwd(), path.resolve(directory))
6
+ if (!relativePath.startsWith('.') && relativePath.length > 0) {
7
+ // Make sure all relative paths start with "./something", not just "something"
8
+ relativePath = `./${relativePath}`
9
+ }
10
+
11
+ const home = os.homedir()
12
+ const homeShorthand = os.platform() === 'win32' ? '$HOME' : '~'
13
+ const prettifiedHomeShorthand = directory.startsWith(home)
14
+ ? `${homeShorthand}${directory.slice(home.length)}`
15
+ : directory
16
+
17
+ if (relativePath.length < 1) {
18
+ // If relativePath is ".", we don't want to return it
19
+ return prettifiedHomeShorthand
20
+ }
21
+
22
+ if (
23
+ relativePath.length > 0 &&
24
+ relativePath.length < prettifiedHomeShorthand.length
25
+ ) {
26
+ // If relativePath is shroter than the ~/... home path, we use the relative one.
27
+ return relativePath
28
+ } else {
29
+ // ..otherwise just use the ~/... home relative path.
30
+ return prettifiedHomeShorthand
31
+ }
32
+ }
@@ -0,0 +1,59 @@
1
+ import type { Language } from '../getPlatformSpecs.js'
2
+ import type { SourceFile, SourceImport } from './SourceFile.js'
3
+ import type { Type } from './types/Type.js'
4
+
5
+ export interface BridgedType<
6
+ FromLanguage extends Language,
7
+ ToLanguage extends Language,
8
+ > {
9
+ /**
10
+ * The underlying type that is being bridged between {@linkcode FromLanguage} and {@linkcode ToLanguage}
11
+ */
12
+ readonly type: Type
13
+ /**
14
+ * Whether the underlying type has a valid type (is not void or null)
15
+ */
16
+ readonly hasType: boolean
17
+ /**
18
+ * Whether this type can be passed by reference
19
+ */
20
+ readonly canBePassedByReference: boolean
21
+ /**
22
+ * Whether this bridged type needs special handling, or can just be used as-is
23
+ */
24
+ readonly needsSpecialHandling: boolean
25
+
26
+ /**
27
+ * Get all imports required for this bridge to work
28
+ */
29
+ getRequiredImports(language: Language): SourceImport[]
30
+
31
+ /**
32
+ * Get all extra files that need to be created for this type, as well as the bridge.
33
+ */
34
+ getExtraFiles(): SourceFile[]
35
+
36
+ /**
37
+ * Get the code for the type itself in the given language
38
+ */
39
+ getTypeCode(language: FromLanguage | ToLanguage): string
40
+
41
+ /**
42
+ * Parse the given parameter from the source language to the given target language, in the given language.
43
+ * For example, to convert an ArrayBuffer from Swift ({@linkcode from}) to C++ ({@linkcode to}) we
44
+ * have to wrap it in an ArrayBufferHolder in Swift ({@linkcode inLanguage}), and unwrap
45
+ * it from the ArrayBufferHolder again in C++ ({@linkcode inLanguage})
46
+ */
47
+ parse(
48
+ parameterName: string,
49
+ from: FromLanguage,
50
+ to: ToLanguage,
51
+ inLanguage: FromLanguage | ToLanguage
52
+ ): string
53
+ parse(
54
+ parameterName: string,
55
+ from: ToLanguage,
56
+ to: FromLanguage,
57
+ inLanguage: FromLanguage | ToLanguage
58
+ ): string
59
+ }
@@ -0,0 +1,24 @@
1
+ import type { Language } from '../getPlatformSpecs.js'
2
+ import type { SourceFile, SourceImport } from './SourceFile.js'
3
+
4
+ export interface CodeNode {
5
+ /**
6
+ * Get the code of this code node (e.g. property, method) in the given language.
7
+ */
8
+ getCode(language: Language): string
9
+ /**
10
+ * Get all extra definition files this code node needs (e.g. extra type/struct declarations
11
+ * for complex types), or `[]` if none are required (e.g. if this uses primitive types only)
12
+ *
13
+ * All files returned here must be created in the project.
14
+ * To include them, see {@linkcode getRequiredImports | getRequiredImports()}
15
+ */
16
+ getExtraFiles(): SourceFile[]
17
+ /**
18
+ * Get all required imports this code node needs (e.g. extra type/struct declarations for complex types),
19
+ * or `[]` if no imports are required (e.g. if this uses primitive types only).
20
+ *
21
+ * All imports returned here must be included in the current file (e.g. `#include "..."` or `import ...`)
22
+ */
23
+ getRequiredImports(language: Language): SourceImport[]
24
+ }
@@ -0,0 +1,14 @@
1
+ import type { NitroConfig } from '../config/NitroConfig.js'
2
+ import type { Language } from '../getPlatformSpecs.js'
3
+ import type { Method } from './Method.js'
4
+ import type { Property } from './Property.js'
5
+
6
+ export interface HybridObjectSpec {
7
+ name: string
8
+ language: Language
9
+ properties: Property[]
10
+ methods: Method[]
11
+ baseTypes: HybridObjectSpec[]
12
+ isHybridView: boolean
13
+ config: NitroConfig
14
+ }
@@ -0,0 +1,154 @@
1
+ import type { CodeNode } from './CodeNode.js'
2
+ import type { Language } from '../getPlatformSpecs.js'
3
+ import { type SourceFile, type SourceImport } from './SourceFile.js'
4
+ import { Parameter } from './Parameter.js'
5
+ import type { Type } from './types/Type.js'
6
+ import { indent } from '../utils.js'
7
+
8
+ export type MethodBody = string
9
+
10
+ export interface MethodModifiers {
11
+ /**
12
+ * The name of the class that defines this C++ method.
13
+ * Example: `Person` -> `void Person::sayHi()`
14
+ */
15
+ classDefinitionName?: string
16
+ /**
17
+ * Whether the function should be marked as inlineable.
18
+ */
19
+ inline?: boolean
20
+ /*+
21
+ * Whether the func is a pure virtual C++ function.
22
+ */
23
+ virtual?: boolean
24
+ /**
25
+ * Whether the function is marked as `noexcept` (doesn't throw) or not.
26
+ */
27
+ noexcept?: boolean
28
+ /**
29
+ * Whether this function overrides a base/super function.
30
+ */
31
+ override?: boolean
32
+ /**
33
+ * Whether this method has a `@DoNotStrip` and `@Keep` attribute to avoid
34
+ * it from being stripped from the binary by the Java compiler or ProGuard.
35
+ */
36
+ doNotStrip?: boolean
37
+ }
38
+
39
+ export class Method implements CodeNode {
40
+ readonly name: string
41
+ readonly returnType: Type
42
+ readonly parameters: Parameter[]
43
+
44
+ constructor(name: string, returnType: Type, parameters: Parameter[]) {
45
+ this.name = name
46
+ this.returnType = returnType
47
+ this.parameters = parameters
48
+ if (this.name.startsWith('__')) {
49
+ throw new Error(
50
+ `Method names are not allowed to start with two underscores (__)! (In ${this.jsSignature})`
51
+ )
52
+ }
53
+ }
54
+
55
+ get jsSignature(): string {
56
+ const returnType = this.returnType.kind
57
+ const params = this.parameters.map((p) => `${p.name}: ${p.type.kind}`)
58
+ return `${this.name}(${params.join(', ')}): ${returnType}`
59
+ }
60
+
61
+ getCode(
62
+ language: Language,
63
+ modifiers?: MethodModifiers,
64
+ body?: MethodBody
65
+ ): string {
66
+ body = body?.trim()
67
+
68
+ switch (language) {
69
+ case 'c++': {
70
+ const returnType = this.returnType.getCode('c++')
71
+ const params = this.parameters.map((p) => p.getCode('c++'))
72
+
73
+ // C++ modifiers start in the beginning
74
+ const name = modifiers?.classDefinitionName
75
+ ? `${modifiers.classDefinitionName}::${this.name}`
76
+ : this.name
77
+ let signature = `${returnType} ${name}(${params.join(', ')})`
78
+ if (modifiers?.inline) signature = `inline ${signature}`
79
+ if (modifiers?.virtual) signature = `virtual ${signature}`
80
+ if (modifiers?.noexcept) signature = `${signature} noexcept`
81
+ if (modifiers?.override) signature = `${signature} override`
82
+
83
+ if (body == null) {
84
+ // It's a function declaration (no body)
85
+ if (modifiers?.virtual) {
86
+ // if it is a virtual function, we have no implementation (= 0)
87
+ signature = `${signature} = 0`
88
+ }
89
+ return `${signature};`
90
+ } else {
91
+ return `
92
+ ${signature} {
93
+ ${indent(body, ' ')}
94
+ }`.trim()
95
+ }
96
+ }
97
+ case 'swift': {
98
+ const params = this.parameters.map((p) => p.getCode('swift'))
99
+ const returnType = this.returnType.getCode('swift')
100
+ let signature = `func ${this.name}(${params.join(', ')}) throws -> ${returnType}`
101
+
102
+ if (modifiers?.inline) signature = `@inline(__always)\n${signature}`
103
+
104
+ if (body == null) {
105
+ return signature
106
+ } else {
107
+ return `
108
+ ${signature} {
109
+ ${indent(body, ' ')}
110
+ }`.trim()
111
+ }
112
+ }
113
+ case 'kotlin': {
114
+ const params = this.parameters.map((p) => p.getCode('kotlin'))
115
+ const returnType = this.returnType.getCode('kotlin')
116
+ let signature = `fun ${this.name}(${params.join(', ')}): ${returnType}`
117
+
118
+ if (modifiers?.inline) signature = `inline ${signature}`
119
+ if (modifiers?.override) signature = `override ${signature}`
120
+ if (modifiers?.virtual) signature = `abstract ${signature}`
121
+ if (modifiers?.doNotStrip)
122
+ signature = `@DoNotStrip\n@Keep\n${signature}`
123
+
124
+ if (body == null) {
125
+ return signature
126
+ } else {
127
+ return `
128
+ ${signature} {
129
+ ${indent(body, ' ')}
130
+ }
131
+ `.trim()
132
+ }
133
+ }
134
+ default:
135
+ throw new Error(
136
+ `Language ${language} is not yet supported for property getters!`
137
+ )
138
+ }
139
+ }
140
+
141
+ getExtraFiles(): SourceFile[] {
142
+ const returnTypeExtraFiles = this.returnType.getExtraFiles()
143
+ const paramsExtraFiles = this.parameters.flatMap((p) => p.getExtraFiles())
144
+ return [...returnTypeExtraFiles, ...paramsExtraFiles]
145
+ }
146
+
147
+ getRequiredImports(language: Language): SourceImport[] {
148
+ const returnTypeFiles = this.returnType.getRequiredImports(language)
149
+ const paramsImports = this.parameters.flatMap((p) =>
150
+ p.getRequiredImports(language)
151
+ )
152
+ return [...returnTypeFiles, ...paramsImports]
153
+ }
154
+ }
@@ -0,0 +1,81 @@
1
+ import type { ParameterDeclaration } from 'ts-morph'
2
+ import type { CodeNode } from './CodeNode.js'
3
+ import { escapeCppName, toReferenceType } from './helpers.js'
4
+ import type { Language } from '../getPlatformSpecs.js'
5
+ import { type SourceFile, type SourceImport } from './SourceFile.js'
6
+ import type { NamedType, Type } from './types/Type.js'
7
+ import { NamedWrappingType } from './types/NamedWrappingType.js'
8
+ import { createNamedType } from './createType.js'
9
+
10
+ export class Parameter implements CodeNode {
11
+ readonly type: NamedType
12
+
13
+ constructor(name: string, type: Type)
14
+ constructor(parameter: ParameterDeclaration, language: Language)
15
+ constructor(...args: [string, Type] | [ParameterDeclaration, Language]) {
16
+ if (typeof args[0] === 'string' && typeof args[1] === 'object') {
17
+ // constructor(...) #1
18
+ if (args.length !== 2)
19
+ throw new Error(`Missing arguments for new Parameter(...) overload #1!`)
20
+ const [name, type] = args
21
+ this.type = new NamedWrappingType(name, type)
22
+ } else if (typeof args[0] === 'object' && typeof args[1] === 'string') {
23
+ // constructor(...) #2
24
+ const [param, language] = args
25
+ const name = param.getSymbolOrThrow().getEscapedName()
26
+ const type = param.getType()
27
+ const isOptional =
28
+ param.hasQuestionToken() || param.isOptional() || type.isNullable()
29
+ this.type = createNamedType(language, name, type, isOptional)
30
+ } else {
31
+ // constructor(...)???
32
+ throw new Error(`Invalid constructor! Arguments: ${args}`)
33
+ }
34
+ if (this.type.name.startsWith('__')) {
35
+ throw new Error(
36
+ `Parameter names are not allowed to start with two underscores (__)! (In ${this.jsSignature})`
37
+ )
38
+ }
39
+ }
40
+
41
+ get jsSignature(): string {
42
+ return `${this.type.name}: ${this.type.kind}`
43
+ }
44
+
45
+ get name(): string {
46
+ return this.type.name
47
+ }
48
+
49
+ getCode(language: Language): string {
50
+ const name = escapeCppName(this.name)
51
+ switch (language) {
52
+ case 'c++':
53
+ let cppType = this.type.getCode('c++')
54
+ if (this.type.canBePassedByReference) {
55
+ // T -> const T&
56
+ cppType = toReferenceType(cppType)
57
+ }
58
+ return `${cppType} ${name}`
59
+ case 'swift':
60
+ let flags = ''
61
+ if (this.type.kind === 'function') {
62
+ flags = '@escaping '
63
+ }
64
+ return `${name}: ${flags + this.type.getCode('swift')}`
65
+ case 'kotlin':
66
+ return `${name}: ${this.type.getCode('kotlin')}`
67
+ default:
68
+ throw new Error(
69
+ `Language ${language} is not yet supported for parameters!`
70
+ )
71
+ }
72
+ }
73
+
74
+ getExtraFiles(): SourceFile[] {
75
+ return this.type.getExtraFiles()
76
+ }
77
+
78
+ getRequiredImports(language: Language): SourceImport[] {
79
+ return this.type.getRequiredImports(language)
80
+ }
81
+ }