UNPKG

@ledgerhq/live-common

Version:
89 lines 4.47 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const rxjs_1 = require("rxjs"); const getDeviceInfo_1 = __importDefault(require("../hw/getDeviceInfo")); const listAppsUseCase_1 = require("../device/use-cases/listAppsUseCase"); const execWithTransport_1 = require("../device/use-cases/execWithTransport"); const logic_1 = require("./logic"); const runner_1 = require("./runner"); const operators_1 = require("rxjs/operators"); const logs_1 = require("@ledgerhq/logs"); /** * Tries to install a list of apps * * @param transport Transport instance * @param appNames List of app names to install * @param onSuccessObs Optional observable to run after the installation * @param allowPartialDependencies If true, keep installing apps even if some are missing * @returns Observable of InlineAppInstallEvent or ConnectAppEvent * - Event "inline-install" contains a global progress of the installation */ const inlineAppInstall = ({ transport, appNames, onSuccessObs, allowPartialDependencies = false, }) => { const tracer = new logs_1.LocalTracer("hw", { ...transport.getTraceContext(), function: "inlineAppInstall", }); tracer.trace("Starting inline app install"); return (0, rxjs_1.concat)((0, rxjs_1.of)({ type: "listing-apps", }), (0, rxjs_1.from)((0, getDeviceInfo_1.default)(transport)).pipe((0, operators_1.mergeMap)(deviceInfo => { tracer.trace("Got device info", { deviceInfo }); return (0, listAppsUseCase_1.listAppsUseCase)(transport, deviceInfo); }), (0, operators_1.mergeMap)(e => { // Bubble up events if (e.type === "device-permission-granted" || e.type === "device-permission-requested") { return (0, rxjs_1.of)(e); } if (e.type === "result") { // Figure out the operations that need to happen const state = appNames.reduce((state, name) => (0, logic_1.reducer)(state, { type: "install", name, allowPartialDependencies, }), (0, logic_1.initState)(e.result)); // Failed appOps in this flow will throw by default but if we're here // it means we didn't throw, so we wan't to notify the action about it. const maybeSkippedEvent = state.skippedAppOps.length ? (0, rxjs_1.of)({ type: "some-apps-skipped", skippedAppOps: state.skippedAppOps, }) : rxjs_1.EMPTY; if (!state.installQueue.length) { // There's nothing to install, we can consider this a success. return (0, rxjs_1.defer)(onSuccessObs || (() => rxjs_1.EMPTY)); } if ((0, logic_1.isOutOfMemoryState)((0, logic_1.predictOptimisticState)(state))) { // In this case we can't install either by lack of storage, or permissions, // we fallback to the error case listing the missing apps. const missingAppNames = state.installQueue; tracer.trace("Out of memory", { appNames: missingAppNames, appName: missingAppNames[0] || appNames[0], }); return (0, rxjs_1.of)({ type: "app-not-installed", appNames: missingAppNames, appName: missingAppNames[0] || appNames[0], // TODO remove when LLD/LLM integrate appNames }); } const exec = (0, execWithTransport_1.execWithTransport)(transport); return (0, rxjs_1.concat)((0, rxjs_1.of)({ type: "listed-apps", installQueue: state.installQueue, }), maybeSkippedEvent, (0, runner_1.runAllWithProgress)(state, exec).pipe((0, operators_1.throttleTime)(100), (0, operators_1.map)(({ globalProgress, itemProgress, installQueue, currentAppOp }) => ({ type: "inline-install", progress: globalProgress, itemProgress, installQueue, currentAppOp, }))), (0, rxjs_1.defer)(onSuccessObs || (() => rxjs_1.EMPTY))); } return rxjs_1.EMPTY; }))); }; exports.default = inlineAppInstall; //# sourceMappingURL=inlineAppInstall.js.map