catalyst-core 0.2.0-beta.2 → 0.3.0-beta.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 (184) hide show
  1. package/babel.native.config.cjs +8 -0
  2. package/bin/catalyst.js +49 -105
  3. package/changelog.md +8 -0
  4. package/dist/caching.js +1 -1
  5. package/dist/index.jsx +8 -0
  6. package/dist/logger.js +74 -3
  7. package/dist/native/androidProject/app/build.gradle.kts +1 -0
  8. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/CustomWebview.kt +143 -4
  9. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/MainActivity.kt +26 -6
  10. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/MetricsMonitor.kt +143 -17
  11. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/NativeBridge.kt +6 -0
  12. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/WebCacheManager.kt +26 -0
  13. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/BridgeUtils.kt +56 -1
  14. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/KeyboardUtil.kt +48 -8
  15. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/PerfDeliveryState.kt +36 -0
  16. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/PerfEventBuffer.kt +289 -0
  17. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/ProfilerNavigationState.kt +13 -0
  18. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/ProfilerLifecycleTest.kt +51 -0
  19. package/dist/native/androidSetup.js +300 -8
  20. package/dist/native/bridge/WebBridge.js +481 -59
  21. package/dist/native/bridge/constants/NativeInterfaces.js +290 -44
  22. package/dist/native/bridge/errors.js +250 -26
  23. package/dist/native/bridge/hooks/index.js +125 -1
  24. package/dist/native/bridge/hooks/useCamera.js +347 -9
  25. package/dist/native/bridge/hooks/useDataProtection.js +200 -2
  26. package/dist/native/bridge/hooks/useDeviceInfo.js +71 -2
  27. package/dist/native/bridge/hooks/useFilePicker.js +429 -2
  28. package/dist/native/bridge/hooks/useGoogleSignIn.js +81 -1
  29. package/dist/native/bridge/hooks/useHapticFeedback.js +196 -1
  30. package/dist/native/bridge/hooks/useIntent.js +95 -1
  31. package/dist/native/bridge/hooks/useNativeTransition.js +202 -27
  32. package/dist/native/bridge/hooks/useNetworkStatus.js +84 -3
  33. package/dist/native/bridge/hooks/useNotification.js +318 -2
  34. package/dist/native/bridge/hooks/useSafeArea.js +84 -2
  35. package/dist/native/bridge/hooks/useVideoStream.js +434 -6
  36. package/dist/native/bridge/hooks/utils.js +27 -1
  37. package/dist/native/bridge/hooks.js +16 -1
  38. package/dist/native/bridge/perf/collectors/ApiCollector.js +85 -0
  39. package/dist/native/bridge/perf/collectors/CacheCollector.js +215 -0
  40. package/dist/native/bridge/perf/collectors/HookCollector.js +165 -0
  41. package/dist/native/bridge/perf/collectors/InsightsCollector.js +505 -0
  42. package/dist/native/bridge/perf/collectors/InteractionCollector.js +273 -0
  43. package/dist/native/bridge/perf/collectors/KeyboardCollector.js +124 -0
  44. package/dist/native/bridge/perf/collectors/NavigationCollector.js +294 -0
  45. package/dist/native/bridge/perf/collectors/NetworkTimingCollector.js +183 -0
  46. package/dist/native/bridge/perf/collectors/RenderCollector.js +284 -0
  47. package/dist/native/bridge/perf/collectors/ScrollCollector.js +111 -0
  48. package/dist/native/bridge/perf/collectors/ThreadCollector.js +111 -0
  49. package/dist/native/bridge/perf/core/constants.js +126 -0
  50. package/dist/native/bridge/perf/core/measure.js +189 -0
  51. package/dist/native/bridge/perf/core/session.js +100 -0
  52. package/dist/native/bridge/perf/core/store.js +554 -0
  53. package/dist/native/bridge/perf/core/summary.js +174 -0
  54. package/dist/native/bridge/perf/core/traceExport.js +240 -0
  55. package/dist/native/bridge/perf/core/waterfalls.js +146 -0
  56. package/dist/native/bridge/perf/index.js +402 -0
  57. package/dist/native/bridge/safeArea.js +53 -5
  58. package/dist/native/bridge/standardizedHooks.js +595 -82
  59. package/dist/native/bridge/useBaseHook.js +274 -38
  60. package/dist/native/bridge/utils/CameraUtils.js +201 -56
  61. package/dist/native/bridge/utils/FileObjectConverter.js +129 -18
  62. package/dist/native/bridge/utils/NativeBridge.js +425 -141
  63. package/dist/native/buildAndroid/assets.js +510 -13
  64. package/dist/native/buildAndroid/build.js +296 -19
  65. package/dist/native/buildAndroid/config.js +87 -1
  66. package/dist/native/buildAndroid/index.js +374 -1
  67. package/dist/native/buildAppAndroid.js +34 -2
  68. package/dist/native/buildAppIos.js +62 -2
  69. package/dist/native/buildIos/assets.js +609 -8
  70. package/dist/native/buildIos/build.js +639 -20
  71. package/dist/native/buildIos/config.js +294 -12
  72. package/dist/native/buildIos/index.js +343 -6
  73. package/dist/native/buildIos/plugins.js +343 -16
  74. package/dist/native/internal-plugins/device-info-plugin/android/DeviceInfoPlugin.kt +43 -0
  75. package/dist/native/internal-plugins/device-info-plugin/ios/DeviceInfoPlugin.swift +28 -0
  76. package/dist/native/internal-plugins/device-info-plugin/manifest.json +19 -0
  77. package/dist/native/internalPluginUtils.js +232 -7
  78. package/dist/native/iosnativeWebView/Sources/Core/Constants/CatalystConstants.swift +19 -0
  79. package/dist/native/iosnativeWebView/Sources/Core/Constants/ConfigConstants.swift +4 -0
  80. package/dist/native/iosnativeWebView/Sources/Core/Utils/BootTimingUtility.swift +5 -1
  81. package/dist/native/iosnativeWebView/Sources/Core/Utils/CacheManager.swift +10 -0
  82. package/dist/native/iosnativeWebView/Sources/Core/Utils/DisplayLinkPerfMonitor.swift +89 -0
  83. package/dist/native/iosnativeWebView/Sources/Core/Utils/PerfEventBuffer.swift +373 -0
  84. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeFileHandler.swift +35 -1
  85. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeMessageValidator.swift +24 -11
  86. package/dist/native/iosnativeWebView/Sources/Core/WebView/NativeBridge.swift +9 -0
  87. package/dist/native/iosnativeWebView/Sources/Core/WebView/WebView.swift +126 -0
  88. package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewNavigationDelegate.swift +75 -1
  89. package/dist/native/iosnativeWebView/iosnativeWebViewTests/BridgeMessageValidatorTests.swift +13 -0
  90. package/dist/native/package.json +3 -0
  91. package/dist/native/plugin-bridge/PluginBridge.js +227 -1
  92. package/dist/native/pluginComposerAndroid.js +407 -23
  93. package/dist/native/pluginComposerIos.js +435 -11
  94. package/dist/native/renameAndroidProject.js +1094 -88
  95. package/dist/native/setupEmulatorIos.js +289 -22
  96. package/dist/native/setupServer.js +160 -19
  97. package/dist/native/terminalProgress.js +199 -11
  98. package/dist/native/utils.js +193 -15
  99. package/dist/offline/catalyst-sw.js +145 -1
  100. package/dist/offline/registerServiceWorker.js +33 -1
  101. package/dist/otel.js +375 -46
  102. package/dist/router/ClientRouter.js +14 -2
  103. package/dist/router/ServerRouter.js +9 -1
  104. package/dist/router.js +1 -1
  105. package/dist/scripts/build.js +112 -3
  106. package/dist/scripts/checkVersion.js +3 -1
  107. package/dist/scripts/cleanCache.js +30 -1
  108. package/dist/scripts/generateOfflineManifest.js +116 -1
  109. package/dist/scripts/loadEnvironmentVariables.js +32 -6
  110. package/dist/scripts/plugins.js +309 -1
  111. package/dist/scripts/preServerInit.js +13 -0
  112. package/dist/scripts/scriptUtils.js +54 -3
  113. package/dist/scripts/serve.js +51 -4
  114. package/dist/scripts/start.js +47 -10
  115. package/dist/scripts/validator.js +149 -1
  116. package/dist/sentry.cjs +127 -0
  117. package/dist/sentry.js +125 -5
  118. package/dist/server/expressServer.js +250 -5
  119. package/dist/server/manifestCache.js +36 -0
  120. package/dist/server/renderer/ChunkExtractor.js +144 -0
  121. package/dist/server/renderer/document/Body.jsx +59 -0
  122. package/dist/server/renderer/document/FastRefresh.jsx +20 -0
  123. package/dist/server/renderer/document/Head.jsx +60 -0
  124. package/dist/server/renderer/document/index.jsx +2 -0
  125. package/dist/server/renderer/extract.js +149 -31
  126. package/dist/server/renderer/handler.jsx +433 -0
  127. package/dist/server/renderer/index.js +8 -1
  128. package/dist/server/renderer/render.js +47 -0
  129. package/dist/server/utils/botDetectionMiddleware.js +29 -0
  130. package/dist/server/utils/cjsRequire.js +10 -0
  131. package/dist/server/utils/userAgentUtil.js +87 -9
  132. package/dist/server/utils/validator.js +164 -1
  133. package/dist/vite/FastRefresh.jsx +20 -0
  134. package/dist/vite/inject-cache-key-plugin.js +276 -0
  135. package/dist/vite/loadCustomViteConfig.js +22 -0
  136. package/dist/vite/manifest-categorization-plugin.js +455 -0
  137. package/dist/vite/node-loader.mjs +458 -0
  138. package/dist/vite/scssParams.js +21 -0
  139. package/dist/vite/vite.config.client.js +130 -0
  140. package/dist/vite/vite.config.js +422 -0
  141. package/dist/vite/vite.config.server.js +84 -0
  142. package/dist/web-router/components/MetaTag.jsx +34 -0
  143. package/dist/web-router/components/RouterDataProvider.jsx +332 -0
  144. package/dist/web-router/components/Split.jsx +200 -0
  145. package/dist/web-router/components/SplitInview.jsx +106 -0
  146. package/dist/web-router/components/SsrRequestContext.jsx +14 -0
  147. package/dist/web-router/context.jsx +12 -0
  148. package/dist/web-router/hooks.jsx +72 -0
  149. package/dist/web-router/types/components/MetaTag.d.ts +2 -0
  150. package/dist/web-router/types/components/RouterDataProvider.d.ts +95 -0
  151. package/dist/web-router/types/context.d.ts +14 -0
  152. package/dist/web-router/types/hooks.d.ts +1 -0
  153. package/dist/web-router/types/index.d.ts +3 -0
  154. package/dist/web-router/types/utils/metaDataUtils.d.ts +24 -0
  155. package/dist/web-router/utils/metaDataUtils.jsx +119 -0
  156. package/mcp_v2/conversion-tasks.json +35 -17
  157. package/mcp_v2/knowledge-base.json +124 -13
  158. package/mcp_v2/lib/helpers.js +10 -0
  159. package/mcp_v2/mcp.js +4 -4
  160. package/mcp_v2/package.json +1 -0
  161. package/mcp_v2/tools/build.js +116 -20
  162. package/mcp_v2/tools/conversion.js +106 -5
  163. package/mcp_v2/tools/tasks.js +18 -14
  164. package/package.json +35 -68
  165. package/babel.config.js +0 -32
  166. package/dist/index.js +0 -1
  167. package/dist/scripts/devBuild.js +0 -3
  168. package/dist/scripts/devServe.js +0 -3
  169. package/dist/scripts/loadScriptsBeforeServerStarts.js +0 -4
  170. package/dist/scripts/registerAliases.js +0 -6
  171. package/dist/server/renderer/document/Body.js +0 -11
  172. package/dist/server/renderer/document/Head.js +0 -9
  173. package/dist/server/renderer/document/index.js +0 -1
  174. package/dist/server/renderer/handler.js +0 -47
  175. package/dist/server/startServer.js +0 -57
  176. package/dist/webpack/babel-plugins/remove-client.plugin.js +0 -5
  177. package/dist/webpack/babel-plugins/remove-ssr.plugin.js +0 -5
  178. package/dist/webpack/babel.config.client.js +0 -1
  179. package/dist/webpack/babel.config.ssr.js +0 -1
  180. package/dist/webpack/base.babel.js +0 -7
  181. package/dist/webpack/development.client.babel.js +0 -10
  182. package/dist/webpack/production.client.babel.js +0 -4
  183. package/dist/webpack/production.ssr.babel.js +0 -8
  184. package/dist/webpack/scssParams.js +0 -9
@@ -1 +1,374 @@
1
- "use strict";const path=require("path");const{runCommand,runInteractiveCommand}=require("../utils.js");const TerminalProgress=require("../TerminalProgress.js").default;const{composeAndroidPlugins}=require("../pluginComposerAndroid.js");const{resolvePluginConfig,resolveInternalPluginsRoot}=require("../internalPluginUtils.js");const createConfigPhase=require("./config.js");const createAssetsPhase=require("./assets.js");const createBuildPhase=require("./build.js");const catalystCorePath=path.dirname(require.resolve("catalyst-core/package.json"));const pwd=path.join(catalystCorePath,"dist/native");const ANDROID_PACKAGE="io.yourname.androidproject";const steps={config:"Initialize Configuration",tools:"Validate Android Tools",emulator:"Check and Start Emulator",copyAssets:"Copy Build Assets",build:"Build and Install Application",aab:"Build Signed AAB"};const progressConfig={titlePaddingTop:2,titlePaddingBottom:1,stepPaddingLeft:4,stepSpacing:1,errorPaddingLeft:6,bottomMargin:2};function createAndroidBuild(config){const{WEBVIEW_CONFIG,BUILD_OUTPUT_PATH}=config;const configPath=`${process.cwd()}/config/config.json`;const publicPath=`${process.cwd()}/public`;const progress=new TerminalProgress(steps,"Catalyst Android Build",progressConfig);const ctx={WEBVIEW_CONFIG,BUILD_OUTPUT_PATH,configPath,publicPath,pwd,progress,ANDROID_PACKAGE,runCommand,runInteractiveCommand};const{initializeConfig,validateAndroidTools}=createConfigPhase(ctx);const{copyBuildAssets,copySplashscreenAssets,copyOfflinePage,copyIconAssets,configureAppName,processNotifications}=createAssetsPhase(ctx);const{detectPhysicalDevice,testPhysicalDeviceInstallation,handleEmulatorSetup,buildApp,launchApp,moveApkToOutputPath,buildSignedAAB}=createBuildPhase(ctx);async function buildAndroidApp(){let androidConfig=null;let targetDevice=null;try{progress.start("config");const{WEBVIEW_CONFIG:wvConfig,BUILD_OUTPUT_PATH:bop}=await initializeConfig();androidConfig=wvConfig.android;const buildType=androidConfig.buildType||"debug";const buildOptimisation=!!androidConfig.buildOptimisation||false;progress.complete("config");progress.start("tools");const{ADB_PATH,EMULATOR_PATH}=validateAndroidTools(androidConfig);progress.complete("tools");if(buildType!=="release"){progress.start("emulator");const physicalDevice=await detectPhysicalDevice(ADB_PATH);if(physicalDevice){progress.log(`Found physical device: ${physicalDevice.model} (${physicalDevice.id})`,"success");const canInstallOnPhysical=await testPhysicalDeviceInstallation(ADB_PATH,physicalDevice.id);if(canInstallOnPhysical){targetDevice={type:"physical",id:physicalDevice.id,model:physicalDevice.model};progress.log(`Using physical device: ${physicalDevice.model}`,"success");}else{progress.log("Physical device installation test failed, falling back to emulator","warning");targetDevice=await handleEmulatorSetup(ADB_PATH,EMULATOR_PATH,androidConfig);}}else{targetDevice=await handleEmulatorSetup(ADB_PATH,EMULATOR_PATH,androidConfig);}progress.complete("emulator");}else{progress.log("Skipping device setup for release build","info");}progress.start("copyAssets");await copyBuildAssets(androidConfig,buildOptimisation);await copySplashscreenAssets();await copyOfflinePage();await copyIconAssets();await configureAppName(androidConfig);const pluginConfig=resolvePluginConfig(wvConfig);composeAndroidPlugins({corePluginsRoot:resolveInternalPluginsRoot(catalystCorePath),androidProjectPath:`${pwd}/androidProject`,pluginConfig,log:(message,status="info")=>progress.log(message,status)});await processNotifications(wvConfig);progress.log(`Build optimization: ${buildOptimisation?"Enabled":"Disabled"}`,"info");progress.complete("copyAssets");let movedApkPath=null;if(buildType==="release"){progress.start("aab");await buildSignedAAB(androidConfig);progress.complete("aab");movedApkPath=await moveApkToOutputPath(buildType,bop,androidConfig.appName);}else{progress.start("build");await buildApp(ADB_PATH,androidConfig,buildOptimisation,targetDevice);await launchApp(ADB_PATH,buildType,targetDevice);progress.complete("build");movedApkPath=await moveApkToOutputPath(buildType,bop,androidConfig.appName);}const summaryItems=["Build completed successfully:",{text:`Build Type: ${buildType}`,indent:1,prefix:"├─ ",color:"gray"},{text:`SDK Path: ${androidConfig.sdkPath}`,indent:1,prefix:"├─ ",color:"gray"},{text:`Build Optimization: ${buildOptimisation?"Enabled":"Disabled"}`,indent:1,prefix:"├─ ",color:"gray"}];if(buildType==="release"){if(movedApkPath){summaryItems.push({text:`APK Build Location: ${movedApkPath}`,indent:1,prefix:"├─ ",color:"green"});}summaryItems.push({text:`Output: Signed AAB generated in build-output/`,indent:1,prefix:"└─ ",color:"green"});}else{if(movedApkPath){summaryItems.push({text:`APK Build Location: ${movedApkPath}`,indent:1,prefix:"├─ ",color:"green"});}if(targetDevice&&targetDevice.type==="physical"){summaryItems.push({text:`Target Device: ${targetDevice.model} (Physical)`,indent:1,prefix:"└─ ",color:"green"});}else{summaryItems.push({text:`Target Device: ${androidConfig.emulatorName} (Emulator)`,indent:1,prefix:"└─ ",color:"gray"});}}progress.printTreeContent("Build Summary",summaryItems);}catch(error){if(progress.currentStep){progress.fail(progress.currentStep.id,error.message);const troubleshootingItems=["Build failed. Please try the following steps:",{text:"Check if Android SDK is properly configured",indent:1,prefix:"├─ ",color:"yellow"},{text:"Verify build assets exist in the source directory",indent:1,prefix:"├─ ",color:"yellow"}];const buildType=androidConfig?.buildType||"debug";if(buildType!=="release"){if(error.message.includes("physical device")||error.message.includes("installation test")){troubleshootingItems.push("\nPhysical Device Issues:",{text:"Enable Developer Options on your device",indent:1,prefix:"├─ ",color:"yellow"},{text:"Enable USB Debugging in Developer Options",indent:1,prefix:"├─ ",color:"yellow"},{text:'Accept the "Allow USB Debugging" prompt on your device',indent:1,prefix:"├─ ",color:"yellow"},{text:"Try disconnecting and reconnecting your device",indent:1,prefix:"├─ ",color:"yellow"},{text:'Check if "adb devices" shows your device as authorized',indent:1,prefix:"├─ ",color:"yellow"});}troubleshootingItems.push({text:"Verify that the emulator exists and is working",indent:1,prefix:"├─ ",color:"yellow"},{text:"If using physical device, ensure it stays connected",indent:1,prefix:"├─ ",color:"yellow"});}else{troubleshootingItems.push({text:"Verify keystore configuration for release builds",indent:1,prefix:"├─ ",color:"yellow"},{text:"Check that keystore passwords are properly set",indent:1,prefix:"├─ ",color:"yellow"});}troubleshootingItems.push({text:'Run "npm run setupEmulator:android" to reconfigure Android settings',indent:1,prefix:"└─ ",color:"yellow"},"\nVerify Configuration:");if(androidConfig){troubleshootingItems.push({text:`Build Type: ${buildType}`,indent:1,prefix:"├─ ",color:"gray"},{text:`Android SDK Path: ${androidConfig.sdkPath||"Not configured"}`,indent:1,prefix:"├─ ",color:"gray"});if(buildType!=="release"){if(targetDevice){troubleshootingItems.push({text:`Target Device: ${targetDevice.type==="physical"?`${targetDevice.model} (Physical)`:`${androidConfig.emulatorName} (Emulator)`}`,indent:1,prefix:"└─ ",color:"gray"});}else{troubleshootingItems.push({text:`Selected Emulator: ${androidConfig.emulatorName||"Not configured"}`,indent:1,prefix:"└─ ",color:"gray"});}}else{troubleshootingItems.push({text:`Output Path: ${androidConfig.outputPath||"build-output/"}`,indent:1,prefix:"└─ ",color:"gray"});}}else{troubleshootingItems.push({text:"Configuration could not be loaded",indent:1,prefix:"├─ ",color:"red"},{text:"Check if config/config.json exists and has valid Android configuration",indent:1,prefix:"└─ ",color:"red"});}progress.printTreeContent("Troubleshooting Guide",troubleshootingItems);}throw error;}}async function buildAndroidForTesting(){try{const{WEBVIEW_CONFIG:wvConfig}=await initializeConfig();const androidConfig=wvConfig.android;const buildOptimisation=!!androidConfig.buildOptimisation||false;await copyBuildAssets(androidConfig,buildOptimisation);await copySplashscreenAssets();await copyOfflinePage();await copyIconAssets();await configureAppName(androidConfig);const pluginConfig=resolvePluginConfig(wvConfig);composeAndroidPlugins({corePluginsRoot:resolveInternalPluginsRoot(catalystCorePath),androidProjectPath:`${pwd}/androidProject`,pluginConfig,log:(message,status="info")=>progress.log(message,status)});await processNotifications(wvConfig);progress.log("✅ buildAndroidForTesting complete — project ready for gradlew test","success");return{success:true};}catch(error){progress.log("buildAndroidForTesting failed: "+error.message,"error");throw error;}}return{buildAndroidApp,buildAndroidForTesting,progress,WEBVIEW_CONFIG};}module.exports={createAndroidBuild,pwd};
1
+ "use strict";
2
+
3
+ const path = require("path");
4
+ const {
5
+ runCommand,
6
+ runInteractiveCommand
7
+ } = require("../utils.js");
8
+ const TerminalProgress = require("../TerminalProgress.js").default;
9
+ const {
10
+ composeAndroidPlugins
11
+ } = require("../pluginComposerAndroid.js");
12
+ const {
13
+ resolvePluginConfig,
14
+ resolveInternalPluginsRoot
15
+ } = require("../internalPluginUtils.js");
16
+ const createConfigPhase = require("./config.js");
17
+ const createAssetsPhase = require("./assets.js");
18
+ const createBuildPhase = require("./build.js");
19
+ const catalystCorePath = path.dirname(require.resolve("catalyst-core/package.json"));
20
+ const pwd = path.join(catalystCorePath, "dist/native");
21
+ const ANDROID_PACKAGE = "io.yourname.androidproject";
22
+ const steps = {
23
+ config: "Initialize Configuration",
24
+ tools: "Validate Android Tools",
25
+ emulator: "Check and Start Emulator",
26
+ copyAssets: "Copy Build Assets",
27
+ build: "Build and Install Application",
28
+ aab: "Build Signed AAB"
29
+ };
30
+ const progressConfig = {
31
+ titlePaddingTop: 2,
32
+ titlePaddingBottom: 1,
33
+ stepPaddingLeft: 4,
34
+ stepSpacing: 1,
35
+ errorPaddingLeft: 6,
36
+ bottomMargin: 2
37
+ };
38
+ function createAndroidBuild(config) {
39
+ const {
40
+ WEBVIEW_CONFIG,
41
+ BUILD_OUTPUT_PATH
42
+ } = config;
43
+ const configPath = `${process.cwd()}/config/config.json`;
44
+ const publicPath = `${process.cwd()}/public`;
45
+ const progress = new TerminalProgress(steps, "Catalyst Android Build", progressConfig);
46
+ const ctx = {
47
+ WEBVIEW_CONFIG,
48
+ BUILD_OUTPUT_PATH,
49
+ configPath,
50
+ publicPath,
51
+ pwd,
52
+ progress,
53
+ ANDROID_PACKAGE,
54
+ runCommand,
55
+ runInteractiveCommand
56
+ };
57
+ const {
58
+ initializeConfig,
59
+ validateAndroidTools
60
+ } = createConfigPhase(ctx);
61
+ const {
62
+ copyBuildAssets,
63
+ copySplashscreenAssets,
64
+ copyOfflinePage,
65
+ copyIconAssets,
66
+ configureAppName,
67
+ processNotifications
68
+ } = createAssetsPhase(ctx);
69
+ const {
70
+ detectPhysicalDevice,
71
+ testPhysicalDeviceInstallation,
72
+ handleEmulatorSetup,
73
+ buildApp,
74
+ launchApp,
75
+ moveApkToOutputPath,
76
+ buildSignedAAB
77
+ } = createBuildPhase(ctx);
78
+ async function buildAndroidApp() {
79
+ let androidConfig = null;
80
+ let targetDevice = null;
81
+ try {
82
+ progress.start("config");
83
+ const {
84
+ WEBVIEW_CONFIG: wvConfig,
85
+ BUILD_OUTPUT_PATH: bop
86
+ } = await initializeConfig();
87
+ androidConfig = wvConfig.android;
88
+ const buildType = androidConfig.buildType || "debug";
89
+ const buildOptimisation = !!androidConfig.buildOptimisation || false;
90
+ progress.complete("config");
91
+ progress.start("tools");
92
+ const {
93
+ ADB_PATH,
94
+ EMULATOR_PATH
95
+ } = validateAndroidTools(androidConfig);
96
+ progress.complete("tools");
97
+ if (buildType !== "release") {
98
+ progress.start("emulator");
99
+ const physicalDevice = await detectPhysicalDevice(ADB_PATH);
100
+ if (physicalDevice) {
101
+ progress.log(`Found physical device: ${physicalDevice.model} (${physicalDevice.id})`, "success");
102
+ const canInstallOnPhysical = await testPhysicalDeviceInstallation(ADB_PATH, physicalDevice.id);
103
+ if (canInstallOnPhysical) {
104
+ targetDevice = {
105
+ type: "physical",
106
+ id: physicalDevice.id,
107
+ model: physicalDevice.model
108
+ };
109
+ progress.log(`Using physical device: ${physicalDevice.model}`, "success");
110
+ } else {
111
+ progress.log("Physical device installation test failed, falling back to emulator", "warning");
112
+ targetDevice = await handleEmulatorSetup(ADB_PATH, EMULATOR_PATH, androidConfig);
113
+ }
114
+ } else {
115
+ targetDevice = await handleEmulatorSetup(ADB_PATH, EMULATOR_PATH, androidConfig);
116
+ }
117
+ progress.complete("emulator");
118
+ } else {
119
+ progress.log("Skipping device setup for release build", "info");
120
+ }
121
+ progress.start("copyAssets");
122
+ await copyBuildAssets(androidConfig, buildOptimisation);
123
+ await copySplashscreenAssets();
124
+ await copyOfflinePage();
125
+ await copyIconAssets();
126
+ await configureAppName(androidConfig);
127
+ const pluginConfig = resolvePluginConfig(wvConfig);
128
+ composeAndroidPlugins({
129
+ corePluginsRoot: resolveInternalPluginsRoot(catalystCorePath),
130
+ androidProjectPath: `${pwd}/androidProject`,
131
+ pluginConfig,
132
+ log: (message, status = "info") => progress.log(message, status)
133
+ });
134
+ await processNotifications(wvConfig);
135
+ progress.log(`Build optimization: ${buildOptimisation ? "Enabled" : "Disabled"}`, "info");
136
+ progress.complete("copyAssets");
137
+ let movedApkPath = null;
138
+ if (buildType === "release") {
139
+ progress.start("aab");
140
+ await buildSignedAAB(androidConfig);
141
+ progress.complete("aab");
142
+ movedApkPath = await moveApkToOutputPath(buildType, bop, androidConfig.appName);
143
+ } else {
144
+ progress.start("build");
145
+ await buildApp(ADB_PATH, androidConfig, buildOptimisation, targetDevice);
146
+ await launchApp(ADB_PATH, buildType, targetDevice);
147
+ progress.complete("build");
148
+ movedApkPath = await moveApkToOutputPath(buildType, bop, androidConfig.appName);
149
+ }
150
+ const summaryItems = ["Build completed successfully:", {
151
+ text: `Build Type: ${buildType}`,
152
+ indent: 1,
153
+ prefix: "├─ ",
154
+ color: "gray"
155
+ }, {
156
+ text: `SDK Path: ${androidConfig.sdkPath}`,
157
+ indent: 1,
158
+ prefix: "├─ ",
159
+ color: "gray"
160
+ }, {
161
+ text: `Build Optimization: ${buildOptimisation ? "Enabled" : "Disabled"}`,
162
+ indent: 1,
163
+ prefix: "├─ ",
164
+ color: "gray"
165
+ }];
166
+ if (buildType === "release") {
167
+ if (movedApkPath) {
168
+ summaryItems.push({
169
+ text: `APK Build Location: ${movedApkPath}`,
170
+ indent: 1,
171
+ prefix: "├─ ",
172
+ color: "green"
173
+ });
174
+ }
175
+ summaryItems.push({
176
+ text: `Output: Signed AAB generated in build-output/`,
177
+ indent: 1,
178
+ prefix: "└─ ",
179
+ color: "green"
180
+ });
181
+ } else {
182
+ if (movedApkPath) {
183
+ summaryItems.push({
184
+ text: `APK Build Location: ${movedApkPath}`,
185
+ indent: 1,
186
+ prefix: "├─ ",
187
+ color: "green"
188
+ });
189
+ }
190
+ if (targetDevice && targetDevice.type === "physical") {
191
+ summaryItems.push({
192
+ text: `Target Device: ${targetDevice.model} (Physical)`,
193
+ indent: 1,
194
+ prefix: "└─ ",
195
+ color: "green"
196
+ });
197
+ } else {
198
+ summaryItems.push({
199
+ text: `Target Device: ${androidConfig.emulatorName} (Emulator)`,
200
+ indent: 1,
201
+ prefix: "└─ ",
202
+ color: "gray"
203
+ });
204
+ }
205
+ }
206
+ progress.printTreeContent("Build Summary", summaryItems);
207
+ } catch (error) {
208
+ if (progress.currentStep) {
209
+ progress.fail(progress.currentStep.id, error.message);
210
+ const troubleshootingItems = ["Build failed. Please try the following steps:", {
211
+ text: "Check if Android SDK is properly configured",
212
+ indent: 1,
213
+ prefix: "├─ ",
214
+ color: "yellow"
215
+ }, {
216
+ text: "Verify build assets exist in the source directory",
217
+ indent: 1,
218
+ prefix: "├─ ",
219
+ color: "yellow"
220
+ }];
221
+ const buildType = androidConfig?.buildType || "debug";
222
+ if (buildType !== "release") {
223
+ if (error.message.includes("physical device") || error.message.includes("installation test")) {
224
+ troubleshootingItems.push("\nPhysical Device Issues:", {
225
+ text: "Enable Developer Options on your device",
226
+ indent: 1,
227
+ prefix: "├─ ",
228
+ color: "yellow"
229
+ }, {
230
+ text: "Enable USB Debugging in Developer Options",
231
+ indent: 1,
232
+ prefix: "├─ ",
233
+ color: "yellow"
234
+ }, {
235
+ text: 'Accept the "Allow USB Debugging" prompt on your device',
236
+ indent: 1,
237
+ prefix: "├─ ",
238
+ color: "yellow"
239
+ }, {
240
+ text: "Try disconnecting and reconnecting your device",
241
+ indent: 1,
242
+ prefix: "├─ ",
243
+ color: "yellow"
244
+ }, {
245
+ text: 'Check if "adb devices" shows your device as authorized',
246
+ indent: 1,
247
+ prefix: "├─ ",
248
+ color: "yellow"
249
+ });
250
+ }
251
+ troubleshootingItems.push({
252
+ text: "Verify that the emulator exists and is working",
253
+ indent: 1,
254
+ prefix: "├─ ",
255
+ color: "yellow"
256
+ }, {
257
+ text: "If using physical device, ensure it stays connected",
258
+ indent: 1,
259
+ prefix: "├─ ",
260
+ color: "yellow"
261
+ });
262
+ } else {
263
+ troubleshootingItems.push({
264
+ text: "Verify keystore configuration for release builds",
265
+ indent: 1,
266
+ prefix: "├─ ",
267
+ color: "yellow"
268
+ }, {
269
+ text: "Check that keystore passwords are properly set",
270
+ indent: 1,
271
+ prefix: "├─ ",
272
+ color: "yellow"
273
+ });
274
+ }
275
+ troubleshootingItems.push({
276
+ text: 'Run "npm run setupEmulator:android" to reconfigure Android settings',
277
+ indent: 1,
278
+ prefix: "└─ ",
279
+ color: "yellow"
280
+ }, "\nVerify Configuration:");
281
+ if (androidConfig) {
282
+ troubleshootingItems.push({
283
+ text: `Build Type: ${buildType}`,
284
+ indent: 1,
285
+ prefix: "├─ ",
286
+ color: "gray"
287
+ }, {
288
+ text: `Android SDK Path: ${androidConfig.sdkPath || "Not configured"}`,
289
+ indent: 1,
290
+ prefix: "├─ ",
291
+ color: "gray"
292
+ });
293
+ if (buildType !== "release") {
294
+ if (targetDevice) {
295
+ troubleshootingItems.push({
296
+ text: `Target Device: ${targetDevice.type === "physical" ? `${targetDevice.model} (Physical)` : `${androidConfig.emulatorName} (Emulator)`}`,
297
+ indent: 1,
298
+ prefix: "└─ ",
299
+ color: "gray"
300
+ });
301
+ } else {
302
+ troubleshootingItems.push({
303
+ text: `Selected Emulator: ${androidConfig.emulatorName || "Not configured"}`,
304
+ indent: 1,
305
+ prefix: "└─ ",
306
+ color: "gray"
307
+ });
308
+ }
309
+ } else {
310
+ troubleshootingItems.push({
311
+ text: `Output Path: ${androidConfig.outputPath || "build-output/"}`,
312
+ indent: 1,
313
+ prefix: "└─ ",
314
+ color: "gray"
315
+ });
316
+ }
317
+ } else {
318
+ troubleshootingItems.push({
319
+ text: "Configuration could not be loaded",
320
+ indent: 1,
321
+ prefix: "├─ ",
322
+ color: "red"
323
+ }, {
324
+ text: "Check if config/config.json exists and has valid Android configuration",
325
+ indent: 1,
326
+ prefix: "└─ ",
327
+ color: "red"
328
+ });
329
+ }
330
+ progress.printTreeContent("Troubleshooting Guide", troubleshootingItems);
331
+ }
332
+ throw error;
333
+ }
334
+ }
335
+ async function buildAndroidForTesting() {
336
+ try {
337
+ const {
338
+ WEBVIEW_CONFIG: wvConfig
339
+ } = await initializeConfig();
340
+ const androidConfig = wvConfig.android;
341
+ const buildOptimisation = !!androidConfig.buildOptimisation || false;
342
+ await copyBuildAssets(androidConfig, buildOptimisation);
343
+ await copySplashscreenAssets();
344
+ await copyOfflinePage();
345
+ await copyIconAssets();
346
+ await configureAppName(androidConfig);
347
+ const pluginConfig = resolvePluginConfig(wvConfig);
348
+ composeAndroidPlugins({
349
+ corePluginsRoot: resolveInternalPluginsRoot(catalystCorePath),
350
+ androidProjectPath: `${pwd}/androidProject`,
351
+ pluginConfig,
352
+ log: (message, status = "info") => progress.log(message, status)
353
+ });
354
+ await processNotifications(wvConfig);
355
+ progress.log("✅ buildAndroidForTesting complete — project ready for gradlew test", "success");
356
+ return {
357
+ success: true
358
+ };
359
+ } catch (error) {
360
+ progress.log("buildAndroidForTesting failed: " + error.message, "error");
361
+ throw error;
362
+ }
363
+ }
364
+ return {
365
+ buildAndroidApp,
366
+ buildAndroidForTesting,
367
+ progress,
368
+ WEBVIEW_CONFIG
369
+ };
370
+ }
371
+ module.exports = {
372
+ createAndroidBuild,
373
+ pwd
374
+ };
@@ -1,2 +1,34 @@
1
- "use strict";const{createAndroidBuild,pwd}=require("./buildAndroid/index.js");const{WEBVIEW_CONFIG,BUILD_OUTPUT_PATH}=require(`${process.cwd()}/config/config.json`);async function main(){const build=createAndroidBuild({WEBVIEW_CONFIG,BUILD_OUTPUT_PATH});const{buildAndroidApp}=build;try{await buildAndroidApp();}catch(error){process.exit(1);}process.exit(0);}if(require.main===module){main();}// Legacy re-exports for any tooling that imports from this file directly
2
- module.exports={createAndroidBuild,pwd};
1
+ "use strict";
2
+
3
+ const {
4
+ createAndroidBuild,
5
+ pwd
6
+ } = require("./buildAndroid/index.js");
7
+ const {
8
+ WEBVIEW_CONFIG,
9
+ BUILD_OUTPUT_PATH
10
+ } = require(`${process.cwd()}/config/config.json`);
11
+ async function main() {
12
+ const build = createAndroidBuild({
13
+ WEBVIEW_CONFIG,
14
+ BUILD_OUTPUT_PATH
15
+ });
16
+ const {
17
+ buildAndroidApp
18
+ } = build;
19
+ try {
20
+ await buildAndroidApp();
21
+ } catch (error) {
22
+ process.exit(1);
23
+ }
24
+ process.exit(0);
25
+ }
26
+ if (require.main === module) {
27
+ main();
28
+ }
29
+
30
+ // Legacy re-exports for any tooling that imports from this file directly
31
+ module.exports = {
32
+ createAndroidBuild,
33
+ pwd
34
+ };
@@ -1,2 +1,62 @@
1
- "use strict";const path=require("path");const{createIosBuild,pwd}=require("./buildIos/index.js");const{composeIosPlugins}=require("./pluginComposerIos.js");const{resolveInternalPluginsRoot,resolvePluginConfig}=require("./internalPluginUtils.js");const catalystCorePath=path.dirname(require.resolve("catalyst-core/package.json"));const{WEBVIEW_CONFIG,BUILD_OUTPUT_PATH}=require(`${process.cwd()}/config/config.json`);async function main(){const build=createIosBuild({WEBVIEW_CONFIG,BUILD_OUTPUT_PATH});const{progress,generateConfigConstants,updateInfoPlist,updateEntitlements,syncPluginResources,buildForIOS,PROJECT_DIR}=build;try{progress.log("Starting build process...","info");const pluginConfig=resolvePluginConfig(WEBVIEW_CONFIG);const pluginComposition=composeIosPlugins({corePluginsRoot:resolveInternalPluginsRoot(catalystCorePath),iosProjectPath:PROJECT_DIR,pluginConfig,log:(message,status="info")=>progress.log(message,status)});await generateConfigConstants();await updateInfoPlist(pluginComposition);await updateEntitlements(pluginComposition);await syncPluginResources(pluginComposition);await buildForIOS(pluginComposition);}catch(error){progress.log("Build failed: "+error.message,"error");process.exit(1);}process.exit(0);}if(require.main===module){main();}// Legacy re-exports for any tooling that imports from this file directly
2
- module.exports={createIosBuild,pwd};
1
+ "use strict";
2
+
3
+ const path = require("path");
4
+ const {
5
+ createIosBuild,
6
+ pwd
7
+ } = require("./buildIos/index.js");
8
+ const {
9
+ composeIosPlugins
10
+ } = require("./pluginComposerIos.js");
11
+ const {
12
+ resolveInternalPluginsRoot,
13
+ resolvePluginConfig
14
+ } = require("./internalPluginUtils.js");
15
+ const catalystCorePath = path.dirname(require.resolve("catalyst-core/package.json"));
16
+ const {
17
+ WEBVIEW_CONFIG,
18
+ BUILD_OUTPUT_PATH
19
+ } = require(`${process.cwd()}/config/config.json`);
20
+ async function main() {
21
+ const build = createIosBuild({
22
+ WEBVIEW_CONFIG,
23
+ BUILD_OUTPUT_PATH
24
+ });
25
+ const {
26
+ progress,
27
+ generateConfigConstants,
28
+ updateInfoPlist,
29
+ updateEntitlements,
30
+ syncPluginResources,
31
+ buildForIOS,
32
+ PROJECT_DIR
33
+ } = build;
34
+ try {
35
+ progress.log("Starting build process...", "info");
36
+ const pluginConfig = resolvePluginConfig(WEBVIEW_CONFIG);
37
+ const pluginComposition = composeIosPlugins({
38
+ corePluginsRoot: resolveInternalPluginsRoot(catalystCorePath),
39
+ iosProjectPath: PROJECT_DIR,
40
+ pluginConfig,
41
+ log: (message, status = "info") => progress.log(message, status)
42
+ });
43
+ await generateConfigConstants();
44
+ await updateInfoPlist(pluginComposition);
45
+ await updateEntitlements(pluginComposition);
46
+ await syncPluginResources(pluginComposition);
47
+ await buildForIOS(pluginComposition);
48
+ } catch (error) {
49
+ progress.log("Build failed: " + error.message, "error");
50
+ process.exit(1);
51
+ }
52
+ process.exit(0);
53
+ }
54
+ if (require.main === module) {
55
+ main();
56
+ }
57
+
58
+ // Legacy re-exports for any tooling that imports from this file directly
59
+ module.exports = {
60
+ createIosBuild,
61
+ pwd
62
+ };