From b277000c2af28a20b7183a65d4eb0e898819a070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sat, 17 Jun 2023 02:45:31 +0100 Subject: [PATCH 01/11] feat: kwm v2 key import ui --- src/components/ImportSecretModal.tsx | 46 +++++++++ src/features/settings/Settings.tsx | 2 + src/features/settings/keyFormats.ts | 67 +++++++++++++ .../settings/panels/KWMv2/KWMv2EKeyItem.tsx | 76 +++++++++++++++ .../settings/panels/PanelKWMv2Key.tsx | 94 +++++++++++++++++++ .../settings/panels/PanelQMCv2Key.tsx | 90 ++++++++++++++++-- .../QMCv2/{KeyInput.tsx => QMCv2EKeyItem.tsx} | 6 +- src/features/settings/settingsSelector.ts | 2 + src/features/settings/settingsSlice.ts | 89 ++++++++++++++---- src/util/DatabaseKeyExtractor.ts | 6 +- src/util/MMKVParser.ts | 4 + src/util/__tests__/splitN.ts.test.ts | 10 ++ src/util/splitN.ts | 20 ++++ 13 files changed, 480 insertions(+), 32 deletions(-) create mode 100644 src/components/ImportSecretModal.tsx create mode 100644 src/features/settings/keyFormats.ts create mode 100644 src/features/settings/panels/KWMv2/KWMv2EKeyItem.tsx create mode 100644 src/features/settings/panels/PanelKWMv2Key.tsx rename src/features/settings/panels/QMCv2/{KeyInput.tsx => QMCv2EKeyItem.tsx} (86%) create mode 100644 src/util/__tests__/splitN.ts.test.ts create mode 100644 src/util/splitN.ts diff --git a/src/components/ImportSecretModal.tsx b/src/components/ImportSecretModal.tsx new file mode 100644 index 0000000..2a83999 --- /dev/null +++ b/src/components/ImportSecretModal.tsx @@ -0,0 +1,46 @@ +import { + Center, + Flex, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalHeader, + ModalOverlay, + Tabs, + Text, +} from '@chakra-ui/react'; + +import { FileInput } from '~/components/FileInput'; + +export interface ImportSecretModalProps { + clientName?: React.ReactNode; + children: React.ReactNode; + show: boolean; + onClose: () => void; + onImport: (file: File) => void; +} + +export function ImportSecretModal({ clientName, children, show, onClose, onImport }: ImportSecretModalProps) { + const handleFileReceived = (files: File[]) => onImport(files[0]); + + return ( + + + + 导入密钥数据库 + + +
+ 拖放或点我选择含有密钥的数据库文件 +
+ + 选择你的{clientName && <>「{clientName}」}客户端平台以查看对应说明: + + {children} + +
+
+
+ ); +} diff --git a/src/features/settings/Settings.tsx b/src/features/settings/Settings.tsx index 3d93f7b..a59155b 100644 --- a/src/features/settings/Settings.tsx +++ b/src/features/settings/Settings.tsx @@ -26,9 +26,11 @@ import { useState } from 'react'; import { MdExpandMore, MdMenu, MdOutlineSettingsBackupRestore } from 'react-icons/md'; import { useAppDispatch } from '~/hooks'; import { commitStagingChange, discardStagingChanges } from './settingsSlice'; +import { PanelKWMv2Key } from './panels/PanelKWMv2Key'; const TABS: { name: string; Tab: () => JSX.Element }[] = [ { name: 'QMCv2 密钥', Tab: PanelQMCv2Key }, + { name: 'KWMv2 密钥', Tab: PanelKWMv2Key }, { name: '其它/待定', Tab: () => 这里空空如也~, diff --git a/src/features/settings/keyFormats.ts b/src/features/settings/keyFormats.ts new file mode 100644 index 0000000..65ce879 --- /dev/null +++ b/src/features/settings/keyFormats.ts @@ -0,0 +1,67 @@ +import { nanoid } from 'nanoid'; +import { objectify } from 'radash'; + +export function productionKeyToStaging>( + src: P, + make: (k: keyof P, v: P[keyof P]) => null | S +): S[] { + const result: S[] = []; + for (const [key, value] of Object.entries(src)) { + const item = make(key, value as P[keyof P]); + if (item) { + result.push(item); + } + } + return result; +} +export function stagingKeyToProduction(src: S[], toKey: (s: S) => keyof P, toValue: (s: S) => P[keyof P]): P { + return objectify(src, toKey, toValue) as P; +} + +// QMCv2 (QQ) +export interface StagingQMCv2Key { + id: string; + name: string; + ekey: string; +} + +export type ProductionQMCv2Keys = Record; + +export const qmc2StagingToProductionKey = (key: StagingQMCv2Key) => key.name.normalize(); +export const qmc2StagingToProductionValue = (key: StagingQMCv2Key) => key.ekey.trim(); +export const qmc2ProductionToStaging = ( + key: keyof ProductionQMCv2Keys, + value: ProductionQMCv2Keys[keyof ProductionQMCv2Keys] +): StagingQMCv2Key => { + return { + id: nanoid(), + name: key.normalize(), + ekey: value.trim(), + }; +}; + +// KWMv2 (KuWo) + +export interface StagingKWMv2Key { + id: string; + rid: string; + quality: string; + ekey: string; +} + +export type ProductionKWMv2Keys = Record; + +export const kwm2StagingToProductionKey = (key: StagingKWMv2Key) => `${key.rid}-${key.quality}`; +export const kwm2StagingToProductionValue = (key: StagingKWMv2Key) => key.ekey; +export const kwm2ProductionToStaging = ( + key: keyof ProductionKWMv2Keys, + value: ProductionKWMv2Keys[keyof ProductionKWMv2Keys] +): null | StagingKWMv2Key => { + if (typeof value !== 'string') return null; + + const m = key.match(/^(\d+)-(\w+)$/); + if (!m) return null; + + const [_, rid, quality] = m; + return { id: nanoid(), rid, quality, ekey: value }; +}; diff --git a/src/features/settings/panels/KWMv2/KWMv2EKeyItem.tsx b/src/features/settings/panels/KWMv2/KWMv2EKeyItem.tsx new file mode 100644 index 0000000..35244b4 --- /dev/null +++ b/src/features/settings/panels/KWMv2/KWMv2EKeyItem.tsx @@ -0,0 +1,76 @@ +import { + HStack, + Icon, + IconButton, + Input, + InputGroup, + InputLeftElement, + InputRightElement, + ListItem, + Text, + VStack, +} from '@chakra-ui/react'; +import { MdDelete, MdVpnKey } from 'react-icons/md'; +import { kwm2DeleteKey, kwm2UpdateKey } from '../../settingsSlice'; +import { useAppDispatch } from '~/hooks'; +import { memo } from 'react'; +import { StagingKWMv2Key } from '../../keyFormats'; + +export const KWMv2EKeyItem = memo(({ id, ekey, quality, rid, i }: StagingKWMv2Key & { i: number }) => { + const dispatch = useAppDispatch(); + + const updateKey = (prop: keyof StagingKWMv2Key, e: React.ChangeEvent) => + dispatch(kwm2UpdateKey({ id, field: prop, value: e.target.value })); + const deleteKey = () => dispatch(kwm2DeleteKey({ id })); + + return ( + + + + {i + 1} + + + + + updateKey('rid', e)} + type="number" + maxW="8em" + /> + updateKey('quality', e)} + flex={1} + /> + + + + + + + updateKey('ekey', e)} /> + + + {ekey.length || '?'} + + + + + + } + variant="ghost" + colorScheme="red" + type="button" + onClick={deleteKey} + /> + + + ); +}); diff --git a/src/features/settings/panels/PanelKWMv2Key.tsx b/src/features/settings/panels/PanelKWMv2Key.tsx new file mode 100644 index 0000000..80a0cb5 --- /dev/null +++ b/src/features/settings/panels/PanelKWMv2Key.tsx @@ -0,0 +1,94 @@ +import { + Box, + Button, + ButtonGroup, + Code, + Flex, + HStack, + Heading, + Icon, + IconButton, + List, + Menu, + MenuButton, + MenuDivider, + MenuItem, + MenuList, + Text, + useToast, +} from '@chakra-ui/react'; +import { useDispatch, useSelector } from 'react-redux'; +import { kwm2AddKey, kwm2ClearKeys } from '../settingsSlice'; +import { selectStagingKWMv2Keys } from '../settingsSelector'; +import { useState } from 'react'; +import { MdAdd, MdDeleteForever, MdExpandMore, MdFileUpload } from 'react-icons/md'; +import { KWMv2EKeyItem } from './KWMv2/KWMv2EKeyItem'; +import { ImportSecretModal } from '~/components/ImportSecretModal'; + +export function PanelKWMv2Key() { + const toast = useToast(); + const dispatch = useDispatch(); + const kwm2Keys = useSelector(selectStagingKWMv2Keys); + const [showImportModal, setShowImportModal] = useState(false); + + const addKey = () => dispatch(kwm2AddKey()); + const clearAll = () => dispatch(kwm2ClearKeys()); + const handleSecretImport = () => { + toast({ + title: '尚未实现', + isClosable: true, + status: 'error', + }); + }; + + return ( + + + 酷我解密密钥(KwmV2) + + + + 酷我安卓版本的「臻品音质」已经换用 V2 版,后缀名为 mflac 或沿用旧的 kwm。{''} + 该格式需要提取密钥后才能正常解密。 + + + + + + + }> + + setShowImportModal(true)} icon={}> + 从文件导入密钥 + + + }> + 清空密钥 + + + + + + + + + {kwm2Keys.map(({ id, ekey, quality, rid }, i) => ( + + ))} + + {kwm2Keys.length === 0 && 还没有添加密钥。} + + + setShowImportModal(false)} + onImport={handleSecretImport} + > + 尚未实现 + + + ); +} diff --git a/src/features/settings/panels/PanelQMCv2Key.tsx b/src/features/settings/panels/PanelQMCv2Key.tsx index 52856f2..e18709d 100644 --- a/src/features/settings/panels/PanelQMCv2Key.tsx +++ b/src/features/settings/panels/PanelQMCv2Key.tsx @@ -14,19 +14,33 @@ import { MenuDivider, MenuItem, MenuList, + Tab, + TabList, + TabPanel, + TabPanels, Text, Tooltip, + useToast, } from '@chakra-ui/react'; import { useDispatch, useSelector } from 'react-redux'; -import { qmc2AddKey, qmc2AllowFuzzyNameSearch, qmc2ClearKeys } from '../settingsSlice'; +import { qmc2AddKey, qmc2AllowFuzzyNameSearch, qmc2ClearKeys, qmc2ImportKeys } from '../settingsSlice'; import { selectStagingQMCv2Settings } from '../settingsSelector'; import React, { useState } from 'react'; import { MdAdd, MdDeleteForever, MdExpandMore, MdFileUpload } from 'react-icons/md'; -import { ImportFileModal } from './QMCv2/ImportFileModal'; -import { KeyInput } from './QMCv2/KeyInput'; +import { QMCv2EKeyItem } from './QMCv2/QMCv2EKeyItem'; import { InfoOutlineIcon } from '@chakra-ui/icons'; +import { ImportSecretModal } from '~/components/ImportSecretModal'; +import { StagingQMCv2Key } from '../keyFormats'; +import { DatabaseKeyExtractor } from '~/util/DatabaseKeyExtractor'; +import { MMKVParser } from '~/util/MMKVParser'; +import { getFileName } from '~/util/pathHelper'; +import { InstructionsAndroid } from './QMCv2/InstructionsAndroid'; +import { InstructionsIOS } from './QMCv2/InstructionsIOS'; +import { InstructionsMac } from './QMCv2/InstructionsMac'; +import { InstructionsPC } from './QMCv2/InstructionsPC'; export function PanelQMCv2Key() { + const toast = useToast(); const dispatch = useDispatch(); const { keys: qmc2Keys, allowFuzzyNameSearch } = useSelector(selectStagingQMCv2Settings); const [showImportModal, setShowImportModal] = useState(false); @@ -38,6 +52,44 @@ export function PanelQMCv2Key() { dispatch(qmc2AllowFuzzyNameSearch({ enable: e.target.checked })); }; + const handleSecretImport = async (file: File) => { + try { + const fileBuffer = await file.arrayBuffer(); + + let qmc2Keys: null | Omit[] = null; + + if (/[_.]db$/i.test(file.name)) { + const extractor = await DatabaseKeyExtractor.getInstance(); + qmc2Keys = extractor.extractQmAndroidDbKeys(fileBuffer); + if (!qmc2Keys) { + alert(`不是支持的 SQLite 数据库文件。\n表名:${qmc2Keys}`); + return; + } + } else if (/MMKVStreamEncryptId|filenameEkeyMap/i.test(file.name)) { + const fileBuffer = await file.arrayBuffer(); + const map = MMKVParser.toStringMap(new DataView(fileBuffer)); + qmc2Keys = Array.from(map.entries(), ([name, ekey]) => ({ name: getFileName(name), ekey })); + } + + if (qmc2Keys) { + dispatch(qmc2ImportKeys(qmc2Keys)); + setShowImportModal(false); + toast({ + title: `导入成功 (${qmc2Keys.length})`, + description: '记得保存更改来应用。', + isClosable: true, + duration: 5000, + status: 'success', + }); + } else { + alert(`不支持的文件:${file.name}`); + } + } catch (e) { + console.error('error during import: ', e); + alert(`导入数据库时发生错误:${e}`); + } + }; + return ( @@ -99,14 +151,40 @@ export function PanelQMCv2Key() { - {qmc2Keys.map(({ id, key, name }, i) => ( - + {qmc2Keys.map(({ id, ekey, name }, i) => ( + ))} {qmc2Keys.length === 0 && 还没有添加密钥。} - setShowImportModal(false)} /> + setShowImportModal(false)} + onImport={handleSecretImport} + > + + 安卓 + iOS + Mac + Windows + + + + + + + + + + + + + + + + ); } diff --git a/src/features/settings/panels/QMCv2/KeyInput.tsx b/src/features/settings/panels/QMCv2/QMCv2EKeyItem.tsx similarity index 86% rename from src/features/settings/panels/QMCv2/KeyInput.tsx rename to src/features/settings/panels/QMCv2/QMCv2EKeyItem.tsx index 77d193e..bf133d0 100644 --- a/src/features/settings/panels/QMCv2/KeyInput.tsx +++ b/src/features/settings/panels/QMCv2/QMCv2EKeyItem.tsx @@ -15,10 +15,10 @@ import { qmc2DeleteKey, qmc2UpdateKey } from '../../settingsSlice'; import { useAppDispatch } from '~/hooks'; import { memo } from 'react'; -export const KeyInput = memo(({ id, name, ekey, i }: { id: string; name: string; ekey: string; i: number }) => { +export const QMCv2EKeyItem = memo(({ id, name, ekey, i }: { id: string; name: string; ekey: string; i: number }) => { const dispatch = useAppDispatch(); - const updateKey = (prop: 'name' | 'key', e: React.ChangeEvent) => + const updateKey = (prop: 'name' | 'ekey', e: React.ChangeEvent) => dispatch(qmc2UpdateKey({ id, field: prop, value: e.target.value })); const deleteKey = () => dispatch(qmc2DeleteKey({ id })); @@ -36,7 +36,7 @@ export const KeyInput = memo(({ id, name, ekey, i }: { id: string; name: string; - updateKey('key', e)} /> + updateKey('ekey', e)} /> {ekey.length || '?'} diff --git a/src/features/settings/settingsSelector.ts b/src/features/settings/settingsSelector.ts index f53f796..3798f41 100644 --- a/src/features/settings/settingsSelector.ts +++ b/src/features/settings/settingsSelector.ts @@ -6,6 +6,8 @@ import { hasOwn } from '~/util/objects'; export const selectStagingQMCv2Settings = (state: RootState) => state.settings.staging.qmc2; export const selectFinalQMCv2Settings = (state: RootState) => state.settings.production.qmc2; +export const selectStagingKWMv2Keys = (state: RootState) => state.settings.staging.kwm2.keys; + export const selectDecryptOptionByFile = (state: RootState, name: string): DecryptCommandOptions => { const normalizedName = name.normalize(); diff --git a/src/features/settings/settingsSlice.ts b/src/features/settings/settingsSlice.ts index dacd10b..e5722e2 100644 --- a/src/features/settings/settingsSlice.ts +++ b/src/features/settings/settingsSlice.ts @@ -1,20 +1,39 @@ import { createSlice } from '@reduxjs/toolkit'; import type { PayloadAction } from '@reduxjs/toolkit'; import { nanoid } from 'nanoid'; -import { objectify } from 'radash'; +import { + ProductionKWMv2Keys, + ProductionQMCv2Keys, + StagingKWMv2Key, + StagingQMCv2Key, + kwm2ProductionToStaging, + kwm2StagingToProductionKey, + kwm2StagingToProductionValue, + productionKeyToStaging, + qmc2ProductionToStaging, + qmc2StagingToProductionKey, + qmc2StagingToProductionValue, + stagingKeyToProduction, +} from './keyFormats'; export interface StagingSettings { qmc2: { - keys: { id: string; name: string; key: string }[]; + keys: StagingQMCv2Key[]; allowFuzzyNameSearch: boolean; }; + kwm2: { + keys: StagingKWMv2Key[]; + }; } export interface ProductionSettings { qmc2: { - keys: Record; // { [fileName]: ekey } + keys: ProductionQMCv2Keys; // { [fileName]: ekey } allowFuzzyNameSearch: boolean; }; + kwm2: { + keys: ProductionKWMv2Keys; // { [`${rid}-${quality}`]: ekey } + }; } export interface SettingsState { @@ -23,35 +42,33 @@ export interface SettingsState { } const initialState: SettingsState = { staging: { - qmc2: { - allowFuzzyNameSearch: false, - keys: [], - }, + qmc2: { allowFuzzyNameSearch: false, keys: [] }, + kwm2: { keys: [] }, }, production: { - qmc2: { - allowFuzzyNameSearch: false, - keys: {}, - }, + qmc2: { allowFuzzyNameSearch: false, keys: {} }, + kwm2: { keys: {} }, }, }; const stagingToProduction = (staging: StagingSettings): ProductionSettings => ({ qmc2: { - keys: objectify( - staging.qmc2.keys, - (item) => item.name.normalize(), - (item) => item.key.trim() - ), + keys: stagingKeyToProduction(staging.qmc2.keys, qmc2StagingToProductionKey, qmc2StagingToProductionValue), allowFuzzyNameSearch: staging.qmc2.allowFuzzyNameSearch, }, + kwm2: { + keys: stagingKeyToProduction(staging.kwm2.keys, kwm2StagingToProductionKey, kwm2StagingToProductionValue), + }, }); const productionToStaging = (production: ProductionSettings): StagingSettings => ({ qmc2: { - keys: Object.entries(production.qmc2.keys).map(([name, key]) => ({ id: nanoid(), name, key })), + keys: productionKeyToStaging(production.qmc2.keys, qmc2ProductionToStaging), allowFuzzyNameSearch: production.qmc2.allowFuzzyNameSearch, }, + kwm2: { + keys: productionKeyToStaging(production.kwm2.keys, kwm2ProductionToStaging), + }, }); export const settingsSlice = createSlice({ @@ -64,10 +81,11 @@ export const settingsSlice = createSlice({ staging: productionToStaging(payload), }; }, + // qmc2AddKey(state) { - state.staging.qmc2.keys.push({ id: nanoid(), name: '', key: '' }); + state.staging.qmc2.keys.push({ id: nanoid(), name: '', ekey: '' }); }, - qmc2ImportKeys(state, { payload }: PayloadAction<{ name: string; key: string }[]>) { + qmc2ImportKeys(state, { payload }: PayloadAction[]>) { const newItems = payload.map((item) => ({ id: nanoid(), ...item })); state.staging.qmc2.keys.push(...newItems); }, @@ -77,7 +95,7 @@ export const settingsSlice = createSlice({ }, qmc2UpdateKey( state, - { payload: { id, field, value } }: PayloadAction<{ id: string; field: 'name' | 'key'; value: string }> + { payload: { id, field, value } }: PayloadAction<{ id: string; field: keyof StagingQMCv2Key; value: string }> ) { const keyItem = state.staging.qmc2.keys.find((item) => item.id === id); if (keyItem) { @@ -90,6 +108,31 @@ export const settingsSlice = createSlice({ qmc2AllowFuzzyNameSearch(state, { payload: { enable } }: PayloadAction<{ enable: boolean }>) { state.staging.qmc2.allowFuzzyNameSearch = enable; }, + // TODO: reuse the logic somehow? + kwm2AddKey(state) { + state.staging.kwm2.keys.push({ id: nanoid(), ekey: '', quality: '', rid: '' }); + }, + kwm2ImportKeys(state, { payload }: PayloadAction[]>) { + const newItems = payload.map((item) => ({ id: nanoid(), ...item })); + state.staging.kwm2.keys.push(...newItems); + }, + kwm2DeleteKey(state, { payload: { id } }: PayloadAction<{ id: string }>) { + const kwm2 = state.staging.kwm2; + kwm2.keys = kwm2.keys.filter((item) => item.id !== id); + }, + kwm2UpdateKey( + state, + { payload: { id, field, value } }: PayloadAction<{ id: string; field: keyof StagingKWMv2Key; value: string }> + ) { + const keyItem = state.staging.kwm2.keys.find((item) => item.id === id); + if (keyItem) { + keyItem[field] = value; + } + }, + kwm2ClearKeys(state) { + state.staging.kwm2.keys = []; + }, + // discardStagingChanges: (state) => { state.staging = productionToStaging(state.production); }, @@ -118,6 +161,12 @@ export const { qmc2ImportKeys, qmc2AllowFuzzyNameSearch, + kwm2AddKey, + kwm2UpdateKey, + kwm2DeleteKey, + kwm2ClearKeys, + kwm2ImportKeys, + commitStagingChange, discardStagingChanges, } = settingsSlice.actions; diff --git a/src/util/DatabaseKeyExtractor.ts b/src/util/DatabaseKeyExtractor.ts index 7df071f..5158820 100644 --- a/src/util/DatabaseKeyExtractor.ts +++ b/src/util/DatabaseKeyExtractor.ts @@ -3,7 +3,7 @@ import { SQLDatabase, SQLStatic, loadSQL } from './sqlite'; export interface QMAndroidKeyEntry { name: string; - key: string; + ekey: string; } export class DatabaseKeyExtractor { @@ -33,10 +33,10 @@ export class DatabaseKeyExtractor { } const keys = db.exec('select file_path, ekey from `audio_file_ekey_table`')[0].values; - return keys.map(([path, key]) => ({ + return keys.map(([path, ekey]) => ({ // strip dir name name: getFileName(String(path)), - key: String(key), + ekey: String(ekey), })); } finally { db?.close(); diff --git a/src/util/MMKVParser.ts b/src/util/MMKVParser.ts index 6a8425d..530f237 100644 --- a/src/util/MMKVParser.ts +++ b/src/util/MMKVParser.ts @@ -95,4 +95,8 @@ export class MMKVParser { } return result; } + + public static parseKuwoEKey(_view: DataView): unknown[] { + return []; + } } diff --git a/src/util/__tests__/splitN.ts.test.ts b/src/util/__tests__/splitN.ts.test.ts new file mode 100644 index 0000000..448322b --- /dev/null +++ b/src/util/__tests__/splitN.ts.test.ts @@ -0,0 +1,10 @@ +import { splitN } from '../splitN'; + +test('some test cases', () => { + expect(splitN('1,2,3', ',', 2)).toEqual(['1', '2,3']); + expect(splitN('1,2,3', ',', 3)).toEqual(['1', '2', '3']); + expect(splitN('1,2,3', ',', 4)).toEqual(['1', '2', '3']); + + expect(splitN('1,2,3', '.', 3)).toEqual(['1,2,3']); + expect(splitN('1,2,3', '?', 0)).toEqual(['1,2,3']); +}); diff --git a/src/util/splitN.ts b/src/util/splitN.ts new file mode 100644 index 0000000..0b3d402 --- /dev/null +++ b/src/util/splitN.ts @@ -0,0 +1,20 @@ +export function splitN(str: string, sep: string, maxN: number) { + if (maxN <= 1) { + return [str]; + } + + const chunks: string[] = []; + const lenSep = sep.length; + let searchIdx = 0; + for (; maxN > 1; maxN--) { + const nextIdx = str.indexOf(sep, searchIdx); + if (nextIdx === -1) { + break; + } + chunks.push(str.slice(searchIdx, nextIdx)); + searchIdx = nextIdx + lenSep; + } + + chunks.push(str.slice(searchIdx)); + return chunks; +} From a13034cf353e47ce1f436872d2f7526462bf25ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sat, 17 Jun 2023 02:49:49 +0100 Subject: [PATCH 02/11] ci: reduce ram usage when building --- .drone.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.drone.yml b/.drone.yml index 027ff27..3335819 100644 --- a/.drone.yml +++ b/.drone.yml @@ -15,6 +15,8 @@ steps: environment: # 让 npm 使用淘宝源 npm_config_registry: https://registry.npmmirror.com + # 限制内存使用 + NODE_OPTIONS: --max-old-space-size=512 - name: publish image: node:18.16.0-bullseye From 6a338f9aace47e7ed2d3a2daa860855299afcae7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sat, 17 Jun 2023 02:50:04 +0100 Subject: [PATCH 03/11] build: remove migrated component --- .../settings/panels/QMCv2/ImportFileModal.tsx | 122 ------------------ 1 file changed, 122 deletions(-) delete mode 100644 src/features/settings/panels/QMCv2/ImportFileModal.tsx diff --git a/src/features/settings/panels/QMCv2/ImportFileModal.tsx b/src/features/settings/panels/QMCv2/ImportFileModal.tsx deleted file mode 100644 index 0f9a84a..0000000 --- a/src/features/settings/panels/QMCv2/ImportFileModal.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import { - Center, - Flex, - Modal, - ModalBody, - ModalCloseButton, - ModalContent, - ModalHeader, - ModalOverlay, - Tab, - TabList, - TabPanel, - TabPanels, - Tabs, - Text, - useToast, -} from '@chakra-ui/react'; - -import { FileInput } from '~/components/FileInput'; -import { qmc2ImportKeys } from '../../settingsSlice'; -import { useAppDispatch } from '~/hooks'; -import { DatabaseKeyExtractor } from '~/util/DatabaseKeyExtractor'; - -import { InstructionsAndroid } from './InstructionsAndroid'; -import { MMKVParser } from '~/util/MMKVParser'; -import { getFileName } from '~/util/pathHelper'; -import { InstructionsMac } from './InstructionsMac'; -import { InstructionsIOS } from './InstructionsIOS'; -import { InstructionsPC } from './InstructionsPC'; - -export interface ImportFileModalProps { - show: boolean; - onClose: () => void; -} - -interface KeyEntry { - name: string; - key: string; -} - -export function ImportFileModal({ onClose, show }: ImportFileModalProps) { - const dispatch = useAppDispatch(); - const toast = useToast(); - const handleFileReceived = async (files: File[]) => { - try { - const file = files[0]; - const fileBuffer = await file.arrayBuffer(); - - let qmc2Keys: null | KeyEntry[] = null; - - if (/[_.]db$/i.test(file.name)) { - const extractor = await DatabaseKeyExtractor.getInstance(); - qmc2Keys = extractor.extractQmAndroidDbKeys(fileBuffer); - if (!qmc2Keys) { - alert(`不是支持的 SQLite 数据库文件。\n表名:${qmc2Keys}`); - return; - } - } else if (/MMKVStreamEncryptId|filenameEkeyMap/i.test(file.name)) { - const fileBuffer = await file.arrayBuffer(); - const map = MMKVParser.toStringMap(new DataView(fileBuffer)); - qmc2Keys = Array.from(map.entries(), ([name, key]) => ({ name: getFileName(name), key })); - } - - if (qmc2Keys) { - dispatch(qmc2ImportKeys(qmc2Keys)); - onClose(); - toast({ - title: `导入成功 (${qmc2Keys.length})`, - description: '记得保存更改来应用。', - isClosable: true, - duration: 5000, - status: 'success', - }); - } else { - alert(`不支持的文件:${file.name}`); - } - } catch (e) { - console.error('error during import: ', e); - alert(`导入数据库时发生错误:${e}`); - } - }; - - return ( - - - - 导入密钥数据库 - - -
- 拖放或点我选择含有密钥的数据库文件 -
- - 选择你的「QQ 音乐」客户端平台以查看对应说明: - - - - 安卓 - iOS - Mac - Windows - - - - - - - - - - - - - - - - -
-
-
- ); -} From 53039567baeca22a2064de34fde506045824e2e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sat, 17 Jun 2023 03:00:06 +0100 Subject: [PATCH 04/11] Revert "ci: reduce ram usage when building" This reverts commit a13034cf353e47ce1f436872d2f7526462bf25ee. --- .drone.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.drone.yml b/.drone.yml index 3335819..027ff27 100644 --- a/.drone.yml +++ b/.drone.yml @@ -15,8 +15,6 @@ steps: environment: # 让 npm 使用淘宝源 npm_config_registry: https://registry.npmmirror.com - # 限制内存使用 - NODE_OPTIONS: --max-old-space-size=512 - name: publish image: node:18.16.0-bullseye From 99b679817b8377884b0b067beca4372811b21a07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sat, 17 Jun 2023 03:18:15 +0100 Subject: [PATCH 05/11] feat: parse kwm v2 key from mmkv --- .../settings/panels/PanelKWMv2Key.tsx | 45 ++++++++++++++----- src/util/MMKVParser.ts | 28 +++++++++++- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/src/features/settings/panels/PanelKWMv2Key.tsx b/src/features/settings/panels/PanelKWMv2Key.tsx index 80a0cb5..b656066 100644 --- a/src/features/settings/panels/PanelKWMv2Key.tsx +++ b/src/features/settings/panels/PanelKWMv2Key.tsx @@ -17,13 +17,17 @@ import { Text, useToast, } from '@chakra-ui/react'; -import { useDispatch, useSelector } from 'react-redux'; -import { kwm2AddKey, kwm2ClearKeys } from '../settingsSlice'; -import { selectStagingKWMv2Keys } from '../settingsSelector'; import { useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; import { MdAdd, MdDeleteForever, MdExpandMore, MdFileUpload } from 'react-icons/md'; -import { KWMv2EKeyItem } from './KWMv2/KWMv2EKeyItem'; + import { ImportSecretModal } from '~/components/ImportSecretModal'; +import { MMKVParser } from '~/util/MMKVParser'; + +import { kwm2AddKey, kwm2ClearKeys, kwm2ImportKeys } from '../settingsSlice'; +import { selectStagingKWMv2Keys } from '../settingsSelector'; +import { KWMv2EKeyItem } from './KWMv2/KWMv2EKeyItem'; +import type { StagingKWMv2Key } from '../keyFormats'; export function PanelKWMv2Key() { const toast = useToast(); @@ -33,12 +37,29 @@ export function PanelKWMv2Key() { const addKey = () => dispatch(kwm2AddKey()); const clearAll = () => dispatch(kwm2ClearKeys()); - const handleSecretImport = () => { - toast({ - title: '尚未实现', - isClosable: true, - status: 'error', - }); + const handleSecretImport = async (file: File) => { + let keys: Omit[] | null = null; + if (/cn\.kuwo\.player\.mmkv\.defaultconfig/i.test(file.name)) { + const fileBuffer = await file.arrayBuffer(); + keys = MMKVParser.parseKuwoEKey(new DataView(fileBuffer)); + } + + if (keys) { + dispatch(kwm2ImportKeys(keys)); + setShowImportModal(false); + toast({ + title: `导入完成,共导入了 ${keys.length} 个密钥。`, + description: '记得按下「保存」来应用。', + isClosable: true, + status: 'success', + }); + } else { + toast({ + title: `不支持的文件:${file.name}`, + isClosable: true, + status: 'error', + }); + } }; return ( @@ -82,12 +103,12 @@ export function PanelKWMv2Key() { setShowImportModal(false)} onImport={handleSecretImport} > - 尚未实现 + 文档缺失 ); diff --git a/src/util/MMKVParser.ts b/src/util/MMKVParser.ts index 530f237..943e07a 100644 --- a/src/util/MMKVParser.ts +++ b/src/util/MMKVParser.ts @@ -1,3 +1,4 @@ +import type { StagingKWMv2Key } from '~/features/settings/keyFormats'; import { formatHex } from './formatHex'; const textDecoder = new TextDecoder('utf-8', { ignoreBOM: true }); @@ -85,6 +86,15 @@ export class MMKVParser { return result; } + public skipContainer() { + // Container [ + // len: int, + // data: variant + // ] + const containerLen = this.readInt(); + this.offset += containerLen; + } + public static toStringMap(view: DataView): Map { const mmkv = new MMKVParser(view); const result = new Map(); @@ -96,7 +106,21 @@ export class MMKVParser { return result; } - public static parseKuwoEKey(_view: DataView): unknown[] { - return []; + public static parseKuwoEKey(view: DataView) { + const mmkv = new MMKVParser(view); + const result: Omit[] = []; + while (!mmkv.eof) { + const key = mmkv.readString(); + const idMatch = key.match(/^sec_ekey#(\d+)-(.+)/); + if (!idMatch) { + mmkv.skipContainer(); + continue; + } + + const [_, rid, quality] = idMatch; + const ekey = mmkv.readVariantString(); + result.push({ rid, quality, ekey }); + } + return result; } } From 761b2a4df00de10e05173e6939ff72932d4af717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sat, 17 Jun 2023 14:25:59 +0100 Subject: [PATCH 06/11] chore: upgrade libparakeet to v0.2.0 --- package.json | 2 +- pnpm-lock.yaml | 792 ++++++++++++++++++------------------------------- 2 files changed, 297 insertions(+), 497 deletions(-) diff --git a/package.json b/package.json index 0ad3924..e0fbfdb 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@chakra-ui/react": "^2.7.0", "@emotion/react": "^11.11.0", "@emotion/styled": "^11.11.0", - "@jixun/libparakeet": "0.1.2", + "@jixun/libparakeet": "0.2.0", "@reduxjs/toolkit": "^1.9.5", "framer-motion": "^10.12.16", "immer": "^10.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3c20d01..3c64281 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,7 +15,7 @@ dependencies: version: 2.1.1 '@chakra-ui/icons': specifier: ^2.0.19 - version: 2.0.19(@chakra-ui/system@2.5.7)(react@18.2.0) + version: 2.0.19(@chakra-ui/system@2.5.8)(react@18.2.0) '@chakra-ui/react': specifier: ^2.7.0 version: 2.7.0(@emotion/react@11.11.0)(@emotion/styled@11.11.0)(@types/react@18.2.7)(framer-motion@10.12.16)(react-dom@18.2.0)(react@18.2.0) @@ -26,8 +26,8 @@ dependencies: specifier: ^11.11.0 version: 11.11.0(@emotion/react@11.11.0)(@types/react@18.2.7)(react@18.2.0) '@jixun/libparakeet': - specifier: 0.1.2 - version: 0.1.2 + specifier: 0.2.0 + version: 0.2.0 '@reduxjs/toolkit': specifier: ^1.9.5 version: 1.9.5(react-redux@8.0.5)(react@18.2.0) @@ -192,39 +192,11 @@ packages: dependencies: '@babel/highlight': 7.18.6 - /@babel/compat-data@7.21.7: - resolution: {integrity: sha512-KYMqFYTaenzMK4yUtf4EW9wc4N9ef80FsbMtkwool5zpwl4YrT1SdWYSTRcT94KO4hannogdS+LxY7L+arP3gA==} - engines: {node: '>=6.9.0'} - dev: true - /@babel/compat-data@7.22.3: resolution: {integrity: sha512-aNtko9OPOwVESUFp3MZfD8Uzxl7JzSeJpd7npIoxCasU37PFbAQRpKglkaKwlHOyeJdrREpo8TW8ldrkYWwvIQ==} engines: {node: '>=6.9.0'} dev: true - /@babel/core@7.21.8: - resolution: {integrity: sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.21.4 - '@babel/generator': 7.21.5 - '@babel/helper-compilation-targets': 7.21.5(@babel/core@7.21.8) - '@babel/helper-module-transforms': 7.21.5 - '@babel/helpers': 7.21.5 - '@babel/parser': 7.21.8 - '@babel/template': 7.20.7 - '@babel/traverse': 7.21.5 - '@babel/types': 7.21.5 - convert-source-map: 1.9.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/core@7.22.1: resolution: {integrity: sha512-Hkqu7J4ynysSXxmAahpN1jjRwVJ+NdpraFLIWflgjpVob3KNyK3/tIUc7Q7szed8WMp0JNa7Qtd1E9Oo22F9gA==} engines: {node: '>=6.9.0'} @@ -248,16 +220,6 @@ packages: - supports-color dev: true - /@babel/generator@7.21.5: - resolution: {integrity: sha512-SrKK/sRv8GesIW1bDagf9cCG38IOMYZusoe1dfg0D8aiUe3Amvoj1QtjTPAWcfrZFvIwlleLb0gxzQidL9w14w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.21.5 - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.18 - jsesc: 2.5.2 - dev: true - /@babel/generator@7.22.3: resolution: {integrity: sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A==} engines: {node: '>=6.9.0'} @@ -272,28 +234,14 @@ packages: resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.5 + '@babel/types': 7.22.3 dev: true /@babel/helper-builder-binary-assignment-operator-visitor@7.21.5: resolution: {integrity: sha512-uNrjKztPLkUk7bpCNC0jEKDJzzkvel/W+HguzbN8krA+LPfC1CEobJEvAvGka2A/M+ViOqXdcRL0GqPUJSjx9g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.5 - dev: true - - /@babel/helper-compilation-targets@7.21.5(@babel/core@7.21.8): - resolution: {integrity: sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.21.7 - '@babel/core': 7.21.8 - '@babel/helper-validator-option': 7.21.0 - browserslist: 4.21.5 - lru-cache: 5.1.1 - semver: 6.3.0 + '@babel/types': 7.22.3 dev: true /@babel/helper-compilation-targets@7.22.1(@babel/core@7.22.1): @@ -310,15 +258,15 @@ packages: semver: 6.3.0 dev: true - /@babel/helper-create-class-features-plugin@7.21.8(@babel/core@7.21.8): + /@babel/helper-create-class-features-plugin@7.21.8(@babel/core@7.22.1): resolution: {integrity: sha512-+THiN8MqiH2AczyuZrnrKL6cAxFRRQDKW9h1YkBvbgKmAm6mwiacig1qT73DHIWMGo40GRnsEfN3LA+E6NtmSw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-environment-visitor': 7.21.5 + '@babel/helper-environment-visitor': 7.22.1 '@babel/helper-function-name': 7.21.0 '@babel/helper-member-expression-to-functions': 7.21.5 '@babel/helper-optimise-call-expression': 7.18.6 @@ -330,25 +278,25 @@ packages: - supports-color dev: true - /@babel/helper-create-regexp-features-plugin@7.21.8(@babel/core@7.21.8): + /@babel/helper-create-regexp-features-plugin@7.21.8(@babel/core@7.22.1): resolution: {integrity: sha512-zGuSdedkFtsFHGbexAvNuipg1hbtitDLo2XE8/uf6Y9sOQV1xsYX/2pNbtedp/X0eU1pIt+kGvaqHCowkRbS5g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-annotate-as-pure': 7.18.6 regexpu-core: 5.3.2 semver: 6.3.0 dev: true - /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.21.8): + /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.22.1): resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} peerDependencies: '@babel/core': ^7.4.0-0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-compilation-targets': 7.21.5(@babel/core@7.21.8) + '@babel/core': 7.22.1 + '@babel/helper-compilation-targets': 7.22.1(@babel/core@7.22.1) '@babel/helper-plugin-utils': 7.21.5 debug: 4.3.4 lodash.debounce: 4.0.8 @@ -358,11 +306,6 @@ packages: - supports-color dev: true - /@babel/helper-environment-visitor@7.21.5: - resolution: {integrity: sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==} - engines: {node: '>=6.9.0'} - dev: true - /@babel/helper-environment-visitor@7.22.1: resolution: {integrity: sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA==} engines: {node: '>=6.9.0'} @@ -387,7 +330,7 @@ packages: resolution: {integrity: sha512-nIcGfgwpH2u4n9GG1HpStW5Ogx7x7ekiFHbjjFRKXbn5zUvqO9ZgotCO4x1aNbKn/x/xOUaXEhyNHCwtFCpxWg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.5 + '@babel/types': 7.22.3 dev: true /@babel/helper-module-imports@7.21.4: @@ -396,22 +339,6 @@ packages: dependencies: '@babel/types': 7.22.3 - /@babel/helper-module-transforms@7.21.5: - resolution: {integrity: sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-environment-visitor': 7.21.5 - '@babel/helper-module-imports': 7.21.4 - '@babel/helper-simple-access': 7.21.5 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/helper-validator-identifier': 7.19.1 - '@babel/template': 7.20.7 - '@babel/traverse': 7.21.5 - '@babel/types': 7.21.5 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/helper-module-transforms@7.22.1: resolution: {integrity: sha512-dxAe9E7ySDGbQdCVOY/4+UcD8M9ZFqZcZhSPsPacvCG4M+9lwtDDQfI2EoaSvmf7W/8yCBkGU0m7Pvt1ru3UZw==} engines: {node: '>=6.9.0'} @@ -432,7 +359,7 @@ packages: resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.5 + '@babel/types': 7.22.3 dev: true /@babel/helper-plugin-utils@7.21.5: @@ -440,17 +367,17 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@babel/helper-remap-async-to-generator@7.18.9(@babel/core@7.21.8): + /@babel/helper-remap-async-to-generator@7.18.9(@babel/core@7.22.1): resolution: {integrity: sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-environment-visitor': 7.21.5 + '@babel/helper-environment-visitor': 7.22.1 '@babel/helper-wrap-function': 7.20.5 - '@babel/types': 7.21.5 + '@babel/types': 7.22.3 transitivePeerDependencies: - supports-color dev: true @@ -459,12 +386,12 @@ packages: resolution: {integrity: sha512-/y7vBgsr9Idu4M6MprbOVUfH3vs7tsIfnVWv/Ml2xgwvyH6LTngdfbf5AdsKwkJy4zgy1X/kuNrEKvhhK28Yrg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-environment-visitor': 7.21.5 + '@babel/helper-environment-visitor': 7.22.1 '@babel/helper-member-expression-to-functions': 7.21.5 '@babel/helper-optimise-call-expression': 7.18.6 - '@babel/template': 7.20.7 - '@babel/traverse': 7.21.5 - '@babel/types': 7.21.5 + '@babel/template': 7.21.9 + '@babel/traverse': 7.22.1 + '@babel/types': 7.22.3 transitivePeerDependencies: - supports-color dev: true @@ -480,7 +407,7 @@ packages: resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.5 + '@babel/types': 7.22.3 dev: true /@babel/helper-split-export-declaration@7.18.6: @@ -508,20 +435,9 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/helper-function-name': 7.21.0 - '@babel/template': 7.20.7 - '@babel/traverse': 7.21.5 - '@babel/types': 7.21.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helpers@7.21.5: - resolution: {integrity: sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.20.7 - '@babel/traverse': 7.21.5 - '@babel/types': 7.21.5 + '@babel/template': 7.21.9 + '@babel/traverse': 7.22.1 + '@babel/types': 7.22.3 transitivePeerDependencies: - supports-color dev: true @@ -545,14 +461,6 @@ packages: chalk: 2.4.2 js-tokens: 4.0.0 - /@babel/parser@7.21.8: - resolution: {integrity: sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.21.5 - dev: true - /@babel/parser@7.22.3: resolution: {integrity: sha512-vrukxyW/ep8UD1UDzOYpTKQ6abgjFoeG6L+4ar9+c5TN9QnlqiOi6QK7LSR5ewm/ERyGkT/Ai6VboNrxhbr9Uw==} engines: {node: '>=6.0.0'} @@ -561,414 +469,414 @@ packages: '@babel/types': 7.22.3 dev: true - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.21.8): + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.20.7(@babel/core@7.21.8): + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.20.7(@babel/core@7.22.1): resolution: {integrity: sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.21.8) + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.22.1) dev: true - /@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.21.8): + /@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.22.1): resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-environment-visitor': 7.21.5 + '@babel/core': 7.22.1 + '@babel/helper-environment-visitor': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 - '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.21.8) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.8) + '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.22.1) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.1) transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.21.8): + /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-create-class-features-plugin': 7.21.8(@babel/core@7.21.8) + '@babel/core': 7.22.1 + '@babel/helper-create-class-features-plugin': 7.21.8(@babel/core@7.22.1) '@babel/helper-plugin-utils': 7.21.5 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-class-static-block@7.21.0(@babel/core@7.21.8): + /@babel/plugin-proposal-class-static-block@7.21.0(@babel/core@7.22.1): resolution: {integrity: sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-create-class-features-plugin': 7.21.8(@babel/core@7.21.8) + '@babel/core': 7.22.1 + '@babel/helper-create-class-features-plugin': 7.21.8(@babel/core@7.22.1) '@babel/helper-plugin-utils': 7.21.5 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.21.8) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.1) transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.21.8): + /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.1) dev: true - /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.21.8): + /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.22.1): resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.1) dev: true - /@babel/plugin-proposal-json-strings@7.18.6(@babel/core@7.21.8): + /@babel/plugin-proposal-json-strings@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.1) dev: true - /@babel/plugin-proposal-logical-assignment-operators@7.20.7(@babel/core@7.21.8): + /@babel/plugin-proposal-logical-assignment-operators@7.20.7(@babel/core@7.22.1): resolution: {integrity: sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.21.8) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.1) dev: true - /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.21.8): + /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.1) dev: true - /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.21.8): + /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.8) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.1) dev: true - /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.21.8): + /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.22.1): resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.21.7 - '@babel/core': 7.21.8 - '@babel/helper-compilation-targets': 7.21.5(@babel/core@7.21.8) + '@babel/compat-data': 7.22.3 + '@babel/core': 7.22.1 + '@babel/helper-compilation-targets': 7.22.1(@babel/core@7.22.1) '@babel/helper-plugin-utils': 7.21.5 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.8) - '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.21.8) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.1) + '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.22.1) dev: true - /@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.21.8): + /@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.1) dev: true - /@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.21.8): + /@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.22.1): resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.1) dev: true - /@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.21.8): + /@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-create-class-features-plugin': 7.21.8(@babel/core@7.21.8) + '@babel/core': 7.22.1 + '@babel/helper-create-class-features-plugin': 7.21.8(@babel/core@7.22.1) '@babel/helper-plugin-utils': 7.21.5 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-private-property-in-object@7.21.0(@babel/core@7.21.8): + /@babel/plugin-proposal-private-property-in-object@7.21.0(@babel/core@7.22.1): resolution: {integrity: sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-create-class-features-plugin': 7.21.8(@babel/core@7.21.8) + '@babel/helper-create-class-features-plugin': 7.21.8(@babel/core@7.22.1) '@babel/helper-plugin-utils': 7.21.5 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.8) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.22.1) transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-unicode-property-regex@7.18.6(@babel/core@7.21.8): + /@babel/plugin-proposal-unicode-property-regex@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} engines: {node: '>=4'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-create-regexp-features-plugin': 7.21.8(@babel/core@7.21.8) + '@babel/core': 7.22.1 + '@babel/helper-create-regexp-features-plugin': 7.21.8(@babel/core@7.22.1) '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.21.8): + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.22.1): resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.21.8): + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.22.1): resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.21.8): + /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.22.1): resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.21.8): + /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.22.1): resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.21.8): + /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.22.1): resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-import-assertions@7.20.0(@babel/core@7.21.8): + /@babel/plugin-syntax-import-assertions@7.20.0(@babel/core@7.22.1): resolution: {integrity: sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.21.8): + /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.22.1): resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.21.8): + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.22.1): resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.21.8): + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.22.1): resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.21.8): + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.22.1): resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.21.8): + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.22.1): resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.21.8): + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.22.1): resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.21.8): + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.22.1): resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.21.8): + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.22.1): resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.21.8): + /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.22.1): resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.21.8): + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.22.1): resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-arrow-functions@7.21.5(@babel/core@7.21.8): + /@babel/plugin-transform-arrow-functions@7.21.5(@babel/core@7.22.1): resolution: {integrity: sha512-wb1mhwGOCaXHDTcsRYMKF9e5bbMgqwxtqa2Y1ifH96dXJPwbuLX9qHy3clhrxVqgMz7nyNXs8VkxdH8UBcjKqA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-async-to-generator@7.20.7(@babel/core@7.21.8): + /@babel/plugin-transform-async-to-generator@7.20.7(@babel/core@7.22.1): resolution: {integrity: sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-module-imports': 7.21.4 '@babel/helper-plugin-utils': 7.21.5 - '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.21.8) + '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.22.1) transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-block-scoped-functions@7.18.6(@babel/core@7.21.8): + /@babel/plugin-transform-block-scoped-functions@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-block-scoping@7.21.0(@babel/core@7.21.8): + /@babel/plugin-transform-block-scoping@7.21.0(@babel/core@7.22.1): resolution: {integrity: sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-classes@7.21.0(@babel/core@7.21.8): + /@babel/plugin-transform-classes@7.21.0(@babel/core@7.22.1): resolution: {integrity: sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-compilation-targets': 7.21.5(@babel/core@7.21.8) - '@babel/helper-environment-visitor': 7.21.5 + '@babel/helper-compilation-targets': 7.22.1(@babel/core@7.22.1) + '@babel/helper-environment-visitor': 7.22.1 '@babel/helper-function-name': 7.21.0 '@babel/helper-optimise-call-expression': 7.18.6 '@babel/helper-plugin-utils': 7.21.5 @@ -979,207 +887,207 @@ packages: - supports-color dev: true - /@babel/plugin-transform-computed-properties@7.21.5(@babel/core@7.21.8): + /@babel/plugin-transform-computed-properties@7.21.5(@babel/core@7.22.1): resolution: {integrity: sha512-TR653Ki3pAwxBxUe8srfF3e4Pe3FTA46uaNHYyQwIoM4oWKSoOZiDNyHJ0oIoDIUPSRQbQG7jzgVBX3FPVne1Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 - '@babel/template': 7.20.7 + '@babel/template': 7.21.9 dev: true - /@babel/plugin-transform-destructuring@7.21.3(@babel/core@7.21.8): + /@babel/plugin-transform-destructuring@7.21.3(@babel/core@7.22.1): resolution: {integrity: sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-dotall-regex@7.18.6(@babel/core@7.21.8): + /@babel/plugin-transform-dotall-regex@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-create-regexp-features-plugin': 7.21.8(@babel/core@7.21.8) + '@babel/core': 7.22.1 + '@babel/helper-create-regexp-features-plugin': 7.21.8(@babel/core@7.22.1) '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-duplicate-keys@7.18.9(@babel/core@7.21.8): + /@babel/plugin-transform-duplicate-keys@7.18.9(@babel/core@7.22.1): resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-exponentiation-operator@7.18.6(@babel/core@7.21.8): + /@babel/plugin-transform-exponentiation-operator@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-builder-binary-assignment-operator-visitor': 7.21.5 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-for-of@7.21.5(@babel/core@7.21.8): + /@babel/plugin-transform-for-of@7.21.5(@babel/core@7.22.1): resolution: {integrity: sha512-nYWpjKW/7j/I/mZkGVgHJXh4bA1sfdFnJoOXwJuj4m3Q2EraO/8ZyrkCau9P5tbHQk01RMSt6KYLCsW7730SXQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-function-name@7.18.9(@babel/core@7.21.8): + /@babel/plugin-transform-function-name@7.18.9(@babel/core@7.22.1): resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-compilation-targets': 7.21.5(@babel/core@7.21.8) + '@babel/core': 7.22.1 + '@babel/helper-compilation-targets': 7.22.1(@babel/core@7.22.1) '@babel/helper-function-name': 7.21.0 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-literals@7.18.9(@babel/core@7.21.8): + /@babel/plugin-transform-literals@7.18.9(@babel/core@7.22.1): resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-member-expression-literals@7.18.6(@babel/core@7.21.8): + /@babel/plugin-transform-member-expression-literals@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-modules-amd@7.20.11(@babel/core@7.21.8): + /@babel/plugin-transform-modules-amd@7.20.11(@babel/core@7.22.1): resolution: {integrity: sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-module-transforms': 7.21.5 + '@babel/core': 7.22.1 + '@babel/helper-module-transforms': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-commonjs@7.21.5(@babel/core@7.21.8): + /@babel/plugin-transform-modules-commonjs@7.21.5(@babel/core@7.22.1): resolution: {integrity: sha512-OVryBEgKUbtqMoB7eG2rs6UFexJi6Zj6FDXx+esBLPTCxCNxAY9o+8Di7IsUGJ+AVhp5ncK0fxWUBd0/1gPhrQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-module-transforms': 7.21.5 + '@babel/core': 7.22.1 + '@babel/helper-module-transforms': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 '@babel/helper-simple-access': 7.21.5 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-systemjs@7.20.11(@babel/core@7.21.8): + /@babel/plugin-transform-modules-systemjs@7.20.11(@babel/core@7.22.1): resolution: {integrity: sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-module-transforms': 7.21.5 + '@babel/helper-module-transforms': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 '@babel/helper-validator-identifier': 7.19.1 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-umd@7.18.6(@babel/core@7.21.8): + /@babel/plugin-transform-modules-umd@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-module-transforms': 7.21.5 + '@babel/core': 7.22.1 + '@babel/helper-module-transforms': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-named-capturing-groups-regex@7.20.5(@babel/core@7.21.8): + /@babel/plugin-transform-named-capturing-groups-regex@7.20.5(@babel/core@7.22.1): resolution: {integrity: sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-create-regexp-features-plugin': 7.21.8(@babel/core@7.21.8) + '@babel/core': 7.22.1 + '@babel/helper-create-regexp-features-plugin': 7.21.8(@babel/core@7.22.1) '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-new-target@7.18.6(@babel/core@7.21.8): + /@babel/plugin-transform-new-target@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-object-super@7.18.6(@babel/core@7.21.8): + /@babel/plugin-transform-object-super@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 '@babel/helper-replace-supers': 7.21.5 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-parameters@7.21.3(@babel/core@7.21.8): + /@babel/plugin-transform-parameters@7.21.3(@babel/core@7.22.1): resolution: {integrity: sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-property-literals@7.18.6(@babel/core@7.21.8): + /@babel/plugin-transform-property-literals@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true @@ -1203,196 +1111,196 @@ packages: '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-regenerator@7.21.5(@babel/core@7.21.8): + /@babel/plugin-transform-regenerator@7.21.5(@babel/core@7.22.1): resolution: {integrity: sha512-ZoYBKDb6LyMi5yCsByQ5jmXsHAQDDYeexT1Szvlmui+lADvfSecr5Dxd/PkrTC3pAD182Fcju1VQkB4oCp9M+w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 regenerator-transform: 0.15.1 dev: true - /@babel/plugin-transform-reserved-words@7.18.6(@babel/core@7.21.8): + /@babel/plugin-transform-reserved-words@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-shorthand-properties@7.18.6(@babel/core@7.21.8): + /@babel/plugin-transform-shorthand-properties@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-spread@7.20.7(@babel/core@7.21.8): + /@babel/plugin-transform-spread@7.20.7(@babel/core@7.22.1): resolution: {integrity: sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 dev: true - /@babel/plugin-transform-sticky-regex@7.18.6(@babel/core@7.21.8): + /@babel/plugin-transform-sticky-regex@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-template-literals@7.18.9(@babel/core@7.21.8): + /@babel/plugin-transform-template-literals@7.18.9(@babel/core@7.22.1): resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-typeof-symbol@7.18.9(@babel/core@7.21.8): + /@babel/plugin-transform-typeof-symbol@7.18.9(@babel/core@7.22.1): resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-unicode-escapes@7.21.5(@babel/core@7.21.8): + /@babel/plugin-transform-unicode-escapes@7.21.5(@babel/core@7.22.1): resolution: {integrity: sha512-LYm/gTOwZqsYohlvFUe/8Tujz75LqqVC2w+2qPHLR+WyWHGCZPN1KBpJCJn+4Bk4gOkQy/IXKIge6az5MqwlOg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/plugin-transform-unicode-regex@7.18.6(@babel/core@7.21.8): + /@babel/plugin-transform-unicode-regex@7.18.6(@babel/core@7.22.1): resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-create-regexp-features-plugin': 7.21.8(@babel/core@7.21.8) + '@babel/core': 7.22.1 + '@babel/helper-create-regexp-features-plugin': 7.21.8(@babel/core@7.22.1) '@babel/helper-plugin-utils': 7.21.5 dev: true - /@babel/preset-env@7.21.5(@babel/core@7.21.8): + /@babel/preset-env@7.21.5(@babel/core@7.22.1): resolution: {integrity: sha512-wH00QnTTldTbf/IefEVyChtRdw5RJvODT/Vb4Vcxq1AZvtXj6T0YeX0cAcXhI6/BdGuiP3GcNIL4OQbI2DVNxg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.21.7 - '@babel/core': 7.21.8 - '@babel/helper-compilation-targets': 7.21.5(@babel/core@7.21.8) + '@babel/compat-data': 7.22.3 + '@babel/core': 7.22.1 + '@babel/helper-compilation-targets': 7.22.1(@babel/core@7.22.1) '@babel/helper-plugin-utils': 7.21.5 '@babel/helper-validator-option': 7.21.0 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.20.7(@babel/core@7.21.8) - '@babel/plugin-proposal-async-generator-functions': 7.20.7(@babel/core@7.21.8) - '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-proposal-class-static-block': 7.21.0(@babel/core@7.21.8) - '@babel/plugin-proposal-dynamic-import': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.21.8) - '@babel/plugin-proposal-json-strings': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-proposal-logical-assignment-operators': 7.20.7(@babel/core@7.21.8) - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.21.8) - '@babel/plugin-proposal-optional-catch-binding': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.21.8) - '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-proposal-private-property-in-object': 7.21.0(@babel/core@7.21.8) - '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.8) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.21.8) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.21.8) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.21.8) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.21.8) - '@babel/plugin-syntax-import-assertions': 7.20.0(@babel/core@7.21.8) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.21.8) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.8) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.21.8) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.8) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.8) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.8) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.8) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.8) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.8) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.21.8) - '@babel/plugin-transform-arrow-functions': 7.21.5(@babel/core@7.21.8) - '@babel/plugin-transform-async-to-generator': 7.20.7(@babel/core@7.21.8) - '@babel/plugin-transform-block-scoped-functions': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-transform-block-scoping': 7.21.0(@babel/core@7.21.8) - '@babel/plugin-transform-classes': 7.21.0(@babel/core@7.21.8) - '@babel/plugin-transform-computed-properties': 7.21.5(@babel/core@7.21.8) - '@babel/plugin-transform-destructuring': 7.21.3(@babel/core@7.21.8) - '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-transform-duplicate-keys': 7.18.9(@babel/core@7.21.8) - '@babel/plugin-transform-exponentiation-operator': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-transform-for-of': 7.21.5(@babel/core@7.21.8) - '@babel/plugin-transform-function-name': 7.18.9(@babel/core@7.21.8) - '@babel/plugin-transform-literals': 7.18.9(@babel/core@7.21.8) - '@babel/plugin-transform-member-expression-literals': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-transform-modules-amd': 7.20.11(@babel/core@7.21.8) - '@babel/plugin-transform-modules-commonjs': 7.21.5(@babel/core@7.21.8) - '@babel/plugin-transform-modules-systemjs': 7.20.11(@babel/core@7.21.8) - '@babel/plugin-transform-modules-umd': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-transform-named-capturing-groups-regex': 7.20.5(@babel/core@7.21.8) - '@babel/plugin-transform-new-target': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-transform-object-super': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.21.8) - '@babel/plugin-transform-property-literals': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-transform-regenerator': 7.21.5(@babel/core@7.21.8) - '@babel/plugin-transform-reserved-words': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-transform-shorthand-properties': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-transform-spread': 7.20.7(@babel/core@7.21.8) - '@babel/plugin-transform-sticky-regex': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-transform-template-literals': 7.18.9(@babel/core@7.21.8) - '@babel/plugin-transform-typeof-symbol': 7.18.9(@babel/core@7.21.8) - '@babel/plugin-transform-unicode-escapes': 7.21.5(@babel/core@7.21.8) - '@babel/plugin-transform-unicode-regex': 7.18.6(@babel/core@7.21.8) - '@babel/preset-modules': 0.1.5(@babel/core@7.21.8) - '@babel/types': 7.21.5 - babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.21.8) - babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.21.8) - babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.21.8) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.20.7(@babel/core@7.22.1) + '@babel/plugin-proposal-async-generator-functions': 7.20.7(@babel/core@7.22.1) + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-proposal-class-static-block': 7.21.0(@babel/core@7.22.1) + '@babel/plugin-proposal-dynamic-import': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.22.1) + '@babel/plugin-proposal-json-strings': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-proposal-logical-assignment-operators': 7.20.7(@babel/core@7.22.1) + '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.22.1) + '@babel/plugin-proposal-optional-catch-binding': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.22.1) + '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-proposal-private-property-in-object': 7.21.0(@babel/core@7.22.1) + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.1) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.22.1) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.1) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.1) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.1) + '@babel/plugin-syntax-import-assertions': 7.20.0(@babel/core@7.22.1) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.22.1) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.1) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.1) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.1) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.1) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.1) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.1) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.1) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.22.1) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.22.1) + '@babel/plugin-transform-arrow-functions': 7.21.5(@babel/core@7.22.1) + '@babel/plugin-transform-async-to-generator': 7.20.7(@babel/core@7.22.1) + '@babel/plugin-transform-block-scoped-functions': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-transform-block-scoping': 7.21.0(@babel/core@7.22.1) + '@babel/plugin-transform-classes': 7.21.0(@babel/core@7.22.1) + '@babel/plugin-transform-computed-properties': 7.21.5(@babel/core@7.22.1) + '@babel/plugin-transform-destructuring': 7.21.3(@babel/core@7.22.1) + '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-transform-duplicate-keys': 7.18.9(@babel/core@7.22.1) + '@babel/plugin-transform-exponentiation-operator': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-transform-for-of': 7.21.5(@babel/core@7.22.1) + '@babel/plugin-transform-function-name': 7.18.9(@babel/core@7.22.1) + '@babel/plugin-transform-literals': 7.18.9(@babel/core@7.22.1) + '@babel/plugin-transform-member-expression-literals': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-transform-modules-amd': 7.20.11(@babel/core@7.22.1) + '@babel/plugin-transform-modules-commonjs': 7.21.5(@babel/core@7.22.1) + '@babel/plugin-transform-modules-systemjs': 7.20.11(@babel/core@7.22.1) + '@babel/plugin-transform-modules-umd': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-transform-named-capturing-groups-regex': 7.20.5(@babel/core@7.22.1) + '@babel/plugin-transform-new-target': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-transform-object-super': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.22.1) + '@babel/plugin-transform-property-literals': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-transform-regenerator': 7.21.5(@babel/core@7.22.1) + '@babel/plugin-transform-reserved-words': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-transform-shorthand-properties': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-transform-spread': 7.20.7(@babel/core@7.22.1) + '@babel/plugin-transform-sticky-regex': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-transform-template-literals': 7.18.9(@babel/core@7.22.1) + '@babel/plugin-transform-typeof-symbol': 7.18.9(@babel/core@7.22.1) + '@babel/plugin-transform-unicode-escapes': 7.21.5(@babel/core@7.22.1) + '@babel/plugin-transform-unicode-regex': 7.18.6(@babel/core@7.22.1) + '@babel/preset-modules': 0.1.5(@babel/core@7.22.1) + '@babel/types': 7.22.3 + babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.22.1) + babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.22.1) + babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.22.1) core-js-compat: 3.30.2 semver: 6.3.0 transitivePeerDependencies: - supports-color dev: true - /@babel/preset-modules@0.1.5(@babel/core@7.21.8): + /@babel/preset-modules@0.1.5(@babel/core@7.22.1): resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-plugin-utils': 7.21.5 - '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.21.8) - '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.21.8) - '@babel/types': 7.21.5 + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.22.1) + '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.22.1) + '@babel/types': 7.22.3 esutils: 2.0.3 dev: true @@ -1405,6 +1313,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.13.11 + dev: false /@babel/runtime@7.22.3: resolution: {integrity: sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==} @@ -1412,15 +1321,6 @@ packages: dependencies: regenerator-runtime: 0.13.11 - /@babel/template@7.20.7: - resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.21.4 - '@babel/parser': 7.21.8 - '@babel/types': 7.21.5 - dev: true - /@babel/template@7.21.9: resolution: {integrity: sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==} engines: {node: '>=6.9.0'} @@ -1430,24 +1330,6 @@ packages: '@babel/types': 7.22.3 dev: true - /@babel/traverse@7.21.5: - resolution: {integrity: sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.21.4 - '@babel/generator': 7.21.5 - '@babel/helper-environment-visitor': 7.21.5 - '@babel/helper-function-name': 7.21.0 - '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.21.8 - '@babel/types': 7.21.5 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/traverse@7.22.1: resolution: {integrity: sha512-lAWkdCoUFnmwLBhIRLciFntGYsIIoC6vIbN8zrLPqBnJmPu7Z6nzqnKd7FsxQUNAvZfVZ0x6KdNvNp8zWIOHSQ==} engines: {node: '>=6.9.0'} @@ -1466,15 +1348,6 @@ packages: - supports-color dev: true - /@babel/types@7.21.5: - resolution: {integrity: sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.21.5 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - dev: true - /@babel/types@7.22.3: resolution: {integrity: sha512-P3na3xIQHTKY4L0YOG7pM8M8uoUIB910WQaSiiMCZUC2Cy8XFEQONGABFnHWBa2gpGKODTAJcNhi5Zk0sLRrzg==} engines: {node: '>=6.9.0'} @@ -1744,17 +1617,6 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/icon@3.0.16(@chakra-ui/system@2.5.7)(react@18.2.0): - resolution: {integrity: sha512-RpA1X5Ptz8Mt39HSyEIW1wxAz2AXyf9H0JJ5HVx/dBdMZaGMDJ0HyyPBVci0m4RCoJuyG1HHG/DXJaVfUTVAeg==} - peerDependencies: - '@chakra-ui/system': '>=2.0.0' - react: '>=18' - dependencies: - '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.7(@emotion/react@11.11.0)(@emotion/styled@11.11.0)(react@18.2.0) - react: 18.2.0 - dev: false - /@chakra-ui/icon@3.0.16(@chakra-ui/system@2.5.8)(react@18.2.0): resolution: {integrity: sha512-RpA1X5Ptz8Mt39HSyEIW1wxAz2AXyf9H0JJ5HVx/dBdMZaGMDJ0HyyPBVci0m4RCoJuyG1HHG/DXJaVfUTVAeg==} peerDependencies: @@ -1766,14 +1628,14 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/icons@2.0.19(@chakra-ui/system@2.5.7)(react@18.2.0): + /@chakra-ui/icons@2.0.19(@chakra-ui/system@2.5.8)(react@18.2.0): resolution: {integrity: sha512-0A6U1ZBZhLIxh3QgdjuvIEhAZi3B9v8g6Qvlfa3mu6vSnXQn2CHBZXmJwxpXxO40NK/2gj/gKXrLeUaFR6H/Qw==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/icon': 3.0.16(@chakra-ui/system@2.5.7)(react@18.2.0) - '@chakra-ui/system': 2.5.7(@emotion/react@11.11.0)(@emotion/styled@11.11.0)(react@18.2.0) + '@chakra-ui/icon': 3.0.16(@chakra-ui/system@2.5.8)(react@18.2.0) + '@chakra-ui/system': 2.5.8(@emotion/react@11.11.0)(@emotion/styled@11.11.0)(react@18.2.0) react: 18.2.0 dev: false @@ -2387,14 +2249,6 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/styled-system@2.9.0: - resolution: {integrity: sha512-rToN30eOezrTZ5qBHmWqEwsYPenHtc3WU6ODAfMUwNnmCJQiu2erRGv8JwIjmRJnKSOEnNKccI2UXe2EwI6+JA==} - dependencies: - '@chakra-ui/shared-utils': 2.0.5 - csstype: 3.1.1 - lodash.mergewith: 4.6.2 - dev: false - /@chakra-ui/styled-system@2.9.1: resolution: {integrity: sha512-jhYKBLxwOPi9/bQt9kqV3ELa/4CjmNNruTyXlPp5M0v0+pDMUngPp48mVLoskm9RKZGE0h1qpvj/jZ3K7c7t8w==} dependencies: @@ -2417,25 +2271,6 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/system@2.5.7(@emotion/react@11.11.0)(@emotion/styled@11.11.0)(react@18.2.0): - resolution: {integrity: sha512-yB6en7YdJPxKvKY2jJROVwkBE2CLFmHS4ZDx27VdYs0Fa4kGiyDFhJAfnMtLBNDVsTy1NhUHL9aqR63u56QqFg==} - peerDependencies: - '@emotion/react': ^11.0.0 - '@emotion/styled': ^11.0.0 - react: '>=18' - dependencies: - '@chakra-ui/color-mode': 2.1.12(react@18.2.0) - '@chakra-ui/object-utils': 2.1.0 - '@chakra-ui/react-utils': 2.0.12(react@18.2.0) - '@chakra-ui/styled-system': 2.9.0 - '@chakra-ui/theme-utils': 2.0.17 - '@chakra-ui/utils': 2.0.15 - '@emotion/react': 11.11.0(@types/react@18.2.7)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.0)(@types/react@18.2.7)(react@18.2.0) - react: 18.2.0 - react-fast-compare: 3.2.1 - dev: false - /@chakra-ui/system@2.5.8(@emotion/react@11.11.0)(@emotion/styled@11.11.0)(react@18.2.0): resolution: {integrity: sha512-Vy8UUaCxikOzOGE54IP8tKouvU38rEYU1HCSquU9+oe7Jd70HaiLa4vmUKvHyMUmxkOzDHIkgZLbVQCubSnN5w==} peerDependencies: @@ -2510,17 +2345,6 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/theme-tools@2.0.17(@chakra-ui/styled-system@2.9.0): - resolution: {integrity: sha512-Auu38hnihlJZQcPok6itRDBbwof3TpXGYtDPnOvrq4Xp7jnab36HLt7KEXSDPXbtOk3ZqU99pvI1en5LbDrdjg==} - peerDependencies: - '@chakra-ui/styled-system': '>=2.0.0' - dependencies: - '@chakra-ui/anatomy': 2.1.2 - '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/styled-system': 2.9.0 - color2k: 2.0.2 - dev: false - /@chakra-ui/theme-tools@2.0.18(@chakra-ui/styled-system@2.9.1): resolution: {integrity: sha512-MbiRuXb2tb41FbnW41zhsYYAU0znlpfYZnu0mxCf8U2otCwPekJCfESUGYypjq4JnydQ7TDOk+Kz/Wi974l4mw==} peerDependencies: @@ -2532,15 +2356,6 @@ packages: color2k: 2.0.2 dev: false - /@chakra-ui/theme-utils@2.0.17: - resolution: {integrity: sha512-aUaVLFIU1Rs8m+5WVOUvqHKapOX8nSgUVGaeRWS4odxBM95dG4j15f4L88LEMw4D4+WWd0CSAS139OnRgj1rCw==} - dependencies: - '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/styled-system': 2.9.0 - '@chakra-ui/theme': 3.1.1(@chakra-ui/styled-system@2.9.0) - lodash.mergewith: 4.6.2 - dev: false - /@chakra-ui/theme-utils@2.0.18: resolution: {integrity: sha512-aSbkUUiFpc1NHC7lQdA6uYlr6EcZFXz6b4aJ7VRDpqTiywvqYnvfGzhmsB0z94vgtS9qXc6HoIwBp25jYGV2MA==} dependencies: @@ -2550,17 +2365,6 @@ packages: lodash.mergewith: 4.6.2 dev: false - /@chakra-ui/theme@3.1.1(@chakra-ui/styled-system@2.9.0): - resolution: {integrity: sha512-VHcG0CPLd9tgvWnajpAGqrAYhx4HwgfK0E9VOrdwa/3bN+AgY/0EAAXzfe0Q0W2MBWzSgaYqZcQ5cDRpYbiYPA==} - peerDependencies: - '@chakra-ui/styled-system': '>=2.8.0' - dependencies: - '@chakra-ui/anatomy': 2.1.2 - '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/styled-system': 2.9.0 - '@chakra-ui/theme-tools': 2.0.17(@chakra-ui/styled-system@2.9.0) - dev: false - /@chakra-ui/theme@3.1.2(@chakra-ui/styled-system@2.9.1): resolution: {integrity: sha512-ebUXMS3LZw2OZxEQNYaFw3/XuA3jpyprhS/frjHMvZKSOaCjMW+c9z25S0jp1NnpQff08VGI8EWbyVZECXU1QA==} peerDependencies: @@ -3062,8 +2866,8 @@ packages: chalk: 4.1.2 dev: true - /@jixun/libparakeet@0.1.2: - resolution: {integrity: sha512-PxhA7EtC3ss3ACxaGckgD41wGAhWllfy80LfL8GMiXkdXMipgcfFfeEcJBBpvTZ/FlDfoFLDJSOz0uculhsgnQ==} + /@jixun/libparakeet@0.2.0: + resolution: {integrity: sha512-FASxHQuiLZZMv2QpP/RajmUuI+HiKJNRYVHkUkZ7UdKpOesWVhhuXv5FGEETLL/Im/Ky2orpF3gOnejY0tR+Ow==} dev: false /@jridgewell/gen-mapping@0.3.3: @@ -3155,7 +2959,7 @@ packages: reselect: 4.1.8 dev: false - /@rollup/plugin-babel@5.3.1(@babel/core@7.21.8)(rollup@2.79.1): + /@rollup/plugin-babel@5.3.1(@babel/core@7.22.1)(rollup@2.79.1): resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} engines: {node: '>= 10.0.0'} peerDependencies: @@ -3166,7 +2970,7 @@ packages: '@types/babel__core': optional: true dependencies: - '@babel/core': 7.21.8 + '@babel/core': 7.22.1 '@babel/helper-module-imports': 7.21.4 '@rollup/pluginutils': 3.1.0(rollup@2.79.1) rollup: 2.79.1 @@ -3508,10 +3312,6 @@ packages: resolution: {integrity: sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==} dev: false - /@types/node@20.1.4: - resolution: {integrity: sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q==} - dev: true - /@types/node@20.2.5: resolution: {integrity: sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==} dev: true @@ -3551,7 +3351,7 @@ packages: /@types/resolve@1.17.1: resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} dependencies: - '@types/node': 20.1.4 + '@types/node': 20.2.5 dev: true /@types/scheduler@0.16.3: @@ -3995,38 +3795,38 @@ packages: resolve: 1.22.2 dev: false - /babel-plugin-polyfill-corejs2@0.3.3(@babel/core@7.21.8): + /babel-plugin-polyfill-corejs2@0.3.3(@babel/core@7.22.1): resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.21.7 - '@babel/core': 7.21.8 - '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.8) + '@babel/compat-data': 7.22.3 + '@babel/core': 7.22.1 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.22.1) semver: 6.3.0 transitivePeerDependencies: - supports-color dev: true - /babel-plugin-polyfill-corejs3@0.6.0(@babel/core@7.21.8): + /babel-plugin-polyfill-corejs3@0.6.0(@babel/core@7.22.1): resolution: {integrity: sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.8) + '@babel/core': 7.22.1 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.22.1) core-js-compat: 3.30.2 transitivePeerDependencies: - supports-color dev: true - /babel-plugin-polyfill-regenerator@0.4.1(@babel/core@7.21.8): + /babel-plugin-polyfill-regenerator@0.4.1(@babel/core@7.22.1): resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.8 - '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.8) + '@babel/core': 7.22.1 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.22.1) transitivePeerDependencies: - supports-color dev: true @@ -5608,7 +5408,7 @@ packages: resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 20.1.4 + '@types/node': 20.2.5 merge-stream: 2.0.0 supports-color: 7.2.0 dev: true @@ -6534,7 +6334,7 @@ packages: /regenerator-transform@0.15.1: resolution: {integrity: sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==} dependencies: - '@babel/runtime': 7.21.5 + '@babel/runtime': 7.22.3 dev: true /regexp.prototype.flags@1.5.0: @@ -7579,10 +7379,10 @@ packages: engines: {node: '>=10.0.0'} dependencies: '@apideck/better-ajv-errors': 0.3.6(ajv@8.12.0) - '@babel/core': 7.21.8 - '@babel/preset-env': 7.21.5(@babel/core@7.21.8) - '@babel/runtime': 7.21.5 - '@rollup/plugin-babel': 5.3.1(@babel/core@7.21.8)(rollup@2.79.1) + '@babel/core': 7.22.1 + '@babel/preset-env': 7.21.5(@babel/core@7.22.1) + '@babel/runtime': 7.22.3 + '@rollup/plugin-babel': 5.3.1(@babel/core@7.22.1)(rollup@2.79.1) '@rollup/plugin-node-resolve': 11.2.1(rollup@2.79.1) '@rollup/plugin-replace': 2.4.2(rollup@2.79.1) '@surma/rollup-plugin-off-main-thread': 2.2.3 From 2881f70f6824f6ec63d5ef4891bfaeab145bb144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sat, 17 Jun 2023 14:28:36 +0100 Subject: [PATCH 07/11] refactor: move text encoder/decoder to util file --- src/decrypt-worker/crypto/qmc/qmc_v2.ts | 4 ++-- src/decrypt-worker/util/utf8Encoder.ts | 10 ++++++++++ src/util/MMKVParser.ts | 5 ++--- src/util/levenshtein.ts | 8 ++++---- 4 files changed, 18 insertions(+), 9 deletions(-) create mode 100644 src/decrypt-worker/util/utf8Encoder.ts diff --git a/src/decrypt-worker/crypto/qmc/qmc_v2.ts b/src/decrypt-worker/crypto/qmc/qmc_v2.ts index 116a2a8..c39234a 100644 --- a/src/decrypt-worker/crypto/qmc/qmc_v2.ts +++ b/src/decrypt-worker/crypto/qmc/qmc_v2.ts @@ -3,6 +3,7 @@ import type { CryptoBase } from '../CryptoBase'; import type { DecryptCommandOptions } from '~/decrypt-worker/types.ts'; import { SEED, ENC_V2_KEY_1, ENC_V2_KEY_2 } from './qmc_v2.key.ts'; import { fetchParakeet } from '@jixun/libparakeet'; +import { stringToUTF8Bytes } from '~/decrypt-worker/util/utf8Encoder.ts'; export class QMC2Crypto implements CryptoBase { cryptoName = 'QMC/v2'; @@ -36,8 +37,7 @@ export class QMC2CryptoWithKey implements CryptoBase { } const parakeet = await fetchParakeet(); - const textEncoder = new TextEncoder(); - const key = textEncoder.encode(options.qmc2Key); + const key = stringToUTF8Bytes(options.qmc2Key); const keyCrypto = parakeet.make.QMCv2KeyCrypto(SEED, ENC_V2_KEY_1, ENC_V2_KEY_2); return transformBlob(buffer, (p) => p.make.QMCv2EKey(key, keyCrypto), { parakeet, diff --git a/src/decrypt-worker/util/utf8Encoder.ts b/src/decrypt-worker/util/utf8Encoder.ts new file mode 100644 index 0000000..e679be2 --- /dev/null +++ b/src/decrypt-worker/util/utf8Encoder.ts @@ -0,0 +1,10 @@ +export const utf8Encoder = new TextEncoder(); +export const utf8Decoder = new TextDecoder('utf-8'); + +export function stringToUTF8Bytes(str: string) { + return utf8Encoder.encode(str); +} + +export function bytesToUTF8String(str: BufferSource) { + return utf8Decoder.decode(str); +} diff --git a/src/util/MMKVParser.ts b/src/util/MMKVParser.ts index 943e07a..f2a7d43 100644 --- a/src/util/MMKVParser.ts +++ b/src/util/MMKVParser.ts @@ -1,8 +1,7 @@ import type { StagingKWMv2Key } from '~/features/settings/keyFormats'; +import { bytesToUTF8String } from '~/decrypt-worker/util/utf8Encoder'; import { formatHex } from './formatHex'; -const textDecoder = new TextDecoder('utf-8', { ignoreBOM: true }); - export class MMKVParser { private offset = 4; private length: number; @@ -67,7 +66,7 @@ export class MMKVParser { // ] const strByteLen = this.readInt(); const data = this.readBytes(strByteLen); - return textDecoder.decode(data).normalize(); + return bytesToUTF8String(data).normalize(); } public readVariantString() { diff --git a/src/util/levenshtein.ts b/src/util/levenshtein.ts index 49617c5..340a057 100644 --- a/src/util/levenshtein.ts +++ b/src/util/levenshtein.ts @@ -1,6 +1,6 @@ -const textEncoder = new TextEncoder(); - // translation of pseudocode from Wikipedia: +import { stringToUTF8Bytes } from '~/decrypt-worker/util/utf8Encoder'; + // https://en.wikipedia.org/wiki/Levenshtein_distance#Iterative_with_two_matrix_rows export function levenshtein(str1: string, str2: string) { if (str1 === str2) { @@ -14,8 +14,8 @@ export function levenshtein(str1: string, str2: string) { } // Convert them to Uint8Array to avoid expensive string APIs. - const s = textEncoder.encode(str1.toLowerCase()); - const t = textEncoder.encode(str2.toLowerCase()); + const s = stringToUTF8Bytes(str1.normalize().toLowerCase()); + const t = stringToUTF8Bytes(str2.normalize().toLowerCase()); const m = s.byteLength; const n = t.byteLength; From 6f1d1423fe341d5133471e1ac2a9fe5e9c7f8acc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sat, 17 Jun 2023 14:29:24 +0100 Subject: [PATCH 08/11] refactor: move QMCv2KeyCrypto constructor to shared utility method --- src/decrypt-worker/crypto/qmc/qmc_v2.ts | 3 ++- src/decrypt-worker/util/qmc2KeyCrypto.ts | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 src/decrypt-worker/util/qmc2KeyCrypto.ts diff --git a/src/decrypt-worker/crypto/qmc/qmc_v2.ts b/src/decrypt-worker/crypto/qmc/qmc_v2.ts index c39234a..6996802 100644 --- a/src/decrypt-worker/crypto/qmc/qmc_v2.ts +++ b/src/decrypt-worker/crypto/qmc/qmc_v2.ts @@ -4,6 +4,7 @@ import type { DecryptCommandOptions } from '~/decrypt-worker/types.ts'; import { SEED, ENC_V2_KEY_1, ENC_V2_KEY_2 } from './qmc_v2.key.ts'; import { fetchParakeet } from '@jixun/libparakeet'; import { stringToUTF8Bytes } from '~/decrypt-worker/util/utf8Encoder.ts'; +import { makeQMCv2KeyCrypto } from '~/decrypt-worker/util/qmc2KeyCrypto.ts'; export class QMC2Crypto implements CryptoBase { cryptoName = 'QMC/v2'; @@ -38,7 +39,7 @@ export class QMC2CryptoWithKey implements CryptoBase { const parakeet = await fetchParakeet(); const key = stringToUTF8Bytes(options.qmc2Key); - const keyCrypto = parakeet.make.QMCv2KeyCrypto(SEED, ENC_V2_KEY_1, ENC_V2_KEY_2); + const keyCrypto = makeQMCv2KeyCrypto(parakeet); return transformBlob(buffer, (p) => p.make.QMCv2EKey(key, keyCrypto), { parakeet, cleanup: () => keyCrypto.delete(), diff --git a/src/decrypt-worker/util/qmc2KeyCrypto.ts b/src/decrypt-worker/util/qmc2KeyCrypto.ts new file mode 100644 index 0000000..7f534ee --- /dev/null +++ b/src/decrypt-worker/util/qmc2KeyCrypto.ts @@ -0,0 +1,4 @@ +import type { Parakeet } from '@jixun/libparakeet'; +import { SEED, ENC_V2_KEY_1, ENC_V2_KEY_2 } from '../crypto/qmc/qmc_v2.key'; + +export const makeQMCv2KeyCrypto = (p: Parakeet) => p.make.QMCv2KeyCrypto(SEED, ENC_V2_KEY_1, ENC_V2_KEY_2); From 32dbed45cbdeaed6415d8c01402997a699d89bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sat, 17 Jun 2023 14:29:50 +0100 Subject: [PATCH 09/11] feat: add KWMv2 support --- src/crypto/pasreKuwo.ts | 25 ++++++++++++ src/crypto/strlen.ts | 9 +++++ src/decrypt-worker/crypto/kwm/kwm.ts | 15 ++++++- src/decrypt-worker/types.ts | 1 + src/features/file-listing/fileListingSlice.ts | 18 +++++++-- src/features/settings/keyFormats.ts | 14 +++++-- src/features/settings/persistSettings.ts | 11 ++++++ src/features/settings/settingsSelector.ts | 39 +++++++++++++------ 8 files changed, 112 insertions(+), 20 deletions(-) create mode 100644 src/crypto/pasreKuwo.ts create mode 100644 src/crypto/strlen.ts diff --git a/src/crypto/pasreKuwo.ts b/src/crypto/pasreKuwo.ts new file mode 100644 index 0000000..db6cf90 --- /dev/null +++ b/src/crypto/pasreKuwo.ts @@ -0,0 +1,25 @@ +import { bytesToUTF8String } from '~/decrypt-worker/util/utf8Encoder'; +import { strlen } from './strlen'; + +export interface KuwoHeader { + rid: string; // uint64 + encVersion: 1 | 2; // uint32 + quality: string; +} + +export function parseKuwoHeader(view: DataView): KuwoHeader | null { + const magic = view.buffer.slice(view.byteOffset, view.byteOffset + 0x10); + if (bytesToUTF8String(magic) !== 'yeelion-kuwo-tme') { + return null; // not kuwo-encrypted file + } + + const qualityBytes = new Uint8Array(view.buffer.slice(view.byteOffset + 0x30, view.byteOffset + 0x40)); + const qualityLen = strlen(qualityBytes); + const quality = bytesToUTF8String(qualityBytes.slice(0, qualityLen)); + + return { + encVersion: view.getUint32(0x10, true) as 1 | 2, + rid: view.getUint32(0x18, true).toString(), + quality, + }; +} diff --git a/src/crypto/strlen.ts b/src/crypto/strlen.ts new file mode 100644 index 0000000..b4d67df --- /dev/null +++ b/src/crypto/strlen.ts @@ -0,0 +1,9 @@ +export function strlen(data: Uint8Array): number { + const n = data.byteLength; + for (let i = 0; i < n; i++) { + if (data[i] === 0) { + return i; + } + } + return n; +} diff --git a/src/decrypt-worker/crypto/kwm/kwm.ts b/src/decrypt-worker/crypto/kwm/kwm.ts index 063002d..f4c08c4 100644 --- a/src/decrypt-worker/crypto/kwm/kwm.ts +++ b/src/decrypt-worker/crypto/kwm/kwm.ts @@ -1,14 +1,25 @@ import { transformBlob } from '~/decrypt-worker/util/transformBlob'; import type { CryptoBase } from '../CryptoBase'; import { KWM_KEY } from './kwm.key'; +import { DecryptCommandOptions } from '~/decrypt-worker/types'; +import { makeQMCv2KeyCrypto } from '~/decrypt-worker/util/qmc2KeyCrypto'; +import { fetchParakeet } from '@jixun/libparakeet'; +import { stringToUTF8Bytes } from '~/decrypt-worker/util/utf8Encoder'; // v1 only export class KWMCrypto implements CryptoBase { cryptoName = 'KWM'; checkByDecryptHeader = true; - async decrypt(buffer: ArrayBuffer): Promise { - return transformBlob(buffer, (p) => p.make.KuwoKWM(KWM_KEY)); + async decrypt(buffer: ArrayBuffer, opts: DecryptCommandOptions): Promise { + const kwm2key = opts.kwm2key ?? ''; + + const parakeet = await fetchParakeet(); + const keyCrypto = makeQMCv2KeyCrypto(parakeet); + return transformBlob(buffer, (p) => p.make.KuwoKWMv2(KWM_KEY, stringToUTF8Bytes(kwm2key), keyCrypto), { + cleanup: () => keyCrypto.delete(), + parakeet, + }); } public static make() { diff --git a/src/decrypt-worker/types.ts b/src/decrypt-worker/types.ts index 79ea815..232264f 100644 --- a/src/decrypt-worker/types.ts +++ b/src/decrypt-worker/types.ts @@ -1,5 +1,6 @@ export interface DecryptCommandOptions { qmc2Key?: string; + kwm2key?: string; } export interface DecryptCommandPayload { diff --git a/src/features/file-listing/fileListingSlice.ts b/src/features/file-listing/fileListingSlice.ts index d1e575b..533f7ea 100644 --- a/src/features/file-listing/fileListingSlice.ts +++ b/src/features/file-listing/fileListingSlice.ts @@ -1,11 +1,12 @@ import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; import type { PayloadAction } from '@reduxjs/toolkit'; import type { RootState } from '~/store'; -import { decryptionQueue } from '~/decrypt-worker/client'; import type { DecryptionResult } from '~/decrypt-worker/constants'; +import type { DecryptCommandOptions } from '~/decrypt-worker/types'; +import { decryptionQueue } from '~/decrypt-worker/client'; import { DecryptErrorType } from '~/decrypt-worker/util/DecryptError'; -import { selectDecryptOptionByFile } from '../settings/settingsSelector'; +import { selectQMCv2KeyByFileName, selectKWMv2Key } from '../settings/settingsSelector'; export enum ProcessState { QUEUED = 'QUEUED', @@ -63,7 +64,18 @@ export const processFile = createAsyncThunk< thunkAPI.dispatch(setFileAsProcessing({ id: fileId })); }; - const options = selectDecryptOptionByFile(state, file.fileName); + const fileHeader = await fetch(file.raw, { + headers: { + Range: 'bytes=0-1023', + }, + }) + .then((r) => r.blob()) + .then((r) => r.arrayBuffer()); + + const options: DecryptCommandOptions = { + qmc2Key: selectQMCv2KeyByFileName(state, file.fileName), + kwm2key: selectKWMv2Key(state, new DataView(fileHeader)), + }; return decryptionQueue.add({ id: fileId, blobURI: file.raw, options }, onPreProcess); }); diff --git a/src/features/settings/keyFormats.ts b/src/features/settings/keyFormats.ts index 65ce879..a9647d6 100644 --- a/src/features/settings/keyFormats.ts +++ b/src/features/settings/keyFormats.ts @@ -51,6 +51,13 @@ export interface StagingKWMv2Key { export type ProductionKWMv2Keys = Record; +export const parseKwm2ProductionKey = (key: string): null | { rid: string; quality: string } => { + const m = key.match(/^(\d+)-(\w+)$/); + if (!m) return null; + const [_, rid, quality] = m; + + return { rid, quality }; +}; export const kwm2StagingToProductionKey = (key: StagingKWMv2Key) => `${key.rid}-${key.quality}`; export const kwm2StagingToProductionValue = (key: StagingKWMv2Key) => key.ekey; export const kwm2ProductionToStaging = ( @@ -59,9 +66,8 @@ export const kwm2ProductionToStaging = ( ): null | StagingKWMv2Key => { if (typeof value !== 'string') return null; - const m = key.match(/^(\d+)-(\w+)$/); - if (!m) return null; + const parsed = parseKwm2ProductionKey(key); + if (!parsed) return null; - const [_, rid, quality] = m; - return { id: nanoid(), rid, quality, ekey: value }; + return { id: nanoid(), rid: parsed.rid, quality: parsed.quality, ekey: value }; }; diff --git a/src/features/settings/persistSettings.ts b/src/features/settings/persistSettings.ts index c77d543..c16163c 100644 --- a/src/features/settings/persistSettings.ts +++ b/src/features/settings/persistSettings.ts @@ -5,6 +5,7 @@ import type { AppStore } from '~/store'; import { settingsSlice, setProductionChanges, ProductionSettings } from './settingsSlice'; import { enumObject } from '~/util/objects'; import { getLogger } from '~/util/logUtils'; +import { parseKwm2ProductionKey } from './keyFormats'; const DEFAULT_STORAGE_KEY = 'um-react-settings'; @@ -22,6 +23,16 @@ function mergeSettings(settings: ProductionSettings): ProductionSettings { draft.qmc2.allowFuzzyNameSearch = allowFuzzyNameSearch; } } + + if (settings?.kwm2) { + const { keys } = settings.kwm2; + + for (const [k, v] of enumObject(keys)) { + if (typeof v === 'string' && parseKwm2ProductionKey(k)) { + draft.kwm2.keys[k] = v; + } + } + } }); } diff --git a/src/features/settings/settingsSelector.ts b/src/features/settings/settingsSelector.ts index 3798f41..42d61b7 100644 --- a/src/features/settings/settingsSelector.ts +++ b/src/features/settings/settingsSelector.ts @@ -1,30 +1,47 @@ -import type { DecryptCommandOptions } from '~/decrypt-worker/types'; +import { parseKuwoHeader } from '~/crypto/pasreKuwo'; import type { RootState } from '~/store'; import { closestByLevenshtein } from '~/util/levenshtein'; import { hasOwn } from '~/util/objects'; +import { kwm2StagingToProductionKey } from './keyFormats'; export const selectStagingQMCv2Settings = (state: RootState) => state.settings.staging.qmc2; export const selectFinalQMCv2Settings = (state: RootState) => state.settings.production.qmc2; export const selectStagingKWMv2Keys = (state: RootState) => state.settings.staging.kwm2.keys; +export const selectFinalKWMv2Keys = (state: RootState) => state.settings.production.kwm2.keys; -export const selectDecryptOptionByFile = (state: RootState, name: string): DecryptCommandOptions => { +export const selectQMCv2KeyByFileName = (state: RootState, name: string): string | undefined => { const normalizedName = name.normalize(); - let qmc2Key: string | undefined; - const { keys: qmc2Keys, allowFuzzyNameSearch } = selectFinalQMCv2Settings(state); - if (hasOwn(qmc2Keys, normalizedName)) { - qmc2Key = qmc2Keys[normalizedName]; + let ekey: string | undefined; + const { keys, allowFuzzyNameSearch } = selectFinalQMCv2Settings(state); + if (hasOwn(keys, normalizedName)) { + ekey = keys[normalizedName]; } else if (allowFuzzyNameSearch) { - const qmc2KeyStoreNames = Object.keys(qmc2Keys); + const qmc2KeyStoreNames = Object.keys(keys); if (qmc2KeyStoreNames.length > 0) { const closestName = closestByLevenshtein(normalizedName, qmc2KeyStoreNames); console.debug('qmc2: key db could not find %o, using closest %o instead.', normalizedName, closestName); - qmc2Key = qmc2Keys[closestName]; + ekey = keys[closestName]; } } - return { - qmc2Key, - }; + return ekey; +}; + +export const selectKWMv2Key = (state: RootState, headerView: DataView): string | undefined => { + const hdr = parseKuwoHeader(headerView); + if (!hdr) { + return; + } + + const keys = selectFinalKWMv2Keys(state); + const lookupKey = kwm2StagingToProductionKey({ id: '', ekey: '', quality: hdr.quality, rid: hdr.rid }); + + let ekey: string | undefined; + if (hasOwn(keys, lookupKey)) { + ekey = keys[lookupKey]; + } + + return ekey; }; From 7a696b1c8aa9182ec46183a92a58b6de89c63608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sat, 17 Jun 2023 14:55:38 +0100 Subject: [PATCH 10/11] feat: update instructions for kwmv2 key import --- .../AndroidADBPullInstruction.tsx} | 30 +++++++++++++------ .../AndroidADBPullInstruction}/adb_dump.ps1 | 4 +-- .../AndroidADBPullInstruction/adb_dump.sh | 2 ++ .../settings/panels/KWMv2/InstructionsPC.tsx | 9 ++++++ .../settings/panels/PanelKWMv2Key.tsx | 24 +++++++++++++-- .../settings/panels/PanelQMCv2Key.tsx | 4 +-- .../settings/panels/QMCv2/adb_dump.sh | 2 -- 7 files changed, 58 insertions(+), 17 deletions(-) rename src/{features/settings/panels/QMCv2/InstructionsAndroid.tsx => components/AndroidADBPullInstruction/AndroidADBPullInstruction.tsx} (80%) rename src/{features/settings/panels/QMCv2 => components/AndroidADBPullInstruction}/adb_dump.ps1 (61%) create mode 100644 src/components/AndroidADBPullInstruction/adb_dump.sh create mode 100644 src/features/settings/panels/KWMv2/InstructionsPC.tsx delete mode 100644 src/features/settings/panels/QMCv2/adb_dump.sh diff --git a/src/features/settings/panels/QMCv2/InstructionsAndroid.tsx b/src/components/AndroidADBPullInstruction/AndroidADBPullInstruction.tsx similarity index 80% rename from src/features/settings/panels/QMCv2/InstructionsAndroid.tsx rename to src/components/AndroidADBPullInstruction/AndroidADBPullInstruction.tsx index 9128444..b489e41 100644 --- a/src/features/settings/panels/QMCv2/InstructionsAndroid.tsx +++ b/src/components/AndroidADBPullInstruction/AndroidADBPullInstruction.tsx @@ -17,10 +17,22 @@ import { ExternalLinkIcon } from '@chakra-ui/icons'; import { Light as SyntaxHighlighter } from 'react-syntax-highlighter'; import hljsStyleGitHub from 'react-syntax-highlighter/dist/esm/styles/hljs/github'; -import PowerShellAdbDumpCommand from './adb_dump.ps1?raw'; -import ShellAdbDumpCommand from './adb_dump.sh?raw'; +import PowerShellAdbDumpCommandTemplate from './adb_dump.ps1?raw'; +import ShellAdbDumpCommandTemplate from './adb_dump.sh?raw'; + +const applyTemplate = (tpl: string, values: Record) => { + return tpl.replace(/\{\{\s*(\w+)\s*\}\}/g, (_, key) => (Object.hasOwn(values, key) ? String(values[key]) : '')); +}; + +export interface AndroidADBPullInstructionProps { + dir: string; + file: string; +} + +export function AndroidADBPullInstruction({ dir, file }: AndroidADBPullInstructionProps) { + const psAdbDumpCommand = applyTemplate(PowerShellAdbDumpCommandTemplate, { dir, file }); + const shAdbDumpCommand = applyTemplate(ShellAdbDumpCommandTemplate, { dir, file }); -export function InstructionsAndroid() { return ( <> @@ -50,12 +62,12 @@ export function InstructionsAndroid() { - 访问 /data/data/com.tencent.qqmusic/databases/ 目录。 + 访问 {dir}/ 目录。 - 将文件 player_process_db 复制到浏览器可访问的目录。 + 将文件 {file} 复制到浏览器可访问的目录。
(例如下载目录)
@@ -99,12 +111,12 @@ export function InstructionsAndroid() { 粘贴执行下述代码。若设备提示「超级用户请求」请允许: - {PowerShellAdbDumpCommand} + {psAdbDumpCommand} - 提交当前目录下的 player_process_db 文件。 + 提交当前目录下的 {file} 文件。 @@ -128,12 +140,12 @@ export function InstructionsAndroid() { 粘贴执行下述代码。若设备提示「超级用户请求」请允许: - {ShellAdbDumpCommand} + {shAdbDumpCommand} - 提交当前目录下的 player_process_db 文件。 + 提交当前目录下的 {file} 文件。 diff --git a/src/features/settings/panels/QMCv2/adb_dump.ps1 b/src/components/AndroidADBPullInstruction/adb_dump.ps1 similarity index 61% rename from src/features/settings/panels/QMCv2/adb_dump.ps1 rename to src/components/AndroidADBPullInstruction/adb_dump.ps1 index f9a4fdf..3f40ac7 100644 --- a/src/features/settings/panels/QMCv2/adb_dump.ps1 +++ b/src/components/AndroidADBPullInstruction/adb_dump.ps1 @@ -1,8 +1,8 @@ try { - $gz_b64 = adb shell su -c "cat '/data/data/com.tencent.qqmusic/databases/player_process_db' | gzip | base64" | Out-String + $gz_b64 = adb shell su -c "cat '{{ dir }}/{{ file }}' | gzip | base64" | Out-String $bStream = New-Object System.IO.MemoryStream(,[System.Convert]::FromBase64String($gz_b64)) $decoded = New-Object System.IO.Compression.GzipStream($bStream, [System.IO.Compression.CompressionMode]::Decompress) - $outFile = New-Object System.IO.FileStream("player_process_db", [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write) + $outFile = New-Object System.IO.FileStream("{{ file }}", [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write) $decoded.CopyTo($outFile) } finally { if ($outFile -ne $null) { $outFile.Dispose() } diff --git a/src/components/AndroidADBPullInstruction/adb_dump.sh b/src/components/AndroidADBPullInstruction/adb_dump.sh new file mode 100644 index 0000000..38947c8 --- /dev/null +++ b/src/components/AndroidADBPullInstruction/adb_dump.sh @@ -0,0 +1,2 @@ +sh adb shell su -c "cat '{{ dir }}/{{ file }}' | gzip | base64" \ + | base64 -d | gzip -d '{{ file }}' diff --git a/src/features/settings/panels/KWMv2/InstructionsPC.tsx b/src/features/settings/panels/KWMv2/InstructionsPC.tsx new file mode 100644 index 0000000..86d0a07 --- /dev/null +++ b/src/features/settings/panels/KWMv2/InstructionsPC.tsx @@ -0,0 +1,9 @@ +import { Text } from '@chakra-ui/react'; + +export function InstructionsPC() { + return ( + <> + 使用 Windows 客户端下载的文件不需要导入密钥。 + + ); +} diff --git a/src/features/settings/panels/PanelKWMv2Key.tsx b/src/features/settings/panels/PanelKWMv2Key.tsx index b656066..9c41ac4 100644 --- a/src/features/settings/panels/PanelKWMv2Key.tsx +++ b/src/features/settings/panels/PanelKWMv2Key.tsx @@ -14,6 +14,10 @@ import { MenuDivider, MenuItem, MenuList, + Tab, + TabList, + TabPanel, + TabPanels, Text, useToast, } from '@chakra-ui/react'; @@ -28,6 +32,8 @@ import { kwm2AddKey, kwm2ClearKeys, kwm2ImportKeys } from '../settingsSlice'; import { selectStagingKWMv2Keys } from '../settingsSelector'; import { KWMv2EKeyItem } from './KWMv2/KWMv2EKeyItem'; import type { StagingKWMv2Key } from '../keyFormats'; +import { InstructionsPC } from './KWMv2/InstructionsPC'; +import { AndroidADBPullInstruction } from '~/components/AndroidADBPullInstruction/AndroidADBPullInstruction'; export function PanelKWMv2Key() { const toast = useToast(); @@ -39,7 +45,7 @@ export function PanelKWMv2Key() { const clearAll = () => dispatch(kwm2ClearKeys()); const handleSecretImport = async (file: File) => { let keys: Omit[] | null = null; - if (/cn\.kuwo\.player\.mmkv\.defaultconfig/i.test(file.name)) { + if (/cn\.kuwo\.player\.mmkv/i.test(file.name)) { const fileBuffer = await file.arrayBuffer(); keys = MMKVParser.parseKuwoEKey(new DataView(fileBuffer)); } @@ -108,7 +114,21 @@ export function PanelKWMv2Key() { onClose={() => setShowImportModal(false)} onImport={handleSecretImport} > - 文档缺失 + + 安卓 + Windows + + + + + + + + + ); diff --git a/src/features/settings/panels/PanelQMCv2Key.tsx b/src/features/settings/panels/PanelQMCv2Key.tsx index e18709d..2d9d67a 100644 --- a/src/features/settings/panels/PanelQMCv2Key.tsx +++ b/src/features/settings/panels/PanelQMCv2Key.tsx @@ -34,10 +34,10 @@ import { StagingQMCv2Key } from '../keyFormats'; import { DatabaseKeyExtractor } from '~/util/DatabaseKeyExtractor'; import { MMKVParser } from '~/util/MMKVParser'; import { getFileName } from '~/util/pathHelper'; -import { InstructionsAndroid } from './QMCv2/InstructionsAndroid'; import { InstructionsIOS } from './QMCv2/InstructionsIOS'; import { InstructionsMac } from './QMCv2/InstructionsMac'; import { InstructionsPC } from './QMCv2/InstructionsPC'; +import { AndroidADBPullInstruction } from '~/components/AndroidADBPullInstruction/AndroidADBPullInstruction'; export function PanelQMCv2Key() { const toast = useToast(); @@ -172,7 +172,7 @@ export function PanelQMCv2Key() { - + diff --git a/src/features/settings/panels/QMCv2/adb_dump.sh b/src/features/settings/panels/QMCv2/adb_dump.sh deleted file mode 100644 index 42fa8ad..0000000 --- a/src/features/settings/panels/QMCv2/adb_dump.sh +++ /dev/null @@ -1,2 +0,0 @@ -sh adb shell su -c "cat '/data/data/com.tencent.qqmusic/databases/player_process_db' | gzip | base64" \ - | base64 -d | gzip -d player_process_db From 368410374a6e1e50d8000b2a5233afdcb410ce8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sat, 17 Jun 2023 14:57:04 +0100 Subject: [PATCH 11/11] 0.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e0fbfdb..b0685c9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "um-react", "private": true, - "version": "0.1.0", + "version": "0.2.0", "type": "module", "scripts": { "start": "vite",