diff --git a/.dockerignore b/.dockerignore index 2e8188d..d3d0013 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,6 +2,7 @@ node_modules dist package-lock.json pnpm-lock.yaml +.pnpm-debug.log .parcel-cache .git src/server/core/*.exe diff --git a/.gitignore b/.gitignore index ca249d4..6091f8e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ dist package-lock.json pnpm-lock.yaml +.pnpm-debug.log node_modules src/server/core/*.exe src/server/core/yt-dlp diff --git a/README.md b/README.md index 574cb29..220061a 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,13 @@ # yt-dlp Web UI A not so terrible web ui for yt-dlp. -Created for the only purpose of *consume* videos from my server/nas. +Created for the only purpose of *consuming* videos from my server/nas. I will eventually make this better as soon as I can. Not in the immediate. Changelog: ``` +03/02/22: i18n enabled! I need help with the traductions :/ + 27/01/22: Multidownload implemented! 26/01/22: Multiple downloads are being implemented. Maybe by next release they will be there. diff --git a/frontend/src/App.css b/frontend/src/App.css old mode 100644 new mode 100755 index 080dfd9..018c4b6 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -13,8 +13,10 @@ } .settings { - text-decoration: underline; cursor: pointer; + padding: 3px; + border: 1px solid var(--border); + border-radius: 5px; } .form-control{ diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx old mode 100644 new mode 100755 index 9515fb1..707d6d4 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -9,12 +9,13 @@ import { Button, ButtonGroup, } from "react-bootstrap"; -import { X, HddFill } from "react-bootstrap-icons"; +import { X, HddFill, GearFill, Translate } from "react-bootstrap-icons"; import { buildMessage, updateInStateMap, validateDomain, validateIP } from "./utils"; import { IDLInfo, IDLInfoBase, IMessage } from "./interfaces"; import { MessageToast } from "./components/MessageToast"; import { StackableResult } from "./components/StackableResult"; import { CliArguments } from "./classes"; +import { I18nBuilder } from "./i18n"; import './App.css'; const socket = io(`http://${localStorage.getItem('server-addr') || 'localhost'}:3022`) @@ -31,8 +32,11 @@ export function App() { const [invalidIP, setInvalidIP] = useState(false); const [updatedBin, setUpdatedBin] = useState(false); const [showSettings, setShowSettings] = useState(false); + const [showLanguages, setShowLanguages] = useState(false); const [freeDiskSpace, setFreeDiskSpace] = useState(''); + const [darkMode, setDarkMode] = useState(localStorage.getItem('theme') === 'dark'); + const [language, setLanguage] = useState(localStorage.getItem('language') || 'english'); const xaInput = useRef(null); const mtInput = useRef(null); @@ -47,6 +51,8 @@ export function App() { cliArgs.fromString(localStorage.getItem('cliArgs')) + const i18n = new I18nBuilder(language); + /* -------------------- Effects -------------------- */ /* WebSocket connect event handler*/ @@ -114,6 +120,11 @@ export function App() { }) }, []) + /* Change language */ + useEffect(() => { + i18n.setLanguage(language) + }, [language]) + /* -------------------- component functions -------------------- */ /** @@ -230,6 +241,15 @@ export function App() { } } + /** + * Language toggler handler + */ + const handleLanguageChage = (event: React.ChangeEvent) => { + setLanguage(event.target.value); + setShowLanguages(false); + localStorage.setItem('language', event.target.value); + } + return (
@@ -244,7 +264,7 @@ export function App() { @@ -253,8 +273,8 @@ export function App() {
-
Status
-
Ready
+
{i18n.t('statusTitle')}
+
{i18n.t('statusReady')}
: null @@ -289,8 +309,8 @@ export function App() { } - - + + {' '} @@ -300,18 +320,37 @@ export function App() {
- setShowSettings(!showSettings)}>Settings + setShowSettings(!showSettings)}> + {i18n.t('settingsAnchor')} + {' '} + + + {' '} + setShowLanguages(!showLanguages)}> + + + {showLanguages ? + + : null + }
+ {showSettings ?
-
Server address
+
{i18n.t('serverAddressTitle')}
ws:// - +
- +

{' '} : null } +
- Once you close this page the download will continue in the background. + {i18n.t('bgReminder')}
- {`Connected to ${localStorage.getItem('server-addr') || 'localhost'}`} + <> + {i18n.t('toastConnected')}{localStorage.getItem('server-addr') || 'localhost'} + - Updated yt-dlp binary! + {i18n.t('toastUpdated')} diff --git a/frontend/src/assets/i18n.yaml b/frontend/src/assets/i18n.yaml new file mode 100644 index 0000000..87fb3a3 --- /dev/null +++ b/frontend/src/assets/i18n.yaml @@ -0,0 +1,82 @@ +--- +languages: + english: + urlInput: YouTube or other supported service video URL + statusTitle: Status + statusReady: Ready + startButton: Start + abortAllButton: Abort All + updateBinButton: Update yt-dlp binary + darkThemeButton: Dark theme + lightThemeButton: Light theme + settingsAnchor: Settings + serverAddressTitle: Server address + extractAudioCheckbox: Extract audio + noMTimeCheckbox: Don't set file modification time + bgReminder: Once you close this page the download will continue in the background. + toastConnected: 'Connected to ' + toastUpdated: Updated yt-dlp binary! + italian: + urlInput: URL di YouTube o di qualsiasi altro servizio supportato + statusTitle: Stato + startButton: Inizia + statusReady: Pronto + abortAllButton: Termina tutto + updateBinButton: Aggiorna yt-dlp + darkThemeButton: Tema scuro + lightThemeButton: Tema chiaro + settingsAnchor: Impostazioni + serverAddressTitle: Indirizzo server + extractAudioCheckbox: Estrai l'audio + noMTimeCheckbox: Non impostare la proprietà "Data ultima modifica" + bgReminder: Chiusa questa UI il download continuerà in background. + toastConnected: 'Connesso a ' + toastUpdated: yt-dlp aggiornato con successo! + chinese: + urlInput: 输入网址 + statusTitle: 运行状态 + startButton: 开始 + statusReady: Ready + abortAllButton: 退出 + updateBinButton: yt-dlp 现代化 + darkThemeButton: Dark theme + lightThemeButton: Light theme + settingsAnchor: Settings + serverAddressTitle: Server address + extractAudioCheckbox: Extract audio + noMTimeCheckbox: Don't set file modification time + bgReminder: Once you close this page the download will continue in the background. + toastConnected: 'Connected to ' + toastUpdated: Updated yt-dlp binary! + spanish: + urlInput: YouTube or other supported service video url + statusTitle: Status + startButton: Start + statusReady: Ready + abortAllButton: Abort All + updateBinButton: Update yt-dlp binary + darkThemeButton: Dark theme + lightThemeButton: Light theme + settingsAnchor: Settings + serverAddressTitle: Server address + extractAudioCheckbox: Extract audio + noMTimeCheckbox: Don't set file modification time + bgReminder: Once you close this page the download will continue in the background. + toastConnected: 'Connected to ' + toastUpdated: Updated yt-dlp binary! + russian: + urlInput: YouTube or other supported service video url + statusTitle: Status + startButton: Start + statusReady: Ready + abortAllButton: Abort All + updateBinButton: Update yt-dlp binary + darkThemeButton: Dark theme + lightThemeButton: Light theme + settingsAnchor: Settings + serverAddressTitle: Server address + extractAudioCheckbox: Extract audio + noMTimeCheckbox: Don't set file modification time + bgReminder: Once you close this page the download will continue in the background. + toastConnected: 'Connected to ' + toastUpdated: Updated yt-dlp binary! diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts new file mode 100644 index 0000000..f5cba0e --- /dev/null +++ b/frontend/src/i18n.ts @@ -0,0 +1,28 @@ +// @ts-nocheck +import i18n from "./assets/i18n.yaml"; + +export class I18nBuilder { + private language: string; + private textMap = i18n.languages; + + constructor(language: string) { + this.language = language; + } + + getLanguage(): string { + return this.language; + } + + setLanguage(language: string): void { + this.language = language; + } + + t(key: string): string { + const map = this.textMap[this.language] + if (map) { + const translation = map[key]; + return translation ? translation : 'caption not defined'; + } + return 'caption not defined'; + } +} \ No newline at end of file diff --git a/package.json b/package.json index d585019..7f5a2c8 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "uuid": "^8.3.2" }, "devDependencies": { + "@parcel/transformer-yaml": "^2.2.1", "parcel": "^2.0.1", "typescript": "^4.5.2" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8dcb2c4..89b56e2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2,6 +2,7 @@ lockfileVersion: 5.3 specifiers: '@koa/cors': ^3.1.0 + '@parcel/transformer-yaml': ^2.2.1 '@types/better-sqlite3': ^7.4.2 '@types/koa': ^2.13.4 '@types/koa-static': ^4.0.2 @@ -51,6 +52,7 @@ dependencies: uuid: 8.3.2 devDependencies: + '@parcel/transformer-yaml': 2.2.1 parcel: 2.2.1 typescript: 4.5.5 @@ -335,17 +337,27 @@ packages: lodash.clone: 4.5.0 dev: true - /@parcel/bundler-default/2.2.1_@parcel+core@2.2.1: + /@parcel/bundler-default/2.2.1: resolution: {integrity: sha512-s2MsShmp7ww4Vh6Qn7uGQII776j0F6OTO6snJ5w9sdFqub/NdpjvwBEsRo+UDryq5oKsrQYQtNiDdPuOZ+M9bQ==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: '@parcel/diagnostic': 2.2.1 '@parcel/hash': 2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/utils': 2.2.1 nullthrows: 1.1.1 - transitivePeerDependencies: - - '@parcel/core' + dev: true + + /@parcel/cache/2.2.1: + resolution: {integrity: sha512-sO4+sKErJFfAhAsOiG7HUid0XgtfwoXbc6TT2Dvpjbd/hCGoUWZNfvs8l5cq7/Ip6pgUuXzPV4Pz7HX+cshTsw==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@parcel/core': ^2.2.1 + dependencies: + '@parcel/fs': 2.2.1 + '@parcel/logger': 2.2.1 + '@parcel/utils': 2.2.1 + lmdb: 2.1.7 dev: true /@parcel/cache/2.2.1_@parcel+core@2.2.1: @@ -371,13 +383,11 @@ packages: string-width: 4.2.3 dev: true - /@parcel/compressor-raw/2.2.1_@parcel+core@2.2.1: + /@parcel/compressor-raw/2.2.1: resolution: {integrity: sha512-Z2tOOaVg/7gRvQbh/mHscuAoWoSSPThIgJBNtGG7JPH4u5sDmXW6CkbOc81VBYQd3uz8btNdNvBFEHG0+jpK+Q==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 - transitivePeerDependencies: - - '@parcel/core' + '@parcel/plugin': 2.2.1 dev: true /@parcel/config-default/2.2.1_@parcel+core@2.2.1: @@ -385,37 +395,37 @@ packages: peerDependencies: '@parcel/core': ^2.2.1 dependencies: - '@parcel/bundler-default': 2.2.1_@parcel+core@2.2.1 - '@parcel/compressor-raw': 2.2.1_@parcel+core@2.2.1 + '@parcel/bundler-default': 2.2.1 + '@parcel/compressor-raw': 2.2.1 '@parcel/core': 2.2.1 - '@parcel/namer-default': 2.2.1_@parcel+core@2.2.1 - '@parcel/optimizer-cssnano': 2.2.1_@parcel+core@2.2.1 - '@parcel/optimizer-htmlnano': 2.2.1_@parcel+core@2.2.1 + '@parcel/namer-default': 2.2.1 + '@parcel/optimizer-cssnano': 2.2.1 + '@parcel/optimizer-htmlnano': 2.2.1 '@parcel/optimizer-image': 2.2.1_@parcel+core@2.2.1 - '@parcel/optimizer-svgo': 2.2.1_@parcel+core@2.2.1 - '@parcel/optimizer-terser': 2.2.1_@parcel+core@2.2.1 - '@parcel/packager-css': 2.2.1_@parcel+core@2.2.1 - '@parcel/packager-html': 2.2.1_@parcel+core@2.2.1 - '@parcel/packager-js': 2.2.1_@parcel+core@2.2.1 - '@parcel/packager-raw': 2.2.1_@parcel+core@2.2.1 - '@parcel/packager-svg': 2.2.1_@parcel+core@2.2.1 - '@parcel/reporter-dev-server': 2.2.1_@parcel+core@2.2.1 - '@parcel/resolver-default': 2.2.1_@parcel+core@2.2.1 - '@parcel/runtime-browser-hmr': 2.2.1_@parcel+core@2.2.1 - '@parcel/runtime-js': 2.2.1_@parcel+core@2.2.1 - '@parcel/runtime-react-refresh': 2.2.1_@parcel+core@2.2.1 - '@parcel/runtime-service-worker': 2.2.1_@parcel+core@2.2.1 - '@parcel/transformer-babel': 2.2.1_@parcel+core@2.2.1 - '@parcel/transformer-css': 2.2.1_@parcel+core@2.2.1 - '@parcel/transformer-html': 2.2.1_@parcel+core@2.2.1 + '@parcel/optimizer-svgo': 2.2.1 + '@parcel/optimizer-terser': 2.2.1 + '@parcel/packager-css': 2.2.1 + '@parcel/packager-html': 2.2.1 + '@parcel/packager-js': 2.2.1 + '@parcel/packager-raw': 2.2.1 + '@parcel/packager-svg': 2.2.1 + '@parcel/reporter-dev-server': 2.2.1 + '@parcel/resolver-default': 2.2.1 + '@parcel/runtime-browser-hmr': 2.2.1 + '@parcel/runtime-js': 2.2.1 + '@parcel/runtime-react-refresh': 2.2.1 + '@parcel/runtime-service-worker': 2.2.1 + '@parcel/transformer-babel': 2.2.1 + '@parcel/transformer-css': 2.2.1 + '@parcel/transformer-html': 2.2.1 '@parcel/transformer-image': 2.2.1_@parcel+core@2.2.1 '@parcel/transformer-js': 2.2.1_@parcel+core@2.2.1 - '@parcel/transformer-json': 2.2.1_@parcel+core@2.2.1 - '@parcel/transformer-postcss': 2.2.1_@parcel+core@2.2.1 - '@parcel/transformer-posthtml': 2.2.1_@parcel+core@2.2.1 - '@parcel/transformer-raw': 2.2.1_@parcel+core@2.2.1 - '@parcel/transformer-react-refresh-wrap': 2.2.1_@parcel+core@2.2.1 - '@parcel/transformer-svg': 2.2.1_@parcel+core@2.2.1 + '@parcel/transformer-json': 2.2.1 + '@parcel/transformer-postcss': 2.2.1 + '@parcel/transformer-posthtml': 2.2.1 + '@parcel/transformer-raw': 2.2.1 + '@parcel/transformer-react-refresh-wrap': 2.2.1 + '@parcel/transformer-svg': 2.2.1 transitivePeerDependencies: - '@types/express' - acorn @@ -444,9 +454,9 @@ packages: '@parcel/hash': 2.2.1 '@parcel/logger': 2.2.1 '@parcel/package-manager': 2.2.1_@parcel+core@2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/source-map': 2.0.1 - '@parcel/types': 2.2.1_@parcel+core@2.2.1 + '@parcel/types': 2.2.1 '@parcel/utils': 2.2.1 '@parcel/workers': 2.2.1_@parcel+core@2.2.1 abortcontroller-polyfill: 1.7.3 @@ -492,6 +502,26 @@ packages: readable-stream: 2.3.7 dev: true + /@parcel/fs/2.2.1: + resolution: {integrity: sha512-SuSM8SoatLM2+eb4N85oTW32U38rKaMcgf6OIqdlBTFQQdyFcKz1nRHHTb7egvVKdp8gTXkLp0S952t3kJT+mg==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@parcel/core': ^2.2.1 + dependencies: + '@parcel/fs-search': 2.2.1 + '@parcel/fs-write-stream-atomic': 2.2.1 + '@parcel/types': 2.2.1 + '@parcel/utils': 2.2.1 + '@parcel/watcher': 2.0.5 + '@parcel/workers': 2.2.1 + graceful-fs: 4.2.9 + mkdirp: 0.5.5 + ncp: 2.0.0 + nullthrows: 1.1.1 + rimraf: 3.0.2 + utility-types: 3.10.0 + dev: true + /@parcel/fs/2.2.1_@parcel+core@2.2.1: resolution: {integrity: sha512-SuSM8SoatLM2+eb4N85oTW32U38rKaMcgf6OIqdlBTFQQdyFcKz1nRHHTb7egvVKdp8gTXkLp0S952t3kJT+mg==} engines: {node: '>= 12.0.0'} @@ -501,7 +531,7 @@ packages: '@parcel/core': 2.2.1 '@parcel/fs-search': 2.2.1 '@parcel/fs-write-stream-atomic': 2.2.1 - '@parcel/types': 2.2.1_@parcel+core@2.2.1 + '@parcel/types': 2.2.1 '@parcel/utils': 2.2.1 '@parcel/watcher': 2.0.5 '@parcel/workers': 2.2.1_@parcel+core@2.2.1 @@ -544,15 +574,13 @@ packages: chalk: 4.1.2 dev: true - /@parcel/namer-default/2.2.1_@parcel+core@2.2.1: + /@parcel/namer-default/2.2.1: resolution: {integrity: sha512-uhQwAJyWADEKUVAPZV8TKlUUmKjeKycMatf554u7PeKWSw4H6yUd1z6Ta9IXIx5qi2u3RMeDct5psjh4fpcyEw==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: '@parcel/diagnostic': 2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 nullthrows: 1.1.1 - transitivePeerDependencies: - - '@parcel/core' dev: true /@parcel/node-libs-browser/2.2.1: @@ -594,29 +622,26 @@ packages: nullthrows: 1.1.1 dev: true - /@parcel/optimizer-cssnano/2.2.1_@parcel+core@2.2.1: + /@parcel/optimizer-cssnano/2.2.1: resolution: {integrity: sha512-sjQNL4x3oBF2BCsL1SMKxNoNGqnNT1CBZPl+6F6jVxiaj6KHPzZOkeEL7Ioow5Jb6pAe79JKWXyHQBFhyLiHOw==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/source-map': 2.0.1 cssnano: 5.0.16_postcss@8.4.5 postcss: 8.4.5 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/optimizer-htmlnano/2.2.1_@parcel+core@2.2.1: + /@parcel/optimizer-htmlnano/2.2.1: resolution: {integrity: sha512-NIz66Rj2JYxmDWKdM0CNxfPTY45mAhrW8zLuJGcGJSqNq8srj1TKzdHl+HukTHxRF5D0jOv+xLOgJmdNfObHNg==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 htmlnano: 2.0.0_svgo@2.8.0 nullthrows: 1.1.1 posthtml: 0.16.5 svgo: 2.8.0 transitivePeerDependencies: - - '@parcel/core' - cssnano - postcss - purgecss @@ -631,7 +656,7 @@ packages: engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: '@parcel/diagnostic': 2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/utils': 2.2.1 '@parcel/workers': 2.2.1_@parcel+core@2.2.1 detect-libc: 1.0.3 @@ -639,33 +664,49 @@ packages: - '@parcel/core' dev: true - /@parcel/optimizer-svgo/2.2.1_@parcel+core@2.2.1: + /@parcel/optimizer-svgo/2.2.1: resolution: {integrity: sha512-+wUe30x1xYP4NYiyMTinY2K3vmbxf6K8dBFoEv5lb+ODFqMsE7Kr0DNyVR3aH0FSKxa3ii4nfLA/eAvaG97qmQ==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: '@parcel/diagnostic': 2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/utils': 2.2.1 svgo: 2.8.0 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/optimizer-terser/2.2.1_@parcel+core@2.2.1: + /@parcel/optimizer-terser/2.2.1: resolution: {integrity: sha512-mP1WIxEB2GlmxRODOx1vpii7QceufYojoivchr6ifn3abE/UCz89TUyWGyGgzVby4YF2kSlQ6gDrcKl+wnOGtQ==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: '@parcel/diagnostic': 2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/source-map': 2.0.1 '@parcel/utils': 2.2.1 nullthrows: 1.1.1 terser: 5.10.0 transitivePeerDependencies: - - '@parcel/core' - acorn dev: true + /@parcel/package-manager/2.2.1: + resolution: {integrity: sha512-BpiRC8TM/R7OQVs8bP9+8aIe0FVMQHSNccVUMRb0kUtNt1GRVHoDu3lRE4P28LLw1nHhJ3YnMV/k1ZVwAOalLA==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@parcel/core': ^2.2.1 + dependencies: + '@parcel/diagnostic': 2.2.1 + '@parcel/fs': 2.2.1 + '@parcel/logger': 2.2.1 + '@parcel/types': 2.2.1 + '@parcel/utils': 2.2.1 + '@parcel/workers': 2.2.1 + command-exists: 1.2.9 + cross-spawn: 6.0.5 + nullthrows: 1.1.1 + semver: 5.7.1 + split2: 3.2.2 + dev: true + /@parcel/package-manager/2.2.1_@parcel+core@2.2.1: resolution: {integrity: sha512-BpiRC8TM/R7OQVs8bP9+8aIe0FVMQHSNccVUMRb0kUtNt1GRVHoDu3lRE4P28LLw1nHhJ3YnMV/k1ZVwAOalLA==} engines: {node: '>= 12.0.0'} @@ -676,7 +717,7 @@ packages: '@parcel/diagnostic': 2.2.1 '@parcel/fs': 2.2.1_@parcel+core@2.2.1 '@parcel/logger': 2.2.1 - '@parcel/types': 2.2.1_@parcel+core@2.2.1 + '@parcel/types': 2.2.1 '@parcel/utils': 2.2.1 '@parcel/workers': 2.2.1_@parcel+core@2.2.1 command-exists: 1.2.9 @@ -686,83 +727,73 @@ packages: split2: 3.2.2 dev: true - /@parcel/packager-css/2.2.1_@parcel+core@2.2.1: + /@parcel/packager-css/2.2.1: resolution: {integrity: sha512-nTqj94jWenjw3O3lJc+IFSMx/3oQ/a4ZYXSU8UNfsvDdFGQQ/7Qeo7c33t9UXFm3PGXpSFaoBK1+Y3ffS116YQ==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/source-map': 2.0.1 '@parcel/utils': 2.2.1 nullthrows: 1.1.1 postcss: 8.4.5 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/packager-html/2.2.1_@parcel+core@2.2.1: + /@parcel/packager-html/2.2.1: resolution: {integrity: sha512-A67CDWX8zv5YtzetPfg2R5l4/fmADWx2SeAxJWnW2t52ysAlxpwPC53vu1U5T54jaf2NbxfQPpOBem1P7Vk9Vw==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 - '@parcel/types': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 + '@parcel/types': 2.2.1 '@parcel/utils': 2.2.1 nullthrows: 1.1.1 posthtml: 0.16.5 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/packager-js/2.2.1_@parcel+core@2.2.1: + /@parcel/packager-js/2.2.1: resolution: {integrity: sha512-jTh+72Pix0H0rrMFGj0Q+20pWANoFdk0byL9wh3ayIfaBM/7N/vi51+yjek3p2cQjuaxp5ISQDQlW9t4zVVwgw==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: '@parcel/diagnostic': 2.2.1 '@parcel/hash': 2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/source-map': 2.0.1 '@parcel/utils': 2.2.1 globals: 13.12.0 nullthrows: 1.1.1 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/packager-raw/2.2.1_@parcel+core@2.2.1: + /@parcel/packager-raw/2.2.1: resolution: {integrity: sha512-/53i0XRF9okJKyq1uCvOiD8iBCaaBy9WWF3H3VdC1ZCyl45Ku5zMoN4XsVktGKgiFAeDeBA7Tn94gIO/f8g7+g==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 - transitivePeerDependencies: - - '@parcel/core' + '@parcel/plugin': 2.2.1 dev: true - /@parcel/packager-svg/2.2.1_@parcel+core@2.2.1: + /@parcel/packager-svg/2.2.1: resolution: {integrity: sha512-tdqzReIoWXw0r3XMJGInAFZxo64kSHjG+8s2ZHm/uSXTjiH3uebfROs/KjcwMVjqdFkhnE3htf/VBpzk0DS/uQ==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 - '@parcel/types': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 + '@parcel/types': 2.2.1 '@parcel/utils': 2.2.1 posthtml: 0.16.5 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/plugin/2.2.1_@parcel+core@2.2.1: + /@parcel/plugin/2.2.1: resolution: {integrity: sha512-UrmAmtCO+Ma78ojhG9LSB5bYSkcjTwyPexfcpgCsZiLrv4cXDjKe7gEYfxWbrJw4ahkUhfgRsrTfUzD/TPYxiA==} engines: {node: '>= 12.0.0'} dependencies: - '@parcel/types': 2.2.1_@parcel+core@2.2.1 + '@parcel/types': 2.2.1 transitivePeerDependencies: - '@parcel/core' dev: true - /@parcel/reporter-cli/2.2.1_@parcel+core@2.2.1: + /@parcel/reporter-cli/2.2.1: resolution: {integrity: sha512-NhUH68M9kIDC/qTZqDIIQ/itEI94wn8hwEbNZTeEhIP44I2vYTPxQ7Ta+82mj5t5te+7Rxle11zic0XsOLuGVQ==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 - '@parcel/types': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 + '@parcel/types': 2.2.1 '@parcel/utils': 2.2.1 chalk: 4.1.2 filesize: 6.4.0 @@ -772,15 +803,13 @@ packages: strip-ansi: 6.0.1 term-size: 2.2.1 wrap-ansi: 7.0.0 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/reporter-dev-server/2.2.1_@parcel+core@2.2.1: + /@parcel/reporter-dev-server/2.2.1: resolution: {integrity: sha512-rSRH1nFRS6nEN3Wma3oejcu1jzvbu9/hXgMKOp3TJax9jJ3nJdYPEeIA/jbJTqU1pf6hWyG3wvPOiXW8nhCGAg==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/utils': 2.2.1 connect: 3.7.0 ejs: 3.1.6 @@ -789,64 +818,53 @@ packages: serve-handler: 6.1.3 ws: 7.5.6 transitivePeerDependencies: - - '@parcel/core' - '@types/express' - bufferutil - debug - utf-8-validate dev: true - /@parcel/resolver-default/2.2.1_@parcel+core@2.2.1: + /@parcel/resolver-default/2.2.1: resolution: {integrity: sha512-+3sHzfiugwwzsc5FNy0ZalWyJrtV68GVQmjAKmZJCMb4k/6TIBQgzggQqhRuztowsiJadL8JAM8djxYVlYAkqg==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: '@parcel/node-resolver-core': 2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 - transitivePeerDependencies: - - '@parcel/core' + '@parcel/plugin': 2.2.1 dev: true - /@parcel/runtime-browser-hmr/2.2.1_@parcel+core@2.2.1: + /@parcel/runtime-browser-hmr/2.2.1: resolution: {integrity: sha512-/jqka4kOlzUwb2ygzM1LtAVq/rxGaFarcR6YIchIAbp3DUSV/1nelo5swCw8FirN9O7qRBdgkIuW+0JAa+Dbzg==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/utils': 2.2.1 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/runtime-js/2.2.1_@parcel+core@2.2.1: + /@parcel/runtime-js/2.2.1: resolution: {integrity: sha512-yLQpSMNcxG5EoKbLlRS1n+5KXnJ2Mz7yE2hpVez9lhzDiIFAPSxiCZQ1dWJ4o7urOKMckKYRheW4/x5Nm4ErhA==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/utils': 2.2.1 nullthrows: 1.1.1 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/runtime-react-refresh/2.2.1_@parcel+core@2.2.1: + /@parcel/runtime-react-refresh/2.2.1: resolution: {integrity: sha512-TvZqri/xBYV3KlsnxPy/NzxoCioUQlIkQjp6y9JdwGq8ez5B39e4ntwFoWT3hRTRhPBtwa1Tfoc3JRaCRGBFXg==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/utils': 2.2.1 react-refresh: 0.9.0 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/runtime-service-worker/2.2.1_@parcel+core@2.2.1: + /@parcel/runtime-service-worker/2.2.1: resolution: {integrity: sha512-IvTXUJKpgmy7ba8Z2r/rzvpsWvZPOtzb0oWLk5qNV3YND5PS7Cfu0Pdr7y2y9NnBepdzb4u88tqSDhRoyp2ndw==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/utils': 2.2.1 nullthrows: 1.1.1 - transitivePeerDependencies: - - '@parcel/core' dev: true /@parcel/source-map/2.0.1: @@ -854,7 +872,7 @@ packages: engines: {node: ^12.18.3 || >=14} dev: true - /@parcel/transformer-babel/2.2.1_@parcel+core@2.2.1: + /@parcel/transformer-babel/2.2.1: resolution: {integrity: sha512-eNQTmnsiY2ycuGgr3tu5BfR6rz9WGhb6psz+cZkIbfZp0xaJaovTftjT5jR4clsDO/+dX5cM8KOUuJm5MYXRjg==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: @@ -865,7 +883,7 @@ packages: '@babel/traverse': 7.16.10 '@parcel/babel-ast-utils': 2.2.1 '@parcel/diagnostic': 2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/source-map': 2.0.1 '@parcel/utils': 2.2.1 browserslist: 4.19.1 @@ -874,16 +892,15 @@ packages: nullthrows: 1.1.1 semver: 5.7.1 transitivePeerDependencies: - - '@parcel/core' - supports-color dev: true - /@parcel/transformer-css/2.2.1_@parcel+core@2.2.1: + /@parcel/transformer-css/2.2.1: resolution: {integrity: sha512-fytU0mzQuddVAAkRDJBuE6x0JpVx5NYC2s4eDJqErOORJ/dwpngEz+TjjJGU2kUH9r74QypTcMb6J5z8WpoV/g==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: '@parcel/hash': 2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/source-map': 2.0.1 '@parcel/utils': 2.2.1 nullthrows: 1.1.1 @@ -891,31 +908,27 @@ packages: postcss-modules: 4.3.0_postcss@8.4.5 postcss-value-parser: 4.2.0 semver: 5.7.1 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/transformer-html/2.2.1_@parcel+core@2.2.1: + /@parcel/transformer-html/2.2.1: resolution: {integrity: sha512-awKgFd+a1oFKlO3ipLGHaiXUTx+6/KBLAdvidmtxLRcq5PsLA2eyZ6BZ5TsWJ+eP4jq0mtB+KxrXiWkPQ73Y0Q==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: '@parcel/diagnostic': 2.2.1 '@parcel/hash': 2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 nullthrows: 1.1.1 posthtml: 0.16.5 posthtml-parser: 0.10.2 posthtml-render: 3.0.0 semver: 5.7.1 - transitivePeerDependencies: - - '@parcel/core' dev: true /@parcel/transformer-image/2.2.1_@parcel+core@2.2.1: resolution: {integrity: sha512-MirsSBI2JE5VLrYc9XKbOQKcxPdcpSTDqTLjcaUv5dkjkiXeRvLbA5OsDwrWwnyqKFvXgsJWrQ3tVc9Zql7gmg==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/workers': 2.2.1_@parcel+core@2.2.1 nullthrows: 1.1.1 transitivePeerDependencies: @@ -927,7 +940,7 @@ packages: engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: '@parcel/diagnostic': 2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/source-map': 2.0.1 '@parcel/utils': 2.2.1 '@parcel/workers': 2.2.1_@parcel+core@2.2.1 @@ -942,22 +955,20 @@ packages: - '@parcel/core' dev: true - /@parcel/transformer-json/2.2.1_@parcel+core@2.2.1: + /@parcel/transformer-json/2.2.1: resolution: {integrity: sha512-ghFatxa8RABmp1J8k0Tn9sIpCVJaUtpzv/qA1Way5vK05wLL8kKU/P2ZCoNtgih2ru3MhM8vv5KIN4R3cAeSHg==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 json5: 2.2.0 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/transformer-postcss/2.2.1_@parcel+core@2.2.1: + /@parcel/transformer-postcss/2.2.1: resolution: {integrity: sha512-x5ABi/xv6scNcN9O+hOAk53KUtLOH/cqzQgw7ZXgrcK/BW0PAxzCuIfOjg0BlM32kmk5NcWu4scHCZPq7us9Zw==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: '@parcel/hash': 2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/utils': 2.2.1 clone: 2.1.2 nullthrows: 1.1.1 @@ -965,57 +976,58 @@ packages: postcss-value-parser: 4.2.0 semver: 5.7.1 transitivePeerDependencies: - - '@parcel/core' - postcss dev: true - /@parcel/transformer-posthtml/2.2.1_@parcel+core@2.2.1: + /@parcel/transformer-posthtml/2.2.1: resolution: {integrity: sha512-59QKoQmImyYGFwfnbrsyBwxIhtpuAu1q6btp6OkThaTUgJvv24eKzcftMORAGxeSBP2CtKtkIlhcIkA8L8cfPw==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/utils': 2.2.1 nullthrows: 1.1.1 posthtml: 0.16.5 posthtml-parser: 0.10.2 posthtml-render: 3.0.0 semver: 5.7.1 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/transformer-raw/2.2.1_@parcel+core@2.2.1: + /@parcel/transformer-raw/2.2.1: resolution: {integrity: sha512-8fC8x31QzwJjbutuIHscb/MlxORXqZJNowQlWfFUHS9lmDNz0f23HnUHwApONA8E9GV/Bn5WzfdVL4tolvcK2w==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 - transitivePeerDependencies: - - '@parcel/core' + '@parcel/plugin': 2.2.1 dev: true - /@parcel/transformer-react-refresh-wrap/2.2.1_@parcel+core@2.2.1: + /@parcel/transformer-react-refresh-wrap/2.2.1: resolution: {integrity: sha512-6V08fevCTUTohx2li4PavJD3YkrcX5D18l3PLBHW9okSQi392NTb1Mru966sBdc9A8H0B6RLD0RjvWE1K6PbOQ==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 '@parcel/utils': 2.2.1 react-refresh: 0.9.0 - transitivePeerDependencies: - - '@parcel/core' dev: true - /@parcel/transformer-svg/2.2.1_@parcel+core@2.2.1: + /@parcel/transformer-svg/2.2.1: resolution: {integrity: sha512-I9cyagYxe+t06bodE1PcxHVPJb1SFutpDA3+ZGMdE6G/5c7OqsnbaA0bgZSTdwDPZomXNQ4++LY5A1QEIFT6Xw==} engines: {node: '>= 12.0.0', parcel: ^2.2.1} dependencies: '@parcel/diagnostic': 2.2.1 '@parcel/hash': 2.2.1 - '@parcel/plugin': 2.2.1_@parcel+core@2.2.1 + '@parcel/plugin': 2.2.1 nullthrows: 1.1.1 posthtml: 0.16.5 posthtml-parser: 0.10.2 posthtml-render: 3.0.0 semver: 5.7.1 + dev: true + + /@parcel/transformer-yaml/2.2.1: + resolution: {integrity: sha512-c88gF1Ek+NUBZ4ACn0bTCooxlnBD/Ch/RCHdqe1rY0I9N1LY6V7D5QYbBJFyNJXwwjHX7qUAqblF3xXULJ/mBg==} + engines: {node: '>= 12.0.0', parcel: ^2.2.1} + dependencies: + '@parcel/plugin': 2.2.1 + js-yaml: 3.14.1 transitivePeerDependencies: - '@parcel/core' dev: true @@ -1023,24 +1035,12 @@ packages: /@parcel/types/2.2.1: resolution: {integrity: sha512-h25EMpnypXHJ05Gx2WxGpRbokgCdmro98AlDbQ39XkddBkjUSodj8+efQWiDxSB/IPS1kPf1drBtS0bI0zCeXA==} dependencies: - '@parcel/cache': 2.2.1_@parcel+core@2.2.1 + '@parcel/cache': 2.2.1 '@parcel/diagnostic': 2.2.1 - '@parcel/fs': 2.2.1_@parcel+core@2.2.1 - '@parcel/package-manager': 2.2.1_@parcel+core@2.2.1 + '@parcel/fs': 2.2.1 + '@parcel/package-manager': 2.2.1 '@parcel/source-map': 2.0.1 - '@parcel/workers': 2.2.1_@parcel+core@2.2.1 - utility-types: 3.10.0 - dev: true - - /@parcel/types/2.2.1_@parcel+core@2.2.1: - resolution: {integrity: sha512-h25EMpnypXHJ05Gx2WxGpRbokgCdmro98AlDbQ39XkddBkjUSodj8+efQWiDxSB/IPS1kPf1drBtS0bI0zCeXA==} - dependencies: - '@parcel/cache': 2.2.1_@parcel+core@2.2.1 - '@parcel/diagnostic': 2.2.1 - '@parcel/fs': 2.2.1_@parcel+core@2.2.1 - '@parcel/package-manager': 2.2.1_@parcel+core@2.2.1 - '@parcel/source-map': 2.0.1 - '@parcel/workers': 2.2.1_@parcel+core@2.2.1 + '@parcel/workers': 2.2.1 utility-types: 3.10.0 transitivePeerDependencies: - '@parcel/core' @@ -1082,6 +1082,20 @@ packages: node-gyp-build: 4.3.0 dev: true + /@parcel/workers/2.2.1: + resolution: {integrity: sha512-ham7/qFYSOvvUUMcRACH/HJc3W7Ng/YLWt23kvXIniA4d9bqGoNKl0oCTiGQzDZ2emx1SmaEN52zG6cJ+xh/lQ==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@parcel/core': ^2.2.1 + dependencies: + '@parcel/diagnostic': 2.2.1 + '@parcel/logger': 2.2.1 + '@parcel/types': 2.2.1 + '@parcel/utils': 2.2.1 + chrome-trace-event: 1.0.3 + nullthrows: 1.1.1 + dev: true + /@parcel/workers/2.2.1_@parcel+core@2.2.1: resolution: {integrity: sha512-ham7/qFYSOvvUUMcRACH/HJc3W7Ng/YLWt23kvXIniA4d9bqGoNKl0oCTiGQzDZ2emx1SmaEN52zG6cJ+xh/lQ==} engines: {node: '>= 12.0.0'} @@ -1417,6 +1431,12 @@ packages: readable-stream: 2.3.7 dev: false + /argparse/1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + /asn1.js/5.4.1: resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} dependencies: @@ -2322,6 +2342,12 @@ packages: engines: {node: '>=0.8.0'} dev: true + /esprima/4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + /eventemitter3/4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} dev: true @@ -2966,6 +2992,14 @@ packages: /js-tokens/4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + /js-yaml/3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + /jsesc/2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} @@ -3436,8 +3470,8 @@ packages: '@parcel/fs': 2.2.1_@parcel+core@2.2.1 '@parcel/logger': 2.2.1 '@parcel/package-manager': 2.2.1_@parcel+core@2.2.1 - '@parcel/reporter-cli': 2.2.1_@parcel+core@2.2.1 - '@parcel/reporter-dev-server': 2.2.1_@parcel+core@2.2.1 + '@parcel/reporter-cli': 2.2.1 + '@parcel/reporter-dev-server': 2.2.1 '@parcel/utils': 2.2.1 chalk: 4.1.2 commander: 7.2.0 @@ -4467,6 +4501,10 @@ packages: readable-stream: 3.6.0 dev: true + /sprintf-js/1.0.3: + resolution: {integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=} + dev: true + /sqlite/4.0.23: resolution: {integrity: sha512-dSdmSkrdIhUL7xP/fiEMfFuAo4dxb0afag3rK8T4Y9lYxE3g3fXT0J8H9qSFvmcKxnM0zEA8yvLbpdWQ8mom3g==} dev: false