Source: service/storage/FioriStorage.js

(function() {
    /**
     * @augments Help4.service.StorageService.StorageInterface
     * @property {string} _storageScope
     * @property {Object} _service
     * @property {Object} _container
     */
    Help4.service.StorageService.FioriStorage = class extends Help4.service.StorageService.StorageInterface {
        /**
         * @override
         * @constructor
         */
        constructor() {
            const {STORAGE_LEVEL: {application}} = Help4.service.StorageService;

            super({
                params: {
                    storageLevel: {init: application}
                },
                statics: {
                    _storageScope: {init: 'web_assistant', destroy: false},
                    _service:      {init: null, destroy: false},
                    _container:    {init: null, destroy: false}
                }
            });

            _init.call(this);
        }

        /**
         * @override
         * @param {string} [key = null]
         * @returns {Promise<*>}
         */
        get(key = null) {
            const {_container, _storageScope} = this;

            return new Help4.Promise(resolve => {
                _container.load()
                .then(() => {
                    let data = _container.getItemValue?.(_storageScope);
                    if (!data) return resolve();

                    try {
                        data = Help4.JSON.parse(data);
                        resolve(key ? data[key] : data);
                    } catch(e) {
                        resolve();
                    }
                })
                .catch(() => resolve);
            });
        }

        /**
         * @override
         * @param {string} key
         * @param {string} value
         * @returns {Promise<boolean>}
         */
        async set(key, value) {
            const data = await this.get() || {};
            if (data[key] !== value) {
                data[key] = value;
                return _saveNewPayload.call(this, data);
            }
            return true;
        }

        /**
         * @override
         * @param {string} key
         * @returns {Promise<boolean>}
         */
        async del(key) {
            const data = await this.get() || {};
            if (data.hasOwnProperty(key)) {
                delete data[key];
                return _saveNewPayload.call(this, data);
            }
            return true;
        }
    }

    /**
     * @memberof Help4.service.StorageService.FioriStorage#
     * @private
     * @returns {boolean}
     */
    function _init() {
        // XRAY-3906, XRAY-4886: e.g. for LearningApp
        // XRAY-3908: e.g. in SFSF
        const shell = Help4.getShell?.();
        if (!shell || !(shell instanceof Help4.shell.Fiori)) return this._isReady = true;

        // XRAY-3910: promises broken in older UI5 versions:
        // they do not support catch but this is important for us
        // therefore limiting to UI5 version 1.80
        let ui5Version = shell.getUI5Version();
        let [main, sub] = ui5Version?.split('.') || [];
        main = Number(main) || 0;
        sub = Number(sub) || 0;
        if (main < 1 || sub < 80) return this._isReady = true;

        const s = this._service = shell.getUI5Service('Personalization');
        if (!s) return this._isReady = true;

        s.getContainer(this._storageScope, {validity: Infinity})
        .done(async container => {
            this._container = container;
            const available = await this._test();
            this.dataFunctions.set({available}, {allowReadonlyOverride: true});  // this.available is readonly; allow override
            this._isReady = true;
        })
        .fail(() => {
            this._isReady = true;
        });
    }

    /**
     * @memberof Help4.service.StorageService.FioriStorage#
     * @private
     * @param {Object} payload
     * @returns {Promise<boolean>}
     */
    function _saveNewPayload(payload) {
        const {_container, _storageScope} = this;

        _container.setItemValue?.(_storageScope, Help4.JSON.stringify(payload));

        return new Help4.Promise(resolve => {
            _container.save()
            .then(() => resolve(true))
            .catch(() => resolve(false));
        });
    }
})();