UNPKG

medusa-plugin-tolgee

Version:

Medusa V2 Plugin to easily add translations to your models with Tolgee

160 lines 15.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("@medusajs/utils"); const common_1 = require("../../common"); const axios_1 = __importDefault(require("axios")); class TolgeeModuleService { constructor({ tolgeeClient, logger }, options) { this.client_ = tolgeeClient; this.logger = logger; this.options_ = { ...options, keys: { ...common_1.defaultSupportedProperties, ...options.keys, }, }; } async getOptions() { try { // TODO: axios-cache-interceptor type mismatch const { data: languages } = await this.client_.get(`/languages`, { params: { size: 9999 }, // use transformResponse to also cache computation. // concat to the existing transforms gives JSON deserial. automatically transformResponse: axios_1.default.defaults.transformResponse.concat((data) => { const languages = data?._embedded?.languages; if (!languages || languages.length < 1) return { defaultLanguage: "en", availableLanguages: [] }; const defaultLanguage = languages.find((lang) => lang.base)?.tag ?? languages[0].tag; const availableLanguages = languages.map((lang) => ({ label: lang.name, tag: lang.tag, })); return { defaultLanguage, availableLanguages }; }) }); return { ...languages, apiKey: this.options_.apiKey, apiUrl: this.options_.baseURL }; } catch (error) { throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to fetch languages for project: ${error.message}`); } } async getModelKeyNames(id) { try { const response = await this.client_.get(`/keys/search?search=ns=${id}&size=9999`, { cache: false }); return response.data?._embedded?.keys?.map(k => k.name) ?? []; } catch (error) { throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to fetch key names for model ${id}: ${error.message}`); } } async list(filter) { try { const country_code = filter.context?.country_code?.toLowerCase(); const ids = Array.isArray(filter.id) ? filter.id : [filter.id]; const langs = (await this.getOptions()).availableLanguages.map((lang) => lang.tag).join(","); // We use separate queries to simplify caching, they get batched anyway const data = await Promise.all(ids.map(id => this.client_.get(`/translations`, { params: { languages: `${langs}`, filterNamespace: `${id}`, size: 9999 }, id: `get-translation-${id}` }))); const keys = data.flatMap(d => d.data._embedded.keys); // TODO: proper typing of Tolgee response and normalized result const results = []; for (const id of ids) { const normalizedData = this.getNormalizedData(id, keys); // If the locale is passed via context, directly return the keys for that locale. Simplifies user-side fetching results.push({ id, ...(country_code ? normalizedData[country_code] : normalizedData) }); } return results; } catch (error) { throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to fetch translations for key ID ${filter.id}: ${error.message}`); } } getNormalizedData(id, keys) { const data = {}; for (const key of keys) { if (key.keyName.startsWith(id)) { for (const language in key.translations) { if (!data[language]) data[language] = {}; data[language][key.keyName.split(".")[1]] = key.translations[language].text; } } } return data; } async createNewKeyWithTranslation(keys) { try { const tolgeeOptions = await this.getOptions(); await this.client_.post(`/keys/import`, { keys: keys.map(({ id, tags, keyName, translation }) => ({ name: `${id}.${keyName}`, tags, namespace: id, translations: { [tolgeeOptions.defaultLanguage]: translation }, })) }, { cache: { update: Object.fromEntries(keys.map(({ id }) => [`get-translation-${id}`, "delete"])) } }); return; } catch (error) { this.logger.error(error); throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to import keys ${error}`); } } async createModelTranslations(models, type) { const keys = models.flatMap((model) => this.options_.keys?.[type]?.map((key) => ({ id: model.id, tags: this.options_.tags?.[type] ?? [type], keyName: key, translation: model?.[key] ?? "" })) ?? []); try { await this.createNewKeyWithTranslation(keys); return models.map((model) => model.id); } catch (error) { this.logger.error(`Entities of type ${type} already translated or error creating translations: ${models.map((model) => model.id)}`, error); return []; } } async getNamespaceKeys(id) { const ids = Array.isArray(id) ? id : [id]; try { const response = await this.client_.get(`/keys/select?filterNamespace=${ids.join(",")}`, { cache: false }); return response.data.ids; } catch (error) { throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to fetch namespace keys for ${id}: ${error.message}`); } } async deleteTranslation(id) { const keys = await this.getNamespaceKeys(id); try { const response = await this.client_.delete(`/keys/${keys}`, { cache: { update: { [`get-translation-${id}`]: "delete" } } }); return response.data; } catch (error) { throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to delete translations for namespace ${id}: ${error.message}`); } } } exports.default = TolgeeModuleService; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL3RvbGdlZS9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsMkNBQTZDO0FBQzdDLHlDQUF3RztBQUV4RyxrREFBdUQ7QUFvQ3ZELE1BQU0sbUJBQW1CO0lBS3JCLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUF3RCxFQUFFLE9BQTJCO1FBQ25ILElBQUksQ0FBQyxPQUFPLEdBQUcsWUFBWSxDQUFBO1FBQzNCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFBO1FBRXBCLElBQUksQ0FBQyxRQUFRLEdBQUc7WUFDWixHQUFHLE9BQU87WUFDVixJQUFJLEVBQUU7Z0JBQ0YsR0FBRyxtQ0FBMEI7Z0JBQzdCLEdBQUcsT0FBTyxDQUFDLElBQUk7YUFDbEI7U0FDSixDQUFBO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxVQUFVO1FBQ1osSUFBSSxDQUFDO1lBQ0QsOENBQThDO1lBQzlDLE1BQU0sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEdBQUcsTUFBTyxJQUFJLENBQUMsT0FBeUIsQ0FBQyxHQUFHLENBQXFFLFlBQVksRUFBRTtnQkFDcEosTUFBTSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRTtnQkFDdEIsbURBQW1EO2dCQUNuRCx1RUFBdUU7Z0JBQ3ZFLGlCQUFpQixFQUFHLGVBQUssQ0FBQyxRQUFRLENBQUMsaUJBQWdELENBQUMsTUFBTSxDQUFDLENBQUMsSUFBNkIsRUFBRSxFQUFFO29CQUN6SCxNQUFNLFNBQVMsR0FBRyxJQUFJLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQTtvQkFDNUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUM7d0JBQ2xDLE9BQU87NEJBQ0gsZUFBZSxFQUFFLElBQUk7NEJBQ3JCLGtCQUFrQixFQUFFLEVBQUU7eUJBQ3pCLENBQUE7b0JBRUwsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFBO29CQUNwRixNQUFNLGtCQUFrQixHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7d0JBQ2hELEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSTt3QkFDaEIsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHO3FCQUNoQixDQUFDLENBQUMsQ0FBQTtvQkFDSCxPQUFPLEVBQUUsZUFBZSxFQUFFLGtCQUFrQixFQUFFLENBQUE7Z0JBQ2xELENBQUMsQ0FBQzthQUNMLENBQUMsQ0FBQTtZQUdGLE9BQU87Z0JBQ0gsR0FBRyxTQUFTO2dCQUNaLE1BQU0sRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU07Z0JBQzVCLE1BQU0sRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU87YUFDaEMsQ0FBQTtRQUNMLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2IsTUFBTSxJQUFJLG1CQUFXLENBQ2pCLG1CQUFXLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUNsQywwQ0FBMEMsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUM1RCxDQUFBO1FBQ0wsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsZ0JBQWdCLENBQUMsRUFBVTtRQUM3QixJQUFJLENBQUM7WUFDRCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLDBCQUEwQixFQUFFLFlBQVksRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFBO1lBQ25HLE9BQU8sUUFBUSxDQUFDLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDbEUsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDYixNQUFNLElBQUksbUJBQVcsQ0FDakIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEVBQ2xDLHVDQUF1QyxFQUFFLEtBQUssS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUNoRSxDQUFBO1FBQ0wsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsSUFBSSxDQUNOLE1BR0M7UUFFRCxJQUFJLENBQUM7WUFDRCxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsQ0FBQTtZQUVoRSxNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUE7WUFDOUQsTUFBTSxLQUFLLEdBQUcsQ0FBQyxNQUFNLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUU1Rix1RUFBdUU7WUFDdkUsTUFBTSxJQUFJLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxTQUFTLEVBQUUsR0FBRyxLQUFLLEVBQUUsRUFBRSxlQUFlLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxFQUFFLG1CQUFtQixFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzNMLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtZQUVyRCwrREFBK0Q7WUFDL0QsTUFBTSxPQUFPLEdBQVMsRUFBRSxDQUFBO1lBQ3hCLEtBQUssTUFBTSxFQUFFLElBQUksR0FBRyxFQUFFLENBQUM7Z0JBQ25CLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUE7Z0JBQ3ZELCtHQUErRztnQkFDL0csT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtZQUMzRixDQUFDO1lBQ0QsT0FBTyxPQUFPLENBQUE7UUFDbEIsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDYixNQUFNLElBQUksbUJBQVcsQ0FDakIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEVBQ2xDLDJDQUEyQyxNQUFNLENBQUMsRUFBRSxLQUFLLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FDM0UsQ0FBQTtRQUNMLENBQUM7SUFDTCxDQUFDO0lBRU8saUJBQWlCLENBQUMsRUFBVSxFQUFFLElBQVc7UUFDN0MsTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFBO1FBQ2YsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUNyQixJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQzdCLEtBQUssTUFBTSxRQUFRLElBQUksR0FBRyxDQUFDLFlBQVksRUFBRSxDQUFDO29CQUN0QyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQzt3QkFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFBO29CQUN4QyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FBQTtnQkFDL0UsQ0FBQztZQUNMLENBQUM7UUFDTCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUE7SUFDZixDQUFDO0lBRU8sS0FBSyxDQUFDLDJCQUEyQixDQUFDLElBS3ZDO1FBQ0MsSUFBSSxDQUFDO1lBQ0QsTUFBTSxhQUFhLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUE7WUFDN0MsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQ2xDO2dCQUNJLElBQUksRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztvQkFDcEQsSUFBSSxFQUFFLEdBQUcsRUFBRSxJQUFJLE9BQU8sRUFBRTtvQkFDeEIsSUFBSTtvQkFDSixTQUFTLEVBQUUsRUFBRTtvQkFDYixZQUFZLEVBQUUsRUFBRSxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQUMsRUFBRSxXQUFXLEVBQUU7aUJBQ2pFLENBQUMsQ0FBQzthQUNOLEVBQ0Q7Z0JBQ0ksS0FBSyxFQUFFO29CQUNILE1BQU0sRUFBRSxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLG1CQUFtQixFQUFFLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO2lCQUN4RjthQUNKLENBQ0osQ0FBQTtZQUVELE9BQU07UUFDVixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNiLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFBO1lBQ3hCLE1BQU0sSUFBSSxtQkFBVyxDQUNqQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFDbEMseUJBQXlCLEtBQUssRUFBRSxDQUNuQyxDQUFBO1FBQ0wsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsdUJBQXVCLENBQ3pCLE1BQWtCLEVBQ2xCLElBQXFCO1FBRXJCLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUNsQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUN0QyxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUU7WUFDWixJQUFJLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUMxQyxPQUFPLEVBQUUsR0FBRztZQUNaLFdBQVcsRUFBRSxLQUFLLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFO1NBQ2xDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FDWixDQUFBO1FBRUQsSUFBSSxDQUFDO1lBQ0QsTUFBTSxJQUFJLENBQUMsMkJBQTJCLENBQUMsSUFBSSxDQUFDLENBQUE7WUFDNUMsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDMUMsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsSUFBSSx1REFBdUQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUE7WUFDMUksT0FBTyxFQUFFLENBQUE7UUFDYixDQUFDO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFxQjtRQUNoRCxNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDekMsSUFBSSxDQUFDO1lBQ0QsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FDbkMsZ0NBQWdDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFDL0MsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQ25CLENBQUE7WUFFRCxPQUFPLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFBO1FBQzVCLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2IsTUFBTSxJQUFJLG1CQUFXLENBQ2pCLG1CQUFXLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUNsQyxzQ0FBc0MsRUFBRSxLQUFLLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FDL0QsQ0FBQTtRQUNMLENBQUM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLGlCQUFpQixDQUFDLEVBQVU7UUFDOUIsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDLENBQUE7UUFFNUMsSUFBSSxDQUFDO1lBQ0QsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxTQUFTLElBQUksRUFBRSxFQUFFO2dCQUN4RCxLQUFLLEVBQUU7b0JBQ0gsTUFBTSxFQUFFLEVBQUUsQ0FBQyxtQkFBbUIsRUFBRSxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUU7aUJBQ2xEO2FBQ0osQ0FBQyxDQUFBO1lBRUYsT0FBTyxRQUFRLENBQUMsSUFBSSxDQUFBO1FBQ3hCLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2IsTUFBTSxJQUFJLG1CQUFXLENBQ2pCLG1CQUFXLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUNsQywrQ0FBK0MsRUFBRSxLQUFLLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FDeEUsQ0FBQTtRQUNMLENBQUM7SUFDTCxDQUFDO0NBQ0o7QUFFRCxrQkFBZSxtQkFBbUIsQ0FBQSJ9