@nebula-rn/host 0.0.1

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 (37) hide show
  1. package/NebulaHost.podspec +23 -0
  2. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  3. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  4. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  5. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  6. package/android/.gradle/8.9/gc.properties +0 -0
  7. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  8. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  9. package/android/.gradle/vcs-1/gc.properties +0 -0
  10. package/android/build.gradle +27 -0
  11. package/android/consumer-rules.pro +1 -0
  12. package/android/src/main/AndroidManifest.xml +1 -0
  13. package/android/src/main/java/com/hectorzhuang/nebula/NebulaActivity.kt +290 -0
  14. package/android/src/main/java/com/hectorzhuang/nebula/NebulaAppManager.kt +134 -0
  15. package/android/src/main/java/com/hectorzhuang/nebula/NebulaConfig.kt +324 -0
  16. package/android/src/main/java/com/hectorzhuang/nebula/NebulaEventHub.kt +49 -0
  17. package/android/src/main/java/com/hectorzhuang/nebula/NebulaHost.kt +145 -0
  18. package/android/src/main/java/com/hectorzhuang/nebula/NebulaHostModalActivity.kt +178 -0
  19. package/android/src/main/java/com/hectorzhuang/nebula/NebulaManifestManager.kt +130 -0
  20. package/android/src/main/java/com/hectorzhuang/nebula/NebulaNativeModule.kt +604 -0
  21. package/android/src/main/java/com/hectorzhuang/nebula/NebulaPackage.kt +16 -0
  22. package/android/src/main/java/com/hectorzhuang/nebula/NebulaRouter.kt +300 -0
  23. package/ios/Nebula/NebulaAppManager.swift +355 -0
  24. package/ios/Nebula/NebulaConfig.swift +549 -0
  25. package/ios/Nebula/NebulaContainerController.swift +580 -0
  26. package/ios/Nebula/NebulaDevLoading.swift +333 -0
  27. package/ios/Nebula/NebulaHost.swift +611 -0
  28. package/ios/Nebula/NebulaManifest.swift +214 -0
  29. package/ios/Nebula/NebulaNativeModule.swift +682 -0
  30. package/ios/Nebula/NebulaNativeModuleBridge.m +364 -0
  31. package/ios/Nebula/NebulaPerformanceMonitor.swift +46 -0
  32. package/ios/Nebula/NebulaRouter.swift +594 -0
  33. package/ios/Nebula/NebulaRouterBridge.m +19 -0
  34. package/ios/Nebula/RNInstanceViewController.swift +52 -0
  35. package/package.json +41 -0
  36. package/react-native.config.js +14 -0
  37. package/src/index.ts +9 -0
@@ -0,0 +1,130 @@
1
+ package com.hectorzhuang.nebula
2
+
3
+ import java.io.File
4
+ import org.json.JSONObject
5
+
6
+ data class NebulaInstalledApp(
7
+ val appId: String,
8
+ val mode: String,
9
+ val bundlePath: String,
10
+ val sourceUrl: String,
11
+ val version: String? = null,
12
+ val updateStrategy: String = "manual",
13
+ )
14
+
15
+ data class NebulaManifest(
16
+ val appId: String,
17
+ val entryPagePath: String?,
18
+ val pages: Map<String, String>,
19
+ val pageConfigs: Map<String, Map<String, Any?>>,
20
+ val updateStrategy: String?,
21
+ val version: String?,
22
+ val window: Map<String, Any?>,
23
+ )
24
+
25
+ object NebulaManifestManager {
26
+ private val manifests = linkedMapOf<String, NebulaManifest>()
27
+
28
+ @Synchronized
29
+ fun registerManifest(appId: String, manifest: NebulaManifest) {
30
+ manifests[appId] = manifest
31
+ }
32
+
33
+ @Synchronized
34
+ fun registerRoutes(appId: String, routes: Map<String, String>) {
35
+ val current = manifests[appId]
36
+ manifests[appId] =
37
+ NebulaManifest(
38
+ appId = appId,
39
+ entryPagePath = current?.entryPagePath ?: "/",
40
+ pages = routes,
41
+ pageConfigs = current?.pageConfigs ?: emptyMap(),
42
+ updateStrategy = current?.updateStrategy,
43
+ version = current?.version,
44
+ window = current?.window ?: emptyMap(),
45
+ )
46
+ }
47
+
48
+ fun loadManifest(appId: String, sandboxDir: File): NebulaManifest? {
49
+ val manifestFile = File(sandboxDir, "app.json")
50
+ if (!manifestFile.exists()) {
51
+ return manifests[appId]
52
+ }
53
+ val manifest = parseManifest(appId, JSONObject(manifestFile.readText()))
54
+ manifests[appId] = manifest
55
+ return manifest
56
+ }
57
+
58
+ fun removeManifest(appId: String) {
59
+ manifests.remove(appId)
60
+ }
61
+
62
+ fun getManifest(appId: String): NebulaManifest? = manifests[appId]
63
+
64
+ fun getEntryPagePath(appId: String): String = manifests[appId]?.entryPagePath ?: "/"
65
+
66
+ fun getComponentName(appId: String, routePath: String): String? {
67
+ val manifest = manifests[appId] ?: return null
68
+ return manifest.pages[normalizeRoute(routePath)]
69
+ }
70
+
71
+ fun getPageConfig(appId: String, routePath: String): Map<String, Any?> {
72
+ val manifest = manifests[appId] ?: return emptyMap()
73
+ val normalizedRoute = normalizeRoute(routePath)
74
+ val base = manifest.window.toMutableMap()
75
+ manifest.pageConfigs[normalizedRoute]?.let { base.putAll(it) }
76
+ if (normalizedRoute != "/" && base["navigationBarTitleText"] == null) {
77
+ manifest.pageConfigs["/"]?.get("navigationBarTitleText")?.let {
78
+ base["navigationBarTitleText"] = it
79
+ }
80
+ }
81
+ return base
82
+ }
83
+
84
+ private fun parseManifest(appId: String, json: JSONObject): NebulaManifest {
85
+ val pagesObject = json.optJSONObject("pages") ?: JSONObject()
86
+ val pageConfigsObject = json.optJSONObject("pageConfigs") ?: JSONObject()
87
+ val pages = mutableMapOf<String, String>()
88
+ val pageConfigs = mutableMapOf<String, Map<String, Any?>>()
89
+
90
+ pagesObject.keys().forEach { key ->
91
+ pages[normalizeRoute(key)] = pagesObject.optString(key)
92
+ }
93
+
94
+ pageConfigsObject.keys().forEach { key ->
95
+ pageConfigs[normalizeRoute(key)] = jsonObjectToMap(pageConfigsObject.optJSONObject(key))
96
+ }
97
+
98
+ return NebulaManifest(
99
+ appId = json.optString("appId", appId),
100
+ entryPagePath = normalizeRoute(json.optString("entryPagePath", "/")),
101
+ pages = pages,
102
+ pageConfigs = pageConfigs,
103
+ updateStrategy = json.optString("updateStrategy", "manual"),
104
+ version = json.optString("version", null),
105
+ window = jsonObjectToMap(json.optJSONObject("window")),
106
+ )
107
+ }
108
+
109
+ internal fun normalizeRoute(routePath: String?): String {
110
+ val raw = routePath?.takeIf { it.isNotBlank() } ?: "/"
111
+ return if (raw.startsWith("/")) raw else "/$raw"
112
+ }
113
+
114
+ internal fun jsonObjectToMap(jsonObject: JSONObject?): Map<String, Any?> {
115
+ if (jsonObject == null) {
116
+ return emptyMap()
117
+ }
118
+ val result = linkedMapOf<String, Any?>()
119
+ jsonObject.keys().forEach { key ->
120
+ val value = jsonObject.opt(key)
121
+ result[key] =
122
+ when (value) {
123
+ is JSONObject -> jsonObjectToMap(value)
124
+ JSONObject.NULL -> null
125
+ else -> value
126
+ }
127
+ }
128
+ return result
129
+ }
130
+ }