Skip to content
This repository was archived by the owner on May 1, 2026. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { addChannelInternal } from './channel/add'
import { createKeyInternal } from './key'
import { doLoginExists, loginInternal } from './login'
import { createSupabaseClient, findBuildCommandForProjectType, findMainFile, findMainFileForProjectType, findProjectType, findRoot, findSavedKey, getAllPackagesDependencies, getAppId, getBundleVersion, getConfig, getInstalledVersion, getLocalConfig, getOrganization, getPackageScripts, getPMAndCommand, PACKNAME, projectIsMonorepo, promptAndSyncCapacitor, updateConfigbyKey, updateConfigUpdater, validateIosUpdaterSync, verifyUser } from './utils'
import { writeConfig } from './config'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix import ordering to resolve ESLint error.

The static analysis tool reports: Expected "./config" to come before "./utils" (perfectionist/sort-imports). Move the writeConfig import above the ./utils import.

♻️ Proposed fix
+import { writeConfig } from './config'
 import { checkAlerts } from './api/update'
 import { addAppInternal } from './app/add'
 ...
 import { checkAlerts, ... } from './utils'
-import { writeConfig } from './config'
🧰 Tools
🪛 ESLint

[error] 19-19: Expected "./config" to come before "./utils".

(perfectionist/sort-imports)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/init.ts` at line 19, Move the import of writeConfig so it appears before
the import from './utils' to satisfy the perfectionist/sort-imports rule;
specifically, adjust the import ordering in src/init.ts so the statement
importing writeConfig from './config' is placed above the import that references
'./utils' (preserving existing named/default specifiers and spacing).


interface SuperOptions extends Options {
local: boolean
Expand Down Expand Up @@ -169,6 +170,24 @@ async function markStep(orgId: string, apikey: string, step: string, appId: stri
return markSnag('onboarding-v2', orgId, apikey, `onboarding-step-${step}`, appId)
}

/**
* Save the app ID to the capacitor config file.
*/
async function saveAppIdToCapacitorConfig(appId: string) {
try {
const extConfig = await getConfig()
if (extConfig?.config) {
extConfig.config.appId = appId
await writeConfig('CapacitorUpdater', extConfig, true)
pLog.info(`💾 Saved new app ID "${appId}" to capacitor config`)
}
Comment on lines +179 to +183
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Silent skip when extConfig.config is falsy — add a fallback warning.

If getConfig() somehow returns a value with a falsy .config (the ?. guard implies this is a considered possibility), the save is silently skipped and the user receives no feedback. This is inconsistent with the catch block, which does warn and guide the user.

♻️ Proposed fix
     const extConfig = await getConfig()
     if (extConfig?.config) {
       extConfig.config.appId = appId
       await writeConfig('CapacitorUpdater', extConfig, true)
       pLog.info(`💾 Saved new app ID "${appId}" to capacitor config`)
     }
+    else {
+      pLog.warn(`⚠️  Could not find capacitor config to update. Please set appId to "${appId}" manually.`)
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (extConfig?.config) {
extConfig.config.appId = appId
await writeConfig('CapacitorUpdater', extConfig, true)
pLog.info(`💾 Saved new app ID "${appId}" to capacitor config`)
}
if (extConfig?.config) {
extConfig.config.appId = appId
await writeConfig('CapacitorUpdater', extConfig, true)
pLog.info(`💾 Saved new app ID "${appId}" to capacitor config`)
}
else {
pLog.warn(`⚠️ Could not find capacitor config to update. Please set appId to "${appId}" manually.`)
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/init.ts` around lines 179 - 183, The current code silently skips saving
when extConfig.config is falsy; update the block around extConfig?.config to add
an else branch that calls pLog.warn (or pLog.info with warning) to inform the
user that the capacitor config was not found/usable and that the appId was not
saved, and include guidance on how to fix or retry; modify the logic that calls
writeConfig('CapacitorUpdater', extConfig, true) so it only runs when extConfig
&& extConfig.config, and emit the warning otherwise to mirror the existing catch
behavior (referencing extConfig, extConfig.config, writeConfig, and pLog).

}
catch (err) {
pLog.warn(`⚠️ Could not save app ID to capacitor config: ${err}`)
pLog.info(` You may need to manually update your capacitor.config file with the new app ID: ${appId}`)
}
}

function stopForBrokenIosSync(platformRunner: string, details: string[]): never {
pLog.error('Capgo iOS dependency sync verification failed.')
for (const detail of details) {
Expand Down Expand Up @@ -386,6 +405,9 @@ async function addAppStep(organization: Organization, apikey: string, appId: str
currentAppId = suggestions[suggestionIndex]
}

// Save the new app ID to capacitor config
await saveAppIdToCapacitorConfig(currentAppId)
Comment on lines +408 to +409
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Save app ID only after app creation succeeds

This writes currentAppId to capacitor.config.* before addAppInternal confirms the app was actually created, so a later non-already exist failure (re-thrown at the bottom of the catch) leaves local config pointing to an unregistered app ID. That recreates the local/backend mismatch this change is trying to prevent in failure paths; persisting the ID should happen only after the add call succeeds.

Useful? React with 👍 / 👎.


pLog.info(`🔄 Trying with new app ID: ${currentAppId}`)
continue
Comment on lines 407 to 412
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

saveAppIdToCapacitorConfig is called before the new ID is confirmed to be registrable, leaving the local config in an inconsistent state.

The save is triggered inside the catch block, right after the user picks a new ID but before addAppInternal is called for it in the next iteration. If that attempt also fails (e.g. the suggested ID is also taken), the capacitor config now contains an unregistered app ID. With maxRetries = 5, all retries could fail and exit(1) fires, leaving the config pointing at an ID that was never successfully created on the Capgo backend.

The save belongs in the success path, guarded by a change check:

🐛 Proposed fix — move save to success path
     try {
       const s = pSpinner()
       s.start(`Running: ${pm.runner} `@capgo/cli`@latest app add ${currentAppId}`)
       const addRes = await addAppInternal(currentAppId, options, organization, true)
       if (!addRes)
         s.stop(`App already add ✅`)
       else
         s.stop(`App add Done ✅`)

+      // Persist the app ID only after it has been successfully registered,
+      // and only when it differs from the one already in the local config.
+      if (currentAppId !== appId) {
+        await saveAppIdToCapacitorConfig(currentAppId)
+      }
+
       pLog.info(`This app is accessible to all members of your organization based on their permissions`)
       await markStep(organization.gid, apikey, 'add-app', currentAppId)
       return currentAppId
     }
     catch (error) {
       ...
       if (choice === 'custom') { ... }
       else { ... }

-      // Save the new app ID to capacitor config
-      await saveAppIdToCapacitorConfig(currentAppId)
-
       pLog.info(`🔄 Trying with new app ID: ${currentAppId}`)
       continue
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/init.ts` around lines 407 - 412, Currently saveAppIdToCapacitorConfig is
invoked inside the catch block immediately after the user picks currentAppId,
which can leave local config pointing to an ID that was never registered;
instead, remove the save from the catch and only call
saveAppIdToCapacitorConfig(currentAppId) after addAppInternal succeeds (the
success path), and guard the save with a check that the saved ID actually
differs from the previous one so you don't overwrite unnecessarily; update the
flow around addAppInternal, currentAppId, maxRetries and exit(1) to ensure the
config is only written on confirmed registration.

}
Expand Down
Loading