From 0714088d4b2e8724ce95d12e14676ca7eb132c8a Mon Sep 17 00:00:00 2001 From: eiiko6 Date: Mon, 15 Dec 2025 16:24:30 +0100 Subject: [PATCH] added token storage in a store, and improved layout on mobile --- package.json | 2 +- src-tauri/Cargo.lock | 29 ++++++ src-tauri/Cargo.toml | 1 + src-tauri/capabilities/default.json | 5 +- .../com/strawberries/chatapp/MainActivity.kt | 25 +++++- src-tauri/src/lib.rs | 1 + src/App.vue | 31 +++++-- src/api/client.ts | 6 +- src/base.css | 16 ++-- src/components/MessageList.vue | 21 +++-- src/main.ts | 2 - src/pages/ChatPage.vue | 5 +- src/pages/LoginPage.vue | 23 +++-- src/pages/RoomsPage.vue | 4 +- src/router/index.ts | 6 +- src/stores/auth.ts | 57 +++++++----- yarn.lock | 90 ++----------------- 17 files changed, 170 insertions(+), 154 deletions(-) diff --git a/package.json b/package.json index 174cb29..6bae961 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "dependencies": { "@tauri-apps/api": "^2", "@tauri-apps/plugin-opener": "^2", - "pinia": "^3.0.4", + "@tauri-apps/plugin-store": "~2", "vue": "^3.5.13", "vue-router": "^4.6.4" }, diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9d3fd1c..4586fb2 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -444,6 +444,7 @@ dependencies = [ "tauri", "tauri-build", "tauri-plugin-opener", + "tauri-plugin-store", ] [[package]] @@ -3642,6 +3643,22 @@ dependencies = [ "zbus", ] +[[package]] +name = "tauri-plugin-store" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a77036340a97eb5bbe1b3209c31e5f27f75e6f92a52fd9dd4b211ef08bf310" +dependencies = [ + "dunce", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.17", + "tokio", + "tracing", +] + [[package]] name = "tauri-runtime" version = "2.9.2" @@ -3859,9 +3876,21 @@ dependencies = [ "mio", "pin-project-lite", "socket2", + "tokio-macros", "windows-sys 0.61.2", ] +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "tokio-util" version = "0.7.17" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a7cafbf..b193f35 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -22,4 +22,5 @@ tauri = { version = "2", features = [] } tauri-plugin-opener = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" +tauri-plugin-store = "2" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index f5c766d..ddbfac0 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -7,6 +7,7 @@ ], "permissions": [ "core:default", - "opener:default" + "opener:default", + "store:default" ] -} +} \ No newline at end of file diff --git a/src-tauri/gen/android/app/src/main/java/com/strawberries/chatapp/MainActivity.kt b/src-tauri/gen/android/app/src/main/java/com/strawberries/chatapp/MainActivity.kt index 3e228ab..89d7a42 100644 --- a/src-tauri/gen/android/app/src/main/java/com/strawberries/chatapp/MainActivity.kt +++ b/src-tauri/gen/android/app/src/main/java/com/strawberries/chatapp/MainActivity.kt @@ -2,10 +2,33 @@ package com.strawberries.chatapp import android.os.Bundle import androidx.activity.enableEdgeToEdge +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsControllerCompat class MainActivity : TauriActivity() { override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) + + // Allow content to extend under the system bars + WindowCompat.setDecorFitsSystemWindows(window, false) + + // Make status and navigation bars transparent + window.statusBarColor = android.graphics.Color.TRANSPARENT + window.navigationBarColor = android.graphics.Color.TRANSPARENT + + // Get the insets controller + val insetsController = WindowInsetsControllerCompat(window, window.decorView) + + // Set system bar icons to light (white) + // false = dark background → light icons + insetsController.isAppearanceLightStatusBars = false + insetsController.isAppearanceLightNavigationBars = false + + // Optional: handle display cutout (notch) + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { + window.attributes.layoutInDisplayCutoutMode = + android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES + } } -} +} \ No newline at end of file diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 4a277ef..2a7b19c 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -7,6 +7,7 @@ fn greet(name: &str) -> String { #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() + .plugin(tauri_plugin_store::Builder::new().build()) .plugin(tauri_plugin_opener::init()) .invoke_handler(tauri::generate_handler![greet]) .run(tauri::generate_context!()) diff --git a/src/App.vue b/src/App.vue index 5273d94..e8e7b3b 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,10 +1,25 @@ - - + + diff --git a/src/api/client.ts b/src/api/client.ts index f0c094f..bea52a8 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -1,12 +1,12 @@ -import { useAuthStore } from '../stores/auth' +import { initAuth } from '../stores/auth.ts' -const BASE_URL = 'http://localhost:8080' +const BASE_URL = 'http://192.168.1.183:8081' export async function apiFetch( path: string, options: RequestInit = {} ): Promise { - const auth = useAuthStore() + const auth = await initAuth() const res = await fetch(`${BASE_URL}${path}`, { ...options, diff --git a/src/base.css b/src/base.css index c02dbc6..cf58fbf 100644 --- a/src/base.css +++ b/src/base.css @@ -1,4 +1,3 @@ -/* ---- CSS reset (minimal, modern) ---- */ *, *::before, *::after { @@ -16,19 +15,17 @@ body, height: 100%; } -/* ---- Theme variables ---- */ :root { - --bg: #0f1115; - --panel: #171923; + --bg: #0f1116; + --panel: #171922; --text: #e6e6eb; - --muted: #9aa0a6; - --accent: #f27aa2; - --accent-hover: #ff91b4; - --border: #2a2f3a; + --muted: #9aa0aa; + --accent: #f27aa3; + --accent-hover: #ff91b3; + --border: #2a2f3b; --radius: 8px; } -/* ---- Base ---- */ body { font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; @@ -37,7 +34,6 @@ body { line-height: 1.5; } -/* ---- Inputs & buttons ---- */ input, textarea { background: var(--panel); border: 1px solid var(--border); diff --git a/src/components/MessageList.vue b/src/components/MessageList.vue index f590f4c..3e79d76 100644 --- a/src/components/MessageList.vue +++ b/src/components/MessageList.vue @@ -5,8 +5,9 @@ defineProps<{ messages: Message[] }>() @@ -16,16 +17,22 @@ ul { padding: 0; margin: 0; list-style: none; - word-wrap: break-word; } -li { - white-space: pre-wrap; +.message { + margin-bottom: 1rem; +} + +.sender { + font-weight: bold; + margin-bottom: 0.25rem; } .message-content { - display: inline-block; + padding-left: 1rem; + white-space: pre-wrap; + word-wrap: break-word; max-width: 100%; - word-break: break-word; + display: block; } diff --git a/src/main.ts b/src/main.ts index a0d11fb..5ddd84a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,11 +1,9 @@ import { createApp } from 'vue' -import { createPinia } from 'pinia' import router from './router' import App from './App.vue' import './base.css' createApp(App) - .use(createPinia()) .use(router) .mount('#app') diff --git a/src/pages/ChatPage.vue b/src/pages/ChatPage.vue index 38ed231..067a0c8 100644 --- a/src/pages/ChatPage.vue +++ b/src/pages/ChatPage.vue @@ -50,9 +50,8 @@ function scrollToBottom() { .chat-page { display: flex; flex-direction: column; - height: 100%; - max-width: 720px; - margin: 0 auto; + height: 95%; + width: 90%; padding: 15px; border: 1px solid var(--border); border-radius: var(--radius); diff --git a/src/pages/LoginPage.vue b/src/pages/LoginPage.vue index 784178e..b4fd81f 100644 --- a/src/pages/LoginPage.vue +++ b/src/pages/LoginPage.vue @@ -1,18 +1,22 @@ @@ -25,6 +29,8 @@ async function submit() { + +

{{ errorMessage }}

@@ -55,4 +61,11 @@ async function submit() { margin-bottom: 0.5rem; text-align: center; } + +.error-message { + color: red; + font-size: 0.9rem; + text-align: center; + margin-top: 0.5rem; +} diff --git a/src/pages/RoomsPage.vue b/src/pages/RoomsPage.vue index c371d67..529ac16 100644 --- a/src/pages/RoomsPage.vue +++ b/src/pages/RoomsPage.vue @@ -17,14 +17,14 @@ diff --git a/src/router/index.ts b/src/router/index.ts index 0c5a2bb..5816d86 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,5 +1,5 @@ import { createRouter, createWebHistory } from 'vue-router' -import { useAuthStore } from '../stores/auth' +import { initAuth } from '../stores/auth.ts' import LoginPage from '../pages/LoginPage.vue' import RoomsPage from '../pages/RoomsPage.vue' @@ -14,8 +14,8 @@ const router = createRouter({ ], }) -router.beforeEach((to) => { - const auth = useAuthStore() +router.beforeEach(async (to) => { + const auth = await initAuth() if (!auth.isAuthenticated && to.path !== '/login') { return '/login' } diff --git a/src/stores/auth.ts b/src/stores/auth.ts index 85de3a3..02abcab 100644 --- a/src/stores/auth.ts +++ b/src/stores/auth.ts @@ -1,32 +1,41 @@ -import { defineStore } from 'pinia' +import { load, Store } from '@tauri-apps/plugin-store' import type { LoginResponse } from '../types/api' import { apiFetch } from '../api/client' -export const useAuthStore = defineStore('auth', { - state: () => ({ - token: null as string | null, - uuid: null as string | null, - }), +let store: Store | null = null - getters: { - isAuthenticated: (s) => !!s.token, - }, +async function getStore() { + if (!store) { + store = await load('store.json', { autoSave: false }) + } + return store +} - actions: { - async login(email: string, username: string, password: string) { - const res = await apiFetch('/login', { - method: 'POST', - body: JSON.stringify({ email, username, password }), - }) +export async function initAuth() { + const s = await getStore() + const token = await s.get('token') + const uuid = await s.get('uuid') + return { token: token || null, uuid: uuid || null, isAuthenticated: !!token } +} - this.token = res.token - this.uuid = res.uuid - }, +export async function login(email: string, username: string, password: string) { + const res: LoginResponse = await apiFetch('/login', { + method: 'POST', + body: JSON.stringify({ email, username, password }), + }) - logout() { - this.token = null - this.uuid = null - }, - }, -}) + const s = await getStore() + await s.set('token', res.token) + await s.set('uuid', res.uuid) + await s.save() + return { token: res.token, uuid: res.uuid, isAuthenticated: true } +} + +export async function logout() { + const s = await getStore() + await s.delete('token') + await s.delete('uuid') + await s.save() + return { token: null, uuid: null, isAuthenticated: false } +} diff --git a/yarn.lock b/yarn.lock index 1916a13..98e98fe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -356,6 +356,13 @@ dependencies: "@tauri-apps/api" "^2.8.0" +"@tauri-apps/plugin-store@~2": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-store/-/plugin-store-2.4.1.tgz#5e2d3362e41861d2fa79a3f1a78c091e12963236" + integrity sha512-ckGSEzZ5Ii4Hf2D5x25Oqnm2Zf9MfDWAzR+volY0z/OOBz6aucPKEY0F649JvQ0Vupku6UJo7ugpGRDOFOunkA== + dependencies: + "@tauri-apps/api" "^2.8.0" + "@types/estree@1.0.8": version "1.0.8" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" @@ -442,33 +449,6 @@ resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz#cbe97fe0162b365edc1dba80e173f90492535343" integrity sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g== -"@vue/devtools-api@^7.7.7": - version "7.7.9" - resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-7.7.9.tgz#999dbea50da6b00cf59a1336f11fdc2b43d9e063" - integrity sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g== - dependencies: - "@vue/devtools-kit" "^7.7.9" - -"@vue/devtools-kit@^7.7.9": - version "7.7.9" - resolved "https://registry.yarnpkg.com/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz#bc218a815616e8987df7ab3e10fc1fb3b8706c58" - integrity sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA== - dependencies: - "@vue/devtools-shared" "^7.7.9" - birpc "^2.3.0" - hookable "^5.5.3" - mitt "^3.0.1" - perfect-debounce "^1.0.0" - speakingurl "^14.0.1" - superjson "^2.2.2" - -"@vue/devtools-shared@^7.7.9": - version "7.7.9" - resolved "https://registry.yarnpkg.com/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz#fa4c096b744927081a7dda5fcf05f34b1ae6ca14" - integrity sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA== - dependencies: - rfdc "^1.4.1" - "@vue/language-core@2.2.12": version "2.2.12" resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-2.2.12.tgz#d01f7e865f593f968cb65c12a13d8337e65641f0" @@ -531,11 +511,6 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -birpc@^2.3.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/birpc/-/birpc-2.9.0.tgz#b59550897e4cd96a223e2a6c1475b572236ed145" - integrity sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw== - brace-expansion@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" @@ -543,13 +518,6 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -copy-anything@^4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-4.0.5.tgz#16cabafd1ea4bb327a540b750f2b4df522825aea" - integrity sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA== - dependencies: - is-what "^5.2.0" - csstype@^3.1.3: version "3.2.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.2.3.tgz#ec48c0f3e993e50648c86da559e2610995cf989a" @@ -617,16 +585,6 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -hookable@^5.5.3: - version "5.5.3" - resolved "https://registry.yarnpkg.com/hookable/-/hookable-5.5.3.tgz#6cfc358984a1ef991e2518cb9ed4a778bbd3215d" - integrity sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ== - -is-what@^5.2.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/is-what/-/is-what-5.5.0.tgz#a3031815757cfe1f03fed990bf6355a2d3f628c4" - integrity sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw== - magic-string@^0.30.21: version "0.30.21" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" @@ -641,11 +599,6 @@ minimatch@^9.0.3: dependencies: brace-expansion "^2.0.1" -mitt@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" - integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== - muggle-string@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/muggle-string/-/muggle-string-0.4.1.tgz#3b366bd43b32f809dc20659534dd30e7c8a0d328" @@ -661,11 +614,6 @@ path-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== -perfect-debounce@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz#9c2e8bc30b169cc984a58b7d5b28049839591d2a" - integrity sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA== - picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -676,13 +624,6 @@ picomatch@^4.0.2, picomatch@^4.0.3: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== -pinia@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/pinia/-/pinia-3.0.4.tgz#75dde12784a61e34c1fa6abcd13c1a1061c360c0" - integrity sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw== - dependencies: - "@vue/devtools-api" "^7.7.7" - postcss@^8.5.3, postcss@^8.5.6: version "8.5.6" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" @@ -692,11 +633,6 @@ postcss@^8.5.3, postcss@^8.5.6: picocolors "^1.1.1" source-map-js "^1.2.1" -rfdc@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" - integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== - rollup@^4.34.9: version "4.53.4" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.53.4.tgz#5517de2593624928ac18f041b269f3b79cb64e09" @@ -733,18 +669,6 @@ source-map-js@^1.2.1: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== -speakingurl@^14.0.1: - version "14.0.1" - resolved "https://registry.yarnpkg.com/speakingurl/-/speakingurl-14.0.1.tgz#f37ec8ddc4ab98e9600c1c9ec324a8c48d772a53" - integrity sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ== - -superjson@^2.2.2: - version "2.2.6" - resolved "https://registry.yarnpkg.com/superjson/-/superjson-2.2.6.tgz#a223a3a988172a5f9656e2063fe5f733af40d099" - integrity sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA== - dependencies: - copy-anything "^4" - tinyglobby@^0.2.13: version "0.2.15" resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.15.tgz#e228dd1e638cea993d2fdb4fcd2d4602a79951c2"