@codeimplants/version-control
v1.0.7
Published
A lightweight cross-platform SDK to remotely control app version behavior such as soft update, force update, and maintenance mode using backend-driven rules, without enforcing UI.
Maintainers
Readme
Version Control SDK
A lightweight, backend-driven SDK that enables remote control of app version behavior including soft updates, force updates, and maintenance mode for mobile and web applications.
Features
- 🚀 Soft Updates - Notify users about new versions with optional updates
- ⚡ Force Updates - Enforce minimum version requirements
- 🔧 Maintenance Mode - Put your app in maintenance mode remotely
- 🛑 Kill Switch - Emergency app disable capability
- 📱 Cross-Platform - Works on iOS, Android, and Web
- 🎯 Auto-Detection - Automatically detects platform, version, and app ID
- 🔌 Backend-Driven - All decisions made server-side for instant updates
- 🪶 Lightweight - Minimal dependencies and footprint
Installation
npm install @codeimplants/version-controlOr with yarn:
yarn add @codeimplants/version-controlQuick Start
Simple Usage
import { VersionSDK } from "@codeimplants/version-control";
// Quick check with minimal config
const decision = await VersionSDK.check(
"https://api.yourapp.com",
"your-api-key",
);
// Handle the decision
switch (decision.action) {
case "FORCE_UPDATE":
// Show force update dialog
window.location.href = decision.storeUrl;
break;
case "SOFT_UPDATE":
// Show optional update dialog
showUpdatePrompt(decision.message, decision.storeUrl);
break;
case "MAINTENANCE":
// Show maintenance screen
showMaintenanceScreen(decision.message);
break;
case "KILL_SWITCH":
// App is disabled
showKillSwitchScreen(decision.message);
break;
case "NONE":
// Continue normally
break;
}Advanced Usage
import { VersionSDK, VCConfig } from "@codeimplants/version-control";
const config: VCConfig = {
backendUrl: "https://api.yourapp.com",
apiKey: "your-api-key",
appId: "com.yourapp.mobile", // Optional: auto-detected
platform: "ios", // Optional: auto-detected
version: "2.1.0", // Optional: auto-detected
timeout: 8000, // Optional: default 8000ms
debug: true, // Optional: enable logging
};
const sdk = VersionSDK.init(config);
const decision = await sdk.checkVersion();Auto-Detection
The SDK automatically detects the following if not provided:
Platform Detection
- Capacitor: Detects iOS/Android via Capacitor.getPlatform()
- React Native: Detects via navigator.product
- User Agent: Falls back to UA string parsing
- Web: Default fallback
Version Detection
Checks in order:
- Capacitor App plugin (
Capacitor.Plugins.App.getInfo()) - Global variables:
APP_VERSION,__VERSION__,VERSION,packageVersion - Fallback:
"1.0.0"
App ID Detection
Checks in order:
- Capacitor App plugin bundle ID
- Fallback:
"unknown.app"
Configuration
VCConfig
interface VCConfig {
backendUrl: string; // Your backend API URL (required)
apiKey?: string; // API key for authentication
appId?: string; // App identifier (auto-detected if not provided)
platform?: Platform; // 'android' | 'ios' | 'web' | 'all'
version?: string; // Current app version (auto-detected if not provided)
timeout?: number; // Request timeout in ms (default: 8000)
debug?: boolean; // Enable debug logging
}Response Types
VCDecision
interface VCDecision {
action: VCAction; // The action to take
message?: string; // User-facing message
storeUrl?: string; // App store URL for updates
minVersion?: string; // Minimum required version (for FORCE_UPDATE)
latestVersion?: string; // Latest available version
raw?: any; // Raw backend response
}Actions
NONE- No action required, app is up to dateSOFT_UPDATE- Update available but optionalFORCE_UPDATE- Update required to continueMAINTENANCE- App is in maintenance modeKILL_SWITCH- App is disabledBLOCKED- Access blocked for this version/platform
Backend Integration
The SDK expects your backend endpoint to accept POST requests at /sdk/version/check:
Request Format
{
"appId": "com.yourapp.mobile",
"platform": "ios",
"currentVersion": "2.0.0",
"environment": "prod"
}Response Format
{
"status": "FORCE_UPDATE", // VCAction
"message": "Please update to continue",
"title": "Update Required",
"minVersion": "2.1.0",
"latestVersion": "2.3.0",
"storeUrl": "https://apps.apple.com/..."
}Examples
React Example
import React, { useEffect, useState } from 'react';
import { VersionSDK, VCDecision } from '@codeimplants/version-control';
function App() {
const [versionCheck, setVersionCheck] = useState<VCDecision | null>(null);
useEffect(() => {
async function checkVersion() {
const decision = await VersionSDK.check(
'https://api.yourapp.com',
'your-api-key'
);
setVersionCheck(decision);
}
checkVersion();
}, []);
if (versionCheck?.action === 'FORCE_UPDATE') {
return (
<div className="update-required">
<h1>Update Required</h1>
<p>{versionCheck.message}</p>
<button onClick={() => window.location.href = versionCheck.storeUrl}>
Update Now
</button>
</div>
);
}
if (versionCheck?.action === 'MAINTENANCE') {
return (
<div className="maintenance">
<h1>Maintenance Mode</h1>
<p>{versionCheck.message}</p>
</div>
);
}
return <YourApp />;
}Capacitor/Ionic Example
import { VersionSDK } from "@codeimplants/version-control";
import { AlertController } from "@ionic/angular";
export class AppComponent {
constructor(private alertController: AlertController) {}
async ngOnInit() {
const decision = await VersionSDK.check(
"https://api.yourapp.com",
"your-api-key",
);
if (decision.action === "SOFT_UPDATE") {
const alert = await this.alertController.create({
header: "Update Available",
message: decision.message,
buttons: [
{ text: "Later", role: "cancel" },
{
text: "Update",
handler: () => {
window.open(decision.storeUrl, "_system");
},
},
],
});
await alert.present();
}
}
}React Native Example
import { VersionSDK } from "@codeimplants/version-control";
import { Alert, Linking } from "react-native";
async function checkAppVersion() {
const decision = await VersionSDK.check(
"https://api.yourapp.com",
"your-api-key",
);
if (decision.action === "FORCE_UPDATE") {
Alert.alert(
"Update Required",
decision.message,
[
{
text: "Update Now",
onPress: () => Linking.openURL(decision.storeUrl),
},
],
{ cancelable: false },
);
}
}Version Comparison
The SDK uses semantic versioning (semver) comparison:
// Examples of version comparisons
"1.0.0" < "1.0.1"; // true
"1.0.0" < "1.1.0"; // true
"2.0.0" > "1.9.9"; // true
"1.0" === "1.0.0"; // true (normalized)Error Handling
The SDK gracefully handles errors and returns { action: "NONE" } if:
- Network request fails
- Backend is unreachable
- Request times out
- Invalid response format
Enable debug mode to see detailed error logs:
const config = {
backendUrl: "https://api.yourapp.com",
debug: true, // Logs all requests and responses
};Best Practices
- Check on App Launch - Always check version status when the app starts
- Cache Decisions - Cache the decision for a reasonable time (e.g., 1 hour)
- Handle Offline - Gracefully handle offline scenarios (SDK returns
NONE) - User Experience - Don't interrupt critical user flows with update prompts
- Test Thoroughly - Test all action types before deploying rules
- Gradual Rollouts - Use backend rules to gradually roll out forced updates
Platform Support
- ✅ iOS (Native & Web)
- ✅ Android (Native & Web)
- ✅ Web Browsers
- ✅ Capacitor
- ✅ React Native
- ✅ Ionic
- ✅ Cordova
TypeScript
The SDK is written in TypeScript and includes full type definitions.
License
MIT
