react-native-codepush-sdk
Version:
A React Native CodePush SDK for over-the-air updates
182 lines (181 loc) • 6.79 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.useCodePush = exports.CodePushProvider = void 0;
const react_1 = __importStar(require("react"));
const react_native_1 = require("react-native");
const CustomCodePush_1 = __importDefault(require("./CustomCodePush"));
const CodePushContext = (0, react_1.createContext)(undefined);
const CodePushProvider = ({ children, config, autoCheck = true, checkOnResume = true, }) => {
const [codePush] = (0, react_1.useState)(() => new CustomCodePush_1.default(config));
const [currentUpdate, setCurrentUpdate] = (0, react_1.useState)(null);
const [availableUpdate, setAvailableUpdate] = (0, react_1.useState)(null);
const [syncStatus, setSyncStatus] = (0, react_1.useState)(null);
const [isChecking, setIsChecking] = (0, react_1.useState)(false);
const [isDownloading, setIsDownloading] = (0, react_1.useState)(false);
const [isInstalling, setIsInstalling] = (0, react_1.useState)(false);
(0, react_1.useEffect)(() => {
// Wait for SDK to initialize (load stored package) before updating state
codePush.initialize()
.then(async () => {
await loadCurrentUpdate();
if (autoCheck) {
await checkForUpdate();
}
})
.catch(error => {
console.error('Error initializing CodePush SDK:', error);
});
// Set up app state listener for resume checks
if (checkOnResume) {
const handleAppStateChange = (nextAppState) => {
if (nextAppState === 'active') {
checkForUpdate();
}
};
const subscription = react_native_1.AppState.addEventListener('change', handleAppStateChange);
return () => subscription === null || subscription === void 0 ? void 0 : subscription.remove();
}
}, []);
const loadCurrentUpdate = async () => {
try {
const current = await codePush.getCurrentPackage();
setCurrentUpdate(current);
}
catch (error) {
console.error('Failed to load current update:', error);
}
};
const checkForUpdate = async () => {
if (isChecking)
return;
setIsChecking(true);
try {
const update = await codePush.checkForUpdate();
setAvailableUpdate(update);
}
catch (error) {
console.error('Failed to check for update:', error);
}
finally {
setIsChecking(false);
}
};
const syncUpdate = async () => {
if (!availableUpdate || isDownloading || isInstalling)
return;
try {
const success = await codePush.sync({
installMode: 'ON_NEXT_RESTART',
mandatoryInstallMode: 'ON_NEXT_RESTART',
}, (status) => {
setSyncStatus(status);
switch (status.status) {
case 'DOWNLOADING_PACKAGE':
setIsDownloading(true);
setIsInstalling(false);
break;
case 'INSTALLING_UPDATE':
setIsDownloading(false);
setIsInstalling(true);
break;
case 'UPDATE_INSTALLED':
case 'UP_TO_DATE':
case 'UNKNOWN_ERROR':
setIsDownloading(false);
setIsInstalling(false);
break;
}
}, (progress) => {
// Handle download progress if needed
});
if (success) {
setAvailableUpdate(null);
await loadCurrentUpdate();
}
}
catch (error) {
console.error('Failed to sync update:', error);
setIsDownloading(false);
setIsInstalling(false);
}
};
const rollback = async () => {
try {
await codePush.rollback();
setCurrentUpdate(null);
}
catch (error) {
console.error('Failed to rollback:', error);
}
};
const clearUpdates = async () => {
try {
await codePush.clearUpdates();
setCurrentUpdate(null);
setAvailableUpdate(null);
}
catch (error) {
console.error('Failed to clear updates:', error);
}
};
const contextValue = {
codePush,
currentUpdate,
availableUpdate,
syncStatus,
isChecking,
isDownloading,
isInstalling,
checkForUpdate,
syncUpdate,
rollback,
clearUpdates,
getBundleUrl: () => codePush.getBundleUrl(),
};
return (react_1.default.createElement(CodePushContext.Provider, { value: contextValue }, children));
};
exports.CodePushProvider = CodePushProvider;
const useCodePush = () => {
const context = (0, react_1.useContext)(CodePushContext);
if (context === undefined) {
throw new Error('useCodePush must be used within a CodePushProvider');
}
return context;
};
exports.useCodePush = useCodePush;