catalyst-core 0.1.0-canary.1 → 0.1.0-canary.2
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/changelog.md +5 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/plugins/LegacyGoogleSignInPlugin.kt +176 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/plugins/README.md +97 -0
- package/dist/native/androidSetup.js +1 -1
- package/dist/native/buildAppAndroid.js +6 -3
- package/dist/native/buildAppIos.js +1 -1
- package/package.json +2 -1
package/changelog.md
CHANGED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
package io.yourname.androidproject.plugins
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.content.Intent
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import android.webkit.WebView
|
|
7
|
+
import androidx.activity.result.ActivityResultLauncher
|
|
8
|
+
import androidx.activity.result.contract.ActivityResultContracts
|
|
9
|
+
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
|
10
|
+
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
|
11
|
+
import com.google.android.gms.auth.api.signin.GoogleSignInClient
|
|
12
|
+
import com.google.android.gms.auth.api.signin.GoogleSignInOptions as LegacyGoogleSignInOptions
|
|
13
|
+
import com.google.android.gms.common.api.ApiException
|
|
14
|
+
import io.yourname.androidproject.utils.BridgeUtils
|
|
15
|
+
import org.json.JSONObject
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Legacy Google Sign-In Plugin
|
|
19
|
+
*
|
|
20
|
+
* DEPRECATION NOTICE: This plugin uses the deprecated Google Sign-In SDK.
|
|
21
|
+
* Google is removing this SDK from Play Services in 2025.
|
|
22
|
+
*
|
|
23
|
+
* Purpose: Provides serverAuthCode support for specific users who need
|
|
24
|
+
* authorization codes to exchange for access/refresh tokens on backend.
|
|
25
|
+
*
|
|
26
|
+
* Migration Path: Once backend supports ID token exchange for access tokens,
|
|
27
|
+
* this plugin can be removed by:
|
|
28
|
+
* 1. Delete this file
|
|
29
|
+
* 2. Remove legacy dependency from build.gradle.kts
|
|
30
|
+
* 3. Remove plugin registration from NativeBridge
|
|
31
|
+
*
|
|
32
|
+
* @see <a href="https://developer.android.com/identity/sign-in/legacy-gsi-migration">Legacy GSI Migration Guide</a>
|
|
33
|
+
*/
|
|
34
|
+
class LegacyGoogleSignInPlugin(
|
|
35
|
+
private val activity: Activity,
|
|
36
|
+
private val webView: WebView
|
|
37
|
+
) {
|
|
38
|
+
private var signInClient: GoogleSignInClient? = null
|
|
39
|
+
private var isInProgress: Boolean = false
|
|
40
|
+
private lateinit var launcher: ActivityResultLauncher<Intent>
|
|
41
|
+
|
|
42
|
+
companion object {
|
|
43
|
+
private const val TAG = "LegacyGoogleSignInPlugin"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Configuration for legacy Google Sign-In request
|
|
48
|
+
*/
|
|
49
|
+
data class SignInConfig(
|
|
50
|
+
val clientId: String
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Callback interface for sign-in results
|
|
55
|
+
*/
|
|
56
|
+
interface SignInCallback {
|
|
57
|
+
fun onSuccess(result: JSONObject)
|
|
58
|
+
fun onCancelled()
|
|
59
|
+
fun onError(error: String)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private var currentCallback: SignInCallback? = null
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Initialize the plugin
|
|
66
|
+
* Must be called during Activity initialization
|
|
67
|
+
*/
|
|
68
|
+
fun initialize(launcher: ActivityResultLauncher<Intent>) {
|
|
69
|
+
this.launcher = launcher
|
|
70
|
+
Log.d(TAG, "Legacy Google Sign-In Plugin initialized")
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Start legacy Google Sign-In flow
|
|
75
|
+
*/
|
|
76
|
+
fun signIn(config: SignInConfig, callback: SignInCallback) {
|
|
77
|
+
if (isInProgress) {
|
|
78
|
+
callback.onError("Sign-in already in progress")
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
isInProgress = true
|
|
83
|
+
currentCallback = callback
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
// Build legacy Google Sign-In options
|
|
87
|
+
val gso = LegacyGoogleSignInOptions.Builder(LegacyGoogleSignInOptions.DEFAULT_SIGN_IN)
|
|
88
|
+
.requestIdToken(config.clientId)
|
|
89
|
+
.requestServerAuthCode(config.clientId)
|
|
90
|
+
.requestEmail()
|
|
91
|
+
.requestProfile()
|
|
92
|
+
.build()
|
|
93
|
+
signInClient = GoogleSignIn.getClient(activity, gso)
|
|
94
|
+
|
|
95
|
+
Log.d(TAG, "Launching legacy Google Sign-In for serverAuthCode")
|
|
96
|
+
val signInIntent = signInClient?.signInIntent
|
|
97
|
+
launcher.launch(signInIntent)
|
|
98
|
+
} catch (e: Exception) {
|
|
99
|
+
isInProgress = false
|
|
100
|
+
currentCallback = null
|
|
101
|
+
callback.onError("Failed to start sign-in: ${e.message}")
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Handle activity result from Google Sign-In
|
|
107
|
+
* Call this from ActivityResultLauncher callback
|
|
108
|
+
*/
|
|
109
|
+
fun handleActivityResult(resultCode: Int, data: Intent?) {
|
|
110
|
+
if (resultCode == Activity.RESULT_OK) {
|
|
111
|
+
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
|
|
112
|
+
try {
|
|
113
|
+
val account = task.getResult(ApiException::class.java)
|
|
114
|
+
handleSignInSuccess(account)
|
|
115
|
+
} catch (e: ApiException) {
|
|
116
|
+
handleSignInError(e)
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
handleSignInCancelled()
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private fun handleSignInSuccess(account: GoogleSignInAccount) {
|
|
124
|
+
Log.d(TAG, "Legacy Google Sign-In successful")
|
|
125
|
+
|
|
126
|
+
val payload = JSONObject().apply {
|
|
127
|
+
account.idToken?.let { put("idToken", it) }
|
|
128
|
+
account.email?.let { put("email", it) }
|
|
129
|
+
account.displayName?.let { put("name", it) }
|
|
130
|
+
account.photoUrl?.toString()?.let { put("photoUrl", it) }
|
|
131
|
+
account.givenName?.let { put("givenName", it) }
|
|
132
|
+
account.familyName?.let { put("familyName", it) }
|
|
133
|
+
|
|
134
|
+
// This is the key - serverAuthCode from legacy SDK
|
|
135
|
+
account.serverAuthCode?.let { put("serverAuthCode", it) }
|
|
136
|
+
|
|
137
|
+
put("provider", "google")
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
isInProgress = false
|
|
141
|
+
val callback = currentCallback
|
|
142
|
+
currentCallback = null
|
|
143
|
+
callback?.onSuccess(payload)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private fun handleSignInError(error: ApiException) {
|
|
147
|
+
Log.e(TAG, "Legacy Google Sign-In failed: ${error.message}", error)
|
|
148
|
+
isInProgress = false
|
|
149
|
+
val callback = currentCallback
|
|
150
|
+
currentCallback = null
|
|
151
|
+
callback?.onError("Sign-in failed: ${error.message}")
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private fun handleSignInCancelled() {
|
|
155
|
+
Log.d(TAG, "Legacy Google Sign-In cancelled")
|
|
156
|
+
isInProgress = false
|
|
157
|
+
val callback = currentCallback
|
|
158
|
+
currentCallback = null
|
|
159
|
+
callback?.onCancelled()
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Check if sign-in is currently in progress
|
|
164
|
+
*/
|
|
165
|
+
fun isSignInInProgress(): Boolean = isInProgress
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Cleanup resources
|
|
169
|
+
*/
|
|
170
|
+
fun cleanup() {
|
|
171
|
+
signInClient = null
|
|
172
|
+
currentCallback = null
|
|
173
|
+
isInProgress = false
|
|
174
|
+
Log.d(TAG, "Legacy Google Sign-In Plugin cleaned up")
|
|
175
|
+
}
|
|
176
|
+
}
|
package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/plugins/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Plugins Directory
|
|
2
|
+
|
|
3
|
+
This directory contains optional plugin modules that extend NativeBridge functionality with features that may be deprecated or need to be conditionally included.
|
|
4
|
+
|
|
5
|
+
## LegacyGoogleSignInPlugin
|
|
6
|
+
|
|
7
|
+
**Status:** ⚠️ DEPRECATED - Will be removed when backend supports ID token exchange
|
|
8
|
+
|
|
9
|
+
### Purpose
|
|
10
|
+
Provides `serverAuthCode` support for Google Sign-In using the deprecated Google Sign-In SDK. The serverAuthCode can be exchanged on your backend for access and refresh tokens.
|
|
11
|
+
|
|
12
|
+
### Why Plugin Architecture?
|
|
13
|
+
The legacy Google Sign-In SDK is being removed from Google Play Services in 2025. By isolating this in a plugin:
|
|
14
|
+
- Easy to remove when no longer needed
|
|
15
|
+
- Clear separation from modern Credential Manager implementation
|
|
16
|
+
- Single point of maintenance
|
|
17
|
+
- Self-documenting deprecation
|
|
18
|
+
|
|
19
|
+
### Migration Timeline
|
|
20
|
+
|
|
21
|
+
1. **Current State** (Using Plugin)
|
|
22
|
+
- Modern users: Credential Manager (no serverAuthCode)
|
|
23
|
+
- Legacy users: Plugin provides serverAuthCode via deprecated SDK
|
|
24
|
+
|
|
25
|
+
2. **Future State** (Remove Plugin)
|
|
26
|
+
- All users: Credential Manager with ID token
|
|
27
|
+
- Backend: Exchange ID token for access tokens
|
|
28
|
+
- Plugin: Delete this file + remove dependency
|
|
29
|
+
|
|
30
|
+
### Removal Checklist
|
|
31
|
+
|
|
32
|
+
When you're ready to remove the legacy Google Sign-In support:
|
|
33
|
+
|
|
34
|
+
#### Step 1: Update Backend
|
|
35
|
+
- [ ] Implement ID token validation endpoint
|
|
36
|
+
- [ ] Add token exchange logic (ID token → access/refresh tokens)
|
|
37
|
+
- [ ] Test with modern Credential Manager flow
|
|
38
|
+
|
|
39
|
+
#### Step 2: Update Frontend
|
|
40
|
+
- [ ] Remove `requestServerAuthCode` flag from all sign-in calls
|
|
41
|
+
- [ ] Update backend calls to use ID token instead of serverAuthCode
|
|
42
|
+
|
|
43
|
+
#### Step 3: Remove Plugin (Android)
|
|
44
|
+
- [ ] Delete `LegacyGoogleSignInPlugin.kt` file
|
|
45
|
+
- [ ] Remove legacy dependency from `build.gradle.kts`:
|
|
46
|
+
```kotlin
|
|
47
|
+
// DELETE THIS LINE:
|
|
48
|
+
implementation("com.google.android.gms:play-services-auth:21.0.0")
|
|
49
|
+
```
|
|
50
|
+
- [ ] In `NativeBridge.kt`:
|
|
51
|
+
- Remove `legacyGoogleSignInPlugin` property
|
|
52
|
+
- Remove `legacyGoogleSignInLauncher`
|
|
53
|
+
- Remove `initializeLegacyGoogleSignInLauncher()` call
|
|
54
|
+
- Remove `useLegacyGoogleSignIn()` method
|
|
55
|
+
- Remove plugin cleanup in `cleanup()`
|
|
56
|
+
- Remove legacy routing in `launchGoogleSignIn()`
|
|
57
|
+
- [ ] Remove `requestServerAuthCode` field from `GoogleSignInOptions`
|
|
58
|
+
|
|
59
|
+
#### Step 4: Test
|
|
60
|
+
- [ ] Test sign-in flow with modern Credential Manager
|
|
61
|
+
- [ ] Verify backend receives and validates ID tokens
|
|
62
|
+
- [ ] Verify token exchange works correctly
|
|
63
|
+
|
|
64
|
+
### Usage (Current)
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
// In JavaScript
|
|
68
|
+
signIn({
|
|
69
|
+
clientId: "YOUR_WEB_CLIENT_ID",
|
|
70
|
+
requestServerAuthCode: true // Triggers plugin
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Returns:
|
|
74
|
+
{
|
|
75
|
+
idToken: "...",
|
|
76
|
+
email: "...",
|
|
77
|
+
serverAuthCode: "..." // From plugin
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Architecture
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
NativeBridge
|
|
85
|
+
├─ Modern Flow: CredentialManager (default)
|
|
86
|
+
└─ Legacy Flow: LegacyGoogleSignInPlugin (conditional)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The plugin is:
|
|
90
|
+
- ✅ Isolated in separate file
|
|
91
|
+
- ✅ Clearly marked as deprecated
|
|
92
|
+
- ✅ Easy to remove (no entanglement with main code)
|
|
93
|
+
- ✅ Self-documenting with removal checklist
|
|
94
|
+
|
|
95
|
+
### References
|
|
96
|
+
- [Google Sign-In Migration Guide](https://developer.android.com/identity/sign-in/legacy-gsi-migration)
|
|
97
|
+
- [Credential Manager Documentation](https://developer.android.com/identity/sign-in/credential-manager-siwg)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var _fs=_interopRequireDefault(require("fs"));var _child_process=require("child_process");var _utils=require("./utils.js");var _TerminalProgress=_interopRequireDefault(require("./TerminalProgress.js"));var _setupServer=require("./setupServer.js");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e};}const
|
|
1
|
+
"use strict";var _fs=_interopRequireDefault(require("fs"));var _path=_interopRequireDefault(require("path"));var _child_process=require("child_process");var _utils=require("./utils.js");var _TerminalProgress=_interopRequireDefault(require("./TerminalProgress.js"));var _setupServer=require("./setupServer.js");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e};}const catalystCorePath=_path.default.dirname(require.resolve("catalyst-core/package.json"));const pwd=_path.default.join(catalystCorePath,"dist/native");const configPath=`${process.env.PWD}/config/config.json`;const steps={java:"Check Java Environment",config:"Initialize Configuration",androidTools:"Validate Android Tools",emulator:"Configure Android Emulator",properties:"Update Local Properties",saveConfig:"Save Configuration",setupServer:"Setup Server"};const progressPaddingConfig={titlePaddingTop:2,titlePaddingBottom:1,stepPaddingLeft:4,stepSpacing:1,errorPaddingLeft:6,bottomMargin:2};const progress=new _TerminalProgress.default(steps,"Catalyst Universal Android Setup",progressPaddingConfig);async function checkJavaInstallation(){try{(0,_utils.runCommand)("java -version");(0,_utils.runCommand)("javac -version");progress.log("Java is installed and configured","success");return true;}catch(error){progress.log("Java installation not found or not properly configured","error");return false;}}async function installJava(){progress.log("Installing Java (Zulu JDK 17)...");try{try{(0,_utils.runCommand)("brew --version");}catch(error){throw new Error("Homebrew is required but not installed. Please install Homebrew first.");}const javaHome="/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home";// Try installing Java
|
|
2
2
|
try{await(0,_utils.runCommand)("brew install --cask zulu@17");}catch(error){if(error.message.includes("already installed")){progress.log("Attempting to reinstall Java...","info");try{await(0,_utils.runCommand)("brew reinstall --cask zulu@17");}catch(reinstallError){throw new Error(`Failed to reinstall Java: ${reinstallError.message}. Please run 'brew reinstall --cask zulu@17' manually.`);}}else{throw error;}}// Verify Java installation
|
|
3
3
|
if(!_fs.default.existsSync(javaHome)){throw new Error(`Java installation not found at ${javaHome}. Please verify the installation manually.`);}// Set up environment variables
|
|
4
4
|
const homeDir=process.env.HOME;const shellProfile=`${homeDir}/.zshrc`;const exportCommand=`\n# Java Configuration\nexport JAVA_HOME=${javaHome}\nexport PATH=$JAVA_HOME/bin:$PATH\n`;try{_fs.default.appendFileSync(shellProfile,exportCommand);}catch(error){throw new Error(`Failed to update ${shellProfile}: ${error.message}. Please add the following lines manually:\n${exportCommand}`);}// Set for current process
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-extra-semi */"use strict";var _renameAndroidProject=require("./renameAndroidProject.js");var _child_process=require("child_process");var _fs=_interopRequireDefault(require("fs"));var _path=_interopRequireDefault(require("path"));var _utils=require("./utils.js");var _TerminalProgress=_interopRequireDefault(require("./TerminalProgress.js"));// Import the AAB builder
|
|
2
|
-
function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e};}const configPath=`${process.env.PWD}/config/config.json`;const publicPath=`${process.env.PWD}/public`;const
|
|
2
|
+
function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e};}const configPath=`${process.env.PWD}/config/config.json`;const publicPath=`${process.env.PWD}/public`;const catalystCorePath=_path.default.dirname(require.resolve("catalyst-core/package.json"));const pwd=_path.default.join(catalystCorePath,"dist/native");const ANDROID_PACKAGE="io.yourname.androidproject";// Default values for AAB building
|
|
3
3
|
const DEFAULT_PROJECT_PATH=`${pwd}/androidProject`;const DEFAULT_DEPLOYMENT_PATH="./deployment";const DEFAULT_OLD_PROJECT_NAME="androidProject";// Use actual project name in catalyst
|
|
4
4
|
const DEFAULT_OVERWRITE_EXISTING=true;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};const progress=new _TerminalProgress.default(steps,"Catalyst Android Build",progressConfig);async function initializeConfig(){const configFile=_fs.default.readFileSync(configPath,"utf8");const config=JSON.parse(configFile);const{WEBVIEW_CONFIG,BUILD_OUTPUT_PATH}=config;if(!WEBVIEW_CONFIG||Object.keys(WEBVIEW_CONFIG).length===0){throw new Error("WebView Config missing in "+configPath);}if(!WEBVIEW_CONFIG.android){throw new Error("Android config missing in WebView Config");}// Log build type information
|
|
5
5
|
const buildType=WEBVIEW_CONFIG.android.buildType||"debug";progress.log(`Build Type: ${buildType}`,"info");if(buildType==="release"){progress.log("Release build detected - AAB will be generated","info");}return{WEBVIEW_CONFIG,BUILD_OUTPUT_PATH};}function validateAndroidTools(androidConfig){const ANDROID_SDK=androidConfig.sdkPath;const ADB_PATH=`${ANDROID_SDK}/platform-tools/adb`;const EMULATOR_PATH=`${ANDROID_SDK}/emulator/emulator`;progress.log("Validating Android tools...","info");if(!ANDROID_SDK){throw new Error("Android SDK path is not configured");}if(!_fs.default.existsSync(ANDROID_SDK)){throw new Error(`Android SDK path does not exist: ${ANDROID_SDK}`);}if(!_fs.default.existsSync(ADB_PATH)){throw new Error(`ADB not found at: ${ADB_PATH}`);}try{;(0,_utils.runCommand)(`${ADB_PATH} version`);progress.log("ADB validation successful","success");}catch(error){throw new Error(`ADB is not working properly: ${error.message}`);}// Skip emulator validation for release builds
|
|
@@ -52,10 +52,13 @@ await addNotificationPermissions();await generateNotificationResources(WEBVIEW_C
|
|
|
52
52
|
<!-- Firebase default notification configuration -->
|
|
53
53
|
<meta-data
|
|
54
54
|
android:name="com.google.firebase.messaging.default_notification_channel_id"
|
|
55
|
-
android:value="
|
|
55
|
+
android:value="default" />
|
|
56
56
|
<meta-data
|
|
57
57
|
android:name="com.google.firebase.messaging.default_notification_icon"
|
|
58
58
|
android:resource="@drawable/ic_notification" />
|
|
59
|
+
<meta-data
|
|
60
|
+
android:name="com.google.firebase.messaging.default_notification_sound"
|
|
61
|
+
android:resource="@raw/notification_sound_default" />
|
|
59
62
|
|
|
60
63
|
<!-- Push Notification Service -->
|
|
61
64
|
<service
|
|
@@ -88,7 +91,7 @@ async function cleanupNotificationPermissions(){try{const manifestPath=`${pwd}/a
|
|
|
88
91
|
const notificationPermissions=["android.permission.POST_NOTIFICATIONS","android.permission.VIBRATE","android.permission.WAKE_LOCK","android.permission.RECEIVE_BOOT_COMPLETED"];notificationPermissions.forEach(permission=>{const permissionRegex=new RegExp(`\\s*<uses-permission android:name="${permission}"[^>]*/>`,"g");manifestContent=manifestContent.replace(permissionRegex,"");});_fs.default.writeFileSync(manifestPath,manifestContent);}catch(error){// Don't throw error for cleanup operations, just log
|
|
89
92
|
progress.log(`Warning: Error cleaning notification permissions: ${error.message}`,"warning");}}async function cleanupNotificationResources(){try{const colorsPath=`${pwd}/androidProject/app/src/main/res/values/colors.xml`;let colorsContent=_fs.default.readFileSync(colorsPath,"utf8");// Remove notification color
|
|
90
93
|
const existingColorLine=colorsContent.split("\n").find(line=>line.includes('name="notification_color"'));if(existingColorLine){colorsContent=colorsContent.replace(existingColorLine,"");_fs.default.writeFileSync(colorsPath,colorsContent);}}catch(error){progress.log(`Warning: Error cleaning notification resources: ${error.message}`,"warning");}}async function cleanupNotificationMetadata(){try{const manifestPath=`${pwd}/androidProject/app/src/main/AndroidManifest.xml`;let manifestContent=_fs.default.readFileSync(manifestPath,"utf8");// Remove notification metadata entries
|
|
91
|
-
const metadataNames=["default_notification_channel_id","default_notification_icon","default_notification_color","com.google.firebase.messaging.default_notification_channel_id","com.google.firebase.messaging.default_notification_icon"];metadataNames.forEach(metadataName=>{// Remove the meta-data block including comments
|
|
94
|
+
const metadataNames=["default_notification_channel_id","default_notification_icon","default_notification_color","com.google.firebase.messaging.default_notification_channel_id","com.google.firebase.messaging.default_notification_icon","com.google.firebase.messaging.default_notification_sound"];metadataNames.forEach(metadataName=>{// Remove the meta-data block including comments
|
|
92
95
|
const metadataRegex=new RegExp(`\\s*<!--[^>]*notification[^>]*-->\\s*<meta-data[^>]*android:name="${metadataName}"[\\s\\S]*?/>|\\s*<meta-data[^>]*android:name="${metadataName}"[\\s\\S]*?/>`,"gi");manifestContent=manifestContent.replace(metadataRegex,"");});// Remove Push Notification Service
|
|
93
96
|
const serviceRegex=/\s*<!--\s*Push Notification Service\s*-->\s*<service[^>]*android:name="[^"]*PushNotificationUtils"[\s\S]*?<\/service>/gi;manifestContent=manifestContent.replace(serviceRegex,"");// Clean up any standalone notification comments
|
|
94
97
|
manifestContent=manifestContent.replace(/\s*<!--\s*Default notification configuration\s*-->/gi,"");manifestContent=manifestContent.replace(/\s*<!--\s*Firebase default notification configuration\s*-->/gi,"");manifestContent=manifestContent.replace(/\s*<!--\s*Push Notification Service\s*-->/gi,"");_fs.default.writeFileSync(manifestPath,manifestContent);}catch(error){progress.log(`Warning: Error cleaning notification metadata: ${error.message}`,"warning");}}async function cleanupNotificationAssets(){try{const destPath=`${pwd}/androidProject/app/src/main/res`;const imageFormats=["png","jpg","jpeg","gif","bmp","svg","webp","xml"];const audioFormats=["mp3","wav","ogg"];// Define notification icons to clean up
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";const{exec,execSync}=require("child_process");const fs=require("fs");const path=require("path");const TerminalProgress=require("./TerminalProgress.js").default;const crypto=require("crypto");const
|
|
1
|
+
"use strict";const{exec,execSync}=require("child_process");const fs=require("fs");const path=require("path");const TerminalProgress=require("./TerminalProgress.js").default;const crypto=require("crypto");const catalystCorePath=path.dirname(require.resolve("catalyst-core/package.json"));const pwd=path.join(catalystCorePath,"dist/native");const{WEBVIEW_CONFIG,BUILD_OUTPUT_PATH}=require(`${process.env.PWD}/config/config.json`);// Configuration constants
|
|
2
2
|
const iosConfig=WEBVIEW_CONFIG.ios;const protocol=WEBVIEW_CONFIG.useHttps?"https":"http";const ip=WEBVIEW_CONFIG.LOCAL_IP||"localhost";const port=WEBVIEW_CONFIG.port?WEBVIEW_CONFIG.useHttps?443:WEBVIEW_CONFIG.port:null;let url=port?`${protocol}://${ip}:${port}`:`${protocol}://${ip}`;const PUBLIC_PATH=`${process.env.PWD}/public`;const PROJECT_DIR=`${pwd}/iosnativeWebView`;const SCHEME_NAME="iosnativeWebView";const APP_BUNDLE_ID=iosConfig.appBundleId||"com.debug.webview";const PROJECT_NAME=path.basename(PROJECT_DIR);const IPHONE_MODEL=iosConfig.simulatorName;const GOOGLE_SERVICES_FILENAME="GoogleService-Info.plist";function generateProjectObjectId(identifier,suffix=""){return crypto.createHash("md5").update(`${identifier}:${suffix}`).digest("hex").substring(0,24).toUpperCase();}function getXcodeProjectFilePath(){return path.join(PROJECT_DIR,`${PROJECT_NAME}.xcodeproj`,"project.pbxproj");}// Define build steps for progress tracking
|
|
3
3
|
const steps={config:"Generating Required Configuration for build",deviceDetection:"Detecting Physical Device",launchSimulator:"Launch iOS Simulator",clean:"Clean Build Artifacts",assets:"Process Notification Assets",build:"Build IOS Project",findApp:"Locate Built Application",install:"Install Application",launch:"Launch Application"};// Configure progress display
|
|
4
4
|
const progressConfig={titlePaddingTop:2,titlePaddingBottom:1,stepPaddingLeft:4,stepSpacing:1,errorPaddingLeft:6,bottomMargin:2};const progress=new TerminalProgress(steps,"Catalyst iOS Build",progressConfig);// Utility function to run shell commands
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "catalyst-core",
|
|
3
|
-
"version": "0.1.0-canary.
|
|
3
|
+
"version": "0.1.0-canary.2",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"description": "Web framework that provides great performance out of the box",
|
|
6
6
|
"bin": {
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"exports": {
|
|
28
28
|
".": "./dist/index.js",
|
|
29
|
+
"./package.json": "./package.json",
|
|
29
30
|
"./logger": "./dist/logger.js",
|
|
30
31
|
"./caching": "./dist/caching.js",
|
|
31
32
|
"./router/ClientRouter": "./dist/router/ClientRouter.js",
|