diff --git a/.editorconfig b/.editorconfig index d22cd2f..cc17ce5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,10 +6,11 @@ end_of_line = lf indent_size = 4 indent_style = tab insert_final_newline = true -tab_width = 4 trim_trailing_whitespace = true +[*.md] +trim_trailing_whitespace = false + [*.{yml,yaml}] indent_size = 2 indent_style = space -tab_width = 2 diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..cac2c52 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "bradlc.vscode-tailwindcss", + "editorconfig.editorconfig", + ], +} diff --git a/package.json b/package.json index bbabeff..f3865fc 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "music-repo", - "license": "UNLICENSED", "private": true, "type": "module", + "license": "UNLICENSED", "scripts": { - "start:backend": "bun run packages/backend/src/index.ts", - "start:frontend": "pnpm --filter frontend exec vite --open" + "backend:dev": "bun run --watch packages/backend/src/app.ts", + "frontend:dev": "pnpm --filter frontend exec vite --open" }, "devDependencies": { "typescript": "catalog:" diff --git a/packages/backend/package.json b/packages/backend/package.json index 727b665..7bd41c7 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,18 +1,17 @@ { "name": "backend", - "license": "UNLICENSED", "private": true, "type": "module", + "license": "UNLICENSED", "devDependencies": { - "typescript": "catalog:", - "@types/bun": "latest" + "@types/bun": "catalog:", + "typescript": "catalog:" }, "dependencies": { - "@effect/schema": "catalog:", + "@elysiajs/cors": "catalog:", "common": "workspace:^", - "effect": "catalog:", - "fast-check": "catalog:", - "make-api": "workspace:^", - "ulid": "catalog:" + "elysia": "catalog:", + "kysely": "catalog:", + "kysely-bun-sqlite": "catalog:" } } diff --git a/packages/backend/src/RequestError.ts b/packages/backend/src/RequestError.ts deleted file mode 100644 index 661b72e..0000000 --- a/packages/backend/src/RequestError.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Data } from "effect"; - -export class RequestError extends Data.TaggedError("RequestError")<{ - readonly status: number, - readonly body?: string, -}> { - get response(): Response { - if (this.body) { - const body = new TextEncoder().encode(this.body); - return new Response(body, { - headers: { - "Content-Length": body.byteLength.toString(), - "Content-Type": "text/plain; charset=utf-8", - }, - status: this.status, - }); - } else { - return new Response(null, { status: this.status }); - } - } -} diff --git a/packages/backend/src/app.ts b/packages/backend/src/app.ts index ffacbc3..7dcdd4e 100644 --- a/packages/backend/src/app.ts +++ b/packages/backend/src/app.ts @@ -1,292 +1,228 @@ -import { Schema as S } from "@effect/schema"; -import { SessionId } from "common"; -import { CreatePiece, GetPieces, UpdatePiece, DeletePiece, Login, Logout, Me } from "common/api"; -import { AccessLog, SessionData } from "common/db"; -import { DateTime, Duration, Either as E, Effect, Match, Option as O, pipe } from "effect"; -import { constant } from "effect/Function"; -import { Api } from "make-api"; -import { brotliCompress } from "node:zlib"; -import { RequestError } from "./RequestError"; -import { Database } from "./services/database"; -import { Request } from "./services/request"; +import cors from "@elysiajs/cors"; +import { PieceId, RequestId, SessionId } from "common"; +import * as Function from "common/Function"; +import { Elysia, error, t } from "elysia"; +import { sql } from "kysely"; +import { generateSessionId, initDatabase } from "./database"; -const match = (api: Api.Api.Any) => Effect.gen(function* () { +const tbranded = () => t.Transform(t.String()) + .Decode(Function.unsafeCoerce) + .Encode(Function.unsafeCoerce); - const req = yield* Request; +const app = new Elysia() + .use(cors({ origin: "localhost:5173" })) + .decorate("db", await initDatabase()) + .resolve(async ({ db, cookie }) => { + await db + .deleteFrom("Session") + .where(sql`datetime()`, ">=", "expiresAt") + .execute(); - return req.method === api.method - && req.path.length === api.props.route.length - && api.props.route.every((token, i) => pipe( - Match.value(token), - Match.tags({ - Literal: ({ literal }) => req.path[i] === literal, - Param: ({ schema }) => E.isRight(S.decodeUnknownEither(schema)(req.path[i])), - }), - Match.exhaustive, - )); -}); - -const COOKIE_REGEX = /^([!#$%'*+.^_`|~a-z0-9-]+)\s*=\s*([!#$%&'()*+./:<=>?@[\]^_`{|}~a-z0-9-]+)/i; -const WEIGHTED_TOKEN_REGEX = /^([!#$%'*+.^_`|~a-z0-9-]+)\s*(?:;\s*q=(0(?:\.[0-9]{0,3})?|1(?:\.0{0,3})?))?$/i; - -const acceptsBrotli = Effect.gen(function* () { - const req = yield* Request; - - const acceptEncoding = req.headers["accept-encoding"]; - - /* NOTE According to RFC9110, section 12.5.3: - * - * If no Accept-Encoding header field is in the request, any content coding - * is considered acceptable by the user agent. - * - * This means that we could encode the response as brotli in the absence of - * Accept-Encoding header, but we'd rather be nice and assume the user agent - * does not support any encoding. - */ - if (!acceptEncoding) { - return false; - } - - const codings = acceptEncoding - .split(/\s*,\s*/) - .map((token) => token.match(WEIGHTED_TOKEN_REGEX)) - .filter((match) => match !== null) - .map((match) => ({ - coding: match[1], - ...(match[2] ? { quality: Number.parseFloat(match[2]) } : undefined), - })); - - return codings.some(({ coding, quality = 1 }) => coding === "br" && quality > 0); -}); - -const getCookie = (name: string): Effect.Effect, never, Request> => Effect.gen(function* () { - const req = yield* Request; - - const cookieString = req.headers["cookie"]; - - if (!cookieString) { - return O.none(); - } - - const cookieValue = cookieString - .split(/\s*;\s*/) - .map((cookie) => cookie.match(COOKIE_REGEX)) - .filter((match): match is RegExpMatchArray => match !== null && match[1] === name) - .map((match) => match[2])[0]; - - return O.fromNullable(cookieValue); -}); - -const requestJson = (schema: S.Schema) => { - const decoder = S.decodeUnknown(schema); - return pipe( - Request, - Effect.tap((req) => req.headers["content-type"] === "application/json" - ? Effect.void - : new RequestError({ status: 415 }) - ), - Effect.flatMap((req) => req.json), - Effect.flatMap(decoder), - Effect.mapError((error) => new RequestError({ status: 400, body: error.message })), - ); -}; - -export const app = pipe( - Effect.gen(function* () { - - const db = yield* Database; - const req = yield* Request; - - const timestamp = yield* DateTime.now; - - const accessLog = AccessLog.make({ - timestamp, - requestId: req.requestId, - method: req.method, - pathname: req.pathname, - query: req.query, - ip: O.getOrNull(req.ip), - }); - - yield* db.createAccessLog(accessLog); - console.log(`${DateTime.toDateUtc(accessLog.timestamp).toISOString()} ${accessLog.requestId} ${accessLog.method} ${accessLog.pathname}?${new URLSearchParams(accessLog.query).toString()} ${accessLog.ip}`); - - if (yield* match(CreatePiece)) { - return new Response(null, { status: 501 }); - } else if (yield* match(GetPieces)) { - return new Response(null, { status: 501 }); - } else if (yield* match(UpdatePiece)) { - return new Response(null, { status: 501 }); - } else if (yield* match(DeletePiece)) { - return new Response(null, { status: 501 }); - } else if (yield* match(Login)) { - - const body = yield* requestJson(Login.props.request.schema); - - const user = yield* pipe( - db.getUserByUsername(body.username), - Effect.catchTag("NoSuchElementException", () => new RequestError({ status: 401, body: "Invalid username or password" })), - ); - - const valid = yield* Effect.promise(() => Bun.password.verify(body.password, user.password)); - if (!valid) { - return yield* new RequestError({ status: 401, body: "Invalid username or password" }); - } - - const sessionData = SessionData.make({ userId: user.userId }); - const sessionId = yield* db.createSession(sessionData); - - const responseData = Login.props.response[200].schema.make({ - userId: user.userId, - username: user.username, - admin: user.admin, - }); - - const responseJson = yield* pipe( - responseData, - S.encode(Login.props.response[200].schema), - Effect.map(JSON.stringify), - ); - const responseArray = new TextEncoder().encode(responseJson); - - const expiresAt = DateTime.addDuration(yield* DateTime.now, Duration.days(7)); - const setCookie = `sessionId=${sessionId}; Expires=${DateTime.toDateUtc(expiresAt).toUTCString()}; HttpOnly; SameSite=None; Secure`; - - if (yield* acceptsBrotli) { - const responseBrotli = yield* Effect.async((callback) => { - brotliCompress(responseArray, (error, result) => { - if (error !== null) { - callback(Effect.die(error)); - } else { - callback(Effect.succeed(result)); - } - }); - }); - return new Response(responseBrotli, { - headers: { - "Content-Encoding": "br", - "Content-Length": responseArray.byteLength.toString(), - "Content-Type": "application/json", - "Set-Cookie": setCookie, - }, - }); - } else { - return new Response(responseArray, { - headers: { - "Content-Length": responseArray.byteLength.toString(), - "Content-Type": "application/json", - "Set-Cookie": setCookie, - } - }); - } - } else if (yield* match(Logout)) { - - const sessionId = yield* pipe( - getCookie("sessionId"), - Effect.flatten, - Effect.flatMap(S.decodeUnknown(SessionId)), - Effect.catchAll(constant(Effect.succeed(null))), - ); - - if (sessionId !== null) { - db.deleteSession(sessionId); - } - - const setCookie = `sessionId=; Expires=${new Date(0).toUTCString()}; HttpOnly; SameSite=None; Secure`; - return new Response(null, { - status: 204, - headers: { - "Set-Cookie": setCookie, - }, - }); - } else if (yield* match(Me)) { - - const sessionId = yield* pipe( - getCookie("sessionId"), - Effect.flatten, - Effect.flatMap(S.decodeUnknown(SessionId)), - Effect.mapError(() => new RequestError({ status: 401, body: "Session invalid or expired" })), - ); - - const sessionData = yield* pipe( - db.getAndRefreshSessionData(sessionId), - Effect.optionFromOptional, - Effect.map(O.getOrNull), - ); - - if (sessionData === null) { - const setCookie = `sessionId=; Expires=${new Date(0).toUTCString()}; HttpOnly; SameSite=None; Secure`; - return new Response(null, { - status: 401, - headers: { - "Set-Cookie": setCookie, - }, - }); - } - - const user = yield* pipe( - db.getUserById(sessionData.userId), - Effect.optionFromOptional, - Effect.map(O.getOrNull), - ); - - if (user === null) { - const setCookie = `sessionId=; Expires=${new Date(0).toUTCString()}; HttpOnly; SameSite=None; Secure`; - return new Response(null, { - status: 401, - headers: { - "Set-Cookie": setCookie, - }, - }); - } - - const responseData = Me.props.response[200].schema.make({ - userId: user.userId, - username: user.username, - admin: user.admin, - }); - - const responseJson = yield* pipe( - responseData, - S.encode(Me.props.response[200].schema), - Effect.map(JSON.stringify), - ); - const responseArray = new TextEncoder().encode(responseJson); - - const expiresAt = DateTime.addDuration(yield* DateTime.now, Duration.days(7)); - const setCookie = `sessionId=${sessionId}; Expires=${DateTime.toDateUtc(expiresAt).toUTCString()}; HttpOnly; SameSite=None; Secure`; - - if (yield* acceptsBrotli) { - const responseBrotli = yield* Effect.async((callback) => { - brotliCompress(responseArray, (error, result) => { - if (error !== null) { - callback(Effect.die(error)); - } else { - callback(Effect.succeed(result)); - } - }); - }); - return new Response(responseBrotli, { - headers: { - "Content-Encoding": "br", - "Content-Length": responseArray.byteLength.toString(), - "Content-Type": "application/json", - "Set-Cookie": setCookie, - }, - }); - } else { - return new Response(responseArray, { - headers: { - "Content-Length": responseArray.byteLength.toString(), - "Content-Type": "application/json", - "Set-Cookie": setCookie, - } - }); - } + const sessionId = cookie.sessionId.value; + if (sessionId === undefined) { + return { user: null }; } - return new Response(null, { status: 404 }); - }), - Effect.catchAllDefect(() => new RequestError({ status: 500 })), - Effect.catchTag("RequestError", (error) => Effect.succeed(error.response)), -); + const res = await db + .updateTable("Session") + .set({ expiresAt: sql`datetime('now', '+7 days') `}) + .where("sessionId", "=", SessionId(sessionId)) + .returning(["userId"]) + .executeTakeFirst(); + + if (res === undefined) { + return { user: null }; + } + + const user = await db + .selectFrom("User") + .selectAll() + .where("userId", "=", res.userId) + .executeTakeFirst(); + + if (user === undefined) { + return { user: null }; + } + + return { user }; + }) + .onTransform(async ({ db, request, server }) => { + + const requestId = RequestId(Bun.randomUUIDv7("hex")); + const timestamp = new Date().toISOString(); + const { method } = request; + const url = new URL(request.url); + const { pathname } = url; + const query = JSON.stringify(Object.fromEntries(url.searchParams.entries())); + const ip = server?.requestIP(request)?.address ?? null; + + await db + .insertInto("AccessLog") + .values({ requestId, timestamp, method, pathname, query, ip }) + .execute(); + + console.log(`${timestamp} ${method} ${request.url} ${ip}`); + }) + .get("/me", async ({ user }) => { + + if (user === null) { + return error("Unauthorized"); + } + + return { + userId: user.userId, + username: user.username, + admin: user.admin !== 0, + }; + }) + .post("/login", async ({ db, body: { username, password }, cookie }) => { + + const user = await db + .selectFrom("User") + .selectAll() + .where("username", "=", username) + .executeTakeFirst(); + + if (user === undefined) { + return error("Unauthorized", "Invalid username or password"); + } + + const valid = await Bun.password.verify(password, user.password); + if (!valid) { + return error("Unauthorized", "Invalid username or password"); + } + + const sessionId = generateSessionId(); + await db + .insertInto("Session") + .values({ sessionId, userId: user.userId, expiresAt: sql`datetime('now', '+7 days')` }) + .execute(); + + const expiresAt = new Date().getTime() + 604800000; + cookie.sessionId.set({ + value: sessionId, + expires: new Date(expiresAt), + httpOnly: true, + sameSite: "none", + secure: true, + }); + + return { + userId: user.userId, + username: user.username, + admin: user.admin !== 0, + }; + }, { + body: t.Object({ + username: t.String({ minLength: 1 }), + password: t.String({ minLength: 1 }), + }), + }) + .post("/logout", async ({ db, cookie, set }) => { + + set.status = "No Content"; + + const sessionCookie = cookie.sessionId; + sessionCookie.remove(); + + const sessionId = sessionCookie.value; + if (sessionId === undefined) { + return; + } + + await db + .deleteFrom("Session") + .where("sessionId", "=", SessionId(sessionId)) + .execute(); + }) + .post("/piece", async ({ db, body: { name, composer, lyricist, arranger }, user }) => { + + if (user === null) { + return error(401); + } + + const pieceId = PieceId(Bun.randomUUIDv7()); + + const res = await db + .insertInto("Piece") + .values({ pieceId, name, composer, lyricist, arranger, createdBy: user.userId, createdAt: sql`datetime()` }) + .returningAll() + .executeTakeFirstOrThrow(); + + return res; + }, { + body: t.Object({ + name: t.String({ minLength: 1 }), + composer: t.Nullable(t.String({ minLength: 1 })), + lyricist: t.Nullable(t.String({ minLength: 1 })), + arranger: t.Nullable(t.String({ minLength: 1 })), + }), + }) + .get("/piece", async ({ db, user }) => { + + if (user === null) { + return error(401); + } + + const res = await db + .selectFrom("Piece") + .selectAll() + .orderBy(["name", "composer", "arranger"]) + .execute(); + + return res; + }) + .put("/piece/:pieceId", async ({ db, body: { name, composer, lyricist, arranger }, params: { pieceId }, user }) => { + + if (user === null) { + return error(401); + } + + const res = await db + .updateTable("Piece") + .set({ name, composer, lyricist, arranger, modifiedBy: user.userId, modifiedAt: sql`datetime()` }) + .where("pieceId", "=", pieceId) + .returningAll() + .execute(); + + if (res.length === 0) { + return error("Not Found"); + } + + return res; + }, { + body: t.Object({ + name: t.String({ minLength: 1 }), + composer: t.Nullable(t.String({ minLength: 1 })), + lyricist: t.Nullable(t.String({ minLength: 1 })), + arranger: t.Nullable(t.String({ minLength: 1 })), + }), + params: t.Object({ + pieceId: tbranded(), + }) + }) + .delete("/piece/:pieceId", async ({ db, params: { pieceId }, set, user }) => { + + if (user === null) { + return error(401); + } + + const res = await db + .deleteFrom("Piece") + .where("pieceId", "=", pieceId) + .returningAll() + .execute(); + + if (res.length === 0) { + return error("Not Found"); + } + + set.status = "No Content"; + }, { + params: t.Object({ + pieceId: tbranded(), + }), + }) + .listen(process.env.PORT || 3000); + +export type App = typeof app; diff --git a/packages/backend/src/database.ts b/packages/backend/src/database.ts new file mode 100644 index 0000000..eca10ec --- /dev/null +++ b/packages/backend/src/database.ts @@ -0,0 +1,162 @@ +import { AttachmentId, PieceId, RequestId, SessionId, Sha256, UserId } from "common"; +import { ColumnType, CompiledQuery, CreateTableBuilder, Insertable, Kysely, Selectable, sql, Updateable } from "kysely"; +import { BunSqliteDialect } from "kysely-bun-sqlite"; +import { Database as BunSqliteDatabase } from "bun:sqlite"; + +export function generateSessionId(byteLength: number = 32): SessionId { + const array = new Uint8Array(byteLength); + crypto.getRandomValues(array); + const string = Buffer.from(array).toString("base64url"); + return SessionId(string); +}; + +export interface Database { + AccessLog: AccessLogTable; + Attachment: AttachmentTable; + File: FileTable; + Piece: PieceTable; + Session: SessionTable; + User: UserTable; +} + +export interface SystemInformation { + createdBy: ColumnType; + createdAt: ColumnType; + modifiedBy: ColumnType; + modifiedAt: ColumnType; +} + +export interface AccessLogTable { + requestId: ColumnType; + timestamp: ColumnType; + method: ColumnType; + pathname: ColumnType; + query: ColumnType; + ip: ColumnType; +} + +export interface Attachment { + pieceId: ColumnType; + sha256: Sha256; + filename: string; + mediaType: string; +} + +export interface AttachmentTable extends Attachment, SystemInformation { + attachmentId: ColumnType; +} + +export interface FileTable { + sha256: ColumnType; + data: ColumnType; +} + +export interface Piece { + name: string; + composer: string | null; + lyricist: string | null; + arranger: string | null; +} + +export interface PieceTable extends Piece, SystemInformation { + pieceId: ColumnType; +} + +export interface Session { + userId: UserId; +} + +export interface SessionTable extends Session { + sessionId: ColumnType; + expiresAt: string; +} + +export interface UserTable { + userId: ColumnType; + username: string; + password: string; + admin: number; +} + +function systemInformation(schema: CreateTableBuilder) { + return schema + .addColumn("createdBy", "text", (c) => c.references("User.userId").onDelete("set null").onUpdate("cascade")) + .addColumn("createdAt", "text", (c) => c.notNull()) + .addColumn("modifiedBy", "text", (c) => c.references("User.userId").onDelete("set null").onUpdate("cascade")) + .addColumn("modifiedAt", "text"); +} + +export async function initDatabase(filename: string = "db.sqlite3"): Promise> { + + const database = new BunSqliteDatabase(filename, { create: true, readwrite: true }); + const dialect = new BunSqliteDialect({ database }); + const db = new Kysely({ dialect }); + + await db.executeQuery(CompiledQuery.raw("PRAGMA foreign_keys = ON")); + + await db.schema + .createTable("AccessLog") + .ifNotExists() + .addColumn("requestId", "text", (c) => c.notNull().primaryKey()) + .addColumn("timestamp", "text", (c) => c.notNull()) + .addColumn("method", "text", (c) => c.notNull()) + .addColumn("pathname", "text", (c) => c.notNull()) + .addColumn("query", "text", (c) => c.notNull()) + .addColumn("ip", "text") + .execute(); + + await db.schema + .createIndex("AccessLog_timestamp") + .ifNotExists() + .on("AccessLog") + .column("timestamp") + .execute(); + + await db.schema + .createTable("User") + .ifNotExists() + .addColumn("userId", "text", (c) => c.notNull().primaryKey()) + .addColumn("username", "text", (c) => c.notNull().unique()) + .addColumn("password", "text", (c) => c.notNull()) + .addColumn("admin", "boolean", (c) => c.notNull()) + .execute(); + + await db.schema + .createTable("Piece") + .ifNotExists() + .addColumn("pieceId", "text", (c) => c.notNull().primaryKey()) + .addColumn("name", "text", (c) => c.notNull()) + .addColumn("composer", "text") + .addColumn("lyricist", "text") + .addColumn("arranger", "text") + .$call(systemInformation) + .execute(); + + await db.schema + .createIndex("Piece_name_composer_arranger") + .ifNotExists() + .on("Piece") + .columns(["name", "composer", "arranger"]) + .execute(); + + await db.schema + .createTable("Session") + .ifNotExists() + .addColumn("sessionId", "text", (c) => c.notNull().primaryKey()) + .addColumn("userId", "text", (c) => c.references("User.userId").onDelete("cascade").onUpdate("cascade")) + .addColumn("expiresAt", "text", (c) => c.notNull()) + .execute(); + + await db.schema + .createTable("Attachment") + .ifNotExists() + .addColumn("attachmentId", "text", (c) => c.notNull().primaryKey()) + .addColumn("pieceId", "text", (c) => c.notNull().references("Piece.pieceId").onDelete("cascade").onUpdate("cascade")) + .addColumn("sha256", "blob", (c) => c.notNull()) + .addColumn("filename", "text", (c) => c.notNull()) + .addColumn("mediaType", "text", (c) => c.notNull()) + .$call(systemInformation) + .execute(); + + return db; +} diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts deleted file mode 100644 index 91b1d2e..0000000 --- a/packages/backend/src/index.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { RequestId } from "common"; -import { Effect, Exit, Layer, ManagedRuntime, Option as O, pipe, Scope, unsafeCoerce } from "effect"; -import { ulid } from "ulid"; -import { app } from "./app"; -import { DatabaseLive } from "./services/database"; -import { Request, RequestInterface } from "./services/request"; -import { StorageFilesystem } from "./services/storage"; - -const scope = Effect.runSync(Scope.make()); - -const runtime = pipe( - StorageFilesystem("storage"), - Layer.merge(DatabaseLive()), - Layer.provide(Layer.succeed(Scope.Scope, scope)), - ManagedRuntime.make, -); - -const server = Bun.serve({ - fetch: (request, server) => { - - const url = new URL(request.url); - - const ip = pipe( - server.requestIP(request), - O.fromNullable, - O.map((a) => a.address), - ); - - const query = Object.freeze(Object.fromEntries(url.searchParams.entries())); - - const requestId = RequestId.make(ulid()); - const requestInterface = Object.freeze({ - requestId, - method: request.method, - pathname: url.pathname, - path: Object.freeze(url.pathname.slice(1).split("/")), - query, - headers: Object.freeze(Object.fromEntries(request.headers.entries())), - ip, - - json: Effect.tryPromise({ - try: () => request.json(), - catch: unsafeCoerce, - }), - }); - - const fiber = pipe( - app, - Effect.provideService(Request, requestInterface), - runtime.runFork, - ); - - return new Promise((resolve, reject) => { - fiber.addObserver(Exit.match({ - onSuccess: resolve, - onFailure: reject, - })); - }); - }, - websocket: { - message: () => { }, - }, -}); - -process.on("SIGINT", () => { - Effect.runFork(Effect.gen(function* () { - yield* runtime.disposeEffect; - yield* Scope.close(scope, Exit.void); - })); - server.stop(); -}); diff --git a/packages/backend/src/services/database.ts b/packages/backend/src/services/database.ts deleted file mode 100644 index f43fbe4..0000000 --- a/packages/backend/src/services/database.ts +++ /dev/null @@ -1,197 +0,0 @@ -import { Schema as S } from "@effect/schema"; -import { Database as SqliteDatabase } from "bun:sqlite"; -import { PieceId, SessionId, UserId } from "common"; -import { AccessLog, Piece, SessionData, User } from "common/db"; -import { Context, Effect, Layer, pipe, Option as O } from "effect"; -import { NoSuchElementException } from "effect/Cause"; -import { ulid } from "ulid"; - -export function generateSessionId(byteLength: number = 12): SessionId { - const array = new Uint8Array(byteLength); - crypto.getRandomValues(array); - const string = Buffer.from(array).toString("base64url"); - return SessionId.make(string); -} - -export interface DatabaseInterface { - readonly createAccessLog: (accessLog: AccessLog) => Effect.Effect; - - readonly createPiece: (name: string, composer: O.Option, lyricist: O.Option, arranger: O.Option, user: UserId) => Effect.Effect; - readonly getPieces: Effect.Effect; - readonly updatePiece: (pieceId: PieceId, name: string, composer: O.Option, lyricist: O.Option, arranger: O.Option, user: UserId) => Effect.Effect; - readonly deletePiece: (pieceId: PieceId) => Effect.Effect; - - readonly getUserByUsername: (username: string) => Effect.Effect; - readonly getUserById: (userId: UserId) => Effect.Effect; - - readonly createSession: (sessionData: SessionData) => Effect.Effect; - readonly getAndRefreshSessionData: (sessionId: SessionId) => Effect.Effect; - readonly deleteSession: (sessionId: SessionId) => Effect.Effect; -} - -export class Database extends Context.Tag("Database")() { } - -export const DatabaseLive = (filePath: string = "db.sqlite3") => Layer.effect(Database, pipe( - Effect.acquireRelease( - Effect.sync(() => new SqliteDatabase(filePath, { create: true, readwrite: true, strict: true })), - (db) => Effect.sync(() => db.close()), - ), - Effect.tap((db) => Effect.sync(() => { - const systemInformation = ` - createdBy TEXT REFERENCES User (userId) ON DELETE SET NULL ON UPDATE CASCADE, - createdAt TEXT NOT NULL, - modifiedBy TEXT REFERENCES User (userId) ON DELETE SET NULL ON UPDATE CASCADE, - modifiedAt TEXT - `; - - db.exec("PRAGMA foreign_keys = ON"); - - db.exec(`CREATE TABLE IF NOT EXISTS AccessLog ( - timestamp TEXT NOT NULL, - requestId TEXT NOT NULL, - method TEXT NOT NULL, - pathname TEXT NOT NULL, - query TEXT NOT NULL, - ip TEXT - )`); - - db.exec(`CREATE TABLE IF NOT EXISTS User ( - userId TEXT NOT NULL PRIMARY KEY, - username TEXT NOT NULL UNIQUE, - password TEXT NOT NULL, - admin BOOLEAN NOT NULL - )`); - - db.exec(`CREATE TABLE IF NOT EXISTS Piece ( - pieceId TEXT NOT NULL PRIMARY KEY, - name TEXT NOT NULL, - composer TEXT, - lyricist TEXT, - arranger TEXT, - ${systemInformation} - )`); - - db.exec(`CREATE TABLE IF NOT EXISTS Session ( - sessionId TEXT NOT NULL PRIMARY KEY, - userId TEXT NOT NULL REFERENCES User (userId) ON DELETE CASCADE ON UPDATE CASCADE, - expiresAt TEXT NOT NULL - )`); - - db.exec(`CREATE TABLE IF NOT EXISTS Attachment ( - attachmentId TEXT NOT NULL PRIMARY KEY, - pieceId TEXT NOT NULL REFERENCES Piece (pieceId) ON DELETE CASCADE ON UPDATE CASCADE, - sha256 BLOB NOT NULL, - filename TEXT NOT NULL, - mediaType TEXT NOT NULL, - ${systemInformation} - )`); - - const userCount = db.query("SELECT COUNT(*) FROM User").values()[0][0] as number; - if (userCount <= 0) { - const userId = UserId.make(ulid()); - const username = "admin"; - const password = Bun.password.hashSync("admin"); - const admin = true; - db.exec("INSERT INTO User (userId, username, password, admin) VALUES (?, ?, ?, ?)", userId, username, password, admin); - } - })), - Effect.map((db) => { - const createAccessLog = db.prepare< - never, - [timestamp: string, requestId: string, method: string, pathname: string, query: string, ip: string | null] - >("INSERT INTO AccessLog (timestamp, requestId, method, pathname, query, ip) VALUES (?, ?, ?, ?, ?, ?)"); - - const createPiece = db.prepare< - never, - [pieceId: PieceId, name: string, composer: string | null, lyricist: string | null, arranger: string | null, user: UserId] - >("INSERT INTO Piece (pieceId, name, composer, lyricist, arranger, createdBy, createdAt, modifiedBy, modifiedAt) VALUES (?1, ?2, ?3, ?4, ?5, ?6, datetime(), ?6, NULL)"); - const getPieces = db.prepare< - typeof Piece.Encoded, - [] - >("SELECT pieceId, name, composer, lyricist, arranger, createdBy, createdAt, modifiedBy, modifiedAt FROM Piece ORDER BY name, composer, arranger"); - const updatePiece = db.prepare< - never, - [pieceId: PieceId, name: string, composer: string | null, lyricist: string | null, arranger: string | null, user: UserId] - >("UPDATE Piece SET name = ?2, composer = ?3, lyricist = ?4, arranger = ?5, modifiedBy = ?6, modifiedAt = datetime() WHERE pieceId = ?1"); - const pieceExists = db.prepare("SELECT 1 FROM Piece WHERE PieceId = ?"); - const deletePiece = db.prepare("DELETE FROM Piece WHERE pieceId = ?"); - - const getUserByUsername = db.prepare< - { userId: string, username: string, password: string, admin: number }, - [username: string] - >("SELECT userId, username, password, admin FROM User WHERE username = ?"); - const getUserById = db.prepare< - { userId: string, username: string, password: string, admin: number }, - [userId: UserId] - >("SELECT userId, username, password, admin FROM User WHERE userId = ?"); - - const cleanupSessions = db.prepare("DELETE FROM Session WHERE datetime() >= expiresAt"); - const createSession = db.prepare< - never, - [sessionId: SessionId, userId: UserId] - >("INSERT INTO Session (sessionId, userId, expiresAt) VALUES (?, ?, datetime('now', '+7 days'))"); - const updateSession = db.prepare("UPDATE Session SET expiresAt = datetime('now', '+7 days') WHERE sessionId = ? RETURNING userId"); - const deleteSession = db.prepare("DELETE FROM Session WHERE sessionId = ?"); - - return Object.freeze({ - createAccessLog: (accessLog) => Effect.sync(() => { - const { timestamp, requestId, method, pathname, query, ip } = S.encodeSync(AccessLog)(accessLog); - createAccessLog.run(timestamp, requestId, method, pathname, query, ip); - }), - - createPiece: (name: string, composer: O.Option, lyricist: O.Option, arranger: O.Option, user: UserId) => Effect.sync(() => { - const pieceId = PieceId.make(ulid()); - createPiece.run(pieceId, name, O.getOrNull(composer), O.getOrNull(lyricist), O.getOrNull(arranger), user); - return pieceId; - }), - - getPieces: Effect.sync(() => { - const res = getPieces.all(); - const decoder = S.decodeSync(Piece); - return Object.freeze(res.map((encoded) => decoder(encoded))); - }), - - updatePiece: (pieceId: PieceId, name: string, composer: O.Option, lyricist: O.Option, arranger: O.Option, user: UserId) => Effect.suspend(() => { - updatePiece.run(pieceId, name, O.getOrNull(composer), O.getOrNull(lyricist), O.getOrNull(arranger), user); - const matched = pieceExists.get(pieceId) !== null; - return matched ? Effect.void : Effect.fail(new NoSuchElementException()); - }), - - deletePiece: (pieceId: PieceId) => Effect.suspend(() => { - const matched = deletePiece.run(pieceId).changes > 0; - return matched ? Effect.void : Effect.fail(new NoSuchElementException()); - }), - - getUserByUsername: (username) => Effect.suspend(() => { - const res = getUserByUsername.get(username); - if (res === null) return Effect.fail(new NoSuchElementException()); - return Effect.succeed(S.decodeSync(User)(res)); - }), - - getUserById: (userId) => Effect.suspend(() => { - const res = getUserById.get(userId); - if (res === null) return Effect.fail(new NoSuchElementException()); - return Effect.succeed(S.decodeSync(User)(res)); - }), - - createSession: ({ userId }) => Effect.sync(() => { - cleanupSessions.run(); - const sessionId = generateSessionId(); - createSession.run(sessionId, userId); - return sessionId; - }), - - getAndRefreshSessionData: (sessionId) => Effect.suspend(() => { - cleanupSessions.run(); - const res = updateSession.get(sessionId); - if (res === null) return Effect.fail(new NoSuchElementException()); - return Effect.succeed(S.decodeUnknownSync(SessionData)(res)); - }), - - deleteSession: (sessionId) => Effect.sync(() => { - cleanupSessions.run(); - deleteSession.run(sessionId); - }), - }); - }), -)); diff --git a/packages/backend/src/services/request.ts b/packages/backend/src/services/request.ts deleted file mode 100644 index 38d84d5..0000000 --- a/packages/backend/src/services/request.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { RequestId } from "common"; -import { Context, Effect, Option as O } from "effect"; - -export interface RequestInterface { - readonly requestId: RequestId; - readonly method: string; - readonly pathname: string; - readonly path: readonly string[]; - readonly query: { readonly [_: string]: string }; - readonly headers: { readonly [_: string]: string }; - readonly ip: O.Option; - - readonly json: Effect.Effect; -} - -export class Request extends Context.Tag("Request")() { } diff --git a/packages/backend/src/services/storage.ts b/packages/backend/src/services/storage.ts deleted file mode 100644 index 1346141..0000000 --- a/packages/backend/src/services/storage.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { Sha256 } from "common"; -import { Context, Data, Effect, Layer } from "effect"; -import { NoSuchElementException } from "effect/Cause"; -import { constant, flow } from "effect/Function"; -import path from "node:path"; - -export class StorageError extends Data.TaggedError("StorageError")<{ cause: unknown }> { } - -export interface StorageInterface { - /** - * @param sha256 SHA-256 of blob to read - * @returns Blob, if exists - */ - readonly read: (sha256: Sha256) => Effect.Effect; - /** - * @param data Blob to write - * @param sha256 Precomputed SHA-256, trusted to be accurate if provided - * @returns Precomputed SHA-256, if provided, internally computed SHA-256 - * otherwise - */ - readonly write: (data: Uint8Array, sha256?: Sha256) => Effect.Effect; -} - -export class Storage extends Context.Tag("Storage")() { } - -/** - * Storage implementation that uses the filesystem. - */ -export const StorageFilesystem = (baseDir: string = ".") => { - const sha256toFilePath = (sha256: Sha256): string => { - const sha256hex = Buffer.from(sha256).toString("hex"); - return path.join( - baseDir, - sha256hex.slice(0, 2), - sha256hex.slice(2, 4), - sha256hex.slice(4), - ); - } - - return Layer.succeed(Storage, Object.freeze({ - read: (sha256) => { - const filePath = sha256toFilePath(sha256); - return Effect.gen(function* () { - const arrayBuffer = yield* Effect.tryPromise({ - try: () => Bun.file(filePath).arrayBuffer(), - catch: (error) => new StorageError({ cause: error }), - }); - const array = new Uint8Array(arrayBuffer); - return array; - }); - }, - write: (data, sha256) => Effect.gen(function* () { - if (sha256 === undefined) { - sha256 = Sha256.make(new Uint8Array(Bun.SHA256.byteLength)); - Bun.SHA256.hash(data, sha256); - } - const filePath = sha256toFilePath(sha256); - yield* Effect.tryPromise({ - try: () => Bun.write(filePath, data), - catch: (error) => new StorageError({ cause: error }), - }); - return sha256; - }), - })); -}; - - -const sha256ToBase64 = (sha256: Sha256): string => { - return Buffer.from(sha256).toString("base64"); -} - -/** - * Storage that keeps all data in memory. - */ -export const StorageMemory = Layer.sync(Storage, () => { - const map = new Map(); - - return Object.freeze({ - read: flow( - sha256ToBase64, - _ => map.get(_), - Effect.fromNullable, - ), - write: (data, sha256) => Effect.sync(() => { - if (sha256 === undefined) { - sha256 = Sha256.make(new Uint8Array(Bun.SHA256.byteLength)); - Bun.SHA256.hash(data, sha256); - } - map.set(sha256ToBase64(sha256), data); - return sha256; - }), - }); -}); - -/** - * Storage that discards any writes silently and always fails to read. - */ -export const StorageEmpty = Layer.succeed(Storage, Object.freeze({ - read: constant(Effect.fail(new NoSuchElementException())), - write: (data, sha256) => Effect.sync(() => { - if (sha256 === undefined) { - sha256 = Sha256.make(new Uint8Array(Bun.SHA256.byteLength)); - Bun.SHA256.hash(data, sha256); - } - return sha256; - }), -})); diff --git a/packages/common/package.json b/packages/common/package.json index 99792d6..1a3f683 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -1,29 +1,13 @@ { "name": "common", - "license": "UNLICENSED", "private": true, "type": "module", + "license": "UNLICENSED", "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js" - }, - "./api": { - "types": "./dist/api.d.ts", - "import": "./dist/api.js" - }, - "./db": { - "types": "./dist/db.d.ts", - "import": "./dist/db.js" - } + ".": { "import": "./src/index.ts" }, + "./*": { "import": "./src/*.ts" } }, "devDependencies": { "typescript": "catalog:" - }, - "dependencies": { - "@effect/schema": "catalog:", - "effect": "catalog:", - "fast-check": "catalog:", - "make-api": "workspace:^" } } diff --git a/packages/common/src/Brand.ts b/packages/common/src/Brand.ts new file mode 100644 index 0000000..40e9976 --- /dev/null +++ b/packages/common/src/Brand.ts @@ -0,0 +1,35 @@ +import * as Function from "./Function"; +import * as Types from "./Types"; + +declare const BrandTypeId: unique symbol; +export type BrandTypeId = typeof BrandTypeId; + +declare const ConstructorTypeId: unique symbol; +export type ConstructorTypeId = typeof ConstructorTypeId; + +export interface Brand { + readonly [BrandTypeId]: { + readonly [k in K]: K; + } +} + +export declare namespace Brand { + export interface Constructor> { + readonly [ConstructorTypeId]: ConstructorTypeId; + (args: Brand.Unbranded): A; + } + + export type Unbranded

= P extends infer Q & Brands

? Q : P; + + export type Brands

= P extends Brand + ? Types.UnionToIntersection<{ + [k in keyof P[BrandTypeId]]: k extends string | symbol ? Brand : never + }[keyof P[BrandTypeId]]> + : never; +} + +export type Branded = A & Brand; + +export const nominal = >(): Brand.Constructor => { + return Function.identity as Brand.Constructor; +}; diff --git a/packages/common/src/Function.ts b/packages/common/src/Function.ts new file mode 100644 index 0000000..4dde3da --- /dev/null +++ b/packages/common/src/Function.ts @@ -0,0 +1,3 @@ +export const identity = (a: A): A => a; + +export const unsafeCoerce: (a: A) => B = identity as any; diff --git a/packages/common/src/Types.ts b/packages/common/src/Types.ts new file mode 100644 index 0000000..ac92a80 --- /dev/null +++ b/packages/common/src/Types.ts @@ -0,0 +1 @@ +export type UnionToIntersection = (T extends any ? (x: T) => any : never) extends (x: infer R) => any ? R : never; diff --git a/packages/common/src/api.ts b/packages/common/src/api.ts deleted file mode 100644 index 7e5a8a0..0000000 --- a/packages/common/src/api.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Api } from "make-api"; -import { Schema as S } from "@effect/schema"; -import { PieceId, UserId } from "common"; -import { pipe } from "effect"; -import { Piece } from "./db"; - -// --- PIECES ------------------------------------------------------------------ - -export const CreatePiece = pipe( - Api.make("POST", "piece"), - Api.requestBodyJson(S.Struct({ - name: S.NonEmptyString, - composer: S.Union(S.NonEmptyString, S.Null), - lyricist: S.Union(S.NonEmptyString, S.Null), - arranger: S.Union(S.NonEmptyString, S.Null), - })), - Api.responseBodyJson(201, Piece), - Api.responseBodyText(400, S.String), -); - -export const GetPieces = pipe( - Api.make("GET", "piece"), - Api.responseBodyJson(200, S.Array(Piece)), -); - -export const UpdatePiece = pipe( - Api.make("PUT", "piece", ["pieceId", PieceId]), - Api.requestBodyJson(S.Struct({ - name: S.NonEmptyString, - composer: S.Union(S.NonEmptyString, S.Null), - lyricist: S.Union(S.NonEmptyString, S.Null), - arranger: S.Union(S.NonEmptyString, S.Null), - })), - Api.responseBodyJson(200, Piece), - Api.responseBodyText(400, S.String), -); - -export const DeletePiece = pipe( - Api.make("DELETE", "piece", ["pieceId", PieceId]), - Api.responseBodyNone(200), - Api.responseBodyText(400, S.String), - Api.responseBodyText(404, S.String), -); - -// --- AUTHENTICATION ---------------------------------------------------------- - -export const Me = pipe( - Api.make("GET", "me"), - Api.responseBodyJson(200, S.Struct({ - userId: UserId, - username: S.NonEmptyString, - admin: S.Boolean, - })), - Api.responseBodyText(401, S.String), -); - -export const Logout = pipe( - Api.make("POST", "logout"), - Api.responseBodyNone(204), -); - -export const Login = pipe( - Api.make("POST", "login"), - Api.requestBodyJson(S.Struct({ - username: S.NonEmptyString, - password: S.NonEmptyString, - })), - Api.responseBodyJson(200, S.Struct({ - userId: UserId, - username: S.NonEmptyString, - admin: S.Boolean, - })), - Api.responseBodyText(400, S.String), - Api.responseBodyText(401, S.String), -); diff --git a/packages/common/src/db.ts b/packages/common/src/db.ts deleted file mode 100644 index 93d6fc1..0000000 --- a/packages/common/src/db.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Schema as S } from "@effect/schema"; -import { AttachmentId, BooleanFromNumber, PieceId, RequestId, SessionId, Sha256, UserId } from "common"; -import { Brand as B, pipe } from "effect"; - -export const SessionData = S.Struct({ - userId: UserId, -}); - -export type SessionData = typeof SessionData.Type; - -export const SystemInformation = S.Struct({ - createdBy: S.Union(UserId, S.Null), - createdAt: S.DateTimeUtc, - modifiedBy: S.Union(UserId, S.Null), - modifiedAt: S.DateTimeUtc, -}); - -export type SystemInformation = typeof SystemInformation.Type; - -// --- TABLES ------------------------------------------------------------------ - -export const AccessLog = S.Struct({ - timestamp: S.DateTimeUtc, - requestId: RequestId, - method: S.NonEmptyString, - pathname: S.NonEmptyString, - query: S.parseJson(S.Record({ - key: S.String, - value: S.String, - })), - ip: S.Union(S.NonEmptyString, S.Null), -}); - -export const Attachment = pipe( - S.Struct({ - attachmentId: AttachmentId, - pieceId: PieceId, - sha256: Sha256, - filename: S.NonEmptyString, - mediaType: S.NonEmptyString, - }), - S.extend(SystemInformation), -); - -export const Piece = pipe( - S.Struct({ - pieceId: PieceId, - name: S.NonEmptyString, - composer: S.Union(S.NonEmptyString, S.Null), - lyricist: S.Union(S.NonEmptyString, S.Null), - arranger: S.Union(S.NonEmptyString, S.Null), - }), - S.extend(SystemInformation), -); - -export const Session = pipe( - S.Struct({ - sessionId: SessionId, - expiresAt: S.DateTimeUtc, - }), - S.extend(SessionData), -); - -export const User = S.Struct({ - userId: UserId, - username: S.NonEmptyString, - password: S.NonEmptyString, - admin: BooleanFromNumber, -}); - -export type AccessLog = typeof AccessLog.Type; -export type Attachment = typeof Attachment.Type; -export type Piece = typeof Piece.Type; -export type Session = typeof Session.Type; -export type User = typeof User.Type; diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 5edd3ae..80a8004 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -1,33 +1,22 @@ -import { Schema as S } from "@effect/schema"; -import { Brand as B, pipe } from "effect"; +import * as Brand from "./Brand"; -export const AttachmentId = pipe(S.ULID, S.brand("AttachmentId")); -export const PieceId = pipe(S.ULID, S.brand("PieceId")); -export const RequestId = pipe(S.ULID, S.brand("RequestId")); -export const SessionId = pipe(S.NonEmptyString, S.brand("SessionId")); -export const UserId = pipe(S.ULID, S.brand("UserId")); +export type UUID = Brand.Branded; +export const UUID = Brand.nominal(); -export type AttachmentId = typeof AttachmentId.Type; -export type PieceId = typeof PieceId.Type; -export type RequestId = typeof RequestId.Type; -export type SessionId = typeof SessionId.Type; -export type UserId = typeof UserId.Type; +export type Sha256 = Brand.Branded; +export const Sha256 = Brand.nominal(); -export type Sha256 = B.Branded; -export const Sha256 = pipe( - S.Uint8ArrayFromSelf, - S.fromBrand(B.refined( - (array) => array.byteLength === 32, - () => B.error(`Expected Uint8Array to be 32 bytes long`), - )), -).annotations({ identifier: "SHA-256" }); +export type AttachmentId = Brand.Branded; +export const AttachmentId = Brand.nominal(); -export class BooleanFromNumber extends S.transform( - S.Number, - S.Boolean, - { - strict: true, - decode: (a) => a !== 0, - encode: (i) => i ? 1 : 0, - }, -).annotations({ identifier: "BooleanFromNumber" }) { } +export type PieceId = Brand.Branded; +export const PieceId = Brand.nominal(); + +export type RequestId = Brand.Branded; +export const RequestId = Brand.nominal(); + +export type SessionId = Brand.Branded; +export const SessionId = Brand.nominal(); + +export type UserId = Brand.Branded; +export const UserId = Brand.nominal(); diff --git a/packages/common/tsconfig.json b/packages/common/tsconfig.json index bf9b8f8..f52a4d1 100644 --- a/packages/common/tsconfig.json +++ b/packages/common/tsconfig.json @@ -1,6 +1,3 @@ { "extends": "../../tsconfig.base.json", - "references": [ - { "path": "../make-api" }, - ], } diff --git a/packages/frontend/index.html b/packages/frontend/index.html index 586c720..aee5219 100644 --- a/packages/frontend/index.html +++ b/packages/frontend/index.html @@ -1,10 +1,12 @@ - + Repozytorium muzyczne - + - + +

+ diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 1872cff..2849e28 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -1,21 +1,25 @@ { "name": "frontend", - "license": "UNLICENSED", "private": true, "type": "module", + "license": "UNLICENSED", "devDependencies": { - "@vanilla-extract/css": "catalog:", - "@vanilla-extract/vite-plugin": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@vitejs/plugin-react": "catalog:", + "autoprefixer": "catalog:", + "backend": "workspace:^", + "elysia": "catalog:", + "postcss": "catalog:", + "tailwindcss": "catalog:", "typescript": "catalog:", "vite": "catalog:" }, "dependencies": { - "@effect/schema": "catalog:", + "@elysiajs/eden": "catalog:", "common": "workspace:^", - "effect": "catalog:", - "fast-check": "catalog:", - "make-api": "workspace:^", - "preact": "catalog:", - "preact-iso": "catalog:" + "react": "catalog:", + "react-dom": "catalog:", + "react-router-dom": "catalog:" } } diff --git a/packages/frontend/postcss.config.js b/packages/frontend/postcss.config.js new file mode 100644 index 0000000..7b75c83 --- /dev/null +++ b/packages/frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/packages/frontend/src/App.tsx b/packages/frontend/src/App.tsx deleted file mode 100644 index efbb802..0000000 --- a/packages/frontend/src/App.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { ErrorBoundary, LocationProvider, Route, Router } from "preact-iso"; -import { Home } from "./routes/Home"; -import { Login } from "./routes/Login"; - -export const App = () => ( - - - - - - - - -); diff --git a/packages/frontend/src/app.tsx b/packages/frontend/src/app.tsx new file mode 100644 index 0000000..de4aca1 --- /dev/null +++ b/packages/frontend/src/app.tsx @@ -0,0 +1,26 @@ +import { Home } from "./routes/Home"; +import { Login } from "./routes/Login"; +import { createRoot } from "react-dom/client"; +import { StrictMode } from "react"; +import "./style.css"; +import { createBrowserRouter, RouterProvider } from "react-router-dom"; + +const router = createBrowserRouter([ + { + path: "/", + element: , + }, + { + path: "/login", + element: , + } +]); + +const rootElement = document.getElementById("root") as HTMLDivElement; +const root = createRoot(rootElement); + +root.render( + + + +); diff --git a/packages/frontend/src/client.ts b/packages/frontend/src/client.ts new file mode 100644 index 0000000..1c72668 --- /dev/null +++ b/packages/frontend/src/client.ts @@ -0,0 +1,4 @@ +import { treaty } from "@elysiajs/eden"; +import type { App } from "backend/app"; + +export const client = treaty("localhost:3000"); diff --git a/packages/frontend/src/index.css.ts b/packages/frontend/src/index.css.ts deleted file mode 100644 index 61eb243..0000000 --- a/packages/frontend/src/index.css.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { globalStyle } from "@vanilla-extract/css"; - -globalStyle("html, body", { - margin: 0, - padding: 0, - - width: "100%", - height: "100%", - overflow: "hidden", - - backgroundColor: "white", - color: "black", - - fontFamily: "system-ui, sans-serif", - fontSize: 16, - fontWeight: "normal", - - "@media": { - "(prefers-color-scheme: dark)": { - backgroundColor: "#1E1E1E", - color: "white", - }, - }, -}); - -globalStyle("input, button, select, textarea", { - border: "none", - outline: "none", - backgroundImage: "none", - backgroundColor: "transparent", - - fontFamily: "system-ui, sans-serif", - fontSize: 16, - fontWeight: "normal", - - color: "black", - - "@media": { - "(prefers-color-scheme: dark)": { - color: "white", - }, - }, -}); diff --git a/packages/frontend/src/index.tsx b/packages/frontend/src/index.tsx deleted file mode 100644 index ed53a05..0000000 --- a/packages/frontend/src/index.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { render } from "preact"; -import { App } from "./App"; - -import "./index.css"; - -render(, document.body); diff --git a/packages/frontend/src/routes/Home.css.ts b/packages/frontend/src/routes/Home.css.ts index 61aaf67..de8e054 100644 --- a/packages/frontend/src/routes/Home.css.ts +++ b/packages/frontend/src/routes/Home.css.ts @@ -1,31 +1,4 @@ -import { style } from "@vanilla-extract/css"; - -export const container = style({ - width: 1000, - maxWidth: "100%", - - margin: "0 auto", - - display: "flex", - flexDirection: "column", - alignItems: "stretch", -}); - -export const loading = style({ - padding: 8, - - textAlign: "center", -}); - -export const header = style({ - padding: 8, - - display: "flex", - justifyContent: "space-between", - alignItems: "baseline", -}); - -export const logout = style({ +export const logout = { padding: 8, backgroundColor: "#C0C0C0", @@ -83,4 +56,4 @@ export const logout = style({ borderBottomColor: "#202020", }, }, -}); +}; diff --git a/packages/frontend/src/routes/Home.tsx b/packages/frontend/src/routes/Home.tsx index aba72cf..9c2e6c7 100644 --- a/packages/frontend/src/routes/Home.tsx +++ b/packages/frontend/src/routes/Home.tsx @@ -1,79 +1,66 @@ -import { Schema as S } from "@effect/schema"; -import { Me } from "common/api"; -import { Effect, Fiber, Option as O, Option, pipe } from "effect"; -import { useLocation } from "preact-iso"; -import { useEffect, useMemo } from "preact/hooks"; +import { useEffect } from "react"; +import { useNavigate } from "react-router-dom"; +import { client } from "../client"; import { useStore } from "../store"; -import * as style from "./Home.css"; export const Home = () => { - const { route } = useLocation(); + const navigate = useNavigate(); - const user = Option.getOrNull(useStore(state => state.user)); + const user = useStore(state => state.user); const setUser = useStore(state => state.setUser); - useEffect(() => { + const init = async () => { if (user !== null) return; - const effect = Effect.gen(function* () { - const res = yield* Effect.promise((signal) => fetch("http://localhost:3000/me", { - method: "GET", - signal, - credentials: "include", - })); + const { data, error } = await client.me.get(); - if (!res.ok) { - route("/login"); - return; - } - - const responseData = yield* pipe( - Effect.promise(() => res.json()), - Effect.flatMap(S.decodeUnknown(Me.props.response[200].schema)), - Effect.orDie, - ); - - setUser(O.some(responseData)); - }); - - const fiber = Effect.runFork(effect); - return () => Effect.runFork(Fiber.interrupt(fiber), { immediate: true }); - }, []); - - const logoutEffect = useMemo(() => Effect.gen(function* () { - const res = yield* Effect.promise((signal) => fetch("http://localhost:3000/logout", { - method: "POST", - signal, - credentials: "include", - })); - - if (!res.ok) { - yield* Effect.die(new Error("Response was not ok")); + if (error !== null) { + navigate("/login"); + return; } - setUser(O.none()); + setUser(data); + }; - route("/login"); - }), []); + useEffect(() => { + init(); + }, []); - const onLogoutClick = () => { - Effect.runFork(logoutEffect); + const onLogoutClick = async () => { + const { data, error } = await client.logout.post(); + + if (error !== null) { + console.error("Response was not ok"); + } + + setUser(null); + navigate("/login"); }; if (user === null) { return ( -
-
Ładowanie…
+
+
Ładowanie…
); } return ( -
-
-
Użytkownik: {user.username}
-
+
+
+
+ Użytkownik: {user.username} +
+
+ +
); diff --git a/packages/frontend/src/routes/Login.css.ts b/packages/frontend/src/routes/Login.css.ts index e4b101e..b3317b3 100644 --- a/packages/frontend/src/routes/Login.css.ts +++ b/packages/frontend/src/routes/Login.css.ts @@ -1,83 +1,4 @@ -import { style } from "@vanilla-extract/css"; - -export const container = style({ - width: "100%", - height: "100%", - - display: "flex", - alignItems: "center", - justifyContent: "center", -}); - -export const box = style({ - padding: 8, - - display: "flex", - flexDirection: "column", - gap: 8, - - borderWidth: 1, - borderStyle: "solid", - borderColor: "black", - - borderRadius: 4, - - "@media": { - "(prefers-color-scheme: dark)": { - borderColor: "white", - }, - }, -}); - -export const header = style({ - paddingBottom: 8, - - borderBottomWidth: 1, - borderBottomStyle: "solid", - borderBottomColor: "black", - - textAlign: "center", - fontWeight: "bold", - - "@media": { - "(prefers-color-scheme: dark)": { - borderBottomColor: "white", - }, - }, -}); - -export const input = style({ - width: "32ch", - padding: 8, - - borderWidth: 1, - borderStyle: "solid", - borderColor: "black", - - borderRadius: 4, - - "selectors": { - "&:focus": { - outlineWidth: 2, - outlineStyle: "solid", - outlineColor: "#8080FF", - - "@media": { - "(prefers-color-scheme: dark)": { - outlineColor: "#C0C0FF", - }, - }, - }, - }, - - "@media": { - "(prefers-color-scheme: dark)": { - borderColor: "white", - }, - }, -}); - -export const submit = style({ +export const submit = { padding: 8, backgroundColor: "#C0C0C0", diff --git a/packages/frontend/src/routes/Login.tsx b/packages/frontend/src/routes/Login.tsx index ef90b0f..7614bda 100644 --- a/packages/frontend/src/routes/Login.tsx +++ b/packages/frontend/src/routes/Login.tsx @@ -1,14 +1,11 @@ -import { Schema as S } from "@effect/schema"; -import { Login as LoginApi } from "common/api"; -import { Effect, Fiber, Option as O, pipe } from "effect"; -import { useLocation } from "preact-iso"; -import { useId, useMemo, useRef } from "preact/hooks"; +import { FormEventHandler, useId } from "react"; +import { useNavigate } from "react-router-dom"; +import { client } from "../client"; import { useStore } from "../store"; -import * as style from "./Login.css"; export const Login = () => { - const { route } = useLocation(); + const navigate = useNavigate(); const loginUsername = useStore(state => state.loginUsername); const loginPassword = useStore(state => state.loginPassword); @@ -21,76 +18,55 @@ export const Login = () => { const usernameId = useId(); const passwordId = useId(); - const requestFiber = useRef | null>(null); - const requestEffect = useMemo(() => Effect.gen(function* () { - const requestData = LoginApi.props.request.schema.make({ username: loginUsername, password: loginPassword }); + const onSubmit: FormEventHandler = async (e) => { + e.preventDefault(); - const requestJson = yield* pipe( - requestData, - S.encode(LoginApi.props.request.schema), - Effect.map(JSON.stringify), - Effect.orDie, - ); + const { data, error } = await client.login.post({ + username: loginUsername, + password: loginPassword, + }); - const res = yield* Effect.promise((signal) => fetch("http://localhost:3000/login", { - method: "POST", - body: requestJson, - headers: { "Content-Type": "application/json" }, - signal, - credentials: "include", - })); - - if (!res.ok) { - yield* Effect.die(new Error("Response was not ok")); + if (error) { + console.error(error.value); + return; } - const responseData = yield* pipe( - Effect.promise(() => res.json()), - Effect.flatMap(S.decodeUnknown(LoginApi.props.response[200].schema)), - Effect.orDie, - ); - setLoginUsername(""); setLoginPassword(""); - setUser(O.some(responseData)); + setUser(data); - route("/"); - }), [loginUsername, loginPassword]); - - const onSubmit = (e: SubmitEvent) => { - e.preventDefault(); - - if (requestFiber.current !== null) { - Effect.runFork(Fiber.interrupt(requestFiber.current), { immediate: true }); - } - - requestFiber.current = Effect.runFork(requestEffect); + navigate("/"); }; return ( -
-
-
Repozytorium muzyczne
- +
+ +
Repozytorium muzyczne
+ setLoginUsername(e.currentTarget.value)} /> - + setLoginPassword(e.currentTarget.value)} /> - +
); diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index eb0b3fe..d2a6b41 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -1,6 +1,6 @@ import { UserId } from "common"; -import { identity, Option as O } from "effect"; -import { useLayoutEffect, useState } from "preact/hooks"; +import * as Function from "common/Function"; +import { useLayoutEffect, useState } from "react"; export type Update = T | ((prev: T) => T); export type Updater = (action: Update) => void; @@ -21,19 +21,19 @@ export interface Store { readonly loginUsername: string; readonly loginPassword: string; - readonly user: O.Option; + readonly user: Store.User | null; readonly setLoginUsername: Updater; readonly setLoginPassword: Updater; - readonly setUser: Updater>; + readonly setUser: Updater; } let store: Store = Object.freeze({ loginUsername: "", loginPassword: "", - user: O.none(), + user: null, setLoginUsername: (action) => set(mapProp("loginUsername", action)), setLoginPassword: (action) => set(mapProp("loginPassword", action)), @@ -78,14 +78,16 @@ function set(action: Partial | ((store: Store) => Partial), replac } } -export function useStore(selector: Selector = identity as Selector): T { +export function useStore(selector: Selector = Function.identity as Selector): T { const [state, setState] = useState(() => selector(store)); useLayoutEffect(() => { const listener = new Listener(selector, setState); listeners.add(listener); - return () => listeners.delete(listener); + return () => { + listeners.delete(listener); + }; }, []); return state; diff --git a/packages/frontend/src/style.css b/packages/frontend/src/style.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/packages/frontend/src/style.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/packages/frontend/src/vite.d.ts b/packages/frontend/src/vite.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/packages/frontend/src/vite.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/frontend/tailwind.config.js b/packages/frontend/tailwind.config.js new file mode 100644 index 0000000..94d9ddb --- /dev/null +++ b/packages/frontend/tailwind.config.js @@ -0,0 +1,11 @@ +/** @type {import("tailwindcss").Config} */ +export default { + content: [ + "./index.html", + "./src/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/packages/frontend/tsconfig.json b/packages/frontend/tsconfig.json index c71ee5d..a476017 100644 --- a/packages/frontend/tsconfig.json +++ b/packages/frontend/tsconfig.json @@ -1,6 +1,10 @@ { "extends": "../../tsconfig.base.json", + "compilerOptions": { + "types": ["react", "react-dom"], + }, "references": [ { "path": "../common" }, + { "path": "../backend" }, ], } diff --git a/packages/frontend/vite.config.js b/packages/frontend/vite.config.js deleted file mode 100644 index fb2c7c2..0000000 --- a/packages/frontend/vite.config.js +++ /dev/null @@ -1,13 +0,0 @@ -import { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin"; -import path from "node:path"; - -/** @type {import("vite").UserConfig} */ -export default { - plugins: [vanillaExtractPlugin()], - resolve: { - alias: { - "common": path.resolve(__dirname, "../common/src"), - "make-api": path.resolve(__dirname, "../make-api/src"), - }, - }, -}; diff --git a/packages/frontend/vite.config.ts b/packages/frontend/vite.config.ts new file mode 100644 index 0000000..e25138c --- /dev/null +++ b/packages/frontend/vite.config.ts @@ -0,0 +1,12 @@ +import react from "@vitejs/plugin-react"; +import path from "node:path"; +import { defineConfig } from "vite"; + +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + "common": path.resolve(__dirname, "../common/src"), + }, + }, +}); diff --git a/packages/make-api/package.json b/packages/make-api/package.json deleted file mode 100644 index 01a7e88..0000000 --- a/packages/make-api/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "make-api", - "license": "UNLICENSED", - "private": true, - "type": "module", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js" - } - }, - "devDependencies": { - "typescript": "catalog:" - }, - "dependencies": { - "@effect/schema": "catalog:", - "effect": "catalog:", - "fast-check": "catalog:" - } -} diff --git a/packages/make-api/src/Api.ts b/packages/make-api/src/Api.ts deleted file mode 100644 index cf4a114..0000000 --- a/packages/make-api/src/Api.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { Schema as S } from "@effect/schema"; -import type { Field } from "./Field"; -import type { Method } from "./Method"; -import type { MimeTypePredicate } from "./MimeType"; -import { QueryEmpty, type Query } from "./Query"; -import { RequestBodyFile, RequestBodyJson, RequestBodyMultipart, RequestBodyNone, RequestBodyText, RequestBodyUrlEncoded, type RequestBody } from "./RequestBody"; -import { ResponseBodyFile, ResponseBodyJson, ResponseBodyNone, ResponseBodyText, ResponseEmpty, type ResponseBody } from "./ResponseBody"; -import { Route, RouteLiteral, RouteParam } from "./Route"; - -export interface Api { - readonly method: Method; - readonly props: Props; -} - -export namespace Api { - export type Any = Api; - - export type Props = T extends Api ? Props : never; - - export type PropsAny = { - readonly route: Route.Any; - readonly request: RequestBody.Any; - readonly response: { readonly [_: number]: ResponseBody.Any }; - readonly query: Query.Any; - }; -} - -export const Api = (method: Method, props: Props): Api => Object.freeze>({ - method, - props, -}); - -// --- BUILDERS ---------------------------------------------------------------- - -export type RouteInputLiteral = Literal; - -export type RouteInputParam> = readonly [Name, Schema]; - -export namespace RouteInputLiteral { - export type Any = RouteInputLiteral; -} - -export namespace RouteInputParam { - export type Any = RouteInputParam>; -} - -export namespace RouteInput { - export type Any = readonly ( - | RouteInputLiteral.Any - | RouteInputParam.Any - )[]; - - export type Route = { readonly [K in keyof R]: - R[K] extends RouteInputLiteral ? RouteLiteral - : R[K] extends RouteInputParam ? RouteParam - : never; - }; -} - -export const make = (method: Method, ...routeInput: R): Api<{ - readonly route: RouteInput.Route, - readonly request: RequestBodyNone, - readonly response: {}, - readonly query: {}, -}> => Api(method, { - route: Route(...routeInput.map((r) => typeof r === "string" ? RouteLiteral(r) : RouteParam(r[0], r[1])) as RouteInput.Route), - request: RequestBodyNone, - response: ResponseEmpty, - query: QueryEmpty, -}); - -export const requestBodyText = >(schema: Schema) => - ({ method, props }: T): Api<{ - readonly route: T["props"]["route"], - readonly request: RequestBodyText, - readonly response: T["props"]["response"], - readonly query: T["props"]["query"], - }> => Api(method, { ...props, request: RequestBodyText(schema) }); - -export const requestBodyJson = (schema: Schema) => - ({ method, props }: T): Api<{ - readonly route: T["props"]["route"], - readonly request: RequestBodyJson, - readonly response: T["props"]["response"], - readonly query: T["props"]["query"], - }> => Api(method, { ...props, request: RequestBodyJson(schema) }); - -export const requestBodyUrlEncoded = (fields: Fields) => - ({ method, props }: T): Api<{ - readonly route: T["props"]["route"], - readonly request: RequestBodyUrlEncoded, - readonly response: T["props"]["response"], - readonly query: T["props"]["query"], - }> => Api(method, { ...props, request: RequestBodyUrlEncoded(fields) }); - -export const requestBodyMultipart = (fields: Fields) => - ({ method, props }: T): Api<{ - readonly route: T["props"]["route"], - readonly request: RequestBodyMultipart, - readonly response: T["props"]["response"], - readonly query: T["props"]["query"], - }> => Api(method, { ...props, request: RequestBodyMultipart(fields) }); - -export const requestBodyFile = (mimeType: MimeTypePredicate) => - ({ method, props }: T): Api<{ - readonly route: T["props"]["route"], - readonly request: RequestBodyFile, - readonly response: T["props"]["response"], - readonly query: T["props"]["query"], - }> => Api(method, { ...props, request: RequestBodyFile(mimeType) }); - -export const responseBodyNone = (status: Status) => - ({ method, props: { response, ...props } }: T): Api<{ - readonly route: T["props"]["route"], - readonly request: T["props"]["request"], - readonly response: { readonly [K in keyof T["props"]["response"] | Status]: K extends Status ? ResponseBodyNone : T["props"]["response"][K] }, - readonly query: T["props"]["query"], - }> => Api(method, { ...props, response: Object.freeze({ ...response, [status]: ResponseBodyNone }) }); - -export const responseBodyText = >(status: Status, schema: Schema) => - ({ method, props: { response, ...props } }: T): Api<{ - readonly route: T["props"]["route"], - readonly request: T["props"]["request"], - readonly response: { readonly [K in keyof T["props"]["response"] | Status]: K extends Status ? ResponseBodyText : T["props"]["response"][K] }, - readonly query: T["props"]["query"], - }> => Api(method, { ...props, response: Object.freeze({ ...response, [status]: ResponseBodyText(schema) }) }); - -export const responseBodyJson = (status: Status, schema: Schema) => - ({ method, props: { response, ...props } }: T): Api<{ - readonly route: T["props"]["route"], - readonly request: T["props"]["request"], - readonly response: { readonly [K in keyof T["props"]["response"] | Status]: K extends Status ? ResponseBodyJson : T["props"]["response"][K] }, - readonly query: T["props"]["query"], - }> => Api(method, { ...props, response: Object.freeze({ ...response, [status]: ResponseBodyJson(schema) }) }); - -export const responseBodyFile = (status: Status, mimeType: MimeTypePredicate) => - ({ method, props: { response, ...props } }: T): Api<{ - readonly route: T["props"]["route"], - readonly request: T["props"]["request"], - readonly response: { readonly [K in keyof T["props"]["response"] | Status]: K extends Status ? ResponseBodyFile : T["props"]["response"][K] }, - readonly query: T["props"]["query"], - }> => Api(method, { ...props, response: Object.freeze({ ...response, [status]: ResponseBodyFile(mimeType) }) }); - -export const query = (query: Query) => - ({ method, props: { query: _, ...props } }: T): Api<{ - readonly route: T["props"]["route"], - readonly request: T["props"]["request"], - readonly response: T["props"]["response"], - readonly query: Query, - }> => Api(method, { ...props, query }); diff --git a/packages/make-api/src/Field.ts b/packages/make-api/src/Field.ts deleted file mode 100644 index 63f0856..0000000 --- a/packages/make-api/src/Field.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Schema as S } from "@effect/schema"; -import type { MimeTypePredicate } from "./MimeType"; -import type { Multiplicity } from "./Multiplicity"; - -// --- INTERFACES -------------------------------------------------------------- - -export interface FieldText> { - readonly _tag: "Text"; - readonly multiplicity: M; - readonly schema: Schema; -} - -export interface FieldJson { - readonly _tag: "Json"; - readonly multiplicity: M; - readonly schema: Schema; -} - -export interface FieldFile { - readonly _tag: "File"; - readonly multiplicity: M; - readonly mimeType: MimeTypePredicate; -} - -export namespace FieldText { - export type Any = FieldText>; -} - -export namespace FieldJson { - export type Any = FieldJson; -} - -export namespace FieldFile { - export type Any = FieldFile; -} - -export namespace Field { - export type Any = - | FieldText.Any - | FieldJson.Any - | FieldFile.Any - ; - - export type AnyUrlEncoded = - | FieldText.Any - | FieldJson.Any - ; -} - -// --- CONSTRUCTORS ------------------------------------------------------------ - -export const FieldText = >(multiplicity: M, schema: Schema): FieldText => Object.freeze>({ - _tag: "Text", - multiplicity, - schema, -}); - -export const FieldJson = (multiplicity: M, schema: Schema): FieldJson => Object.freeze>({ - _tag: "Json", - multiplicity, - schema, -}); - -export const FieldFile = (multiplicity: M, mimeType: MimeTypePredicate): FieldFile => Object.freeze>({ - _tag: "File", - multiplicity, - mimeType, -}); diff --git a/packages/make-api/src/Method.ts b/packages/make-api/src/Method.ts deleted file mode 100644 index ffad978..0000000 --- a/packages/make-api/src/Method.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type Method = - | "GET" - | "POST" - | "PUT" - | "DELETE" - | "PATCH" - ; diff --git a/packages/make-api/src/MimeType.ts b/packages/make-api/src/MimeType.ts deleted file mode 100644 index c18b2fe..0000000 --- a/packages/make-api/src/MimeType.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { Predicate } from "effect" - -export type MimeTypePredicate = T | readonly T[] | Predicate.Refinement; diff --git a/packages/make-api/src/Multiplicity.ts b/packages/make-api/src/Multiplicity.ts deleted file mode 100644 index ff37349..0000000 --- a/packages/make-api/src/Multiplicity.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { Option as O } from "effect"; - -export type Multiplicity = - | "single" - | "optional" - | "multiple" - | "any" - ; - -export namespace Multiplicity { - export type With = { - single: T, - optional: O.Option, - multiple: readonly [T, ...T[]], - any: readonly T[], - }[M]; -} diff --git a/packages/make-api/src/Query.ts b/packages/make-api/src/Query.ts deleted file mode 100644 index 7b9571c..0000000 --- a/packages/make-api/src/Query.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Field } from "./Field"; - -export namespace Query { - export type Any = { readonly [_: string]: Field.AnyUrlEncoded }; -} - -export const QueryEmpty: {} = Object.freeze<{}>({}); diff --git a/packages/make-api/src/RequestBody.ts b/packages/make-api/src/RequestBody.ts deleted file mode 100644 index baaf6d3..0000000 --- a/packages/make-api/src/RequestBody.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { Schema as S } from "@effect/schema"; -import type { Field } from "./Field"; -import type { MimeTypePredicate } from "./MimeType"; - -// --- INTERFACES -------------------------------------------------------------- - -export interface RequestBodyNone { - readonly _tag: "None"; -} - -export interface RequestBodyText> { - readonly _tag: "Text"; - readonly schema: Schema; -} - -export interface RequestBodyJson { - readonly _tag: "Json"; - readonly schema: Schema; -} - -export interface RequestBodyUrlEncoded { - readonly _tag: "UrlEncoded"; - readonly fields: Readonly; -} - -export interface RequestBodyMultipart { - readonly _tag: "Multipart"; - readonly fields: Readonly; -} - -export interface RequestBodyFile { - readonly _tag: "File"; - readonly mimeType: MimeTypePredicate; -} - -export namespace RequestBodyText { - export type Any = RequestBodyText>; -} - -export namespace RequestBodyJson { - export type Any = RequestBodyJson; -} - -export namespace RequestBodyUrlEncoded { - export type Any = RequestBodyUrlEncoded<{}>; -} - -export namespace RequestBodyMultipart { - export type Any = RequestBodyMultipart<{}>; -} - -export namespace RequestBodyFile { - export type Any = RequestBodyFile; -} - -export namespace RequestBody { - export type Any = - | RequestBodyNone - | RequestBodyText.Any - | RequestBodyJson.Any - | RequestBodyUrlEncoded.Any - | RequestBodyMultipart.Any - | RequestBodyFile.Any - ; -} - -// --- CONSTRUCTORS ------------------------------------------------------------ - -export const RequestBodyNone: RequestBodyNone = Object.freeze({ - _tag: "None", -}); - -export const RequestBodyText = >(schema: Schema): RequestBodyText => Object.freeze>({ - _tag: "Text", - schema, -}); - -export const RequestBodyJson = (schema: Schema): RequestBodyJson => Object.freeze>({ - _tag: "Json", - schema, -}); - -export const RequestBodyUrlEncoded = (fields: Fields): RequestBodyUrlEncoded => Object.freeze>({ - _tag: "UrlEncoded", - fields, -}); - -export const RequestBodyMultipart = (fields: Fields): RequestBodyMultipart => Object.freeze>({ - _tag: "Multipart", - fields, -}); - -export const RequestBodyFile = (mimeType: MimeTypePredicate): RequestBodyFile => Object.freeze>({ - _tag: "File", - mimeType, -}); diff --git a/packages/make-api/src/ResponseBody.ts b/packages/make-api/src/ResponseBody.ts deleted file mode 100644 index 6e4b21e..0000000 --- a/packages/make-api/src/ResponseBody.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { Schema as S } from "@effect/schema"; -import type { MimeTypePredicate } from "./MimeType"; - -// --- INTERFACES -------------------------------------------------------------- - -export interface ResponseBodyNone { - readonly _tag: "None"; -} - -export interface ResponseBodyText> { - readonly _tag: "Text"; - readonly schema: Schema; -} - -export interface ResponseBodyJson { - readonly _tag: "Json"; - readonly schema: Schema; -} - -export interface ResponseBodyFile { - readonly _tag: "File"; - readonly mimeType: MimeTypePredicate; -} - -export namespace ResponseBodyText { - export type Any = ResponseBodyText>; -} - -export namespace ResponseBodyJson { - export type Any = ResponseBodyJson; -} - -export namespace ResponseBodyFile { - export type Any = ResponseBodyFile; -} - -export namespace ResponseBody { - export type Any = - | ResponseBodyNone - | ResponseBodyText.Any - | ResponseBodyJson.Any - | ResponseBodyFile.Any - ; -} - -// --- CONSTRUCTORS ------------------------------------------------------------ - -export const ResponseBodyNone: ResponseBodyNone = Object.freeze({ - _tag: "None", -}); - -export const ResponseBodyText = >(schema: Schema): ResponseBodyText => Object.freeze>({ - _tag: "Text", - schema, -}); - -export const ResponseBodyJson = (schema: Schema): ResponseBodyJson => Object.freeze>({ - _tag: "Json", - schema, -}); - -export const ResponseBodyFile = (mimeType: MimeTypePredicate): ResponseBodyFile => Object.freeze>({ - _tag: "File", - mimeType, -}); - -export const ResponseEmpty: {} = Object.freeze<{}>({}); diff --git a/packages/make-api/src/Route.ts b/packages/make-api/src/Route.ts deleted file mode 100644 index 4b87dbb..0000000 --- a/packages/make-api/src/Route.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Schema as S } from "@effect/schema"; - -// --- INTERFACES -------------------------------------------------------------- - -export interface RouteLiteral { - readonly _tag: "Literal"; - readonly literal: Literal; -} - -export interface RouteParam> { - readonly _tag: "Param"; - readonly name: Name; - readonly schema: Schema; -} - -export namespace RouteLiteral { - export type Any = RouteLiteral; -} - -export namespace RouteParam { - export type Any = RouteParam>; -} - -export namespace Route { - export type Any = readonly ( - | RouteLiteral.Any - | RouteParam.Any - )[]; -} - -// --- CONSTRUCTORS ------------------------------------------------------------ - -export const RouteLiteral = (literal: Literal): RouteLiteral => Object.freeze>({ - _tag: "Literal", - literal, -}); - -export const RouteParam = >(name: Name, schema: Schema): RouteParam => Object.freeze>({ - _tag: "Param", - name, - schema, -}); - -export const Route = (...route: Route): Route => Object.freeze(route); diff --git a/packages/make-api/src/index.ts b/packages/make-api/src/index.ts deleted file mode 100644 index f200a36..0000000 --- a/packages/make-api/src/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export * as Api from "./Api"; -export * from "./Field"; -export * from "./Method"; -export * from "./MimeType"; -export * from "./Multiplicity"; -export * from "./Query"; -export * from "./RequestBody"; -export * from "./ResponseBody"; -export * from "./Route"; diff --git a/packages/make-api/tsconfig.json b/packages/make-api/tsconfig.json deleted file mode 100644 index f52a4d1..0000000 --- a/packages/make-api/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0cee2cd..9033876 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,36 +6,57 @@ settings: catalogs: default: - '@effect/schema': - specifier: ^0.70.1 - version: 0.70.1 - '@vanilla-extract/css': - specifier: ^1.15.3 - version: 1.15.3 - '@vanilla-extract/vite-plugin': - specifier: ^4.0.13 - version: 4.0.13 - effect: - specifier: ^3.6.0 - version: 3.6.0 - fast-check: - specifier: ^3.20.0 - version: 3.20.0 - preact: - specifier: ^10.23.1 - version: 10.23.1 - preact-iso: - specifier: ^2.6.3 - version: 2.6.3 + '@elysiajs/cors': + specifier: ^1.1.1 + version: 1.1.1 + '@elysiajs/eden': + specifier: ^1.1.3 + version: 1.1.3 + '@types/bun': + specifier: ^1.1.13 + version: 1.1.13 + '@types/react': + specifier: ^18.3.12 + version: 18.3.12 + '@types/react-dom': + specifier: ^18.3.1 + version: 18.3.1 + '@vitejs/plugin-react': + specifier: ^4.3.3 + version: 4.3.3 + autoprefixer: + specifier: ^10.4.20 + version: 10.4.20 + elysia: + specifier: ^1.1.25 + version: 1.1.25 + kysely: + specifier: ^0.27.4 + version: 0.27.4 + kysely-bun-sqlite: + specifier: ^0.3.2 + version: 0.3.2 + postcss: + specifier: ^8.4.49 + version: 8.4.49 + react: + specifier: ^18.3.1 + version: 18.3.1 + react-dom: + specifier: ^18.3.1 + version: 18.3.1 + react-router-dom: + specifier: ^6.28.0 + version: 6.28.0 + tailwindcss: + specifier: ^3.4.15 + version: 3.4.15 typescript: - specifier: ^5.6.0-beta - version: 5.6.0-dev.20240802 - ulid: - specifier: ^2.3.0 - version: 2.3.0 + specifier: ^5.6.3 + version: 5.6.3 vite: - specifier: ^5.3.5 - version: 5.3.5 + specifier: ^5.4.11 + version: 5.4.11 importers: @@ -43,206 +64,186 @@ importers: devDependencies: typescript: specifier: 'catalog:' - version: 5.6.0-dev.20240802 + version: 5.6.3 packages/backend: dependencies: - '@effect/schema': + '@elysiajs/cors': specifier: 'catalog:' - version: 0.70.1(effect@3.6.0) + version: 1.1.1(elysia@1.1.25(@sinclair/typebox@0.33.7)(typescript@5.6.3)) common: specifier: workspace:^ version: link:../common - effect: + elysia: specifier: 'catalog:' - version: 3.6.0 - fast-check: + version: 1.1.25(@sinclair/typebox@0.33.7)(typescript@5.6.3) + kysely: specifier: 'catalog:' - version: 3.20.0 - make-api: - specifier: workspace:^ - version: link:../make-api - ulid: + version: 0.27.4 + kysely-bun-sqlite: specifier: 'catalog:' - version: 2.3.0 + version: 0.3.2(kysely@0.27.4) devDependencies: '@types/bun': - specifier: latest - version: 1.1.6 + specifier: 'catalog:' + version: 1.1.13 typescript: specifier: 'catalog:' - version: 5.6.0-dev.20240802 + version: 5.6.3 packages/common: - dependencies: - '@effect/schema': - specifier: 'catalog:' - version: 0.70.1(effect@3.6.0) - effect: - specifier: 'catalog:' - version: 3.6.0 - fast-check: - specifier: 'catalog:' - version: 3.20.0 - make-api: - specifier: workspace:^ - version: link:../make-api devDependencies: typescript: specifier: 'catalog:' - version: 5.6.0-dev.20240802 + version: 5.6.3 packages/frontend: dependencies: - '@effect/schema': + '@elysiajs/eden': specifier: 'catalog:' - version: 0.70.1(effect@3.6.0) + version: 1.1.3(elysia@1.1.25(@sinclair/typebox@0.33.7)(typescript@5.6.3)) common: specifier: workspace:^ version: link:../common - effect: + react: specifier: 'catalog:' - version: 3.6.0 - fast-check: + version: 18.3.1 + react-dom: specifier: 'catalog:' - version: 3.20.0 - make-api: - specifier: workspace:^ - version: link:../make-api - preact: + version: 18.3.1(react@18.3.1) + react-router-dom: specifier: 'catalog:' - version: 10.23.1 - preact-iso: - specifier: 'catalog:' - version: 2.6.3(preact-render-to-string@6.5.7(preact@10.23.1))(preact@10.23.1) + version: 6.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: - '@vanilla-extract/css': + '@types/react': specifier: 'catalog:' - version: 1.15.3 - '@vanilla-extract/vite-plugin': + version: 18.3.12 + '@types/react-dom': specifier: 'catalog:' - version: 4.0.13(@types/node@20.12.14)(vite@5.3.5(@types/node@20.12.14)) + version: 18.3.1 + '@vitejs/plugin-react': + specifier: 'catalog:' + version: 4.3.3(vite@5.4.11(@types/node@20.12.14)) + autoprefixer: + specifier: 'catalog:' + version: 10.4.20(postcss@8.4.49) + backend: + specifier: workspace:^ + version: link:../backend + elysia: + specifier: 'catalog:' + version: 1.1.25(@sinclair/typebox@0.33.7)(typescript@5.6.3) + postcss: + specifier: 'catalog:' + version: 8.4.49 + tailwindcss: + specifier: 'catalog:' + version: 3.4.15 typescript: specifier: 'catalog:' - version: 5.6.0-dev.20240802 + version: 5.6.3 vite: specifier: 'catalog:' - version: 5.3.5(@types/node@20.12.14) - - packages/make-api: - dependencies: - '@effect/schema': - specifier: 'catalog:' - version: 0.70.1(effect@3.6.0) - effect: - specifier: 'catalog:' - version: 3.6.0 - fast-check: - specifier: 'catalog:' - version: 3.20.0 - devDependencies: - typescript: - specifier: 'catalog:' - version: 5.6.0-dev.20240802 + version: 5.4.11(@types/node@20.12.14) packages: + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@babel/code-frame@7.24.7': - resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.25.2': - resolution: {integrity: sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==} + '@babel/compat-data@7.26.2': + resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==} engines: {node: '>=6.9.0'} - '@babel/core@7.25.2': - resolution: {integrity: sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==} + '@babel/core@7.26.0': + resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} engines: {node: '>=6.9.0'} - '@babel/generator@7.25.0': - resolution: {integrity: sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==} + '@babel/generator@7.26.2': + resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.25.2': - resolution: {integrity: sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==} + '@babel/helper-compilation-targets@7.25.9': + resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.24.7': - resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.25.2': - resolution: {integrity: sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==} + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-plugin-utils@7.24.8': - resolution: {integrity: sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==} + '@babel/helper-plugin-utils@7.25.9': + resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} engines: {node: '>=6.9.0'} - '@babel/helper-simple-access@7.24.7': - resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.24.8': - resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.24.7': - resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.24.8': - resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==} + '@babel/helpers@7.26.0': + resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.25.0': - resolution: {integrity: sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==} - engines: {node: '>=6.9.0'} - - '@babel/highlight@7.24.7': - resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.25.3': - resolution: {integrity: sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==} + '@babel/parser@7.26.2': + resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-syntax-typescript@7.24.7': - resolution: {integrity: sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==} + '@babel/plugin-transform-react-jsx-self@7.25.9': + resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.25.0': - resolution: {integrity: sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==} + '@babel/plugin-transform-react-jsx-source@7.25.9': + resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} engines: {node: '>=6.9.0'} - - '@babel/template@7.25.0': - resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.25.3': - resolution: {integrity: sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.25.2': - resolution: {integrity: sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==} - engines: {node: '>=6.9.0'} - - '@effect/schema@0.70.1': - resolution: {integrity: sha512-pxHAmOxWXUs7ZcHBTJUHcMg3ici65bOepxWV7cs//ujv1n9cLQJDQE8phUIzbxtROPcEbZwukGgJy7/HlBjx+w==} peerDependencies: - effect: ^3.6.0 + '@babel/core': ^7.0.0-0 - '@emotion/hash@0.9.2': - resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} + '@babel/template@7.25.9': + resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.25.9': + resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.26.0': + resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} + engines: {node: '>=6.9.0'} + + '@elysiajs/cors@1.1.1': + resolution: {integrity: sha512-Bl6JSURwbneaJqkq02bd0C/F8StkmU5zoPLpnSncy4DZSU8TDwWPXxmoHqozI3hf1piDaSQ+I21cmpjPlQ8uYQ==} + peerDependencies: + elysia: '>= 1.1.0' + + '@elysiajs/eden@1.1.3': + resolution: {integrity: sha512-N4AbnQ0q5dmpPLv+SHJc11EjOWUhSLGSpsWuMJ4Kg2NhoXzsZB/dPgjtgKJFIKcUdBmpS3k2YLiN/nrNzotNrA==} + peerDependencies: + elysia: '>= 1.1.0' '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} @@ -382,6 +383,10 @@ packages: cpu: [x64] os: [win32] + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} @@ -400,158 +405,253 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@rollup/rollup-android-arm-eabi@4.19.2': - resolution: {integrity: sha512-OHflWINKtoCFSpm/WmuQaWW4jeX+3Qt3XQDepkkiFTsoxFc5BpF3Z5aDxFZgBqRjO6ATP5+b1iilp4kGIZVWlA==} + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@remix-run/router@1.21.0': + resolution: {integrity: sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==} + engines: {node: '>=14.0.0'} + + '@rollup/rollup-android-arm-eabi@4.27.2': + resolution: {integrity: sha512-Tj+j7Pyzd15wAdSJswvs5CJzJNV+qqSUcr/aCD+jpQSBtXvGnV0pnrjoc8zFTe9fcKCatkpFpOO7yAzpO998HA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.19.2': - resolution: {integrity: sha512-k0OC/b14rNzMLDOE6QMBCjDRm3fQOHAL8Ldc9bxEWvMo4Ty9RY6rWmGetNTWhPo+/+FNd1lsQYRd0/1OSix36A==} + '@rollup/rollup-android-arm64@4.27.2': + resolution: {integrity: sha512-xsPeJgh2ThBpUqlLgRfiVYBEf/P1nWlWvReG+aBWfNv3XEBpa6ZCmxSVnxJgLgkNz4IbxpLy64h2gCmAAQLneQ==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.19.2': - resolution: {integrity: sha512-IIARRgWCNWMTeQH+kr/gFTHJccKzwEaI0YSvtqkEBPj7AshElFq89TyreKNFAGh5frLfDCbodnq+Ye3dqGKPBw==} + '@rollup/rollup-darwin-arm64@4.27.2': + resolution: {integrity: sha512-KnXU4m9MywuZFedL35Z3PuwiTSn/yqRIhrEA9j+7OSkji39NzVkgxuxTYg5F8ryGysq4iFADaU5osSizMXhU2A==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.19.2': - resolution: {integrity: sha512-52udDMFDv54BTAdnw+KXNF45QCvcJOcYGl3vQkp4vARyrcdI/cXH8VXTEv/8QWfd6Fru8QQuw1b2uNersXOL0g==} + '@rollup/rollup-darwin-x64@4.27.2': + resolution: {integrity: sha512-Hj77A3yTvUeCIx/Vi+4d4IbYhyTwtHj07lVzUgpUq9YpJSEiGJj4vXMKwzJ3w5zp5v3PFvpJNgc/J31smZey6g==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.19.2': - resolution: {integrity: sha512-r+SI2t8srMPYZeoa1w0o/AfoVt9akI1ihgazGYPQGRilVAkuzMGiTtexNZkrPkQsyFrvqq/ni8f3zOnHw4hUbA==} + '@rollup/rollup-freebsd-arm64@4.27.2': + resolution: {integrity: sha512-RjgKf5C3xbn8gxvCm5VgKZ4nn0pRAIe90J0/fdHUsgztd3+Zesb2lm2+r6uX4prV2eUByuxJNdt647/1KPRq5g==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.27.2': + resolution: {integrity: sha512-duq21FoXwQtuws+V9H6UZ+eCBc7fxSpMK1GQINKn3fAyd9DFYKPJNcUhdIKOrMFjLEJgQskoMoiuizMt+dl20g==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.27.2': + resolution: {integrity: sha512-6npqOKEPRZkLrMcvyC/32OzJ2srdPzCylJjiTJT2c0bwwSGm7nz2F9mNQ1WrAqCBZROcQn91Fno+khFhVijmFA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.19.2': - resolution: {integrity: sha512-+tYiL4QVjtI3KliKBGtUU7yhw0GMcJJuB9mLTCEauHEsqfk49gtUBXGtGP3h1LW8MbaTY6rSFIQV1XOBps1gBA==} + '@rollup/rollup-linux-arm-musleabihf@4.27.2': + resolution: {integrity: sha512-V9Xg6eXtgBtHq2jnuQwM/jr2mwe2EycnopO8cbOvpzFuySCGtKlPCI3Hj9xup/pJK5Q0388qfZZy2DqV2J8ftw==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.19.2': - resolution: {integrity: sha512-OR5DcvZiYN75mXDNQQxlQPTv4D+uNCUsmSCSY2FolLf9W5I4DSoJyg7z9Ea3TjKfhPSGgMJiey1aWvlWuBzMtg==} + '@rollup/rollup-linux-arm64-gnu@4.27.2': + resolution: {integrity: sha512-uCFX9gtZJoQl2xDTpRdseYuNqyKkuMDtH6zSrBTA28yTfKyjN9hQ2B04N5ynR8ILCoSDOrG/Eg+J2TtJ1e/CSA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.19.2': - resolution: {integrity: sha512-Hw3jSfWdUSauEYFBSFIte6I8m6jOj+3vifLg8EU3lreWulAUpch4JBjDMtlKosrBzkr0kwKgL9iCfjA8L3geoA==} + '@rollup/rollup-linux-arm64-musl@4.27.2': + resolution: {integrity: sha512-/PU9P+7Rkz8JFYDHIi+xzHabOu9qEWR07L5nWLIUsvserrxegZExKCi2jhMZRd0ATdboKylu/K5yAXbp7fYFvA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.19.2': - resolution: {integrity: sha512-rhjvoPBhBwVnJRq/+hi2Q3EMiVF538/o9dBuj9TVLclo9DuONqt5xfWSaE6MYiFKpo/lFPJ/iSI72rYWw5Hc7w==} + '@rollup/rollup-linux-powerpc64le-gnu@4.27.2': + resolution: {integrity: sha512-eCHmol/dT5odMYi/N0R0HC8V8QE40rEpkyje/ZAXJYNNoSfrObOvG/Mn+s1F/FJyB7co7UQZZf6FuWnN6a7f4g==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.19.2': - resolution: {integrity: sha512-EAz6vjPwHHs2qOCnpQkw4xs14XJq84I81sDRGPEjKPFVPBw7fwvtwhVjcZR6SLydCv8zNK8YGFblKWd/vRmP8g==} + '@rollup/rollup-linux-riscv64-gnu@4.27.2': + resolution: {integrity: sha512-DEP3Njr9/ADDln3kNi76PXonLMSSMiCir0VHXxmGSHxCxDfQ70oWjHcJGfiBugzaqmYdTC7Y+8Int6qbnxPBIQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.19.2': - resolution: {integrity: sha512-IJSUX1xb8k/zN9j2I7B5Re6B0NNJDJ1+soezjNojhT8DEVeDNptq2jgycCOpRhyGj0+xBn7Cq+PK7Q+nd2hxLA==} + '@rollup/rollup-linux-s390x-gnu@4.27.2': + resolution: {integrity: sha512-NHGo5i6IE/PtEPh5m0yw5OmPMpesFnzMIS/lzvN5vknnC1sXM5Z/id5VgcNPgpD+wHmIcuYYgW+Q53v+9s96lQ==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.19.2': - resolution: {integrity: sha512-OgaToJ8jSxTpgGkZSkwKE+JQGihdcaqnyHEFOSAU45utQ+yLruE1dkonB2SDI8t375wOKgNn8pQvaWY9kPzxDQ==} + '@rollup/rollup-linux-x64-gnu@4.27.2': + resolution: {integrity: sha512-PaW2DY5Tan+IFvNJGHDmUrORadbe/Ceh8tQxi8cmdQVCCYsLoQo2cuaSj+AU+YRX8M4ivS2vJ9UGaxfuNN7gmg==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.19.2': - resolution: {integrity: sha512-5V3mPpWkB066XZZBgSd1lwozBk7tmOkKtquyCJ6T4LN3mzKENXyBwWNQn8d0Ci81hvlBw5RoFgleVpL6aScLYg==} + '@rollup/rollup-linux-x64-musl@4.27.2': + resolution: {integrity: sha512-dOlWEMg2gI91Qx5I/HYqOD6iqlJspxLcS4Zlg3vjk1srE67z5T2Uz91yg/qA8sY0XcwQrFzWWiZhMNERylLrpQ==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.19.2': - resolution: {integrity: sha512-ayVstadfLeeXI9zUPiKRVT8qF55hm7hKa+0N1V6Vj+OTNFfKSoUxyZvzVvgtBxqSb5URQ8sK6fhwxr9/MLmxdA==} + '@rollup/rollup-win32-arm64-msvc@4.27.2': + resolution: {integrity: sha512-euMIv/4x5Y2/ImlbGl88mwKNXDsvzbWUlT7DFky76z2keajCtcbAsN9LUdmk31hAoVmJJYSThgdA0EsPeTr1+w==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.19.2': - resolution: {integrity: sha512-Mda7iG4fOLHNsPqjWSjANvNZYoW034yxgrndof0DwCy0D3FvTjeNo+HGE6oGWgvcLZNLlcp0hLEFcRs+UGsMLg==} + '@rollup/rollup-win32-ia32-msvc@4.27.2': + resolution: {integrity: sha512-RsnE6LQkUHlkC10RKngtHNLxb7scFykEbEwOFDjr3CeCMG+Rr+cKqlkKc2/wJ1u4u990urRHCbjz31x84PBrSQ==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.19.2': - resolution: {integrity: sha512-DPi0ubYhSow/00YqmG1jWm3qt1F8aXziHc/UNy8bo9cpCacqhuWu+iSq/fp2SyEQK7iYTZ60fBU9cat3MXTjIQ==} + '@rollup/rollup-win32-x64-msvc@4.27.2': + resolution: {integrity: sha512-foJM5vv+z2KQmn7emYdDLyTbkoO5bkHZE1oth2tWbQNGW7mX32d46Hz6T0MqXdWS2vBZhaEtHqdy9WYwGfiliA==} cpu: [x64] os: [win32] - '@types/bun@1.1.6': - resolution: {integrity: sha512-uJgKjTdX0GkWEHZzQzFsJkWp5+43ZS7HC8sZPFnOwnSo1AsNl2q9o2bFeS23disNDqbggEgyFkKCHl/w8iZsMA==} + '@sinclair/typebox@0.33.7': + resolution: {integrity: sha512-et38XPs6GMoB6XugH+Spp/HRv5gHYffw7rXC3caen/dIKC7Q6sqs6eEH9Yd9UKziUkOQdrLr9OXUULAc+pRMng==} - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.6.8': + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + + '@types/bun@1.1.13': + resolution: {integrity: sha512-KmQxSBgVWCl6RSuerlLGZlIWfdxkKqat0nxN61+qu4y1KDn0Ll3j7v1Pl8GnaL3a/U6GGWVTJh75ap62kR1E8Q==} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} '@types/node@20.12.14': resolution: {integrity: sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==} + '@types/prop-types@15.7.13': + resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} + + '@types/react-dom@18.3.1': + resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==} + + '@types/react@18.3.12': + resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==} + '@types/ws@8.5.12': resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==} - '@vanilla-extract/babel-plugin-debug-ids@1.0.6': - resolution: {integrity: sha512-C188vUEYmw41yxg3QooTs8r1IdbDQQ2mH7L5RkORBnHx74QlmsNfqVmKwAVTgrlYt8JoRaWMtPfGm/Ql0BNQrA==} - - '@vanilla-extract/css@1.15.3': - resolution: {integrity: sha512-mxoskDAxdQAspbkmQRxBvolUi1u1jnyy9WZGm+GeH8V2wwhEvndzl1QoK7w8JfA0WFevTxbev5d+i+xACZlPhA==} - - '@vanilla-extract/integration@7.1.7': - resolution: {integrity: sha512-xKwrCtmiBq6QzRNj+IOg5cAMRQRXkFnnvcE374MROJPnVvDX0d+lrIQapFGt64F0H8Gjk4kVl4slvCiV3ECQ4w==} - - '@vanilla-extract/private@1.0.5': - resolution: {integrity: sha512-6YXeOEKYTA3UV+RC8DeAjFk+/okoNz/h88R+McnzA2zpaVqTR/Ep+vszkWYlGBcMNO7vEkqbq5nT/JMMvhi+tw==} - - '@vanilla-extract/vite-plugin@4.0.13': - resolution: {integrity: sha512-JeACJlPtsWp/73Ke1Px/QvDA8M3GlBt4ZjWytSm7rYoKv1qEANSnvAZsAevIp56tTMJaqs++R3L7OkmnFeKhlw==} + '@vitejs/plugin-react@4.3.3': + resolution: {integrity: sha512-NooDe9GpHGqNns1i8XDERg0Vsg5SSYRhRxxyTGogUdkdNt47jal+fbuYi+Yfq6pzRCKXyoPcWisfxE6RIM3GKA==} + engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: - vite: ^4.0.3 || ^5.0.0 + vite: ^4.2.0 || ^5.0.0 - acorn@8.12.1: - resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} - engines: {node: '>=0.4.0'} + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + autoprefixer@10.4.20: + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} + engines: {node: ^10 || ^12 || >=14} hasBin: true + peerDependencies: + postcss: ^8.1.0 - ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} browserslist@4.23.3: resolution: {integrity: sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - bun-types@1.1.17: - resolution: {integrity: sha512-Z4+OplcSd/YZq7ZsrfD00DKJeCwuNY96a1IDJyR73+cTBaFIS7SC6LhpY/W3AMEXO9iYq5NJ58WAwnwL1p5vKg==} + browserslist@4.24.2: + resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} + bun-types@1.1.34: + resolution: {integrity: sha512-br5QygTEL/TwB4uQOb96Ky22j4Gq2WxWH/8Oqv20fk5HagwKXo/akB+LiYgSfzexCt6kkcUaVm+bKiPl71xPvw==} + + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} caniuse-lite@1.0.30001646: resolution: {integrity: sha512-dRg00gudiBDDTmUhClSdv3hqRfpbOnU28IpI1T6PBTLWa+kOj0681C8uML3PifYfREuBrVjDGhL3adYpBT6spw==} - chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} + caniuse-lite@1.0.30001680: + resolution: {integrity: sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==} - color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} - color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} - confbox@0.1.7: - resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - css-what@6.1.0: - resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} - engines: {node: '>= 6'} + cookie@1.0.1: + resolution: {integrity: sha512-Xd8lFX4LM9QEEwxQpF9J9NTUh8pmdJO0cyRJhFiDoLTk2eH8FXlRv2IFGYVadZpqI3j8fhNrSdKCeYPxiAhLXw==} + engines: {node: '>=18'} + + cross-spawn@7.0.5: + resolution: {integrity: sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==} + engines: {node: '>= 8'} cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} @@ -561,8 +661,8 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - debug@4.3.6: - resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -570,27 +670,39 @@ packages: supports-color: optional: true - dedent@1.5.3: - resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - deep-object-diff@1.1.9: - resolution: {integrity: sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==} + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - - effect@3.6.0: - resolution: {integrity: sha512-7bUV/Ytt058F3YWZJyra63MGA80msTk4AnFiVlvCM65RN7afc3LsvLOHpMifLqX/8CG0eDlJLg2lDLByyEnYGQ==} + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} electron-to-chromium@1.5.4: resolution: {integrity: sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==} + electron-to-chromium@1.5.62: + resolution: {integrity: sha512-t8c+zLmJHa9dJy96yBZRXGQYoiCEnHYgFwn1asvSPZSUdVxnB62A4RASd7k41ytG3ErFBA0TpHlKg9D9SQBmLg==} + + elysia@1.1.25: + resolution: {integrity: sha512-lBLUnhfD86q/0a5sNzWTiNuPsrW7ykGz8HoebybVfK+P1hjVwzzPkM/NtNnwPx7wrpd+D7UP7EyqeFPD4CPaQA==} + peerDependencies: + '@sinclair/typebox': '>= 0.32.0' + openapi-types: '>= 12.0.0' + typescript: '>= 5.0.0' + peerDependenciesMeta: + openapi-types: + optional: true + typescript: + optional: true + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} @@ -600,48 +712,103 @@ packages: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} - escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} - eval@0.1.8: - resolution: {integrity: sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==} - engines: {node: '>= 0.8'} + fast-decode-uri-component@1.0.1: + resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} - fast-check@3.20.0: - resolution: {integrity: sha512-pZIjqLpOZgdSLecec4GKC3Zq5702MZ34upMKxojnNVSWA0K64V3pXOBT1Wdsrc3AphLtzRBbsi8bRWF4TUGmUg==} - engines: {node: '>=8.0.0'} + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} - javascript-stringify@2.1.0: - resolution: {integrity: sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==} + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + hasBin: true js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} + jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} hasBin: true json5@2.2.3: @@ -649,24 +816,58 @@ packages: engines: {node: '>=6'} hasBin: true - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + kysely-bun-sqlite@0.3.2: + resolution: {integrity: sha512-YucMcOGGxNCmlAnkvNfTKZX6Bk1sYsuVVXlQN/5ZUgerlq/J9/EuR3aMOOZ25ASLM7oMglSxfeQxkiw0+hrEOQ==} + engines: {bun: '>=1'} + peerDependencies: + kysely: ^0.27.2 + + kysely@0.27.4: + resolution: {integrity: sha512-dyNKv2KRvYOQPLCAOCjjQuCk4YFd33BvGdf/o5bC7FiW+BB6snA81Zt+2wT9QDFzKqxKa5rrOmvlK/anehCcgA==} + engines: {node: '>=14.0.0'} + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - media-query-parser@2.0.2: - resolution: {integrity: sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w==} + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} - mlly@1.7.1: - resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} - modern-ahocorasick@1.0.1: - resolution: {integrity: sha512-yoe+JbhTClckZ67b2itRtistFKf8yPYelHLc7e5xAwtNAXxM6wJTUx2C7QeVSJFDzKT7bCIFyBVybPMKvmB9AA==} + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} @@ -676,85 +877,217 @@ packages: node-releases@2.0.18: resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} - pkg-types@1.1.3: - resolution: {integrity: sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - postcss@8.4.40: - resolution: {integrity: sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==} + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} - preact-iso@2.6.3: - resolution: {integrity: sha512-2JqNi+Elyt7rf0kULtMn/QskbZE10cDMrhmoanGKWJX3gOCTIfLt/ta5xWu+kQUsyInPkTQIVp3fS5Im0V+X8A==} + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: - preact: '>=10' - preact-render-to-string: '>=6.4.0' + react: ^18.3.1 - preact-render-to-string@6.5.7: - resolution: {integrity: sha512-nACZDdv/ZZciuldVYMcfGqr61DKJeaAfPx96hn6OXoBGhgtU2yGQkA0EpTzWH4SvnwF0syLsL4WK7AIp3Ruc1g==} + react-refresh@0.14.2: + resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} + engines: {node: '>=0.10.0'} + + react-router-dom@6.28.0: + resolution: {integrity: sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==} + engines: {node: '>=14.0.0'} peerDependencies: - preact: '>=10' + react: '>=16.8' + react-dom: '>=16.8' - preact@10.23.1: - resolution: {integrity: sha512-O5UdRsNh4vdZaTieWe3XOgSpdMAmkIYBCT3VhQDlKrzyCm8lUYsk0fmVEvoQQifoOjFRTaHZO69ylrzTW2BH+A==} + react-router@6.28.0: + resolution: {integrity: sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==} + engines: {node: '>=14.0.0'} + peerDependencies: + react: '>=16.8' - pure-rand@6.1.0: - resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} - require-like@0.1.2: - resolution: {integrity: sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==} + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} - rollup@4.19.2: - resolution: {integrity: sha512-6/jgnN1svF9PjNYJ4ya3l+cqutg49vOZ4rVgsDKxdl+5gpGPnByFXWGyfH9YGx9i3nfBwSu1Iyu6vGwFFA0BdQ==} + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup@4.27.2: + resolution: {integrity: sha512-KreA+PzWmk2yaFmZVwe6GB2uBD86nXl86OsDkt1bJS9p3vqWuEQ6HnJJ+j/mZi/q0920P99/MVRlB4L3crpF5w==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} - to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} - typescript@5.6.0-dev.20240802: - resolution: {integrity: sha512-aPQg1SL05JivtUdMmXq3BBa9NqhNbDvOlDPXvCf3K+kZ5jkxDdf2El6BLEkkzxkWOczoxma8l40ppGsC6pF40A==} - engines: {node: '>=14.17'} + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} hasBin: true - ufo@1.5.4: - resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} - ulid@2.3.0: - resolution: {integrity: sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==} + tailwindcss@3.4.15: + resolution: {integrity: sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==} + engines: {node: '>=14.0.0'} + hasBin: true + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + typescript@5.6.3: + resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} + engines: {node: '>=14.17'} hasBin: true undici-types@5.26.5: @@ -766,13 +1099,17 @@ packages: peerDependencies: browserslist: '>= 4.21.0' - vite-node@1.6.0: - resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} - engines: {node: ^18.0.0 || >=20.0.0} + update-browserslist-db@1.1.1: + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' - vite@5.3.5: - resolution: {integrity: sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==} + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vite@5.4.11: + resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -780,6 +1117,7 @@ packages: less: '*' lightningcss: ^1.21.0 sass: '*' + sass-embedded: '*' stylus: '*' sugarss: '*' terser: ^5.4.0 @@ -792,6 +1130,8 @@ packages: optional: true sass: optional: true + sass-embedded: + optional: true stylus: optional: true sugarss: @@ -799,149 +1139,153 @@ packages: terser: optional: true + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} + yaml@2.6.0: + resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==} + engines: {node: '>= 14'} + hasBin: true snapshots: + '@alloc/quick-lru@5.2.0': {} + '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@babel/code-frame@7.24.7': + '@babel/code-frame@7.26.2': dependencies: - '@babel/highlight': 7.24.7 - picocolors: 1.0.1 + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 - '@babel/compat-data@7.25.2': {} + '@babel/compat-data@7.26.2': {} - '@babel/core@7.25.2': + '@babel/core@7.26.0': dependencies: '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.25.0 - '@babel/helper-compilation-targets': 7.25.2 - '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) - '@babel/helpers': 7.25.0 - '@babel/parser': 7.25.3 - '@babel/template': 7.25.0 - '@babel/traverse': 7.25.3 - '@babel/types': 7.25.2 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.2 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helpers': 7.26.0 + '@babel/parser': 7.26.2 + '@babel/template': 7.25.9 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 convert-source-map: 2.0.0 - debug: 4.3.6 + debug: 4.3.7 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/generator@7.25.0': + '@babel/generator@7.26.2': dependencies: - '@babel/types': 7.25.2 + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 + jsesc: 3.0.2 - '@babel/helper-compilation-targets@7.25.2': + '@babel/helper-compilation-targets@7.25.9': dependencies: - '@babel/compat-data': 7.25.2 - '@babel/helper-validator-option': 7.24.8 - browserslist: 4.23.3 + '@babel/compat-data': 7.26.2 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.2 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-module-imports@7.24.7': + '@babel/helper-module-imports@7.25.9': dependencies: - '@babel/traverse': 7.25.3 - '@babel/types': 7.25.2 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.25.2(@babel/core@7.25.2)': + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-simple-access': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - '@babel/traverse': 7.25.3 + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.25.9 transitivePeerDependencies: - supports-color - '@babel/helper-plugin-utils@7.24.8': {} + '@babel/helper-plugin-utils@7.25.9': {} - '@babel/helper-simple-access@7.24.7': + '@babel/helper-string-parser@7.25.9': {} + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/helper-validator-option@7.25.9': {} + + '@babel/helpers@7.26.0': dependencies: - '@babel/traverse': 7.25.3 - '@babel/types': 7.25.2 - transitivePeerDependencies: - - supports-color + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 - '@babel/helper-string-parser@7.24.8': {} - - '@babel/helper-validator-identifier@7.24.7': {} - - '@babel/helper-validator-option@7.24.8': {} - - '@babel/helpers@7.25.0': + '@babel/parser@7.26.2': dependencies: - '@babel/template': 7.25.0 - '@babel/types': 7.25.2 + '@babel/types': 7.26.0 - '@babel/highlight@7.24.7': + '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/helper-validator-identifier': 7.24.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.0.1 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/parser@7.25.3': + '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/types': 7.25.2 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-typescript@7.24.7(@babel/core@7.25.2)': + '@babel/template@7.25.9': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 - '@babel/runtime@7.25.0': + '@babel/traverse@7.25.9': dependencies: - regenerator-runtime: 0.14.1 - - '@babel/template@7.25.0': - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/parser': 7.25.3 - '@babel/types': 7.25.2 - - '@babel/traverse@7.25.3': - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.25.0 - '@babel/parser': 7.25.3 - '@babel/template': 7.25.0 - '@babel/types': 7.25.2 - debug: 4.3.6 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.2 + '@babel/parser': 7.26.2 + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 + debug: 4.3.7 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.25.2': + '@babel/types@7.26.0': dependencies: - '@babel/helper-string-parser': 7.24.8 - '@babel/helper-validator-identifier': 7.24.7 - to-fast-properties: 2.0.0 + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 - '@effect/schema@0.70.1(effect@3.6.0)': + '@elysiajs/cors@1.1.1(elysia@1.1.25(@sinclair/typebox@0.33.7)(typescript@5.6.3))': dependencies: - effect: 3.6.0 - fast-check: 3.20.0 + elysia: 1.1.25(@sinclair/typebox@0.33.7)(typescript@5.6.3) - '@emotion/hash@0.9.2': {} + '@elysiajs/eden@1.1.3(elysia@1.1.25(@sinclair/typebox@0.33.7)(typescript@5.6.3))': + dependencies: + elysia: 1.1.25(@sinclair/typebox@0.33.7)(typescript@5.6.3) '@esbuild/aix-ppc64@0.21.5': optional: true @@ -1012,6 +1356,15 @@ snapshots: '@esbuild/win32-x64@0.21.5': optional: true + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 @@ -1029,137 +1382,176 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@rollup/rollup-android-arm-eabi@4.19.2': - optional: true - - '@rollup/rollup-android-arm64@4.19.2': - optional: true - - '@rollup/rollup-darwin-arm64@4.19.2': - optional: true - - '@rollup/rollup-darwin-x64@4.19.2': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.19.2': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.19.2': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.19.2': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.19.2': - optional: true - - '@rollup/rollup-linux-powerpc64le-gnu@4.19.2': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.19.2': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.19.2': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.19.2': - optional: true - - '@rollup/rollup-linux-x64-musl@4.19.2': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.19.2': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.19.2': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.19.2': - optional: true - - '@types/bun@1.1.6': + '@nodelib/fs.scandir@2.1.5': dependencies: - bun-types: 1.1.17 + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 - '@types/estree@1.0.5': {} + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@remix-run/router@1.21.0': {} + + '@rollup/rollup-android-arm-eabi@4.27.2': + optional: true + + '@rollup/rollup-android-arm64@4.27.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.27.2': + optional: true + + '@rollup/rollup-darwin-x64@4.27.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.27.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.27.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.27.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.27.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.27.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.27.2': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.27.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.27.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.27.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.27.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.27.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.27.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.27.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.27.2': + optional: true + + '@sinclair/typebox@0.33.7': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 + + '@types/babel__generator@7.6.8': + dependencies: + '@babel/types': 7.26.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 + + '@types/babel__traverse@7.20.6': + dependencies: + '@babel/types': 7.26.0 + + '@types/bun@1.1.13': + dependencies: + bun-types: 1.1.34 + + '@types/estree@1.0.6': {} '@types/node@20.12.14': dependencies: undici-types: 5.26.5 + '@types/prop-types@15.7.13': {} + + '@types/react-dom@18.3.1': + dependencies: + '@types/react': 18.3.12 + + '@types/react@18.3.12': + dependencies: + '@types/prop-types': 15.7.13 + csstype: 3.1.3 + '@types/ws@8.5.12': dependencies: '@types/node': 20.12.14 - '@vanilla-extract/babel-plugin-debug-ids@1.0.6': + '@vitejs/plugin-react@4.3.3(vite@5.4.11(@types/node@20.12.14))': dependencies: - '@babel/core': 7.25.2 + '@babel/core': 7.26.0 + '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0) + '@types/babel__core': 7.20.5 + react-refresh: 0.14.2 + vite: 5.4.11(@types/node@20.12.14) transitivePeerDependencies: - supports-color - '@vanilla-extract/css@1.15.3': + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@4.3.0: dependencies: - '@emotion/hash': 0.9.2 - '@vanilla-extract/private': 1.0.5 - css-what: 6.1.0 - cssesc: 3.0.0 - csstype: 3.1.3 - dedent: 1.5.3 - deep-object-diff: 1.1.9 - deepmerge: 4.3.1 - media-query-parser: 2.0.2 - modern-ahocorasick: 1.0.1 + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@5.0.2: {} + + autoprefixer@10.4.20(postcss@8.4.49): + dependencies: + browserslist: 4.23.3 + caniuse-lite: 1.0.30001646 + fraction.js: 4.3.7 + normalize-range: 0.1.2 picocolors: 1.0.1 - transitivePeerDependencies: - - babel-plugin-macros + postcss: 8.4.49 + postcss-value-parser: 4.2.0 - '@vanilla-extract/integration@7.1.7(@types/node@20.12.14)': + balanced-match@1.0.2: {} + + binary-extensions@2.3.0: {} + + brace-expansion@2.0.1: dependencies: - '@babel/core': 7.25.2 - '@babel/plugin-syntax-typescript': 7.24.7(@babel/core@7.25.2) - '@vanilla-extract/babel-plugin-debug-ids': 1.0.6 - '@vanilla-extract/css': 1.15.3 - dedent: 1.5.3 - esbuild: 0.21.5 - eval: 0.1.8 - find-up: 5.0.0 - javascript-stringify: 2.1.0 - mlly: 1.7.1 - vite: 5.3.5(@types/node@20.12.14) - vite-node: 1.6.0(@types/node@20.12.14) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser + balanced-match: 1.0.2 - '@vanilla-extract/private@1.0.5': {} - - '@vanilla-extract/vite-plugin@4.0.13(@types/node@20.12.14)(vite@5.3.5(@types/node@20.12.14))': + braces@3.0.3: dependencies: - '@vanilla-extract/integration': 7.1.7(@types/node@20.12.14) - vite: 5.3.5(@types/node@20.12.14) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - - acorn@8.12.1: {} - - ansi-styles@3.2.1: - dependencies: - color-convert: 1.9.3 + fill-range: 7.1.1 browserslist@4.23.3: dependencies: @@ -1168,51 +1560,84 @@ snapshots: node-releases: 2.0.18 update-browserslist-db: 1.1.0(browserslist@4.23.3) - bun-types@1.1.17: + browserslist@4.24.2: + dependencies: + caniuse-lite: 1.0.30001680 + electron-to-chromium: 1.5.62 + node-releases: 2.0.18 + update-browserslist-db: 1.1.1(browserslist@4.24.2) + + bun-types@1.1.34: dependencies: '@types/node': 20.12.14 '@types/ws': 8.5.12 - cac@6.7.14: {} + camelcase-css@2.0.1: {} caniuse-lite@1.0.30001646: {} - chalk@2.4.2: + caniuse-lite@1.0.30001680: {} + + chokidar@3.6.0: dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 - color-convert@1.9.3: + color-convert@2.0.1: dependencies: - color-name: 1.1.3 + color-name: 1.1.4 - color-name@1.1.3: {} + color-name@1.1.4: {} - confbox@0.1.7: {} + commander@4.1.1: {} convert-source-map@2.0.0: {} - css-what@6.1.0: {} + cookie@1.0.1: {} + + cross-spawn@7.0.5: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 cssesc@3.0.0: {} csstype@3.1.3: {} - debug@4.3.6: + debug@4.3.7: dependencies: - ms: 2.1.2 + ms: 2.1.3 - dedent@1.5.3: {} + didyoumean@1.2.2: {} - deep-object-diff@1.1.9: {} + dlv@1.1.3: {} - deepmerge@4.3.1: {} - - effect@3.6.0: {} + eastasianwidth@0.2.0: {} electron-to-chromium@1.5.4: {} + electron-to-chromium@1.5.62: {} + + elysia@1.1.25(@sinclair/typebox@0.33.7)(typescript@5.6.3): + dependencies: + '@sinclair/typebox': 0.33.7 + cookie: 1.0.1 + fast-decode-uri-component: 1.0.1 + optionalDependencies: + typescript: 5.6.3 + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -1241,146 +1666,371 @@ snapshots: escalade@3.1.2: {} - escape-string-regexp@1.0.5: {} + escalade@3.2.0: {} - eval@0.1.8: - dependencies: - '@types/node': 20.12.14 - require-like: 0.1.2 + fast-decode-uri-component@1.0.1: {} - fast-check@3.20.0: + fast-glob@3.3.2: dependencies: - pure-rand: 6.1.0 + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 - find-up@5.0.0: + fastq@1.17.1: dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 + reusify: 1.0.4 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.5 + signal-exit: 4.1.0 + + fraction.js@4.3.7: {} fsevents@2.3.3: optional: true + function-bind@1.1.2: {} + gensync@1.0.0-beta.2: {} + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + globals@11.12.0: {} - has-flag@3.0.0: {} + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 - javascript-stringify@2.1.0: {} + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-core-module@2.15.1: + dependencies: + hasown: 2.0.2 + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jiti@1.21.6: {} js-tokens@4.0.0: {} - jsesc@2.5.2: {} + jsesc@3.0.2: {} json5@2.2.3: {} - locate-path@6.0.0: + kysely-bun-sqlite@0.3.2(kysely@0.27.4): dependencies: - p-locate: 5.0.0 + bun-types: 1.1.34 + kysely: 0.27.4 + + kysely@0.27.4: {} + + lilconfig@2.1.0: {} + + lilconfig@3.1.2: {} + + lines-and-columns@1.2.4: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lru-cache@10.4.3: {} lru-cache@5.1.1: dependencies: yallist: 3.1.1 - media-query-parser@2.0.2: + merge2@1.4.1: {} + + micromatch@4.0.8: dependencies: - '@babel/runtime': 7.25.0 + braces: 3.0.3 + picomatch: 2.3.1 - mlly@1.7.1: + minimatch@9.0.5: dependencies: - acorn: 8.12.1 - pathe: 1.1.2 - pkg-types: 1.1.3 - ufo: 1.5.4 + brace-expansion: 2.0.1 - modern-ahocorasick@1.0.1: {} + minipass@7.1.2: {} - ms@2.1.2: {} + ms@2.1.3: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 nanoid@3.3.7: {} node-releases@2.0.18: {} - p-limit@3.1.0: + normalize-path@3.0.0: {} + + normalize-range@0.1.2: {} + + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + + package-json-from-dist@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - path-exists@4.0.0: {} - - pathe@1.1.2: {} + lru-cache: 10.4.3 + minipass: 7.1.2 picocolors@1.0.1: {} - pkg-types@1.1.3: - dependencies: - confbox: 0.1.7 - mlly: 1.7.1 - pathe: 1.1.2 + picocolors@1.1.1: {} - postcss@8.4.40: + picomatch@2.3.1: {} + + pify@2.3.0: {} + + pirates@4.0.6: {} + + postcss-import@15.1.0(postcss@8.4.49): + dependencies: + postcss: 8.4.49 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + + postcss-js@4.0.1(postcss@8.4.49): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.49 + + postcss-load-config@4.0.2(postcss@8.4.49): + dependencies: + lilconfig: 3.1.2 + yaml: 2.6.0 + optionalDependencies: + postcss: 8.4.49 + + postcss-nested@6.2.0(postcss@8.4.49): + dependencies: + postcss: 8.4.49 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.4.49: dependencies: nanoid: 3.3.7 - picocolors: 1.0.1 - source-map-js: 1.2.0 + picocolors: 1.1.1 + source-map-js: 1.2.1 - preact-iso@2.6.3(preact-render-to-string@6.5.7(preact@10.23.1))(preact@10.23.1): + queue-microtask@1.2.3: {} + + react-dom@18.3.1(react@18.3.1): dependencies: - preact: 10.23.1 - preact-render-to-string: 6.5.7(preact@10.23.1) + loose-envify: 1.4.0 + react: 18.3.1 + scheduler: 0.23.2 - preact-render-to-string@6.5.7(preact@10.23.1): + react-refresh@0.14.2: {} + + react-router-dom@6.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - preact: 10.23.1 + '@remix-run/router': 1.21.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-router: 6.28.0(react@18.3.1) - preact@10.23.1: {} - - pure-rand@6.1.0: {} - - regenerator-runtime@0.14.1: {} - - require-like@0.1.2: {} - - rollup@4.19.2: + react-router@6.28.0(react@18.3.1): dependencies: - '@types/estree': 1.0.5 + '@remix-run/router': 1.21.0 + react: 18.3.1 + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + resolve@1.22.8: + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.0.4: {} + + rollup@4.27.2: + dependencies: + '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.19.2 - '@rollup/rollup-android-arm64': 4.19.2 - '@rollup/rollup-darwin-arm64': 4.19.2 - '@rollup/rollup-darwin-x64': 4.19.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.19.2 - '@rollup/rollup-linux-arm-musleabihf': 4.19.2 - '@rollup/rollup-linux-arm64-gnu': 4.19.2 - '@rollup/rollup-linux-arm64-musl': 4.19.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.19.2 - '@rollup/rollup-linux-riscv64-gnu': 4.19.2 - '@rollup/rollup-linux-s390x-gnu': 4.19.2 - '@rollup/rollup-linux-x64-gnu': 4.19.2 - '@rollup/rollup-linux-x64-musl': 4.19.2 - '@rollup/rollup-win32-arm64-msvc': 4.19.2 - '@rollup/rollup-win32-ia32-msvc': 4.19.2 - '@rollup/rollup-win32-x64-msvc': 4.19.2 + '@rollup/rollup-android-arm-eabi': 4.27.2 + '@rollup/rollup-android-arm64': 4.27.2 + '@rollup/rollup-darwin-arm64': 4.27.2 + '@rollup/rollup-darwin-x64': 4.27.2 + '@rollup/rollup-freebsd-arm64': 4.27.2 + '@rollup/rollup-freebsd-x64': 4.27.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.27.2 + '@rollup/rollup-linux-arm-musleabihf': 4.27.2 + '@rollup/rollup-linux-arm64-gnu': 4.27.2 + '@rollup/rollup-linux-arm64-musl': 4.27.2 + '@rollup/rollup-linux-powerpc64le-gnu': 4.27.2 + '@rollup/rollup-linux-riscv64-gnu': 4.27.2 + '@rollup/rollup-linux-s390x-gnu': 4.27.2 + '@rollup/rollup-linux-x64-gnu': 4.27.2 + '@rollup/rollup-linux-x64-musl': 4.27.2 + '@rollup/rollup-win32-arm64-msvc': 4.27.2 + '@rollup/rollup-win32-ia32-msvc': 4.27.2 + '@rollup/rollup-win32-x64-msvc': 4.27.2 fsevents: 2.3.3 + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 + semver@6.3.1: {} - source-map-js@1.2.0: {} - - supports-color@5.5.0: + shebang-command@2.0.0: dependencies: - has-flag: 3.0.0 + shebang-regex: 3.0.0 - to-fast-properties@2.0.0: {} + shebang-regex@3.0.0: {} - typescript@5.6.0-dev.20240802: {} + signal-exit@4.1.0: {} - ufo@1.5.4: {} + source-map-js@1.2.1: {} - ulid@2.3.0: {} + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + + supports-preserve-symlinks-flag@1.0.0: {} + + tailwindcss@3.4.15: + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.6 + lilconfig: 2.1.0 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.4.49 + postcss-import: 15.1.0(postcss@8.4.49) + postcss-js: 4.0.1(postcss@8.4.49) + postcss-load-config: 4.0.2(postcss@8.4.49) + postcss-nested: 6.2.0(postcss@8.4.49) + postcss-selector-parser: 6.1.2 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + ts-interface-checker@0.1.13: {} + + typescript@5.6.3: {} undici-types@5.26.5: {} @@ -1390,32 +2040,39 @@ snapshots: escalade: 3.1.2 picocolors: 1.0.1 - vite-node@1.6.0(@types/node@20.12.14): + update-browserslist-db@1.1.1(browserslist@4.24.2): dependencies: - cac: 6.7.14 - debug: 4.3.6 - pathe: 1.1.2 - picocolors: 1.0.1 - vite: 5.3.5(@types/node@20.12.14) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser + browserslist: 4.24.2 + escalade: 3.2.0 + picocolors: 1.1.1 - vite@5.3.5(@types/node@20.12.14): + util-deprecate@1.0.2: {} + + vite@5.4.11(@types/node@20.12.14): dependencies: esbuild: 0.21.5 - postcss: 8.4.40 - rollup: 4.19.2 + postcss: 8.4.49 + rollup: 4.27.2 optionalDependencies: '@types/node': 20.12.14 fsevents: 2.3.3 + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + yallist@3.1.1: {} - yocto-queue@0.1.0: {} + yaml@2.6.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index be682c8..2727038 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,13 +2,20 @@ packages: - 'packages/*' catalog: - '@effect/schema': '^0.70.1' - '@vanilla-extract/css': '^1.15.3' - '@vanilla-extract/vite-plugin': '^4.0.13' - effect: '^3.6.0' - fast-check: '^3.20.0' - preact: '^10.23.1' - preact-iso: '^2.6.3' - typescript: '^5.6.0-beta' - ulid: '^2.3.0' - vite: '^5.3.5' + '@elysiajs/cors': '^1.1.1' + '@elysiajs/eden': '^1.1.3' + '@types/bun': '^1.1.13' + '@types/react': '^18.3.12' + '@types/react-dom': '^18.3.1' + '@vitejs/plugin-react': '^4.3.3' + autoprefixer: '^10.4.20' + elysia: '^1.1.25' + kysely: '^0.27.4' + kysely-bun-sqlite: '^0.3.2' + postcss: '^8.4.49' + react: '^18.3.1' + react-dom: '^18.3.1' + react-router-dom: '^6.28.0' + tailwindcss: '^3.4.15' + typescript: '^5.6.3' + vite: '^5.4.11' diff --git a/tsconfig.base.json b/tsconfig.base.json index 08f87d1..af9a578 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -7,8 +7,8 @@ "rootDir": "${configDir}/src", "outDir": "${configDir}/dist", - "module": "ES2020", - "moduleResolution": "Bundler", + "module": "ES2022", + "moduleResolution": "bundler", "moduleDetection": "force", "types": [], @@ -16,7 +16,6 @@ "target": "ES2022", "lib": ["ES2022", "DOM", "DOM.Iterable"], "jsx": "react-jsx", - "jsxImportSource": "preact", "strict": true, "exactOptionalPropertyTypes": true, @@ -28,9 +27,9 @@ "paths": { "common": ["./packages/common/src/index.ts"], - "common/api": ["./packages/common/src/api.ts"], - "common/db": ["./packages/common/src/db.ts"], - "make-api": ["./packages/make-api/src/index.ts"], + "common/*": ["./packages/common/src/*.ts"], + "backend": ["./packages/backend/src/index.ts"], + "backend/*": ["./packages/backend/src/*.ts"], }, }, "include": ["${configDir}/src"],