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.
- package/README.md +18 -108
- package/lib/Logger.js +56 -0
- package/lib/autolinking/Autolinking.js +1 -0
- package/lib/autolinking/android/createCMakeExtension.js +109 -0
- package/lib/autolinking/android/createGradleExtension.js +36 -0
- package/lib/autolinking/android/createHybridObjectInitializer.js +159 -0
- package/lib/autolinking/createAndroidAutolinking.js +13 -0
- package/lib/autolinking/createIOSAutolinking.js +19 -0
- package/lib/autolinking/ios/createHybridObjectInitializer.js +97 -0
- package/lib/autolinking/ios/createPodspecRubyExtension.js +69 -0
- package/lib/autolinking/ios/createSwiftCxxBridge.js +117 -0
- package/lib/autolinking/ios/createSwiftUmbrellaHeader.js +74 -0
- package/lib/config/NitroConfig.js +112 -0
- package/lib/config/NitroUserConfig.js +88 -0
- package/lib/config/getConfig.js +84 -0
- package/lib/createGitAttributes.js +11 -0
- package/lib/createPlatformSpec.js +127 -0
- package/lib/getFiles.js +28 -0
- package/lib/getPlatformSpecs.js +153 -0
- package/lib/index.js +113 -10
- package/lib/init.js +123 -0
- package/lib/nitrogen.js +165 -0
- package/lib/prettifyDirectory.js +27 -0
- package/lib/syntax/BridgedType.js +1 -0
- package/lib/syntax/CodeNode.js +1 -0
- package/lib/syntax/HybridObjectSpec.js +1 -0
- package/lib/syntax/Method.js +108 -0
- package/lib/syntax/Parameter.js +65 -0
- package/lib/syntax/Property.js +147 -0
- package/lib/syntax/SourceFile.js +7 -0
- package/lib/syntax/c++/CppEnum.js +110 -0
- package/lib/syntax/c++/CppHybridObject.js +146 -0
- package/lib/syntax/c++/CppHybridObjectRegistration.js +18 -0
- package/lib/syntax/c++/CppStruct.js +108 -0
- package/lib/syntax/c++/CppUnion.js +88 -0
- package/lib/syntax/c++/getForwardDeclaration.js +14 -0
- package/lib/syntax/c++/includeNitroHeader.js +34 -0
- package/lib/syntax/createType.js +303 -0
- package/lib/syntax/getAllTypes.js +11 -0
- package/lib/syntax/getCustomTypeConfig.js +53 -0
- package/lib/syntax/getHybridObjectName.d.ts +36 -0
- package/lib/syntax/getHybridObjectName.js +10 -0
- package/lib/syntax/getInterfaceProperties.js +9 -0
- package/lib/syntax/getReferencedTypes.js +47 -0
- package/lib/syntax/helpers.js +53 -0
- package/lib/syntax/isCoreType.js +47 -0
- package/lib/syntax/kotlin/FbjniHybridObject.js +261 -0
- package/lib/syntax/kotlin/JNINativeRegistrations.js +7 -0
- package/lib/syntax/kotlin/KotlinBoxedPrimitive.js +17 -0
- package/lib/syntax/kotlin/KotlinCxxBridgedType.js +893 -0
- package/lib/syntax/kotlin/KotlinEnum.js +113 -0
- package/lib/syntax/kotlin/KotlinFunction.js +256 -0
- package/lib/syntax/kotlin/KotlinHybridObject.js +177 -0
- package/lib/syntax/kotlin/KotlinHybridObjectRegistration.js +26 -0
- package/lib/syntax/kotlin/KotlinStruct.js +172 -0
- package/lib/syntax/kotlin/KotlinVariant.js +191 -0
- package/lib/syntax/swift/SwiftCxxBridgedType.js +819 -0
- package/lib/syntax/swift/SwiftCxxTypeHelper.js +613 -0
- package/lib/syntax/swift/SwiftEnum.js +52 -0
- package/lib/syntax/swift/SwiftFunction.js +83 -0
- package/lib/syntax/swift/SwiftHybridObject.js +103 -0
- package/lib/syntax/swift/SwiftHybridObjectBridge.js +451 -0
- package/lib/syntax/swift/SwiftHybridObjectRegistration.js +42 -0
- package/lib/syntax/swift/SwiftStruct.js +75 -0
- package/lib/syntax/swift/SwiftVariant.js +58 -0
- package/lib/syntax/types/ArrayBufferType.js +37 -0
- package/lib/syntax/types/ArrayType.d.ts +12 -0
- package/lib/syntax/types/ArrayType.js +52 -0
- package/lib/syntax/types/BigIntType.js +27 -0
- package/lib/syntax/types/BooleanType.js +27 -0
- package/lib/syntax/types/CustomType.d.ts +14 -0
- package/lib/syntax/types/CustomType.js +36 -0
- package/lib/syntax/types/DateType.js +35 -0
- package/lib/syntax/types/EnumType.js +101 -0
- package/lib/syntax/types/ErrorType.js +37 -0
- package/lib/syntax/types/FunctionType.js +147 -0
- package/lib/syntax/types/HybridObjectBaseType.js +38 -0
- package/lib/syntax/types/HybridObjectType.js +131 -0
- package/lib/syntax/types/MapType.js +37 -0
- package/lib/syntax/types/NamedWrappingType.js +27 -0
- package/lib/syntax/types/NullType.js +23 -0
- package/lib/syntax/types/NumberType.js +27 -0
- package/lib/syntax/types/OptionalType.js +59 -0
- package/lib/syntax/types/PromiseType.js +62 -0
- package/lib/syntax/types/RecordType.js +47 -0
- package/lib/syntax/types/ResultWrappingType.js +44 -0
- package/lib/syntax/types/StringType.js +35 -0
- package/lib/syntax/types/StructType.js +61 -0
- package/lib/syntax/types/TupleType.js +39 -0
- package/lib/syntax/types/Type.js +1 -0
- package/lib/syntax/types/VariantType.js +75 -0
- package/lib/syntax/types/VoidType.js +27 -0
- package/lib/syntax/types/getTypeAs.js +12 -0
- package/lib/utils.js +126 -0
- package/lib/views/CppHybridViewComponent.js +256 -0
- package/lib/views/createHostComponentJs.js +27 -0
- package/lib/views/kotlin/KotlinHybridViewManager.js +229 -0
- package/lib/views/swift/SwiftHybridViewManager.js +131 -0
- package/lib/writeFile.js +19 -0
- package/package.json +58 -29
- package/src/Logger.ts +63 -0
- package/src/autolinking/Autolinking.ts +9 -0
- package/src/autolinking/android/createCMakeExtension.ts +126 -0
- package/src/autolinking/android/createGradleExtension.ts +43 -0
- package/src/autolinking/android/createHybridObjectInitializer.ts +174 -0
- package/src/autolinking/createAndroidAutolinking.ts +28 -0
- package/src/autolinking/createIOSAutolinking.ts +24 -0
- package/src/autolinking/ios/createHybridObjectInitializer.ts +112 -0
- package/src/autolinking/ios/createPodspecRubyExtension.ts +76 -0
- package/src/autolinking/ios/createSwiftCxxBridge.ts +137 -0
- package/src/autolinking/ios/createSwiftUmbrellaHeader.ts +90 -0
- package/src/config/NitroConfig.ts +139 -0
- package/src/config/NitroUserConfig.ts +105 -0
- package/src/config/getConfig.ts +91 -0
- package/src/createGitAttributes.ts +15 -0
- package/src/createPlatformSpec.ts +176 -0
- package/src/getFiles.ts +31 -0
- package/src/getPlatformSpecs.ts +202 -0
- package/src/index.ts +146 -0
- package/src/init.ts +186 -0
- package/src/nitrogen.ts +246 -0
- package/src/prettifyDirectory.ts +32 -0
- package/src/syntax/BridgedType.ts +59 -0
- package/src/syntax/CodeNode.ts +24 -0
- package/src/syntax/HybridObjectSpec.ts +14 -0
- package/src/syntax/Method.ts +154 -0
- package/src/syntax/Parameter.ts +81 -0
- package/src/syntax/Property.ts +203 -0
- package/src/syntax/SourceFile.ts +80 -0
- package/src/syntax/c++/CppEnum.ts +128 -0
- package/src/syntax/c++/CppHybridObject.ts +165 -0
- package/src/syntax/c++/CppHybridObjectRegistration.ts +39 -0
- package/src/syntax/c++/CppStruct.ts +129 -0
- package/src/syntax/c++/CppUnion.ts +105 -0
- package/src/syntax/c++/getForwardDeclaration.ts +19 -0
- package/src/syntax/c++/includeNitroHeader.ts +40 -0
- package/src/syntax/createType.ts +365 -0
- package/src/syntax/getAllTypes.ts +18 -0
- package/src/syntax/getCustomTypeConfig.ts +71 -0
- package/src/syntax/getHybridObjectName.ts +48 -0
- package/src/syntax/getInterfaceProperties.ts +21 -0
- package/src/syntax/getReferencedTypes.ts +57 -0
- package/src/syntax/helpers.ts +79 -0
- package/src/syntax/isCoreType.ts +60 -0
- package/src/syntax/kotlin/FbjniHybridObject.ts +313 -0
- package/src/syntax/kotlin/JNINativeRegistrations.ts +19 -0
- package/src/syntax/kotlin/KotlinBoxedPrimitive.ts +19 -0
- package/src/syntax/kotlin/KotlinCxxBridgedType.ts +942 -0
- package/src/syntax/kotlin/KotlinEnum.ts +130 -0
- package/src/syntax/kotlin/KotlinFunction.ts +277 -0
- package/src/syntax/kotlin/KotlinHybridObject.ts +205 -0
- package/src/syntax/kotlin/KotlinHybridObjectRegistration.ts +51 -0
- package/src/syntax/kotlin/KotlinStruct.ts +198 -0
- package/src/syntax/kotlin/KotlinVariant.ts +212 -0
- package/src/syntax/swift/SwiftCxxBridgedType.ts +874 -0
- package/src/syntax/swift/SwiftCxxTypeHelper.ts +674 -0
- package/src/syntax/swift/SwiftEnum.ts +65 -0
- package/src/syntax/swift/SwiftFunction.ts +91 -0
- package/src/syntax/swift/SwiftHybridObject.ts +121 -0
- package/src/syntax/swift/SwiftHybridObjectBridge.ts +522 -0
- package/src/syntax/swift/SwiftHybridObjectRegistration.ts +75 -0
- package/src/syntax/swift/SwiftStruct.ts +85 -0
- package/src/syntax/swift/SwiftVariant.ts +67 -0
- package/src/syntax/types/ArrayBufferType.ts +49 -0
- package/src/syntax/types/ArrayType.ts +62 -0
- package/src/syntax/types/BigIntType.ts +35 -0
- package/src/syntax/types/BooleanType.ts +35 -0
- package/src/syntax/types/CustomType.ts +47 -0
- package/src/syntax/types/DateType.ts +43 -0
- package/src/syntax/types/EnumType.ts +130 -0
- package/src/syntax/types/ErrorType.ts +44 -0
- package/src/syntax/types/FunctionType.ts +167 -0
- package/src/syntax/types/HybridObjectBaseType.ts +54 -0
- package/src/syntax/types/HybridObjectType.ts +198 -0
- package/src/syntax/types/MapType.ts +49 -0
- package/src/syntax/types/NamedWrappingType.ts +33 -0
- package/src/syntax/types/NullType.ts +30 -0
- package/src/syntax/types/NumberType.ts +34 -0
- package/src/syntax/types/OptionalType.ts +66 -0
- package/src/syntax/types/PromiseType.ts +72 -0
- package/src/syntax/types/RecordType.ts +56 -0
- package/src/syntax/types/ResultWrappingType.ts +53 -0
- package/src/syntax/types/StringType.ts +44 -0
- package/src/syntax/types/StructType.ts +83 -0
- package/src/syntax/types/TupleType.ts +53 -0
- package/src/syntax/types/Type.ts +82 -0
- package/src/syntax/types/VariantType.ts +92 -0
- package/src/syntax/types/VoidType.ts +34 -0
- package/src/syntax/types/getTypeAs.ts +15 -0
- package/src/utils.ts +162 -0
- package/src/views/CppHybridViewComponent.ts +304 -0
- package/src/views/createHostComponentJs.ts +34 -0
- package/src/views/kotlin/KotlinHybridViewManager.ts +258 -0
- package/src/views/swift/SwiftHybridViewManager.ts +153 -0
- package/src/writeFile.ts +27 -0
- package/.jshintignore +0 -6
- package/.jshintrc +0 -3
- package/.npmignore +0 -3
- package/.travis.yml +0 -13
- package/LICENSE +0 -13
- package/browser/nitrogen-min.js +0 -3
- package/browser/nitrogen.js +0 -6369
- package/lib/apiKey.js +0 -67
- package/lib/blob.js +0 -57
- package/lib/commandManager.js +0 -350
- package/lib/device.js +0 -19
- package/lib/memoryStore.js +0 -24
- package/lib/message.js +0 -298
- package/lib/permission.js +0 -121
- package/lib/principal.js +0 -330
- package/lib/service.js +0 -347
- package/lib/session.js +0 -494
- package/lib/user.js +0 -20
- package/publish +0 -2
- package/scripts/build-documentation +0 -4
- package/scripts/build-module +0 -27
- package/scripts/module.js +0 -12
- package/scripts/postamble.js +0 -1
- package/scripts/preamble.js +0 -2
- package/scripts/run-test-server +0 -9
- package/test/config.js +0 -12
- package/test/fixtures/images/image.jpg +0 -0
- package/test/fixtures/images/motion0.jpg +0 -0
- package/test/fixtures/images/motion1.jpg +0 -0
- package/test/fixtures/images/motion2.jpg +0 -0
- package/test/fixtures/index.js +0 -76
- package/test/main.js +0 -5
- package/test/memoryStore.js +0 -22
- package/test/mocha.opts +0 -3
- package/test/units/apiKey.js +0 -46
- package/test/units/blob.js +0 -35
- package/test/units/commandManager.js +0 -67
- package/test/units/device.js +0 -26
- package/test/units/heartbeat.js +0 -28
- package/test/units/message.js +0 -79
- package/test/units/permissions.js +0 -43
- package/test/units/principal.js +0 -116
- package/test/units/service.js +0 -92
- package/test/units/session.js +0 -97
- package/test/units/user.js +0 -48
- package/yuidoc.json +0 -8
package/src/nitrogen.ts
ADDED
|
@@ -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
|
+
}
|