More things

This commit is contained in:
Sofía Aritz 2023-12-10 15:19:19 +01:00
parent ebd9f7ae36
commit 85e1c86739
Signed by: sofia
GPG key ID: 90B5116E3542B28F
17 changed files with 456 additions and 103 deletions

View file

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>aybWeb</title> <title>aybWeb</title>
</head> </head>
<body> <body class="dark:bg-gray-900 dark:text-white">
<div id="app"></div> <div id="app"></div>
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>
</body> </body>

View file

@ -28,6 +28,8 @@
"vite": "^5.0.0" "vite": "^5.0.0"
}, },
"dependencies": { "dependencies": {
"@dicebear/collection": "^7.0.1",
"@dicebear/core": "^7.0.1",
"pattern.css": "^1.0.0" "pattern.css": "^1.0.0"
} }
} }

View file

@ -5,9 +5,10 @@
import Redirect from "./lib/components/Redirect.svelte" import Redirect from "./lib/components/Redirect.svelte"
import Login from "./routes/Login.svelte" import Login from "./routes/Login.svelte"
import Confirm from "./routes/Confirm.svelte" import Confirm from "./routes/Confirm.svelte"
import Home from "./routes/Home.svelte"; import Home from "./routes/Home.svelte"
import DatabaseOverview from "./routes/DatabaseOverview.svelte"; import DatabaseOverview from "./routes/DatabaseOverview.svelte"
import DatabaseQuery from "./routes/DatabaseQuery.svelte"; import DatabaseQuery from "./routes/DatabaseQuery.svelte"
import UserPage from "./routes/UserPage.svelte"
</script> </script>
<Router> <Router>
@ -16,12 +17,15 @@
<main class="flex w-[95vw] flex-col items-center md:w-[60vw]"> <main class="flex w-[95vw] flex-col items-center md:w-[60vw]">
{#if $loggedIn} {#if $loggedIn}
<Route path="/"><Home /></Route> <Route path="/"><Home /></Route>
<Route path="/database/:entity/:slug/overview" let:params> <Route path="/u/:entity/:slug/overview" let:params>
<DatabaseOverview entity={params.entity} slug={params.slug} /> <DatabaseOverview entity={params.entity} slug={params.slug} />
</Route> </Route>
<Route path="/database/:entity/:slug/query" let:params> <Route path="/u/:entity/:slug/query" let:params>
<DatabaseQuery entity={params.entity} slug={params.slug} /> <DatabaseQuery entity={params.entity} slug={params.slug} />
</Route> </Route>
<Route path="/u/:entity" let:params>
<UserPage entity={params.entity} />
</Route>
<Route path="/auth/login"><Redirect to="/" /></Route> <Route path="/auth/login"><Redirect to="/" /></Route>
<Route path="/auth/confirm"><Redirect to="/" /></Route> <Route path="/auth/confirm"><Redirect to="/" /></Route>
<Route path="/auth/confirm/:token"> <Route path="/auth/confirm/:token">

View file

@ -32,6 +32,6 @@
@layer components { @layer components {
a { a {
@apply text-blue-700 underline hover:text-blue-800; @apply text-blue-700 underline hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-500;
} }
} }

View file

@ -83,6 +83,7 @@ export async function confirm(token: string, auth: UserInstanceData) {
}) })
} }
// TODO(sofiaritz): Check method
export async function createDatabase(slug: string, databaseType: DBType, auth: UserInstanceData) { export async function createDatabase(slug: string, databaseType: DBType, auth: UserInstanceData) {
return request<DatabaseCreation>(`/v1/${slug}/create`, auth, { return request<DatabaseCreation>(`/v1/${slug}/create`, auth, {
headers: { headers: {

View file

@ -0,0 +1,13 @@
<script lang="ts">
import { createAvatar } from "@dicebear/core"
import { identicon } from "@dicebear/collection"
export let slug: string
export let className: string | undefined = undefined
const avatar = createAvatar(identicon, {
seed: slug,
})
</script>
<img src={avatar.toDataUriSync()} alt={`${slug}'s avatar`} class={className} />

View file

@ -3,12 +3,16 @@
import { Link } from "svelte-routing" import { Link } from "svelte-routing"
</script> </script>
<header class="flex items-center justify-between rounded-b-2xl bg-gray-100 p-4"> <header class="flex items-center justify-between bg-gray-100 p-4 dark:bg-gray-950 dark:text-white">
<h1 class="text-xl"> <h1 class="text-xl">
<Link class="text-black no-underline hover:text-gray-800" to="/">aybWeb</Link> <Link
class="text-black no-underline hover:text-black dark:text-white dark:hover:text-white"
to="/">aybWeb</Link
>
</h1> </h1>
{#if $loggedIn} {#if $loggedIn}
<span>Logged in as <code>{$userInfo.slug}</code></span> <span>Logged in as <code><Link to="/u/{$userInfo.slug}">{$userInfo.slug}</Link></code></span
>
{:else} {:else}
<Link <Link
class="rounded bg-blue-600 px-3 py-1.5 text-white no-underline hover:bg-blue-700 hover:text-white" class="rounded bg-blue-600 px-3 py-1.5 text-white no-underline hover:bg-blue-700 hover:text-white"

View file

@ -0,0 +1,18 @@
<script lang="ts">
export let name: string = ""
export let id: string = ""
export let rows: string = ""
export let placeholder: string = ""
export let value: string = ""
export let disabled: boolean = false
</script>
<textarea
class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500 disabled:bg-gray-100 disabled:font-mono"
{name}
{id}
{placeholder}
{value}
{disabled}
{rows}
/>

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { DBType } from "../../api/types"; import { DBType } from "../../api/types"
import { Link } from "svelte-routing"; import { Link } from "svelte-routing"
export let entity: string export let entity: string
export let slug: string export let slug: string
@ -17,19 +17,15 @@
} }
const background = async (slug: string) => { const background = async (slug: string) => {
const utf8 = new TextEncoder().encode(slug); const utf8 = new TextEncoder().encode(slug)
let hash = await crypto.subtle.digest('SHA-256', utf8).then((hashBuffer) => { let hash = await crypto.subtle.digest("SHA-256", utf8).then((hashBuffer) => {
const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashArray = Array.from(new Uint8Array(hashBuffer))
return hashArray return hashArray.map((bytes) => bytes.toString(16).padStart(2, "0")).join("")
.map((bytes) => bytes.toString(16).padStart(2, '0'))
.join('');
}) })
let hashCode = [...hash].reduce((acc, char) => char.charCodeAt(0) + ((acc << 5) - acc), 0); let hashCode = [...hash].reduce((acc, char) => char.charCodeAt(0) + ((acc << 5) - acc), 0)
let primaryColor = (() => { let primaryColor = (() => {
let c = (hashCode & 0x00FFFFFF) let c = (hashCode & 0x00ffffff).toString(16).toUpperCase()
.toString(16)
.toUpperCase()
return "00000".substring(0, 6 - c.length) + c return "00000".substring(0, 6 - c.length) + c
})() })()
@ -60,9 +56,13 @@
} }
</script> </script>
<Link to={`/database/${entity}/${slug}/overview`} role="button" class="border border-gray-300 rounded no-underline text-black hover:text-black"> <Link
to={`/u/${entity}/${slug}/overview`}
role="button"
class="rounded border border-gray-300 text-black no-underline hover:text-black dark:border-gray-800 dark:text-white dark:hover:text-white"
>
{#await background(slug)} {#await background(slug)}
<div class="h-24 pattern-checks-sm"></div> <div class="pattern-checks-sm h-24"></div>
{:then result} {:then result}
<div class={`h-24 ${result[0]}`} style={result[1]}></div> <div class={`h-24 ${result[0]}`} style={result[1]}></div>
{/await} {/await}
@ -70,5 +70,5 @@
<div class="p-2"> <div class="p-2">
<span>{slug.split(".")[0]}</span> <span>{slug.split(".")[0]}</span>
</div> </div>
<span class="block px-2 mb-2">Database type: {displayType(type)}</span> <span class="mb-2 block px-2 dark:text-gray-400">Database type: {displayType(type)}</span>
</Link> </Link>

View file

@ -1,27 +1,27 @@
<script lang="ts"> <script lang="ts">
import { Link } from "svelte-routing"; import { Link } from "svelte-routing"
export let entity: string export let entity: string
export let slug: string export let slug: string
export let selected: "overview" | "query" | "settings" = "overview" export let selected: "overview" | "query" | "settings" = "overview"
</script> </script>
<div class="flex flex-col w-32 gap-2"> <div class="flex w-32 flex-col gap-2">
{#if selected === "overview"} {#if selected === "overview"}
<span>Overview</span> <span>Overview</span>
{:else} {:else}
<Link to={`/database/${entity}/${slug}/overview`}>Overview</Link> <Link to={`/u/${entity}/${slug}/overview`}>Overview</Link>
{/if} {/if}
{#if selected === "query"} {#if selected === "query"}
<span>Query</span> <span>Query</span>
{:else} {:else}
<Link to={`/database/${entity}/${slug}/query`}>Query</Link> <Link to={`/u/${entity}/${slug}/query`}>Query</Link>
{/if} {/if}
{#if selected === "settings"} {#if selected === "settings"}
<span>Settings</span> <span>Settings</span>
{:else} {:else}
<Link to={`/database/${entity}/${slug}/settings`}>Settings</Link> <Link to={`/u/${entity}/${slug}/settings`}>Settings</Link>
{/if} {/if}
</div> </div>

View file

@ -1,22 +1,22 @@
<script lang="ts"> <script lang="ts">
import type { DatabaseQuery } from "../../api/types"; import type { DatabaseQuery } from "../../api/types"
export let data: DatabaseQuery export let data: DatabaseQuery
</script> </script>
<table class="border-gray-400 border p-3 w-full"> <table class="w-full border border-gray-400 p-3">
<thead> <thead>
<tr class="border-gray-400 border text-left"> <tr class="border border-gray-400 text-left">
{#each data.fields as field} {#each data.fields as field}
<th class="border-gray-400 border px-2">{field}</th> <th class="border border-gray-400 px-2">{field}</th>
{/each} {/each}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each data.rows as row} {#each data.rows as row}
<tr class="border-gray-400 border"> <tr class="border border-gray-400">
{#each row as value} {#each row as value}
<td class="px-2 border-gray-400 border">{value}</td> <td class="border border-gray-400 px-2">{value}</td>
{/each} {/each}
</tr> </tr>
{/each} {/each}

View file

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import DatabasePagesHeader from "../lib/components/database/DatabasePagesHeader.svelte"; import DatabasePagesHeader from "../lib/components/database/DatabasePagesHeader.svelte"
export let entity: string export let entity: string
export let slug: string export let slug: string
@ -7,24 +7,29 @@
<div class="flex gap-6 md:w-8/12"> <div class="flex gap-6 md:w-8/12">
<DatabasePagesHeader selected="overview" {slug} {entity} /> <DatabasePagesHeader selected="overview" {slug} {entity} />
<div class="flex flex-col w-full"> <div class="flex w-full flex-col">
<h1 class="text-2xl">Congratulations, you've got your database set-up!</h1> <h1 class="text-2xl">Congratulations, you've got your database set-up!</h1>
<div class="flex gap-6"> <div class="flex gap-6">
<div class="border border-gray-300 rounded p-6 mt-6 w-full"> <div class="mt-6 w-full rounded border border-gray-300 p-6">
<h2 class="text-xl">Documentation</h2> <h2 class="text-xl">Documentation</h2>
<span class="text-gray-500 block mt-1">Check out the link below for more information about ayb</span> <span class="mt-1 block text-gray-500"
>Check out the link below for more information about ayb</span
>
<a class="mt-1 block" href="https://git.sofiaritz.com/sofia/wip">ayb.host/docs</a> <a class="mt-1 block" href="https://git.sofiaritz.com/sofia/wip">ayb.host/docs</a>
</div> </div>
<div class="border border-gray-300 rounded p-6 mt-6 w-full"> <div class="mt-6 w-full rounded border border-gray-300 p-6">
<h2 class="text-xl">Getting help</h2> <h2 class="text-xl">Getting help</h2>
<span class="text-gray-500 block mt-1">Contact the instance owner for support</span> <span class="mt-1 block text-gray-500">Contact the instance owner for support</span>
<a class="mt-1 block" href="https://git.sofiaritz.com/sofia/wip">ayb.host/support</a> <a class="mt-1 block" href="https://git.sofiaritz.com/sofia/wip">ayb.host/support</a
>
</div> </div>
</div> </div>
<div class="flex gap-6"> <div class="flex gap-6">
<div class="border border-gray-300 rounded p-6 mt-6 w-full"> <div class="mt-6 w-full rounded border border-gray-300 p-6">
<h2 class="text-xl">Usage limits</h2> <h2 class="text-xl">Usage limits</h2>
<span class="text-gray-500 block mt-1">You are not subject to usage limits right now</span> <span class="mt-1 block text-gray-500"
>You are not subject to usage limits right now</span
>
<a class="mt-1 block" href="https://git.sofiaritz.com/sofia/wip">ayb.host/limits</a> <a class="mt-1 block" href="https://git.sofiaritz.com/sofia/wip">ayb.host/limits</a>
</div> </div>
</div> </div>

View file

@ -1,11 +1,12 @@
<script lang="ts"> <script lang="ts">
import { login, queryDatabase, unwrapResponse } from "../lib/api"; import { login, queryDatabase, unwrapResponse } from "../lib/api"
import { userInstanceData } from "../lib/auth/stores"; import { userInstanceData } from "../lib/auth/stores"
import DatabaseResult from "../lib/components/database/DatabaseQueryResult.svelte"; import DatabaseResult from "../lib/components/database/DatabaseQueryResult.svelte"
import DatabasePagesHeader from "../lib/components/database/DatabasePagesHeader.svelte"; import DatabasePagesHeader from "../lib/components/database/DatabasePagesHeader.svelte"
import { createForm } from "felte"; import { createForm } from "felte"
import { Input } from "../lib/components/common"; import { Input } from "../lib/components/common"
import Button from "../lib/components/common/Button.svelte"; import Button from "../lib/components/common/Button.svelte"
import Textarea from "../lib/components/common/Textarea.svelte"
export let entity: string export let entity: string
export let slug: string export let slug: string
@ -16,14 +17,20 @@
const { form } = createForm({ const { form } = createForm({
onSubmit: async (values) => { onSubmit: async (values) => {
let lowercaseQuery = values["query"].toLowerCase() let lowercaseQuery = values["query"].toLowerCase()
if (lowercaseQuery.includes("delete") || lowercaseQuery.includes("drop") || lowercaseQuery.includes("truncate")) { if (
let confirmed = confirm("Your query can potentially perform destructive actions. Do you want to continue?") lowercaseQuery.includes("delete") ||
if (!confirmed) return; lowercaseQuery.includes("drop") ||
lowercaseQuery.includes("truncate")
) {
let confirmed = confirm(
"Your query can potentially perform destructive actions. Do you want to continue?",
)
if (!confirmed) return
} }
result = { status: "loading" } result = { status: "loading" }
let query = values["query"].trim() let query = values["query"].trim()
if (!query.endsWith(";")) query += ";"; if (!query.endsWith(";")) query += ";"
return await queryDatabase(`${entity}/${slug}`, query, $userInstanceData) return await queryDatabase(`${entity}/${slug}`, query, $userInstanceData)
}, },
@ -35,7 +42,7 @@
<div class="flex gap-6 md:w-8/12"> <div class="flex gap-6 md:w-8/12">
<DatabasePagesHeader selected="query" {slug} {entity} /> <DatabasePagesHeader selected="query" {slug} {entity} />
<div class="flex flex-col w-full"> <div class="flex w-full flex-col">
<h1 class="text-2xl">Start querying your database</h1> <h1 class="text-2xl">Start querying your database</h1>
<div class="flex gap-2 pt-4"> <div class="flex gap-2 pt-4">
<label for="big-mode mb-0">Big mode enabled</label> <label for="big-mode mb-0">Big mode enabled</label>
@ -44,16 +51,24 @@
<form class="mt-2 gap-6" use:form> <form class="mt-2 gap-6" use:form>
{#if bigMode === true} {#if bigMode === true}
<div class="flex flex-col gap-6"> <div class="flex flex-col gap-6">
<textarea name="query" rows="5" placeholder="SELECT <Textarea
name="query"
rows="5"
placeholder="SELECT
id, id,
name, name,
score score
FROM favorite_databases"/> FROM favorite_databases"
/>
<Button type="submit">Query</Button> <Button type="submit">Query</Button>
</div> </div>
{:else} {:else}
<div class="flex gap-6"> <div class="flex gap-6">
<Input name="query" type="text" placeholder="SELECT * FROM favorite_databases"/> <Input
name="query"
type="text"
placeholder="SELECT * FROM favorite_databases"
/>
<Button type="submit">Query</Button> <Button type="submit">Query</Button>
</div> </div>
{/if} {/if}
@ -62,17 +77,20 @@ FROM favorite_databases"/>
{#if result != null} {#if result != null}
{#if result.message != null} {#if result.message != null}
<span><span class="pr-2 text-red-600">Error</span>{result.message}</span> <span><span class="pr-2 text-red-600">Error</span>{result.message}</span>
{:else if ((result.fields != null && result.rows != null) && result.rows.length > 0)} {:else if result.fields != null && result.rows != null && result.rows.length > 0}
<DatabaseResult data={result} /> <DatabaseResult data={result} />
{:else if (result.fields != null && result.rows != null)} {:else if result.fields != null && result.rows != null}
<span class="text-gray-500 block">No rows returned</span> <span class="block text-gray-500">No rows returned</span>
{:else if result.status === "loading"} {:else if result.status === "loading"}
<span class="text-gray-500 block">Loading...</span> <span class="block text-gray-500">Loading...</span>
{:else} {:else}
<span><span class="pr-2 text-red-600">Error</span>Unknown response from the server</span> <span
><span class="pr-2 text-red-600">Error</span>Unknown response from the
server</span
>
{/if} {/if}
{:else} {:else}
<span class="text-gray-500 block">Waiting for your query...</span> <span class="block text-gray-500">Waiting for your query...</span>
{/if} {/if}
</div> </div>
</div> </div>

View file

@ -1,25 +1,53 @@
<script lang="ts"> <script lang="ts">
import { userInfo } from "../lib/auth/stores"; import { userInfo } from "../lib/auth/stores"
import DatabaseCard from "../lib/components/database/DatabaseCard.svelte"; import DatabaseCard from "../lib/components/database/DatabaseCard.svelte"
import { Link } from "svelte-routing"; import { Link } from "svelte-routing"
import Avatar from "../lib/components/Avatar.svelte"
</script> </script>
<div class="md:w-8/12"> <div class="flex flex-col gap-6 md:w-8/12">
<h1 class="text-2xl">Your databases</h1> <div class="flex flex-col gap-3">
<h1 class="text-2xl">Organizations</h1>
<div class="flex gap-6">
<a
href={`/u/${$userInfo.slug}`}
class="flex flex-col items-center gap-1 text-black no-underline hover:text-black dark:text-white dark:hover:text-white"
>
<Avatar
className="w-12 rounded border-gray-300 dark:border-gray-700 dark:border-2 bg-white border"
slug={$userInfo.slug}
/>
<span class="text-sm">{$userInfo.slug}</span>
</a>
</div>
</div>
<div class="flex flex-col gap-3">
<h1 class="text-2xl">Databases</h1>
{#if $userInfo.databases.length > 0} {#if $userInfo.databases.length > 0}
<div class="grid grid-cols-2 gap-6 mt-5"> <div class="grid grid-cols-2 gap-6">
{#each $userInfo.databases as database (database.slug)} {#each $userInfo.databases as database (database.slug)}
<DatabaseCard entity={$userInfo.slug} slug={database.slug} type={database.database_type}/> <DatabaseCard
entity={$userInfo.slug}
slug={database.slug}
type={database.database_type}
/>
{/each} {/each}
</div> </div>
{:else} {:else}
<div class="flex mt-5"> <div class="mt-5 flex">
<Link to="/database/new" role="button" class="flex flex-col gap-3 justify-center items-center h-60 w-full border border-gray-300 rounded p-2 no-underline text-black hover:text-black"> <Link
to="/database/new"
role="button"
class="flex h-60 w-full flex-col items-center justify-center gap-3 rounded border border-gray-300 p-2 text-black no-underline hover:text-black"
>
<span class="text-4xl">+</span> <span class="text-4xl">+</span>
<h2 class="font-bold text-xl">Create a new database</h2> <h2 class="text-xl font-bold">Create a new database</h2>
<span class="text-gray-500 block">The instance owner hasn't set any limits for your account</span> <span class="block text-gray-500"
>The instance owner hasn't set any limits for your account</span
>
</Link> </Link>
</div> </div>
{/if} {/if}
</div> </div>
</div>

View file

@ -49,7 +49,7 @@
<h1 class="text-2xl text-red">Error</h1> <h1 class="text-2xl text-red">Error</h1>
<span>{error.toString()}</span> <span>{error.toString()}</span>
{:else if state === State.Waiting} {:else if state === State.Waiting}
<h1 class="mb-6 text-2xl font-bold text-gray-900">Login</h1> <h1 class="mb-6 text-2xl font-bold text-gray-900 dark:text-white">Login</h1>
<form class="flex flex-col gap-3.5" use:form> <form class="flex flex-col gap-3.5" use:form>
<label class="block" for="instance-input"> <label class="block" for="instance-input">
Instance Instance
@ -59,7 +59,7 @@
id="instance-input" id="instance-input"
placeholder="https://ayb.sofiaritz.com" placeholder="https://ayb.sofiaritz.com"
/> />
<span class="text-sm text-gray-700" <span class="text-sm text-gray-700 dark:text-gray-400"
>You can find an updated instance list at <a >You can find an updated instance list at <a
href="https://git.sofiaritz.com/sofia/wip">ayb.host/instances</a href="https://git.sofiaritz.com/sofia/wip">ayb.host/instances</a
></span ></span

View file

@ -0,0 +1,44 @@
<script lang="ts">
import { entityInfo, unwrapResponse } from "../lib/api"
import { userInstanceData } from "../lib/auth/stores"
import Avatar from "../lib/components/Avatar.svelte"
import DatabaseCard from "../lib/components/database/DatabaseCard.svelte"
export let entity: string
const fetchEntity = async (entity: string) =>
unwrapResponse(await entityInfo(entity, $userInstanceData))
const isNotFound = (message: string) =>
message.trim().toLowerCase().startsWith("entity not found")
</script>
{#await fetchEntity(entity)}
<h1 class="text-2xl">Loading...</h1>
{:then entity}
<div class="mb-6 flex w-full gap-9">
<div class="flex w-2/12 flex-col gap-6">
<Avatar
className="w-full border-gray-300 dark:border-gray-700 dark:border-2 bg-white border rounded"
slug={entity.slug}
/>
<h1 class="text-2xl">{entity.slug}</h1>
</div>
<div class="flex w-full flex-col gap-6">
{#each entity.databases as database (database.slug)}
<DatabaseCard
entity={entity.slug}
slug={database.slug}
type={database.database_type}
/>
{/each}
</div>
</div>
{:catch error}
{#if isNotFound(error.message)}
<h1 class="mb-5 text-5xl">404</h1>
<h1 class="text-sm">
The entity you are trying to see either does not exist or you are not authorized to view
it.
</h1>
{/if}
{/await}

216
yarn.lock
View file

@ -15,6 +15,196 @@
"@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/gen-mapping" "^0.3.0"
"@jridgewell/trace-mapping" "^0.3.9" "@jridgewell/trace-mapping" "^0.3.9"
"@dicebear/adventurer-neutral@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/adventurer-neutral/-/adventurer-neutral-7.0.1.tgz#2ff2b2334e11e8d1540ff9187e90f920e65b4dc2"
integrity sha512-dZfyaUFS8qQv7Lv+OXNTHVkercDCh+VqGSJU8jIf3FFbtFbFF79FXZJwJ8V3+pr0xKcZWa8i+8hXLtU3gqZ18g==
"@dicebear/adventurer@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/adventurer/-/adventurer-7.0.1.tgz#0f175f0bff38de4f3251d36912a2c80ae17610fe"
integrity sha512-eqbHHAQO8HjG8YNMl8xgklxphC7HvfDtqVr1rkJWP98e7r2AdQpu0cPYIOZPV4uv9gxl1ncaErQjdjvIvFRGiA==
"@dicebear/avataaars-neutral@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/avataaars-neutral/-/avataaars-neutral-7.0.1.tgz#0eea134753e1f8ea459a3444fc3ba1e071377782"
integrity sha512-e3XwK3xup4ifJ/BUNjR5rcrw9982SC75UTJlPsKuuOM/Lwx3MtUe3+dqeDSyYbrC7KoWespX70oDZK1+2dBQFw==
"@dicebear/avataaars@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/avataaars/-/avataaars-7.0.1.tgz#33240f6bb2f1d9694265ac8786e1b149aa10903a"
integrity sha512-U7JJLDFJsbVyQl3j1SqtTxi5h+I5JXL8CGfwAOPtQTnk/tKQFXM9WF/zdHegtxbxYAxQaYJtyprdwTJHx5ELnw==
"@dicebear/big-ears-neutral@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/big-ears-neutral/-/big-ears-neutral-7.0.1.tgz#472120f04e07411e18576d8e25466633d49ff8ed"
integrity sha512-2QK9HVmApoGFLi3ONW9mh0Tk/PPyHx9rvzUvcT5H/mb80ooBqIVMPYYq4rVlGVP6wAtsNHdoxzzlKja0DG+vvQ==
"@dicebear/big-ears@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/big-ears/-/big-ears-7.0.1.tgz#c62cafb9812828c52080b03a6b706a4cfafc6bb7"
integrity sha512-ITI0IQCwdn5s5/kUrNdO488TQvZdiCljnzKpqbQ1hqfsxZ0C+eZs+cudZ0bqLftYxM+WBvmaJwrh3pXNAz1h+w==
"@dicebear/big-smile@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/big-smile/-/big-smile-7.0.1.tgz#f16b526a7559abb5f032f82351e7e8d25d7dd5a9"
integrity sha512-hVAhUMZ0LUhMFvtmUDR8GU7v2ufl5pOcVPiVSC3oV8nyywFp7s1ZqYGhi6rBCEG3qsMR54JfMFWkjV88j4Yrmg==
"@dicebear/bottts-neutral@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/bottts-neutral/-/bottts-neutral-7.0.1.tgz#ee272b0bb4af0fb5cff0d3a6c1b8492ec1c8a2f9"
integrity sha512-1T1NEKAEvqyGlUprkO1Q1btITZnMBiCP5YeCy6wYyM7qJsPVDSySsjASJ1j/+IZFi8ePgWReFIbigFiHdo7iLA==
"@dicebear/bottts@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/bottts/-/bottts-7.0.1.tgz#050c6a13388e8c7002c4d275525169e271c55dcb"
integrity sha512-k0adSvnT9+gFDO7/Cmts9TM3CSWYrZrxZe1WpELjTvwe4QOqdn3LgrYR9JXU/2hRz3GaXtP02SHNd85CkadYVw==
"@dicebear/collection@^7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/collection/-/collection-7.0.1.tgz#822edfed1309ab7aa3588a7d1cb635afd4b8579b"
integrity sha512-Y5xzjU2hiklYUkqsSr5VBpVPG++iUUTm1UDJLPM+iXg3lMF3PQuifXoaAxcuoBvvnKfJKNHf5wP1Bq6nRUl4NA==
dependencies:
"@dicebear/adventurer" "7.0.1"
"@dicebear/adventurer-neutral" "7.0.1"
"@dicebear/avataaars" "7.0.1"
"@dicebear/avataaars-neutral" "7.0.1"
"@dicebear/big-ears" "7.0.1"
"@dicebear/big-ears-neutral" "7.0.1"
"@dicebear/big-smile" "7.0.1"
"@dicebear/bottts" "7.0.1"
"@dicebear/bottts-neutral" "7.0.1"
"@dicebear/croodles" "7.0.1"
"@dicebear/croodles-neutral" "7.0.1"
"@dicebear/fun-emoji" "7.0.1"
"@dicebear/icons" "7.0.1"
"@dicebear/identicon" "7.0.1"
"@dicebear/initials" "7.0.1"
"@dicebear/lorelei" "7.0.1"
"@dicebear/lorelei-neutral" "7.0.1"
"@dicebear/micah" "7.0.1"
"@dicebear/miniavs" "7.0.1"
"@dicebear/notionists" "7.0.1"
"@dicebear/notionists-neutral" "7.0.1"
"@dicebear/open-peeps" "7.0.1"
"@dicebear/personas" "7.0.1"
"@dicebear/pixel-art" "7.0.1"
"@dicebear/pixel-art-neutral" "7.0.1"
"@dicebear/rings" "7.0.1"
"@dicebear/shapes" "7.0.1"
"@dicebear/thumbs" "7.0.1"
"@dicebear/converter@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/converter/-/converter-7.0.1.tgz#3ff9049c0cecb015d0f4549454c62f211a0dab0a"
integrity sha512-CEIF6ZKi1FAE9kW10FvuPUjA6HLi+LcuB/GRFct/Bv28llzTel9xwbmfOEa1aIM8Nnp8BuT4U7tBIytksf+ptw==
dependencies:
"@types/json-schema" "^7.0.11"
tmp-promise "^3.0.3"
"@dicebear/core@^7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/core/-/core-7.0.1.tgz#a43bfa851e00f522a0f50fc7b5aaad117389000a"
integrity sha512-jaJG693c+myLocgG3kKXdHa+WJ+S6OcD31SEr9Oby7hhOzALQYD+LcJ15oBWwI7SLHJcGPYTOLyx2eDr8YhXCQ==
dependencies:
"@dicebear/converter" "7.0.1"
"@types/json-schema" "^7.0.11"
"@dicebear/croodles-neutral@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/croodles-neutral/-/croodles-neutral-7.0.1.tgz#f3fcda48aa4e9dfd9366013cb53e2806dae6907b"
integrity sha512-u09YylowZcbSAVyKJ4I8BCo1ehluqg3onYCclx++8mOWcEo+XGsGKIeN7osayaflNY/qtA9Jt2JsPgiS8KpQ5A==
"@dicebear/croodles@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/croodles/-/croodles-7.0.1.tgz#6ceee52434046dfbeb8ff674f240a307c6d5a006"
integrity sha512-uauBTUvKFvsiaT+LWYKCEboEeOJy2Pk055nsdczi13UgHHfj+Qvy0/ky/uzYn+WC/1gewqQ6w/yS1WfpgPtIpg==
"@dicebear/fun-emoji@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/fun-emoji/-/fun-emoji-7.0.1.tgz#e6ac7bbe755ae34a03a5dee4646a5b7ae5622ab6"
integrity sha512-oJj5sb4rakro4e0lZTCkcKkiClHxDWr6+NWTwoU5L1HYRkXV6ngk4s7xSdOrYBQpYjLhdu+Lpx1VHYNpLUu2vg==
"@dicebear/icons@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/icons/-/icons-7.0.1.tgz#b02cfb4fc5f527c085dca4d26a7f23f36cca1aa4"
integrity sha512-juHS4feScGCz4YdiwjxR60RJ2G7Z6W+tdUqNHN9ufMvY/FpJTfrQvzvrJfJfc84QZwIrqI/96WV3JIBEIO2AwQ==
"@dicebear/identicon@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/identicon/-/identicon-7.0.1.tgz#b8b7031c18606a7aee9c961b8abde30917d84a52"
integrity sha512-9W9pqqhvpMsZmOkjuLwlw0iift56A3VFq7eNpJPB1mm6gytfqgxozgOVLDFgug9VXgUVI2Jrk/XnXGIFVIeVQA==
"@dicebear/initials@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/initials/-/initials-7.0.1.tgz#a53b6352c879a140add756de0c9d427ae6693059"
integrity sha512-zCI6fky4odM5ezl/GlhcSdnu+oNfmBbIghFB5NzgB/wV5nHmw2okONRC+Mgmxv8P8EpFb9z5hEOnh8xwW8htow==
"@dicebear/lorelei-neutral@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/lorelei-neutral/-/lorelei-neutral-7.0.1.tgz#e985886dfe42ddc73f9411e7cc591ad7d9b15911"
integrity sha512-4XaqE5v1dhE4TYrKSGG/VNUFqA31ADlqOnr6bd27E5MnaJLlY8ZAm3sue7EI9kEJ/i5KYov+Q4uS7JNDA5+cag==
"@dicebear/lorelei@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/lorelei/-/lorelei-7.0.1.tgz#3106ae79123eb1d1684ea29e82d614d26d72c7b0"
integrity sha512-3pyI2JF70PlqZUZEs5pVxmQWDJ2/bWmGG/iFtwsEh9HivtF8Zon4Er0NrsEoiKDvScyY4VGwl4LyUBc8JvNb9w==
"@dicebear/micah@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/micah/-/micah-7.0.1.tgz#7637beac297171694123d6f4722814aebc800d10"
integrity sha512-zHnEewRaREZGNTqnlZiSoha/wNFxEsVQ3E5QYpe9KB3rcLW4CVUgFAHjb449vniG6NfsAWzyAkOfhy4N6Zzw0g==
"@dicebear/miniavs@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/miniavs/-/miniavs-7.0.1.tgz#7e3fdc6085448caf08b43c8390e9691a7d990662"
integrity sha512-v0n2JT0N1I7vAGoi4NQ98IKtn4JgjwD2Gkqq7l5QAy0jzl1v289FfTng0cOrthroMGBQ5jPS0wUyI0TluoFZRw==
"@dicebear/notionists-neutral@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/notionists-neutral/-/notionists-neutral-7.0.1.tgz#6a916d0fd5b0d6d9ccca0bf3b14f8eec48a7bbc0"
integrity sha512-jRA7u2UU1I9EXzqBZL3vwI/V7pdDT60yB3bBjyD5J4TznT7bMwt7qEm1eV31U37mn3H+LTFiPD9/4G6whiU3nQ==
"@dicebear/notionists@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/notionists/-/notionists-7.0.1.tgz#83d635ddc8842f76dc9d45b9322e929c20cc7975"
integrity sha512-uEYBywouoUmvWtWARyeqAoQWX1DpvKL33dVxZ5K/ulYd/nXu9WHeFCPaP4tqE5II1XPS4khwneimFN6F1HA5NQ==
"@dicebear/open-peeps@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/open-peeps/-/open-peeps-7.0.1.tgz#eb78d2f02600dea4a55d21ec73ae3f321553c9cc"
integrity sha512-z1gXzd7XXLzSZpOrDPZmnJDXySCUEKmunRdRuWBSRrfIcVkgStZM0y8uuSrs3LpR8U2xcNJN9yO2wNRRWKmFEw==
"@dicebear/personas@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/personas/-/personas-7.0.1.tgz#74e494a401ac6126bb22d63ad398e44e3833fd5c"
integrity sha512-6/nsrN7JIlMqdH7UwhrACVoCEM3IVHkpMq2I0A1JbhmYp240TI8kM5xYSF0KRdOyAPbyDH/TEB8Uld4LKE+3wQ==
"@dicebear/pixel-art-neutral@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/pixel-art-neutral/-/pixel-art-neutral-7.0.1.tgz#1c1b11928afd9b8d789e5e885d37bf02b2dea880"
integrity sha512-+9RS0ohGDbPu+W2eGGk3LyzvFbM5qsuhCQR4qO7YIcvmODyNFPJ7eW9g/MHFVPLQXq60SCEUF5CEKY0xs4baUQ==
"@dicebear/pixel-art@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/pixel-art/-/pixel-art-7.0.1.tgz#3027b02feb5f8f3b9b56b24504ae11ea9539596d"
integrity sha512-9f17Ze4533CbHp23E+gRSSZdCUAB5/PieRq6/ZtVOnPI/PfglhhKMKSxQIm/H267gE2Y+VVhHpUTwGlbAgh1Lg==
"@dicebear/rings@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/rings/-/rings-7.0.1.tgz#643ca6499a8864174abd14e44549c158200ff9eb"
integrity sha512-6wsLE4kbkBGeaaEA/afIV0eNYYfIVXo60XgApJA7JdcwyvdTa9LE5Wcp2VBEsZYXdsT9Ml7BC4er/QyMqCayUw==
"@dicebear/shapes@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/shapes/-/shapes-7.0.1.tgz#77ca1e85a104378c9f18a6ab346cca7799de3e34"
integrity sha512-/ol+SazDlJYYe5pYaqKcnYDBjux+2Ny57hIrkHhonV0z4ny3Pq6c4Lq+hN3MnTBpKJszCXLrSP3uCbSQpjnkOg==
"@dicebear/thumbs@7.0.1":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@dicebear/thumbs/-/thumbs-7.0.1.tgz#5e3883ea5ece77d9e6dbf906a4a3de15467b7e50"
integrity sha512-eQYVJ8NN9buPfbd2Va0fY8sHRq9n1d7FJt/dL9xwimRGlpWh9lqS6gcHazuSHhSgnRHsHLANEiyboIcyhWh2Hg==
"@esbuild/android-arm64@0.19.8": "@esbuild/android-arm64@0.19.8":
version "0.19.8" version "0.19.8"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.8.tgz#fb7130103835b6d43ea499c3f30cfb2b2ed58456" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.8.tgz#fb7130103835b6d43ea499c3f30cfb2b2ed58456"
@ -280,6 +470,11 @@
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
"@types/json-schema@^7.0.11":
version "7.0.15"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
"@types/pug@^2.0.6": "@types/pug@^2.0.6":
version "2.0.10" version "2.0.10"
resolved "https://registry.yarnpkg.com/@types/pug/-/pug-2.0.10.tgz#52f8dbd6113517aef901db20b4f3fca543b88c1f" resolved "https://registry.yarnpkg.com/@types/pug/-/pug-2.0.10.tgz#52f8dbd6113517aef901db20b4f3fca543b88c1f"
@ -987,6 +1182,13 @@ rimraf@^2.5.2:
dependencies: dependencies:
glob "^7.1.3" glob "^7.1.3"
rimraf@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
dependencies:
glob "^7.1.3"
rollup@^4.2.0: rollup@^4.2.0:
version "4.6.1" version "4.6.1"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.6.1.tgz#351501c86b5b4f976dde8c5837516452b59921f8" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.6.1.tgz#351501c86b5b4f976dde8c5837516452b59921f8"
@ -1165,6 +1367,20 @@ thenify-all@^1.0.0:
dependencies: dependencies:
any-promise "^1.0.0" any-promise "^1.0.0"
tmp-promise@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-3.0.3.tgz#60a1a1cc98c988674fcbfd23b6e3367bdeac4ce7"
integrity sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==
dependencies:
tmp "^0.2.0"
tmp@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
dependencies:
rimraf "^3.0.0"
to-regex-range@^5.0.1: to-regex-range@^5.0.1:
version "5.0.1" version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"