Mobile App Updates Service
๐ Overviewโ
Service Path: internal/api/v1/mobile-app/services/updates.js
The Mobile App Updates service manages version information for DashClicks mobile applications. Core responsibilities include:
- Version Retrieval: Get latest app version by platform (iOS/Android)
- Variant Support: Handle different app variants (production, beta, development)
- Update Notifications: Enable in-app update prompts for outdated versions
- Version Control: Centralized version management for mobile releases
๐๏ธ Collections Usedโ
- mobile-app.updates (link removed - file does not exist) - Mobile app version records
๐ Data Flowโ
Update Check Flowโ
sequenceDiagram
participant MobileApp
participant API
participant UpdatesService
participant UpdatesDB
MobileApp->>API: GET /mobile-app/updates/latest
Note over MobileApp,API: Query: platform=ios&variant=production
API->>UpdatesService: getLatest({ platform, variant })
UpdatesService->>UpdatesDB: Find latest version
Note over UpdatesService,UpdatesDB: Sort by version_code DESC
UpdatesDB-->>UpdatesService: Latest update record
UpdatesService-->>API: Update data
API-->>MobileApp: Version info
Note over API,MobileApp: {version, version_code, url, notes}
MobileApp->>MobileApp: Compare with current version
alt Update Available
MobileApp->>MobileApp: Show update prompt
else Up to Date
MobileApp->>MobileApp: Continue normally
end
Version Management Flowโ
flowchart TD
A[New App Release] --> B[Create Version Record]
B --> C{Platform?}
C -->|iOS| D[Set platform = 'ios']
C -->|Android| E[Set platform = 'android']
D --> F{Variant?}
E --> F
F -->|Production| G[variant = 'production']
F -->|Beta| H[variant = 'beta']
F -->|Dev| I[variant = 'development']
G --> J[Set version_code]
H --> J
I --> J
J --> K[Set version string]
K --> L[Add download URL]
L --> M[Add release notes]
M --> N[Save to Database]
N --> O[Mobile Apps Query Latest]
O --> P[Return Highest version_code]
style D fill:#e8f5e9
style E fill:#fff4e6
style G fill:#e3f2fd
style H fill:#fff3e0
style I fill:#fce4ec
๐ง Business Logic & Functionsโ
getLatest({ platform, variant })โ
Purpose: Retrieve the latest app version for specified platform and variant
Parameters:
platform(String) - Mobile platform: 'ios' or 'android'variant(String) - App variant: 'production', 'beta', or 'development'
Returns:
{
_id: ObjectId,
platform: String, // 'ios' or 'android'
variant: String, // 'production', 'beta', 'development'
version: String, // Semantic version (e.g., '2.5.3')
version_code: Number, // Integer version for comparison (e.g., 253)
url: String, // App Store/Play Store URL or direct download
release_notes: String, // What's new in this version
required: Boolean, // Force update if true
created_at: Date,
updated_at: Date
}
// Returns null if no version found
Business Logic Flow:
-
Query Latest Version
return await Updates.findOne(
{
platform, // 'ios' or 'android'
variant, // 'production', 'beta', 'development'
},
{},
{ sort: { version_code: -1 } }, // Highest version_code first
);- Filters by exact platform and variant match
- Sorts by version_code in descending order (-1)
- Returns first result (latest version)
Key Business Rules:
- Version Code Sorting: Uses integer version_code for reliable sorting (not string comparison)
- Platform Specific: iOS and Android versions tracked separately
- Variant Isolation: Production, beta, and development versions independent
- Null Safe: Returns null if no version exists for platform/variant combo
Example Usage:
// Get latest production iOS version
const iosUpdate = await getLatest({
platform: 'ios',
variant: 'production',
});
// Returns:
// {
// _id: '507f1f77bcf86cd799439011',
// platform: 'ios',
// variant: 'production',
// version: '2.5.3',
// version_code: 253,
// url: 'https://apps.apple.com/app/dashclicks/id123456789',
// release_notes: 'Bug fixes and performance improvements',
// required: false,
// created_at: '2025-10-01T10:00:00Z',
// updated_at: '2025-10-01T10:00:00Z'
// }
// Get latest Android beta version
const androidBeta = await getLatest({
platform: 'android',
variant: 'beta',
});
// Returns:
// {
// _id: '507f1f77bcf86cd799439012',
// platform: 'android',
// variant: 'beta',
// version: '2.6.0-beta.1',
// version_code: 260,
// url: 'https://play.google.com/store/apps/details?id=com.dashclicks.app',
// release_notes: 'Testing new features: dark mode, push notifications',
// required: false,
// created_at: '2025-10-05T14:30:00Z',
// updated_at: '2025-10-05T14:30:00Z'
// }
// No version available scenario
const devVersion = await getLatest({
platform: 'ios',
variant: 'development',
});
// Returns: null (no development builds available)
Side Effects:
- None (read-only operation)
Performance Considerations:
- Index Required: Compound index on (platform, variant, version_code) for optimal performance
- Simple Query: Single document lookup with sort, very fast
- Cache Friendly: Results rarely change, suitable for caching
๐ Integration Pointsโ
Mobile Applicationsโ
iOS App (Swift):
// Check for updates on app launch
func checkForUpdate() {
let platform = "ios"
let variant = "production" // or "beta" for TestFlight
API.get("/mobile-app/updates/latest?platform=\(platform)&variant=\(variant)") { result in
guard let update = result else { return }
let currentVersion = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
let currentCode = Int(currentVersion ?? "0") ?? 0
if update.version_code > currentCode {
// Show update prompt
showUpdateAlert(
version: update.version,
notes: update.release_notes,
required: update.required,
url: update.url
)
}
}
}
Android App (Kotlin):
// Check for updates
suspend fun checkForUpdate() {
val platform = "android"
val variant = "production" // or "beta" for beta testers
val update = api.getLatestUpdate(platform, variant)
update?.let {
val currentVersionCode = BuildConfig.VERSION_CODE
if (it.version_code > currentVersionCode) {
// Show update dialog
showUpdateDialog(
version = it.version,
releaseNotes = it.release_notes,
required = it.required,
url = it.url
)
}
}
}
Admin Panelโ
Version Publishing:
// Admin creates new version record
POST /admin/mobile-app/updates
{
platform: 'ios',
variant: 'production',
version: '2.5.4',
version_code: 254, // Must be higher than previous
url: 'https://apps.apple.com/app/dashclicks/id123456789',
release_notes: 'Critical security update',
required: true // Force users to update
}
CI/CD Pipelineโ
Automated Version Creation:
# GitHub Actions workflow
- name: Create Version Record
run: |
VERSION_CODE=$(git rev-list --count HEAD)
VERSION=$(cat package.json | jq -r .version)
curl -X POST $API_URL/admin/mobile-app/updates \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-d "{
\"platform\": \"$PLATFORM\",
\"variant\": \"production\",
\"version\": \"$VERSION\",
\"version_code\": $VERSION_CODE,
\"url\": \"$APP_STORE_URL\",
\"release_notes\": \"$RELEASE_NOTES\"
}"
๐งช Edge Cases & Special Handlingโ
No Version Availableโ
First Release Scenario:
const update = await getLatest({
platform: 'ios',
variant: 'production',
});
if (!update) {
// No version published yet
// Mobile app should handle gracefully
console.log('No updates available');
}
Version Code Conflictsโ
Same version_code for Different Variants:
// Valid: Same version_code across variants
const prodUpdate = {
platform: 'ios',
variant: 'production',
version_code: 250,
};
const betaUpdate = {
platform: 'ios',
variant: 'beta',
version_code: 250, // OK - different variant
};
// Invalid: Same version_code within same platform/variant
const duplicate = {
platform: 'ios',
variant: 'production',
version_code: 250, // โ Conflict with prodUpdate
};
Platform Case Sensitivityโ
Query Must Match Exactly:
// โ
Correct
await getLatest({ platform: 'ios', variant: 'production' });
// โ Wrong - case sensitive
await getLatest({ platform: 'iOS', variant: 'production' });
// Returns: null
// โ Wrong - typo
await getLatest({ platform: 'ios', variant: 'prod' });
// Returns: null
Required Update Handlingโ
Force Update Flow:
const update = await getLatest({
platform: 'android',
variant: 'production',
});
if (update && update.required) {
// Mobile app should:
// 1. Block app access
// 2. Show non-dismissible update dialog
// 3. Redirect to app store
// 4. Prevent "Skip" or "Later" options
}
Version Code Orderingโ
Semantic Versioning to Version Code:
// Version string โ Version code conversion
'1.0.0' โ 100
'1.2.5' โ 125
'2.0.0' โ 200
'2.5.3' โ 253
// Ensures correct sorting:
// 253 > 125 > 100 (version_code comparison)
// '2.5.3' > '1.2.5' > '1.0.0' (semantic order)
Beta Tester Updatesโ
Separate Beta Channel:
// Production users
const prodUpdate = await getLatest({
platform: 'ios',
variant: 'production',
});
// Returns: v2.5.3 (stable)
// Beta testers
const betaUpdate = await getLatest({
platform: 'ios',
variant: 'beta',
});
// Returns: v2.6.0-beta.1 (testing features)
// Beta users don't see production updates
// Production users don't see beta updates
โ ๏ธ Important Notesโ
-
Version Code Importance: Always use
version_codefor version comparison, notversionstring. Version codes are integers and sort reliably (e.g., 100 < 253). -
Platform Values: Only two valid platforms: 'ios' and 'android'. Case-sensitive, must be lowercase.
-
Variant Types:
- production: Live app in App Store/Play Store
- beta: TestFlight/Beta testing builds
- development: Internal development builds
-
Required Updates: When
required: true, mobile apps should block access until user updates. Use for critical security patches. -
URL Field:
- iOS: App Store URL (e.g.,
https://apps.apple.com/app/id123456789) - Android: Play Store URL (e.g.,
https://play.google.com/store/apps/details?id=com.app) - Beta: TestFlight or Firebase App Distribution links
- iOS: App Store URL (e.g.,
-
Version Code Increment: Each new release must have a higher
version_codethan previous. Common approach: use build number or Git commit count. -
Release Notes: Should be user-friendly, not technical. Focus on features, improvements, and bug fixes visible to users.
-
Null Return: Service returns
nullif no version exists. Mobile apps must handle gracefully (don't crash). -
Index Optimization: Create compound index
{ platform: 1, variant: 1, version_code: -1 }for best performance. -
Cache Strategy: Update records rarely change. Consider caching results for 1-5 minutes to reduce database load.
-
Multi-Tenant: This service is platform-wide (not account-specific). All users see same version information.
-
Update Frequency: Check for updates on app launch and periodically (e.g., every 24 hours when app is active).
๐ Related Documentationโ
- Mobile App Updates Collection (link removed - file does not exist) - Update record schema
- Mobile App Controllers (link removed - file does not exist) - API endpoints
- Admin Module (link removed - file does not exist) - Version management interface
- CI/CD Pipeline (link removed - file does not exist) - Automated version publishing