Skip to main content

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:

  1. 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โ€‹

  1. Version Code Importance: Always use version_code for version comparison, not version string. Version codes are integers and sort reliably (e.g., 100 < 253).

  2. Platform Values: Only two valid platforms: 'ios' and 'android'. Case-sensitive, must be lowercase.

  3. Variant Types:

    • production: Live app in App Store/Play Store
    • beta: TestFlight/Beta testing builds
    • development: Internal development builds
  4. Required Updates: When required: true, mobile apps should block access until user updates. Use for critical security patches.

  5. 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
  6. Version Code Increment: Each new release must have a higher version_code than previous. Common approach: use build number or Git commit count.

  7. Release Notes: Should be user-friendly, not technical. Focus on features, improvements, and bug fixes visible to users.

  8. Null Return: Service returns null if no version exists. Mobile apps must handle gracefully (don't crash).

  9. Index Optimization: Create compound index { platform: 1, variant: 1, version_code: -1 } for best performance.

  10. Cache Strategy: Update records rarely change. Consider caching results for 1-5 minutes to reduce database load.

  11. Multi-Tenant: This service is platform-wide (not account-specific). All users see same version information.

  12. Update Frequency: Check for updates on app launch and periodically (e.g., every 24 hours when app is active).

  • 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
๐Ÿ’ฌ

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM