Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8709af48f8 |
@@ -27,9 +27,9 @@
|
||||
"@elysia/jwt": "^1.4.2",
|
||||
"@elysia/server-timing": "^1.4.1",
|
||||
"@elysiajs/cors": "^1.4.2",
|
||||
"@types/pg": "^8.23.1",
|
||||
"elysia": "^1.4.30",
|
||||
"kysely": "^0.29.6",
|
||||
"@types/pg": "^8.21.0",
|
||||
"elysia": "^1.4.29",
|
||||
"kysely": "^0.29.5",
|
||||
"ml-levenberg-marquardt": "^5.1.0",
|
||||
"pg": "^8.23.0",
|
||||
"zipcodes-us": "^1.1.3"
|
||||
|
||||
@@ -11,8 +11,6 @@ export async function up(db: Kysely<any>): Promise<void> {
|
||||
)
|
||||
.addColumn("discord_id", "text", (cb) => cb.unique())
|
||||
.addColumn("email", "text", (cb) => cb.unique())
|
||||
.addColumn("password_hash", "text")
|
||||
.addColumn("role", "text", (cb) => cb.notNull().defaultTo("user"))
|
||||
.addColumn("name", "text", (cb) => cb.notNull().defaultTo("Anonymous"))
|
||||
.addColumn("gender", "text")
|
||||
.execute();
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
|
||||
import { Kysely, sql } from 'kysely'
|
||||
import { addDefaultColumns } from '../db';
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
// TABLE: VERIFICATIONS
|
||||
await db.schema.createTable("verifications")
|
||||
.$call(addDefaultColumns)
|
||||
.addColumn("assessment_id", "bigint", (cb) => cb.notNull().unique())
|
||||
.addColumn("status", "text", (cb) => cb.notNull().defaultTo("request")) // request | in_review | action_requested | completed
|
||||
.addColumn("completed_at", "timestamptz")
|
||||
.addColumn("completed_by", "uuid")
|
||||
.addColumn("url_back_squat", "text")
|
||||
.addColumn("url_deadlift", "text")
|
||||
.addColumn("url_bench_press", "text")
|
||||
.addColumn("url_run", "text")
|
||||
.addColumn("url_broad_jump", "text")
|
||||
.addColumn("url_cone_drill", "text")
|
||||
.addColumn("verf_back_squat", "boolean")
|
||||
.addColumn("verf_deadlift", "boolean")
|
||||
.addColumn("verf_bench_press", "boolean")
|
||||
.addColumn("verf_run", "boolean")
|
||||
.addColumn("verf_broad_jump", "boolean")
|
||||
.addColumn("verf_cone_drill", "boolean")
|
||||
.addColumn("reviewer_notes", "text") // can be structured in the future, for now keep simple
|
||||
.addForeignKeyConstraint(
|
||||
"fk_verifications_assessment_id",
|
||||
["assessment_id"],
|
||||
"assessments",
|
||||
["id"],
|
||||
(cb) => cb.onDelete("cascade")
|
||||
)
|
||||
.addForeignKeyConstraint(
|
||||
"fk_verifications_completed_by",
|
||||
["completed_by"],
|
||||
"accounts",
|
||||
["id"],
|
||||
(cb) => cb.onDelete("restrict")
|
||||
)
|
||||
.addCheckConstraint(
|
||||
"chk_verifications_completed_fields",
|
||||
sql`status != 'completed' OR (completed_at IS NOT NULL AND completed_by IS NOT NULL)`
|
||||
)
|
||||
.execute()
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
// TABLE: VERIFICATIONS
|
||||
await db.schema.dropTable("verifications").ifExists().execute()
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import {
|
||||
StandardsConfigSchema,
|
||||
} from "@blade-and-brawn/calculator";
|
||||
import { Gender } from "@blade-and-brawn/domain";
|
||||
import { Value } from "@sinclair/typebox/value";
|
||||
import { db } from "./db";
|
||||
import { DEFAULT_NAME, env, log } from "../util";
|
||||
import standardsConfig from "./seed-data/standards-config.json" with {type: "json"};
|
||||
import type { AccountRole } from "../services/accounts";
|
||||
|
||||
Value.Assert(StandardsConfigSchema, standardsConfig);
|
||||
|
||||
@@ -69,26 +69,44 @@ async function seedCalculator(standardsConfigId: string): Promise<void> {
|
||||
log.info({ id: result.id }, "seeded default calculator");
|
||||
}
|
||||
|
||||
async function seedAdminAccount(): Promise<void> {
|
||||
async function seedAccounts(): Promise<void> {
|
||||
const ACCOUNT_NAME = "Xominus";
|
||||
|
||||
const existing = await db.selectFrom("accounts")
|
||||
.select(["id"])
|
||||
.where("email", "=", env.PUBLIC_ADMIN_EMAIL)
|
||||
.where("name", "=", ACCOUNT_NAME)
|
||||
.executeTakeFirst();
|
||||
if (existing) {
|
||||
log.info({ id: existing.id }, "admin account already seeded, skipping");
|
||||
log.info({ id: existing.id }, "default account already seeded, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
const account = await db.insertInto("accounts")
|
||||
.values({
|
||||
name: "Admin",
|
||||
email: env.PUBLIC_ADMIN_EMAIL,
|
||||
role: "admin" satisfies AccountRole,
|
||||
password_hash: env.ADMIN_PASSWORD_HASH
|
||||
name: ACCOUNT_NAME,
|
||||
discord_id: "1325552430942916731",
|
||||
email: "xominus@bladeandbrawn.com"
|
||||
})
|
||||
.returning("id")
|
||||
.executeTakeFirstOrThrow();
|
||||
log.info({ id: account.id }, "seeded admin account");
|
||||
log.info({ id: account.id }, "seeded default account");
|
||||
|
||||
await db.insertInto("assessments")
|
||||
.values({
|
||||
account_id: account.id,
|
||||
name: ACCOUNT_NAME,
|
||||
gender: Gender.Male,
|
||||
age: 25,
|
||||
weight: 80,
|
||||
perf_back_squat: 72.57472,
|
||||
perf_deadlift: 127.00576,
|
||||
perf_bench_press: 102.0582,
|
||||
perf_run: 446000,
|
||||
perf_broad_jump: 185.42000000000002,
|
||||
perf_cone_drill: 9870,
|
||||
})
|
||||
.execute();
|
||||
log.info({ accountId: account.id }, "seeded placeholder assessment");
|
||||
}
|
||||
|
||||
(async () => {
|
||||
@@ -103,7 +121,7 @@ async function seedAdminAccount(): Promise<void> {
|
||||
const datasetId = await seedStandardsDataset();
|
||||
const standardsConfigId = await seedStandardsConfig(datasetId);
|
||||
await seedCalculator(standardsConfigId);
|
||||
await seedAdminAccount();
|
||||
await seedAccounts();
|
||||
log.info("seed finished");
|
||||
}
|
||||
catch (err) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Printful, PrintfulClient, PrintfulError, Webflow, WebflowClient, Webflo
|
||||
import { env } from "../util";
|
||||
|
||||
const DOMAIN = env.NODE_ENV === "development" ?
|
||||
"dev-api.bladeandbrawn.com" :
|
||||
"dev.api.bladeandbrawn.com" :
|
||||
"api.bladeandbrawn.com";
|
||||
|
||||
const PRINTFUL_WEBHOOK_URL = env.NODE_ENV === "development" ?
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
import { Activity, Gender, inToCm, lbToKg, minToMs, secToMs } from "@blade-and-brawn/domain";
|
||||
import { db } from "../database/db";
|
||||
import { env, log } from "../util";
|
||||
import type { AccountRole } from "../services/accounts";
|
||||
import { VerificationsService } from "../services/verifications";
|
||||
|
||||
const TEST_DISCORD_ID = "test-verification-seed";
|
||||
const TEST_ASSESSMENT_NAME = "Test Verification Player";
|
||||
|
||||
async function seedTestAccount(): Promise<string> {
|
||||
const existing = await db.selectFrom("accounts")
|
||||
.select("id")
|
||||
.where("discord_id", "=", TEST_DISCORD_ID)
|
||||
.executeTakeFirst();
|
||||
if (existing) {
|
||||
log.info({ id: existing.id }, "test account already seeded, reusing");
|
||||
return existing.id;
|
||||
}
|
||||
|
||||
const account = await db.insertInto("accounts")
|
||||
.values({
|
||||
discord_id: TEST_DISCORD_ID,
|
||||
name: "Test Player",
|
||||
role: "user" satisfies AccountRole,
|
||||
})
|
||||
.returning("id")
|
||||
.executeTakeFirstOrThrow();
|
||||
log.info({ id: account.id }, "seeded test account");
|
||||
return account.id;
|
||||
}
|
||||
|
||||
async function seedTestAssessment(accountId: string): Promise<string> {
|
||||
const existing = await db.selectFrom("assessments")
|
||||
.select("id")
|
||||
.where("account_id", "=", accountId)
|
||||
.where("name", "=", TEST_ASSESSMENT_NAME)
|
||||
.executeTakeFirst();
|
||||
if (existing) {
|
||||
log.info({ id: existing.id }, "test assessment already seeded, reusing");
|
||||
return existing.id;
|
||||
}
|
||||
|
||||
const result = await db.insertInto("assessments")
|
||||
.values({
|
||||
account_id: accountId,
|
||||
name: TEST_ASSESSMENT_NAME,
|
||||
gender: Gender.Male,
|
||||
age: 22,
|
||||
weight: lbToKg(180),
|
||||
perf_back_squat: lbToKg(225),
|
||||
perf_deadlift: lbToKg(315),
|
||||
perf_bench_press: lbToKg(185),
|
||||
perf_broad_jump: inToCm(96),
|
||||
perf_run: minToMs(7) + secToMs(30),
|
||||
perf_cone_drill: secToMs(7),
|
||||
})
|
||||
.returning("id")
|
||||
.executeTakeFirstOrThrow();
|
||||
log.info({ id: result.id }, "seeded test assessment");
|
||||
return result.id;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const answer = prompt(`Seed a test verification request in the database (${env.DATABASE_URL})? (y/N)`);
|
||||
if (answer?.trim().toLowerCase() !== "y") {
|
||||
log.info("Aborted");
|
||||
await db.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const accountId = await seedTestAccount();
|
||||
const assessmentId = await seedTestAssessment(accountId);
|
||||
|
||||
const verifications = new VerificationsService();
|
||||
const verification = await verifications.request(assessmentId, accountId, {
|
||||
[Activity.BackSquat]: "https://example.com/videos/back-squat.mp4",
|
||||
[Activity.Deadlift]: "https://example.com/videos/deadlift.mp4",
|
||||
[Activity.BenchPress]: "https://example.com/videos/bench-press.mp4",
|
||||
[Activity.Run]: "https://example.com/videos/run.mp4",
|
||||
[Activity.BroadJump]: "https://example.com/videos/broad-jump.mp4",
|
||||
[Activity.ConeDrill]: "https://example.com/videos/cone-drill.mp4",
|
||||
});
|
||||
if (!verification) throw new Error("Failed to seed verification request — assessment ownership check failed");
|
||||
|
||||
log.info({ id: verification.id, assessmentId, accountId }, "seeded test verification request");
|
||||
}
|
||||
catch (err) {
|
||||
log.error({ err }, "seed failed");
|
||||
process.exit(1);
|
||||
}
|
||||
finally {
|
||||
await db.destroy();
|
||||
}
|
||||
})();
|
||||
+21
-256
@@ -1,18 +1,16 @@
|
||||
import {
|
||||
ActivityPerformanceSchema,
|
||||
ActivityVerificationsSchema,
|
||||
ActivityVideosSchema,
|
||||
PlayerSchema,
|
||||
} from "@blade-and-brawn/domain"
|
||||
import { cors } from "@elysiajs/cors";
|
||||
import { Elysia, NotFoundError, redirect, status, t } from "elysia";
|
||||
import { Elysia, NotFoundError, status, t } from "elysia";
|
||||
import {
|
||||
PrintfulError,
|
||||
WebflowError,
|
||||
Printful,
|
||||
Webflow,
|
||||
} from "@blade-and-brawn/commerce";
|
||||
import { DEFAULT_NAME, DUMMY_PASSWORD_HASH, env, log } from "./util";
|
||||
import { DEFAULT_NAME, env, log, sha256Sum } from "./util";
|
||||
import serverTiming from "@elysia/server-timing";
|
||||
import jwt from "@elysia/jwt";
|
||||
import { CommerceService, WOrderStatusSchema } from "./services/commerce";
|
||||
@@ -22,17 +20,12 @@ import { CalculatorService, CalculatorUnavailableError } from "./services/calcul
|
||||
import { StandardsParamsSchema } from "@blade-and-brawn/calculator";
|
||||
import { StandardsService } from "./services/standards";
|
||||
import { EventsService, EventStatusSchema } from "./services/events";
|
||||
import { AccountsService, type AccountRole } from "./services/accounts";
|
||||
import { Value } from "@sinclair/typebox/value";
|
||||
import { AssessmentsService } from "./services/assessments";
|
||||
import { VerificationsService, VerificationStatusSchema } from "./services/verifications";
|
||||
import { Not } from "@sinclair/typebox";
|
||||
import { AccountsService } from "./services/accounts";
|
||||
|
||||
// CONSTANTS
|
||||
// -----------------------
|
||||
const EVENT_QUEUE_MANAGE_DELAY_MS = 1000 // 1 sec
|
||||
const JWT_EXP = "1d";
|
||||
const JWT_EXP_SECONDS = 60 * 60 * 24; // keep in sync with JWT_EXP; used for cookie maxAge
|
||||
|
||||
// SERVICES
|
||||
// -----------------------
|
||||
@@ -42,9 +35,7 @@ const s = (() => {
|
||||
const Commerce = new CommerceService();
|
||||
const Accounts = new AccountsService(Calculator);
|
||||
const Events = new EventsService();
|
||||
const Assessments = new AssessmentsService();
|
||||
const Verifications = new VerificationsService();
|
||||
return { Standards, Calculator, Commerce, Accounts, Events, Assessments, Verifications };
|
||||
return { Standards, Calculator, Commerce, Accounts, Events };
|
||||
})();
|
||||
|
||||
// QUEUES
|
||||
@@ -60,18 +51,11 @@ const authPlugin = new Elysia({ name: "auth" })
|
||||
.use(jwt({ name: "jwt", secret: env.AUTH_SECRET }))
|
||||
.guard({ cookie: t.Cookie({ auth: t.Optional(t.String()) }) })
|
||||
.macro({
|
||||
authAdmin: {
|
||||
async resolve({ jwt, cookie: { auth } }) {
|
||||
const token = auth.value && await jwt.verify(auth.value);
|
||||
if (!token || token.role !== "admin" || !token.accountId || !token.sessionId) throw status(401, "Unauthorized");
|
||||
return { role: token.role.toString(), sessionId: token.sessionId.toString(), accountId: token.accountId.toString() };
|
||||
}
|
||||
},
|
||||
auth: {
|
||||
async resolve({ jwt, cookie: { auth } }) {
|
||||
const token = auth.value && await jwt.verify(auth.value);
|
||||
if (!token || !token.role || !token.accountId || !token.sessionId) throw status(401, "Unauthorized");
|
||||
return { role: token.role.toString(), sessionId: token.sessionId.toString(), accountId: token.accountId.toString() };
|
||||
if (!token || !token.sessionId) throw status(401, "Unauthorized");
|
||||
return { sessionId: token.sessionId.toString() };
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -92,12 +76,7 @@ export const app = new Elysia()
|
||||
],
|
||||
}),
|
||||
)
|
||||
.guard({
|
||||
cookie: t.Cookie({
|
||||
auth: t.Optional(t.String()),
|
||||
authDiscord: t.Optional(t.String())
|
||||
})
|
||||
})
|
||||
.guard({ cookie: t.Cookie({ auth: t.Optional(t.String()) }) })
|
||||
.use(authPlugin)
|
||||
|
||||
.error({
|
||||
@@ -144,117 +123,22 @@ export const app = new Elysia()
|
||||
.get("/health", () => ({ status: "ok" }))
|
||||
|
||||
// AUTHENTICATION
|
||||
.post("/auth/login", async ({ jwt, body: { password, email }, cookie: { auth } }) => {
|
||||
const account = await s.Accounts.getByEmail(email);
|
||||
const password_match = await Bun.password.verify(password, account?.password_hash ?? DUMMY_PASSWORD_HASH);
|
||||
if (!account || !password_match) throw status(401, "Invalid credentials");
|
||||
.post("/auth/login", async ({ jwt, body, cookie: { auth } }) => {
|
||||
const match = crypto.timingSafeEqual(sha256Sum(body.password), Buffer.from(env.ADMIN_PASSWORD, "hex"));
|
||||
if (!match) throw status(401, "Invalid credentials");
|
||||
|
||||
auth.set({
|
||||
value: await jwt.sign({ role: account.role, sessionId: randomUUIDv7(), accountId: account.id, exp: JWT_EXP }),
|
||||
value: await jwt.sign({ sessionId: randomUUIDv7(), exp: JWT_EXP }),
|
||||
path: "/",
|
||||
maxAge: JWT_EXP_SECONDS,
|
||||
sameSite: env.NODE_ENV === "production" ? "lax" : "none",
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
domain: env.NODE_ENV === "production" ?
|
||||
".bladeandbrawn.com" :
|
||||
undefined
|
||||
});
|
||||
}, { body: t.Object({ email: t.String(), password: t.String() }) })
|
||||
|
||||
.group("/auth/discord", (app) => app
|
||||
.get("/login", async ({ cookie: { authDiscord } }) => {
|
||||
const state = crypto.randomUUID();
|
||||
|
||||
authDiscord.set({
|
||||
value: state,
|
||||
path: "/",
|
||||
maxAge: 60 * 10, // 10 min
|
||||
maxAge: 60 * 60 * 24 * 7,
|
||||
sameSite: "lax",
|
||||
httpOnly: true,
|
||||
secure: env.NODE_ENV === "production"
|
||||
});
|
||||
|
||||
const url = new URL("https://discord.com/api/oauth2/authorize");
|
||||
url.searchParams.set("client_id", env.BOT_CLIENT_ID);
|
||||
url.searchParams.set("redirect_uri", env.BOT_REDIRECT_URL);
|
||||
url.searchParams.set("response_type", "code");
|
||||
url.searchParams.set("scope", "identify email");
|
||||
url.searchParams.set("state", state);
|
||||
|
||||
return redirect(url.toString(), 302);
|
||||
})
|
||||
.get("/callback", async ({ query, cookie: { authDiscord, auth }, jwt }) => {
|
||||
if (query.error) throw status(400, { error: query.error_description ? `${query.error}: ${query.error_description}` : query.error });
|
||||
|
||||
if (!query.state) throw status(400, "No Discord OAuth2 state query parameter provided");
|
||||
if (query.state !== authDiscord.value) throw status(400, "Invalid Discord OAuth state");
|
||||
|
||||
const tokenRes = await fetch("https://discord.com/api/oauth2/token", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
client_id: env.BOT_CLIENT_ID,
|
||||
client_secret: env.BOT_CLIENT_SECRET,
|
||||
grant_type: "authorization_code",
|
||||
code: query.code ?? "",
|
||||
redirect_uri: env.BOT_REDIRECT_URL
|
||||
}).toString()
|
||||
});
|
||||
if (!tokenRes.ok) {
|
||||
const errorBody = await tokenRes.json().catch(() => null);
|
||||
throw status(502, { error: errorBody ?? "Discord token exchange failed" });
|
||||
}
|
||||
|
||||
const tokenResPayload = await tokenRes.json();
|
||||
Value.Assert(t.Object({ access_token: t.String() }), tokenResPayload);
|
||||
|
||||
const identityRes = await fetch("https://discord.com/api/users/@me", {
|
||||
headers: { "Authorization": `Bearer ${tokenResPayload.access_token}` }
|
||||
});
|
||||
if (!identityRes.ok) {
|
||||
const errorBody = await identityRes.json().catch(() => null);
|
||||
throw status(502, { error: errorBody ?? "Failed to fetch Discord identity" });
|
||||
}
|
||||
|
||||
const identityResPayload = await identityRes.json();
|
||||
Value.Assert(t.Object({ id: t.String(), email: t.Optional(t.String()), username: t.String() }), identityResPayload);
|
||||
|
||||
// Create the account
|
||||
let accountId = (await s.Accounts.get(`@${identityResPayload.id}`))?.id;
|
||||
if (!accountId) {
|
||||
accountId = (await s.Accounts.create(
|
||||
identityResPayload.id,
|
||||
identityResPayload.email,
|
||||
identityResPayload.username
|
||||
)).id;
|
||||
}
|
||||
|
||||
// Authenticate
|
||||
auth.set({
|
||||
value: await jwt.sign({ role: "user" satisfies AccountRole, sessionId: randomUUIDv7(), accountId, exp: JWT_EXP }),
|
||||
path: "/",
|
||||
maxAge: JWT_EXP_SECONDS,
|
||||
sameSite: env.NODE_ENV === "production" ? "lax" : "none",
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
secure: env.NODE_ENV === "production",
|
||||
domain: env.NODE_ENV === "production" ?
|
||||
".bladeandbrawn.com" :
|
||||
undefined
|
||||
});
|
||||
|
||||
return redirect(env.BOT_LOGIN_REDIRECT_URL, 302);
|
||||
}, {
|
||||
query: t.Object({
|
||||
code: t.Optional(t.String()),
|
||||
state: t.Optional(t.String()),
|
||||
error: t.Optional(t.String()),
|
||||
error_description: t.Optional(t.String()),
|
||||
})
|
||||
})
|
||||
)
|
||||
}, { body: t.Object({ password: t.String() }) })
|
||||
|
||||
// CALCULATOR
|
||||
.group("/calculator", (app) => app
|
||||
@@ -268,7 +152,7 @@ export const app = new Elysia()
|
||||
}),
|
||||
})
|
||||
// Authenticated
|
||||
.guard({ authAdmin: true }, (app) => app
|
||||
.guard({ auth: true })
|
||||
.get("/standards/config", async () => {
|
||||
return await s.Calculator.Standards.Config.get();
|
||||
})
|
||||
@@ -278,8 +162,7 @@ export const app = new Elysia()
|
||||
body: t.Object({ standardsConfigId: t.String() })
|
||||
})
|
||||
)
|
||||
)
|
||||
.group("/standards", { authAdmin: true }, (app) => app
|
||||
.group("/standards", { auth: true }, (app) => app
|
||||
.post("/configs", async ({ body: { name, datasetId, params } }) => {
|
||||
return await s.Standards.Configs.create(name, datasetId, params);
|
||||
}, {
|
||||
@@ -319,7 +202,7 @@ export const app = new Elysia()
|
||||
)
|
||||
|
||||
// COMMERCE
|
||||
.group("/commerce", { authAdmin: true }, (app) => app
|
||||
.group("/commerce", { auth: true }, (app) => app
|
||||
.group("/products", (app) => app
|
||||
.get("/", async ({ query }) => {
|
||||
const [pProducts, wProducts] = await Promise.all([
|
||||
@@ -423,7 +306,7 @@ export const app = new Elysia()
|
||||
)
|
||||
|
||||
// EVENTS
|
||||
.group("/events", { authAdmin: true }, (app) => app
|
||||
.group("/events", { auth: true }, (app) => app
|
||||
.get("/", async ({ query }) => {
|
||||
const events = await s.Events.list({
|
||||
filter: { status: query.status, type: query.type, group: query.group },
|
||||
@@ -458,6 +341,7 @@ export const app = new Elysia()
|
||||
|
||||
// ACCOUNTS
|
||||
.group("/accounts", (app) => app
|
||||
// Non-authenticated
|
||||
.get("/:id/stats", async ({ params: { id } }) => {
|
||||
const stats = await s.Accounts.stats(id);
|
||||
if (!stats) throw new NotFoundError("Account stats not found");
|
||||
@@ -465,14 +349,8 @@ export const app = new Elysia()
|
||||
}, {
|
||||
params: t.Object({ id: t.String() })
|
||||
})
|
||||
.guard({ auth: true }, (app) => app
|
||||
.get("/me/stats", async ({ accountId }) => {
|
||||
const stats = await s.Accounts.stats(accountId);
|
||||
if (!stats) throw new NotFoundError("Account stats not found");
|
||||
return stats;
|
||||
})
|
||||
)
|
||||
.guard({ authAdmin: true }, (app) => app
|
||||
// Authenticated
|
||||
.guard({ auth: true })
|
||||
.get("/:id", async ({ params: { id } }) => {
|
||||
const account = await s.Accounts.get(id);
|
||||
if (!account) throw new NotFoundError("Account not found");
|
||||
@@ -481,118 +359,6 @@ export const app = new Elysia()
|
||||
params: t.Object({ id: t.String() })
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
// ASSESSMENTS
|
||||
.group("/assessments", (app) => app
|
||||
.guard({ auth: true }, (app) => app
|
||||
.post("/me", async ({ body: { player, activityPerformances }, accountId }) => {
|
||||
return await s.Assessments.create(player, activityPerformances, accountId);
|
||||
}, {
|
||||
body: t.Object({
|
||||
player: PlayerSchema,
|
||||
activityPerformances: t.Array(ActivityPerformanceSchema)
|
||||
})
|
||||
})
|
||||
.get("/me", async ({ accountId }) => {
|
||||
return await s.Assessments.list({ filter: { accountId } });
|
||||
})
|
||||
.delete("/me/:id", async ({ params: { id }, accountId }) => {
|
||||
const deleted = await s.Assessments.delete(id, accountId);
|
||||
if (!deleted) throw new NotFoundError("Assessment not found");
|
||||
}, {
|
||||
params: t.Object({ id: t.String() })
|
||||
})
|
||||
)
|
||||
.guard({ authAdmin: true }, (app) => app
|
||||
.post("/", async ({ body: { player, activityPerformances, id } }) => {
|
||||
await s.Assessments.create(player, activityPerformances, id);
|
||||
}, {
|
||||
body: t.Object({
|
||||
player: PlayerSchema,
|
||||
activityPerformances: t.Array(ActivityPerformanceSchema),
|
||||
id: t.Optional(t.String()),
|
||||
})
|
||||
})
|
||||
.put("/:id", async ({ body: { player, activityPerformances }, params: { id } }) => {
|
||||
const updated = await s.Assessments.update(id, player, activityPerformances);
|
||||
if (!updated) throw new NotFoundError("Assessment not found");
|
||||
}, {
|
||||
params: t.Object({ id: t.String() }),
|
||||
body: t.Object({
|
||||
player: PlayerSchema,
|
||||
activityPerformances: t.Array(ActivityPerformanceSchema),
|
||||
})
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
// VERIFICATIONS
|
||||
.group("/verifications", (app) => app
|
||||
.guard({ auth: true }, (app) => app
|
||||
.post("/me", async ({ body: { assessmentId, activityVideoUrls }, accountId }) => {
|
||||
const requested = await s.Verifications.request(assessmentId, accountId, activityVideoUrls);
|
||||
if (!requested) throw new NotFoundError("Assessment not found");
|
||||
return requested;
|
||||
}, {
|
||||
body: t.Object({
|
||||
assessmentId: t.String(),
|
||||
activityVideoUrls: ActivityVideosSchema,
|
||||
})
|
||||
})
|
||||
)
|
||||
.guard({ authAdmin: true }, (app) => app
|
||||
.get("/", async ({ query }) => {
|
||||
return await s.Verifications.list({
|
||||
filter: { status: query.status },
|
||||
limit: query.limit,
|
||||
offset: query.offset,
|
||||
});
|
||||
}, {
|
||||
query: t.Object({
|
||||
status: t.Optional(VerificationStatusSchema),
|
||||
limit: t.Optional(t.Numeric()),
|
||||
offset: t.Optional(t.Numeric()),
|
||||
})
|
||||
})
|
||||
.get("/:id", async ({ params: { id } }) => {
|
||||
const verification = await s.Verifications.get(id);
|
||||
if (!verification) throw new NotFoundError("Verification not found");
|
||||
return verification;
|
||||
}, {
|
||||
params: t.Object({ id: t.String() })
|
||||
})
|
||||
.post("/:id/request-action", async ({ params: { id }, body: { reviewerNotes, activityVerifications } }) => {
|
||||
const verification = await s.Verifications.get(id);
|
||||
if (!verification) throw new NotFoundError("Verification not found");
|
||||
if (verification.status === "completed" || verification.status === "action_requested")
|
||||
throw status(409, { error: "Cannot modify a completed or action-requested verification" });
|
||||
|
||||
const updated = await s.Verifications.requestAction(id, reviewerNotes ?? null, activityVerifications);
|
||||
if (!updated) throw new NotFoundError("Verification not found");
|
||||
}, {
|
||||
params: t.Object({ id: t.String() }),
|
||||
body: t.Object({
|
||||
reviewerNotes: t.Optional(t.String()),
|
||||
activityVerifications: ActivityVerificationsSchema,
|
||||
})
|
||||
})
|
||||
.post("/:id/complete", async ({ params: { id }, body: { activityVerifications }, accountId }) => {
|
||||
const verification = await s.Verifications.get(id);
|
||||
if (!verification) throw new NotFoundError("Verification not found");
|
||||
if (verification.status === "completed" || verification.status === "action_requested")
|
||||
throw status(409, { error: "Cannot modify a completed or action-requested verification" });
|
||||
|
||||
const updated = await s.Verifications.complete(id, accountId, activityVerifications);
|
||||
if (!updated) throw new NotFoundError("Verification not found");
|
||||
}, {
|
||||
params: t.Object({ id: t.String() }),
|
||||
body: t.Object({
|
||||
activityVerifications: ActivityVerificationsSchema,
|
||||
})
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
// WEBHOOKS
|
||||
.post("/webhooks/printful", async ({ body, query }) => {
|
||||
@@ -701,4 +467,3 @@ app.listen(3000, async () => {
|
||||
|
||||
export type API = typeof app
|
||||
export { type EventStatus } from "./services/events";
|
||||
export { type VerificationStatus } from "./services/verifications";
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { Activity, Gender } from "@blade-and-brawn/domain";
|
||||
import { Activity, Gender, type Player } from "@blade-and-brawn/domain";
|
||||
import { db } from "../database/db";
|
||||
import type { CalculatorService } from "./calculator";
|
||||
import { Value } from "@sinclair/typebox/value";
|
||||
import { t } from "elysia";
|
||||
|
||||
export type AccountRole = "user" | "admin";
|
||||
|
||||
export class AccountsService {
|
||||
constructor(private Calculator: CalculatorService) { }
|
||||
|
||||
@@ -15,31 +13,13 @@ export class AccountsService {
|
||||
: ["accounts.id", "=", id];
|
||||
}
|
||||
|
||||
async create(discordId: string, email?: string, name?: string) {
|
||||
return await db.insertInto("accounts")
|
||||
.values({
|
||||
discord_id: discordId,
|
||||
name: name ?? "",
|
||||
email: email ?? null
|
||||
})
|
||||
.returning("id")
|
||||
.executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
async get(id: string) {
|
||||
return await (db).selectFrom("accounts")
|
||||
.select(["id", "discord_id", "name", "email", "gender", "role"])
|
||||
.selectAll()
|
||||
.where(...AccountsService.idComparison(id))
|
||||
.executeTakeFirst();
|
||||
}
|
||||
|
||||
async getByEmail(email: string) {
|
||||
return await (db).selectFrom("accounts")
|
||||
.select(["id", "discord_id", "name", "email", "gender", "password_hash", "role"])
|
||||
.where("email", "=", email)
|
||||
.executeTakeFirst();
|
||||
}
|
||||
|
||||
async stats(id: string) {
|
||||
const latestAssessment = await db.selectFrom("accounts")
|
||||
.innerJoin("assessments", "assessments.account_id", "accounts.id")
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
import { Activity, type ActivityPerformance, type Player } from "@blade-and-brawn/domain";
|
||||
import { db } from "../database/db";
|
||||
|
||||
export class AssessmentsService {
|
||||
private static performanceFor = (activityPerformances: ActivityPerformance[], activity: Activity) =>
|
||||
activityPerformances.find((p) => p.activity === activity)?.performance ?? null;
|
||||
|
||||
async create(player: Player, activityPerformances: ActivityPerformance[], accountId?: string) {
|
||||
return await db.insertInto("assessments")
|
||||
.values({
|
||||
account_id: accountId ?? null,
|
||||
name: player.name ?? "Anonymous",
|
||||
age: player.metrics.age,
|
||||
weight: player.metrics.weight,
|
||||
gender: player.metrics.gender,
|
||||
perf_back_squat: AssessmentsService.performanceFor(activityPerformances, Activity.BackSquat),
|
||||
perf_deadlift: AssessmentsService.performanceFor(activityPerformances, Activity.Deadlift),
|
||||
perf_bench_press: AssessmentsService.performanceFor(activityPerformances, Activity.BenchPress),
|
||||
perf_broad_jump: AssessmentsService.performanceFor(activityPerformances, Activity.BroadJump),
|
||||
perf_run: AssessmentsService.performanceFor(activityPerformances, Activity.Run),
|
||||
perf_cone_drill: AssessmentsService.performanceFor(activityPerformances, Activity.ConeDrill),
|
||||
})
|
||||
.returning("id")
|
||||
.executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
async list(opt: {
|
||||
filter?: { accountId?: string },
|
||||
limit?: number,
|
||||
offset?: number,
|
||||
} = {}) {
|
||||
return await db.selectFrom("assessments")
|
||||
.selectAll()
|
||||
.$if(opt.filter?.accountId !== undefined, (qb) => qb
|
||||
.where("account_id", "=", opt.filter!.accountId!)
|
||||
)
|
||||
.orderBy("created_at", "desc")
|
||||
.$if(opt.limit !== undefined, (qb) => qb.limit(opt.limit!))
|
||||
.$if(opt.offset !== undefined, (qb) => qb.offset(opt.offset!))
|
||||
.execute();
|
||||
}
|
||||
|
||||
async update(id: string, player: Player, activityPerformances: ActivityPerformance[]) {
|
||||
const result = await db.updateTable("assessments")
|
||||
.where("id", "=", id)
|
||||
.set({
|
||||
name: player.name ?? "Anonymous",
|
||||
age: player.metrics.age,
|
||||
weight: player.metrics.weight,
|
||||
gender: player.metrics.gender,
|
||||
perf_back_squat: AssessmentsService.performanceFor(activityPerformances, Activity.BackSquat),
|
||||
perf_deadlift: AssessmentsService.performanceFor(activityPerformances, Activity.Deadlift),
|
||||
perf_bench_press: AssessmentsService.performanceFor(activityPerformances, Activity.BenchPress),
|
||||
perf_broad_jump: AssessmentsService.performanceFor(activityPerformances, Activity.BroadJump),
|
||||
perf_run: AssessmentsService.performanceFor(activityPerformances, Activity.Run),
|
||||
perf_cone_drill: AssessmentsService.performanceFor(activityPerformances, Activity.ConeDrill),
|
||||
})
|
||||
.executeTakeFirst();
|
||||
return result.numUpdatedRows > 0n;
|
||||
}
|
||||
|
||||
async delete(id: string, accountId: string): Promise<boolean> {
|
||||
const result = await db.deleteFrom("assessments")
|
||||
.where("id", "=", id)
|
||||
.where("account_id", "=", accountId)
|
||||
.executeTakeFirst();
|
||||
return result.numDeletedRows > 0n;
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
import { Activity, type ActivityVerifications, type ActivityVideoUrls } from "@blade-and-brawn/domain";
|
||||
import type { Static } from "@sinclair/typebox";
|
||||
import { t } from "elysia";
|
||||
import { db } from "../database/db";
|
||||
|
||||
export const VerificationStatusSchema = t.Union([
|
||||
t.Literal("request"),
|
||||
t.Literal("in_review"),
|
||||
t.Literal("action_requested"),
|
||||
t.Literal("completed"),
|
||||
]);
|
||||
export type VerificationStatus = Static<typeof VerificationStatusSchema>;
|
||||
|
||||
export class VerificationsService {
|
||||
async request(assessmentId: string, accountId: string, activityVideoUrls: ActivityVideoUrls) {
|
||||
// Only the owning account may request verification of their own assessment.
|
||||
const assessment = await db.selectFrom("assessments")
|
||||
.select("id")
|
||||
.where("id", "=", assessmentId)
|
||||
.where("account_id", "=", accountId)
|
||||
.executeTakeFirst();
|
||||
if (!assessment) return undefined;
|
||||
|
||||
return await db.insertInto("verifications")
|
||||
.values({
|
||||
assessment_id: assessmentId,
|
||||
status: "request" satisfies VerificationStatus,
|
||||
url_back_squat: activityVideoUrls[Activity.BackSquat] ?? null,
|
||||
url_deadlift: activityVideoUrls[Activity.Deadlift] ?? null,
|
||||
url_bench_press: activityVideoUrls[Activity.BenchPress] ?? null,
|
||||
url_broad_jump: activityVideoUrls[Activity.BroadJump] ?? null,
|
||||
url_run: activityVideoUrls[Activity.Run] ?? null,
|
||||
url_cone_drill: activityVideoUrls[Activity.ConeDrill] ?? null,
|
||||
})
|
||||
.onConflict((oc) => oc
|
||||
.column("assessment_id")
|
||||
.doUpdateSet((eb) => ({
|
||||
status: "request" satisfies VerificationStatus,
|
||||
url_back_squat: eb.ref("excluded.url_back_squat"),
|
||||
url_deadlift: eb.ref("excluded.url_deadlift"),
|
||||
url_bench_press: eb.ref("excluded.url_bench_press"),
|
||||
url_broad_jump: eb.ref("excluded.url_broad_jump"),
|
||||
url_run: eb.ref("excluded.url_run"),
|
||||
url_cone_drill: eb.ref("excluded.url_cone_drill"),
|
||||
// Re-requesting means new videos are under review, so the
|
||||
// previous cycle's per-activity judgments and completion
|
||||
// info no longer apply.
|
||||
verf_back_squat: null,
|
||||
verf_deadlift: null,
|
||||
verf_bench_press: null,
|
||||
verf_broad_jump: null,
|
||||
verf_run: null,
|
||||
verf_cone_drill: null,
|
||||
completed_at: null,
|
||||
completed_by: null,
|
||||
}))
|
||||
)
|
||||
.returning("id")
|
||||
.executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
// Joined with the assessment being verified, since reviewing a request
|
||||
// requires seeing the player's claimed performance alongside the videos.
|
||||
private static baseQuery() {
|
||||
return db.selectFrom("verifications")
|
||||
.innerJoin("assessments", "assessments.id", "verifications.assessment_id")
|
||||
.select([
|
||||
"verifications.id",
|
||||
"verifications.assessment_id",
|
||||
"verifications.status",
|
||||
"verifications.created_at",
|
||||
"verifications.completed_at",
|
||||
"verifications.completed_by",
|
||||
"verifications.reviewer_notes",
|
||||
"verifications.url_back_squat",
|
||||
"verifications.url_deadlift",
|
||||
"verifications.url_bench_press",
|
||||
"verifications.url_broad_jump",
|
||||
"verifications.url_run",
|
||||
"verifications.url_cone_drill",
|
||||
"verifications.verf_back_squat",
|
||||
"verifications.verf_deadlift",
|
||||
"verifications.verf_bench_press",
|
||||
"verifications.verf_broad_jump",
|
||||
"verifications.verf_run",
|
||||
"verifications.verf_cone_drill",
|
||||
"assessments.name",
|
||||
"assessments.gender",
|
||||
"assessments.age",
|
||||
"assessments.weight",
|
||||
"assessments.perf_back_squat",
|
||||
"assessments.perf_deadlift",
|
||||
"assessments.perf_bench_press",
|
||||
"assessments.perf_broad_jump",
|
||||
"assessments.perf_run",
|
||||
"assessments.perf_cone_drill",
|
||||
]);
|
||||
}
|
||||
|
||||
async get(id: string) {
|
||||
return await VerificationsService.baseQuery()
|
||||
.where("verifications.id", "=", id)
|
||||
.executeTakeFirst();
|
||||
}
|
||||
|
||||
async list(opt: {
|
||||
filter?: { status?: VerificationStatus },
|
||||
limit?: number,
|
||||
offset?: number,
|
||||
} = {}) {
|
||||
return await VerificationsService.baseQuery()
|
||||
.$if(opt.filter?.status !== undefined, (qb) => qb
|
||||
.where("verifications.status", "=", opt.filter!.status!)
|
||||
)
|
||||
.orderBy("verifications.created_at", "desc")
|
||||
.$if(opt.limit !== undefined, (qb) => qb.limit(opt.limit!))
|
||||
.$if(opt.offset !== undefined, (qb) => qb.offset(opt.offset!))
|
||||
.execute();
|
||||
}
|
||||
|
||||
async requestAction(id: string, reviewerNotes: string | null, activityVerifications: ActivityVerifications) {
|
||||
const result = await db.updateTable("verifications")
|
||||
.where("id", "=", id)
|
||||
.set({
|
||||
status: "action_requested" satisfies VerificationStatus,
|
||||
reviewer_notes: reviewerNotes,
|
||||
verf_back_squat: activityVerifications[Activity.BackSquat] ?? null,
|
||||
verf_deadlift: activityVerifications[Activity.Deadlift] ?? null,
|
||||
verf_bench_press: activityVerifications[Activity.BenchPress] ?? null,
|
||||
verf_broad_jump: activityVerifications[Activity.BroadJump] ?? null,
|
||||
verf_run: activityVerifications[Activity.Run] ?? null,
|
||||
verf_cone_drill: activityVerifications[Activity.ConeDrill] ?? null,
|
||||
})
|
||||
.executeTakeFirst();
|
||||
return result.numUpdatedRows > 0n;
|
||||
}
|
||||
|
||||
async complete(id: string, completedBy: string, activityVerifications: ActivityVerifications) {
|
||||
const result = await db.updateTable("verifications")
|
||||
.where("id", "=", id)
|
||||
.set({
|
||||
status: "completed" satisfies VerificationStatus,
|
||||
completed_at: new Date(),
|
||||
completed_by: completedBy,
|
||||
verf_back_squat: activityVerifications[Activity.BackSquat] ?? null,
|
||||
verf_deadlift: activityVerifications[Activity.Deadlift] ?? null,
|
||||
verf_bench_press: activityVerifications[Activity.BenchPress] ?? null,
|
||||
verf_broad_jump: activityVerifications[Activity.BroadJump] ?? null,
|
||||
verf_run: activityVerifications[Activity.Run] ?? null,
|
||||
verf_cone_drill: activityVerifications[Activity.ConeDrill] ?? null,
|
||||
})
|
||||
.executeTakeFirst();
|
||||
return result.numUpdatedRows > 0n;
|
||||
}
|
||||
}
|
||||
@@ -20,22 +20,16 @@ export const env = {
|
||||
WEBFLOW_AUTH: requireEnv("WEBFLOW_AUTH"),
|
||||
WEBFLOW_WEBHOOK_SECRET: requireEnv("WEBFLOW_WEBHOOK_SECRET"),
|
||||
AUTH_SECRET: requireEnv("AUTH_SECRET"),
|
||||
PUBLIC_ADMIN_EMAIL: requireEnv("PUBLIC_ADMIN_EMAIL"),
|
||||
ADMIN_PASSWORD_HASH: requireEnv("ADMIN_PASSWORD_HASH"),
|
||||
ADMIN_PASSWORD: requireEnv("ADMIN_PASSWORD"),
|
||||
DATABASE_URL: requireEnv("DATABASE_URL"),
|
||||
DATABASE_POOL_MAX: requireEnv("DATABASE_POOL_MAX"),
|
||||
MAX_WORKER_COUNT: requireEnv("MAX_WORKER_COUNT"),
|
||||
NODE_ENV: optionEnv("NODE_ENV", "development"),
|
||||
LOG_LEVEL: optionEnv("LOG_LEVEL", "info"),
|
||||
BOT_CLIENT_ID: requireEnv("BOT_CLIENT_ID"),
|
||||
BOT_CLIENT_SECRET: requireEnv("BOT_CLIENT_SECRET"),
|
||||
BOT_REDIRECT_URL: requireEnv("BOT_REDIRECT_URL"),
|
||||
BOT_LOGIN_REDIRECT_URL: requireEnv("BOT_LOGIN_REDIRECT_URL"),
|
||||
};
|
||||
|
||||
export const WORKER_COUNT = Math.min(os.availableParallelism(), +env.MAX_WORKER_COUNT);
|
||||
export const DEFAULT_NAME = "Default";
|
||||
export const DUMMY_PASSWORD_HASH = await Bun.password.hash("Dummy");
|
||||
|
||||
function requireEnv(key: string): string {
|
||||
const val = Bun.env[key];
|
||||
|
||||
@@ -22,7 +22,7 @@ export default {
|
||||
const { player, attributes } = res.data;
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor(0xEEE8AA)
|
||||
.setColor(0xE74C3C)
|
||||
.setTitle(`${message.author.username}'s Stats`)
|
||||
.setThumbnail(message.author.displayAvatarURL())
|
||||
.setDescription(`**Overall Level: ${player}**`)
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@blade-and-brawn/api": "workspace:*",
|
||||
"@sveltejs/kit": "^2.70.3",
|
||||
"@sveltejs/kit": "^2.70.2",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
||||
"elysia": "^1.4.30",
|
||||
"svelte": "^5.57.0",
|
||||
"elysia": "^1.4.29",
|
||||
"svelte": "^5.56.9",
|
||||
"svelte-adapter-bun": "^1.0.1",
|
||||
"svelte-check": "^4.7.6",
|
||||
"vite": "^7.3.6"
|
||||
@@ -25,8 +25,8 @@
|
||||
"@blade-and-brawn/domain": "workspace:*",
|
||||
"@elysia/eden": "^1.4.10",
|
||||
"@tailwindcss/vite": "^4.3.3",
|
||||
"daisyui": "^5.7.38",
|
||||
"jose": "^6.2.12",
|
||||
"daisyui": "^5.7.17",
|
||||
"jose": "^6.2.9",
|
||||
"tailwindcss": "^4.3.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { beforeNavigate } from "$app/navigation";
|
||||
import {
|
||||
LevelCalculator,
|
||||
type LevelCalculatorOutput,
|
||||
@@ -15,42 +13,11 @@
|
||||
type ActivityPerformance,
|
||||
type Player,
|
||||
} from "@blade-and-brawn/domain";
|
||||
import { api } from "$lib/api";
|
||||
|
||||
type AssessmentRow = NonNullable<
|
||||
Awaited<ReturnType<typeof api.assessments.me.get>>["data"]
|
||||
>[number];
|
||||
|
||||
interface CalcData {
|
||||
key: string;
|
||||
id?: string;
|
||||
levels?: LevelCalculatorOutput;
|
||||
player: Player;
|
||||
activityPerformances: ActivityPerformance[];
|
||||
/** JSON snapshot of {player, activityPerformances} as of the last successful save/load. "" means never saved. */
|
||||
savedSnapshot: string;
|
||||
/** whether the metrics/performance editing panel is open — collapsed by default, since levels are the primary thing being compared */
|
||||
expanded?: boolean;
|
||||
saving?: boolean;
|
||||
saveError?: string;
|
||||
deleting?: boolean;
|
||||
deleteError?: string;
|
||||
}
|
||||
|
||||
function snapshotOf(
|
||||
player: Player,
|
||||
activityPerformances: ActivityPerformance[],
|
||||
): string {
|
||||
return JSON.stringify({ player, activityPerformances });
|
||||
}
|
||||
|
||||
function isDirty(calculation: CalcData): boolean {
|
||||
return (
|
||||
snapshotOf(
|
||||
calculation.player,
|
||||
calculation.activityPerformances,
|
||||
) !== calculation.savedSnapshot
|
||||
);
|
||||
}
|
||||
|
||||
interface Props {
|
||||
@@ -61,136 +28,7 @@
|
||||
|
||||
const levelCalculator = $derived(new LevelCalculator(allStandards));
|
||||
|
||||
// toggle + name + overall + one column per attribute + actions
|
||||
const TABLE_COLUMNS = 4 + Object.keys(Attribute).length;
|
||||
|
||||
let calculations = $state<CalcData[]>([]);
|
||||
let loading = $state(true);
|
||||
let loadError = $state<string | null>(null);
|
||||
|
||||
const PERF_COLUMN = {
|
||||
[Activity.BackSquat]: "perf_back_squat",
|
||||
[Activity.Deadlift]: "perf_deadlift",
|
||||
[Activity.BenchPress]: "perf_bench_press",
|
||||
[Activity.Run]: "perf_run",
|
||||
[Activity.BroadJump]: "perf_broad_jump",
|
||||
[Activity.ConeDrill]: "perf_cone_drill",
|
||||
} as const satisfies Record<Activity, keyof AssessmentRow>;
|
||||
|
||||
function assessmentToCalc(assessment: AssessmentRow): CalcData {
|
||||
const player: Player = {
|
||||
name: assessment.name,
|
||||
metrics: {
|
||||
age: assessment.age,
|
||||
weight: assessment.weight,
|
||||
gender: assessment.gender as Gender,
|
||||
},
|
||||
};
|
||||
const activityPerformances = Object.values(Activity).map((a) => ({
|
||||
activity: a,
|
||||
performance: (assessment[PERF_COLUMN[a]] as number | null) ?? 0,
|
||||
}));
|
||||
|
||||
return {
|
||||
key: crypto.randomUUID(),
|
||||
id: assessment.id,
|
||||
player,
|
||||
activityPerformances,
|
||||
savedSnapshot: snapshotOf(player, activityPerformances),
|
||||
};
|
||||
}
|
||||
|
||||
function errorMessage(err: unknown): string {
|
||||
const value = (err as { value?: { error?: string } })?.value;
|
||||
return (
|
||||
value?.error ??
|
||||
(err instanceof Error ? err.message : "Unknown error")
|
||||
);
|
||||
}
|
||||
|
||||
async function loadAssessments() {
|
||||
loading = true;
|
||||
loadError = null;
|
||||
try {
|
||||
const res = await api.assessments.me.get();
|
||||
if (res.error) throw res.error;
|
||||
calculations = (res.data ?? []).map(assessmentToCalc);
|
||||
} catch (err) {
|
||||
loadError = errorMessage(err);
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function saveCalculation(calculation: CalcData) {
|
||||
calculation.saving = true;
|
||||
calculation.saveError = undefined;
|
||||
try {
|
||||
if (calculation.id) {
|
||||
const res = await api
|
||||
.assessments({ id: calculation.id })
|
||||
.put({
|
||||
player: calculation.player,
|
||||
activityPerformances: calculation.activityPerformances,
|
||||
});
|
||||
if (res.error) throw res.error;
|
||||
} else {
|
||||
const res = await api.assessments.me.post({
|
||||
player: calculation.player,
|
||||
activityPerformances: calculation.activityPerformances,
|
||||
});
|
||||
if (res.error) throw res.error;
|
||||
calculation.id = res.data?.id;
|
||||
}
|
||||
calculation.savedSnapshot = snapshotOf(
|
||||
calculation.player,
|
||||
calculation.activityPerformances,
|
||||
);
|
||||
} catch (err) {
|
||||
calculation.saveError = errorMessage(err);
|
||||
} finally {
|
||||
calculation.saving = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteCalculation(calculation: CalcData, index: number) {
|
||||
if (!calculation.id) {
|
||||
calculations.splice(index, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
calculation.deleting = true;
|
||||
calculation.deleteError = undefined;
|
||||
try {
|
||||
const res = await api.assessments.me({ id: calculation.id }).delete();
|
||||
if (res.error) throw res.error;
|
||||
calculations.splice(index, 1);
|
||||
} catch (err) {
|
||||
calculation.deleteError = errorMessage(err);
|
||||
} finally {
|
||||
calculation.deleting = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMount(loadAssessments);
|
||||
|
||||
beforeNavigate((navigation) => {
|
||||
if (!calculations.some(isDirty)) return;
|
||||
|
||||
if (navigation.type === "leave") {
|
||||
// triggers the browser's native "leave site?" confirmation
|
||||
navigation.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!confirm(
|
||||
"You have unsaved player changes that will be lost. Leave anyway?",
|
||||
)
|
||||
) {
|
||||
navigation.cancel();
|
||||
}
|
||||
});
|
||||
let calculations = $state([] as CalcData[]);
|
||||
|
||||
$effect(() => {
|
||||
for (const calculation of calculations) {
|
||||
@@ -201,11 +39,19 @@
|
||||
}
|
||||
});
|
||||
|
||||
const createCalculation = function (name: string): CalcData {
|
||||
$effect(() => {
|
||||
const savedCalcs = localStorage.getItem("calculations");
|
||||
if (savedCalcs) calculations = JSON.parse(savedCalcs);
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
localStorage.setItem("calculations", JSON.stringify(calculations));
|
||||
});
|
||||
|
||||
$inspect(calculations[0]);
|
||||
|
||||
const createCalculation = function (name: string) {
|
||||
return {
|
||||
key: crypto.randomUUID(),
|
||||
savedSnapshot: "", // never saved — always dirty until the first save
|
||||
expanded: true, // a brand new player needs its details filled in right away
|
||||
player: {
|
||||
name: name,
|
||||
metrics: {
|
||||
@@ -221,6 +67,21 @@
|
||||
};
|
||||
};
|
||||
|
||||
function downloadObject(obj: unknown, filename = "data.json") {
|
||||
const json = JSON.stringify(obj, null, 2);
|
||||
const blob = new Blob([json], { type: "application/json" });
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
|
||||
a.remove();
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
const formatMs = (ms: number) => {
|
||||
const total = Math.floor(ms / 1000);
|
||||
const m = Math.floor(total / 60);
|
||||
@@ -239,7 +100,7 @@
|
||||
const formatSeconds = (ms: number) => (ms / 1000).toFixed(2) + " seconds";
|
||||
|
||||
const performanceOptionsFromActivity = function (activity: Activity) {
|
||||
const options: { name: string; value: number }[] = [];
|
||||
const options: { name: string; value: string }[] = [];
|
||||
switch (activity) {
|
||||
case Activity.BackSquat:
|
||||
case Activity.Deadlift:
|
||||
@@ -247,7 +108,7 @@
|
||||
for (let i = 0; i < 600; ++i) {
|
||||
options.push({
|
||||
name: String(i) + " lb",
|
||||
value: lbToKg(i),
|
||||
value: String(lbToKg(i)),
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -255,7 +116,7 @@
|
||||
case Activity.Run: {
|
||||
const MAX_MIN = 30;
|
||||
for (let ms = 0; ms <= MAX_MIN * 60_000; ms += 1_000) {
|
||||
options.push({ name: formatMs(ms), value: ms });
|
||||
options.push({ name: formatMs(ms), value: String(ms) });
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -266,7 +127,7 @@
|
||||
const inches = halfStep / 2;
|
||||
options.push({
|
||||
name: inchesToFeetInches(inches),
|
||||
value: Number((inches * 2.54).toFixed(1)),
|
||||
value: (inches * 2.54).toFixed(1),
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -278,7 +139,7 @@
|
||||
for (let ms = MIN_MS; ms <= MAX_MS; ms += 10) {
|
||||
options.push({
|
||||
name: formatSeconds(ms),
|
||||
value: ms,
|
||||
value: String(ms),
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -288,15 +149,7 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="mt-5 mb-5 flex w-full items-center">
|
||||
<button
|
||||
onclick={loadAssessments}
|
||||
class="btn btn-secondary btn-sm"
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? "Refreshing..." : "Refresh"}
|
||||
</button>
|
||||
|
||||
<div class="mt-5 mb-5 flex w-full">
|
||||
<div class="ml-auto">
|
||||
<button
|
||||
onclick={() =>
|
||||
@@ -305,166 +158,97 @@
|
||||
)}
|
||||
class="btn btn-primary">New</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if loadError}
|
||||
<div role="alert" class="alert alert-error w-full mb-4">
|
||||
<span>{loadError}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="w-full overflow-x-auto">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-8"></th>
|
||||
<th>Name</th>
|
||||
<th>Overall</th>
|
||||
{#each Object.values(Attribute) as attribute (attribute)}
|
||||
<th>{attribute}</th>
|
||||
{/each}
|
||||
<th class="w-40"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each calculations as calculation, index (calculation.key)}
|
||||
<tr class="hover:bg-base-300">
|
||||
<td>
|
||||
<button
|
||||
onclick={() =>
|
||||
(calculation.expanded = !calculation.expanded)}
|
||||
class="btn btn-ghost btn-xs"
|
||||
aria-label={calculation.expanded
|
||||
? "Collapse details"
|
||||
: "Expand details"}
|
||||
onclick={() => downloadObject(calculations)}
|
||||
class="btn btn-secondary">Export</button
|
||||
>
|
||||
{calculation.expanded ? "▾" : "▸"}
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-center gap-2">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section
|
||||
class="w-full px-3 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"
|
||||
>
|
||||
{#each calculations as calculation, index}
|
||||
<div
|
||||
class="card card-compact bg-base-200 p-4 shadow-lg max-w-sm w-full"
|
||||
>
|
||||
<div class="card-body gap-4 p-4">
|
||||
<input
|
||||
class="input input-bordered input-sm w-full min-w-32"
|
||||
class="input input-bordered input-sm w-full"
|
||||
type="text"
|
||||
bind:value={calculation.player.name}
|
||||
placeholder="Player name"
|
||||
/>
|
||||
{#if isDirty(calculation)}
|
||||
<div class="badge badge-warning badge-xs shrink-0">
|
||||
Unsaved
|
||||
|
||||
<ul
|
||||
class="bg-base-100 rounded-box shadow-xs divide-y divide-base-300"
|
||||
>
|
||||
<li class="p-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="font-semibold text-sm">OVERALL</div>
|
||||
<div class="badge badge-neutral badge-xs">
|
||||
{calculation?.levels?.player || "N/A"}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="badge badge-neutral font-semibold">
|
||||
{calculation?.levels?.player ?? "N/A"}
|
||||
</li>
|
||||
|
||||
{#each Object.values(Attribute) as attribute}
|
||||
<li class="p-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="opacity-80 text-sm">
|
||||
{attribute}
|
||||
</div>
|
||||
</td>
|
||||
{#each Object.values(Attribute) as attribute (attribute)}
|
||||
<td>
|
||||
<div class="badge badge-ghost">
|
||||
<div class="badge badge-ghost badge-xs">
|
||||
{calculation?.levels?.attributes?.[
|
||||
attribute
|
||||
] ?? "N/A"}
|
||||
] || "N/A"}
|
||||
</div>
|
||||
</td>
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
<td>
|
||||
<div class="flex gap-2 justify-end">
|
||||
<button
|
||||
onclick={() => saveCalculation(calculation)}
|
||||
disabled={calculation.saving ||
|
||||
!isDirty(calculation)}
|
||||
class="btn btn-primary btn-xs"
|
||||
>
|
||||
{calculation.saving ? "Saving..." : "Save"}
|
||||
</button>
|
||||
<button
|
||||
onclick={() =>
|
||||
confirm(
|
||||
`Remove ${calculation.player.name}?`,
|
||||
) && deleteCalculation(calculation, index)}
|
||||
disabled={calculation.deleting}
|
||||
class="btn btn-error btn-xs"
|
||||
>
|
||||
{calculation.deleting ? "..." : "Delete"}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{#if calculation.expanded}
|
||||
<tr>
|
||||
<td colspan={TABLE_COLUMNS}>
|
||||
<div
|
||||
class="bg-base-200/60 rounded-lg p-4 flex flex-col gap-4"
|
||||
>
|
||||
</ul>
|
||||
|
||||
<fieldset
|
||||
class="fieldset"
|
||||
class="fieldset bg-base-200/60 rounded-lg"
|
||||
onchange={() =>
|
||||
(calculation.levels =
|
||||
levelCalculator.calculate(
|
||||
(calculation.levels = levelCalculator.calculate(
|
||||
calculation.player,
|
||||
calculation.activityPerformances,
|
||||
))}
|
||||
>
|
||||
<legend
|
||||
class="fieldset-legend text-xs font-semibold opacity-70"
|
||||
>
|
||||
Metrics
|
||||
</legend>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-3">
|
||||
<label class="form-control">
|
||||
<span class="label mb-1 text-xs"
|
||||
>Gender</span
|
||||
>
|
||||
<span class="label mb-1 text-xs">Gender</span>
|
||||
<select
|
||||
class="select select-bordered select-sm w-full"
|
||||
bind:value={
|
||||
calculation.player.metrics
|
||||
.gender
|
||||
}
|
||||
>
|
||||
{#each Object.values(Gender) as gender (gender)}
|
||||
<option value={gender}
|
||||
>{gender}</option
|
||||
bind:value={calculation.player.metrics.gender}
|
||||
>
|
||||
{#each Object.values(Gender) as gender}
|
||||
<option value={gender}>{gender}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label class="form-control">
|
||||
<span class="label mb-1 text-xs"
|
||||
>Age</span
|
||||
>
|
||||
<span class="label mb-1 text-xs">Age</span>
|
||||
<input
|
||||
class="input input-bordered input-sm w-full"
|
||||
type="number"
|
||||
min="1"
|
||||
max="100"
|
||||
step="1"
|
||||
bind:value={
|
||||
calculation.player.metrics
|
||||
.age
|
||||
}
|
||||
bind:value={calculation.player.metrics.age}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label class="form-control">
|
||||
<span class="label mb-1 text-xs"
|
||||
>Weight</span
|
||||
>
|
||||
<span class="label mb-1 text-xs">Weight</span>
|
||||
<select
|
||||
class="select select-bordered select-sm w-full"
|
||||
bind:value={
|
||||
calculation.player.metrics
|
||||
.weight
|
||||
}
|
||||
bind:value={calculation.player.metrics.weight}
|
||||
>
|
||||
{#each range(400) as weight (weight)}
|
||||
<option
|
||||
value={lbToKg(weight)}
|
||||
{#each range(400) as weight}
|
||||
<option value={lbToKg(weight)}
|
||||
>{weight}</option
|
||||
>
|
||||
{/each}
|
||||
@@ -474,38 +258,25 @@
|
||||
</fieldset>
|
||||
|
||||
<fieldset
|
||||
class="fieldset"
|
||||
class="fieldset bg-base-200/60 rounded-lg"
|
||||
onchange={() =>
|
||||
(calculation.levels =
|
||||
levelCalculator.calculate(
|
||||
(calculation.levels = levelCalculator.calculate(
|
||||
calculation.player,
|
||||
calculation.activityPerformances,
|
||||
))}
|
||||
>
|
||||
<legend
|
||||
class="fieldset-legend text-xs font-semibold opacity-70"
|
||||
>
|
||||
Activity performances
|
||||
</legend>
|
||||
<div class="grid grid-cols-2 md:grid-cols-3 gap-3">
|
||||
{#each calculation.activityPerformances as activityPerformance (activityPerformance.activity)}
|
||||
<label
|
||||
class="form-control space-y-1"
|
||||
>
|
||||
<span
|
||||
class="label mb-1 text-xs"
|
||||
>
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
{#each calculation.activityPerformances as activityPerformance}
|
||||
<label class="form-control space-y-1">
|
||||
<span class="label mb-1 text-xs">
|
||||
{activityPerformance.activity}
|
||||
</span>
|
||||
<select
|
||||
class="select select-bordered select-sm w-full"
|
||||
bind:value={
|
||||
activityPerformance.performance
|
||||
}
|
||||
bind:value={activityPerformance.performance}
|
||||
>
|
||||
{#each performanceOptionsFromActivity(activityPerformance.activity) as option (option.value)}
|
||||
<option
|
||||
value={option.value}
|
||||
{#each performanceOptionsFromActivity(activityPerformance.activity) as option}
|
||||
<option value={option.value}
|
||||
>{option.name}</option
|
||||
>
|
||||
{/each}
|
||||
@@ -514,41 +285,13 @@
|
||||
{/each}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
{#if calculation.saveError}
|
||||
<div
|
||||
role="alert"
|
||||
class="alert alert-error alert-sm"
|
||||
>
|
||||
<span class="text-xs"
|
||||
>{calculation.saveError}</span
|
||||
</div>
|
||||
<button
|
||||
onclick={() =>
|
||||
confirm(`Delete ${calculation.player.name}?`) &&
|
||||
calculations.splice(index, 1)}
|
||||
class="btn btn-error btn-sm w-1/4">Delete</button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
{#if calculation.deleteError}
|
||||
<div
|
||||
role="alert"
|
||||
class="alert alert-error alert-sm"
|
||||
>
|
||||
<span class="text-xs"
|
||||
>{calculation.deleteError}</span
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{:else}
|
||||
<tr>
|
||||
<td
|
||||
colspan={TABLE_COLUMNS}
|
||||
class="text-center opacity-60"
|
||||
>
|
||||
{loading ? "Loading..." : "No players yet"}
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -25,11 +25,6 @@
|
||||
path: "/activity",
|
||||
links: [{ name: "Events", path: "/events" }],
|
||||
},
|
||||
{
|
||||
name: "Verification",
|
||||
path: "/verification",
|
||||
links: [{ name: "Requests", path: "/requests" }],
|
||||
},
|
||||
];
|
||||
|
||||
let { children } = $props();
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { api } from "$lib/api";
|
||||
import { Activity } from "@blade-and-brawn/domain";
|
||||
import type { VerificationStatus } from "@blade-and-brawn/api";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
type VerificationRow = NonNullable<
|
||||
Awaited<ReturnType<typeof api.verifications.get>>["data"]
|
||||
>[number];
|
||||
|
||||
const LIMIT = 25;
|
||||
|
||||
const STATUS_BADGE: Record<VerificationStatus, string> = {
|
||||
request: "badge-info",
|
||||
in_review: "badge-warning",
|
||||
action_requested: "badge-error",
|
||||
completed: "badge-success",
|
||||
};
|
||||
|
||||
const URL_COLUMN = {
|
||||
[Activity.BackSquat]: "url_back_squat",
|
||||
[Activity.Deadlift]: "url_deadlift",
|
||||
[Activity.BenchPress]: "url_bench_press",
|
||||
[Activity.Run]: "url_run",
|
||||
[Activity.BroadJump]: "url_broad_jump",
|
||||
[Activity.ConeDrill]: "url_cone_drill",
|
||||
} as const satisfies Record<Activity, keyof VerificationRow>;
|
||||
|
||||
function videoCount(row: VerificationRow): number {
|
||||
return Object.values(Activity).filter((a) => row[URL_COLUMN[a]]).length;
|
||||
}
|
||||
|
||||
function formatDate(value: string | Date | null): string {
|
||||
if (!value) return "—";
|
||||
return new Date(value).toLocaleString();
|
||||
}
|
||||
|
||||
function errorMessage(err: unknown): string {
|
||||
const value = (err as { value?: { error?: string } })?.value;
|
||||
return (
|
||||
value?.error ??
|
||||
(err instanceof Error ? err.message : "Unknown error")
|
||||
);
|
||||
}
|
||||
|
||||
let requests = $state<VerificationRow[]>([]);
|
||||
let loading = $state(true);
|
||||
let loadError = $state<string | null>(null);
|
||||
let offset = $state(0);
|
||||
let status = $state<VerificationStatus | "">("request");
|
||||
|
||||
async function refresh() {
|
||||
loading = true;
|
||||
loadError = null;
|
||||
try {
|
||||
const res = await api.verifications.get({
|
||||
query: { status: status || undefined, limit: LIMIT, offset },
|
||||
});
|
||||
if (res.error) throw res.error;
|
||||
requests = res.data as VerificationRow[];
|
||||
} catch (err) {
|
||||
loadError = errorMessage(err);
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
function setStatus(value: string) {
|
||||
status = value as VerificationStatus | "";
|
||||
offset = 0;
|
||||
refresh();
|
||||
}
|
||||
|
||||
function prevPage() {
|
||||
offset = Math.max(0, offset - LIMIT);
|
||||
refresh();
|
||||
}
|
||||
|
||||
function nextPage() {
|
||||
offset += LIMIT;
|
||||
refresh();
|
||||
}
|
||||
|
||||
onMount(refresh);
|
||||
</script>
|
||||
|
||||
<div class="w-full flex items-center gap-2 flex-wrap mt-10 mb-5">
|
||||
<select
|
||||
class="select select-sm w-44"
|
||||
value={status}
|
||||
onchange={(e) => setStatus(e.currentTarget.value)}
|
||||
>
|
||||
<option value="">All statuses</option>
|
||||
<option value="request">Request</option>
|
||||
<option value="action_requested">Action requested</option>
|
||||
<option value="completed">Completed</option>
|
||||
</select>
|
||||
|
||||
<button
|
||||
class="btn btn-secondary btn-sm"
|
||||
onclick={refresh}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? "Refreshing..." : "Refresh"}
|
||||
</button>
|
||||
|
||||
<div class="flex-1"></div>
|
||||
|
||||
<button
|
||||
class="btn btn-neutral btn-sm"
|
||||
onclick={prevPage}
|
||||
disabled={offset === 0 || loading}
|
||||
>
|
||||
Prev
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-neutral btn-sm"
|
||||
onclick={nextPage}
|
||||
disabled={requests.length < LIMIT || loading}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if loadError}
|
||||
<div role="alert" class="alert alert-error w-full mb-4">
|
||||
<span>{loadError}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="w-full overflow-x-auto">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Player</th>
|
||||
<th>Status</th>
|
||||
<th>Videos</th>
|
||||
<th>Requested</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each requests as row (row.id)}
|
||||
<tr class="hover:bg-base-300">
|
||||
<td>{row.name}</td>
|
||||
<td>
|
||||
<div class="badge {STATUS_BADGE[row.status]}">
|
||||
{row.status}
|
||||
</div>
|
||||
</td>
|
||||
<td>{videoCount(row)} / {Object.values(Activity).length}</td>
|
||||
<td class="whitespace-nowrap">{formatDate(row.created_at)}</td>
|
||||
<td>
|
||||
<a
|
||||
class="btn btn-primary btn-xs"
|
||||
href="/verification/requests/{row.id}"
|
||||
>
|
||||
Review
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{:else}
|
||||
<tr>
|
||||
<td colspan="5" class="text-center opacity-60">
|
||||
{loading ? "Loading..." : "No verification requests"}
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -1,467 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { page } from "$app/state";
|
||||
import { goto } from "$app/navigation";
|
||||
import { api } from "$lib/api";
|
||||
import { Activity, cmToIn, kgToLb } from "@blade-and-brawn/domain";
|
||||
import type { ActivityVerifications } from "@blade-and-brawn/domain";
|
||||
import type { VerificationStatus } from "@blade-and-brawn/api";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
async function loadVerification(id: string) {
|
||||
return await api.verifications({ id }).get();
|
||||
}
|
||||
|
||||
type VerificationDetail = NonNullable<
|
||||
Awaited<ReturnType<typeof loadVerification>>["data"]
|
||||
>;
|
||||
type VerfChoice = "unset" | "pass" | "fail";
|
||||
|
||||
const ACTIVITIES = Object.values(Activity);
|
||||
|
||||
const STATUS_BADGE: Record<VerificationStatus, string> = {
|
||||
request: "badge-info",
|
||||
in_review: "badge-warning",
|
||||
action_requested: "badge-error",
|
||||
completed: "badge-success",
|
||||
};
|
||||
|
||||
const URL_COLUMN = {
|
||||
[Activity.BackSquat]: "url_back_squat",
|
||||
[Activity.Deadlift]: "url_deadlift",
|
||||
[Activity.BenchPress]: "url_bench_press",
|
||||
[Activity.Run]: "url_run",
|
||||
[Activity.BroadJump]: "url_broad_jump",
|
||||
[Activity.ConeDrill]: "url_cone_drill",
|
||||
} as const satisfies Record<Activity, keyof VerificationDetail>;
|
||||
|
||||
const VERF_COLUMN = {
|
||||
[Activity.BackSquat]: "verf_back_squat",
|
||||
[Activity.Deadlift]: "verf_deadlift",
|
||||
[Activity.BenchPress]: "verf_bench_press",
|
||||
[Activity.Run]: "verf_run",
|
||||
[Activity.BroadJump]: "verf_broad_jump",
|
||||
[Activity.ConeDrill]: "verf_cone_drill",
|
||||
} as const satisfies Record<Activity, keyof VerificationDetail>;
|
||||
|
||||
const PERF_COLUMN = {
|
||||
[Activity.BackSquat]: "perf_back_squat",
|
||||
[Activity.Deadlift]: "perf_deadlift",
|
||||
[Activity.BenchPress]: "perf_bench_press",
|
||||
[Activity.Run]: "perf_run",
|
||||
[Activity.BroadJump]: "perf_broad_jump",
|
||||
[Activity.ConeDrill]: "perf_cone_drill",
|
||||
} as const satisfies Record<Activity, keyof VerificationDetail>;
|
||||
|
||||
function formatPerformance(activity: Activity, value: number | null): string {
|
||||
if (value === null) return "—";
|
||||
switch (activity) {
|
||||
case Activity.BackSquat:
|
||||
case Activity.Deadlift:
|
||||
case Activity.BenchPress:
|
||||
return `${Math.round(kgToLb(value))} lb`;
|
||||
case Activity.Run: {
|
||||
const totalSeconds = Math.floor(value / 1000);
|
||||
const minutes = Math.floor(totalSeconds / 60);
|
||||
const seconds = totalSeconds % 60;
|
||||
return `${minutes}m ${seconds}s`;
|
||||
}
|
||||
case Activity.ConeDrill:
|
||||
return `${(value / 1000).toFixed(2)} seconds`;
|
||||
case Activity.BroadJump: {
|
||||
const inches = cmToIn(value);
|
||||
const ft = Math.floor(inches / 12);
|
||||
const rem = Math.round((inches - ft * 12) * 2) / 2;
|
||||
return `${ft}' ${rem}"`;
|
||||
}
|
||||
default:
|
||||
return "—";
|
||||
}
|
||||
}
|
||||
|
||||
function verfChoiceFrom(value: boolean | null): VerfChoice {
|
||||
if (value === true) return "pass";
|
||||
if (value === false) return "fail";
|
||||
return "unset";
|
||||
}
|
||||
|
||||
function toActivityVerifications(
|
||||
choices: Record<Activity, VerfChoice>,
|
||||
): ActivityVerifications {
|
||||
const result: ActivityVerifications = {};
|
||||
for (const activity of ACTIVITIES) {
|
||||
if (choices[activity] === "pass") result[activity] = true;
|
||||
else if (choices[activity] === "fail") result[activity] = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function errorMessage(err: unknown): string {
|
||||
const value = (err as { value?: { error?: string } })?.value;
|
||||
return (
|
||||
value?.error ??
|
||||
(err instanceof Error ? err.message : "Unknown error")
|
||||
);
|
||||
}
|
||||
|
||||
const id = page.params.id;
|
||||
|
||||
let verification = $state<VerificationDetail | null>(null);
|
||||
let loading = $state(true);
|
||||
let loadError = $state<string | null>(null);
|
||||
let stepIndex = $state(0);
|
||||
let notes = $state("");
|
||||
let verf = $state<Record<Activity, VerfChoice>>(
|
||||
Object.fromEntries(ACTIVITIES.map((a) => [a, "unset"])) as Record<
|
||||
Activity,
|
||||
VerfChoice
|
||||
>,
|
||||
);
|
||||
let submitting = $state<"action" | "complete" | undefined>();
|
||||
let submitError = $state<string | null>(null);
|
||||
|
||||
const SUMMARY_STEP = ACTIVITIES.length;
|
||||
const isSummaryStep = $derived(stepIndex === SUMMARY_STEP);
|
||||
const reviewedCount = $derived(
|
||||
ACTIVITIES.filter((a) => verf[a] !== "unset").length,
|
||||
);
|
||||
const allReviewed = $derived(reviewedCount === ACTIVITIES.length);
|
||||
const isReadOnly = $derived(
|
||||
verification?.status === "completed" ||
|
||||
verification?.status === "action_requested",
|
||||
);
|
||||
|
||||
async function load() {
|
||||
loading = true;
|
||||
loadError = null;
|
||||
try {
|
||||
const res = await loadVerification(id);
|
||||
if (res.error) throw res.error;
|
||||
if (!res.data) throw new Error("Verification not found");
|
||||
verification = res.data;
|
||||
notes = verification.reviewer_notes ?? "";
|
||||
verf = Object.fromEntries(
|
||||
ACTIVITIES.map((a) => [
|
||||
a,
|
||||
verfChoiceFrom(verification![VERF_COLUMN[a]]),
|
||||
]),
|
||||
) as Record<Activity, VerfChoice>;
|
||||
} catch (err) {
|
||||
loadError = errorMessage(err);
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
function goPrev() {
|
||||
stepIndex = Math.max(0, stepIndex - 1);
|
||||
}
|
||||
|
||||
function goNext() {
|
||||
stepIndex = Math.min(SUMMARY_STEP, stepIndex + 1);
|
||||
}
|
||||
|
||||
function setVerf(activity: Activity, choice: VerfChoice) {
|
||||
if (isReadOnly) return;
|
||||
verf[activity] = choice;
|
||||
}
|
||||
|
||||
async function requestAction() {
|
||||
submitting = "action";
|
||||
submitError = null;
|
||||
try {
|
||||
const res = await api
|
||||
.verifications({ id })
|
||||
["request-action"].post({
|
||||
reviewerNotes: notes || undefined,
|
||||
activityVerifications: toActivityVerifications(verf),
|
||||
});
|
||||
if (res.error) throw res.error;
|
||||
await goto("/verification/requests");
|
||||
} catch (err) {
|
||||
submitError = errorMessage(err);
|
||||
} finally {
|
||||
submitting = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async function complete() {
|
||||
submitting = "complete";
|
||||
submitError = null;
|
||||
try {
|
||||
const res = await api.verifications({ id }).complete.post({
|
||||
activityVerifications: toActivityVerifications(verf),
|
||||
});
|
||||
if (res.error) throw res.error;
|
||||
await goto("/verification/requests");
|
||||
} catch (err) {
|
||||
submitError = errorMessage(err);
|
||||
} finally {
|
||||
submitting = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
onMount(load);
|
||||
</script>
|
||||
|
||||
<div class="w-full mt-10 mb-5">
|
||||
<a href="/verification/requests" class="link link-hover text-sm opacity-70"
|
||||
>← Back to requests</a
|
||||
>
|
||||
</div>
|
||||
|
||||
{#if loading}
|
||||
<div class="w-full flex justify-center pt-10">
|
||||
<span class="loading loading-spinner loading-lg"></span>
|
||||
</div>
|
||||
{:else if loadError}
|
||||
<div role="alert" class="alert alert-error w-full mb-4">
|
||||
<span>{loadError}</span>
|
||||
</div>
|
||||
{:else if verification}
|
||||
{@const v = verification}
|
||||
<div class="w-full flex items-center gap-3 flex-wrap mb-6">
|
||||
<h1 class="text-xl font-semibold">{v.name}</h1>
|
||||
<div class="badge {STATUS_BADGE[v.status]}">{v.status}</div>
|
||||
<span class="text-sm opacity-70"
|
||||
>{v.gender} · age {v.age} · {Math.round(kgToLb(v.weight))} lb</span
|
||||
>
|
||||
<div class="flex-1"></div>
|
||||
<span class="text-sm opacity-70"
|
||||
>{reviewedCount} / {ACTIVITIES.length} reviewed</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div role="tablist" class="tabs tabs-border w-full">
|
||||
{#each ACTIVITIES as activity, i (activity)}
|
||||
<button
|
||||
role="tab"
|
||||
class="tab gap-2"
|
||||
class:tab-active={stepIndex === i}
|
||||
onclick={() => (stepIndex = i)}
|
||||
>
|
||||
{activity}
|
||||
{#if verf[activity] === "pass"}
|
||||
<span class="text-success">✓</span>
|
||||
{:else if verf[activity] === "fail"}
|
||||
<span class="text-error">✕</span>
|
||||
{/if}
|
||||
</button>
|
||||
{/each}
|
||||
<button
|
||||
role="tab"
|
||||
class="tab"
|
||||
class:tab-active={isSummaryStep}
|
||||
onclick={() => (stepIndex = SUMMARY_STEP)}
|
||||
>
|
||||
Summary
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if !isSummaryStep}
|
||||
{@const activity = ACTIVITIES[stepIndex]}
|
||||
<div class="w-full flex flex-col gap-4 bg-base-200/60 rounded-lg p-6 mt-4">
|
||||
<div class="flex items-center justify-between flex-wrap gap-2">
|
||||
<h2 class="text-lg font-semibold">{activity}</h2>
|
||||
<div class="text-right">
|
||||
<div class="text-xs opacity-60">Claimed</div>
|
||||
<div class="text-2xl font-bold">
|
||||
{formatPerformance(activity, v[PERF_COLUMN[activity]])}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if v[URL_COLUMN[activity]]}
|
||||
{@const videoUrl = v[URL_COLUMN[activity]]}
|
||||
<!-- svelte-ignore a11y_media_has_caption -->
|
||||
<video
|
||||
class="w-full max-h-[480px] rounded-lg bg-black"
|
||||
src={videoUrl}
|
||||
controls
|
||||
preload="metadata"
|
||||
></video>
|
||||
<a
|
||||
class="link link-primary text-xs self-start"
|
||||
href={videoUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Open video in new tab
|
||||
</a>
|
||||
{:else}
|
||||
<div
|
||||
class="w-full aspect-video rounded-lg bg-base-300 flex items-center justify-center opacity-60"
|
||||
>
|
||||
No video uploaded
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="flex gap-2 justify-center mt-2">
|
||||
<button
|
||||
class="btn btn-sm {verf[activity] === 'pass'
|
||||
? 'btn-success'
|
||||
: 'btn-outline btn-success'}"
|
||||
disabled={isReadOnly}
|
||||
onclick={() => setVerf(activity, "pass")}
|
||||
>
|
||||
Pass
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm {verf[activity] === 'fail'
|
||||
? 'btn-error'
|
||||
: 'btn-outline btn-error'}"
|
||||
disabled={isReadOnly}
|
||||
onclick={() => setVerf(activity, "fail")}
|
||||
>
|
||||
Fail
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm btn-ghost"
|
||||
disabled={isReadOnly || verf[activity] === "unset"}
|
||||
onclick={() => setVerf(activity, "unset")}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between mt-2">
|
||||
<button
|
||||
class="btn btn-neutral btn-sm"
|
||||
onclick={goPrev}
|
||||
disabled={stepIndex === 0}
|
||||
>
|
||||
← Previous
|
||||
</button>
|
||||
<button class="btn btn-neutral btn-sm" onclick={goNext}>
|
||||
Next →
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="w-full flex flex-col gap-4 bg-base-200/60 rounded-lg p-6 mt-4">
|
||||
<h2 class="text-lg font-semibold">Review summary</h2>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Activity</th>
|
||||
<th>Claimed</th>
|
||||
<th>Video</th>
|
||||
<th>Result</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each ACTIVITIES as activity, i (activity)}
|
||||
<tr>
|
||||
<td>
|
||||
<button
|
||||
class="link link-hover"
|
||||
onclick={() => (stepIndex = i)}
|
||||
>
|
||||
{activity}
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
{formatPerformance(
|
||||
activity,
|
||||
v[PERF_COLUMN[activity]],
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
{#if v[URL_COLUMN[activity]]}
|
||||
<a
|
||||
class="link link-primary"
|
||||
href={v[URL_COLUMN[activity]]}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
View
|
||||
</a>
|
||||
{:else}
|
||||
<span class="opacity-50">None</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td>
|
||||
{#if verf[activity] === "pass"}
|
||||
<span class="badge badge-success"
|
||||
>Pass</span
|
||||
>
|
||||
{:else if verf[activity] === "fail"}
|
||||
<span class="badge badge-error"
|
||||
>Fail</span
|
||||
>
|
||||
{:else}
|
||||
<span class="badge badge-ghost"
|
||||
>Unreviewed</span
|
||||
>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<label class="form-control">
|
||||
<span class="label mb-1 text-xs">Reviewer notes</span>
|
||||
<textarea
|
||||
class="textarea textarea-bordered w-full"
|
||||
rows="3"
|
||||
placeholder="What needs to be fixed?"
|
||||
disabled={isReadOnly}
|
||||
bind:value={notes}
|
||||
></textarea>
|
||||
</label>
|
||||
|
||||
{#if submitError}
|
||||
<div role="alert" class="alert alert-error">
|
||||
<span>{submitError}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="flex items-center gap-2 justify-between">
|
||||
<button
|
||||
class="btn btn-neutral btn-sm"
|
||||
onclick={goPrev}
|
||||
disabled={stepIndex === 0}
|
||||
>
|
||||
← Previous
|
||||
</button>
|
||||
|
||||
{#if isReadOnly}
|
||||
<span class="text-sm opacity-70">
|
||||
{v.status === "completed"
|
||||
? "This verification is completed and read-only."
|
||||
: "This verification is waiting on the player to resubmit and is read-only."}
|
||||
</span>
|
||||
{:else}
|
||||
<div class="flex items-center gap-2">
|
||||
{#if !allReviewed}
|
||||
<span class="text-xs text-warning"
|
||||
>Mark every activity Pass or Fail to complete</span
|
||||
>
|
||||
{/if}
|
||||
<button
|
||||
class="btn btn-warning"
|
||||
disabled={!!submitting}
|
||||
onclick={requestAction}
|
||||
>
|
||||
{submitting === "action"
|
||||
? "Submitting..."
|
||||
: "Request action"}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-success"
|
||||
disabled={!!submitting || !allReviewed}
|
||||
onclick={complete}
|
||||
>
|
||||
{submitting === "complete"
|
||||
? "Submitting..."
|
||||
: "Complete"}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -2,7 +2,6 @@
|
||||
import "../app.css";
|
||||
import { goto } from "$app/navigation";
|
||||
import { api } from "$lib/api";
|
||||
import { env } from "$env/dynamic/public";
|
||||
|
||||
let error = $state("");
|
||||
let loading = $state(false);
|
||||
@@ -15,10 +14,7 @@
|
||||
|
||||
loading = true;
|
||||
try {
|
||||
const { status } = await api.auth.login.post({
|
||||
email: env.PUBLIC_ADMIN_EMAIL ?? "",
|
||||
password,
|
||||
});
|
||||
const { status } = await api.auth.login.post({ password });
|
||||
|
||||
if (status === 401) {
|
||||
error = "Invalid password";
|
||||
@@ -26,9 +22,11 @@
|
||||
}
|
||||
|
||||
await goto("/");
|
||||
} catch {
|
||||
}
|
||||
catch {
|
||||
error = "Unable to reach the server. Please try again.";
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"pino": "^10.3.1",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "^1.4.2",
|
||||
"@types/bun": "^1.3.14",
|
||||
"typescript": "^7.0.2",
|
||||
},
|
||||
},
|
||||
@@ -22,9 +22,9 @@
|
||||
"@elysia/jwt": "^1.4.2",
|
||||
"@elysia/server-timing": "^1.4.1",
|
||||
"@elysiajs/cors": "^1.4.2",
|
||||
"@types/pg": "^8.23.1",
|
||||
"elysia": "^1.4.30",
|
||||
"kysely": "^0.29.6",
|
||||
"@types/pg": "^8.21.0",
|
||||
"elysia": "^1.4.29",
|
||||
"kysely": "^0.29.5",
|
||||
"ml-levenberg-marquardt": "^5.1.0",
|
||||
"pg": "^8.23.0",
|
||||
"zipcodes-us": "^1.1.3",
|
||||
@@ -52,16 +52,16 @@
|
||||
"@blade-and-brawn/domain": "workspace:*",
|
||||
"@elysia/eden": "^1.4.10",
|
||||
"@tailwindcss/vite": "^4.3.3",
|
||||
"daisyui": "^5.7.38",
|
||||
"jose": "^6.2.12",
|
||||
"daisyui": "^5.7.17",
|
||||
"jose": "^6.2.9",
|
||||
"tailwindcss": "^4.3.3",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blade-and-brawn/api": "workspace:*",
|
||||
"@sveltejs/kit": "^2.70.3",
|
||||
"@sveltejs/kit": "^2.70.2",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
||||
"elysia": "^1.4.30",
|
||||
"svelte": "^5.57.0",
|
||||
"elysia": "^1.4.29",
|
||||
"svelte": "^5.56.9",
|
||||
"svelte-adapter-bun": "^1.0.1",
|
||||
"svelte-check": "^4.7.6",
|
||||
"vite": "^7.3.6",
|
||||
@@ -107,7 +107,7 @@
|
||||
|
||||
"@blade-and-brawn/portal": ["@blade-and-brawn/portal@workspace:apps/portal"],
|
||||
|
||||
"@borewit/text-codec": ["@borewit/text-codec@0.2.2", "", {}, "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ=="],
|
||||
"@borewit/text-codec": ["@borewit/text-codec@0.2.1", "", {}, "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw=="],
|
||||
|
||||
"@discordjs/builders": ["@discordjs/builders@1.14.1", "", { "dependencies": { "@discordjs/formatters": "^0.6.2", "@discordjs/util": "^1.2.0", "@sapphire/shapeshift": "^4.0.0", "discord-api-types": "^0.38.40", "fast-deep-equal": "^3.1.3", "ts-mixer": "^6.0.4", "tslib": "^2.6.3" } }, "sha512-gSKkhXLqs96TCzk66VZuHHl8z2bQMJFGwrXC0f33ngK+FLNau4hU1PYny3DNJfNdSH+gVMzE85/d5FQ2BpcNwQ=="],
|
||||
|
||||
@@ -129,57 +129,63 @@
|
||||
|
||||
"@elysiajs/cors": ["@elysiajs/cors@1.4.2", "", { "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-FTCcbH35brTLigF1W7BYySRZomgI/dBEMK9BgK9RP9Nez7zmpGh4koL/Yr1BFv8nYz7CfhRvcM8d/c+XnwMaVQ=="],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ=="],
|
||||
"@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.28.2", "", { "os": "android", "cpu": "arm" }, "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg=="],
|
||||
"@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="],
|
||||
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.2", "", { "os": "android", "cpu": "arm64" }, "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A=="],
|
||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="],
|
||||
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.28.2", "", { "os": "android", "cpu": "x64" }, "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q=="],
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="],
|
||||
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw=="],
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="],
|
||||
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw=="],
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="],
|
||||
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw=="],
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="],
|
||||
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg=="],
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="],
|
||||
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.2", "", { "os": "linux", "cpu": "arm" }, "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w=="],
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="],
|
||||
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug=="],
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="],
|
||||
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ=="],
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="],
|
||||
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.2", "", { "os": "linux", "cpu": "none" }, "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ=="],
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="],
|
||||
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.2", "", { "os": "linux", "cpu": "none" }, "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA=="],
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="],
|
||||
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ=="],
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="],
|
||||
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.2", "", { "os": "linux", "cpu": "none" }, "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA=="],
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="],
|
||||
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg=="],
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="],
|
||||
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.2", "", { "os": "linux", "cpu": "x64" }, "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ=="],
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="],
|
||||
|
||||
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.2", "", { "os": "none", "cpu": "arm64" }, "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw=="],
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="],
|
||||
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.2", "", { "os": "none", "cpu": "x64" }, "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw=="],
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="],
|
||||
|
||||
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ=="],
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="],
|
||||
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw=="],
|
||||
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="],
|
||||
|
||||
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.2", "", { "os": "none", "cpu": "arm64" }, "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q=="],
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="],
|
||||
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g=="],
|
||||
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="],
|
||||
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ=="],
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="],
|
||||
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA=="],
|
||||
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="],
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g=="],
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="],
|
||||
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="],
|
||||
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="],
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="],
|
||||
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||
|
||||
@@ -187,99 +193,99 @@
|
||||
|
||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.6.0", "", {}, "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw=="],
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
||||
|
||||
"@napi-rs/lzma-linux-x64-gnu": ["@napi-rs/lzma-linux-x64-gnu@1.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ=="],
|
||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.6", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg=="],
|
||||
|
||||
"@oxc-project/types": ["@oxc-project/types@0.149.0", "", {}, "sha512-Efcc+iF0j3Bf67YjEqIqWXbX5XddXoK/Mw4K1/JuXwRCZ8N16VR7iT23nlCc9XrveFVh/E5Rqs2StT0V8v9LdA=="],
|
||||
"@oxc-project/types": ["@oxc-project/types@0.138.0", "", {}, "sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA=="],
|
||||
|
||||
"@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="],
|
||||
|
||||
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
|
||||
|
||||
"@rolldown/binding-android-arm-eabi": ["@rolldown/binding-android-arm-eabi@1.2.8", "", { "os": "android", "cpu": "arm" }, "sha512-tN5aztYkKCte4i5SIrrz5yK/HMjEuCqCSCJa418jOV8tZ1cBY3YF2otxB1ktPxzsLA1BeTqwapK0bfjxNvHJVw=="],
|
||||
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.1.4", "", { "os": "android", "cpu": "arm64" }, "sha512-EZLpf/8y7GXkkra90ML47kzik/GMP3EMcE9bPyHmRfxLC6z9+aW5A8poCsoxjrT5GfEcNAAvWwUHjvP1pUQkfw=="],
|
||||
|
||||
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.2.8", "", { "os": "android", "cpu": "arm64" }, "sha512-dIYTWl9XprMUiQFoc55KUyk/oS8SKYH3zFl0LTR7RT0Xj4hgSVyuJcroH8JUu8RcpF8fTB6E0aOwCkZoYPcDSQ=="],
|
||||
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.1.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-aUi+HBvmYb7j8krl1+qJgkG8C17fO79gk3c+jPw4S8glRFc1DTija9S3EyaTSQUm5GJXYKDAsugBEhFHH2vYiQ=="],
|
||||
|
||||
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.2.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-PCSDQGXD2IyTEFrcgPyBM8jJuGmrbCMuoIOXdbEGVemruKACXoLQJrb+A45Z0L5t1RQkdfJprAYPkikbh7dzdA=="],
|
||||
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.1.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-F7hHC3gwY11+vByKPRWqwGbeXWVgKmL+pTGCinaEhdihzBV2aQ0fvZOch9cXYUOKuKKq429HeYXOqQLc7wFCEg=="],
|
||||
|
||||
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.2.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-Uk7lRsGhPFHVX/sAUC6D5H9Ol30dFHd6iquokll2th3LpdJ3F5CzQB+7DHn0Ri2mG+U7k2zXiPHDrwZenXhwSA=="],
|
||||
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.1.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-sI5yw+7s92SK6odiEhD5lKCBlWcpjHS5qyqpVQbZAJ0fIzEUXrmbl3DH2ybR3PZogulNJF+COLtmA8hUfvkCCQ=="],
|
||||
|
||||
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.2.8", "", { "os": "freebsd", "cpu": "x64" }, "sha512-DjszaTEVogPqA5bYzsEeqDCQxbcp2fexQwKcRspYji2yzR68fCf+e4fx6kBSRDwX5/brZaHw/hWS9+A/+/w9sQ=="],
|
||||
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.1.4", "", { "os": "linux", "cpu": "arm" }, "sha512-mCi0OKgEieFircrtVYmQAFGszRtMnZ6fpZAXrxanXAu7lqZcsK1E1RAaZNG0uKAnxox3B1f4EyQNnoyMfN1vAA=="],
|
||||
|
||||
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.2.8", "", { "os": "linux", "cpu": "arm" }, "sha512-zmwa7FTmdzB6aaEEuuls18H6Ap5JmJPSoPTuXixeJZV6tG40SyLkApQtz1g8ptZtiEKqj9OM0oNLPh1AgvE31Q=="],
|
||||
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.1.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-B9Ial3Kv5sh0SHnB1g/QWcUQCEvCF6QKGAl4zXypYj65mVI+B4AhFBwPtSN7pDrJeIx8Z7zdy4ntx+wQABom7w=="],
|
||||
|
||||
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.2.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-KdYQDPHwJVnbFwdTGMgxsI9SqblBlz6STGM+w1We/d5B8OWWidYH0MwkU/uA1wM5fIpO2MkOVxXrNzzuZhw9ew=="],
|
||||
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.1.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-lZVym0PuHE1KZ22gmFTC15lAkrg9iTszR617oYRB/iPY1A56ywoJzVKOJBKaot5RiikCObmur6pogpse3gRcng=="],
|
||||
|
||||
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.2.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-jFJTifHnNPY+yzOoNZQfSIysrVyXzEQPhPnOUjmD1bcQGHH6s7c8cViKWar8YplQImE5N9JRqMCLrM2CdxOrZA=="],
|
||||
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.1.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-t2DNiLJWNTbnEHyUzTumldML6ET4/g16467LZoDDJ3tSxGvguL5/NyC2lCsNKuyRycg9XeDQF5SSv+TNOhQEXg=="],
|
||||
|
||||
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.2.8", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FhiOziBDWPBjbcmRzfLyIJnaP7AVMFXT7YCXPjXxj7wKU3vx24RjrCNN/zjvVa+N2vVoHJwCoUBvsrN/DG3zIA=="],
|
||||
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.1.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-0WIRnL1Uw4BvTZRLQt+PVgo6ZKTJadlC2btP+/EOXv2f/DWbY0rEgl+y834mIVwP1FkTlWVTrGGJXf12lru7EQ=="],
|
||||
|
||||
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.2.8", "", { "os": "linux", "cpu": "s390x" }, "sha512-WnHfADMzOV2Y55wlx1hzzQnar/wDt/VdvWSD99r18Mz9ylNieIGOkRx3UV21h7m/eJvjySYJkO26VvGNFkwsIQ=="],
|
||||
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.1.4", "", { "os": "linux", "cpu": "x64" }, "sha512-JWtGshGfX+oENAKonoNkqEJX+7hC8yfhi9GUyPX1VX4mdh1y5r+ZiJLR5XzAB0aoP6s/PcILsGjKq8O0mm24bw=="],
|
||||
|
||||
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.2.8", "", { "os": "linux", "cpu": "x64" }, "sha512-H9tRr5ibfXFVLxbPOseVewewFpl28zcEdjRDt2FTUZU7odxP0gEv1ki4/kGmcGOh78oRwZuuQllGLZ9zTJp84g=="],
|
||||
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.1.4", "", { "os": "linux", "cpu": "x64" }, "sha512-rT6yQcxUuXs4CnbofqwHRRV0iem349rLMYpTjkgQGLjrY4ado/eDzwPZPTCgTOlF6Nkp8NEv70yLMTn6qkWxsQ=="],
|
||||
|
||||
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.2.8", "", { "os": "linux", "cpu": "x64" }, "sha512-UefiqfM3D6IVNlZ8tSGs9+Ejjud2T+oxO0IHADU45Y+lyEjD2dVFyZHbkfX0LUb5Zugo/oIv1eCO/KVYhgYJYA=="],
|
||||
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.1.4", "", { "os": "none", "cpu": "arm64" }, "sha512-KXMGoboq5cyaCQjDA4GLuRiOwBQ0EyFnJoVViLeZ45/3rFItRODEr+NdsBcVpll40hhNArlm/speWGRvj08LzA=="],
|
||||
|
||||
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.2.8", "", { "os": "none", "cpu": "arm64" }, "sha512-637Ke4kWSy6rp9cxQ9gMOXlxPgIw/c1beASV4M//3+9I4uwBVOOl74G+e3zyU3u19U7RkRl/HuewixZ/Z6+Rjg=="],
|
||||
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.1.4", "", { "dependencies": { "@emnapi/core": "1.11.1", "@emnapi/runtime": "1.11.1", "@napi-rs/wasm-runtime": "^1.1.6" }, "cpu": "none" }, "sha512-5K83rb36oJiY7BCyE9zLZtGcPV4g5wvq+xwdO0XPIwDVZI8cyB/AUjkNXGb92/rnmezEkjMOpgY61rtwjQtFwg=="],
|
||||
|
||||
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.2.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-xWBkPOF1Q9k/Gv1nQXnVdLxKu74jXppuOM4Z3mnypVUJJJwLsMl7hNJGRAUJoG8A5MgOI1ACKM+wBFxSJzKy4A=="],
|
||||
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.1.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-PnWBtw3TV5KOg69HQQDR0mnQuyCmSGR2pAB4DC1rPF808fgKeTUMj2EOEyKATpgiuxuR5APQmiDO7PDgEjTFSA=="],
|
||||
|
||||
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.2.8", "", { "os": "win32", "cpu": "x64" }, "sha512-uz2ZvfgXbxqNwijjjbxrnvALwpyODDcgc1T1N8N3rf/DXKQmaFwmB4LX4yyjggpwN2obdQLb2rgirX5ffCWYng=="],
|
||||
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.1.4", "", { "os": "win32", "cpu": "x64" }, "sha512-M1lpniBePobTfsa7Ks9a199e1akxsXn+GYBUKsEzv3YFzOm1HJAMNwKI3qr0Zq+mxwx9gOZoTdP1yXRYsZUocQ=="],
|
||||
|
||||
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="],
|
||||
|
||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.63.3", "", { "os": "android", "cpu": "arm" }, "sha512-w3Jnvi1ocaVm/c7yVPpfB98XeSRBMyzp6njL5MVVbGyXjpmUkN+s6Hp4t0PqhGCCaI1ZHMKXt/w0lA1RCaLVcw=="],
|
||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.59.0", "", { "os": "android", "cpu": "arm" }, "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg=="],
|
||||
|
||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.63.3", "", { "os": "android", "cpu": "arm64" }, "sha512-uI/ESiaIbbRYAEhzy8PCUWDp1hB0bjAqM06mW9flOoNO4Q8DQpeoREhBR5Hegfl+wpXiguyJv6XSPzEN7OxyHQ=="],
|
||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.59.0", "", { "os": "android", "cpu": "arm64" }, "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q=="],
|
||||
|
||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.63.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oxhrd1jmXLwWZ83eQYDXxuqRdkqkzrjR3JobKeuUyfdNZo11FuQIvqEOZhyIT7OBHxXoGslDDjN0cQcM6T0TqQ=="],
|
||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.59.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg=="],
|
||||
|
||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.63.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-7/YiIMghVE8DrxKvNdorAaJVdriOFgOIpdStnPx8ppx5zfTwC3jBCSEAIzB7JD5404m65THl6H93UTTVUvypmg=="],
|
||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.59.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w=="],
|
||||
|
||||
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.63.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-GXFZRRoMAytaI5z6N3Zhfw0WL18Q0M8r95D5hlC4GqE/lGk8pbSJNUBoOWDfbm6dTciqHj2nU87tI5f6XhQiOg=="],
|
||||
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.59.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA=="],
|
||||
|
||||
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.63.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-77W+8X3ddYgPxUpB8nZFQs2Mq+wc4HVlcSRtApXLjYBcnPMkttrSnU8VwKQjeWYhMsITHFs5cWBQ8vz1Q+5RHQ=="],
|
||||
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.59.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.63.3", "", { "os": "linux", "cpu": "arm" }, "sha512-FVkwK+iUC+mq+GipVK46rRVticfAPtvPUNlqlGXUDxdVk/UGjQiiiUVPUrEXdSpU2ufU0XxLGyTqDtBidDOVmg=="],
|
||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.63.3", "", { "os": "linux", "cpu": "arm" }, "sha512-+aGU1t3398yQOVj1Bz8o3e+KtswxAPvO+mtxtNdfXYMkXIHu7XhhkCD7/DEH9q8tF8uhDnMWvfpUKI8y1sZJsg=="],
|
||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.63.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-cR0kjpRXR2KJ2oQK8E2KTPtphs+b9hZ8IhTZubNryt/RsqgdOZBQ2Zq0q5UedtiIi0rs3jVhJh55RE1ZHUVGUA=="],
|
||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.63.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-y1RYi4Q3/9ByVWSSt9kX2ustE0B7kFYbJ6zZdVZVyqopZs3yhCTwRfrjIX4vezUJInma/Gs6BOFDJg7yZmJ0IQ=="],
|
||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA=="],
|
||||
|
||||
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.63.3", "", { "os": "linux", "cpu": "none" }, "sha512-DNhEA5viIj3Z5bZLE4z4oV8N5ozWqDwyt7T6KG7VdLDJ0nW+rNOYlphBl4/3HQkK75qipPLsVOfStHHOwN9WSg=="],
|
||||
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg=="],
|
||||
|
||||
"@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.63.3", "", { "os": "linux", "cpu": "none" }, "sha512-17gQCqrIpXBX2Cmi9/TygnVOqGbzsba/iaqcYSL8FY7lNugg+7AiYNs5c5nKWD+NRQha36Sa0CqkJqH4XVHwnQ=="],
|
||||
"@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q=="],
|
||||
|
||||
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.63.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-6LwVnZRIyINpdku/yOcI8Tm9YqLmhHK5emmlOOnW9tO0SYEm1FmKPcsSAGp0NBlqR2P04xaND4jvN6sTHqhq8A=="],
|
||||
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA=="],
|
||||
|
||||
"@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.63.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-xMUqkTXlEUtI/p5AAukMwBRr1enU3efsTeF+bskeFfk8t1C9rcC8sLREcZXmTfAXEbvRdJVSonVJez3TMlbR3w=="],
|
||||
"@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA=="],
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.63.3", "", { "os": "linux", "cpu": "none" }, "sha512-S3E94co9F9WRRqEaUoQZ38K1gCz6KiM+nL7/3ijq7fDGF3OznjS5TasgYITlvl27GQKtu4lOAOsr5MFwkijvOA=="],
|
||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg=="],
|
||||
|
||||
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.63.3", "", { "os": "linux", "cpu": "none" }, "sha512-1QtRDwG42x5BJI3s9mxu5rEjDnfbSnk20HQ9/ylTAYnSwYwxMVb+Vgu34wzzTQ7ogqBybebgQNUDAvZVQ38DbA=="],
|
||||
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg=="],
|
||||
|
||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.63.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-BQhejF6ZXOpxbngiNTP12GCGQeaDVL2QXGeBVViKIYzFHM5RKxTxwUMB1fr1BeNFphFMpnRqC5QSXFSa4z6UQw=="],
|
||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.59.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.63.3", "", { "os": "linux", "cpu": "x64" }, "sha512-SXagRwnI2Wlwlitllu59UK/nGVbD1CKPcNqDplHwIC4BqJcpXFjD32d1R/RbuISa95HdQrZM3/7v4bKiowFaLA=="],
|
||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.63.3", "", { "os": "linux", "cpu": "x64" }, "sha512-2IPozoEALRCziGqE8O9KMK60PMu5TS1huv4fwoeCexj+WjmcwFtX9CTOVbfXCUqcELAubEwRFPYlzb/WvwY2HQ=="],
|
||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg=="],
|
||||
|
||||
"@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.63.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-AoxqosUHT9IX54hFn2TiN6A7d6ZKTtE6pd2bqWtqkkNJ6HJGaU6FRouGX8L1O7R/ZwsnCnpQrHzb4pDEx+UHRQ=="],
|
||||
"@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.59.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ=="],
|
||||
|
||||
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.63.3", "", { "os": "none", "cpu": "arm64" }, "sha512-d+CaftKgmkFBzCwezMqqy1d0QNNYugqLCMcYVQWBy5SS2YfeMP8Q8ripkgx9O8IyBXXLHrJ+aaCV4U96usv6Yg=="],
|
||||
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.59.0", "", { "os": "none", "cpu": "arm64" }, "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA=="],
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.63.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-xXlDF6nR1eOuXbdDy5Hl5fmtY7teUDevF/k0O7IPoZe4Tpmdv+lgdE5JRsnhQtt37ql9P0VF2kAN9a0OCZdo+Q=="],
|
||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.59.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A=="],
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.63.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-YtXAgLN+JP7Ay6qG3eWhc7IHMQPzLc8r3uvhAvlJIoCz/4Q32+Bl9Fmnywidh8v1GOIMmymjovfqY9ETAtysvA=="],
|
||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.59.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA=="],
|
||||
|
||||
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.63.3", "", { "os": "win32", "cpu": "x64" }, "sha512-WuWtSJRNo549vzcfZyEgfqb6zeSgn1F+UE5kQ+BCjzz0W4MGCjntUHkZVc1VRuAM7+ULaSyhiPxD1spyewFvkQ=="],
|
||||
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA=="],
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.63.3", "", { "os": "win32", "cpu": "x64" }, "sha512-+lIKX7O0+IGe7WuhATaAMMeT7B76vfhXH/l9wLQL+nvyhbw2ohYCKIdWL56JfDu75CWt5oKRP4QFH/jkMtBquA=="],
|
||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA=="],
|
||||
|
||||
"@sapphire/async-queue": ["@sapphire/async-queue@1.5.5", "", {}, "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg=="],
|
||||
|
||||
@@ -291,9 +297,9 @@
|
||||
|
||||
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||
|
||||
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.13", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-wgKggnhZVL9Bfx1OaKKTrYY9BFRk6C8UAkQNUcIv1+llzYrIqy+RZm5HPKzn0NpEBvTVhTqB4kQyllZywsRBRQ=="],
|
||||
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.10", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-4WfKk68eTih+MiJD4fSbxN7E8kVBmTMPWHUPYjvl2N0rMs53YLTT8/YjKU5Dtnz5LqDjl7LEw4U7lXR2W3J5WA=="],
|
||||
|
||||
"@sveltejs/kit": ["@sveltejs/kit@2.70.3", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.9", "@types/cookie": "^0.6.0", "acorn": "^8.16.0", "cookie": "^0.6.0", "devalue": "^5.8.1", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "set-cookie-parser": "^3.0.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": "^5.3.3 || ^6.0.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0" }, "optionalPeers": ["@opentelemetry/api", "typescript"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-UDvEYuZqAMbfB/oXIoqKvbKcb7YczK5zYrzmsGV1zRJk03jntwp8dXiYoIJotxAndsKvcPFtx9H1GRSKFdSHgg=="],
|
||||
"@sveltejs/kit": ["@sveltejs/kit@2.70.2", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.9", "@types/cookie": "^0.6.0", "acorn": "^8.16.0", "cookie": "^0.6.0", "devalue": "^5.8.1", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "set-cookie-parser": "^3.0.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": "^5.3.3 || ^6.0.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0" }, "optionalPeers": ["@opentelemetry/api", "typescript"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-RzRoRpuR2KXqc5yMO0akQHDZeT4AslOlznGITURsqHaVbtyYP4Wn3eE3gxj9JcDyNYO0crkxhdwFHc+2vkVm6w=="],
|
||||
|
||||
"@sveltejs/load-config": ["@sveltejs/load-config@0.2.3", "", {}, "sha512-VT3qmUb8pRV2QrZjd8iAmtg8lf4W0TIjZbvXtz5MKei/q96teWZgGJyyidJzOjzZzvdq616eSRVeMYIQChUTAQ=="],
|
||||
|
||||
@@ -335,15 +341,19 @@
|
||||
|
||||
"@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.4.2", "", { "dependencies": { "bun-types": "1.4.2" } }, "sha512-GimotNn7+ZV0uVArItBbriZsR1oNf0+WTzPkdcFrzShI7k2norL0uzEaJT8T33dWr7O/c9ZDuAFQrctKCi72oQ=="],
|
||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="],
|
||||
|
||||
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
|
||||
|
||||
"@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
|
||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||
|
||||
"@types/node": ["@types/node@26.2.0", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg=="],
|
||||
"@types/node": ["@types/node@25.3.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ=="],
|
||||
|
||||
"@types/pg": ["@types/pg@8.23.1", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-fKVHpikPdg4GKks3JuLEhvwSyvwzF23hnabPy6DD8ljVbC7+6J5dQzdv4arV6jqq57djnMgs1HKBxX4P8aBI3A=="],
|
||||
"@types/pg": ["@types/pg@8.21.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-AYdtudzabjLZgVgRZmAnU8bAnVUXzuJX2IYHeSIiIHm68olD+LgQYCGWdtcNYnP0uq9c4S4NibVG3Ni7VbKW7Q=="],
|
||||
|
||||
"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
|
||||
|
||||
"@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
|
||||
|
||||
@@ -389,7 +399,7 @@
|
||||
|
||||
"@vladfrangu/async_event_emitter": ["@vladfrangu/async_event_emitter@2.4.7", "", {}, "sha512-Xfe6rpCTxSxfbswi/W/Pz7zp1WWSNn4A0eW4mLkQUewCrXXtMj31lCg+iQyTkh/CkusZSq9eDflu7tjEDXUY6g=="],
|
||||
|
||||
"acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="],
|
||||
"acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
||||
@@ -403,7 +413,7 @@
|
||||
|
||||
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
||||
|
||||
"bun-types": ["bun-types@1.4.2", "", { "dependencies": { "@types/node": "*" } }, "sha512-bxV1FgK7yBIzjRe5zBozIM4Bem11ZJcCXSrjWRG3YWLt8yFDePu4cLjpebO8OvPeIE9trbyPF4fuj3Cia4Fj3w=="],
|
||||
"bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
|
||||
|
||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||
|
||||
@@ -423,7 +433,7 @@
|
||||
|
||||
"cosmiconfig": ["cosmiconfig@9.0.2", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg=="],
|
||||
|
||||
"daisyui": ["daisyui@5.7.38", "", {}, "sha512-ef3RIbteKVmlQ10ak0l4mu8F70pBJ2UBjDJNsA2vWlpNdErpHqfxddxK2ckNNYd7vQvTqP4a1A1vSsunlCGVOw=="],
|
||||
"daisyui": ["daisyui@5.7.17", "", {}, "sha512-w5U5FdL9hH4/zh8eLXytWQt3c0DgHS1WDw+1yuQykT8nSIE9Vc5wkJVeDymD1JlRDLANDawvN4iIGVaxgV6Cjw=="],
|
||||
|
||||
"dateformat": ["dateformat@4.6.3", "", {}, "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA=="],
|
||||
|
||||
@@ -433,11 +443,11 @@
|
||||
|
||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||
|
||||
"devalue": ["devalue@5.9.2", "", {}, "sha512-po4PAY5c53tw5XMocSnf8A/5OHhbbUftpr93aEN6BBoAdntUmK7vu7wOATqvt7cXO7m1Cl4gMVn6p7n6n4mj0w=="],
|
||||
"devalue": ["devalue@5.8.1", "", {}, "sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw=="],
|
||||
|
||||
"diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="],
|
||||
|
||||
"discord-api-types": ["discord-api-types@0.38.55", "", {}, "sha512-ytuaRTzdnHUCXJ6KjL9MrItQX0xKncBKEeYI1Bst4+ud47eejH3cG6gaesYakjpPcUhh68XYS2YwGq3mmujFsA=="],
|
||||
"discord-api-types": ["discord-api-types@0.38.53", "", {}, "sha512-HL1zz/UuZ+bbJjA/X8Kbxx9gk8v9rJAbTeWRNYKmIdjwJ7EovjlHgoJTxcLpATfNJ+AonOtMdy3Y5MVIJAAd/A=="],
|
||||
|
||||
"discord.js": ["discord.js@14.27.0", "", { "dependencies": { "@discordjs/builders": "^1.14.1", "@discordjs/collection": "1.5.3", "@discordjs/formatters": "^0.6.2", "@discordjs/rest": "^2.6.2", "@discordjs/util": "^1.2.0", "@discordjs/ws": "^1.2.3", "@sapphire/snowflake": "3.5.5", "discord-api-types": "^0.38.49", "fast-deep-equal": "3.1.3", "lodash.snakecase": "4.1.1", "magic-bytes.js": "^1.13.0", "tslib": "^2.6.3", "undici": "^6.27.0" } }, "sha512-qHbFlFG2N7y3LjPySYsL6A1+BnX6bkTVgo842EX0CqVPk/KTMwZkojPHEXKsQUpWZNyz5BISNHK1cPpQw0+m4A=="],
|
||||
|
||||
@@ -445,25 +455,25 @@
|
||||
|
||||
"dotenv-expand": ["dotenv-expand@12.0.3", "", { "dependencies": { "dotenv": "^16.4.5" } }, "sha512-uc47g4b+4k/M/SeaW1y4OApx+mtLWl92l5LMPP0GNXctZqELk+YGgOPIIC5elYmUH4OuoK3JLhuRUYegeySiFA=="],
|
||||
|
||||
"elysia": ["elysia@1.4.30", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.7", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-S2qqV0CbM4faB1hQQ5IYoeYnAUinjHlzRduxaBc4OoNqh0GjOc8k6tt3hv5ozWcG6Svr6hugw6JL4zNke4jwfA=="],
|
||||
"elysia": ["elysia@1.4.29", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.7", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-GwMRGGwSdjfPt+w3LA0fqTuYJtS8uVRJicvoar98/HrO5qdFKDc9CwjIb6Kja+v39lkY+58hr2JvdR9jQzlUuA=="],
|
||||
|
||||
"end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
|
||||
|
||||
"enhanced-resolve": ["enhanced-resolve@5.25.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-nGXts5znJzmWPu+mIE9izCOzdg63oJca2mDzGWWTth7sr4aCToKcoyFVBQwN75Ij5Pf6p510EwkTqViTRzDV+w=="],
|
||||
"enhanced-resolve": ["enhanced-resolve@5.24.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-rpsZEGT1jFuve6QlpyRp9ckQ+kN61hvF9BzCPyMdaKTm8UJce96KBn3sorXOFXlzjPrs3Vc4T1NsSroZ3PxlFw=="],
|
||||
|
||||
"env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="],
|
||||
|
||||
"error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="],
|
||||
|
||||
"esbuild": ["esbuild@0.28.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.2", "@esbuild/android-arm": "0.28.2", "@esbuild/android-arm64": "0.28.2", "@esbuild/android-x64": "0.28.2", "@esbuild/darwin-arm64": "0.28.2", "@esbuild/darwin-x64": "0.28.2", "@esbuild/freebsd-arm64": "0.28.2", "@esbuild/freebsd-x64": "0.28.2", "@esbuild/linux-arm": "0.28.2", "@esbuild/linux-arm64": "0.28.2", "@esbuild/linux-ia32": "0.28.2", "@esbuild/linux-loong64": "0.28.2", "@esbuild/linux-mips64el": "0.28.2", "@esbuild/linux-ppc64": "0.28.2", "@esbuild/linux-riscv64": "0.28.2", "@esbuild/linux-s390x": "0.28.2", "@esbuild/linux-x64": "0.28.2", "@esbuild/netbsd-arm64": "0.28.2", "@esbuild/netbsd-x64": "0.28.2", "@esbuild/openbsd-arm64": "0.28.2", "@esbuild/openbsd-x64": "0.28.2", "@esbuild/openharmony-arm64": "0.28.2", "@esbuild/sunos-x64": "0.28.2", "@esbuild/win32-arm64": "0.28.2", "@esbuild/win32-ia32": "0.28.2", "@esbuild/win32-x64": "0.28.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA=="],
|
||||
"esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="],
|
||||
|
||||
"esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="],
|
||||
|
||||
"esrap": ["esrap@2.3.7", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, "peerDependencies": { "@typescript-eslint/types": "^8.2.0" }, "optionalPeers": ["@typescript-eslint/types"] }, "sha512-n2nf7fZR3c9yXf0BPEuHuXqT+KW0SJVj4cN5FMEkpCZ3scLjOQWpiccyCxVzCC2q1wubTghuEGzngJY/7Ah0Ow=="],
|
||||
"esrap": ["esrap@2.2.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, "peerDependencies": { "@typescript-eslint/types": "^8.2.0" }, "optionalPeers": ["@typescript-eslint/types"] }, "sha512-On0QbLyaiAkVC4eXtgnXK9Kh2opit+3rcUSOc45DqJ2s/X2eXAHsGOKRSJ6IDagQEW5vPyivANfXUiqgXC67Rw=="],
|
||||
|
||||
"exact-mirror": ["exact-mirror@0.2.7", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-+MeEmDcLA4o/vjK2zujgk+1VTxPR4hdp23qLqkWfStbECtAq9gmsvQa3LW6z/0GXZyHJobrCnmy1cdeE7BjsYg=="],
|
||||
|
||||
"fast-copy": ["fast-copy@4.1.1", "", {}, "sha512-A4QTJmuiztpGtr6AMeJts9R4hbj2ZBUwtOaKrG6rw2y7t6+IaJKjz5M3XDs8BUznxDH43FVc6A0y/gWlMl4UtA=="],
|
||||
"fast-copy": ["fast-copy@4.0.3", "", {}, "sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw=="],
|
||||
|
||||
"fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
|
||||
|
||||
@@ -473,7 +483,7 @@
|
||||
|
||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"file-type": ["file-type@22.1.0", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.5", "token-types": "^6.1.2", "uint8array-extras": "^1.5.0" } }, "sha512-fbvf9u6jnHWr1EP6V8R99E9iLMhNLXgZkUzWBiPpJ5/89UJ/Atuxjn5YXR+XaZWo2hc2/8mGfTez+NDAgOcpLA=="],
|
||||
"file-type": ["file-type@21.3.0", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.4.0" } }, "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA=="],
|
||||
|
||||
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
|
||||
|
||||
@@ -499,19 +509,19 @@
|
||||
|
||||
"jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="],
|
||||
|
||||
"jose": ["jose@6.2.12", "", {}, "sha512-9NiFmJEex0sy2Dk58j2UGBSHgUs2ypF9eZSu4L6vjOX3Dp96Sw1F3uL+H+D1sx02jZZdzUT0HgvCy59CuvXcWw=="],
|
||||
"jose": ["jose@6.2.9", "", {}, "sha512-XrchZOFZUl/T3vTwRe8XK+cJrGtMF4th1ARnDfwbBXFKThGhlsxEE4Zu03AD/bjJSt/9jT/mxrOCkJWOg77aPA=="],
|
||||
|
||||
"joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="],
|
||||
|
||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||
|
||||
"js-yaml": ["js-yaml@4.3.2", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA=="],
|
||||
"js-yaml": ["js-yaml@4.3.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q=="],
|
||||
|
||||
"json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
|
||||
|
||||
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
|
||||
|
||||
"kysely": ["kysely@0.29.6", "", {}, "sha512-hHaB8C/rfzDDtr/t8YZwxAuPJTT0zHyaPoVzcXwDYhYNAgH/4sIfVhi/XLLIY+bL/FqaIJnjATDbi8ObSELmxg=="],
|
||||
"kysely": ["kysely@0.29.5", "", {}, "sha512-ooa+eSbBNPTo3MycPEuW5jdrxQdQwdtB3LC3h43FiXQbIry5tR0C5lDG7eealK0E4D7XjrnOP5DIUg/LyjRMYQ=="],
|
||||
|
||||
"kysely-codegen": ["kysely-codegen@0.20.0", "", { "dependencies": { "chalk": "4.1.2", "cosmiconfig": "^9.0.0", "diff": "^8.0.3", "dotenv": "^17.2.4", "dotenv-expand": "^12.0.3", "micromatch": "^4.0.8", "minimist": "^1.2.8", "pluralize": "^8.0.0", "zod": "^4.3.6" }, "peerDependencies": { "@libsql/kysely-libsql": ">=0.3.0 <0.5.0", "@tediousjs/connection-string": "^1.0.0", "better-sqlite3": ">=7.6.2 <13.0.0", "kysely": ">=0.27.0 <1.0.0", "kysely-bun-sqlite": ">=0.3.2 <1.0.0", "kysely-bun-worker": ">=1.2.0 <2.0.0", "mysql2": ">=2.3.3 <4.0.0", "pg": ">=8.8.0 <9.0.0", "tarn": ">=3.0.0 <4.0.0", "tedious": ">=18.0.0 <20.0.0" }, "optionalPeers": ["@libsql/kysely-libsql", "@tediousjs/connection-string", "better-sqlite3", "kysely-bun-sqlite", "kysely-bun-worker", "mysql2", "pg", "tarn", "tedious"], "bin": { "kysely-codegen": "dist/cli/bin.js" } }, "sha512-LSi2KBG7uDmNCZ+XurLSA9LH7XFyyoQ6xb5DLJSInPTSYLVApjOP2KwO8mSaREWTtoX+C2AG2GTlYR0DLjTbcA=="],
|
||||
|
||||
@@ -565,7 +575,7 @@
|
||||
|
||||
"ml-levenberg-marquardt": ["ml-levenberg-marquardt@5.1.0", "", { "dependencies": { "is-any-array": "^3.0.0", "ml-matrix": "^6.14.0" } }, "sha512-yBYlUQV8+zCmz3CT7Qzt4o2o+UvOx9oxaG/HTgrMjcZRjRxVIAHm8mZM3L0GS2hLMUJpzSLilZdLb4Z5WkgdJw=="],
|
||||
|
||||
"ml-matrix": ["ml-matrix@6.15.0", "", { "dependencies": { "is-any-array": "^3.0.0", "ml-array-rescale": "^2.0.0" } }, "sha512-wFa1v6KP8bKp+fj0nYmRs1Pb5K4zRkXGKsOvLinvILENFIADncm4XlOI+S1M7yuACMGfI6cfk0IifDgd4j5xmw=="],
|
||||
"ml-matrix": ["ml-matrix@6.14.0", "", { "dependencies": { "is-any-array": "^3.0.0", "ml-array-rescale": "^2.0.0" } }, "sha512-5W31+w+6jIm05l85N3Ik04fl+5LfN1lyJLBrEM/r/j7YmvwRclcUyQGXGFWXnN7ASzVjsAnAa3FUXrduAt168A=="],
|
||||
|
||||
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
|
||||
|
||||
@@ -573,9 +583,9 @@
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"nanoid": ["nanoid@3.3.19", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug=="],
|
||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||
|
||||
"obug": ["obug@2.2.1", "", {}, "sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q=="],
|
||||
"obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="],
|
||||
|
||||
"on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="],
|
||||
|
||||
@@ -597,7 +607,7 @@
|
||||
|
||||
"pg-pool": ["pg-pool@3.14.0", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-gKtPkFdQPU3DksooVLi9LsjZxrsBUZIpa+7aVx+LV5pNh0KzP4Zleud2po+ConrxbuXGBJ6Hfer6hdgpIBpBaw=="],
|
||||
|
||||
"pg-protocol": ["pg-protocol@1.16.0", "", {}, "sha512-sILXutLVjCLjcDuOmvhX5e2Z4cS5qG/6Bu3VkpFwdf/633ElGLpEh9bgmuI5I4sqKqkifQiGyiCcx1HdtrK7tg=="],
|
||||
"pg-protocol": ["pg-protocol@1.15.0", "", {}, "sha512-cq9sECI5s0+uPUXjbz8ioyPJni6RzsRib0US67i5IoTZKw8fNeYlVE7u8F4dG7vEJJtc5wdD1K189lCCUwqWTQ=="],
|
||||
|
||||
"pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||
|
||||
@@ -605,7 +615,7 @@
|
||||
|
||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||
|
||||
"picomatch": ["picomatch@4.0.7", "", {}, "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA=="],
|
||||
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||
|
||||
"pino": ["pino@10.3.1", "", { "dependencies": { "@pinojs/redact": "^0.4.0", "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^3.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^4.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg=="],
|
||||
|
||||
@@ -617,7 +627,7 @@
|
||||
|
||||
"pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="],
|
||||
|
||||
"postcss": ["postcss@8.5.28", "", { "dependencies": { "nanoid": "^3.3.18", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A=="],
|
||||
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||
|
||||
"postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
||||
|
||||
@@ -627,7 +637,7 @@
|
||||
|
||||
"postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||
|
||||
"process-warning": ["process-warning@5.1.0", "", {}, "sha512-jQSaVHsPgtyw60e1rQ/A+/ArPEj/S8pS/vFnyGa/gYFXrKk/6RuDkoqVDQ5NI5MmS01698ltlAk0NoDBNLujRw=="],
|
||||
"process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="],
|
||||
|
||||
"pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="],
|
||||
|
||||
@@ -639,9 +649,9 @@
|
||||
|
||||
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||
|
||||
"rolldown": ["rolldown@1.2.8", "", { "dependencies": { "@oxc-project/types": "=0.149.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm-eabi": "1.2.8", "@rolldown/binding-android-arm64": "1.2.8", "@rolldown/binding-darwin-arm64": "1.2.8", "@rolldown/binding-darwin-x64": "1.2.8", "@rolldown/binding-freebsd-x64": "1.2.8", "@rolldown/binding-linux-arm-gnueabihf": "1.2.8", "@rolldown/binding-linux-arm64-gnu": "1.2.8", "@rolldown/binding-linux-arm64-musl": "1.2.8", "@rolldown/binding-linux-ppc64-gnu": "1.2.8", "@rolldown/binding-linux-s390x-gnu": "1.2.8", "@rolldown/binding-linux-x64-gnu": "1.2.8", "@rolldown/binding-linux-x64-musl": "1.2.8", "@rolldown/binding-openharmony-arm64": "1.2.8", "@rolldown/binding-win32-arm64-msvc": "1.2.8", "@rolldown/binding-win32-x64-msvc": "1.2.8" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-Z67nTmhZe7anqnM/EjI392w5i/ANUinjip7QYsOyN37oayduxt3ksdX0hf5OOamkAd53BiIHfbfSzfUmzKFQqQ=="],
|
||||
"rolldown": ["rolldown@1.1.4", "", { "dependencies": { "@oxc-project/types": "=0.138.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.1.4", "@rolldown/binding-darwin-arm64": "1.1.4", "@rolldown/binding-darwin-x64": "1.1.4", "@rolldown/binding-freebsd-x64": "1.1.4", "@rolldown/binding-linux-arm-gnueabihf": "1.1.4", "@rolldown/binding-linux-arm64-gnu": "1.1.4", "@rolldown/binding-linux-arm64-musl": "1.1.4", "@rolldown/binding-linux-ppc64-gnu": "1.1.4", "@rolldown/binding-linux-s390x-gnu": "1.1.4", "@rolldown/binding-linux-x64-gnu": "1.1.4", "@rolldown/binding-linux-x64-musl": "1.1.4", "@rolldown/binding-openharmony-arm64": "1.1.4", "@rolldown/binding-wasm32-wasi": "1.1.4", "@rolldown/binding-win32-arm64-msvc": "1.1.4", "@rolldown/binding-win32-x64-msvc": "1.1.4" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-IjZYiLxZwpnhwhdBH2ugdTGVSdhCQUmLxLoqyjiL0JxYjyRst+5a0P3xfrTxJ5F638j4Mvvw5FAX5XE6eHpXbA=="],
|
||||
|
||||
"rollup": ["rollup@4.63.3", "", { "dependencies": { "@types/estree": "1.0.9" }, "optionalDependencies": { "@napi-rs/lzma-linux-x64-gnu": "1.5.1", "@rollup/rollup-android-arm-eabi": "4.63.3", "@rollup/rollup-android-arm64": "4.63.3", "@rollup/rollup-darwin-arm64": "4.63.3", "@rollup/rollup-darwin-x64": "4.63.3", "@rollup/rollup-freebsd-arm64": "4.63.3", "@rollup/rollup-freebsd-x64": "4.63.3", "@rollup/rollup-linux-arm-gnueabihf": "4.63.3", "@rollup/rollup-linux-arm-musleabihf": "4.63.3", "@rollup/rollup-linux-arm64-gnu": "4.63.3", "@rollup/rollup-linux-arm64-musl": "4.63.3", "@rollup/rollup-linux-loong64-gnu": "4.63.3", "@rollup/rollup-linux-loong64-musl": "4.63.3", "@rollup/rollup-linux-ppc64-gnu": "4.63.3", "@rollup/rollup-linux-ppc64-musl": "4.63.3", "@rollup/rollup-linux-riscv64-gnu": "4.63.3", "@rollup/rollup-linux-riscv64-musl": "4.63.3", "@rollup/rollup-linux-s390x-gnu": "4.63.3", "@rollup/rollup-linux-x64-gnu": "4.63.3", "@rollup/rollup-linux-x64-musl": "4.63.3", "@rollup/rollup-openbsd-x64": "4.63.3", "@rollup/rollup-openharmony-arm64": "4.63.3", "@rollup/rollup-win32-arm64-msvc": "4.63.3", "@rollup/rollup-win32-ia32-msvc": "4.63.3", "@rollup/rollup-win32-x64-gnu": "4.63.3", "@rollup/rollup-win32-x64-msvc": "4.63.3", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-1i2XreiAoMMXuPGD6Msj2xWrMMkHojNRKivInxGQcg7/1KuPuYlfUutLyh4drnOxUTHX9cHI4wFoat8D/NKaBw=="],
|
||||
"rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="],
|
||||
|
||||
"sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="],
|
||||
|
||||
@@ -649,7 +659,7 @@
|
||||
|
||||
"secure-json-parse": ["secure-json-parse@4.1.0", "", {}, "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA=="],
|
||||
|
||||
"set-cookie-parser": ["set-cookie-parser@3.1.2", "", {}, "sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw=="],
|
||||
"set-cookie-parser": ["set-cookie-parser@3.0.1", "", {}, "sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q=="],
|
||||
|
||||
"sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="],
|
||||
|
||||
@@ -661,11 +671,11 @@
|
||||
|
||||
"strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="],
|
||||
|
||||
"strtok3": ["strtok3@10.3.5", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA=="],
|
||||
"strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="],
|
||||
|
||||
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||
|
||||
"svelte": ["svelte@5.57.0", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.10", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "devalue": "^5.8.1", "esm-env": "^1.2.1", "esrap": "^2.2.12", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-NdbDn7fl4be1ViUG0oq/lvG6OZy3oENolV2ONjiqqsfVoeAfzaQAKUcEX3MrQod/Bebv1PgwET9rfXhgn9s4Kg=="],
|
||||
"svelte": ["svelte@5.56.9", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.10", "@types/estree": "^1.0.5", "@types/trusted-types": "^2.0.7", "acorn": "^8.12.1", "aria-query": "5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "devalue": "^5.8.1", "esm-env": "^1.2.1", "esrap": "^2.2.12", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-VT8kSnlEg8069w7AiCcAk3Yf5xvMnrGTagVOmU/OpOLHaHnNqXhWZCH/4EVga/bT/HtWhvE6/fHrXLErx7OnJA=="],
|
||||
|
||||
"svelte-adapter-bun": ["svelte-adapter-bun@1.0.1", "", { "dependencies": { "rolldown": "^1.0.0-beta.38" }, "peerDependencies": { "@sveltejs/kit": "^2.4.0", "typescript": "^5" } }, "sha512-tNOvfm8BGgG+rmEA7hkmqtq07v7zoo4skLQc+hIoQ79J+1fkEMpJEA2RzCIe3aPc8JdrsMJkv3mpiZPMsgahjA=="],
|
||||
|
||||
@@ -677,7 +687,7 @@
|
||||
|
||||
"thread-stream": ["thread-stream@4.2.0", "", { "dependencies": { "real-require": "^1.0.0" } }, "sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ=="],
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="],
|
||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||
|
||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||
|
||||
@@ -693,13 +703,13 @@
|
||||
|
||||
"uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="],
|
||||
|
||||
"undici": ["undici@6.28.1", "", {}, "sha512-zWpdTVD54H48CIybL0rWQ3ukpb9d23wM7eH5RtfdmeP70cWHNjtfo7P4vZX+5CoDcO53J4Pu5uXp7lNfjc6DRA=="],
|
||||
"undici": ["undici@6.28.0", "", {}, "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA=="],
|
||||
|
||||
"undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
|
||||
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
||||
|
||||
"vite": ["vite@7.3.6", "", { "dependencies": { "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg=="],
|
||||
|
||||
"vitefu": ["vitefu@1.1.3", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["vite"] }, "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg=="],
|
||||
"vitefu": ["vitefu@1.1.2", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw=="],
|
||||
|
||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||
|
||||
@@ -707,16 +717,18 @@
|
||||
|
||||
"xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
|
||||
|
||||
"zimmerframe": ["zimmerframe@1.1.5", "", {}, "sha512-msJxIvYDYcoNL+PJsu+7qmpDWsYmAxTY+2TNYXXF0hzBzBk0BMecOqDOG/EckUoKCuKwObfbugIl8QpqHDXeFA=="],
|
||||
"zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="],
|
||||
|
||||
"zipcodes-us": ["zipcodes-us@1.1.3", "", {}, "sha512-gOz8WAO6iWBU4aUc0lljpa+TKZckRKmgoHKcc1jWnn4eTbdc9XO5cXEaGccYn7GAjykueO0Wn+N7zdmzG0Uf5w=="],
|
||||
|
||||
"zod": ["zod@4.6.5", "", {}, "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q=="],
|
||||
"zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
||||
|
||||
"@discordjs/rest/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="],
|
||||
|
||||
"@discordjs/ws/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="],
|
||||
|
||||
"@elysia/jwt/jose": ["jose@6.2.3", "", {}, "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw=="],
|
||||
|
||||
"@sveltejs/kit/cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="],
|
||||
@@ -735,8 +747,8 @@
|
||||
|
||||
"micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
|
||||
|
||||
"thread-stream/real-require": ["real-require@1.0.0", "", {}, "sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g=="],
|
||||
"pg/pg-protocol": ["pg-protocol@1.16.0", "", {}, "sha512-sILXutLVjCLjcDuOmvhX5e2Z4cS5qG/6Bu3VkpFwdf/633ElGLpEh9bgmuI5I4sqKqkifQiGyiCcx1HdtrK7tg=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.4", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A=="],
|
||||
"thread-stream/real-require": ["real-require@1.0.0", "", {}, "sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g=="],
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -36,14 +36,14 @@ target="${1:-migrate}"
|
||||
|
||||
case "$target" in
|
||||
migrate)
|
||||
(cd apps/api && NODE_ENV=production DATABASE_URL="$tunneled_url" bun run --env-file=../../.env.production src/database/migrate.ts latest)
|
||||
DATABASE_URL="$tunneled_url" bun run --filter @blade-and-brawn/api db:migrate:latest
|
||||
;;
|
||||
seed)
|
||||
(cd apps/api && NODE_ENV=production DATABASE_URL="$tunneled_url" bun run --env-file=../../.env.production src/database/seed.ts)
|
||||
DATABASE_URL="$tunneled_url" bun run --filter @blade-and-brawn/api db:seed
|
||||
;;
|
||||
both)
|
||||
(cd apps/api && NODE_ENV=production DATABASE_URL="$tunneled_url" bun run --env-file=../../.env.production src/database/migrate.ts latest)
|
||||
(cd apps/api && NODE_ENV=production DATABASE_URL="$tunneled_url" bun run --env-file=../../.env.production src/database/seed.ts)
|
||||
DATABASE_URL="$tunneled_url" bun run --filter @blade-and-brawn/api db:migrate:latest
|
||||
DATABASE_URL="$tunneled_url" bun run --filter @blade-and-brawn/api db:seed
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [migrate|seed|both]" >&2
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
"build:portal": "bun run --filter @blade-and-brawn/portal build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "^1.4.2",
|
||||
"@types/bun": "^1.3.14",
|
||||
"typescript": "^7.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -42,9 +42,3 @@ export const ActivityPerformanceSchema = t.Object({
|
||||
performance: t.Number(),
|
||||
});
|
||||
export type ActivityPerformance = Static<typeof ActivityPerformanceSchema>;
|
||||
|
||||
export const ActivityVideosSchema = t.Partial(t.Record(t.Enum(Activity), t.String()));
|
||||
export type ActivityVideoUrls = Static<typeof ActivityVideosSchema>;
|
||||
|
||||
export const ActivityVerificationsSchema = t.Partial(t.Record(t.Enum(Activity), t.Boolean()));
|
||||
export type ActivityVerifications = Static<typeof ActivityVerificationsSchema>;
|
||||
|
||||
Reference in New Issue
Block a user