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
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import { readUserConfig } from './getConfig.js'
|
|
3
|
+
import type { NitroUserConfig } from './NitroUserConfig.js'
|
|
4
|
+
|
|
5
|
+
const CXX_BASE_NAMESPACE = ['margelo', 'nitro']
|
|
6
|
+
const ANDROID_BASE_NAMESPACE = ['com', 'margelo', 'nitro']
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Represents the properly parsed `nitro.json` config of the current executing directory.
|
|
10
|
+
*/
|
|
11
|
+
export class NitroConfig {
|
|
12
|
+
private readonly config: NitroUserConfig
|
|
13
|
+
private static singleton: NitroConfig | undefined
|
|
14
|
+
|
|
15
|
+
constructor(config: NitroUserConfig) {
|
|
16
|
+
this.config = config
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static get current(): NitroConfig {
|
|
20
|
+
if (this.singleton == null) {
|
|
21
|
+
console.log(
|
|
22
|
+
chalk.reset(`🔧 Loading ${chalk.underline('nitro.json')} config...`)
|
|
23
|
+
)
|
|
24
|
+
const defaultConfigPath = './nitro.json'
|
|
25
|
+
const config = readUserConfig(defaultConfigPath)
|
|
26
|
+
this.singleton = new NitroConfig(config)
|
|
27
|
+
}
|
|
28
|
+
return this.singleton
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Returns the name of the Android C++ library (aka name in CMakeLists.txt `add_library(..)`).
|
|
33
|
+
* This will be loaded via `System.loadLibrary(...)`.
|
|
34
|
+
* @example `NitroTest`
|
|
35
|
+
*/
|
|
36
|
+
getAndroidCxxLibName(): string {
|
|
37
|
+
return this.config.android.androidCxxLibName
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns the iOS module name (aka Pod name) of the module that will be generated.
|
|
42
|
+
* @example `NitroTest`
|
|
43
|
+
*/
|
|
44
|
+
getIosModuleName(): string {
|
|
45
|
+
return this.config.ios.iosModuleName
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Represents the C++ namespace of the module that will be generated.
|
|
50
|
+
* This can have multiple sub-namespaces, and is always relative to `margelo::nitro`.
|
|
51
|
+
* @example `['image']` -> `margelo::nitro::image`
|
|
52
|
+
*/
|
|
53
|
+
getCxxNamespace(
|
|
54
|
+
language: 'c++' | 'swift',
|
|
55
|
+
...subDefinitionName: string[]
|
|
56
|
+
): string {
|
|
57
|
+
const userNamespace = this.config.cxxNamespace
|
|
58
|
+
const namespace = [
|
|
59
|
+
...CXX_BASE_NAMESPACE,
|
|
60
|
+
...userNamespace,
|
|
61
|
+
...subDefinitionName,
|
|
62
|
+
]
|
|
63
|
+
switch (language) {
|
|
64
|
+
case 'c++':
|
|
65
|
+
return namespace.join('::')
|
|
66
|
+
case 'swift':
|
|
67
|
+
return namespace.join('.')
|
|
68
|
+
default:
|
|
69
|
+
throw new Error(`Invalid language for getCxxNamespace: ${language}`)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Represents the Android namespace of the module that will be generated.
|
|
75
|
+
* This can have multiple sub-namespaces, and is always relative to `com.margelo.nitro`.
|
|
76
|
+
* @example `['image']` -> `com.margelo.nitro.image`
|
|
77
|
+
*/
|
|
78
|
+
getAndroidPackage(
|
|
79
|
+
language: 'java/kotlin' | 'c++/jni',
|
|
80
|
+
...subPackage: string[]
|
|
81
|
+
): string {
|
|
82
|
+
const userPackage = this.config.android.androidNamespace
|
|
83
|
+
const namespace = [...ANDROID_BASE_NAMESPACE, ...userPackage, ...subPackage]
|
|
84
|
+
|
|
85
|
+
switch (language) {
|
|
86
|
+
case 'java/kotlin':
|
|
87
|
+
return namespace.join('.')
|
|
88
|
+
case 'c++/jni':
|
|
89
|
+
return namespace.join('/')
|
|
90
|
+
default:
|
|
91
|
+
throw new Error(`Invalid language for getAndroidPackage: ${language}`)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Return the directory of the android package, and a given sub-package.
|
|
97
|
+
* This will be used on android to put files from a package in their respective package folder.
|
|
98
|
+
*/
|
|
99
|
+
getAndroidPackageDirectory(...subPackage: string[]): string[] {
|
|
100
|
+
const userPackage = this.config.android.androidNamespace
|
|
101
|
+
return [...ANDROID_BASE_NAMESPACE, ...userPackage, ...subPackage]
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get the autolinking configuration of all HybridObjects.
|
|
106
|
+
* Those will be generated and default-constructed.
|
|
107
|
+
*/
|
|
108
|
+
getAutolinkedHybridObjects(): NitroUserConfig['autolinking'] {
|
|
109
|
+
return this.config.autolinking
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Get the paths that will be ignored when loading the TypeScript project.
|
|
114
|
+
* In most cases, this just contains `node_modules/`.
|
|
115
|
+
*/
|
|
116
|
+
getIgnorePaths(): string[] {
|
|
117
|
+
return this.config.ignorePaths ?? []
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
getGitAttributesGeneratedFlag(): boolean {
|
|
121
|
+
return this.config.gitAttributesGeneratedFlag ?? false
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
get isExternalConfig(): boolean {
|
|
125
|
+
// If the C++ namespaces are NOT equal, we are an external config.
|
|
126
|
+
return (
|
|
127
|
+
this.getCxxNamespace('c++') !== NitroConfig.current.getCxxNamespace('c++')
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
getSwiftBridgeHeaderName(): string {
|
|
132
|
+
const moduleName = this.getIosModuleName()
|
|
133
|
+
return `${moduleName}-Swift-Cxx-Bridge`
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
getSwiftBridgeNamespace(language: 'c++' | 'swift'): string {
|
|
137
|
+
return this.getCxxNamespace(language, 'bridge', 'swift')
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
// Namespaces and package names in C++/Java will be matched with a regex.
|
|
4
|
+
const safeNamePattern = /^[a-zA-Z_][a-zA-Z0-9_]*$/
|
|
5
|
+
|
|
6
|
+
const isNotReservedKeyword = (val: string) =>
|
|
7
|
+
!['core', 'nitro', 'NitroModules'].includes(val)
|
|
8
|
+
const isReservedKeywordError = {
|
|
9
|
+
message: `This value is reserved and cannot be used!`,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const NitroUserConfigSchema = z.object({
|
|
13
|
+
/**
|
|
14
|
+
* Represents the C++ namespace of the module that will be generated.
|
|
15
|
+
*
|
|
16
|
+
* This can have multiple sub-namespaces, and is always relative to `margelo::nitro`.
|
|
17
|
+
* @example `['image']` -> `margelo::nitro::image`
|
|
18
|
+
*/
|
|
19
|
+
cxxNamespace: z
|
|
20
|
+
.array(
|
|
21
|
+
z
|
|
22
|
+
.string()
|
|
23
|
+
.regex(safeNamePattern)
|
|
24
|
+
.refine(isNotReservedKeyword, isReservedKeywordError)
|
|
25
|
+
)
|
|
26
|
+
.min(1),
|
|
27
|
+
/**
|
|
28
|
+
* iOS specific options.
|
|
29
|
+
*/
|
|
30
|
+
ios: z.object({
|
|
31
|
+
/**
|
|
32
|
+
* Represents the iOS module name of the module that will be generated.
|
|
33
|
+
*
|
|
34
|
+
* This will be used to generate Swift bridges, as those are always namespaced within the clang module.
|
|
35
|
+
*
|
|
36
|
+
* If you are using CocoaPods, this should be the Pod name defined in the `.podspec`.
|
|
37
|
+
* @example `NitroTest`
|
|
38
|
+
*/
|
|
39
|
+
iosModuleName: z
|
|
40
|
+
.string()
|
|
41
|
+
.regex(safeNamePattern)
|
|
42
|
+
.refine(isNotReservedKeyword, isReservedKeywordError),
|
|
43
|
+
}),
|
|
44
|
+
/**
|
|
45
|
+
* Android specific options.
|
|
46
|
+
*/
|
|
47
|
+
android: z.object({
|
|
48
|
+
/**
|
|
49
|
+
* Represents the Android namespace ("package") of the module that will be generated.
|
|
50
|
+
*
|
|
51
|
+
* This can have multiple sub-namespaces, and is always relative to `com.margelo.nitro`.
|
|
52
|
+
* @example `['image']` -> `com.margelo.nitro.image`
|
|
53
|
+
*/
|
|
54
|
+
androidNamespace: z
|
|
55
|
+
.array(
|
|
56
|
+
z
|
|
57
|
+
.string()
|
|
58
|
+
.regex(safeNamePattern)
|
|
59
|
+
.refine(isNotReservedKeyword, isReservedKeywordError)
|
|
60
|
+
)
|
|
61
|
+
.min(1),
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Represents the name of the Android C++ library (aka name in CMakeLists.txt `add_library(..)`).
|
|
65
|
+
* This will be loaded via `System.loadLibrary(...)`.
|
|
66
|
+
* @example `NitroTest`
|
|
67
|
+
*/
|
|
68
|
+
androidCxxLibName: z
|
|
69
|
+
.string()
|
|
70
|
+
.regex(safeNamePattern)
|
|
71
|
+
.refine(isNotReservedKeyword, isReservedKeywordError),
|
|
72
|
+
}),
|
|
73
|
+
/**
|
|
74
|
+
* Configures the code that gets generated for autolinking (registering)
|
|
75
|
+
* Hybrid Object constructors.
|
|
76
|
+
*
|
|
77
|
+
* Each class listed here needs to have a default constructor/initializer that takes
|
|
78
|
+
* zero arguments.
|
|
79
|
+
*/
|
|
80
|
+
autolinking: z.record(
|
|
81
|
+
z.string(),
|
|
82
|
+
z.object({
|
|
83
|
+
cpp: z.string().optional(),
|
|
84
|
+
swift: z.string().optional(),
|
|
85
|
+
kotlin: z.string().optional(),
|
|
86
|
+
})
|
|
87
|
+
),
|
|
88
|
+
/**
|
|
89
|
+
* A list of paths relative to the project directory that should be ignored by nitrogen.
|
|
90
|
+
* Nitrogen will not look for `.nitro.ts` files in these directories.
|
|
91
|
+
*/
|
|
92
|
+
ignorePaths: z.array(z.string()).optional(),
|
|
93
|
+
/**
|
|
94
|
+
* Configures whether all nitro-generated files are marked as
|
|
95
|
+
* [`linguist-generated`](https://docs.github.com/en/repositories/working-with-files/managing-files/customizing-how-changed-files-appear-on-github)
|
|
96
|
+
* for GitHub. This disables diffing for generated content and excludes them from language statistics.
|
|
97
|
+
* This is controlled via `nitrogen/generated/.gitattributes`.
|
|
98
|
+
*/
|
|
99
|
+
gitAttributesGeneratedFlag: z.boolean().optional().default(true),
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Represents the structure of a `nitro.json` config file.
|
|
104
|
+
*/
|
|
105
|
+
export type NitroUserConfig = z.infer<typeof NitroUserConfigSchema>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { ZodError } from 'zod'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import {
|
|
4
|
+
NitroUserConfigSchema,
|
|
5
|
+
type NitroUserConfig,
|
|
6
|
+
} from './NitroUserConfig.js'
|
|
7
|
+
import chalk from 'chalk'
|
|
8
|
+
|
|
9
|
+
function readFile(configPath: string): string {
|
|
10
|
+
try {
|
|
11
|
+
return fs.readFileSync(configPath, 'utf8')
|
|
12
|
+
} catch (error) {
|
|
13
|
+
if (typeof error === 'object' && error != null && 'code' in error) {
|
|
14
|
+
switch (error.code) {
|
|
15
|
+
case 'ENOENT':
|
|
16
|
+
case 'ENOTDIR':
|
|
17
|
+
console.error(
|
|
18
|
+
`❌ The path ${chalk.underline(configPath)} does not exist! Create a ${chalk.underline('nitro.json')} file and try again.`
|
|
19
|
+
)
|
|
20
|
+
process.exit(1)
|
|
21
|
+
// @ts-expect-error
|
|
22
|
+
break
|
|
23
|
+
default:
|
|
24
|
+
throw error
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
// different kind of error, throw it.
|
|
28
|
+
throw error
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function propPathToString(propPath: PropertyKey[]): string {
|
|
34
|
+
if (propPath.length === 0) return ''
|
|
35
|
+
const prop = propPath.reduce<string>((prev, curr) => {
|
|
36
|
+
if (typeof curr === 'string') {
|
|
37
|
+
return `${prev}.${curr}`
|
|
38
|
+
} else if (typeof curr === 'number') {
|
|
39
|
+
return `${prev}[${curr}]`
|
|
40
|
+
} else {
|
|
41
|
+
return prev
|
|
42
|
+
}
|
|
43
|
+
}, '')
|
|
44
|
+
return prop.slice(1)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function parseConfig(json: string): NitroUserConfig {
|
|
48
|
+
let object: unknown
|
|
49
|
+
try {
|
|
50
|
+
object = JSON.parse(json)
|
|
51
|
+
} catch (error) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
`Failed to parse nitro.json config as JSON! Make sure it has a valid JSON syntax. JSON: ${json}`,
|
|
54
|
+
{
|
|
55
|
+
cause: error,
|
|
56
|
+
}
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
return NitroUserConfigSchema.parse(object)
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (error instanceof ZodError) {
|
|
64
|
+
const issues = error.issues.map((i) => {
|
|
65
|
+
const prop = propPathToString(i.path)
|
|
66
|
+
switch (i.code) {
|
|
67
|
+
case 'invalid_type':
|
|
68
|
+
return `\`${prop}\` must be ${i.expected}, but is ${i.input}.`
|
|
69
|
+
case 'invalid_value':
|
|
70
|
+
case 'invalid_union':
|
|
71
|
+
case 'invalid_element':
|
|
72
|
+
return `\`${prop}\` is not a valid & safe string. It must only contain alphanumeric characters and must not start with a number.`
|
|
73
|
+
default:
|
|
74
|
+
return `\`${prop}\`: ${i.message} (${i.code})`
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
console.error(
|
|
78
|
+
`❌ Invalid nitro.json config file! ${issues.join(' - also, ')}`
|
|
79
|
+
)
|
|
80
|
+
process.exit(1)
|
|
81
|
+
} else {
|
|
82
|
+
throw error
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function readUserConfig(configPath: string): NitroUserConfig {
|
|
88
|
+
const json = readFile(configPath)
|
|
89
|
+
const config = parseConfig(json)
|
|
90
|
+
return config
|
|
91
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import fs from 'fs/promises'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
|
|
4
|
+
export async function createGitAttributes(
|
|
5
|
+
markAsGenerated: boolean,
|
|
6
|
+
folder: string
|
|
7
|
+
): Promise<string> {
|
|
8
|
+
const file = path.join(folder, '.gitattributes')
|
|
9
|
+
// Marks all files in this current folder as "generated"
|
|
10
|
+
const content = `
|
|
11
|
+
** linguist-generated=${markAsGenerated}
|
|
12
|
+
`.trim()
|
|
13
|
+
await fs.writeFile(file, content + '\n', 'utf-8')
|
|
14
|
+
return file
|
|
15
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { Node, Type } from 'ts-morph'
|
|
2
|
+
import type { SourceFile } from './syntax/SourceFile.js'
|
|
3
|
+
import { createCppHybridObject } from './syntax/c++/CppHybridObject.js'
|
|
4
|
+
import {
|
|
5
|
+
extendsHybridObject,
|
|
6
|
+
isHybridView,
|
|
7
|
+
isAnyHybridSubclass,
|
|
8
|
+
isDirectlyHybridObject,
|
|
9
|
+
type Language,
|
|
10
|
+
isHybridViewProps,
|
|
11
|
+
isHybridViewMethods,
|
|
12
|
+
} from './getPlatformSpecs.js'
|
|
13
|
+
import type { HybridObjectSpec } from './syntax/HybridObjectSpec.js'
|
|
14
|
+
import { Property } from './syntax/Property.js'
|
|
15
|
+
import { Method } from './syntax/Method.js'
|
|
16
|
+
import { createSwiftHybridObject } from './syntax/swift/SwiftHybridObject.js'
|
|
17
|
+
import { createKotlinHybridObject } from './syntax/kotlin/KotlinHybridObject.js'
|
|
18
|
+
import { createType } from './syntax/createType.js'
|
|
19
|
+
import { Parameter } from './syntax/Parameter.js'
|
|
20
|
+
import { getBaseTypes, getHybridObjectNitroModuleConfig } from './utils.js'
|
|
21
|
+
import { NitroConfig } from './config/NitroConfig.js'
|
|
22
|
+
|
|
23
|
+
export function generatePlatformFiles(
|
|
24
|
+
interfaceType: Type,
|
|
25
|
+
language: Language
|
|
26
|
+
): SourceFile[] {
|
|
27
|
+
const spec = getHybridObjectSpec(interfaceType, language)
|
|
28
|
+
|
|
29
|
+
// TODO: We currently just call this so the HybridObject itself is a "known type".
|
|
30
|
+
// This causes the Swift Umbrella header to properly forward-declare it.
|
|
31
|
+
// Without this, only Hybrid Objects that are actually used in public APIs will be forward-declared.
|
|
32
|
+
createType(language, interfaceType, false)
|
|
33
|
+
|
|
34
|
+
switch (language) {
|
|
35
|
+
case 'c++':
|
|
36
|
+
return generateCppFiles(spec)
|
|
37
|
+
case 'swift':
|
|
38
|
+
return generateSwiftFiles(spec)
|
|
39
|
+
case 'kotlin':
|
|
40
|
+
return generateKotlinFiles(spec)
|
|
41
|
+
default:
|
|
42
|
+
throw new Error(`Language "${language}" is not supported!`)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getHybridObjectSpec(type: Type, language: Language): HybridObjectSpec {
|
|
47
|
+
const config = getHybridObjectNitroModuleConfig(type) ?? NitroConfig.current
|
|
48
|
+
|
|
49
|
+
if (isHybridView(type)) {
|
|
50
|
+
const symbol = type.getAliasSymbolOrThrow()
|
|
51
|
+
const name = symbol.getEscapedName()
|
|
52
|
+
|
|
53
|
+
// It's a Hybrid View - the `Props & Methods` types are just intersected together.
|
|
54
|
+
const unions = type.getIntersectionTypes()
|
|
55
|
+
const props = unions.find((t) => isHybridViewProps(t))
|
|
56
|
+
const methods = unions.find((t) => isHybridViewMethods(t))
|
|
57
|
+
if (props == null)
|
|
58
|
+
throw new Error(
|
|
59
|
+
`Props cannot be null! ${name}<...> (HybridView) requires type arguments.`
|
|
60
|
+
)
|
|
61
|
+
const propsSpec = getHybridObjectSpec(props, language)
|
|
62
|
+
const methodsSpec =
|
|
63
|
+
methods != null ? getHybridObjectSpec(methods, language) : undefined
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
baseTypes: [],
|
|
67
|
+
isHybridView: true,
|
|
68
|
+
language: language,
|
|
69
|
+
methods: methodsSpec?.methods ?? [],
|
|
70
|
+
properties: propsSpec.properties,
|
|
71
|
+
name: name,
|
|
72
|
+
config: config,
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const symbol = type.getSymbolOrThrow()
|
|
77
|
+
const name = symbol.getEscapedName()
|
|
78
|
+
|
|
79
|
+
const properties: Property[] = []
|
|
80
|
+
const methods: Method[] = []
|
|
81
|
+
for (const prop of type.getProperties()) {
|
|
82
|
+
const declarations = prop.getDeclarations()
|
|
83
|
+
if (declarations.length > 1) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
`${name}: Function overloading is not supported! (In "${prop.getName()}")`
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
let declaration = declarations[0]
|
|
89
|
+
if (declaration == null) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
`${name}: Property "${prop.getName()}" does not have a type declaration!`
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const parent = declaration.getParentOrThrow().getType()
|
|
96
|
+
|
|
97
|
+
if (parent === type) {
|
|
98
|
+
// it's an own property. declared literally here. fine.
|
|
99
|
+
} else if (
|
|
100
|
+
extendsHybridObject(parent, true) ||
|
|
101
|
+
isDirectlyHybridObject(parent)
|
|
102
|
+
) {
|
|
103
|
+
// it's coming from a base class that is already a HybridObject. We can grab this via inheritance.
|
|
104
|
+
// don't generate this property natively.
|
|
105
|
+
continue
|
|
106
|
+
} else {
|
|
107
|
+
// it's coming from any TypeScript type that is not a HybridObject.
|
|
108
|
+
// Maybe just a literal interface, then we copy over the props.
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (Node.isPropertySignature(declaration)) {
|
|
112
|
+
const t = declaration.getType()
|
|
113
|
+
const propType = createType(
|
|
114
|
+
language,
|
|
115
|
+
t,
|
|
116
|
+
prop.isOptional() || t.isNullable()
|
|
117
|
+
)
|
|
118
|
+
properties.push(
|
|
119
|
+
new Property(prop.getName(), propType, declaration.isReadonly())
|
|
120
|
+
)
|
|
121
|
+
} else if (Node.isMethodSignature(declaration)) {
|
|
122
|
+
const returnType = declaration.getReturnType()
|
|
123
|
+
const methodReturnType = createType(
|
|
124
|
+
language,
|
|
125
|
+
returnType,
|
|
126
|
+
returnType.isNullable()
|
|
127
|
+
)
|
|
128
|
+
const methodParameters = declaration
|
|
129
|
+
.getParameters()
|
|
130
|
+
.map((p) => new Parameter(p, language))
|
|
131
|
+
methods.push(
|
|
132
|
+
new Method(prop.getName(), methodReturnType, methodParameters)
|
|
133
|
+
)
|
|
134
|
+
} else {
|
|
135
|
+
throw new Error(
|
|
136
|
+
`${name}: Property "${prop.getName()}" is neither a property, nor a method!`
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const bases = getBaseTypes(type)
|
|
142
|
+
.filter((t) => isAnyHybridSubclass(t))
|
|
143
|
+
.map((t) => getHybridObjectSpec(t, language))
|
|
144
|
+
|
|
145
|
+
const spec: HybridObjectSpec = {
|
|
146
|
+
language: language,
|
|
147
|
+
name: name,
|
|
148
|
+
properties: properties,
|
|
149
|
+
methods: methods,
|
|
150
|
+
baseTypes: bases,
|
|
151
|
+
isHybridView: isHybridView(type),
|
|
152
|
+
config: config,
|
|
153
|
+
}
|
|
154
|
+
return spec
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function generateCppFiles(spec: HybridObjectSpec): SourceFile[] {
|
|
158
|
+
const cppFiles = createCppHybridObject(spec)
|
|
159
|
+
return cppFiles
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function generateSwiftFiles(spec: HybridObjectSpec): SourceFile[] {
|
|
163
|
+
// 1. Always generate a C++ spec for the shared layer and type declarations (enums, interfaces, ...)
|
|
164
|
+
const cppFiles = generateCppFiles(spec)
|
|
165
|
+
// 2. Generate Swift specific files and potentially a C++ binding layer
|
|
166
|
+
const swiftFiles = createSwiftHybridObject(spec)
|
|
167
|
+
return [...cppFiles, ...swiftFiles]
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function generateKotlinFiles(spec: HybridObjectSpec): SourceFile[] {
|
|
171
|
+
// 1. Always generate a C++ spec for the shared layer and type declarations (enums, interfaces, ...)
|
|
172
|
+
const cppFiles = generateCppFiles(spec)
|
|
173
|
+
// 2. Generate Kotlin specific files and potentially a C++ binding layer
|
|
174
|
+
const kotlinFiles = createKotlinHybridObject(spec)
|
|
175
|
+
return [...cppFiles, ...kotlinFiles]
|
|
176
|
+
}
|
package/src/getFiles.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Dirent, promises as fs } from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
|
|
4
|
+
function getFilePath(file: Dirent, rootDir: string): string {
|
|
5
|
+
const dir = file.parentPath ?? file.path ?? rootDir
|
|
6
|
+
return path.join(dir, file.name)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function getFiles(directory: string): Promise<string[]> {
|
|
10
|
+
try {
|
|
11
|
+
const files = await fs.readdir(directory, {
|
|
12
|
+
recursive: true,
|
|
13
|
+
withFileTypes: true,
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
return files.filter((f) => f.isFile()).map((f) => getFilePath(f, directory))
|
|
17
|
+
} catch (error) {
|
|
18
|
+
if (
|
|
19
|
+
typeof error === 'object' &&
|
|
20
|
+
error != null &&
|
|
21
|
+
'code' in error &&
|
|
22
|
+
error.code === 'ENOENT'
|
|
23
|
+
) {
|
|
24
|
+
// directory does not exist
|
|
25
|
+
return []
|
|
26
|
+
} else {
|
|
27
|
+
// different error
|
|
28
|
+
throw error
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|