@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
115 lines • 5.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLatestAvailableFirmwareAction = exports.initialState = void 0;
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const getLatestFirmware_1 = require("../tasks/getLatestFirmware");
const getDeviceInfo_1 = require("../tasks/getDeviceInfo");
const core_1 = require("./core");
exports.initialState = {
firmwareUpdateContext: null,
deviceInfo: null,
status: "idle",
...core_1.initialSharedActionState,
};
/**
* Get the latest available firmware that the device could update to
*
* @param `deviceId` A device id, or an empty string if device is usb plugged
* @returns an Observables that emits the evolution of the state machine until finding (or not)
* the latest available firmware. The state is as follow (+ shared state with other actions):
* - `firmwareUpdateContext`: the `FirmwareUpdateContext` when retrieved, null otherwise
* - `deviceInfo`: the `DeviceInfo` when retrieved, null otherwise
* - `status`: the current status of the action: "error" | "no-available-firmware" | "available-firmware" meaning the action has finished
* - `error`: an error coming from the business logic, the device or internal. Some error are retried:
* `{ type`: "SharedError", retrying: true, ... }`
* - `...sharedActionState`
*/
function getLatestAvailableFirmwareAction({ deviceId, }) {
const observable = new rxjs_1.Observable(subscriber => {
subscriber.next({
type: "stateUpdate",
status: "ongoing",
});
(0, getDeviceInfo_1.getDeviceInfoTask)({ deviceId })
.pipe((0, operators_1.switchMap)(event => {
if (event.type !== "data") {
return (0, rxjs_1.of)(event);
}
const { deviceInfo } = event;
// Update the action state before the next task
subscriber.next({
type: "stateUpdate",
status: "ongoing",
deviceInfo,
lockedDevice: false,
error: null,
});
// Keeps `deviceInfo` in the next event
return (0, rxjs_1.forkJoin)([(0, getLatestFirmware_1.getLatestFirmwareTask)({ deviceId, deviceInfo }), (0, rxjs_1.of)(deviceInfo)]).pipe(
// Creating a new "event"-like object, extending it with `deviceInfo`
(0, operators_1.switchMap)(([event, deviceInfo]) => {
return (0, rxjs_1.of)({
...event,
deviceInfo,
});
}));
}))
.subscribe(subscriber);
});
return observable.pipe((0, operators_1.scan)((currentState, event) => {
switch (event.type) {
case "taskError":
// Maps firmware already up-to-date task error to `status` "no-available-firmware"
if (event.error === "FirmwareUpToDate") {
return {
...currentState,
firmwareUpdateContext: null,
deviceInfo: "deviceInfo" in event ? event.deviceInfo : null,
status: "no-available-firmware",
};
}
return {
...currentState,
error: {
type: "GetLatestAvailableFirmwareError",
name: event.error,
},
firmwareUpdateContext: null,
deviceInfo: "deviceInfo" in event ? event.deviceInfo : null,
status: "error",
};
case "data":
return {
...currentState,
error: null,
firmwareUpdateContext: event.firmwareUpdateContext,
deviceInfo: event.deviceInfo,
status: "available-firmware",
};
case "error": {
const sharedState = (0, core_1.sharedReducer)({
event,
});
return {
...currentState,
...sharedState,
firmwareUpdateContext: null,
deviceInfo: "deviceInfo" in event ? event.deviceInfo : null,
status: sharedState.error?.retrying ? "ongoing" : "error",
};
}
case "stateUpdate":
// Updates only the prop that are defined in the event
return {
...currentState,
...(event.lockedDevice !== undefined ? { lockedDevice: event.lockedDevice } : {}),
...(event.deviceInfo !== undefined ? { deviceInfo: event.deviceInfo } : {}),
...(event.status !== undefined ? { status: event.status } : {}),
...(event.error !== undefined ? { error: event.error } : {}),
};
}
}, exports.initialState));
}
exports.getLatestAvailableFirmwareAction = getLatestAvailableFirmwareAction;
//# sourceMappingURL=getLatestAvailableFirmware.js.map