From d4905e36218c090791b1deaef9b7cc9100748933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20Arda=20Kavakc=C4=B1?= <42360077+dybdeskarphet@users.noreply.github.com> Date: Fri, 1 Jul 2022 15:02:49 +0000 Subject: [PATCH 1/8] Improve translation Change "follow system" translation from "Use system language" to "Use system settings". ("follow system" doesn't have an exact translation in Turkish) --- src/scripts/i18n/tr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/i18n/tr.json b/src/scripts/i18n/tr.json index a5d854f..eb477e6 100644 --- a/src/scripts/i18n/tr.json +++ b/src/scripts/i18n/tr.json @@ -9,7 +9,7 @@ "emptyField": "Bu alan boş olamaz.", "edit": "Düzenle", "delete": "Sil", - "followSystem": "Sistem dili", + "followSystem": "Sistem ayarlarını kullan", "more": "Daha fazla", "close": "Kapat", "search": "Ara", From dbb5758418faddc8f4ee205028b2d8f900babfd9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Jul 2022 05:05:27 +0000 Subject: [PATCH 2/8] Bump terser from 4.7.0 to 4.8.1 Bumps [terser](https://github.com/terser/terser) from 4.7.0 to 4.8.1. - [Release notes](https://github.com/terser/terser/releases) - [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md) - [Commits](https://github.com/terser/terser/commits) --- updated-dependencies: - dependency-name: terser dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4ff4276..0b2f298 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "fluent-reader", - "version": "1.1.1", + "version": "1.1.2", "license": "BSD-3-Clause", "devDependencies": { "@fluentui/react": "^7.126.2", @@ -8138,9 +8138,9 @@ } }, "node_modules/terser": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.7.0.tgz", - "integrity": "sha512-Lfb0RiZcjRDXCC3OSHJpEkxJ9Qeqs6mp2v4jf2MHfy8vGERmVDuvjXdd/EnP5Deme5F2yBRBymKmKHCBg2echw==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", "dev": true, "dependencies": { "commander": "^2.20.0", @@ -16274,9 +16274,9 @@ } }, "terser": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.7.0.tgz", - "integrity": "sha512-Lfb0RiZcjRDXCC3OSHJpEkxJ9Qeqs6mp2v4jf2MHfy8vGERmVDuvjXdd/EnP5Deme5F2yBRBymKmKHCBg2echw==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", "dev": true, "requires": { "commander": "^2.20.0", From 5786561dc3ed2139f97ecad20bc303738c229f6a Mon Sep 17 00:00:00 2001 From: lyle Date: Tue, 6 Sep 2022 02:45:27 +0100 Subject: [PATCH 3/8] added miniflux API service, accompanying settings component --- package-lock.json | 2 +- src/components/settings/service.tsx | 9 + src/components/settings/services/miniflux.tsx | 307 +++++++++++++++++ src/schema-types.ts | 1 + src/scripts/models/service.ts | 3 + src/scripts/models/services/miniflux.ts | 321 ++++++++++++++++++ 6 files changed, 642 insertions(+), 1 deletion(-) create mode 100644 src/components/settings/services/miniflux.tsx create mode 100644 src/scripts/models/services/miniflux.ts diff --git a/package-lock.json b/package-lock.json index 4ff4276..d8e9c97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "fluent-reader", - "version": "1.1.1", + "version": "1.1.2", "license": "BSD-3-Clause", "devDependencies": { "@fluentui/react": "^7.126.2", diff --git a/src/components/settings/service.tsx b/src/components/settings/service.tsx index 59097d0..8fd3ae2 100644 --- a/src/components/settings/service.tsx +++ b/src/components/settings/service.tsx @@ -6,6 +6,7 @@ import FeverConfigsTab from "./services/fever" import FeedbinConfigsTab from "./services/feedbin" import GReaderConfigsTab from "./services/greader" import InoreaderConfigsTab from "./services/inoreader" +import MinifluxConfigsTab from "./services/miniflux" type ServiceTabProps = { configs: ServiceConfigs @@ -41,6 +42,7 @@ export class ServiceTab extends React.Component< { key: SyncService.Feedbin, text: "Feedbin" }, { key: SyncService.GReader, text: "Google Reader API (Beta)" }, { key: SyncService.Inoreader, text: "Inoreader" }, + { key: SyncService.Miniflux, text: "Miniflux" }, { key: -1, text: intl.get("service.suggest") }, ] @@ -88,6 +90,13 @@ export class ServiceTab extends React.Component< exit={this.exitConfigsTab} /> ) + case SyncService.Miniflux: + return ( + + ) default: return null } diff --git a/src/components/settings/services/miniflux.tsx b/src/components/settings/services/miniflux.tsx new file mode 100644 index 0000000..6271af0 --- /dev/null +++ b/src/components/settings/services/miniflux.tsx @@ -0,0 +1,307 @@ +import * as React from "react" +import intl from "react-intl-universal" +import { ServiceConfigsTabProps } from "../service" +import { SyncService } from "../../../schema-types" +import { + Stack, + Icon, + Label, + TextField, + PrimaryButton, + DefaultButton, + Checkbox, + MessageBar, + MessageBarType, + Dropdown, + IDropdownOption, +} from "@fluentui/react" +import DangerButton from "../../utils/danger-button" +import { urlTest } from "../../../scripts/utils" +import LiteExporter from "./lite-exporter" +import { MinifluxConfigs } from "../../../scripts/models/services/miniflux" + +type MinifluxConfigsTabState = { + existing: boolean + endpoint: string + apiKeyAuth: boolean + username: string + password: string + apiKey: string + fetchLimit: number + importGroups: boolean +} + +class MinifluxConfigsTab extends React.Component< + ServiceConfigsTabProps, + MinifluxConfigsTabState +> { + constructor(props: ServiceConfigsTabProps) { + super(props) + const configs = props.configs as MinifluxConfigs + this.state = { + existing: configs.type === SyncService.Miniflux, + endpoint: configs.endpoint || "", + apiKeyAuth: true, + username: "", + password: "", + apiKey: "", + fetchLimit: configs.fetchLimit || 250, + importGroups: true, + } + } + + fetchLimitOptions = (): IDropdownOption[] => [ + { key: 250, text: intl.get("service.fetchLimitNum", { count: 250 }) }, + { key: 500, text: intl.get("service.fetchLimitNum", { count: 500 }) }, + { key: 750, text: intl.get("service.fetchLimitNum", { count: 750 }) }, + { key: 1000, text: intl.get("service.fetchLimitNum", { count: 1000 }) }, + { key: 1500, text: intl.get("service.fetchLimitNum", { count: 1500 }) }, + { + key: Number.MAX_SAFE_INTEGER, + text: intl.get("service.fetchUnlimited"), + }, + ] + onFetchLimitOptionChange = (_, option: IDropdownOption) => { + this.setState({ fetchLimit: option.key as number }) + } + + authenticationOptions = (): IDropdownOption[] => [ + { key: "apiKey", text: "API Key" /*intl.get("service.password")*/ }, + { key: "userPass", text: intl.get("service.username") + "/" + intl.get("service.password")} + ] + onAuthenticationOptionsChange = (_, option: IDropdownOption) => { + this.setState({ apiKeyAuth: option.key == "apiKey" }) + } + + handleInputChange = event => { + const name: string = event.target.name + // @ts-expect-error + this.setState({ [name]: event.target.value }) + } + + checkNotEmpty = (v: string) => { + return !this.state.existing && v.length == 0 + ? intl.get("emptyField") + : "" + } + + validateForm = () => { + return ( + urlTest(this.state.endpoint.trim()) && + (this.state.existing || + this.state.apiKey || + (this.state.username && this.state.password)) + ) + } + + save = async () => { + let configs: MinifluxConfigs + + if (this.state.existing) + { + configs = { + ...this.props.configs, + endpoint: this.state.endpoint, + fetchLimit: this.state.fetchLimit, + } as MinifluxConfigs + + if (this.state.apiKey || this.state.password) configs.authKey = this.state.apiKeyAuth ? this.state.apiKey : + Buffer.from(this.state.username + ":" + this.state.password, 'binary').toString('base64') + } + else + { + configs = { + type: SyncService.Miniflux, + endpoint: this.state.endpoint, + apiKeyAuth: this.state.apiKeyAuth, + authKey: this.state.apiKeyAuth ? this.state.apiKey : + Buffer.from(this.state.username + ":" + this.state.password, 'binary').toString('base64'), + fetchLimit: this.state.fetchLimit, + } + + if (this.state.importGroups) configs.importGroups = true + } + + this.props.blockActions() + const valid = await this.props.authenticate(configs) + + if (valid) { + this.props.save(configs) + this.setState({ existing: true }) + this.props.sync() + } else { + this.props.blockActions() + window.utils.showErrorBox( + intl.get("service.failure"), + intl.get("service.failureHint") + ) + } + } + + remove = async () => { + this.props.exit() + await this.props.remove() + } + + render() { + return ( + <> + {!this.state.existing && ( + + {intl.get("service.overwriteWarning")} + + )} + + + + + + + + + + urlTest(v.trim()) + ? "" + : intl.get("sources.badUrl") + } + validateOnLoad={false} + name="endpoint" + value={this.state.endpoint} + onChange={this.handleInputChange} + /> + + + + + + + + + + + { this.state.apiKeyAuth && + + + + + + + } + { !this.state.apiKeyAuth && + + + + + + + } + { !this.state.apiKeyAuth && + + + + + + + } + + + + + + + + + {!this.state.existing && ( + + this.setState({ importGroups: c }) + } + /> + )} + + + + + + {this.state.existing ? ( + + ) : ( + + )} + + + {this.state.existing && ( + + )} + + + ) + } +} + +export default MinifluxConfigsTab diff --git a/src/schema-types.ts b/src/schema-types.ts index 45dcc77..a6572f0 100644 --- a/src/schema-types.ts +++ b/src/schema-types.ts @@ -59,6 +59,7 @@ export const enum SyncService { Feedbin, GReader, Inoreader, + Miniflux, } export interface ServiceConfigs { type: SyncService diff --git a/src/scripts/models/service.ts b/src/scripts/models/service.ts index cc62d57..6eee7c9 100644 --- a/src/scripts/models/service.ts +++ b/src/scripts/models/service.ts @@ -18,6 +18,7 @@ import { createSourceGroup, addSourceToGroup } from "./group" import { feverServiceHooks } from "./services/fever" import { feedbinServiceHooks } from "./services/feedbin" import { gReaderServiceHooks } from "./services/greader" +import { minifluxServiceHooks} from "./services/miniflux" export interface ServiceHooks { authenticate?: (configs: ServiceConfigs) => Promise @@ -45,6 +46,8 @@ export function getServiceHooksFromType(type: SyncService): ServiceHooks { case SyncService.GReader: case SyncService.Inoreader: return gReaderServiceHooks + case SyncService.Miniflux: + return minifluxServiceHooks default: return {} } diff --git a/src/scripts/models/services/miniflux.ts b/src/scripts/models/services/miniflux.ts new file mode 100644 index 0000000..afff5b9 --- /dev/null +++ b/src/scripts/models/services/miniflux.ts @@ -0,0 +1,321 @@ +import intl from "react-intl-universal" +import { ServiceHooks } from "../service" +import { ServiceConfigs, SyncService } from "../../../schema-types" +import { createSourceGroup } from "../group" +import { RSSSource } from "../source" +import { domParser, htmlDecode } from "../../utils" +import { RSSItem } from "../item" +import { SourceRule } from "../rule" + +// miniflux service configs +export interface MinifluxConfigs extends ServiceConfigs { + type: SyncService.Miniflux + endpoint: string + apiKeyAuth: boolean + authKey: string + fetchLimit: number + lastId?: number +} + +// partial api schema +interface Feed { + id: number + feed_url: string + title: string + category: { title: string } +} + +interface Category { + title: string +} + +interface Entry { + id: number + status: "unread" | "read" | "removed" + title: string + url: string + published_at: string + created_at: string + content: string + author: string + starred: boolean + feed: Feed +} + +interface Entries { + total: number + entries: Entry[] +} + +const APIError = () => new Error(intl.get("service.failure")); + +// base endpoint, authorization with dedicated token or http basic user/pass pair +async function fetchAPI(configs: MinifluxConfigs, endpoint: string = "", method: string = "GET", body: string = null): Promise +{ + try + { + const headers = new Headers(); + headers.append("content-type", "application/x-www-form-urlencoded"); + + configs.apiKeyAuth ? + headers.append("X-Auth-Token", configs.authKey) + : + headers.append("Authorization", `Basic ${configs.authKey}`) + + const response = await fetch(configs.endpoint + "/v1/" + endpoint, { + method: method, + body: body, + headers: headers + }); + + return response; + } + catch(error) + { + console.log(error); + throw APIError(); + } +} + +export const minifluxServiceHooks: ServiceHooks = { + + // poll service info endpoint to verify auth + authenticate: async (configs: MinifluxConfigs) => { + const response = await fetchAPI(configs, "me"); + + if (await response.json().then(json => json.error_message)) + return false + + return true + }, + + // collect sources from service, along with associated groups/categories + updateSources: () => async (dispatch, getState) => { + const configs = getState().service as MinifluxConfigs + + // fetch and create groups in redux + if (configs.importGroups) + { + const groups: Category[] = await fetchAPI(configs, "categories") + .then(response => response.json()) + groups.forEach(group => dispatch(createSourceGroup(group.title))) + } + + // fetch all feeds + const feedResponse = await fetchAPI(configs, "feeds") + const feeds = await feedResponse.json() + + if (feeds === undefined) throw APIError() + + // go through feeds, create typed source while also mapping by group + let sources: RSSSource[] = new Array(); + let groupsMap: Map = new Map() + for (let feed of feeds) + { + let source = new RSSSource(feed.feed_url, feed.title); + // associate service christened id to match in other request + source.serviceRef = feed.id.toString(); + sources.push(source); + groupsMap.set(feed.id.toString(), feed.category.title) + } + + return [sources, groupsMap] + }, + + // fetch entries from after the last fetched id (if exists) + // limit by quantity and maximum safe integer (id) + // NOTE: miniflux endpoint /entries default order with "published at", and does not offer "created_at" + // but does offer id sort, directly correlated with "created". some feeds give strange published_at. + + fetchItems: () => async (_, getState) => { + const state = getState() + const configs = state.service as MinifluxConfigs + let items: Entry[] = new Array() + let entriesResponse: Entries + + // parameters + let min = Number.MAX_SAFE_INTEGER + configs.lastId ? configs.lastId : 0 + // intermediate + const quantity = 100; + let continueId: number + + do + { + try + { + if (continueId) + { + entriesResponse = await fetchAPI(configs, `entries? + order=id + &direction=desc + &after_entry_id=${configs.lastId} + &before_entry_id=${continueId} + &limit=${quantity}`).then(response => response.json()); + } + else + { + entriesResponse = await fetchAPI(configs, `entries? + order=id + &direction=desc + &after_entry_id=${configs.lastId} + &limit=${quantity}`).then(response => response.json()); + } + + items = entriesResponse.entries.concat(items) + continueId = items[items.length-1].id + } + catch + { + break; + } + } + while (min > configs.lastId && + entriesResponse.entries && + entriesResponse.total == 100 && + items.length < configs.fetchLimit) + + // break/return nothing if no new items acquired + if (items.length == 0) return [[], configs] + configs.lastId = items[0].id; + + // get sources that possess ref/id given by service, associate new items + const sourceMap = new Map() + for (let source of Object.values(state.sources)) { + if (source.serviceRef) { + sourceMap.set(source.serviceRef, source) + } + } + + // map item objects to rssitem type while appling rules (if exist) + const parsedItems = items.map(item => { + const source = sourceMap.get(item.feed.id.toString()) + + let parsedItem = { + source: source.sid, + title: item.title, + link: item.url, + date: new Date(item.created_at), + fetchedDate: new Date(), + content: item.content, + snippet: htmlDecode(item.content).trim(), + creator: item.author, + hasRead: Boolean(item.status == "read"), + starred: Boolean(item.starred), + hidden: false, + notify: false, + serviceRef: String(item.id), + } as RSSItem + + + // Try to get the thumbnail of the item + let dom = domParser.parseFromString(item.content, "text/html") + let baseEl = dom.createElement("base") + baseEl.setAttribute( + "href", + parsedItem.link.split("/").slice(0, 3).join("/") + ) + dom.head.append(baseEl) + let img = dom.querySelector("img") + if (img && img.src) + parsedItem.thumb = img.src + + + if (source.rules) + { + SourceRule.applyAll(source.rules, parsedItem) + if (Boolean(item.status == "read") !== parsedItem.hasRead) + minifluxServiceHooks.markRead(parsedItem) + if (Boolean(item.starred) !== Boolean(parsedItem.starred)) + minifluxServiceHooks.markUnread(parsedItem) + } + + return parsedItem + }); + + return [parsedItems, configs] + }, + + // get remote read and star state of articles, for local sync + syncItems: () => async(_, getState) => { + const configs = getState().service as MinifluxConfigs + + const unread: Entries = await fetchAPI(configs, "entries?status=unread") + .then(response => response.json()); + const starred: Entries = await fetchAPI(configs, "entries?starred=true") + .then(response => response.json()); + + return [new Set(unread.entries.map((entry: Entry) => String(entry.id))), new Set(starred.entries.map((entry: Entry) => String(entry.id)))]; + }, + + markRead: (item: RSSItem) => async(_, getState) => { + if (!item.serviceRef) return; + + const body = `{ + "entry_ids": [${item.serviceRef}], + "status": "read" + }` + + const response = await fetchAPI(getState().service as MinifluxConfigs, "entries", "PUT", body) + + if (response.status !== 204) throw APIError(); + }, + + markUnread: (item: RSSItem) => async (_, getState) => { + if (!item.serviceRef) return; + + const body = `{ + "entry_ids": [${item.serviceRef}], + "status": "unread" + }` + await fetchAPI(getState().service as MinifluxConfigs, "entries", "PUT", body) + }, + + // mark entries for source ids as read, relative to date, determined by "before" bool + + // context menu component: + // item - null, item date, either + // group - group sources, null, true + // nav - null, daysago, true + + // if null, state consulted for context sids + + markAllRead: (sids, date, before) => async(_, getState) => { + + const state = getState() + let items = state.feeds[state.page.feedId].iids + .map(iid => state.items[iid]) + .filter(item => item.serviceRef && !item.hasRead) + + if (date) items = items.filter(i => before ? i.date < date : i.date > date) + + const refs = items.map(item => item.serviceRef) + + const body = `{ + "entry_ids": [${refs}], + "status": "read" + }` + + await fetchAPI(getState().service as MinifluxConfigs, "entries", "PUT", body) + }, + + star: (item: RSSItem) => async (_, getState) => { + if (!item.serviceRef) return; + + await fetchAPI(getState().service as MinifluxConfigs, `entries/${item.serviceRef}/bookmark`, "PUT"); + }, + + unstar: (item: RSSItem) => async (_, getState) => { + if (!item.serviceRef) return; + + await fetchAPI(getState().service as MinifluxConfigs, `entries/${item.serviceRef}/bookmark`, "PUT"); + } + +} + + + + + + + From c1d2f4be136ee2d26f254c318ab90286341abb84 Mon Sep 17 00:00:00 2001 From: Mat <4396128+yawks@users.noreply.github.com> Date: Tue, 4 Oct 2022 13:05:21 +0200 Subject: [PATCH 4/8] add nextcloud service --- src/components/settings/service.tsx | 9 + .../settings/services/nextcloud.tsx | 253 +++++++++++++++ src/schema-types.ts | 1 + src/scripts/models/service.ts | 3 + src/scripts/models/services/nextcloud.ts | 305 ++++++++++++++++++ 5 files changed, 571 insertions(+) create mode 100644 src/components/settings/services/nextcloud.tsx create mode 100644 src/scripts/models/services/nextcloud.ts diff --git a/src/components/settings/service.tsx b/src/components/settings/service.tsx index 59097d0..7ff3d85 100644 --- a/src/components/settings/service.tsx +++ b/src/components/settings/service.tsx @@ -6,6 +6,7 @@ import FeverConfigsTab from "./services/fever" import FeedbinConfigsTab from "./services/feedbin" import GReaderConfigsTab from "./services/greader" import InoreaderConfigsTab from "./services/inoreader" +import NextcloudConfigsTab from "./services/nextcloud" type ServiceTabProps = { configs: ServiceConfigs @@ -41,6 +42,7 @@ export class ServiceTab extends React.Component< { key: SyncService.Feedbin, text: "Feedbin" }, { key: SyncService.GReader, text: "Google Reader API (Beta)" }, { key: SyncService.Inoreader, text: "Inoreader" }, + { key: SyncService.Nextcloud, text: "Nextcloud news API" }, { key: -1, text: intl.get("service.suggest") }, ] @@ -88,6 +90,13 @@ export class ServiceTab extends React.Component< exit={this.exitConfigsTab} /> ) + case SyncService.Nextcloud: + return ( + + ) default: return null } diff --git a/src/components/settings/services/nextcloud.tsx b/src/components/settings/services/nextcloud.tsx new file mode 100644 index 0000000..35386fa --- /dev/null +++ b/src/components/settings/services/nextcloud.tsx @@ -0,0 +1,253 @@ +import * as React from "react" +import intl from "react-intl-universal" +import { ServiceConfigsTabProps } from "../service" +import { NextcloudConfigs } from "../../../scripts/models/services/nextcloud" +import { SyncService } from "../../../schema-types" +import { + Stack, + Icon, + Label, + TextField, + PrimaryButton, + DefaultButton, + Checkbox, + MessageBar, + MessageBarType, + Dropdown, + IDropdownOption, +} from "@fluentui/react" +import DangerButton from "../../utils/danger-button" +import { urlTest } from "../../../scripts/utils" +import LiteExporter from "./lite-exporter" + +type NextcloudConfigsTabState = { + existing: boolean + endpoint: string + username: string + password: string + fetchLimit: number + importGroups: boolean +} + +class NextcloudConfigsTab extends React.Component< + ServiceConfigsTabProps, + NextcloudConfigsTabState +> { + constructor(props: ServiceConfigsTabProps) { + super(props) + const configs = props.configs as NextcloudConfigs + this.state = { + existing: configs.type === SyncService.Nextcloud, + endpoint: configs.endpoint || "https://yawks.net/nextcloud/", + username: configs.username || "", + password: "", + fetchLimit: configs.fetchLimit || 250, + importGroups: true, + } + } + + fetchLimitOptions = (): IDropdownOption[] => [ + { key: 250, text: intl.get("service.fetchLimitNum", { count: 250 }) }, + { key: 500, text: intl.get("service.fetchLimitNum", { count: 500 }) }, + { key: 750, text: intl.get("service.fetchLimitNum", { count: 750 }) }, + { key: 1000, text: intl.get("service.fetchLimitNum", { count: 1000 }) }, + { key: 1500, text: intl.get("service.fetchLimitNum", { count: 1500 }) }, + { + key: Number.MAX_SAFE_INTEGER, + text: intl.get("service.fetchUnlimited"), + }, + ] + onFetchLimitOptionChange = (_, option: IDropdownOption) => { + this.setState({ fetchLimit: option.key as number }) + } + + handleInputChange = event => { + const name: string = event.target.name + // @ts-expect-error + this.setState({ [name]: event.target.value }) + } + + checkNotEmpty = (v: string) => { + return !this.state.existing && v.length == 0 + ? intl.get("emptyField") + : "" + } + + validateForm = () => { + return ( + urlTest(this.state.endpoint.trim()) && + (this.state.existing || + (this.state.username && this.state.password)) + ) + } + + save = async () => { + let configs: NextcloudConfigs + if (this.state.existing) { + configs = { + ...this.props.configs, + endpoint: this.state.endpoint, + fetchLimit: this.state.fetchLimit, + } as NextcloudConfigs + if (this.state.password) configs.password = this.state.password + } else { + configs = { + type: SyncService.Nextcloud, + endpoint: this.state.endpoint + "index.php/apps/news/api/v1-3", + username: this.state.username, + password: this.state.password, + fetchLimit: this.state.fetchLimit, + } + if (this.state.importGroups) configs.importGroups = true + } + this.props.blockActions() + const valid = await this.props.authenticate(configs) + if (valid) { + this.props.save(configs) + this.setState({ existing: true }) + this.props.sync() + } else { + this.props.blockActions() + window.utils.showErrorBox( + intl.get("service.failure"), + intl.get("service.failureHint") + ) + } + } + + remove = async () => { + this.props.exit() + await this.props.remove() + } + + render() { + return ( + <> + {!this.state.existing && ( + + {intl.get("service.overwriteWarning")} + + )} + + + + + + + + + + + + urlTest(v.trim()) + ? "" + : intl.get("sources.badUrl") + } + validateOnLoad={false} + name="endpoint" + value={this.state.endpoint} + onChange={this.handleInputChange} + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + {!this.state.existing && ( + + this.setState({ importGroups: c }) + } + /> + )} + + + + + + {this.state.existing ? ( + + ) : ( + + )} + + + {this.state.existing && ( + + )} + + + ) + } +} + +export default NextcloudConfigsTab diff --git a/src/schema-types.ts b/src/schema-types.ts index 45dcc77..6b05811 100644 --- a/src/schema-types.ts +++ b/src/schema-types.ts @@ -59,6 +59,7 @@ export const enum SyncService { Feedbin, GReader, Inoreader, + Nextcloud } export interface ServiceConfigs { type: SyncService diff --git a/src/scripts/models/service.ts b/src/scripts/models/service.ts index cc62d57..51c3987 100644 --- a/src/scripts/models/service.ts +++ b/src/scripts/models/service.ts @@ -18,6 +18,7 @@ import { createSourceGroup, addSourceToGroup } from "./group" import { feverServiceHooks } from "./services/fever" import { feedbinServiceHooks } from "./services/feedbin" import { gReaderServiceHooks } from "./services/greader" +import { nextcloudServiceHooks } from "./services/nextcloud" export interface ServiceHooks { authenticate?: (configs: ServiceConfigs) => Promise @@ -45,6 +46,8 @@ export function getServiceHooksFromType(type: SyncService): ServiceHooks { case SyncService.GReader: case SyncService.Inoreader: return gReaderServiceHooks + case SyncService.Nextcloud: + return nextcloudServiceHooks default: return {} } diff --git a/src/scripts/models/services/nextcloud.ts b/src/scripts/models/services/nextcloud.ts new file mode 100644 index 0000000..86ff545 --- /dev/null +++ b/src/scripts/models/services/nextcloud.ts @@ -0,0 +1,305 @@ +import intl from "react-intl-universal" +import * as db from "../../db" +import lf from "lovefield" +import { ServiceHooks } from "../service" +import { ServiceConfigs, SyncService } from "../../../schema-types" +import { createSourceGroup } from "../group" +import { RSSSource } from "../source" +import { domParser } from "../../utils" +import { RSSItem } from "../item" +import { SourceRule } from "../rule" + +export interface NextcloudConfigs extends ServiceConfigs { + type: SyncService.Nextcloud + endpoint: string + username: string + password: string + fetchLimit: number + lastModified?: number + lastId?: number +} + +async function fetchAPI(configs: NextcloudConfigs, params: string) { + const headers = new Headers() + headers.set( + "Authorization", + "Basic " + btoa(configs.username + ":" + configs.password) + ) + return await fetch(configs.endpoint + params, { headers: headers }) +} + +async function markItems( + configs: NextcloudConfigs, + type: string, + method: string, + refs: number[] +) { + const headers = new Headers() + headers.set( + "Authorization", + "Basic " + btoa(configs.username + ":" + configs.password) + ) + headers.set("Content-Type", "application/json; charset=utf-8") + const promises = new Array>() + while (refs.length > 0) { + const batch = new Array() + while (batch.length < 1000 && refs.length > 0) { + batch.push(refs.pop()) + } + const bodyObject: any = {} + bodyObject["itemIds"] = batch + promises.push( + fetch(configs.endpoint + "/items/" + type + "/multiple", { + method: method, + headers: headers, + body: JSON.stringify(bodyObject), + }) + ) + } + return await Promise.all(promises) +} + +const APIError = () => new Error(intl.get("service.failure")) + +export const nextcloudServiceHooks: ServiceHooks = { + authenticate: async (configs: NextcloudConfigs) => { + try { + const result = await fetchAPI(configs, "/version") + return result.status === 200 + } catch { + return false + } + }, + + updateSources: () => async (dispatch, getState) => { + const configs = getState().service as NextcloudConfigs + const response = await fetchAPI(configs, "/feeds") + if (response.status !== 200) throw APIError() + const feeds = await response.json() + let groupsMap: Map + let groupsByTagId: Map = new Map() + if (configs.importGroups) { + const foldersResponse = await fetchAPI(configs, "/folders") + if (foldersResponse.status !== 200) throw APIError() + const folders = await foldersResponse.json() + const foldersSet = new Set() + groupsMap = new Map() + for (let folder of folders.folders) { + const title = folder.name.trim() + if (!foldersSet.has(title)) { + foldersSet.add(title) + dispatch(createSourceGroup(title)) + } + groupsByTagId.set(String(folder.id), title) + } + } + const sources = feeds.feeds.map(s => { + const source = new RSSSource(s.url, s.title) + source.iconurl = s.faviconLink + source.serviceRef = String(s.id) + if (s.folderId && groupsByTagId.has(String(s.folderId))) { + groupsMap.set(String(s.id), groupsByTagId.get(String(s.folderId))) + } + return source + }) + return [sources, groupsMap] + }, + + syncItems: () => async (_, getState) => { + const configs = getState().service as NextcloudConfigs + const [unreadResponse, starredResponse]= await Promise.all([ + fetchAPI(configs, "/items?getRead=false&type=3&batchSize=-1"), + fetchAPI(configs, "/items?getRead=true&type=2&batchSize=-1"), + ]) + if (unreadResponse.status !== 200 || starredResponse.status !== 200) + throw APIError() + const unread = await unreadResponse.json() + const starred = await starredResponse.json() + return [ + new Set(unread.items.map(i => String(i.id))), + new Set(starred.items.map(i => String(i.id))), + ] + }, + + fetchItems: () => async (_, getState) => { + const state = getState() + const configs = state.service as NextcloudConfigs + let items = new Array() + configs.lastModified = configs.lastModified || 0 + configs.lastId = configs.lastId || 0 + let lastFetched: any + + if (!configs.lastModified || configs.lastModified == 0) { + //first sync + let min = Number.MAX_SAFE_INTEGER + do { + try { + const response = await fetchAPI( + configs, + "/items?getRead=true&type=3&batchSize=125&offset=" + min + ) + if (response.status !== 200) throw APIError() + lastFetched = await response.json() + items = [ ...items, ...lastFetched.items] + min = lastFetched.items.reduce((m, n) => Math.min(m, n.id), min) + } catch (error) { + console.log(error) + break + } + } while ( + lastFetched.items && + lastFetched.items.length >= 125 && + items.length < configs.fetchLimit + ) + } else { + //incremental sync + const response = await fetchAPI( + configs, + "/items/updated?lastModified="+configs.lastModified+"&type=3" + ) + if (response.status !== 200) throw APIError() + lastFetched = (await response.json()).items + items.push( + ...lastFetched.filter( + i => i.id > configs.lastId + ) + ) + + } + const previousLastModified = configs.lastModified + configs.lastModified = items.reduce( + (m, n) => Math.max(m, n.lastModified), + configs.lastModified + ) + configs.lastId = items.reduce( + (m, n) => Math.max(m, n.id), + configs.lastId + ) + console.log("last modified from "+ previousLastModified + " to " + configs.lastModified) + configs.lastModified++ //+1 to avoid fetching articles with same lastModified next time + if (items.length > 0) { + const fidMap = new Map() + for (let source of Object.values(state.sources)) { + if (source.serviceRef) { + fidMap.set(source.serviceRef, source) + } + } + + const parsedItems = new Array() + items.forEach(i => { + if (i.body === null || i.url === null) return + const unreadItem = i.unread + const starredItem = i.starred + const source = fidMap.get(String(i.feedId)) + const dom = domParser.parseFromString(i.body, "text/html") + const item = { + source: source.sid, + title: i.title, + link: i.url, + date: new Date(i.pubDate*1000), + fetchedDate: new Date(i.pubDate*1000), + content: i.body, + snippet: dom.documentElement.textContent.trim(), + creator: i.author, + hasRead: !i.unread, + starred: i.starred, + hidden: false, + notify: false, + serviceRef: String(i.id), + } as RSSItem + if (i.enclosureLink ) { + item.thumb = i.enclosureLink + } else { + let baseEl = dom.createElement("base") + baseEl.setAttribute( + "href", + item.link.split("/").slice(0, 3).join("/") + ) + dom.head.append(baseEl) + let img = dom.querySelector("img") + if (img && img.src) item.thumb = img.src + } + // Apply rules and sync back to the service + if (source.rules) SourceRule.applyAll(source.rules, item) + if (unreadItem && item.hasRead) + markItems( + configs, + item.hasRead ? "read" : "unread", + "POST", + [i.id] + ) + if (starredItem !== Boolean(item.starred)) + markItems( + configs, + item.starred ? "star" : "unstar", + "POST", + [i.id] + ) + + parsedItems.push(item) + }) + return [parsedItems, configs] + } else { + return [[], configs] + } + }, + + markAllRead: (sids, date, before) => async (_, getState) => { + const state = getState() + const configs = state.service as NextcloudConfigs + const predicates: lf.Predicate[] = [ + db.items.source.in(sids), + db.items.hasRead.eq(false), + db.items.serviceRef.isNotNull(), + ] + if (date) { + predicates.push( + before ? db.items.date.lte(date) : db.items.date.gte(date) + ) + } + const query = lf.op.and.apply(null, predicates) + const rows = await db.itemsDB + .select(db.items.serviceRef) + .from(db.items) + .where(query) + .exec() + const refs = rows.map(row => parseInt(row["serviceRef"])) + markItems(configs, "unread", "POST", refs) + }, + + markRead: (item: RSSItem) => async (_, getState) => { + await markItems( + getState().service as NextcloudConfigs, + "read", + "POST", + [parseInt(item.serviceRef)] + ) + }, + + markUnread: (item: RSSItem) => async (_, getState) => { + await markItems( + getState().service as NextcloudConfigs, + "unread", + "POST", + [parseInt(item.serviceRef)] + ) + }, + + star: (item: RSSItem) => async (_, getState) => { + await markItems( + getState().service as NextcloudConfigs, + "star", + "POST", + [parseInt(item.serviceRef)] + ) + }, + + unstar: (item: RSSItem) => async (_, getState) => { + await markItems( + getState().service as NextcloudConfigs, + "unstar", + "POST", + [parseInt(item.serviceRef)] + ) + }, +} From 292fcc3e38d29065e8eede2a3549235d858cdef6 Mon Sep 17 00:00:00 2001 From: Mat <4396128+yawks@users.noreply.github.com> Date: Thu, 6 Oct 2022 13:42:09 +0200 Subject: [PATCH 5/8] change default value --- src/components/settings/services/nextcloud.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/settings/services/nextcloud.tsx b/src/components/settings/services/nextcloud.tsx index 35386fa..11d1f26 100644 --- a/src/components/settings/services/nextcloud.tsx +++ b/src/components/settings/services/nextcloud.tsx @@ -38,7 +38,7 @@ class NextcloudConfigsTab extends React.Component< const configs = props.configs as NextcloudConfigs this.state = { existing: configs.type === SyncService.Nextcloud, - endpoint: configs.endpoint || "https://yawks.net/nextcloud/", + endpoint: configs.endpoint || "https://nextcloud.com/", username: configs.username || "", password: "", fetchLimit: configs.fetchLimit || 250, From 7c31c65fe9ccaeba2839816ab109491428ff4d8e Mon Sep 17 00:00:00 2001 From: Bruce Liu Date: Sat, 15 Oct 2022 12:28:06 -0700 Subject: [PATCH 6/8] update dependencies and miniflux support --- package-lock.json | 1836 +++++------------ package.json | 4 +- src/components/settings/service.tsx | 16 +- src/components/settings/services/miniflux.tsx | 195 +- src/schema-types.ts | 2 +- src/scripts/models/service.ts | 6 +- src/scripts/models/services/miniflux.ts | 478 +++-- 7 files changed, 941 insertions(+), 1596 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0b2f298..659c619 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "fluent-reader", - "version": "1.1.2", + "version": "1.1.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "fluent-reader", - "version": "1.1.2", + "version": "1.1.3", "license": "BSD-3-Clause", "devDependencies": { "@fluentui/react": "^7.126.2", @@ -16,7 +16,7 @@ "@types/react-dom": "^16.9.8", "@types/react-redux": "^7.1.9", "@yang991178/rss-parser": "^3.8.1", - "electron": "^19.0.0", + "electron": "^21.0.1", "electron-builder": "^23.0.3", "electron-react-devtools": "^0.5.3", "electron-store": "^5.2.0", @@ -101,9 +101,9 @@ } }, "node_modules/@electron/universal": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.2.0.tgz", - "integrity": "sha512-eu20BwNsrMPKoe2bZ3/l9c78LclDvxg3PlVXrQf3L50NaUuW5M59gbPytI+V4z7/QMrohUHetQaU0ou+p1UG9Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.2.1.tgz", + "integrity": "sha512-7323HyMh7KBAl/nPDppdLsC87G6RwRU02dy5FPeGB1eS7rUePh55+WNWiDPLhFQqqVPHzh77M69uhmoT8XnwMQ==", "dev": true, "dependencies": { "@malept/cross-spawn-promise": "^1.1.0", @@ -436,9 +436,9 @@ "dev": true }, "node_modules/@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", "dev": true, "optional": true }, @@ -533,9 +533,9 @@ } }, "node_modules/@types/verror": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.5.tgz", - "integrity": "sha512-9UjMCHK5GPgQRoNbqdLIAvAy0EInuiqbW0PBMtVP6B5B2HQJlvoJHM+KodPZMEjOa5VkSc+5LH7xy+cUzQdmHw==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.6.tgz", + "integrity": "sha512-NNm+gdePAX1VGvPcGZCDKQZKYSiAWigKhKaz5KF94hG6f2s8de9Ow5+7AbXoeKxL8gavZfk4UquSAygOF2duEQ==", "dev": true, "optional": true }, @@ -588,6 +588,16 @@ "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", "dev": true }, + "node_modules/@types/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@uifabric/foundation": { "version": "7.7.44", "resolved": "https://registry.npmjs.org/@uifabric/foundation/-/foundation-7.7.44.tgz", @@ -934,15 +944,6 @@ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", "dev": true }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "dependencies": { - "string-width": "^4.1.0" - } - }, "node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -985,35 +986,36 @@ "dev": true }, "node_modules/app-builder-lib": { - "version": "23.0.3", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-23.0.3.tgz", - "integrity": "sha512-1qrtXYHXJfXhzJnMtVGjIva3067F1qYQubl2oBjI61gCBoCHvhghdYJ57XxXTQQ0VxnUhg1/Iaez87uXp8mD8w==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-23.6.0.tgz", + "integrity": "sha512-dQYDuqm/rmy8GSCE6Xl/3ShJg6Ab4bZJMT8KaTKGzT436gl1DN4REP3FCWfXoh75qGTJ+u+WsdnnpO9Jl8nyMA==", "dev": true, "dependencies": { "@develar/schema-utils": "~2.6.5", - "@electron/universal": "1.2.0", + "@electron/universal": "1.2.1", "@malept/flatpak-bundler": "^0.4.0", "7zip-bin": "~5.1.1", "async-exit-hook": "^2.0.1", "bluebird-lst": "^1.0.9", - "builder-util": "23.0.2", - "builder-util-runtime": "9.0.0", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", "chromium-pickle-js": "^0.2.0", - "debug": "^4.3.2", - "ejs": "^3.1.6", + "debug": "^4.3.4", + "ejs": "^3.1.7", "electron-osx-sign": "^0.6.0", - "electron-publish": "23.0.2", + "electron-publish": "23.6.0", "form-data": "^4.0.0", - "fs-extra": "^10.0.0", - "hosted-git-info": "^4.0.2", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", "is-ci": "^3.0.0", - "isbinaryfile": "^4.0.8", + "isbinaryfile": "^4.0.10", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "read-config-file": "6.2.0", "sanitize-filename": "^1.6.3", - "semver": "^7.3.5", + "semver": "^7.3.7", + "tar": "^6.1.11", "temp-file": "^3.4.0" }, "engines": { @@ -1046,6 +1048,33 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/app-builder-lib/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/app-builder-lib/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/app-builder-lib/node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -1055,6 +1084,12 @@ "node": ">= 10.0.0" } }, + "node_modules/app-builder-lib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -1104,9 +1139,9 @@ } }, "node_modules/asar": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/asar/-/asar-3.1.0.tgz", - "integrity": "sha512-vyxPxP5arcAqN4F/ebHd/HhwnAiZtwhglvdmc7BR2f0ywbVNTOpSeyhLDbGXtE/y58hv1oC75TaNIXutnsOZsQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz", + "integrity": "sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==", "dev": true, "dependencies": { "chromium-pickle-js": "^0.2.0", @@ -1426,160 +1461,6 @@ "dev": true, "optional": true }, - "node_modules/boxen": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.0.1.tgz", - "integrity": "sha512-49VBlw+PrWEF51aCmy7QIteYPIFZxSpvqBdP/2itCPPlJ49kj9zg/XPRFrdkne2W+CfwXUls8exMvu1RysZpKA==", - "dev": true, - "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.0", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/boxen/node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/boxen/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/boxen/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/boxen/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1737,7 +1618,7 @@ "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, "engines": { "node": "*" @@ -1771,9 +1652,9 @@ "dev": true }, "node_modules/builder-util": { - "version": "23.0.2", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-23.0.2.tgz", - "integrity": "sha512-HaNHL3axNW/Ms8O1mDx3I07G+ZnZ/TKSWWvorOAPau128cdt9S+lNx5ocbx8deSaHHX4WFXSZVHh3mxlaKJNgg==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-23.6.0.tgz", + "integrity": "sha512-QiQHweYsh8o+U/KNCZFSvISRnvRctb8m/2rB2I1JdByzvNKxPeFLlHFRPQRXab6aYeXc18j9LpsDLJ3sGQmWTQ==", "dev": true, "dependencies": { "@types/debug": "^4.1.6", @@ -1781,10 +1662,10 @@ "7zip-bin": "~5.1.1", "app-builder-bin": "4.0.0", "bluebird-lst": "^1.0.9", - "builder-util-runtime": "9.0.0", + "builder-util-runtime": "9.1.1", "chalk": "^4.1.1", "cross-spawn": "^7.0.3", - "debug": "^4.3.2", + "debug": "^4.3.4", "fs-extra": "^10.0.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", @@ -1796,12 +1677,12 @@ } }, "node_modules/builder-util-runtime": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.0.0.tgz", - "integrity": "sha512-SkpEtSmTkREDHRJnxKEv43aAYp8sYWY8fxYBhGLBLOBIRXeaIp6Kv3lBgSD7uR8jQtC7CA659sqJrpSV6zNvSA==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.1.1.tgz", + "integrity": "sha512-azRhYLEoDvRDR8Dhis4JatELC/jUvYjm4cVSj7n9dauGTOM2eeNn9KS0z6YA6oDsjI1xphjNbY6PZZeHPzzqaw==", "dev": true, "dependencies": { - "debug": "^4.3.2", + "debug": "^4.3.4", "sax": "^1.2.4" }, "engines": { @@ -2147,9 +2028,9 @@ "dev": true }, "node_modules/ci-info": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.1.tgz", - "integrity": "sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", + "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", "dev": true }, "node_modules/cipher-base": { @@ -2201,18 +2082,6 @@ "node": ">= 4.0" } }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cli-truncate": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", @@ -2444,47 +2313,6 @@ "proto-list": "~1.2.1" } }, - "node_modules/configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "dependencies": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/configstore/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/configstore/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/console-browserify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", @@ -2666,15 +2494,6 @@ "node": "*" } }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/css-select": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", @@ -2728,9 +2547,9 @@ } }, "node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -2774,15 +2593,6 @@ "node": ">=4" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -2940,21 +2750,33 @@ "node": ">= 0.6.x" } }, - "node_modules/dmg-builder": { - "version": "23.0.3", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-23.0.3.tgz", - "integrity": "sha512-mBYrHHnSM5PC656TDE+xTGmXIuWHAGmmRfyM+dV0kP+AxtwPof4pAXNQ8COd0/exZQ4dqf72FiPS3B9G9aB5IA==", + "node_modules/dir-compare/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "dependencies": { - "app-builder-lib": "23.0.3", - "builder-util": "23.0.2", - "builder-util-runtime": "9.0.0", + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dmg-builder": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-23.6.0.tgz", + "integrity": "sha512-jFZvY1JohyHarIAlTbfQOk+HnceGjjAdFjVn3n8xlDWKsYNqbO4muca6qXEZTfGXeQMG7TYim6CeS5XKSfSsGA==", + "dev": true, + "dependencies": { + "app-builder-lib": "23.6.0", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", "fs-extra": "^10.0.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" }, "optionalDependencies": { - "dmg-license": "^1.0.9" + "dmg-license": "^1.0.11" } }, "node_modules/dmg-builder/node_modules/fs-extra": { @@ -2996,7 +2818,6 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", - "deprecated": "Disk image license agreements are deprecated by Apple and will probably be removed in a future macOS release. Discussion at: https://github.com/argv-minus-one/dmg-license/issues/11", "dev": true, "optional": true, "os": [ @@ -3164,41 +2985,41 @@ } }, "node_modules/electron": { - "version": "19.0.3", - "resolved": "https://registry.npmjs.org/electron/-/electron-19.0.3.tgz", - "integrity": "sha512-V/8pFkXUOsoHcBzuTYVSbIQKLIwI/FAxfpvbkMazdaO/weZoIf9AN3Qc4Wuo9+489mhelDYc8lSX5N7c6A5n6A==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-21.1.1.tgz", + "integrity": "sha512-EM2hvRJtiS3n54yx25Z0Qv54t3LGG+WjUHf1AOl+PKjQj+fmXnjIgVeIF9pM21kP1BTcyjrgvN6Sff0A45OB6A==", "dev": true, "hasInstallScript": true, "dependencies": { "@electron/get": "^1.14.1", "@types/node": "^16.11.26", - "extract-zip": "^1.0.3" + "extract-zip": "^2.0.1" }, "bin": { "electron": "cli.js" }, "engines": { - "node": ">= 8.6" + "node": ">= 10.17.0" } }, "node_modules/electron-builder": { - "version": "23.0.3", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-23.0.3.tgz", - "integrity": "sha512-0lnTsljAgcOMuIiOjPcoFf+WxOOe/O04hZPgIvvUBXIbz3kolbNu0Xdch1f5WuQ40NdeZI7oqs8Eo395PcuGHQ==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-23.6.0.tgz", + "integrity": "sha512-y8D4zO+HXGCNxFBV/JlyhFnoQ0Y0K7/sFH+XwIbj47pqaW8S6PGYQbjoObolKBR1ddQFPt4rwp4CnwMJrW3HAw==", "dev": true, "dependencies": { "@types/yargs": "^17.0.1", - "app-builder-lib": "23.0.3", - "builder-util": "23.0.2", - "builder-util-runtime": "9.0.0", + "app-builder-lib": "23.6.0", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", "chalk": "^4.1.1", - "dmg-builder": "23.0.3", + "dmg-builder": "23.6.0", "fs-extra": "^10.0.0", "is-ci": "^3.0.0", "lazy-val": "^1.0.5", "read-config-file": "6.2.0", - "update-notifier": "^5.1.0", - "yargs": "^17.0.1" + "simple-update-notifier": "^1.0.7", + "yargs": "^17.5.1" }, "bin": { "electron-builder": "cli.js", @@ -3249,14 +3070,17 @@ } }, "node_modules/electron-builder/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/electron-builder/node_modules/color-convert": { @@ -3313,12 +3137,12 @@ } }, "node_modules/electron-builder/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" @@ -3372,36 +3196,37 @@ } }, "node_modules/electron-builder/node_modules/yargs": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.0.1.tgz", - "integrity": "sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ==", + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", + "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", "dev": true, "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.0.0" }, "engines": { "node": ">=12" } }, "node_modules/electron-builder/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/electron-osx-sign": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.6.0.tgz", "integrity": "sha512-+hiIEb2Xxk6eDKJ2FFlpofCnemCbjbT5jz+BKGpVBrRNT3kWTGs4DfNX6IzGwgi33hUcXF+kFs9JW+r6Wc1LRg==", + "deprecated": "Please use @electron/osx-sign moving forward. Be aware the API is slightly different", "dev": true, "dependencies": { "bluebird": "^3.5.0", @@ -3447,14 +3272,14 @@ "dev": true }, "node_modules/electron-publish": { - "version": "23.0.2", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-23.0.2.tgz", - "integrity": "sha512-8gMYgWqv96lc83FCm85wd+tEyxNTJQK7WKyPkNkO8GxModZqt1GO8S+/vAnFGxilS/7vsrVRXFfqiCDUCSuxEg==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-23.6.0.tgz", + "integrity": "sha512-jPj3y+eIZQJF/+t5SLvsI5eS4mazCbNYqatv5JihbqOstIM13k0d1Z3vAWntvtt13Itl61SO6seicWdioOU5dg==", "dev": true, "dependencies": { "@types/fs-extra": "^9.0.11", - "builder-util": "23.0.2", - "builder-util-runtime": "9.0.0", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", "chalk": "^4.1.1", "fs-extra": "^10.0.0", "lazy-val": "^1.0.5", @@ -3764,15 +3589,6 @@ "node": ">=6" } }, - "node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -4021,35 +3837,40 @@ } }, "node_modules/extract-zip": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", - "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", "dev": true, "dependencies": { - "concat-stream": "^1.6.2", - "debug": "^2.6.9", - "mkdirp": "^0.5.4", + "debug": "^4.1.1", + "get-stream": "^5.1.0", "yauzl": "^2.10.0" }, "bin": { "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" } }, - "node_modules/extract-zip/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "dependencies": { - "ms": "2.0.0" + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/extract-zip/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, "node_modules/extsprintf": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", @@ -4075,7 +3896,7 @@ "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "dependencies": { "pend": "~1.2.0" @@ -4366,6 +4187,18 @@ "node": ">=6 <7 || >=8" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -4481,30 +4314,6 @@ "node": ">=10.0" } }, - "node_modules/global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", - "dev": true, - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/global-dirs/node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", @@ -4739,15 +4548,6 @@ "node": ">=0.10.0" } }, - "node_modules/has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/hash-base": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", @@ -5009,15 +4809,6 @@ "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", "dev": true }, - "node_modules/import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/import-local": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", @@ -5275,34 +5066,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-npm": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", - "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -5321,15 +5084,6 @@ "node": ">=8" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -5399,12 +5153,6 @@ "node": ">=4" } }, - "node_modules/is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true - }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -5626,18 +5374,6 @@ "node": ">=0.10.0" } }, - "node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "dependencies": { - "package-json": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/lazy-val": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", @@ -5777,7 +5513,7 @@ "node_modules/lovefield/node_modules/underscore": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", - "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "integrity": "sha512-cp0oQQyZhUM1kpJDLdGO1jPZHgS/MpzoWYfe9+CM2h/QGDZlqwT2T3YGukuBdaNJ/CAPoeyAZRRHz8JFo176vA==", "dev": true }, "node_modules/lower-case": { @@ -5992,9 +5728,9 @@ "dev": true }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -6009,6 +5745,43 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, + "node_modules/minipass": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", + "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/mississippi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", @@ -6465,30 +6238,6 @@ "node": ">=6" } }, - "node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "dev": true, - "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/package-json/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -6630,7 +6379,7 @@ "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, "node_modules/picomatch": { @@ -6676,25 +6425,25 @@ } }, "node_modules/plist": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz", - "integrity": "sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.6.tgz", + "integrity": "sha512-WiIVYyrp8TD4w8yCvyeIr+lkmrGRd5u0VbRnU+tP/aRLxP/YadJUYOMZJ/6hIa3oUyVCsycXvtNRgd5XBJIbiA==", "dev": true, "dependencies": { "base64-js": "^1.5.1", - "xmlbuilder": "^9.0.7" + "xmlbuilder": "^15.1.1" }, "engines": { "node": ">=6" } }, "node_modules/plist/node_modules/xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", "dev": true, "engines": { - "node": ">=4.0" + "node": ">=8.0" } }, "node_modules/posix-character-classes": { @@ -6851,18 +6600,6 @@ "node": ">=6" } }, - "node_modules/pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "dev": true, - "dependencies": { - "escape-goat": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/qr.js": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", @@ -6917,21 +6654,6 @@ "safe-buffer": "^5.1.0" } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, "node_modules/react": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", @@ -7106,30 +6828,6 @@ "node": ">=0.10.0" } }, - "node_modules/registry-auth-token": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", - "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", - "dev": true, - "dependencies": { - "rc": "^1.2.8" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dev": true, - "dependencies": { - "rc": "^1.2.8" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -7384,6 +7082,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "optional": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -7401,32 +7100,12 @@ "dev": true, "optional": true }, - "node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "dependencies": { - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/semver/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "optional": true, "dependencies": { "yallist": "^4.0.0" }, @@ -7438,7 +7117,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "optional": true }, "node_modules/serialize-error": { "version": "7.0.1", @@ -7544,6 +7224,27 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "node_modules/simple-update-notifier": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", + "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "dev": true, + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/slice-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", @@ -8041,15 +7742,6 @@ "node": ">=0.10.0" } }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/sumchecker": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", @@ -8092,6 +7784,50 @@ "node": ">=6" } }, + "node_modules/tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tar/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/temp-file": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", @@ -8307,7 +8043,7 @@ "node_modules/truncate-utf8-bytes": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", "dev": true, "dependencies": { "utf8-byte-length": "^1.0.1" @@ -8404,13 +8140,13 @@ "node_modules/underscore": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", - "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", + "integrity": "sha512-ZqGrAgaqqZM7LGRzNjLnw5elevWb5M8LEoDMadxIW3OWbcv72wMMgKdwOKpd5Fqxe8choLD8HN3iSj3TUh/giQ==", "dev": true }, "node_modules/underscore.string": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", - "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=", + "integrity": "sha512-yxkabuCaIBnzfIvX3kBxQqCs0ar/bfJwDnFEHJUm/ZrRVhT3IItdRF5cZjARLzEnyQYtIUhsZ2LG2j3HidFOFQ==", "dev": true, "engines": { "node": "*" @@ -8449,18 +8185,6 @@ "imurmurhash": "^0.1.4" } }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -8529,122 +8253,6 @@ "yarn": "*" } }, - "node_modules/update-notifier": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", - "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", - "dev": true, - "dependencies": { - "boxen": "^5.0.0", - "chalk": "^4.1.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.4.0", - "is-npm": "^5.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.1.0", - "pupa": "^2.1.1", - "semver": "^7.3.4", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "node_modules/update-notifier/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/update-notifier/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/update-notifier/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-notifier/node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/update-notifier/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -8700,7 +8308,7 @@ "node_modules/utf8-byte-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", - "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", + "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==", "dev": true }, "node_modules/util": { @@ -9281,18 +8889,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/worker-farm": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", @@ -9415,15 +9011,6 @@ "signal-exit": "^3.0.2" } }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/xml2js": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", @@ -9539,7 +9126,7 @@ "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "dev": true, "dependencies": { "buffer-crc32": "~0.2.3", @@ -9593,9 +9180,9 @@ } }, "@electron/universal": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.2.0.tgz", - "integrity": "sha512-eu20BwNsrMPKoe2bZ3/l9c78LclDvxg3PlVXrQf3L50NaUuW5M59gbPytI+V4z7/QMrohUHetQaU0ou+p1UG9Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.2.1.tgz", + "integrity": "sha512-7323HyMh7KBAl/nPDppdLsC87G6RwRU02dy5FPeGB1eS7rUePh55+WNWiDPLhFQqqVPHzh77M69uhmoT8XnwMQ==", "dev": true, "requires": { "@malept/cross-spawn-promise": "^1.1.0", @@ -9872,9 +9459,9 @@ "dev": true }, "@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", "dev": true, "optional": true }, @@ -9969,9 +9556,9 @@ } }, "@types/verror": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.5.tgz", - "integrity": "sha512-9UjMCHK5GPgQRoNbqdLIAvAy0EInuiqbW0PBMtVP6B5B2HQJlvoJHM+KodPZMEjOa5VkSc+5LH7xy+cUzQdmHw==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.6.tgz", + "integrity": "sha512-NNm+gdePAX1VGvPcGZCDKQZKYSiAWigKhKaz5KF94hG6f2s8de9Ow5+7AbXoeKxL8gavZfk4UquSAygOF2duEQ==", "dev": true, "optional": true }, @@ -10023,6 +9610,16 @@ "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", "dev": true }, + "@types/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "dev": true, + "optional": true, + "requires": { + "@types/node": "*" + } + }, "@uifabric/foundation": { "version": "7.7.44", "resolved": "https://registry.npmjs.org/@uifabric/foundation/-/foundation-7.7.44.tgz", @@ -10358,15 +9955,6 @@ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", "dev": true }, - "ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "requires": { - "string-width": "^4.1.0" - } - }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -10400,35 +9988,36 @@ "dev": true }, "app-builder-lib": { - "version": "23.0.3", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-23.0.3.tgz", - "integrity": "sha512-1qrtXYHXJfXhzJnMtVGjIva3067F1qYQubl2oBjI61gCBoCHvhghdYJ57XxXTQQ0VxnUhg1/Iaez87uXp8mD8w==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-23.6.0.tgz", + "integrity": "sha512-dQYDuqm/rmy8GSCE6Xl/3ShJg6Ab4bZJMT8KaTKGzT436gl1DN4REP3FCWfXoh75qGTJ+u+WsdnnpO9Jl8nyMA==", "dev": true, "requires": { "@develar/schema-utils": "~2.6.5", - "@electron/universal": "1.2.0", + "@electron/universal": "1.2.1", "@malept/flatpak-bundler": "^0.4.0", "7zip-bin": "~5.1.1", "async-exit-hook": "^2.0.1", "bluebird-lst": "^1.0.9", - "builder-util": "23.0.2", - "builder-util-runtime": "9.0.0", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", "chromium-pickle-js": "^0.2.0", - "debug": "^4.3.2", - "ejs": "^3.1.6", + "debug": "^4.3.4", + "ejs": "^3.1.7", "electron-osx-sign": "^0.6.0", - "electron-publish": "23.0.2", + "electron-publish": "23.6.0", "form-data": "^4.0.0", - "fs-extra": "^10.0.0", - "hosted-git-info": "^4.0.2", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", "is-ci": "^3.0.0", - "isbinaryfile": "^4.0.8", + "isbinaryfile": "^4.0.10", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "read-config-file": "6.2.0", "sanitize-filename": "^1.6.3", - "semver": "^7.3.5", + "semver": "^7.3.7", + "tar": "^6.1.11", "temp-file": "^3.4.0" }, "dependencies": { @@ -10453,11 +10042,35 @@ "universalify": "^2.0.0" } }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, @@ -10498,9 +10111,9 @@ "dev": true }, "asar": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/asar/-/asar-3.1.0.tgz", - "integrity": "sha512-vyxPxP5arcAqN4F/ebHd/HhwnAiZtwhglvdmc7BR2f0ywbVNTOpSeyhLDbGXtE/y58hv1oC75TaNIXutnsOZsQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz", + "integrity": "sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==", "dev": true, "requires": { "@types/glob": "^7.1.1", @@ -10763,111 +10376,6 @@ "dev": true, "optional": true }, - "boxen": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.0.1.tgz", - "integrity": "sha512-49VBlw+PrWEF51aCmy7QIteYPIFZxSpvqBdP/2itCPPlJ49kj9zg/XPRFrdkne2W+CfwXUls8exMvu1RysZpKA==", - "dev": true, - "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.0", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -11023,7 +10531,7 @@ "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true }, "buffer-equal": { @@ -11051,9 +10559,9 @@ "dev": true }, "builder-util": { - "version": "23.0.2", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-23.0.2.tgz", - "integrity": "sha512-HaNHL3axNW/Ms8O1mDx3I07G+ZnZ/TKSWWvorOAPau128cdt9S+lNx5ocbx8deSaHHX4WFXSZVHh3mxlaKJNgg==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-23.6.0.tgz", + "integrity": "sha512-QiQHweYsh8o+U/KNCZFSvISRnvRctb8m/2rB2I1JdByzvNKxPeFLlHFRPQRXab6aYeXc18j9LpsDLJ3sGQmWTQ==", "dev": true, "requires": { "@types/debug": "^4.1.6", @@ -11061,10 +10569,10 @@ "7zip-bin": "~5.1.1", "app-builder-bin": "4.0.0", "bluebird-lst": "^1.0.9", - "builder-util-runtime": "9.0.0", + "builder-util-runtime": "9.1.1", "chalk": "^4.1.1", "cross-spawn": "^7.0.3", - "debug": "^4.3.2", + "debug": "^4.3.4", "fs-extra": "^10.0.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", @@ -11195,12 +10703,12 @@ } }, "builder-util-runtime": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.0.0.tgz", - "integrity": "sha512-SkpEtSmTkREDHRJnxKEv43aAYp8sYWY8fxYBhGLBLOBIRXeaIp6Kv3lBgSD7uR8jQtC7CA659sqJrpSV6zNvSA==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.1.1.tgz", + "integrity": "sha512-azRhYLEoDvRDR8Dhis4JatELC/jUvYjm4cVSj7n9dauGTOM2eeNn9KS0z6YA6oDsjI1xphjNbY6PZZeHPzzqaw==", "dev": true, "requires": { - "debug": "^4.3.2", + "debug": "^4.3.4", "sax": "^1.2.4" } }, @@ -11356,9 +10864,9 @@ "dev": true }, "ci-info": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.1.tgz", - "integrity": "sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", + "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", "dev": true }, "cipher-base": { @@ -11403,12 +10911,6 @@ "source-map": "~0.6.0" } }, - "cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true - }, "cli-truncate": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", @@ -11602,37 +11104,6 @@ "proto-list": "~1.2.1" } }, - "configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, "console-browserify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", @@ -11791,12 +11262,6 @@ "randomfill": "^1.0.3" } }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true - }, "css-select": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", @@ -11838,9 +11303,9 @@ } }, "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -11867,12 +11332,6 @@ "mimic-response": "^1.0.0" } }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, "defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -12003,19 +11462,28 @@ "requires": { "graceful-readlink": ">= 1.0.0" } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } } } }, "dmg-builder": { - "version": "23.0.3", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-23.0.3.tgz", - "integrity": "sha512-mBYrHHnSM5PC656TDE+xTGmXIuWHAGmmRfyM+dV0kP+AxtwPof4pAXNQ8COd0/exZQ4dqf72FiPS3B9G9aB5IA==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-23.6.0.tgz", + "integrity": "sha512-jFZvY1JohyHarIAlTbfQOk+HnceGjjAdFjVn3n8xlDWKsYNqbO4muca6qXEZTfGXeQMG7TYim6CeS5XKSfSsGA==", "dev": true, "requires": { - "app-builder-lib": "23.0.3", - "builder-util": "23.0.2", - "builder-util-runtime": "9.0.0", - "dmg-license": "^1.0.9", + "app-builder-lib": "23.6.0", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", + "dmg-license": "^1.0.11", "fs-extra": "^10.0.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" @@ -12178,34 +11646,34 @@ } }, "electron": { - "version": "19.0.3", - "resolved": "https://registry.npmjs.org/electron/-/electron-19.0.3.tgz", - "integrity": "sha512-V/8pFkXUOsoHcBzuTYVSbIQKLIwI/FAxfpvbkMazdaO/weZoIf9AN3Qc4Wuo9+489mhelDYc8lSX5N7c6A5n6A==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-21.1.1.tgz", + "integrity": "sha512-EM2hvRJtiS3n54yx25Z0Qv54t3LGG+WjUHf1AOl+PKjQj+fmXnjIgVeIF9pM21kP1BTcyjrgvN6Sff0A45OB6A==", "dev": true, "requires": { "@electron/get": "^1.14.1", "@types/node": "^16.11.26", - "extract-zip": "^1.0.3" + "extract-zip": "^2.0.1" } }, "electron-builder": { - "version": "23.0.3", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-23.0.3.tgz", - "integrity": "sha512-0lnTsljAgcOMuIiOjPcoFf+WxOOe/O04hZPgIvvUBXIbz3kolbNu0Xdch1f5WuQ40NdeZI7oqs8Eo395PcuGHQ==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-23.6.0.tgz", + "integrity": "sha512-y8D4zO+HXGCNxFBV/JlyhFnoQ0Y0K7/sFH+XwIbj47pqaW8S6PGYQbjoObolKBR1ddQFPt4rwp4CnwMJrW3HAw==", "dev": true, "requires": { "@types/yargs": "^17.0.1", - "app-builder-lib": "23.0.3", - "builder-util": "23.0.2", - "builder-util-runtime": "9.0.0", + "app-builder-lib": "23.6.0", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", "chalk": "^4.1.1", - "dmg-builder": "23.0.3", + "dmg-builder": "23.6.0", "fs-extra": "^10.0.0", "is-ci": "^3.0.0", "lazy-val": "^1.0.5", "read-config-file": "6.2.0", - "update-notifier": "^5.1.0", - "yargs": "^17.0.1" + "simple-update-notifier": "^1.0.7", + "yargs": "^17.5.1" }, "dependencies": { "ansi-regex": { @@ -12234,13 +11702,13 @@ } }, "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "requires": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, @@ -12287,12 +11755,12 @@ } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" } }, "supports-color": { @@ -12328,24 +11796,24 @@ "dev": true }, "yargs": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.0.1.tgz", - "integrity": "sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ==", + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", + "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", "dev": true, "requires": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.0.0" } }, "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true } } @@ -12391,14 +11859,14 @@ } }, "electron-publish": { - "version": "23.0.2", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-23.0.2.tgz", - "integrity": "sha512-8gMYgWqv96lc83FCm85wd+tEyxNTJQK7WKyPkNkO8GxModZqt1GO8S+/vAnFGxilS/7vsrVRXFfqiCDUCSuxEg==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-23.6.0.tgz", + "integrity": "sha512-jPj3y+eIZQJF/+t5SLvsI5eS4mazCbNYqatv5JihbqOstIM13k0d1Z3vAWntvtt13Itl61SO6seicWdioOU5dg==", "dev": true, "requires": { "@types/fs-extra": "^9.0.11", - "builder-util": "23.0.2", - "builder-util-runtime": "9.0.0", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", "chalk": "^4.1.1", "fs-extra": "^10.0.0", "lazy-val": "^1.0.5", @@ -12652,12 +12120,6 @@ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, - "escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -12858,31 +12320,25 @@ } }, "extract-zip": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", - "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", "dev": true, "requires": { - "concat-stream": "^1.6.2", - "debug": "^2.6.9", - "mkdirp": "^0.5.4", + "@types/yauzl": "^2.9.1", + "debug": "^4.1.1", + "get-stream": "^5.1.0", "yauzl": "^2.10.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "requires": { - "ms": "2.0.0" + "pump": "^3.0.0" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, @@ -12908,7 +12364,7 @@ "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "requires": { "pend": "~1.2.0" @@ -13158,6 +12614,15 @@ "universalify": "^0.1.0" } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -13249,23 +12714,6 @@ "serialize-error": "^7.0.1" } }, - "global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", - "dev": true, - "requires": { - "ini": "2.0.0" - }, - "dependencies": { - "ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true - } - } - }, "global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", @@ -13457,12 +12905,6 @@ } } }, - "has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true - }, "hash-base": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", @@ -13679,12 +13121,6 @@ "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", "dev": true }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true - }, "import-local": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", @@ -13894,22 +13330,6 @@ "is-extglob": "^2.1.1" } }, - "is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "requires": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - } - }, - "is-npm": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", - "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", - "dev": true - }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -13922,12 +13342,6 @@ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -13979,12 +13393,6 @@ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", "dev": true }, - "is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true - }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -14163,15 +13571,6 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, - "latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "requires": { - "package-json": "^6.3.0" - } - }, "lazy-val": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", @@ -14283,7 +13682,7 @@ "underscore": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", - "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "integrity": "sha512-cp0oQQyZhUM1kpJDLdGO1jPZHgS/MpzoWYfe9+CM2h/QGDZlqwT2T3YGukuBdaNJ/CAPoeyAZRRHz8JFo176vA==", "dev": true } } @@ -14456,9 +13855,9 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -14470,6 +13869,41 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, + "minipass": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", + "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, "mississippi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", @@ -14857,26 +14291,6 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "dev": true, - "requires": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, "pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -14997,7 +14411,7 @@ "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, "picomatch": { @@ -15031,19 +14445,19 @@ } }, "plist": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz", - "integrity": "sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.6.tgz", + "integrity": "sha512-WiIVYyrp8TD4w8yCvyeIr+lkmrGRd5u0VbRnU+tP/aRLxP/YadJUYOMZJ/6hIa3oUyVCsycXvtNRgd5XBJIbiA==", "dev": true, "requires": { "base64-js": "^1.5.1", - "xmlbuilder": "^9.0.7" + "xmlbuilder": "^15.1.1" }, "dependencies": { "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", "dev": true } } @@ -15185,15 +14599,6 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "dev": true, - "requires": { - "escape-goat": "^2.0.0" - } - }, "qr.js": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", @@ -15242,18 +14647,6 @@ "safe-buffer": "^5.1.0" } }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, "react": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", @@ -15412,24 +14805,6 @@ "safe-regex": "^1.1.0" } }, - "registry-auth-token": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", - "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", - "dev": true, - "requires": { - "rc": "^1.2.8" - } - }, - "registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dev": true, - "requires": { - "rc": "^1.2.8" - } - }, "relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -15650,6 +15025,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "optional": true, "requires": { "lru-cache": "^6.0.0" }, @@ -15659,6 +15035,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "optional": true, "requires": { "yallist": "^4.0.0" } @@ -15667,7 +15044,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "optional": true } } }, @@ -15678,23 +15056,6 @@ "dev": true, "optional": true }, - "semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, "serialize-error": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", @@ -15780,6 +15141,23 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "simple-update-notifier": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", + "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "dev": true, + "requires": { + "semver": "~7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, "slice-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", @@ -16198,12 +15576,6 @@ "ansi-regex": "^2.0.0" } }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, "sumchecker": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", @@ -16234,6 +15606,40 @@ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, + "tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, "temp-file": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", @@ -16413,7 +15819,7 @@ "truncate-utf8-bytes": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", "dev": true, "requires": { "utf8-byte-length": "^1.0.1" @@ -16490,13 +15896,13 @@ "underscore": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", - "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", + "integrity": "sha512-ZqGrAgaqqZM7LGRzNjLnw5elevWb5M8LEoDMadxIW3OWbcv72wMMgKdwOKpd5Fqxe8choLD8HN3iSj3TUh/giQ==", "dev": true }, "underscore.string": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", - "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=", + "integrity": "sha512-yxkabuCaIBnzfIvX3kBxQqCs0ar/bfJwDnFEHJUm/ZrRVhT3IItdRF5cZjARLzEnyQYtIUhsZ2LG2j3HidFOFQ==", "dev": true }, "union-value": { @@ -16529,15 +15935,6 @@ "imurmurhash": "^0.1.4" } }, - "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "requires": { - "crypto-random-string": "^2.0.0" - } - }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -16591,94 +15988,6 @@ "dev": true, "optional": true }, - "update-notifier": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", - "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", - "dev": true, - "requires": { - "boxen": "^5.0.0", - "chalk": "^4.1.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.4.0", - "is-npm": "^5.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.1.0", - "pupa": "^2.1.1", - "semver": "^7.3.4", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -16730,7 +16039,7 @@ "utf8-byte-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", - "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", + "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==", "dev": true }, "util": { @@ -17239,15 +16548,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "requires": { - "string-width": "^4.0.0" - } - }, "worker-farm": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", @@ -17356,12 +16656,6 @@ } } }, - "xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true - }, "xml2js": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", @@ -17461,7 +16755,7 @@ "yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "dev": true, "requires": { "buffer-crc32": "~0.2.3", diff --git a/package.json b/package.json index f16740c..4a226ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fluent-reader", - "version": "1.1.2", + "version": "1.1.3", "description": "Modern desktop RSS reader", "main": "./dist/electron.js", "scripts": { @@ -26,7 +26,7 @@ "@types/react-dom": "^16.9.8", "@types/react-redux": "^7.1.9", "@yang991178/rss-parser": "^3.8.1", - "electron": "^19.0.0", + "electron": "^21.0.1", "electron-builder": "^23.0.3", "electron-react-devtools": "^0.5.3", "electron-store": "^5.2.0", diff --git a/src/components/settings/service.tsx b/src/components/settings/service.tsx index 8fd3ae2..441f7e2 100644 --- a/src/components/settings/service.tsx +++ b/src/components/settings/service.tsx @@ -42,7 +42,7 @@ export class ServiceTab extends React.Component< { key: SyncService.Feedbin, text: "Feedbin" }, { key: SyncService.GReader, text: "Google Reader API (Beta)" }, { key: SyncService.Inoreader, text: "Inoreader" }, - { key: SyncService.Miniflux, text: "Miniflux" }, + { key: SyncService.Miniflux, text: "Miniflux" }, { key: -1, text: intl.get("service.suggest") }, ] @@ -90,13 +90,13 @@ export class ServiceTab extends React.Component< exit={this.exitConfigsTab} /> ) - case SyncService.Miniflux: - return ( - - ) + case SyncService.Miniflux: + return ( + + ) default: return null } diff --git a/src/components/settings/services/miniflux.tsx b/src/components/settings/services/miniflux.tsx index 6271af0..32bdc04 100644 --- a/src/components/settings/services/miniflux.tsx +++ b/src/components/settings/services/miniflux.tsx @@ -23,10 +23,10 @@ import { MinifluxConfigs } from "../../../scripts/models/services/miniflux" type MinifluxConfigsTabState = { existing: boolean endpoint: string - apiKeyAuth: boolean - username: string - password: string - apiKey: string + apiKeyAuth: boolean + username: string + password: string + apiKey: string fetchLimit: number importGroups: boolean } @@ -37,13 +37,13 @@ class MinifluxConfigsTab extends React.Component< > { constructor(props: ServiceConfigsTabProps) { super(props) - const configs = props.configs as MinifluxConfigs + const configs = props.configs as MinifluxConfigs this.state = { existing: configs.type === SyncService.Miniflux, endpoint: configs.endpoint || "", apiKeyAuth: true, - username: "", - password: "", + username: "", + password: "", apiKey: "", fetchLimit: configs.fetchLimit || 250, importGroups: true, @@ -65,13 +65,19 @@ class MinifluxConfigsTab extends React.Component< this.setState({ fetchLimit: option.key as number }) } - authenticationOptions = (): IDropdownOption[] => [ - { key: "apiKey", text: "API Key" /*intl.get("service.password")*/ }, - { key: "userPass", text: intl.get("service.username") + "/" + intl.get("service.password")} - ] - onAuthenticationOptionsChange = (_, option: IDropdownOption) => { - this.setState({ apiKeyAuth: option.key == "apiKey" }) - } + authenticationOptions = (): IDropdownOption[] => [ + { key: "apiKey", text: "API Key" /*intl.get("service.password")*/ }, + { + key: "userPass", + text: + intl.get("service.username") + + "/" + + intl.get("service.password"), + }, + ] + onAuthenticationOptionsChange = (_, option: IDropdownOption) => { + this.setState({ apiKeyAuth: option.key == "apiKey" }) + } handleInputChange = event => { const name: string = event.target.name @@ -89,33 +95,39 @@ class MinifluxConfigsTab extends React.Component< return ( urlTest(this.state.endpoint.trim()) && (this.state.existing || - this.state.apiKey || + this.state.apiKey || (this.state.username && this.state.password)) ) } save = async () => { - let configs: MinifluxConfigs + let configs: MinifluxConfigs - if (this.state.existing) - { + if (this.state.existing) { configs = { ...this.props.configs, endpoint: this.state.endpoint, fetchLimit: this.state.fetchLimit, - } as MinifluxConfigs + } as MinifluxConfigs - if (this.state.apiKey || this.state.password) configs.authKey = this.state.apiKeyAuth ? this.state.apiKey : - Buffer.from(this.state.username + ":" + this.state.password, 'binary').toString('base64') - } - else - { + if (this.state.apiKey || this.state.password) + configs.authKey = this.state.apiKeyAuth + ? this.state.apiKey + : Buffer.from( + this.state.username + ":" + this.state.password, + "binary" + ).toString("base64") + } else { configs = { type: SyncService.Miniflux, endpoint: this.state.endpoint, apiKeyAuth: this.state.apiKeyAuth, - authKey: this.state.apiKeyAuth ? this.state.apiKey : - Buffer.from(this.state.username + ":" + this.state.password, 'binary').toString('base64'), + authKey: this.state.apiKeyAuth + ? this.state.apiKey + : Buffer.from( + this.state.username + ":" + this.state.password, + "binary" + ).toString("base64"), fetchLimit: this.state.fetchLimit, } @@ -160,9 +172,7 @@ class MinifluxConfigsTab extends React.Component< userSelect: "none", }} /> - + @@ -188,66 +198,76 @@ class MinifluxConfigsTab extends React.Component< - { this.state.apiKeyAuth && - - - - - - - } - { !this.state.apiKeyAuth && - - - - - - - } - { !this.state.apiKeyAuth && - - - - - - - } + {this.state.apiKeyAuth && ( + + + + + + + + + )} + {!this.state.apiKeyAuth && ( + + + + + + + + + )} + {!this.state.apiKeyAuth && ( + + + + + + + + + )} @@ -295,13 +315,10 @@ class MinifluxConfigsTab extends React.Component< )} - {this.state.existing && ( - - )} ) } } -export default MinifluxConfigsTab +export default MinifluxConfigsTab diff --git a/src/schema-types.ts b/src/schema-types.ts index a6572f0..f7a7026 100644 --- a/src/schema-types.ts +++ b/src/schema-types.ts @@ -59,7 +59,7 @@ export const enum SyncService { Feedbin, GReader, Inoreader, - Miniflux, + Miniflux, } export interface ServiceConfigs { type: SyncService diff --git a/src/scripts/models/service.ts b/src/scripts/models/service.ts index 6eee7c9..4e7bf34 100644 --- a/src/scripts/models/service.ts +++ b/src/scripts/models/service.ts @@ -18,7 +18,7 @@ import { createSourceGroup, addSourceToGroup } from "./group" import { feverServiceHooks } from "./services/fever" import { feedbinServiceHooks } from "./services/feedbin" import { gReaderServiceHooks } from "./services/greader" -import { minifluxServiceHooks} from "./services/miniflux" +import { minifluxServiceHooks } from "./services/miniflux" export interface ServiceHooks { authenticate?: (configs: ServiceConfigs) => Promise @@ -46,8 +46,8 @@ export function getServiceHooksFromType(type: SyncService): ServiceHooks { case SyncService.GReader: case SyncService.Inoreader: return gReaderServiceHooks - case SyncService.Miniflux: - return minifluxServiceHooks + case SyncService.Miniflux: + return minifluxServiceHooks default: return {} } diff --git a/src/scripts/models/services/miniflux.ts b/src/scripts/models/services/miniflux.ts index afff5b9..b4d2955 100644 --- a/src/scripts/models/services/miniflux.ts +++ b/src/scripts/models/services/miniflux.ts @@ -1,4 +1,6 @@ import intl from "react-intl-universal" +import * as db from "../../db" +import lf from "lovefield" import { ServiceHooks } from "../service" import { ServiceConfigs, SyncService } from "../../../schema-types" import { createSourceGroup } from "../group" @@ -11,311 +13,343 @@ import { SourceRule } from "../rule" export interface MinifluxConfigs extends ServiceConfigs { type: SyncService.Miniflux endpoint: string - apiKeyAuth: boolean + apiKeyAuth: boolean authKey: string fetchLimit: number - lastId?: number + lastId?: number } // partial api schema interface Feed { - id: number - feed_url: string - title: string - category: { title: string } + id: number + feed_url: string + title: string + category: { title: string } } interface Category { - title: string + title: string } interface Entry { - id: number - status: "unread" | "read" | "removed" - title: string - url: string - published_at: string - created_at: string - content: string - author: string - starred: boolean - feed: Feed + id: number + status: "unread" | "read" | "removed" + title: string + url: string + published_at: string + created_at: string + content: string + author: string + starred: boolean + feed: Feed } interface Entries { - total: number - entries: Entry[] + total: number + entries: Entry[] } -const APIError = () => new Error(intl.get("service.failure")); +const APIError = () => new Error(intl.get("service.failure")) // base endpoint, authorization with dedicated token or http basic user/pass pair -async function fetchAPI(configs: MinifluxConfigs, endpoint: string = "", method: string = "GET", body: string = null): Promise -{ - try - { - const headers = new Headers(); - headers.append("content-type", "application/x-www-form-urlencoded"); +async function fetchAPI( + configs: MinifluxConfigs, + endpoint: string = "", + method: string = "GET", + body: string = null +): Promise { + try { + const headers = new Headers() + headers.append("content-type", "application/x-www-form-urlencoded") - configs.apiKeyAuth ? - headers.append("X-Auth-Token", configs.authKey) - : - headers.append("Authorization", `Basic ${configs.authKey}`) + configs.apiKeyAuth + ? headers.append("X-Auth-Token", configs.authKey) + : headers.append("Authorization", `Basic ${configs.authKey}`) - const response = await fetch(configs.endpoint + "/v1/" + endpoint, { - method: method, - body: body, - headers: headers - }); - - return response; - } - catch(error) - { - console.log(error); - throw APIError(); - } + let baseUrl = configs.endpoint + if (!baseUrl.endsWith("/")) baseUrl = baseUrl + "/" + if (!baseUrl.endsWith("/v1/")) baseUrl = baseUrl + "v1/" + const response = await fetch(baseUrl + endpoint, { + method: method, + body: body, + headers: headers, + }) + + return response + } catch (error) { + console.log(error) + throw APIError() + } } export const minifluxServiceHooks: ServiceHooks = { + // poll service info endpoint to verify auth + authenticate: async (configs: MinifluxConfigs) => { + const response = await fetchAPI(configs, "me") - // poll service info endpoint to verify auth - authenticate: async (configs: MinifluxConfigs) => { - const response = await fetchAPI(configs, "me"); - - if (await response.json().then(json => json.error_message)) - return false + if (await response.json().then(json => json.error_message)) return false - return true - }, + return true + }, - // collect sources from service, along with associated groups/categories - updateSources: () => async (dispatch, getState) => { - const configs = getState().service as MinifluxConfigs + // collect sources from service, along with associated groups/categories + updateSources: () => async (dispatch, getState) => { + const configs = getState().service as MinifluxConfigs - // fetch and create groups in redux - if (configs.importGroups) - { - const groups: Category[] = await fetchAPI(configs, "categories") - .then(response => response.json()) - groups.forEach(group => dispatch(createSourceGroup(group.title))) - } + // fetch and create groups in redux + if (configs.importGroups) { + const groups: Category[] = await fetchAPI( + configs, + "categories" + ).then(response => response.json()) + groups.forEach(group => dispatch(createSourceGroup(group.title))) + } - // fetch all feeds - const feedResponse = await fetchAPI(configs, "feeds") - const feeds = await feedResponse.json() + // fetch all feeds + const feedResponse = await fetchAPI(configs, "feeds") + const feeds = await feedResponse.json() - if (feeds === undefined) throw APIError() + if (feeds === undefined) throw APIError() - // go through feeds, create typed source while also mapping by group - let sources: RSSSource[] = new Array(); - let groupsMap: Map = new Map() - for (let feed of feeds) - { - let source = new RSSSource(feed.feed_url, feed.title); - // associate service christened id to match in other request - source.serviceRef = feed.id.toString(); - sources.push(source); - groupsMap.set(feed.id.toString(), feed.category.title) - } + // go through feeds, create typed source while also mapping by group + let sources: RSSSource[] = new Array() + let groupsMap: Map = new Map() + for (let feed of feeds) { + let source = new RSSSource(feed.feed_url, feed.title) + // associate service christened id to match in other request + source.serviceRef = feed.id.toString() + sources.push(source) + groupsMap.set(feed.id.toString(), feed.category.title) + } - return [sources, groupsMap] - }, + return [sources, configs.importGroups ? groupsMap : undefined] + }, - // fetch entries from after the last fetched id (if exists) - // limit by quantity and maximum safe integer (id) - // NOTE: miniflux endpoint /entries default order with "published at", and does not offer "created_at" - // but does offer id sort, directly correlated with "created". some feeds give strange published_at. - - fetchItems: () => async (_, getState) => { - const state = getState() - const configs = state.service as MinifluxConfigs - let items: Entry[] = new Array() - let entriesResponse: Entries + // fetch entries from after the last fetched id (if exists) + // limit by quantity and maximum safe integer (id) + // NOTE: miniflux endpoint /entries default order with "published at", and does not offer "created_at" + // but does offer id sort, directly correlated with "created". some feeds give strange published_at. - // parameters - let min = Number.MAX_SAFE_INTEGER - configs.lastId ? configs.lastId : 0 - // intermediate - const quantity = 100; - let continueId: number + fetchItems: () => async (_, getState) => { + const state = getState() + const configs = state.service as MinifluxConfigs + let items: Entry[] = new Array() + let entriesResponse: Entries - do - { - try - { - if (continueId) - { - entriesResponse = await fetchAPI(configs, `entries? + // parameters + configs.lastId = configs.lastId ?? 0 + // intermediate + const quantity = 100 + let continueId: number + + do { + try { + if (continueId) { + entriesResponse = await fetchAPI( + configs, + `entries? order=id &direction=desc &after_entry_id=${configs.lastId} &before_entry_id=${continueId} - &limit=${quantity}`).then(response => response.json()); - } - else - { - entriesResponse = await fetchAPI(configs, `entries? + &limit=${quantity}` + ).then(response => response.json()) + } else { + entriesResponse = await fetchAPI( + configs, + `entries? order=id &direction=desc &after_entry_id=${configs.lastId} - &limit=${quantity}`).then(response => response.json()); - } + &limit=${quantity}` + ).then(response => response.json()) + } - items = entriesResponse.entries.concat(items) - continueId = items[items.length-1].id - } - catch - { - break; - } - } - while (min > configs.lastId && - entriesResponse.entries && - entriesResponse.total == 100 && - items.length < configs.fetchLimit) + items = entriesResponse.entries.concat(items) + continueId = items[items.length - 1].id + } catch { + break + } + } while ( + entriesResponse.entries && + entriesResponse.total === 100 && + items.length < configs.fetchLimit + ) - // break/return nothing if no new items acquired - if (items.length == 0) return [[], configs] - configs.lastId = items[0].id; + // break/return nothing if no new items acquired + if (items.length == 0) return [[], configs] + configs.lastId = items[0].id - // get sources that possess ref/id given by service, associate new items - const sourceMap = new Map() - for (let source of Object.values(state.sources)) { - if (source.serviceRef) { - sourceMap.set(source.serviceRef, source) - } - } + // get sources that possess ref/id given by service, associate new items + const sourceMap = new Map() + for (let source of Object.values(state.sources)) { + if (source.serviceRef) { + sourceMap.set(source.serviceRef, source) + } + } - // map item objects to rssitem type while appling rules (if exist) - const parsedItems = items.map(item => { - const source = sourceMap.get(item.feed.id.toString()) + // map item objects to rssitem type while appling rules (if exist) + const parsedItems = items.map(item => { + const source = sourceMap.get(item.feed.id.toString()) - let parsedItem = { - source: source.sid, - title: item.title, - link: item.url, - date: new Date(item.created_at), - fetchedDate: new Date(), - content: item.content, - snippet: htmlDecode(item.content).trim(), - creator: item.author, - hasRead: Boolean(item.status == "read"), - starred: Boolean(item.starred), - hidden: false, - notify: false, - serviceRef: String(item.id), - } as RSSItem + let parsedItem = { + source: source.sid, + title: item.title, + link: item.url, + date: new Date(item.published_at ?? item.created_at), + fetchedDate: new Date(), + content: item.content, + snippet: htmlDecode(item.content).trim(), + creator: item.author, + hasRead: Boolean(item.status === "read"), + starred: Boolean(item.starred), + hidden: false, + notify: false, + serviceRef: String(item.id), + } as RSSItem + // Try to get the thumbnail of the item + let dom = domParser.parseFromString(item.content, "text/html") + let baseEl = dom.createElement("base") + baseEl.setAttribute( + "href", + parsedItem.link.split("/").slice(0, 3).join("/") + ) + dom.head.append(baseEl) + let img = dom.querySelector("img") + if (img && img.src) parsedItem.thumb = img.src - // Try to get the thumbnail of the item - let dom = domParser.parseFromString(item.content, "text/html") - let baseEl = dom.createElement("base") - baseEl.setAttribute( - "href", - parsedItem.link.split("/").slice(0, 3).join("/") - ) - dom.head.append(baseEl) - let img = dom.querySelector("img") - if (img && img.src) - parsedItem.thumb = img.src + if (source.rules) { + SourceRule.applyAll(source.rules, parsedItem) + if ((item.status === "read") !== parsedItem.hasRead) + minifluxServiceHooks.markRead(parsedItem) + if (item.starred !== parsedItem.starred) + minifluxServiceHooks.markUnread(parsedItem) + } + return parsedItem + }) - if (source.rules) - { - SourceRule.applyAll(source.rules, parsedItem) - if (Boolean(item.status == "read") !== parsedItem.hasRead) - minifluxServiceHooks.markRead(parsedItem) - if (Boolean(item.starred) !== Boolean(parsedItem.starred)) - minifluxServiceHooks.markUnread(parsedItem) - } + return [parsedItems, configs] + }, - return parsedItem - }); + // get remote read and star state of articles, for local sync + syncItems: () => async (_, getState) => { + const configs = getState().service as MinifluxConfigs - return [parsedItems, configs] - }, + const unreadPromise: Promise = fetchAPI( + configs, + "entries?status=unread" + ).then(response => response.json()) + const starredPromise: Promise = fetchAPI( + configs, + "entries?starred=true" + ).then(response => response.json()) + const [unread, starred] = await Promise.all([unreadPromise, starredPromise]) - // get remote read and star state of articles, for local sync - syncItems: () => async(_, getState) => { - const configs = getState().service as MinifluxConfigs + return [ + new Set(unread.entries.map((entry: Entry) => String(entry.id))), + new Set(starred.entries.map((entry: Entry) => String(entry.id))), + ] + }, - const unread: Entries = await fetchAPI(configs, "entries?status=unread") - .then(response => response.json()); - const starred: Entries = await fetchAPI(configs, "entries?starred=true") - .then(response => response.json()); + markRead: (item: RSSItem) => async (_, getState) => { + if (!item.serviceRef) return - return [new Set(unread.entries.map((entry: Entry) => String(entry.id))), new Set(starred.entries.map((entry: Entry) => String(entry.id)))]; - }, - - markRead: (item: RSSItem) => async(_, getState) => { - if (!item.serviceRef) return; - - const body = `{ + const body = `{ "entry_ids": [${item.serviceRef}], "status": "read" }` - const response = await fetchAPI(getState().service as MinifluxConfigs, "entries", "PUT", body) + const response = await fetchAPI( + getState().service as MinifluxConfigs, + "entries", + "PUT", + body + ) - if (response.status !== 204) throw APIError(); - }, + if (response.status !== 204) throw APIError() + }, markUnread: (item: RSSItem) => async (_, getState) => { - if (!item.serviceRef) return; + if (!item.serviceRef) return - const body = `{ + const body = `{ "entry_ids": [${item.serviceRef}], "status": "unread" }` - await fetchAPI(getState().service as MinifluxConfigs, "entries", "PUT", body) + await fetchAPI( + getState().service as MinifluxConfigs, + "entries", + "PUT", + body + ) }, - // mark entries for source ids as read, relative to date, determined by "before" bool + // mark entries for source ids as read, relative to date, determined by "before" bool - // context menu component: - // item - null, item date, either - // group - group sources, null, true - // nav - null, daysago, true - - // if null, state consulted for context sids - - markAllRead: (sids, date, before) => async(_, getState) => { + // context menu component: + // item - null, item date, either + // group - group sources, null, true + // nav - null, daysago, true - const state = getState() - let items = state.feeds[state.page.feedId].iids - .map(iid => state.items[iid]) - .filter(item => item.serviceRef && !item.hasRead) + // if null, state consulted for context sids - if (date) items = items.filter(i => before ? i.date < date : i.date > date) + markAllRead: (sids, date, before) => async (_, getState) => { + let refs: string[] - const refs = items.map(item => item.serviceRef) + if (date) { + const predicates: lf.Predicate[] = [ + db.items.source.in(sids), + db.items.hasRead.eq(false), + db.items.serviceRef.isNotNull(), + before ? db.items.date.lte(date) : db.items.date.gte(date), + ] + const query = lf.op.and.apply(null, predicates) + const rows = await db.itemsDB + .select(db.items.serviceRef) + .from(db.items) + .where(query) + .exec() + refs = rows.map(row => row["serviceRef"]) + } else { + const state = getState() + const items = state.feeds[state.page.feedId].iids + .map(iid => state.items[iid]) + .filter(item => item.serviceRef && !item.hasRead) + refs = items.map(item => item.serviceRef) + } - const body = `{ + const body = `{ "entry_ids": [${refs}], "status": "read" }` - await fetchAPI(getState().service as MinifluxConfigs, "entries", "PUT", body) - }, + await fetchAPI( + getState().service as MinifluxConfigs, + "entries", + "PUT", + body + ) + }, star: (item: RSSItem) => async (_, getState) => { - if (!item.serviceRef) return; + if (!item.serviceRef) return - await fetchAPI(getState().service as MinifluxConfigs, `entries/${item.serviceRef}/bookmark`, "PUT"); + await fetchAPI( + getState().service as MinifluxConfigs, + `entries/${item.serviceRef}/bookmark`, + "PUT" + ) }, unstar: (item: RSSItem) => async (_, getState) => { - if (!item.serviceRef) return; - - await fetchAPI(getState().service as MinifluxConfigs, `entries/${item.serviceRef}/bookmark`, "PUT"); - } + if (!item.serviceRef) return + await fetchAPI( + getState().service as MinifluxConfigs, + `entries/${item.serviceRef}/bookmark`, + "PUT" + ) + }, } - - - - - - - From c6439c5f6d30aef9d33194daa7f8dd7afd5ff6e8 Mon Sep 17 00:00:00 2001 From: vikdevelop <83600218+vikdevelop@users.noreply.github.com> Date: Sun, 16 Oct 2022 00:21:23 +0200 Subject: [PATCH 7/8] Czech translations (#448) * Add Czech translations * Update _locales.ts * Update README.md * Update app.tsx --- src/components/settings/app.tsx | 1 + src/scripts/i18n/README.md | 1 + src/scripts/i18n/_locales.ts | 2 + src/scripts/i18n/cs.json | 242 ++++++++++++++++++++++++++++++++ 4 files changed, 246 insertions(+) create mode 100644 src/scripts/i18n/cs.json diff --git a/src/components/settings/app.tsx b/src/components/settings/app.tsx index 5afaf81..5a018e3 100644 --- a/src/components/settings/app.tsx +++ b/src/components/settings/app.tsx @@ -131,6 +131,7 @@ class AppTab extends React.Component { { key: "de", text: "Deutsch" }, { key: "en-US", text: "English" }, { key: "es", text: "Español" }, + { key: "cs", text: "Čeština" }, { key: "fr-FR", text: "Français" }, { key: "it", text: "Italiano" }, { key: "nl", text: "Nederlands" }, diff --git a/src/scripts/i18n/README.md b/src/scripts/i18n/README.md index 802dbb3..04a4c32 100644 --- a/src/scripts/i18n/README.md +++ b/src/scripts/i18n/README.md @@ -5,6 +5,7 @@ Currently, Fluent Reader supports the following languages. | Locale | Language | Credit | | --- | --- | --- | | en-US | English | [@yang991178](https://github.com/yang991178) | +| cs | Čeština | [@vikdevelop](https://github.com/vikdevelop) | | es | Español | [@kant](https://github.com/kant) | | fr-FR | Français | [@Toinane](https://github.com/Toinane) | | fi-FI | Suomi | [@SUPERHAMSTERI](https://github.com/SUPERHAMSTERI) | diff --git a/src/scripts/i18n/_locales.ts b/src/scripts/i18n/_locales.ts index e8c64d0..d2774ce 100644 --- a/src/scripts/i18n/_locales.ts +++ b/src/scripts/i18n/_locales.ts @@ -1,4 +1,5 @@ import en_US from "./en-US.json" +import cs from "./cs.json" import zh_CN from "./zh-CN.json" import zh_TW from "./zh-TW.json" import ja from "./ja.json" @@ -18,6 +19,7 @@ import pt_PT from "./pt-PT.json" const locales = { "en-US": en_US, + "cs": cs, "zh-CN": zh_CN, "zh-TW": zh_TW, "ja": ja, diff --git a/src/scripts/i18n/cs.json b/src/scripts/i18n/cs.json new file mode 100644 index 0000000..7794962 --- /dev/null +++ b/src/scripts/i18n/cs.json @@ -0,0 +1,242 @@ +{ + "allArticles": "Všechny články", + "add": "Přidat", + "create": "Vytvořit", + "icon": "Ikona", + "name": "Název", + "openExternal": "Otevřít externě", + "emptyName": "Toto pole nesmí být prázdné.", + "emptyField": "Toto pole nesmí být prázdné.", + "edit": "Upravit", + "delete": "Odstranit", + "followSystem": "Podle systému", + "more": "Více", + "close": "Zavřít", + "search": "Hledat", + "loadMore": "Načíst více", + "dangerButton": "Potvrdit {action}?", + "confirmMarkAll": "Opravdu chcete označit všechny články na této stránce jako přečtené?", + "confirm": "Potvrdit", + "cancel": "Zrušit", + "default": "Výchozí", + "time": { + "now": "nyní", + "m": "m", + "h": "h", + "d": "d", + "minute": "{m, plural, =1 {# minute} other {# minutes}}", + "hour": "{h, plural, =1 {# hour} other {# hours}}", + "day": "{d, plural, =1 {# day} other {# days}}" + }, + "log": { + "empty": "Žádné notifikace", + "fetchFailure": "Nepodařilo se načíst zdroj \"{name}\".", + "fetchSuccess": "Úspěšně načten {count, plural, =1 {# article} other {# articles}}.", + "networkError": "Došlo k chybě sítě.", + "parseError": "Při analýze kanálu XML došlo k chybě.", + "syncFailure": "Došlo k chybě při synchronizaci se službou" + }, + "nav": { + "menu": "Menu", + "refresh": "Načíst znovu", + "markAllRead": "Označit vše jako přečtené", + "notifications": "Notifikace", + "view": "Zobrazit" + "settings": "Nastavení" + "minimize": "Maximalizovat", + "maximize": "Minimalizovat" + }, + "menu": { + "close": "Zavřít menu", + "subscriptions": "Odběry" + }, + "article": { + "error": "Nepodařilo se načíst článek.", + "reload": "Načíst znovu?", + "empty": "Žádné články", + "untitled": "(Bez titulku)", + "hide": "Skrýt článek", + "unhide": "Odkrýt článek", + "markRead": "Označit jako přečtené", + "markUnread": "Označit jako nepřečtené", + "markAbove": "Označte výše uvedené jako přečtené", + "markBelow": "Označte níže uvedené jako přečtené", + "star": "Ohvězdičkovat", + "unstar": "Odstranit hvězdu", + "fontSize": "Velikost písma", + "loadWebpage": "Načíst webovou stránku", + "loadFull": "Načíst všechen obsah", + "notify": "Upozornit, pokud je načteno na pozadí", + "dontNotify": "Neupozorňovat", + "textDir": "Směr textu", + "LTR": "Zleva doprava", + "RTL": "Zprava doleva", + "Vertical": "Vertikálně", + "font": "Písmo" + }, + "context": { + "share": "Sdílet", + "read": "Číst", + "copyTitle": "Kopírovat titulek", + "copyURL": "Kopírovat odkaz", + "copy": "Kopírovat", + "search": "Hledat \"{text}\" on {engine}", + "view": "Zobrazit", + "cardView": "Karty", + "listView": "Seznam", + "magazineView": "Časopis", + "compactView": "Kompaktní", + "filter": "Filtrování", + "unreadOnly": "Jen nepřečtené", + "starredOnly": "Jen ohvězdičkované", + "fullSearch": "Vyhledat v plném textu", + "showHidden": "Zobrazit skryté články", + "manageSources": "Spravovat zdroje", + "saveImageAs": "Uložit obrázek jako …", + "copyImage": "Kopírovat obrázek", + "copyImageURL": "Kopírovat adresu obrázku", + "caseSensitive": "Rozlišovat velká a malá písmena", + "showCover": "Zobrazit kryt", + "showSnippet": "Zobrazit úryvek", + "fadeRead": " Vyblednout čtenné články" + }, + "searchEngine": { + "name": "Vyhledávač", + "google": "Google", + "bing": "Bing", + "baidu": "Baidu", + "duckduckgo": "DuckDuckGo" + }, + "settings": { + "writeError": "Došlo k chybě při zapisování souboru.", + "name": "Nastavení", + "fetching": "Probíhá aktualizace zdrojů, prosím vyčkejte …", + "exit": "Opustit nastavení", + "sources": "Zdroje", + "grouping": "Skupiny", + "rules": "Pravidla", + "service": "Služba", + "app": "Předvolby", + "about": "O aplikaci", + "version": "Verze", + "shortcuts": "Zkratky", + "openSource": "Otevřený zdrojový kód", + "feedback": "Zpětná vazba" + }, + "sources": { + "serviceWarning": "Zde importované nebo přidané zdroje nebudou synchronizovány s vaší službou.", + "serviceManaged": "Tento zdroj spravuje vaše služba.", + "untitled": "Zdroj", + "errorAdd": "Došlo k chybě při přidávání zdroje.", + "errorParse": "Při analýze souboru OPML došlo k chybě.", + "errorParseHint": "Ujistěte se, že soubor není poškozený a je kódován pomocí UTF-8.", + "errorImport": "Objevila se chyba při importování {count, plural, =1 {# source} other {# sources}}.", + "exist": "Tento zdroj již existuje.", + "opmlFile": "Soubor OPML", + "name": "Název zdroje", + "editName": "Upravit název", + "fetchFrequency": "Limit frekvence načítání", + "unlimited": "Neomezené", + "openTarget": "Výchozí otevřený cíl pro články", + "delete": "Odstranit zdroj", + "add": "Přidat zdroj", + "import": "Importovat", + "export": "Exportovat", + "rssText": "Celý text RSS", + "loadWebpage": "Načíst webovou stránku", + "inputUrl": "Zadejte URL adresu", + "badIcon": "Nesprávná ikona", + "badUrl": "Nesprávná URL adresa", + "deleteWarning": "Zdroj a všechny uložené články budou odstraněny.", + "selected": "Vybraný zdroj", + "selectedMulti": "Vybrat více zdrojů", + "hidden": "Ukryto v \"all articles\"" + }, + "groups": { + "exist": "Tato skupina již existuje", + "type": "Typ", + "group": "Skupina", + "source": "Zdroj", + "capacity": "Kapacita", + "exitGroup": "Zpět na skupiny", + "deleteSource": "Odstranit ze skupiny", + "sourceHint": "Přetažením zdrojů změníte jejich pořadí.", + "create": "Vytvořit skupinu", + "selectedGroup": "Vybraná skupina", + "selectedSource": "Vybraný zdroj", + "enterName": "Zadejte název", + "editName": "Editovat název", + "deleteGroup": "Odstranit skupinu", + "chooseGroup": "Vybrat skupinu", + "addToGroup": "Přidat do ...", + "groupHint": "Dvojklikem na skupinu upravíte zdroje. Přetažením změníte pořadí." + }, + "rules": { + "intro": "Automatické označování článků nebo odesílání oznámení pomocí regulárních výrazů.", + "help": "Zjistit více", + "source": "Zdroj", + "selectSource": "Vybrat zdroj", + "new": "Nové pravidlo", + "if": "Pokud", + "then": "Poté", + "title": "Titulek", + "content": "Obsah", + "fullSearch": "Titulek nebo obsah", + "creator": "Autor", + "match": "odpovídá", + "notMatch": "neodpovídá", + "regex": "Pravidelný výraz", + "badRegex": "Nesprávný pravidelný výraz.", + "action": "Akce", + "selectAction": "Vybrat akce", + "hint": "Pravidla se použijí v pořadí. Tažením myši můžete změnit pořadí.", + "test": "Testovací pravidla" + }, + "service": { + "intro": "Synchronizace mezi zařízeními pomocí služeb RSS.", + "select": "Vyberte službu", + "suggest": "Navrhnout novou službu", + "overwriteWarning": "Místní zdroje budou odstraněny, pokud ve službě existují.", + "groupsWarning": "Skupiny nejsou automaticky synchronizovány se službou.", + "rateLimitWarning": "Abyste se vyhnuli omezování rychlosti, musíte si vytvořit vlastní klíč API.", + "removeAd": "Odstranit reklamu", + "endpoint": "Koncový bod", + "username": "Uživatelské jméno", + "password": "Heslo", + "unchanged": "Nezměněno", + "fetchLimit": "Limit synchronizace", + "fetchLimitNum": "{count} nejnovějších článků", + "importGroups": "Importovat skupiny", + "failure": "Nedaří se připojit ke službě", + "failureHint": "Zkontrolujte konfiguraci služby nebo stav sítě.", + "fetchUnlimited": "Neomezený (nedoporučuje se)", + "exportToLite": "Exportovat do Fluent reader Lite" + }, + "app": { + "cleanup": "Vyčistit", + "cache": "Vyčistit mezipaměť", + "cacheSize": "Velikost {size} dat v mezipaměti", + "deleteChoices": "Odstranit články před ... dny", + "confirmDelete": "Odstranit", + "daysAgo": "{days, plural, =1 {# day} other {# days}} ago", + "deleteAll": "Odstranit věechny články", + "calculatingSize": "Probíhá výpočet velikosti...", + "itemSize": "Přibližně {size} místního úložiště zabírají články", + "confirmImport": "Opravdu chcete importovat data ze záložního souboru? Všechna aktuální data budou vymazána.", + "data": "Data aplikace", + "backup": "Záloha", + "restore": "Obnovit", + "frData": "Data aplikace Fluent Reader", + "language": "Zobrazovaný jazyk", + "theme": "Motiv", + "lightTheme": "Světlý motiv", + "darkTheme": "Tmavý motiv", + "enableProxy": "Povolit Proxy", + "badUrl": "Nesprávná URL", + "pac": "PAC Adresa", + "setPac": "Nastavit PAC", + "pacHint": "U proxy serverů Socks se doporučuje, aby PAC vracel \"SOCKS5\" pro DNS na straně proxy serveru. Vypnutí proxy vyžaduje restart.", + "fetchInterval": "Automatický interval načítání", + "never": "Nikdy" + } +} From 9318b1c3cedae4ee8dfad30280a13048883979de Mon Sep 17 00:00:00 2001 From: Bruce Liu Date: Sat, 15 Oct 2022 15:32:07 -0700 Subject: [PATCH 8/8] update services, fix json and ui drag --- dist/styles/global.css | 2 +- src/components/settings/services/miniflux.tsx | 1 - .../settings/services/nextcloud.tsx | 19 ++--- src/scripts/i18n/cs.json | 4 +- src/scripts/models/services/miniflux.ts | 79 +++++++++---------- src/scripts/models/services/nextcloud.ts | 51 ++++++------ 6 files changed, 67 insertions(+), 89 deletions(-) diff --git a/dist/styles/global.css b/dist/styles/global.css index 8b6e63f..89bb2c1 100644 --- a/dist/styles/global.css +++ b/dist/styles/global.css @@ -237,7 +237,7 @@ body.darwin .btn-group .seperator { height: var(--navHeight); line-height: var(--navHeight); } -body.darwin.not-fullscreen #root > nav .btn-group .btn:first-of-type { +body.darwin.not-fullscreen #root > nav .btn-group:first-of-type { margin-left: 72px; } #root > nav .btn-group .btn.system { diff --git a/src/components/settings/services/miniflux.tsx b/src/components/settings/services/miniflux.tsx index 32bdc04..221ab41 100644 --- a/src/components/settings/services/miniflux.tsx +++ b/src/components/settings/services/miniflux.tsx @@ -17,7 +17,6 @@ import { } from "@fluentui/react" import DangerButton from "../../utils/danger-button" import { urlTest } from "../../../scripts/utils" -import LiteExporter from "./lite-exporter" import { MinifluxConfigs } from "../../../scripts/models/services/miniflux" type MinifluxConfigsTabState = { diff --git a/src/components/settings/services/nextcloud.tsx b/src/components/settings/services/nextcloud.tsx index 11d1f26..b8fbe25 100644 --- a/src/components/settings/services/nextcloud.tsx +++ b/src/components/settings/services/nextcloud.tsx @@ -18,7 +18,6 @@ import { } from "@fluentui/react" import DangerButton from "../../utils/danger-button" import { urlTest } from "../../../scripts/utils" -import LiteExporter from "./lite-exporter" type NextcloudConfigsTabState = { existing: boolean @@ -129,17 +128,14 @@ class NextcloudConfigsTab extends React.Component< )} - - - + /> @@ -161,7 +157,7 @@ class NextcloudConfigsTab extends React.Component< - + - {this.state.existing && ( - - )} ) diff --git a/src/scripts/i18n/cs.json b/src/scripts/i18n/cs.json index 7794962..f5c59de 100644 --- a/src/scripts/i18n/cs.json +++ b/src/scripts/i18n/cs.json @@ -41,8 +41,8 @@ "refresh": "Načíst znovu", "markAllRead": "Označit vše jako přečtené", "notifications": "Notifikace", - "view": "Zobrazit" - "settings": "Nastavení" + "view": "Zobrazit", + "settings": "Nastavení", "minimize": "Maximalizovat", "maximize": "Minimalizovat" }, diff --git a/src/scripts/models/services/miniflux.ts b/src/scripts/models/services/miniflux.ts index b4d2955..f949507 100644 --- a/src/scripts/models/services/miniflux.ts +++ b/src/scripts/models/services/miniflux.ts @@ -128,18 +128,18 @@ export const minifluxServiceHooks: ServiceHooks = { // fetch entries from after the last fetched id (if exists) // limit by quantity and maximum safe integer (id) // NOTE: miniflux endpoint /entries default order with "published at", and does not offer "created_at" - // but does offer id sort, directly correlated with "created". some feeds give strange published_at. + // but does offer id sort, directly correlated with "created". some feeds give strange published_at. fetchItems: () => async (_, getState) => { const state = getState() const configs = state.service as MinifluxConfigs - let items: Entry[] = new Array() + const items: Entry[] = new Array() let entriesResponse: Entries // parameters configs.lastId = configs.lastId ?? 0 // intermediate - const quantity = 100 + const quantity = 125 let continueId: number do { @@ -147,37 +147,28 @@ export const minifluxServiceHooks: ServiceHooks = { if (continueId) { entriesResponse = await fetchAPI( configs, - `entries? - order=id - &direction=desc - &after_entry_id=${configs.lastId} - &before_entry_id=${continueId} - &limit=${quantity}` + `entries?order=id&direction=desc&after_entry_id=${configs.lastId}&before_entry_id=${continueId}&limit=${quantity}` ).then(response => response.json()) } else { entriesResponse = await fetchAPI( configs, - `entries? - order=id - &direction=desc - &after_entry_id=${configs.lastId} - &limit=${quantity}` + `entries?order=id&direction=desc&after_entry_id=${configs.lastId}&limit=${quantity}` ).then(response => response.json()) } - items = entriesResponse.entries.concat(items) + items.push(...entriesResponse.entries) continueId = items[items.length - 1].id } catch { break } } while ( entriesResponse.entries && - entriesResponse.total === 100 && + entriesResponse.total >= quantity && items.length < configs.fetchLimit ) // break/return nothing if no new items acquired - if (items.length == 0) return [[], configs] + if (items.length === 0) return [[], configs] configs.lastId = items[0].id // get sources that possess ref/id given by service, associate new items @@ -245,7 +236,10 @@ export const minifluxServiceHooks: ServiceHooks = { configs, "entries?starred=true" ).then(response => response.json()) - const [unread, starred] = await Promise.all([unreadPromise, starredPromise]) + const [unread, starred] = await Promise.all([ + unreadPromise, + starredPromise, + ]) return [ new Set(unread.entries.map((entry: Entry) => String(entry.id))), @@ -257,9 +251,9 @@ export const minifluxServiceHooks: ServiceHooks = { if (!item.serviceRef) return const body = `{ - "entry_ids": [${item.serviceRef}], - "status": "read" - }` + "entry_ids": [${item.serviceRef}], + "status": "read" + }` const response = await fetchAPI( getState().service as MinifluxConfigs, @@ -275,9 +269,9 @@ export const minifluxServiceHooks: ServiceHooks = { if (!item.serviceRef) return const body = `{ - "entry_ids": [${item.serviceRef}], - "status": "unread" - }` + "entry_ids": [${item.serviceRef}], + "status": "unread" + }` await fetchAPI( getState().service as MinifluxConfigs, "entries", @@ -296,7 +290,8 @@ export const minifluxServiceHooks: ServiceHooks = { // if null, state consulted for context sids markAllRead: (sids, date, before) => async (_, getState) => { - let refs: string[] + const state = getState() + const configs = state.service as MinifluxConfigs if (date) { const predicates: lf.Predicate[] = [ @@ -311,26 +306,24 @@ export const minifluxServiceHooks: ServiceHooks = { .from(db.items) .where(query) .exec() - refs = rows.map(row => row["serviceRef"]) + const refs = rows.map(row => row["serviceRef"]) + const body = `{ + "entry_ids": [${refs}], + "status": "read" + }` + await fetchAPI(configs, "entries", "PUT", body) } else { - const state = getState() - const items = state.feeds[state.page.feedId].iids - .map(iid => state.items[iid]) - .filter(item => item.serviceRef && !item.hasRead) - refs = items.map(item => item.serviceRef) + const sources = state.sources + await Promise.all( + sids.map(sid => + fetchAPI( + configs, + `feeds/${sources[sid]?.serviceRef}/mark-all-as-read`, + "PUT" + ) + ) + ) } - - const body = `{ - "entry_ids": [${refs}], - "status": "read" - }` - - await fetchAPI( - getState().service as MinifluxConfigs, - "entries", - "PUT", - body - ) }, star: (item: RSSItem) => async (_, getState) => { diff --git a/src/scripts/models/services/nextcloud.ts b/src/scripts/models/services/nextcloud.ts index 86ff545..cd56bd1 100644 --- a/src/scripts/models/services/nextcloud.ts +++ b/src/scripts/models/services/nextcloud.ts @@ -98,7 +98,10 @@ export const nextcloudServiceHooks: ServiceHooks = { source.iconurl = s.faviconLink source.serviceRef = String(s.id) if (s.folderId && groupsByTagId.has(String(s.folderId))) { - groupsMap.set(String(s.id), groupsByTagId.get(String(s.folderId))) + groupsMap.set( + String(s.id), + groupsByTagId.get(String(s.folderId)) + ) } return source }) @@ -107,7 +110,7 @@ export const nextcloudServiceHooks: ServiceHooks = { syncItems: () => async (_, getState) => { const configs = getState().service as NextcloudConfigs - const [unreadResponse, starredResponse]= await Promise.all([ + const [unreadResponse, starredResponse] = await Promise.all([ fetchAPI(configs, "/items?getRead=false&type=3&batchSize=-1"), fetchAPI(configs, "/items?getRead=true&type=2&batchSize=-1"), ]) @@ -133,19 +136,14 @@ export const nextcloudServiceHooks: ServiceHooks = { //first sync let min = Number.MAX_SAFE_INTEGER do { - try { - const response = await fetchAPI( - configs, - "/items?getRead=true&type=3&batchSize=125&offset=" + min - ) - if (response.status !== 200) throw APIError() - lastFetched = await response.json() - items = [ ...items, ...lastFetched.items] - min = lastFetched.items.reduce((m, n) => Math.min(m, n.id), min) - } catch (error) { - console.log(error) - break - } + const response = await fetchAPI( + configs, + "/items?getRead=true&type=3&batchSize=125&offset=" + min + ) + if (response.status !== 200) throw APIError() + lastFetched = await response.json() + items = [...items, ...lastFetched.items] + min = lastFetched.items.reduce((m, n) => Math.min(m, n.id), min) } while ( lastFetched.items && lastFetched.items.length >= 125 && @@ -155,18 +153,14 @@ export const nextcloudServiceHooks: ServiceHooks = { //incremental sync const response = await fetchAPI( configs, - "/items/updated?lastModified="+configs.lastModified+"&type=3" + "/items/updated?lastModified=" + + configs.lastModified + + "&type=3" ) if (response.status !== 200) throw APIError() lastFetched = (await response.json()).items - items.push( - ...lastFetched.filter( - i => i.id > configs.lastId - ) - ) - + items.push(...lastFetched.filter(i => i.id > configs.lastId)) } - const previousLastModified = configs.lastModified configs.lastModified = items.reduce( (m, n) => Math.max(m, n.lastModified), configs.lastModified @@ -175,7 +169,6 @@ export const nextcloudServiceHooks: ServiceHooks = { (m, n) => Math.max(m, n.id), configs.lastId ) - console.log("last modified from "+ previousLastModified + " to " + configs.lastModified) configs.lastModified++ //+1 to avoid fetching articles with same lastModified next time if (items.length > 0) { const fidMap = new Map() @@ -184,7 +177,7 @@ export const nextcloudServiceHooks: ServiceHooks = { fidMap.set(source.serviceRef, source) } } - + const parsedItems = new Array() items.forEach(i => { if (i.body === null || i.url === null) return @@ -196,8 +189,8 @@ export const nextcloudServiceHooks: ServiceHooks = { source: source.sid, title: i.title, link: i.url, - date: new Date(i.pubDate*1000), - fetchedDate: new Date(i.pubDate*1000), + date: new Date(i.pubDate * 1000), + fetchedDate: new Date(), content: i.body, snippet: dom.documentElement.textContent.trim(), creator: i.author, @@ -207,7 +200,7 @@ export const nextcloudServiceHooks: ServiceHooks = { notify: false, serviceRef: String(i.id), } as RSSItem - if (i.enclosureLink ) { + if (i.enclosureLink) { item.thumb = i.enclosureLink } else { let baseEl = dom.createElement("base") @@ -235,7 +228,7 @@ export const nextcloudServiceHooks: ServiceHooks = { "POST", [i.id] ) - + parsedItems.push(item) }) return [parsedItems, configs]