fix: update match configuration to bestOf 5 and scoringType to score_v2

This commit is contained in:
2026-02-28 06:38:05 +01:00
parent e99444b157
commit fb9140a03f
555 changed files with 124715 additions and 1 deletions

View File

@@ -0,0 +1,661 @@
{
".svelte-kit/generated/server/internal.js": {
"file": "internal.js",
"name": "internal",
"src": ".svelte-kit/generated/server/internal.js",
"isEntry": true,
"imports": [
"_root.js",
"_environment.js",
"_server.js",
"_internal.js",
"_shared-server.js"
]
},
"_api.js": {
"file": "chunks/api.js",
"name": "api",
"imports": [
"_shared-server.js",
"_index2.js"
]
},
"_auth.js": {
"file": "chunks/auth.js",
"name": "auth",
"imports": [
"_shared-server.js",
"_url.js",
"_root.js",
"_utils.js",
"_query.js",
"_index2.js"
],
"dynamicImports": [
"node_modules/better-auth/dist/adapters/memory-adapter/index.mjs",
"node_modules/better-auth/dist/adapters/kysely-adapter/index.mjs",
"node_modules/better-auth/dist/adapters/kysely-adapter/index.mjs",
"node_modules/better-auth/dist/adapters/kysely-adapter/bun-sqlite-dialect.mjs",
"node_modules/better-auth/dist/adapters/kysely-adapter/node-sqlite-dialect.mjs"
]
},
"_engine.js": {
"file": "chunks/engine.js",
"name": "engine",
"imports": [
"_index2.js"
]
},
"_environment.js": {
"file": "chunks/environment.js",
"name": "environment"
},
"_exports.js": {
"file": "chunks/exports.js",
"name": "exports"
},
"_false.js": {
"file": "chunks/false.js",
"name": "false"
},
"_index.js": {
"file": "chunks/index.js",
"name": "index",
"imports": [
"_index3.js",
"_root.js"
]
},
"_index2.js": {
"file": "chunks/index2.js",
"name": "index",
"imports": [
"_shared-server.js"
]
},
"_index3.js": {
"file": "chunks/index3.js",
"name": "index"
},
"_index4.js": {
"file": "chunks/index4.js",
"name": "index",
"imports": [
"_state.svelte.js",
"_url.js",
"_utils.js",
"_index.js",
"_root.js",
"_exports.js",
"_index3.js"
]
},
"_internal.js": {
"file": "chunks/internal.js",
"name": "internal",
"imports": [
"_root.js",
"_environment.js",
"_server.js",
"_shared-server.js"
],
"dynamicImports": [
"src/hooks.server.ts"
]
},
"_orchestrator.js": {
"file": "chunks/orchestrator.js",
"name": "orchestrator",
"imports": [
"_index2.js",
"_engine.js",
"_shared-server.js"
]
},
"_query.js": {
"file": "chunks/query.js",
"name": "query",
"imports": [
"_shared.js",
"_environment.js"
]
},
"_root.js": {
"file": "chunks/root.js",
"name": "root",
"imports": [
"_index3.js",
"_false.js"
]
},
"_routing.js": {
"file": "chunks/routing.js",
"name": "routing",
"imports": [
"_url.js"
]
},
"_server.js": {
"file": "chunks/server.js",
"name": "server"
},
"_shared-server.js": {
"file": "chunks/shared-server.js",
"name": "shared-server"
},
"_shared.js": {
"file": "chunks/shared.js",
"name": "shared",
"imports": [
"_utils.js"
]
},
"_state.svelte.js": {
"file": "chunks/state.svelte.js",
"name": "state.svelte",
"imports": [
"_index3.js",
"_url.js",
"_root.js"
]
},
"_url.js": {
"file": "chunks/url.js",
"name": "url"
},
"_utils.js": {
"file": "chunks/utils.js",
"name": "utils"
},
"node_modules/@sveltejs/kit/src/runtime/app/server/remote/index.js": {
"file": "remote-entry.js",
"name": "remote-entry",
"src": "node_modules/@sveltejs/kit/src/runtime/app/server/remote/index.js",
"isEntry": true,
"imports": [
"_query.js",
"_shared.js",
"_false.js",
"_server.js"
]
},
"node_modules/@sveltejs/kit/src/runtime/components/svelte-5/layout.svelte": {
"file": "entries/fallbacks/layout.svelte.js",
"name": "entries/fallbacks/layout.svelte",
"src": "node_modules/@sveltejs/kit/src/runtime/components/svelte-5/layout.svelte",
"isEntry": true
},
"node_modules/@sveltejs/kit/src/runtime/server/index.js": {
"file": "index.js",
"name": "index",
"src": "node_modules/@sveltejs/kit/src/runtime/server/index.js",
"isEntry": true,
"imports": [
"_false.js",
"_server.js",
"_shared.js",
"_url.js",
"_utils.js",
"_index.js",
"_shared-server.js",
"_routing.js",
"_exports.js",
"_internal.js"
]
},
"node_modules/better-auth/dist/adapters/kysely-adapter/bun-sqlite-dialect.mjs": {
"file": "chunks/bun-sqlite-dialect.js",
"name": "bun-sqlite-dialect",
"src": "node_modules/better-auth/dist/adapters/kysely-adapter/bun-sqlite-dialect.mjs",
"isDynamicEntry": true
},
"node_modules/better-auth/dist/adapters/kysely-adapter/index.mjs": {
"file": "chunks/index6.js",
"name": "index",
"src": "node_modules/better-auth/dist/adapters/kysely-adapter/index.mjs",
"isDynamicEntry": true,
"imports": [
"_auth.js"
]
},
"node_modules/better-auth/dist/adapters/kysely-adapter/node-sqlite-dialect.mjs": {
"file": "chunks/node-sqlite-dialect.js",
"name": "node-sqlite-dialect",
"src": "node_modules/better-auth/dist/adapters/kysely-adapter/node-sqlite-dialect.mjs",
"isDynamicEntry": true
},
"node_modules/better-auth/dist/adapters/memory-adapter/index.mjs": {
"file": "chunks/index5.js",
"name": "index",
"src": "node_modules/better-auth/dist/adapters/memory-adapter/index.mjs",
"isDynamicEntry": true
},
"src/hooks.server.ts": {
"file": "entries/hooks.server.js",
"name": "entries/hooks.server",
"src": "src/hooks.server.ts",
"isEntry": true,
"isDynamicEntry": true,
"imports": [
"_environment.js",
"_auth.js",
"_index2.js"
]
},
"src/routes/(app)/+layout.server.ts": {
"file": "entries/pages/(app)/_layout.server.ts.js",
"name": "entries/pages/(app)/_layout.server.ts",
"src": "src/routes/(app)/+layout.server.ts",
"isEntry": true
},
"src/routes/(app)/+layout.svelte": {
"file": "entries/pages/(app)/_layout.svelte.js",
"name": "entries/pages/(app)/_layout.svelte",
"src": "src/routes/(app)/+layout.svelte",
"isEntry": true,
"imports": [
"_index3.js",
"_index4.js",
"_url.js",
"_utils.js",
"_root.js",
"_exports.js",
"_state.svelte.js"
],
"css": [
"_app/immutable/assets/_layout.Dv2no-8m.css"
]
},
"src/routes/(app)/+page.server.ts": {
"file": "entries/pages/(app)/_page.server.ts.js",
"name": "entries/pages/(app)/_page.server.ts",
"src": "src/routes/(app)/+page.server.ts",
"isEntry": true,
"imports": [
"_index2.js"
]
},
"src/routes/(app)/+page.svelte": {
"file": "entries/pages/(app)/_page.svelte.js",
"name": "entries/pages/(app)/_page.svelte",
"src": "src/routes/(app)/+page.svelte",
"isEntry": true,
"imports": [
"_index3.js"
]
},
"src/routes/(app)/admin/+page.server.ts": {
"file": "entries/pages/(app)/admin/_page.server.ts.js",
"name": "entries/pages/(app)/admin/_page.server.ts",
"src": "src/routes/(app)/admin/+page.server.ts",
"isEntry": true,
"imports": [
"_index2.js"
]
},
"src/routes/(app)/admin/+page.svelte": {
"file": "entries/pages/(app)/admin/_page.svelte.js",
"name": "entries/pages/(app)/admin/_page.svelte",
"src": "src/routes/(app)/admin/+page.svelte",
"isEntry": true,
"imports": [
"_index3.js",
"_url.js",
"_utils.js",
"_root.js",
"_exports.js",
"_state.svelte.js"
]
},
"src/routes/(app)/mappools/+page.server.ts": {
"file": "entries/pages/(app)/mappools/_page.server.ts.js",
"name": "entries/pages/(app)/mappools/_page.server.ts",
"src": "src/routes/(app)/mappools/+page.server.ts",
"isEntry": true,
"imports": [
"_index2.js"
]
},
"src/routes/(app)/mappools/+page.svelte": {
"file": "entries/pages/(app)/mappools/_page.svelte.js",
"name": "entries/pages/(app)/mappools/_page.svelte",
"src": "src/routes/(app)/mappools/+page.svelte",
"isEntry": true,
"imports": [
"_index3.js",
"_url.js",
"_utils.js",
"_root.js",
"_exports.js",
"_state.svelte.js"
]
},
"src/routes/(app)/mappools/[id]/+page.server.ts": {
"file": "entries/pages/(app)/mappools/_id_/_page.server.ts.js",
"name": "entries/pages/(app)/mappools/_id_/_page.server.ts",
"src": "src/routes/(app)/mappools/[id]/+page.server.ts",
"isEntry": true,
"imports": [
"_index2.js",
"_api.js"
]
},
"src/routes/(app)/mappools/[id]/+page.svelte": {
"file": "entries/pages/(app)/mappools/_id_/_page.svelte.js",
"name": "entries/pages/(app)/mappools/_id_/_page.svelte",
"src": "src/routes/(app)/mappools/[id]/+page.svelte",
"isEntry": true,
"imports": [
"_index3.js",
"_url.js",
"_utils.js",
"_root.js",
"_exports.js",
"_state.svelte.js"
]
},
"src/routes/(app)/matches/+page.server.ts": {
"file": "entries/pages/(app)/matches/_page.server.ts.js",
"name": "entries/pages/(app)/matches/_page.server.ts",
"src": "src/routes/(app)/matches/+page.server.ts",
"isEntry": true,
"imports": [
"_index2.js",
"_engine.js",
"_orchestrator.js"
]
},
"src/routes/(app)/matches/+page.svelte": {
"file": "entries/pages/(app)/matches/_page.svelte.js",
"name": "entries/pages/(app)/matches/_page.svelte",
"src": "src/routes/(app)/matches/+page.svelte",
"isEntry": true,
"imports": [
"_index3.js",
"_url.js",
"_utils.js",
"_root.js",
"_exports.js",
"_state.svelte.js"
]
},
"src/routes/(app)/matches/[id]/+page.server.ts": {
"file": "entries/pages/(app)/matches/_id_/_page.server.ts.js",
"name": "entries/pages/(app)/matches/_id_/_page.server.ts",
"src": "src/routes/(app)/matches/[id]/+page.server.ts",
"isEntry": true,
"imports": [
"_index2.js",
"_engine.js",
"_orchestrator.js",
"_api.js"
]
},
"src/routes/(app)/matches/[id]/+page.svelte": {
"file": "entries/pages/(app)/matches/_id_/_page.svelte.js",
"name": "entries/pages/(app)/matches/_id_/_page.svelte",
"src": "src/routes/(app)/matches/[id]/+page.svelte",
"isEntry": true,
"imports": [
"_index3.js",
"_url.js",
"_utils.js",
"_root.js",
"_exports.js",
"_state.svelte.js"
]
},
"src/routes/(app)/settings/+page.server.ts": {
"file": "entries/pages/(app)/settings/_page.server.ts.js",
"name": "entries/pages/(app)/settings/_page.server.ts",
"src": "src/routes/(app)/settings/+page.server.ts",
"isEntry": true,
"imports": [
"_auth.js",
"_index2.js"
]
},
"src/routes/(app)/settings/+page.svelte": {
"file": "entries/pages/(app)/settings/_page.svelte.js",
"name": "entries/pages/(app)/settings/_page.svelte",
"src": "src/routes/(app)/settings/+page.svelte",
"isEntry": true,
"imports": [
"_index3.js",
"_url.js",
"_utils.js",
"_root.js",
"_exports.js",
"_state.svelte.js"
]
},
"src/routes/(app)/teams/+page.server.ts": {
"file": "entries/pages/(app)/teams/_page.server.ts.js",
"name": "entries/pages/(app)/teams/_page.server.ts",
"src": "src/routes/(app)/teams/+page.server.ts",
"isEntry": true,
"imports": [
"_index2.js"
]
},
"src/routes/(app)/teams/+page.svelte": {
"file": "entries/pages/(app)/teams/_page.svelte.js",
"name": "entries/pages/(app)/teams/_page.svelte",
"src": "src/routes/(app)/teams/+page.svelte",
"isEntry": true,
"imports": [
"_index3.js",
"_url.js",
"_utils.js",
"_root.js",
"_exports.js",
"_state.svelte.js"
]
},
"src/routes/+error.svelte": {
"file": "entries/pages/_error.svelte.js",
"name": "entries/pages/_error.svelte",
"src": "src/routes/+error.svelte",
"isEntry": true,
"imports": [
"_index3.js",
"_index4.js"
]
},
"src/routes/api/health/+server.ts": {
"file": "entries/endpoints/api/health/_server.ts.js",
"name": "entries/endpoints/api/health/_server.ts",
"src": "src/routes/api/health/+server.ts",
"isEntry": true,
"imports": [
"_index2.js"
]
},
"src/routes/api/mappools/+server.ts": {
"file": "entries/endpoints/api/mappools/_server.ts.js",
"name": "entries/endpoints/api/mappools/_server.ts",
"src": "src/routes/api/mappools/+server.ts",
"isEntry": true,
"imports": [
"_index2.js"
]
},
"src/routes/api/mappools/[id]/+server.ts": {
"file": "entries/endpoints/api/mappools/_id_/_server.ts.js",
"name": "entries/endpoints/api/mappools/_id_/_server.ts",
"src": "src/routes/api/mappools/[id]/+server.ts",
"isEntry": true,
"imports": [
"_index2.js"
]
},
"src/routes/api/mappools/[id]/slots/+server.ts": {
"file": "entries/endpoints/api/mappools/_id_/slots/_server.ts.js",
"name": "entries/endpoints/api/mappools/_id_/slots/_server.ts",
"src": "src/routes/api/mappools/[id]/slots/+server.ts",
"isEntry": true,
"imports": [
"_index2.js"
]
},
"src/routes/api/mappools/[id]/slots/[slotId]/+server.ts": {
"file": "entries/endpoints/api/mappools/_id_/slots/_slotId_/_server.ts.js",
"name": "entries/endpoints/api/mappools/_id_/slots/_slotId_/_server.ts",
"src": "src/routes/api/mappools/[id]/slots/[slotId]/+server.ts",
"isEntry": true,
"imports": [
"_index2.js"
]
},
"src/routes/api/matches/+server.ts": {
"file": "entries/endpoints/api/matches/_server.ts.js",
"name": "entries/endpoints/api/matches/_server.ts",
"src": "src/routes/api/matches/+server.ts",
"isEntry": true,
"imports": [
"_index2.js",
"_engine.js"
]
},
"src/routes/api/matches/[id]/+server.ts": {
"file": "entries/endpoints/api/matches/_id_/_server.ts.js",
"name": "entries/endpoints/api/matches/_id_/_server.ts",
"src": "src/routes/api/matches/[id]/+server.ts",
"isEntry": true,
"imports": [
"_engine.js"
]
},
"src/routes/api/matches/[id]/lobby/+server.ts": {
"file": "entries/endpoints/api/matches/_id_/lobby/_server.ts.js",
"name": "entries/endpoints/api/matches/_id_/lobby/_server.ts",
"src": "src/routes/api/matches/[id]/lobby/+server.ts",
"isEntry": true,
"imports": [
"_engine.js"
]
},
"src/routes/api/matches/[id]/pick/+server.ts": {
"file": "entries/endpoints/api/matches/_id_/pick/_server.ts.js",
"name": "entries/endpoints/api/matches/_id_/pick/_server.ts",
"src": "src/routes/api/matches/[id]/pick/+server.ts",
"isEntry": true,
"imports": [
"_engine.js"
]
},
"src/routes/api/matches/[id]/roll/+server.ts": {
"file": "entries/endpoints/api/matches/_id_/roll/_server.ts.js",
"name": "entries/endpoints/api/matches/_id_/roll/_server.ts",
"src": "src/routes/api/matches/[id]/roll/+server.ts",
"isEntry": true,
"imports": [
"_engine.js"
]
},
"src/routes/api/matches/[id]/rolling/+server.ts": {
"file": "entries/endpoints/api/matches/_id_/rolling/_server.ts.js",
"name": "entries/endpoints/api/matches/_id_/rolling/_server.ts",
"src": "src/routes/api/matches/[id]/rolling/+server.ts",
"isEntry": true,
"imports": [
"_engine.js"
]
},
"src/routes/api/matches/[id]/score/+server.ts": {
"file": "entries/endpoints/api/matches/_id_/score/_server.ts.js",
"name": "entries/endpoints/api/matches/_id_/score/_server.ts",
"src": "src/routes/api/matches/[id]/score/+server.ts",
"isEntry": true,
"imports": [
"_engine.js"
]
},
"src/routes/api/osu/beatmap/[id]/+server.ts": {
"file": "entries/endpoints/api/osu/beatmap/_id_/_server.ts.js",
"name": "entries/endpoints/api/osu/beatmap/_id_/_server.ts",
"src": "src/routes/api/osu/beatmap/[id]/+server.ts",
"isEntry": true,
"imports": [
"_api.js"
]
},
"src/routes/api/queue/+server.ts": {
"file": "entries/endpoints/api/queue/_server.ts.js",
"name": "entries/endpoints/api/queue/_server.ts",
"src": "src/routes/api/queue/+server.ts",
"isEntry": true,
"imports": [
"_engine.js",
"_index2.js"
]
},
"src/routes/demo/+page.svelte": {
"file": "entries/pages/demo/_page.svelte.js",
"name": "entries/pages/demo/_page.svelte",
"src": "src/routes/demo/+page.svelte",
"isEntry": true,
"imports": [
"_index3.js",
"_server.js",
"_routing.js",
"_url.js",
"_root.js"
]
},
"src/routes/demo/better-auth/+page.server.ts": {
"file": "entries/pages/demo/better-auth/_page.server.ts.js",
"name": "entries/pages/demo/better-auth/_page.server.ts",
"src": "src/routes/demo/better-auth/+page.server.ts",
"isEntry": true,
"imports": [
"_auth.js"
]
},
"src/routes/demo/better-auth/+page.svelte": {
"file": "entries/pages/demo/better-auth/_page.svelte.js",
"name": "entries/pages/demo/better-auth/_page.svelte",
"src": "src/routes/demo/better-auth/+page.svelte",
"isEntry": true,
"imports": [
"_index3.js",
"_url.js",
"_utils.js",
"_root.js",
"_exports.js",
"_state.svelte.js"
]
},
"src/routes/demo/better-auth/login/+page.server.ts": {
"file": "entries/pages/demo/better-auth/login/_page.server.ts.js",
"name": "entries/pages/demo/better-auth/login/_page.server.ts",
"src": "src/routes/demo/better-auth/login/+page.server.ts",
"isEntry": true,
"imports": [
"_auth.js"
]
},
"src/routes/demo/better-auth/login/+page.svelte": {
"file": "entries/pages/demo/better-auth/login/_page.svelte.js",
"name": "entries/pages/demo/better-auth/login/_page.svelte",
"src": "src/routes/demo/better-auth/login/+page.svelte",
"isEntry": true,
"imports": [
"_index3.js",
"_url.js",
"_utils.js",
"_root.js",
"_exports.js",
"_state.svelte.js"
]
},
"src/routes/login/+page.server.ts": {
"file": "entries/pages/login/_page.server.ts.js",
"name": "entries/pages/login/_page.server.ts",
"src": "src/routes/login/+page.server.ts",
"isEntry": true,
"imports": [
"_auth.js"
]
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,69 @@
import { b as private_env } from "./shared-server.js";
import "./index2.js";
const CACHE_TTL = 10 * 60 * 1e3;
const MAX_ENTRIES = 500;
const cache = /* @__PURE__ */ new Map();
function getCached(key) {
const entry = cache.get(key);
if (!entry) return null;
if (Date.now() > entry.expiresAt) {
cache.delete(key);
return null;
}
return entry.data;
}
function setCache(key, data, ttl = CACHE_TTL) {
if (cache.size >= MAX_ENTRIES) {
const firstKey = cache.keys().next().value;
if (firstKey) cache.delete(firstKey);
}
cache.set(key, { data, expiresAt: Date.now() + ttl });
}
let clientToken = null;
let clientTokenExpiresAt = 0;
async function getClientToken() {
if (clientToken && Date.now() < clientTokenExpiresAt - 6e4) {
return clientToken;
}
const res = await fetch("https://osu.ppy.sh/oauth/token", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams({
client_id: private_env.OSU_CLIENT_ID,
client_secret: private_env.OSU_CLIENT_SECRET,
grant_type: "client_credentials",
scope: "identify public"
})
});
if (!res.ok) {
throw new Error(`Failed to get osu! client token: ${res.status} ${res.statusText}`);
}
const data = await res.json();
clientToken = data.access_token;
clientTokenExpiresAt = Date.now() + data.expires_in * 1e3;
return clientToken;
}
async function osuFetch(path, token) {
const t = await getClientToken();
const res = await fetch(`https://osu.ppy.sh/api/v2${path}`, {
headers: { Authorization: `Bearer ${t}` }
});
if (!res.ok) {
throw new Error(`osu! API ${path}: ${res.status} ${res.statusText}`);
}
return res.json();
}
async function getBeatmap(beatmapId) {
const cacheKey = `beatmap:${beatmapId}`;
const cached = getCached(cacheKey);
if (cached) return cached;
const data = await osuFetch(`/beatmaps/${beatmapId}`);
setCache(cacheKey, data);
return data;
}
export {
getBeatmap as g
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,155 @@
import { CompiledQuery, DefaultQueryCompiler, DEFAULT_MIGRATION_TABLE, DEFAULT_MIGRATION_LOCK_TABLE, sql } from "kysely";
var BunSqliteAdapter = class {
get supportsCreateIfNotExists() {
return true;
}
get supportsTransactionalDdl() {
return false;
}
get supportsReturning() {
return true;
}
async acquireMigrationLock() {
}
async releaseMigrationLock() {
}
get supportsOutput() {
return true;
}
};
var BunSqliteDriver = class {
#config;
#connectionMutex = new ConnectionMutex();
#db;
#connection;
constructor(config) {
this.#config = { ...config };
}
async init() {
this.#db = this.#config.database;
this.#connection = new BunSqliteConnection(this.#db);
if (this.#config.onCreateConnection) await this.#config.onCreateConnection(this.#connection);
}
async acquireConnection() {
await this.#connectionMutex.lock();
return this.#connection;
}
async beginTransaction(connection) {
await connection.executeQuery(CompiledQuery.raw("begin"));
}
async commitTransaction(connection) {
await connection.executeQuery(CompiledQuery.raw("commit"));
}
async rollbackTransaction(connection) {
await connection.executeQuery(CompiledQuery.raw("rollback"));
}
async releaseConnection() {
this.#connectionMutex.unlock();
}
async destroy() {
this.#db?.close();
}
};
var BunSqliteConnection = class {
#db;
constructor(db) {
this.#db = db;
}
executeQuery(compiledQuery) {
const { sql: sql$1, parameters } = compiledQuery;
const stmt = this.#db.prepare(sql$1);
return Promise.resolve({ rows: stmt.all(parameters) });
}
async *streamQuery() {
throw new Error("Streaming query is not supported by SQLite driver.");
}
};
var ConnectionMutex = class {
#promise;
#resolve;
async lock() {
while (await this.#promise) await this.#promise;
this.#promise = new Promise((resolve) => {
this.#resolve = resolve;
});
}
unlock() {
const resolve = this.#resolve;
this.#promise = void 0;
this.#resolve = void 0;
resolve?.();
}
};
var BunSqliteIntrospector = class {
#db;
constructor(db) {
this.#db = db;
}
async getSchemas() {
return [];
}
async getTables(options = { withInternalKyselyTables: false }) {
let query = this.#db.selectFrom("sqlite_schema").where("type", "=", "table").where("name", "not like", "sqlite_%").select("name").$castTo();
if (!options.withInternalKyselyTables) query = query.where("name", "!=", DEFAULT_MIGRATION_TABLE).where("name", "!=", DEFAULT_MIGRATION_LOCK_TABLE);
const tables = await query.execute();
return Promise.all(tables.map(({ name }) => this.#getTableMetadata(name)));
}
async getMetadata(options) {
return { tables: await this.getTables(options) };
}
async #getTableMetadata(table) {
const db = this.#db;
const autoIncrementCol = (await db.selectFrom("sqlite_master").where("name", "=", table).select("sql").$castTo().execute())[0]?.sql?.split(/[\(\),]/)?.find((it) => it.toLowerCase().includes("autoincrement"))?.split(/\s+/)?.[0]?.replace(/["`]/g, "");
return {
name: table,
columns: (await db.selectFrom(sql`pragma_table_info(${table})`.as("table_info")).select([
"name",
"type",
"notnull",
"dflt_value"
]).execute()).map((col) => ({
name: col.name,
dataType: col.type,
isNullable: !col.notnull,
isAutoIncrementing: col.name === autoIncrementCol,
hasDefaultValue: col.dflt_value != null
})),
isView: true
};
}
};
var BunSqliteQueryCompiler = class extends DefaultQueryCompiler {
getCurrentParameterPlaceholder() {
return "?";
}
getLeftIdentifierWrapper() {
return '"';
}
getRightIdentifierWrapper() {
return '"';
}
getAutoIncrement() {
return "autoincrement";
}
};
var BunSqliteDialect = class {
#config;
constructor(config) {
this.#config = { ...config };
}
createDriver() {
return new BunSqliteDriver(this.#config);
}
createQueryCompiler() {
return new BunSqliteQueryCompiler();
}
createAdapter() {
return new BunSqliteAdapter();
}
createIntrospector(db) {
return new BunSqliteIntrospector(db);
}
};
export {
BunSqliteDialect
};

View File

@@ -0,0 +1,350 @@
import { d as db, b as match, e as matchParticipant, t as teamMember, f as matchParticipantPlayer, g as matchGame, h as matchGameScore, i as matchQueue, p as playerRating } from "./index2.js";
import { eq, sql, asc } from "drizzle-orm";
const MATCH_STATES = {
CREATED: "CREATED",
LOBBY: "LOBBY",
ROLLING: "ROLLING",
PICKING: "PICKING",
PLAYING: "PLAYING",
FINISHED: "FINISHED",
CANCELLED: "CANCELLED"
};
const GAME_STATES = {
PLAYING: "PLAYING",
FINISHED: "FINISHED"
};
async function joinQueue(userId, teamId) {
let rating = await db.query.playerRating.findFirst({
where: eq(playerRating.userId, userId)
});
if (!rating) {
[rating] = await db.insert(playerRating).values({ userId, elo: 1e3 }).returning();
}
const existing = await db.query.matchQueue.findFirst({
where: eq(matchQueue.userId, userId)
});
if (existing) throw new Error("Already in queue");
await db.insert(matchQueue).values({
userId,
teamId,
elo: rating.elo
});
return tryMatchFromQueue();
}
async function leaveQueue(userId) {
await db.delete(matchQueue).where(eq(matchQueue.userId, userId));
}
async function getQueueStatus(userId) {
const entry = await db.query.matchQueue.findFirst({
where: eq(matchQueue.userId, userId)
});
const count = await db.select({ count: sql`count(*)` }).from(matchQueue);
return {
inQueue: !!entry,
queueSize: Number(count[0].count),
joinedAt: entry?.joinedAt ?? null
};
}
async function tryMatchFromQueue() {
const queue = await db.query.matchQueue.findMany({
orderBy: asc(matchQueue.elo)
});
if (queue.length < 2) return null;
let bestPair = null;
let smallestGap = Infinity;
for (let i = 0; i < queue.length - 1; i++) {
const gap = Math.abs(queue[i].elo - queue[i + 1].elo);
if (gap < smallestGap) {
smallestGap = gap;
bestPair = [queue[i], queue[i + 1]];
}
}
if (!bestPair) return null;
const avgElo = (bestPair[0].elo + bestPair[1].elo) / 2;
const selectedPool = await selectMappoolForRating(avgElo);
if (!selectedPool) throw new Error("No mappools available");
await db.delete(matchQueue).where(eq(matchQueue.userId, bestPair[0].userId));
await db.delete(matchQueue).where(eq(matchQueue.userId, bestPair[1].userId));
const created = await createMatch({
name: "Ranked Match",
config: { bestOf: 7, teamSize: 1, scoringType: "score" },
mappoolId: selectedPool.id,
teams: [bestPair[0].teamId, bestPair[1].teamId],
createdBy: "system"
});
return created;
}
async function selectMappoolForRating(avgElo) {
const pools = await db.query.mappool.findMany({
with: { slots: true }
});
if (pools.length === 0) return null;
const targetStars = 3 + (avgElo - 800) / 400 * 4;
const clampedTarget = Math.max(2, Math.min(8, targetStars));
let bestPool = pools[0];
let bestDiff = Infinity;
for (const pool of pools) {
if (pool.slots.length === 0) continue;
const avgStars = pool.slots.reduce((sum, s) => sum + (s.starRating ?? 0), 0) / pool.slots.length;
const diff = Math.abs(avgStars - clampedTarget);
if (diff < bestDiff) {
bestDiff = diff;
bestPool = pool;
}
}
return bestPool;
}
async function createMatch(opts) {
const { name, config, mappoolId, teams, createdBy } = opts;
const [created] = await db.insert(match).values({
name,
config,
mappoolId,
createdBy,
state: MATCH_STATES.CREATED
}).returning();
for (let i = 0; i < teams.length; i++) {
const [participant] = await db.insert(matchParticipant).values({
matchId: created.id,
teamId: teams[i],
slot: i + 1
}).returning();
const members = await db.query.teamMember.findMany({
where: eq(teamMember.teamId, teams[i])
});
for (const member of members) {
await db.insert(matchParticipantPlayer).values({
participantId: participant.id,
userId: member.userId
});
}
}
return getMatchFull(created.id);
}
async function moveToLobby(matchId, osuLobbyId) {
const m = await getMatchOrThrow(matchId);
assertState(m.state, MATCH_STATES.CREATED);
await db.update(match).set({
state: MATCH_STATES.LOBBY,
osuLobbyId: osuLobbyId ?? null,
startedAt: /* @__PURE__ */ new Date()
}).where(eq(match.id, matchId));
return getMatchFull(matchId);
}
async function moveToRolling(matchId) {
const m = await getMatchOrThrow(matchId);
assertState(m.state, MATCH_STATES.LOBBY);
await db.update(match).set({ state: MATCH_STATES.ROLLING }).where(eq(match.id, matchId));
return getMatchFull(matchId);
}
async function submitRoll(matchId, participantId, value) {
const m = await getMatchOrThrow(matchId);
assertState(m.state, MATCH_STATES.ROLLING);
await db.update(matchParticipant).set({ rollValue: value }).where(eq(matchParticipant.id, participantId));
const participants = await db.query.matchParticipant.findMany({
where: eq(matchParticipant.matchId, matchId)
});
const allRolled = participants.every(
(p) => p.id === participantId ? true : p.rollValue !== null
);
if (allRolled) {
const sorted = [...participants].map((p) => ({
...p,
rollValue: p.id === participantId ? value : p.rollValue
})).sort((a, b) => b.rollValue - a.rollValue);
for (let i = 0; i < sorted.length; i++) {
await db.update(matchParticipant).set({ pickOrder: i + 1 }).where(eq(matchParticipant.id, sorted[i].id));
}
await db.update(match).set({ state: MATCH_STATES.PICKING }).where(eq(match.id, matchId));
}
return getMatchFull(matchId);
}
async function pickMap(matchId, participantId, mappoolSlotId) {
const m = await getMatchOrThrow(matchId);
assertState(m.state, MATCH_STATES.PICKING);
const participants = await db.query.matchParticipant.findMany({
where: eq(matchParticipant.matchId, matchId)
});
const totalGames = await db.query.matchGame.findMany({
where: eq(matchGame.matchId, matchId)
});
const expectedPicker = getExpectedPicker(participants, totalGames.length);
if (expectedPicker.id !== participantId) {
throw new Error("Not your turn to pick");
}
const alreadyPlayed = totalGames.some((g) => g.mappoolSlotId === mappoolSlotId);
if (alreadyPlayed) {
throw new Error("This map has already been played");
}
const [game] = await db.insert(matchGame).values({
matchId,
gameNumber: totalGames.length + 1,
mappoolSlotId,
pickedByParticipantId: participantId,
state: GAME_STATES.PLAYING,
startedAt: /* @__PURE__ */ new Date()
}).returning();
await db.update(match).set({ state: MATCH_STATES.PLAYING }).where(eq(match.id, matchId));
return game;
}
async function submitGameScores(matchGameId, scores) {
const game = await db.query.matchGame.findFirst({
where: eq(matchGame.id, matchGameId)
});
if (!game) throw new Error("Game not found");
if (game.state !== GAME_STATES.PLAYING) throw new Error(`Game is ${game.state}, not PLAYING`);
for (const s of scores) {
await db.insert(matchGameScore).values({
matchGameId,
playerId: s.playerId,
score: s.score,
accuracy: s.accuracy ?? 0,
maxCombo: s.maxCombo ?? 0,
count300: s.count300 ?? 0,
count100: s.count100 ?? 0,
count50: s.count50 ?? 0,
countMiss: s.countMiss ?? 0,
mods: s.mods ?? [],
passed: s.passed ?? true
});
}
const allScores = await db.query.matchGameScore.findMany({
where: eq(matchGameScore.matchGameId, matchGameId),
with: { player: true }
});
const participantScores = /* @__PURE__ */ new Map();
for (const s of allScores) {
const pid = s.player.participantId;
participantScores.set(pid, (participantScores.get(pid) ?? 0) + s.score);
}
let winnerId = null;
let highScore = -1;
for (const [pid, total] of participantScores) {
if (total > highScore) {
highScore = total;
winnerId = pid;
}
}
await db.update(matchGame).set({
state: GAME_STATES.FINISHED,
winnerParticipantId: winnerId,
finishedAt: /* @__PURE__ */ new Date()
}).where(eq(matchGame.id, matchGameId));
if (winnerId) {
const participant = await db.query.matchParticipant.findFirst({
where: eq(matchParticipant.id, winnerId)
});
if (participant) {
await db.update(matchParticipant).set({ score: participant.score + 1 }).where(eq(matchParticipant.id, winnerId));
}
}
const m = await getMatchOrThrow(game.matchId);
const config = m.config;
const winsNeeded = Math.ceil(config.bestOf / 2);
const participants = await db.query.matchParticipant.findMany({
where: eq(matchParticipant.matchId, game.matchId)
});
const matchWinner = participants.find((p) => p.score >= winsNeeded);
if (matchWinner) {
await db.update(match).set({
state: MATCH_STATES.FINISHED,
winnerId: matchWinner.teamId,
finishedAt: /* @__PURE__ */ new Date()
}).where(eq(match.id, game.matchId));
await updateElo(participants, matchWinner.id);
} else {
await db.update(match).set({ state: MATCH_STATES.PICKING }).where(eq(match.id, game.matchId));
}
return getMatchFull(game.matchId);
}
async function updateElo(participants, winnerId) {
for (const p of participants) {
const players = await db.query.matchParticipantPlayer.findMany({
where: eq(matchParticipantPlayer.participantId, p.id)
});
const isWinner = p.id === winnerId;
for (const player of players) {
let rating = await db.query.playerRating.findFirst({
where: eq(playerRating.userId, player.userId)
});
if (!rating) {
[rating] = await db.insert(playerRating).values({ userId: player.userId, elo: 1e3 }).returning();
}
const K = 32;
const expected = 0.5;
const actual = isWinner ? 1 : 0;
const newElo = Math.round(rating.elo + K * (actual - expected));
await db.update(playerRating).set({
elo: newElo,
wins: isWinner ? rating.wins + 1 : rating.wins,
losses: isWinner ? rating.losses : rating.losses + 1,
updatedAt: /* @__PURE__ */ new Date()
}).where(eq(playerRating.userId, player.userId));
}
}
}
async function cancelMatch(matchId) {
await db.update(match).set({
state: MATCH_STATES.CANCELLED,
finishedAt: /* @__PURE__ */ new Date()
}).where(eq(match.id, matchId));
return getMatchFull(matchId);
}
function getExpectedPicker(participants, gameCount) {
const sorted = [...participants].sort((a, b) => (a.pickOrder ?? 99) - (b.pickOrder ?? 99));
const pickerIndex = gameCount % sorted.length;
return sorted[pickerIndex];
}
async function getMatchFull(matchId) {
const m = await db.query.match.findFirst({
where: eq(match.id, matchId),
with: {
mappool: {
with: { slots: true }
},
participants: {
with: {
team: true,
players: true
}
},
games: {
with: {
slot: true,
scores: {
with: { player: true }
}
},
orderBy: (g, { asc: asc2 }) => [asc2(g.gameNumber)]
}
}
});
if (!m) throw new Error("Match not found");
return m;
}
async function getMatchOrThrow(matchId) {
const m = await db.query.match.findFirst({
where: eq(match.id, matchId)
});
if (!m) throw new Error("Match not found");
return m;
}
function assertState(current, expected) {
if (current !== expected) {
throw new Error(`Match is ${current}, expected ${expected}`);
}
}
export {
MATCH_STATES as M,
cancelMatch as a,
moveToRolling as b,
createMatch as c,
submitGameScores as d,
getQueueStatus as e,
getMatchFull as g,
joinQueue as j,
leaveQueue as l,
moveToLobby as m,
pickMap as p,
submitRoll as s
};

View File

@@ -0,0 +1,14 @@
let building = false;
let prerendering = false;
function set_building() {
building = true;
}
function set_prerendering() {
prerendering = true;
}
export {
set_prerendering as a,
building as b,
prerendering as p,
set_building as s
};

View File

@@ -0,0 +1,70 @@
function validator(expected) {
function validate(module, file) {
if (!module) return;
for (const key in module) {
if (key[0] === "_" || expected.has(key)) continue;
const values = [...expected.values()];
const hint = hint_for_supported_files(key, file?.slice(file.lastIndexOf("."))) ?? `valid exports are ${values.join(", ")}, or anything with a '_' prefix`;
throw new Error(`Invalid export '${key}'${file ? ` in ${file}` : ""} (${hint})`);
}
}
return validate;
}
function hint_for_supported_files(key, ext = ".js") {
const supported_files = [];
if (valid_layout_exports.has(key)) {
supported_files.push(`+layout${ext}`);
}
if (valid_page_exports.has(key)) {
supported_files.push(`+page${ext}`);
}
if (valid_layout_server_exports.has(key)) {
supported_files.push(`+layout.server${ext}`);
}
if (valid_page_server_exports.has(key)) {
supported_files.push(`+page.server${ext}`);
}
if (valid_server_exports.has(key)) {
supported_files.push(`+server${ext}`);
}
if (supported_files.length > 0) {
return `'${key}' is a valid export in ${supported_files.slice(0, -1).join(", ")}${supported_files.length > 1 ? " or " : ""}${supported_files.at(-1)}`;
}
}
const valid_layout_exports = /* @__PURE__ */ new Set([
"load",
"prerender",
"csr",
"ssr",
"trailingSlash",
"config"
]);
const valid_page_exports = /* @__PURE__ */ new Set([...valid_layout_exports, "entries"]);
const valid_layout_server_exports = /* @__PURE__ */ new Set([...valid_layout_exports]);
const valid_page_server_exports = /* @__PURE__ */ new Set([...valid_layout_server_exports, "actions", "entries"]);
const valid_server_exports = /* @__PURE__ */ new Set([
"GET",
"POST",
"PATCH",
"PUT",
"DELETE",
"OPTIONS",
"HEAD",
"fallback",
"prerender",
"trailingSlash",
"config",
"entries"
]);
const validate_layout_exports = validator(valid_layout_exports);
const validate_page_exports = validator(valid_page_exports);
const validate_layout_server_exports = validator(valid_layout_server_exports);
const validate_page_server_exports = validator(valid_page_server_exports);
const validate_server_exports = validator(valid_server_exports);
export {
validate_layout_exports as a,
validate_page_server_exports as b,
validate_page_exports as c,
validate_server_exports as d,
validate_layout_server_exports as v
};

View File

@@ -0,0 +1,4 @@
const DEV = false;
export {
DEV as D
};

View File

@@ -0,0 +1,60 @@
import { n as noop } from "./index3.js";
import { s as safe_not_equal } from "./root.js";
import "clsx";
const subscriber_queue = [];
function readable(value, start) {
return {
subscribe: writable(value, start).subscribe
};
}
function writable(value, start = noop) {
let stop = null;
const subscribers = /* @__PURE__ */ new Set();
function set(new_value) {
if (safe_not_equal(value, new_value)) {
value = new_value;
if (stop) {
const run_queue = !subscriber_queue.length;
for (const subscriber of subscribers) {
subscriber[1]();
subscriber_queue.push(subscriber, value);
}
if (run_queue) {
for (let i = 0; i < subscriber_queue.length; i += 2) {
subscriber_queue[i][0](subscriber_queue[i + 1]);
}
subscriber_queue.length = 0;
}
}
}
}
function update(fn) {
set(fn(
/** @type {T} */
value
));
}
function subscribe(run, invalidate = noop) {
const subscriber = [run, invalidate];
subscribers.add(subscriber);
if (subscribers.size === 1) {
stop = start(set, update) || noop;
}
run(
/** @type {T} */
value
);
return () => {
subscribers.delete(subscriber);
if (subscribers.size === 0 && stop) {
stop();
stop = null;
}
};
}
return { set, update, subscribe };
}
export {
readable as r,
writable as w
};

View File

@@ -0,0 +1,302 @@
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import { pgTable, timestamp, text, boolean, index, uuid, real, integer, jsonb, uniqueIndex } from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
import { b as private_env } from "./shared-server.js";
const user = pgTable("user", {
id: text("id").primaryKey(),
name: text("name").notNull(),
email: text("email").notNull().unique(),
emailVerified: boolean("email_verified").default(false).notNull(),
image: text("image"),
// ── Staff role: 'player' | 'referee' | 'admin' ──
role: text("role").default("player").notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().$onUpdate(() => /* @__PURE__ */ new Date()).notNull()
});
const session = pgTable(
"session",
{
id: text("id").primaryKey(),
expiresAt: timestamp("expires_at").notNull(),
token: text("token").notNull().unique(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").$onUpdate(() => /* @__PURE__ */ new Date()).notNull(),
ipAddress: text("ip_address"),
userAgent: text("user_agent"),
userId: text("user_id").notNull().references(() => user.id, { onDelete: "cascade" })
},
(table) => [index("session_userId_idx").on(table.userId)]
);
const account = pgTable(
"account",
{
id: text("id").primaryKey(),
accountId: text("account_id").notNull(),
providerId: text("provider_id").notNull(),
userId: text("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
accessTokenExpiresAt: timestamp("access_token_expires_at"),
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
scope: text("scope"),
password: text("password"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").$onUpdate(() => /* @__PURE__ */ new Date()).notNull()
},
(table) => [index("account_userId_idx").on(table.userId)]
);
const verification = pgTable(
"verification",
{
id: text("id").primaryKey(),
identifier: text("identifier").notNull(),
value: text("value").notNull(),
expiresAt: timestamp("expires_at").notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().$onUpdate(() => /* @__PURE__ */ new Date()).notNull()
},
(table) => [index("verification_identifier_idx").on(table.identifier)]
);
const userRelations = relations(user, ({ many }) => ({
sessions: many(session),
accounts: many(account)
}));
const sessionRelations = relations(session, ({ one }) => ({
user: one(user, {
fields: [session.userId],
references: [user.id]
})
}));
const accountRelations = relations(account, ({ one }) => ({
user: one(user, {
fields: [account.userId],
references: [user.id]
})
}));
const team = pgTable("team", {
id: uuid("id").primaryKey().defaultRandom(),
name: text("name").notNull(),
isPersonal: boolean("is_personal").default(false).notNull(),
ownerId: text("owner_id"),
avatarUrl: text("avatar_url"),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull()
});
const teamMember = pgTable("team_member", {
id: uuid("id").primaryKey().defaultRandom(),
teamId: uuid("team_id").notNull().references(() => team.id, { onDelete: "cascade" }),
userId: text("user_id").notNull(),
role: text("role").default("member"),
joinedAt: timestamp("joined_at", { withTimezone: true }).defaultNow()
});
const mappool = pgTable("mappool", {
id: uuid("id").primaryKey().defaultRandom(),
name: text("name").notNull(),
createdBy: text("created_by"),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull()
});
const mappoolSlot = pgTable("mappool_slot", {
id: uuid("id").primaryKey().defaultRandom(),
mappoolId: uuid("mappool_id").notNull().references(() => mappool.id, { onDelete: "cascade" }),
category: text("category").notNull(),
orderInCategory: integer("order_in_category").notNull(),
beatmapId: text("beatmap_id").notNull(),
starRating: real("star_rating"),
mods: text("mods").array().default([]).notNull()
});
const match = pgTable(
"match",
{
id: uuid("id").primaryKey().defaultRandom(),
name: text("name"),
state: text("state").default("CREATED").notNull(),
config: jsonb("config").notNull(),
mappoolId: uuid("mappool_id").references(() => mappool.id),
osuLobbyId: integer("osu_lobby_id"),
scheduledAt: timestamp("scheduled_at", { withTimezone: true }),
startedAt: timestamp("started_at", { withTimezone: true }),
finishedAt: timestamp("finished_at", { withTimezone: true }),
winnerId: uuid("winner_id").references(() => team.id),
createdBy: text("created_by"),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull()
},
(t) => [index("idx_match_state").on(t.state)]
);
const matchParticipant = pgTable(
"match_participant",
{
id: uuid("id").primaryKey().defaultRandom(),
matchId: uuid("match_id").notNull().references(() => match.id, { onDelete: "cascade" }),
teamId: uuid("team_id").notNull().references(() => team.id),
slot: integer("slot").notNull(),
score: integer("score").default(0).notNull(),
rollValue: integer("roll_value"),
pickOrder: integer("pick_order")
},
(t) => [
index("idx_mp_match_team").on(t.matchId, t.teamId),
uniqueIndex("idx_mp_match_slot").on(t.matchId, t.slot),
index("idx_mp_match").on(t.matchId)
]
);
const matchParticipantPlayer = pgTable(
"match_participant_player",
{
id: uuid("id").primaryKey().defaultRandom(),
participantId: uuid("participant_id").notNull().references(() => matchParticipant.id, { onDelete: "cascade" }),
userId: text("user_id").notNull()
},
(t) => [
uniqueIndex("idx_mpp_participant_user").on(t.participantId, t.userId),
index("idx_mpp_participant").on(t.participantId)
]
);
const matchGame = pgTable(
"match_game",
{
id: uuid("id").primaryKey().defaultRandom(),
matchId: uuid("match_id").notNull().references(() => match.id, { onDelete: "cascade" }),
gameNumber: integer("game_number").notNull(),
mappoolSlotId: uuid("mappool_slot_id").notNull().references(() => mappoolSlot.id),
pickedByParticipantId: uuid("picked_by_participant_id").references(() => matchParticipant.id),
winnerParticipantId: uuid("winner_participant_id").references(() => matchParticipant.id),
state: text("state").default("PENDING").notNull(),
startedAt: timestamp("started_at", { withTimezone: true }),
finishedAt: timestamp("finished_at", { withTimezone: true })
},
(t) => [index("idx_match_game_match").on(t.matchId)]
);
const matchGameScore = pgTable(
"match_game_score",
{
id: uuid("id").primaryKey().defaultRandom(),
matchGameId: uuid("match_game_id").notNull().references(() => matchGame.id, { onDelete: "cascade" }),
playerId: uuid("player_id").notNull().references(() => matchParticipantPlayer.id),
score: integer("score").default(0).notNull(),
accuracy: real("accuracy").default(0).notNull(),
maxCombo: integer("max_combo").default(0).notNull(),
count300: integer("count_300").default(0).notNull(),
count100: integer("count_100").default(0).notNull(),
count50: integer("count_50").default(0).notNull(),
countMiss: integer("count_miss").default(0).notNull(),
mods: text("mods").array().default([]).notNull(),
passed: boolean("passed").default(false).notNull()
},
(t) => [index("idx_mgs_game").on(t.matchGameId)]
);
const matchQueue = pgTable(
"match_queue",
{
id: uuid("id").primaryKey().defaultRandom(),
userId: text("user_id").notNull(),
teamId: uuid("team_id").notNull().references(() => team.id),
elo: integer("elo").default(1e3).notNull(),
joinedAt: timestamp("joined_at", { withTimezone: true }).defaultNow().notNull()
},
(t) => [
uniqueIndex("idx_queue_user").on(t.userId),
index("idx_queue_elo").on(t.elo)
]
);
const playerRating = pgTable("player_rating", {
id: uuid("id").primaryKey().defaultRandom(),
userId: text("user_id").notNull().unique(),
elo: integer("elo").default(1e3).notNull(),
wins: integer("wins").default(0).notNull(),
losses: integer("losses").default(0).notNull(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull()
});
const teamRelations = relations(team, ({ many }) => ({
members: many(teamMember)
}));
const teamMemberRelations = relations(teamMember, ({ one }) => ({
team: one(team, { fields: [teamMember.teamId], references: [team.id] })
}));
const mappoolRelations = relations(mappool, ({ many }) => ({
slots: many(mappoolSlot)
}));
const mappoolSlotRelations = relations(mappoolSlot, ({ one }) => ({
mappool: one(mappool, { fields: [mappoolSlot.mappoolId], references: [mappool.id] })
}));
const matchRelations = relations(match, ({ one, many }) => ({
mappool: one(mappool, { fields: [match.mappoolId], references: [mappool.id] }),
participants: many(matchParticipant),
games: many(matchGame)
}));
const matchParticipantRelations = relations(matchParticipant, ({ one, many }) => ({
match: one(match, { fields: [matchParticipant.matchId], references: [match.id] }),
team: one(team, { fields: [matchParticipant.teamId], references: [team.id] }),
players: many(matchParticipantPlayer)
}));
const matchParticipantPlayerRelations = relations(matchParticipantPlayer, ({ one }) => ({
participant: one(matchParticipant, {
fields: [matchParticipantPlayer.participantId],
references: [matchParticipant.id]
})
}));
const matchGameRelations = relations(matchGame, ({ one, many }) => ({
match: one(match, { fields: [matchGame.matchId], references: [match.id] }),
slot: one(mappoolSlot, { fields: [matchGame.mappoolSlotId], references: [mappoolSlot.id] }),
scores: many(matchGameScore)
}));
const matchGameScoreRelations = relations(matchGameScore, ({ one }) => ({
game: one(matchGame, { fields: [matchGameScore.matchGameId], references: [matchGame.id] }),
player: one(matchParticipantPlayer, {
fields: [matchGameScore.playerId],
references: [matchParticipantPlayer.id]
})
}));
const matchQueueRelations = relations(matchQueue, ({ one }) => ({
team: one(team, { fields: [matchQueue.teamId], references: [team.id] })
}));
const schema = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
account,
accountRelations,
mappool,
mappoolRelations,
mappoolSlot,
mappoolSlotRelations,
match,
matchGame,
matchGameRelations,
matchGameScore,
matchGameScoreRelations,
matchParticipant,
matchParticipantPlayer,
matchParticipantPlayerRelations,
matchParticipantRelations,
matchQueue,
matchQueueRelations,
matchRelations,
playerRating,
session,
sessionRelations,
team,
teamMember,
teamMemberRelations,
teamRelations,
user,
userRelations,
verification
}, Symbol.toStringTag, { value: "Module" }));
if (!private_env.DATABASE_URL) throw new Error("DATABASE_URL is not set");
const client = postgres(private_env.DATABASE_URL);
const db = drizzle(client, { schema });
export {
mappoolSlot as a,
match as b,
team as c,
db as d,
matchParticipant as e,
matchParticipantPlayer as f,
matchGame as g,
matchGameScore as h,
matchQueue as i,
account as j,
mappool as m,
playerRating as p,
teamMember as t,
user as u
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
import "./state.svelte.js";
import "clsx";
import "@sveltejs/kit/internal";
import "./url.js";
import "./utils.js";
import { w as writable } from "./index.js";
import "@sveltejs/kit/internal/server";
import "./root.js";
import "./exports.js";
import { g as getContext } from "./index3.js";
function create_updated_store() {
const { set, subscribe } = writable(false);
{
return {
subscribe,
// eslint-disable-next-line @typescript-eslint/require-await
check: async () => false
};
}
}
const stores = {
updated: /* @__PURE__ */ create_updated_store()
};
({
check: stores.updated.check
});
function context() {
return getContext("__request__");
}
const page$1 = {
get data() {
return context().page.data;
},
get error() {
return context().page.error;
},
get status() {
return context().page.status;
},
get url() {
return context().page.url;
}
};
const page = page$1;
export {
page as p
};

View File

@@ -0,0 +1,224 @@
import { logger } from "@better-auth/core/env";
import { createAdapterFactory } from "@better-auth/core/db/adapter";
const memoryAdapter = (db, config) => {
let lazyOptions = null;
const adapterCreator = createAdapterFactory({
config: {
adapterId: "memory",
adapterName: "Memory Adapter",
usePlural: false,
debugLogs: config?.debugLogs || false,
supportsArrays: true,
customTransformInput(props) {
if ((props.options.advanced?.database?.useNumberId || props.options.advanced?.database?.generateId === "serial") && props.field === "id" && props.action === "create") return db[props.model].length + 1;
return props.data;
},
transaction: async (cb) => {
const clone = structuredClone(db);
try {
return await cb(adapterCreator(lazyOptions));
} catch (error) {
Object.keys(db).forEach((key) => {
db[key] = clone[key];
});
throw error;
}
}
},
adapter: ({ getFieldName, getDefaultFieldName, options, getModelName }) => {
const applySortToRecords = (records, sortBy, model) => {
if (!sortBy) return records;
return records.sort((a, b) => {
const field = getFieldName({
model,
field: sortBy.field
});
const aValue = a[field];
const bValue = b[field];
let comparison = 0;
if (aValue == null && bValue == null) comparison = 0;
else if (aValue == null) comparison = -1;
else if (bValue == null) comparison = 1;
else if (typeof aValue === "string" && typeof bValue === "string") comparison = aValue.localeCompare(bValue);
else if (aValue instanceof Date && bValue instanceof Date) comparison = aValue.getTime() - bValue.getTime();
else if (typeof aValue === "number" && typeof bValue === "number") comparison = aValue - bValue;
else if (typeof aValue === "boolean" && typeof bValue === "boolean") comparison = aValue === bValue ? 0 : aValue ? 1 : -1;
else comparison = String(aValue).localeCompare(String(bValue));
return sortBy.direction === "asc" ? comparison : -comparison;
});
};
function convertWhereClause(where, model, join, select) {
const baseRecords = (() => {
const table = db[model];
if (!table) {
logger.error(`[MemoryAdapter] Model ${model} not found in the DB`, Object.keys(db));
throw new Error(`Model ${model} not found`);
}
const evalClause = (record, clause) => {
const { field, value, operator } = clause;
switch (operator) {
case "in":
if (!Array.isArray(value)) throw new Error("Value must be an array");
return value.includes(record[field]);
case "not_in":
if (!Array.isArray(value)) throw new Error("Value must be an array");
return !value.includes(record[field]);
case "contains":
return record[field].includes(value);
case "starts_with":
return record[field].startsWith(value);
case "ends_with":
return record[field].endsWith(value);
case "ne":
return record[field] !== value;
case "gt":
return value != null && Boolean(record[field] > value);
case "gte":
return value != null && Boolean(record[field] >= value);
case "lt":
return value != null && Boolean(record[field] < value);
case "lte":
return value != null && Boolean(record[field] <= value);
default:
return record[field] === value;
}
};
let records = table.filter((record) => {
if (!where.length || where.length === 0) return true;
let result = evalClause(record, where[0]);
for (const clause of where) {
const clauseResult = evalClause(record, clause);
if (clause.connector === "OR") result = result || clauseResult;
else result = result && clauseResult;
}
return result;
});
if (select?.length && select.length > 0) records = records.map((record) => Object.fromEntries(Object.entries(record).filter(([key]) => select.includes(getDefaultFieldName({
model,
field: key
})))));
return records;
})();
if (!join) return baseRecords;
const grouped = /* @__PURE__ */ new Map();
const seenIds = /* @__PURE__ */ new Map();
for (const baseRecord of baseRecords) {
const baseId = String(baseRecord.id);
if (!grouped.has(baseId)) {
const nested = { ...baseRecord };
for (const [joinModel, joinAttr] of Object.entries(join)) {
const joinModelName = getModelName(joinModel);
if (joinAttr.relation === "one-to-one") nested[joinModelName] = null;
else {
nested[joinModelName] = [];
seenIds.set(`${baseId}-${joinModel}`, /* @__PURE__ */ new Set());
}
}
grouped.set(baseId, nested);
}
const nestedEntry = grouped.get(baseId);
for (const [joinModel, joinAttr] of Object.entries(join)) {
const joinModelName = getModelName(joinModel);
const joinTable = db[joinModelName];
if (!joinTable) {
logger.error(`[MemoryAdapter] JoinOption model ${joinModelName} not found in the DB`, Object.keys(db));
throw new Error(`JoinOption model ${joinModelName} not found`);
}
const matchingRecords = joinTable.filter((joinRecord) => joinRecord[joinAttr.on.to] === baseRecord[joinAttr.on.from]);
if (joinAttr.relation === "one-to-one") nestedEntry[joinModelName] = matchingRecords[0] || null;
else {
const seenSet = seenIds.get(`${baseId}-${joinModel}`);
const limit = joinAttr.limit ?? 100;
let count = 0;
for (const matchingRecord of matchingRecords) {
if (count >= limit) break;
if (!seenSet.has(matchingRecord.id)) {
nestedEntry[joinModelName].push(matchingRecord);
seenSet.add(matchingRecord.id);
count++;
}
}
}
}
}
return Array.from(grouped.values());
}
return {
create: async ({ model, data }) => {
if (options.advanced?.database?.useNumberId || options.advanced?.database?.generateId === "serial") data.id = db[getModelName(model)].length + 1;
if (!db[model]) db[model] = [];
db[model].push(data);
return data;
},
findOne: async ({ model, where, select, join }) => {
const res = convertWhereClause(where, model, join, select);
if (join) {
const resArray = res;
if (!resArray.length) return null;
return resArray[0];
}
return res[0] || null;
},
findMany: async ({ model, where, sortBy, limit, select, offset, join }) => {
const res = convertWhereClause(where || [], model, join, select);
if (join) {
const resArray = res;
if (!resArray.length) return [];
applySortToRecords(resArray, sortBy, model);
let paginatedRecords = resArray;
if (offset !== void 0) paginatedRecords = paginatedRecords.slice(offset);
if (limit !== void 0) paginatedRecords = paginatedRecords.slice(0, limit);
return paginatedRecords;
}
let table = applySortToRecords(res, sortBy, model);
if (offset !== void 0) table = table.slice(offset);
if (limit !== void 0) table = table.slice(0, limit);
return table || [];
},
count: async ({ model, where }) => {
if (where) return convertWhereClause(where, model).length;
return db[model].length;
},
update: async ({ model, where, update }) => {
const res = convertWhereClause(where, model);
res.forEach((record) => {
Object.assign(record, update);
});
return res[0] || null;
},
delete: async ({ model, where }) => {
const table = db[model];
const res = convertWhereClause(where, model);
db[model] = table.filter((record) => !res.includes(record));
},
deleteMany: async ({ model, where }) => {
const table = db[model];
const res = convertWhereClause(where, model);
let count = 0;
db[model] = table.filter((record) => {
if (res.includes(record)) {
count++;
return false;
}
return !res.includes(record);
});
return count;
},
updateMany({ model, where, update }) {
const res = convertWhereClause(where, model);
res.forEach((record) => {
Object.assign(record, update);
});
return res[0] || null;
}
};
}
});
return (options) => {
lazyOptions = options;
return adapterCreator(options);
};
};
export {
memoryAdapter
};

View File

@@ -0,0 +1,307 @@
import { c as createKyselyAdapter } from "./auth.js";
import { g } from "./auth.js";
import { sql } from "kysely";
import { createAdapterFactory } from "@better-auth/core/db/adapter";
const kyselyAdapter = (db, config) => {
let lazyOptions = null;
const createCustomAdapter = (db$1) => {
return ({ getFieldName, schema, getDefaultFieldName, getDefaultModelName, getFieldAttributes, getModelName }) => {
const selectAllJoins = (join) => {
const allSelects = [];
const allSelectsStr = [];
if (join) for (const [joinModel, _] of Object.entries(join)) {
const fields = schema[getDefaultModelName(joinModel)]?.fields;
const [_joinModelSchema, joinModelName] = joinModel.includes(".") ? joinModel.split(".") : [void 0, joinModel];
if (!fields) continue;
fields.id = { type: "string" };
for (const [field, fieldAttr] of Object.entries(fields)) {
allSelects.push(sql`${sql.ref(`join_${joinModelName}`)}.${sql.ref(fieldAttr.fieldName || field)} as ${sql.ref(`_joined_${joinModelName}_${fieldAttr.fieldName || field}`)}`);
allSelectsStr.push({
joinModel,
joinModelRef: joinModelName,
fieldName: fieldAttr.fieldName || field
});
}
}
return {
allSelectsStr,
allSelects
};
};
const withReturning = async (values, builder, model, where) => {
let res;
if (config?.type === "mysql") {
await builder.execute();
const field = values.id ? "id" : where.length > 0 && where[0]?.field ? where[0].field : "id";
if (!values.id && where.length === 0) {
res = await db$1.selectFrom(model).selectAll().orderBy(getFieldName({
model,
field
}), "desc").limit(1).executeTakeFirst();
return res;
}
const value = values[field] || where[0]?.value;
res = await db$1.selectFrom(model).selectAll().orderBy(getFieldName({
model,
field
}), "desc").where(getFieldName({
model,
field
}), "=", value).limit(1).executeTakeFirst();
return res;
}
if (config?.type === "mssql") {
res = await builder.outputAll("inserted").executeTakeFirst();
return res;
}
res = await builder.returningAll().executeTakeFirst();
return res;
};
function convertWhereClause(model, w) {
if (!w) return {
and: null,
or: null
};
const conditions = {
and: [],
or: []
};
w.forEach((condition) => {
const { field: _field, value: _value, operator = "=", connector = "AND" } = condition;
const value = _value;
const field = getFieldName({
model,
field: _field
});
const expr = (eb) => {
const f = `${model}.${field}`;
if (operator.toLowerCase() === "in") return eb(f, "in", Array.isArray(value) ? value : [value]);
if (operator.toLowerCase() === "not_in") return eb(f, "not in", Array.isArray(value) ? value : [value]);
if (operator === "contains") return eb(f, "like", `%${value}%`);
if (operator === "starts_with") return eb(f, "like", `${value}%`);
if (operator === "ends_with") return eb(f, "like", `%${value}`);
if (operator === "eq") return eb(f, "=", value);
if (operator === "ne") return eb(f, "<>", value);
if (operator === "gt") return eb(f, ">", value);
if (operator === "gte") return eb(f, ">=", value);
if (operator === "lt") return eb(f, "<", value);
if (operator === "lte") return eb(f, "<=", value);
return eb(f, operator, value);
};
if (connector === "OR") conditions.or.push(expr);
else conditions.and.push(expr);
});
return {
and: conditions.and.length ? conditions.and : null,
or: conditions.or.length ? conditions.or : null
};
}
function processJoinedResults(rows, joinConfig, allSelectsStr) {
if (!joinConfig || !rows.length) return rows;
const groupedByMainId = /* @__PURE__ */ new Map();
for (const currentRow of rows) {
const mainModelFields = {};
const joinedModelFields = {};
for (const [joinModel] of Object.entries(joinConfig)) joinedModelFields[getModelName(joinModel)] = {};
for (const [key, value] of Object.entries(currentRow)) {
const keyStr = String(key);
let assigned = false;
for (const { joinModel, fieldName, joinModelRef } of allSelectsStr) if (keyStr === `_joined_${joinModelRef}_${fieldName}`) {
joinedModelFields[getModelName(joinModel)][getFieldName({
model: joinModel,
field: fieldName
})] = value;
assigned = true;
break;
}
if (!assigned) mainModelFields[key] = value;
}
const mainId = mainModelFields.id;
if (!mainId) continue;
if (!groupedByMainId.has(mainId)) {
const entry$1 = { ...mainModelFields };
for (const [joinModel, joinAttr] of Object.entries(joinConfig)) entry$1[getModelName(joinModel)] = joinAttr.relation === "one-to-one" ? null : [];
groupedByMainId.set(mainId, entry$1);
}
const entry = groupedByMainId.get(mainId);
for (const [joinModel, joinAttr] of Object.entries(joinConfig)) {
const isUnique = joinAttr.relation === "one-to-one";
const limit = joinAttr.limit ?? 100;
const joinedObj = joinedModelFields[getModelName(joinModel)];
const hasData = joinedObj && Object.keys(joinedObj).length > 0 && Object.values(joinedObj).some((value) => value !== null && value !== void 0);
if (isUnique) entry[getModelName(joinModel)] = hasData ? joinedObj : null;
else {
const joinModelName = getModelName(joinModel);
if (Array.isArray(entry[joinModelName]) && hasData) {
if (entry[joinModelName].length >= limit) continue;
const idFieldName = getFieldName({
model: joinModel,
field: "id"
});
const joinedId = joinedObj[idFieldName];
if (joinedId) {
if (!entry[joinModelName].some((item) => item[idFieldName] === joinedId) && entry[joinModelName].length < limit) entry[joinModelName].push(joinedObj);
} else if (entry[joinModelName].length < limit) entry[joinModelName].push(joinedObj);
}
}
}
}
const result = Array.from(groupedByMainId.values());
for (const entry of result) for (const [joinModel, joinAttr] of Object.entries(joinConfig)) if (joinAttr.relation !== "one-to-one") {
const joinModelName = getModelName(joinModel);
if (Array.isArray(entry[joinModelName])) {
const limit = joinAttr.limit ?? 100;
if (entry[joinModelName].length > limit) entry[joinModelName] = entry[joinModelName].slice(0, limit);
}
}
return result;
}
return {
async create({ data, model }) {
return await withReturning(data, db$1.insertInto(model).values(data), model, []);
},
async findOne({ model, where, select, join }) {
const { and, or } = convertWhereClause(model, where);
let query = db$1.selectFrom((eb) => {
let b = eb.selectFrom(model);
if (and) b = b.where((eb$1) => eb$1.and(and.map((expr) => expr(eb$1))));
if (or) b = b.where((eb$1) => eb$1.or(or.map((expr) => expr(eb$1))));
if (select?.length && select.length > 0) b = b.select(select.map((field) => getFieldName({
model,
field
})));
else b = b.selectAll();
return b.as("primary");
}).selectAll("primary");
if (join) for (const [joinModel, joinAttr] of Object.entries(join)) {
const [_joinModelSchema, joinModelName] = joinModel.includes(".") ? joinModel.split(".") : [void 0, joinModel];
query = query.leftJoin(`${joinModel} as join_${joinModelName}`, (join$1) => join$1.onRef(`join_${joinModelName}.${joinAttr.on.to}`, "=", `primary.${joinAttr.on.from}`));
}
const { allSelectsStr, allSelects } = selectAllJoins(join);
query = query.select(allSelects);
const res = await query.execute();
if (!res || !Array.isArray(res) || res.length === 0) return null;
const row = res[0];
if (join) return processJoinedResults(res, join, allSelectsStr)[0];
return row;
},
async findMany({ model, where, limit, select, offset, sortBy, join }) {
const { and, or } = convertWhereClause(model, where);
let query = db$1.selectFrom((eb) => {
let b = eb.selectFrom(model);
if (config?.type === "mssql") {
if (offset !== void 0) {
if (!sortBy) b = b.orderBy(getFieldName({
model,
field: "id"
}));
b = b.offset(offset).fetch(limit || 100);
} else if (limit !== void 0) b = b.top(limit);
} else {
if (limit !== void 0) b = b.limit(limit);
if (offset !== void 0) b = b.offset(offset);
}
if (sortBy?.field) b = b.orderBy(`${getFieldName({
model,
field: sortBy.field
})}`, sortBy.direction);
if (and) b = b.where((eb$1) => eb$1.and(and.map((expr) => expr(eb$1))));
if (or) b = b.where((eb$1) => eb$1.or(or.map((expr) => expr(eb$1))));
if (select?.length && select.length > 0) b = b.select(select.map((field) => getFieldName({
model,
field
})));
else b = b.selectAll();
return b.as("primary");
}).selectAll("primary");
if (join) for (const [joinModel, joinAttr] of Object.entries(join)) {
const [_joinModelSchema, joinModelName] = joinModel.includes(".") ? joinModel.split(".") : [void 0, joinModel];
query = query.leftJoin(`${joinModel} as join_${joinModelName}`, (join$1) => join$1.onRef(`join_${joinModelName}.${joinAttr.on.to}`, "=", `primary.${joinAttr.on.from}`));
}
const { allSelectsStr, allSelects } = selectAllJoins(join);
query = query.select(allSelects);
if (sortBy?.field) query = query.orderBy(`${getFieldName({
model,
field: sortBy.field
})}`, sortBy.direction);
const res = await query.execute();
if (!res) return [];
if (join) return processJoinedResults(res, join, allSelectsStr);
return res;
},
async update({ model, where, update: values }) {
const { and, or } = convertWhereClause(model, where);
let query = db$1.updateTable(model).set(values);
if (and) query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));
if (or) query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));
return await withReturning(values, query, model, where);
},
async updateMany({ model, where, update: values }) {
const { and, or } = convertWhereClause(model, where);
let query = db$1.updateTable(model).set(values);
if (and) query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));
if (or) query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));
const res = (await query.executeTakeFirst()).numUpdatedRows;
return res > Number.MAX_SAFE_INTEGER ? Number.MAX_SAFE_INTEGER : Number(res);
},
async count({ model, where }) {
const { and, or } = convertWhereClause(model, where);
let query = db$1.selectFrom(model).select(db$1.fn.count("id").as("count"));
if (and) query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));
if (or) query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));
const res = await query.execute();
if (typeof res[0].count === "number") return res[0].count;
if (typeof res[0].count === "bigint") return Number(res[0].count);
return parseInt(res[0].count);
},
async delete({ model, where }) {
const { and, or } = convertWhereClause(model, where);
let query = db$1.deleteFrom(model);
if (and) query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));
if (or) query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));
await query.execute();
},
async deleteMany({ model, where }) {
const { and, or } = convertWhereClause(model, where);
let query = db$1.deleteFrom(model);
if (and) query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));
if (or) query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));
const res = (await query.executeTakeFirst()).numDeletedRows;
return res > Number.MAX_SAFE_INTEGER ? Number.MAX_SAFE_INTEGER : Number(res);
},
options: config
};
};
};
let adapterOptions = null;
adapterOptions = {
config: {
adapterId: "kysely",
adapterName: "Kysely Adapter",
usePlural: config?.usePlural,
debugLogs: config?.debugLogs,
supportsBooleans: config?.type === "sqlite" || config?.type === "mssql" || config?.type === "mysql" || !config?.type ? false : true,
supportsDates: config?.type === "sqlite" || config?.type === "mssql" || !config?.type ? false : true,
supportsJSON: config?.type === "postgres" ? true : false,
supportsArrays: false,
supportsUUIDs: config?.type === "postgres" ? true : false,
transaction: config?.transaction ? (cb) => db.transaction().execute((trx) => {
return cb(createAdapterFactory({
config: adapterOptions.config,
adapter: createCustomAdapter(trx)
})(lazyOptions));
}) : false
},
adapter: createCustomAdapter(db)
};
const adapter = createAdapterFactory(adapterOptions);
return (options) => {
lazyOptions = options;
return adapter(options);
};
};
export {
createKyselyAdapter,
g as getKyselyDatabaseType,
kyselyAdapter
};

View File

@@ -0,0 +1,127 @@
import { r as root } from "./root.js";
import "./environment.js";
import "./server.js";
import "./shared-server.js";
let read_implementation = null;
function set_read_implementation(fn) {
read_implementation = fn;
}
function set_manifest(_) {
}
const options = {
app_template_contains_nonce: false,
async: false,
csp: { "mode": "auto", "directives": { "upgrade-insecure-requests": false, "block-all-mixed-content": false }, "reportOnly": { "upgrade-insecure-requests": false, "block-all-mixed-content": false } },
csrf_check_origin: true,
csrf_trusted_origins: [],
embedded: false,
env_public_prefix: "PUBLIC_",
env_private_prefix: "",
hash_routing: false,
hooks: null,
// added lazily, via `get_hooks`
preload_strategy: "modulepreload",
root,
service_worker: false,
service_worker_options: void 0,
templates: {
app: ({ head, body, assets, nonce, env }) => '<!doctype html>\n<html lang="en">\n <head>\n <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1" />\n <link rel="preconnect" href="https://fonts.googleapis.com" />\n <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />\n <link\n href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700;800&family=Geist+Mono:wght@400;500&display=swap"\n rel="stylesheet"\n />\n <title>Vash Esports</title>\n ' + head + '\n </head>\n <body data-sveltekit-preload-data="hover">\n <div style="display: contents">' + body + "</div>\n </body>\n</html>\n",
error: ({ status, message }) => '<!doctype html>\n<html lang="en">\n <head>\n <meta charset="utf-8" />\n <title>' + message + `</title>
<style>
body {
--bg: white;
--fg: #222;
--divider: #ccc;
background: var(--bg);
color: var(--fg);
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
Oxygen,
Ubuntu,
Cantarell,
'Open Sans',
'Helvetica Neue',
sans-serif;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
}
.error {
display: flex;
align-items: center;
max-width: 32rem;
margin: 0 1rem;
}
.status {
font-weight: 200;
font-size: 3rem;
line-height: 1;
position: relative;
top: -0.05rem;
}
.message {
border-left: 1px solid var(--divider);
padding: 0 0 0 1rem;
margin: 0 0 0 1rem;
min-height: 2.5rem;
display: flex;
align-items: center;
}
.message h1 {
font-weight: 400;
font-size: 1em;
margin: 0;
}
@media (prefers-color-scheme: dark) {
body {
--bg: #222;
--fg: #ddd;
--divider: #666;
}
}
</style>
</head>
<body>
<div class="error">
<span class="status">` + status + '</span>\n <div class="message">\n <h1>' + message + "</h1>\n </div>\n </div>\n </body>\n</html>\n"
},
version_hash: "12t8tv8"
};
async function get_hooks() {
let handle;
let handleFetch;
let handleError;
let handleValidationError;
let init;
({ handle, handleFetch, handleError, handleValidationError, init } = await import("../entries/hooks.server.js"));
let reroute;
let transport;
return {
handle,
handleFetch,
handleError,
handleValidationError,
init,
reroute,
transport
};
}
export {
set_manifest as a,
get_hooks as g,
options as o,
read_implementation as r,
set_read_implementation as s
};

View File

@@ -0,0 +1,155 @@
import { CompiledQuery, DefaultQueryCompiler, DEFAULT_MIGRATION_TABLE, DEFAULT_MIGRATION_LOCK_TABLE, sql } from "kysely";
var NodeSqliteAdapter = class {
get supportsCreateIfNotExists() {
return true;
}
get supportsTransactionalDdl() {
return false;
}
get supportsReturning() {
return true;
}
async acquireMigrationLock() {
}
async releaseMigrationLock() {
}
get supportsOutput() {
return true;
}
};
var NodeSqliteDriver = class {
#config;
#connectionMutex = new ConnectionMutex();
#db;
#connection;
constructor(config) {
this.#config = { ...config };
}
async init() {
this.#db = this.#config.database;
this.#connection = new NodeSqliteConnection(this.#db);
if (this.#config.onCreateConnection) await this.#config.onCreateConnection(this.#connection);
}
async acquireConnection() {
await this.#connectionMutex.lock();
return this.#connection;
}
async beginTransaction(connection) {
await connection.executeQuery(CompiledQuery.raw("begin"));
}
async commitTransaction(connection) {
await connection.executeQuery(CompiledQuery.raw("commit"));
}
async rollbackTransaction(connection) {
await connection.executeQuery(CompiledQuery.raw("rollback"));
}
async releaseConnection() {
this.#connectionMutex.unlock();
}
async destroy() {
this.#db?.close();
}
};
var NodeSqliteConnection = class {
#db;
constructor(db) {
this.#db = db;
}
executeQuery(compiledQuery) {
const { sql: sql$1, parameters } = compiledQuery;
const rows = this.#db.prepare(sql$1).all(...parameters);
return Promise.resolve({ rows });
}
async *streamQuery() {
throw new Error("Streaming query is not supported by SQLite driver.");
}
};
var ConnectionMutex = class {
#promise;
#resolve;
async lock() {
while (await this.#promise) await this.#promise;
this.#promise = new Promise((resolve) => {
this.#resolve = resolve;
});
}
unlock() {
const resolve = this.#resolve;
this.#promise = void 0;
this.#resolve = void 0;
resolve?.();
}
};
var NodeSqliteIntrospector = class {
#db;
constructor(db) {
this.#db = db;
}
async getSchemas() {
return [];
}
async getTables(options = { withInternalKyselyTables: false }) {
let query = this.#db.selectFrom("sqlite_schema").where("type", "=", "table").where("name", "not like", "sqlite_%").select("name").$castTo();
if (!options.withInternalKyselyTables) query = query.where("name", "!=", DEFAULT_MIGRATION_TABLE).where("name", "!=", DEFAULT_MIGRATION_LOCK_TABLE);
const tables = await query.execute();
return Promise.all(tables.map(({ name }) => this.#getTableMetadata(name)));
}
async getMetadata(options) {
return { tables: await this.getTables(options) };
}
async #getTableMetadata(table) {
const db = this.#db;
const autoIncrementCol = (await db.selectFrom("sqlite_master").where("name", "=", table).select("sql").$castTo().execute())[0]?.sql?.split(/[\(\),]/)?.find((it) => it.toLowerCase().includes("autoincrement"))?.split(/\s+/)?.[0]?.replace(/["`]/g, "");
return {
name: table,
columns: (await db.selectFrom(sql`pragma_table_info(${table})`.as("table_info")).select([
"name",
"type",
"notnull",
"dflt_value"
]).execute()).map((col) => ({
name: col.name,
dataType: col.type,
isNullable: !col.notnull,
isAutoIncrementing: col.name === autoIncrementCol,
hasDefaultValue: col.dflt_value != null
})),
isView: true
};
}
};
var NodeSqliteQueryCompiler = class extends DefaultQueryCompiler {
getCurrentParameterPlaceholder() {
return "?";
}
getLeftIdentifierWrapper() {
return '"';
}
getRightIdentifierWrapper() {
return '"';
}
getAutoIncrement() {
return "autoincrement";
}
};
var NodeSqliteDialect = class {
#config;
constructor(config) {
this.#config = { ...config };
}
createDriver() {
return new NodeSqliteDriver(this.#config);
}
createQueryCompiler() {
return new NodeSqliteQueryCompiler();
}
createAdapter() {
return new NodeSqliteAdapter();
}
createIntrospector(db) {
return new NodeSqliteIntrospector(db);
}
};
export {
NodeSqliteDialect
};

View File

@@ -0,0 +1,448 @@
import { d as db, b as match, u as user, g as matchGame } from "./index2.js";
import { eq } from "drizzle-orm";
import { g as getMatchFull, M as MATCH_STATES, s as submitRoll, p as pickMap, d as submitGameScores } from "./engine.js";
import { b as private_env } from "./shared-server.js";
let client = null;
let connecting = null;
async function getClient() {
if (client?.isConnected?.()) return client;
if (connecting) {
await connecting;
return client;
}
if (!private_env.OSU_IRC_USERNAME || !private_env.OSU_IRC_PASSWORD) {
throw new Error("OSU_IRC_USERNAME and OSU_IRC_PASSWORD must be set in .env");
}
const banchoModule = await import("bancho.js");
const BanchoClient = banchoModule.BanchoClient ?? banchoModule.default?.BanchoClient ?? banchoModule.default;
client = new BanchoClient({
username: private_env.OSU_IRC_USERNAME,
password: private_env.OSU_IRC_PASSWORD
});
connecting = client.connect().then(() => {
console.log("[Bancho] Connected as", private_env.OSU_IRC_USERNAME);
connecting = null;
});
await connecting;
return client;
}
class TournamentLobby {
channel = null;
channelName = "";
osuMatchId = 0;
// Score collection
collectedScores = [];
matchFinishedResolve = null;
// Ready tracking
allReadyResolve = null;
// Event callbacks (set by orchestrator)
onRollResult = null;
onPickCommand = null;
/**
* Create a new multiplayer lobby via !mp make.
*/
async create(name) {
const c = await getClient();
return new Promise((resolve, reject) => {
const timeout = setTimeout(
() => reject(new Error("Lobby creation timed out")),
15e3
);
const banchoBot = c.getUser("BanchoBot");
const onPM = (msg) => {
const text = msg.message ?? String(msg);
const m = text.match(/https:\/\/osu\.ppy\.sh\/mp\/(\d+)/);
if (m) {
clearTimeout(timeout);
banchoBot.removeListener("message", onPM);
this.osuMatchId = parseInt(m[1]);
this.channelName = `#mp_${this.osuMatchId}`;
this.joinChannel(c).then(
() => resolve({ matchId: this.osuMatchId, channel: this.channelName })
);
}
};
banchoBot.on("message", onPM);
banchoBot.sendMessage(`!mp make ${name}`);
});
}
async joinChannel(c) {
this.channel = c.getChannel(this.channelName);
await this.channel.join();
this.channel.on("message", (msg) => {
const text = msg.message ?? String(msg);
const sender = msg.user?.ircUsername ?? "";
if (sender === "BanchoBot") {
this.parseBanchoMessage(text);
} else if (sender) {
this.parsePlayerMessage(sender, text);
}
});
}
// ── Message Parsing ─────────────────────────────────────────────────
parseBanchoMessage(text) {
const scoreMatch = text.match(
/^(.+?) finished playing \(Score: ([\d,]+).*?(PASSED|FAILED)\)/i
);
if (scoreMatch) {
this.collectedScores.push({
username: scoreMatch[1].trim(),
score: parseInt(scoreMatch[2].replace(/,/g, "")),
passed: scoreMatch[3] === "PASSED"
});
console.log(`[Bancho] Score: ${scoreMatch[1].trim()} = ${scoreMatch[2]}`);
return;
}
if (text.includes("The match has finished!")) {
console.log("[Bancho] Game finished. Scores:", this.collectedScores);
if (this.matchFinishedResolve) {
this.matchFinishedResolve([...this.collectedScores]);
this.matchFinishedResolve = null;
}
this.collectedScores = [];
return;
}
const rollMatch = text.match(/^(.+?) rolls (\d+) point\(s\)/);
if (rollMatch) {
const username = rollMatch[1].trim();
const value = parseInt(rollMatch[2]);
console.log(`[Bancho] Roll: ${username} = ${value}`);
if (this.onRollResult) {
this.onRollResult(username, value);
}
return;
}
if (text.includes("All players are ready")) {
console.log("[Bancho] All players ready");
if (this.allReadyResolve) {
this.allReadyResolve();
this.allReadyResolve = null;
}
return;
}
}
parsePlayerMessage(sender, text) {
const pickMatch = text.match(/^!pick\s+([A-Z]{2})(\d*)/i);
if (pickMatch) {
const category = pickMatch[1].toUpperCase();
const num = pickMatch[2] ? parseInt(pickMatch[2]) : 1;
const label = `${category}${num}`;
console.log(`[Bancho] Pick command from ${sender}: ${label}`);
if (this.onPickCommand) {
this.onPickCommand(sender, label);
}
return;
}
}
// ── IRC Commands ────────────────────────────────────────────────────
async send(cmd) {
if (!this.channel) throw new Error("Lobby not created");
console.log(`[Bancho] ${this.channelName} > ${cmd}`);
await this.channel.sendMessage(cmd);
}
async invite(username) {
await this.send(`!mp invite ${username.replace(/ /g, "_")}`);
}
async setProperties(teamMode, scoreMode, size) {
await this.send(`!mp set ${teamMode} ${scoreMode} ${size}`);
}
async setMap(beatmapId, playmode = 0) {
await this.send(`!mp map ${beatmapId} ${playmode}`);
}
async setMods(mods) {
const filtered = mods.filter((m) => !["NM", "TB", "None", "NF"].includes(m));
if (mods.includes("FM") || mods.includes("Freemod")) {
await this.send("!mp mods Freemod NF");
} else if (filtered.length > 0) {
await this.send(`!mp mods NF ${filtered.join(" ")}`);
} else {
await this.send("!mp mods NF");
}
}
async startGame(delaySec = 5) {
await this.send(`!mp start ${delaySec}`);
}
async close() {
try {
await this.send("!mp close");
} catch {
}
}
async chat(message) {
await this.send(message);
}
// ── Async Waiters ───────────────────────────────────────────────────
/**
* Wait for all players to click "Ready" in osu! client.
* BanchoBot sends "All players are ready" when they do.
*/
waitForReady(timeoutMs = 18e4) {
return new Promise((resolve, reject) => {
const t = setTimeout(() => {
this.allReadyResolve = null;
reject(new Error("Timed out waiting for players to ready"));
}, timeoutMs);
this.allReadyResolve = () => {
clearTimeout(t);
resolve();
};
});
}
/**
* Wait for "The match has finished!" and return all player scores.
*/
waitForScores(timeoutMs = 6e5) {
this.collectedScores = [];
return new Promise((resolve, reject) => {
const t = setTimeout(() => {
this.matchFinishedResolve = null;
reject(new Error("Timed out waiting for match scores"));
}, timeoutMs);
this.matchFinishedResolve = (scores) => {
clearTimeout(t);
resolve(scores);
};
});
}
}
const lobbies = /* @__PURE__ */ new Map();
function getLobby(matchId) {
return lobbies.get(matchId);
}
function setLobby(matchId, lobby) {
lobbies.set(matchId, lobby);
}
function removeLobby(matchId) {
lobbies.delete(matchId);
}
function sleep(ms) {
return new Promise((r) => setTimeout(r, ms));
}
async function initMatchLobby(matchId) {
const m = await getMatchFull(matchId);
const config = m.config;
const lobby = new TournamentLobby();
const lobbyName = `VASH: (${m.participants[0]?.team.name}) vs (${m.participants[1]?.team.name})`;
console.log(`[Orchestrator] Creating lobby: ${lobbyName}`);
const { matchId: osuId, channel } = await lobby.create(lobbyName);
console.log(`[Orchestrator] Created ${channel} (osu mp/${osuId})`);
setLobby(matchId, lobby);
await db.update(match).set({ state: MATCH_STATES.LOBBY, osuLobbyId: osuId, startedAt: /* @__PURE__ */ new Date() }).where(eq(match.id, matchId));
const scoreMode = config.scoringType === "score_v2" ? 3 : config.scoringType === "accuracy" ? 1 : config.scoringType === "combo" ? 2 : 0;
await lobby.setProperties(0, scoreMode, config.teamSize * 2);
await lobby.send("!mp password");
await sleep(500);
const invited = /* @__PURE__ */ new Set();
for (const p of m.participants) {
for (const pl of p.players) {
const u = await db.query.user.findFirst({ where: eq(user.id, pl.userId) });
if (u?.name && !invited.has(u.name.toLowerCase())) {
await lobby.invite(u.name);
invited.add(u.name.toLowerCase());
console.log(`[Orchestrator] Invited ${u.name}`);
await sleep(300);
}
}
}
setupChatHandlers(matchId, lobby);
await lobby.chat(
`Welcome! BO${config.bestOf}. Type !roll to decide pick order, or use the web UI.`
);
await db.update(match).set({ state: MATCH_STATES.ROLLING }).where(eq(match.id, matchId));
return { osuMatchId: osuId, channel };
}
function setupChatHandlers(matchId, lobby) {
lobby.onRollResult = async (username, value) => {
try {
const m = await getMatchFull(matchId);
if (m.state !== MATCH_STATES.ROLLING) {
await lobby.chat(`Rolls are not active right now.`);
return;
}
let targetParticipant = null;
for (const p of m.participants) {
for (const pl of p.players) {
const u = await db.query.user.findFirst({ where: eq(user.id, pl.userId) });
if (u?.name?.toLowerCase() === username.toLowerCase().replace(/_/g, " ")) {
if (p.rollValue === null) {
targetParticipant = p;
break;
} else if (!targetParticipant) {
const unrolled = m.participants.find((pp) => pp.rollValue === null);
if (unrolled) targetParticipant = unrolled;
}
}
}
if (targetParticipant?.rollValue === null) break;
}
if (!targetParticipant || targetParticipant.rollValue !== null) {
await lobby.chat(`${username}: already rolled or not in this match.`);
return;
}
await submitRoll(matchId, targetParticipant.id, value);
console.log(`[Orchestrator] IRC roll: ${username} = ${value}`);
const updated = await getMatchFull(matchId);
if (updated.state === MATCH_STATES.PICKING) {
const sorted = [...updated.participants].sort(
(a, b) => (a.pickOrder ?? 99) - (b.pickOrder ?? 99)
);
await lobby.chat(
`Rolls complete! ${sorted[0]?.team.name} picks first. Use !pick <slot> (e.g. !pick NM1) or pick in web UI.`
);
}
} catch (err) {
console.error("[Orchestrator] IRC roll error:", err.message);
}
};
lobby.onPickCommand = async (username, slotLabel) => {
try {
const m = await getMatchFull(matchId);
if (m.state !== MATCH_STATES.PICKING) {
await lobby.chat(`Picks are not active right now.`);
return;
}
const labelMatch = slotLabel.match(/^([A-Z]{2})(\d+)$/);
if (!labelMatch) {
await lobby.chat(`${username}: Invalid slot. Use format like NM1, HD2, DT1.`);
return;
}
const category = labelMatch[1];
const order = parseInt(labelMatch[2]);
const sorted = [...m.participants].sort(
(a, b) => (a.pickOrder ?? 99) - (b.pickOrder ?? 99)
);
const expectedIdx = m.games.length % sorted.length;
const expectedPicker = sorted[expectedIdx];
let isPickerTurn = false;
if (expectedPicker) {
for (const pl of expectedPicker.players) {
const u = await db.query.user.findFirst({ where: eq(user.id, pl.userId) });
if (u?.name?.toLowerCase() === username.toLowerCase().replace(/_/g, " ")) {
isPickerTurn = true;
break;
}
}
}
if (!isPickerTurn && m.participants[0]?.teamId === m.participants[1]?.teamId) {
isPickerTurn = true;
}
if (!isPickerTurn) {
await lobby.chat(`${username}: It's not your turn to pick.`);
return;
}
const slot = m.mappool?.slots?.find(
(s) => s.category === category && s.orderInCategory === order
);
if (!slot) {
await lobby.chat(`${username}: Slot ${slotLabel} not found in this mappool.`);
return;
}
const alreadyPlayed = m.games.some((g) => g.mappoolSlotId === slot.id);
if (alreadyPlayed) {
await lobby.chat(`${username}: ${slotLabel} has already been played.`);
return;
}
const game = await pickMap(matchId, expectedPicker.id, slot.id);
console.log(`[Orchestrator] IRC pick: ${username} picked ${slotLabel}`);
playPickedMap(matchId, game.id).catch(
(err) => console.error("[Orchestrator] IRC play failed:", err.message)
);
} catch (err) {
console.error("[Orchestrator] IRC pick error:", err.message);
await lobby.chat(`Error: ${err.message}`).catch(() => {
});
}
};
}
async function playPickedMap(matchId, matchGameId) {
const lobby = getLobby(matchId);
if (!lobby) {
console.warn("[Orchestrator] No IRC lobby for", matchId, "— skipping IRC");
return;
}
const game = await db.query.matchGame.findFirst({
where: eq(matchGame.id, matchGameId),
with: { slot: true }
});
if (!game) throw new Error("Game not found");
const slot = game.slot;
await lobby.setMap(slot.beatmapId);
await sleep(1e3);
await lobby.setMods(slot.mods);
await sleep(500);
await lobby.chat(
`Playing ${slot.category}${slot.orderInCategory}. Ready up! (Game starts when all players are ready)`
);
try {
await lobby.waitForReady();
await lobby.chat("All ready — starting in 5s!");
await lobby.startGame(5);
} catch (err) {
console.warn("[Orchestrator] Ready timeout:", err.message);
await lobby.chat("Ready timed out. Use the web UI to force start, or ready up!");
return;
}
collectScores(matchId, matchGameId, lobby).catch(
(err) => console.error("[Orchestrator] Score collection failed:", err)
);
}
async function forceStartGame(matchId) {
const lobby = getLobby(matchId);
if (!lobby) return;
await lobby.chat("Force starting in 10s!");
await lobby.startGame(10);
}
async function collectScores(matchId, matchGameId, lobby) {
const ircScores = await lobby.waitForScores();
console.log(`[Orchestrator] Scores for game ${matchGameId}:`, ircScores);
const m = await getMatchFull(matchId);
const scores = [];
for (const irc of ircScores) {
for (const participant of m.participants) {
for (const player of participant.players) {
const u = await db.query.user.findFirst({ where: eq(user.id, player.userId) });
const ircName = irc.username.toLowerCase().replace(/_/g, " ");
const dbName = u?.name?.toLowerCase();
if (dbName && (dbName === ircName || dbName === irc.username.toLowerCase())) {
scores.push({ playerId: player.id, score: irc.score, passed: irc.passed });
}
}
}
}
if (scores.length === 0) {
console.warn("[Orchestrator] No scores matched any IRC usernames");
return;
}
await submitGameScores(matchGameId, scores);
const updated = await getMatchFull(matchId);
if (updated.state === MATCH_STATES.FINISHED) {
const winner = updated.participants.find((p) => p.teamId === updated.winnerId);
await lobby.chat(`GG! ${winner?.team.name ?? "?"} wins the match!`);
await sleep(5e3);
await lobby.close();
removeLobby(matchId);
} else {
const sorted = [...updated.participants].sort(
(a, b) => (a.pickOrder ?? 99) - (b.pickOrder ?? 99)
);
const nextIdx = updated.games.length % sorted.length;
const nextPicker = sorted[nextIdx];
await lobby.chat(
`${nextPicker?.team.name}'s turn to pick. Use !pick <slot> (e.g. !pick HD1) or pick in web UI.`
);
}
}
async function closeLobby(matchId) {
const lobby = getLobby(matchId);
if (lobby) {
await lobby.close();
removeLobby(matchId);
}
}
export {
closeLobby as c,
forceStartGame as f,
getLobby as g,
initMatchLobby as i,
playPickedMap as p
};

View File

@@ -0,0 +1,258 @@
import { get_request_store, with_request_store } from "@sveltejs/kit/internal/server";
import { z as stringify_remote_arg, f as create_remote_key, h as handle_error_and_jsonify } from "./shared.js";
import { p as prerendering } from "./environment.js";
import { parse } from "devalue";
import { error } from "@sveltejs/kit";
import { HttpError, SvelteKitError } from "@sveltejs/kit/internal";
function create_validator(validate_or_fn, maybe_fn) {
if (!maybe_fn) {
return (arg) => {
if (arg !== void 0) {
error(400, "Bad Request");
}
};
}
if (validate_or_fn === "unchecked") {
return (arg) => arg;
}
if ("~standard" in validate_or_fn) {
return async (arg) => {
const { event, state } = get_request_store();
const result = await validate_or_fn["~standard"].validate(arg);
if (result.issues) {
error(
400,
await state.handleValidationError({
issues: result.issues,
event
})
);
}
return result.value;
};
}
throw new Error(
'Invalid validator passed to remote function. Expected "unchecked" or a Standard Schema (https://standardschema.dev)'
);
}
async function get_response(info, arg, state, get_result) {
await 0;
const cache = get_cache(info, state);
return cache[stringify_remote_arg(arg, state.transport)] ??= get_result();
}
function parse_remote_response(data, transport) {
const revivers = {};
for (const key in transport) {
revivers[key] = transport[key].decode;
}
return parse(data, revivers);
}
async function run_remote_function(event, state, allow_cookies, get_input, fn) {
const store = {
event: {
...event,
setHeaders: () => {
throw new Error("setHeaders is not allowed in remote functions");
},
cookies: {
...event.cookies,
set: (name, value, opts) => {
if (!allow_cookies) {
throw new Error("Cannot set cookies in `query` or `prerender` functions");
}
if (opts.path && !opts.path.startsWith("/")) {
throw new Error("Cookies set in remote functions must have an absolute path");
}
return event.cookies.set(name, value, opts);
},
delete: (name, opts) => {
if (!allow_cookies) {
throw new Error("Cannot delete cookies in `query` or `prerender` functions");
}
if (opts.path && !opts.path.startsWith("/")) {
throw new Error("Cookies deleted in remote functions must have an absolute path");
}
return event.cookies.delete(name, opts);
}
}
},
state: {
...state,
is_in_remote_function: true
}
};
const input = await with_request_store(store, get_input);
return with_request_store(store, () => fn(input));
}
function get_cache(info, state = get_request_store().state) {
let cache = state.remote_data?.get(info);
if (cache === void 0) {
cache = {};
(state.remote_data ??= /* @__PURE__ */ new Map()).set(info, cache);
}
return cache;
}
// @__NO_SIDE_EFFECTS__
function query(validate_or_fn, maybe_fn) {
const fn = maybe_fn ?? validate_or_fn;
const validate = create_validator(validate_or_fn, maybe_fn);
const __ = { type: "query", id: "", name: "" };
const wrapper = (arg) => {
if (prerendering) {
throw new Error(
`Cannot call query '${__.name}' while prerendering, as prerendered pages need static data. Use 'prerender' from $app/server instead`
);
}
const { event, state } = get_request_store();
const get_remote_function_result = () => run_remote_function(event, state, false, () => validate(arg), fn);
const promise = get_response(__, arg, state, get_remote_function_result);
promise.catch(() => {
});
promise.set = (value) => update_refresh_value(get_refresh_context(__, "set", arg), value);
promise.refresh = () => {
const refresh_context = get_refresh_context(__, "refresh", arg);
const is_immediate_refresh = !refresh_context.cache[refresh_context.cache_key];
const value = is_immediate_refresh ? promise : get_remote_function_result();
return update_refresh_value(refresh_context, value, is_immediate_refresh);
};
promise.withOverride = () => {
throw new Error(`Cannot call '${__.name}.withOverride()' on the server`);
};
return (
/** @type {RemoteQuery<Output>} */
promise
);
};
Object.defineProperty(wrapper, "__", { value: __ });
return wrapper;
}
// @__NO_SIDE_EFFECTS__
function batch(validate_or_fn, maybe_fn) {
const fn = maybe_fn ?? validate_or_fn;
const validate = create_validator(validate_or_fn, maybe_fn);
const __ = {
type: "query_batch",
id: "",
name: "",
run: async (args, options) => {
const { event, state } = get_request_store();
return run_remote_function(
event,
state,
false,
async () => Promise.all(args.map(validate)),
async (input) => {
const get_result = await fn(input);
return Promise.all(
input.map(async (arg, i) => {
try {
return { type: "result", data: get_result(arg, i) };
} catch (error2) {
return {
type: "error",
error: await handle_error_and_jsonify(event, state, options, error2),
status: error2 instanceof HttpError || error2 instanceof SvelteKitError ? error2.status : 500
};
}
})
);
}
);
}
};
let batching = { args: [], resolvers: [] };
const wrapper = (arg) => {
if (prerendering) {
throw new Error(
`Cannot call query.batch '${__.name}' while prerendering, as prerendered pages need static data. Use 'prerender' from $app/server instead`
);
}
const { event, state } = get_request_store();
const get_remote_function_result = () => {
return new Promise((resolve, reject) => {
batching.args.push(arg);
batching.resolvers.push({ resolve, reject });
if (batching.args.length > 1) return;
setTimeout(async () => {
const batched = batching;
batching = { args: [], resolvers: [] };
try {
return await run_remote_function(
event,
state,
false,
async () => Promise.all(batched.args.map(validate)),
async (input) => {
const get_result = await fn(input);
for (let i = 0; i < batched.resolvers.length; i++) {
try {
batched.resolvers[i].resolve(get_result(input[i], i));
} catch (error2) {
batched.resolvers[i].reject(error2);
}
}
}
);
} catch (error2) {
for (const resolver of batched.resolvers) {
resolver.reject(error2);
}
}
}, 0);
});
};
const promise = get_response(__, arg, state, get_remote_function_result);
promise.catch(() => {
});
promise.set = (value) => update_refresh_value(get_refresh_context(__, "set", arg), value);
promise.refresh = () => {
const refresh_context = get_refresh_context(__, "refresh", arg);
const is_immediate_refresh = !refresh_context.cache[refresh_context.cache_key];
const value = is_immediate_refresh ? promise : get_remote_function_result();
return update_refresh_value(refresh_context, value, is_immediate_refresh);
};
promise.withOverride = () => {
throw new Error(`Cannot call '${__.name}.withOverride()' on the server`);
};
return (
/** @type {RemoteQuery<Output>} */
promise
);
};
Object.defineProperty(wrapper, "__", { value: __ });
return wrapper;
}
Object.defineProperty(query, "batch", { value: batch, enumerable: true });
function get_refresh_context(__, action, arg) {
const { state } = get_request_store();
const { refreshes } = state;
if (!refreshes) {
const name = __.type === "query_batch" ? `query.batch '${__.name}'` : `query '${__.name}'`;
throw new Error(
`Cannot call ${action} on ${name} because it is not executed in the context of a command/form remote function`
);
}
const cache = get_cache(__, state);
const cache_key = stringify_remote_arg(arg, state.transport);
const refreshes_key = create_remote_key(__.id, cache_key);
return { __, state, refreshes, refreshes_key, cache, cache_key };
}
function update_refresh_value({ __, refreshes, refreshes_key, cache, cache_key }, value, is_immediate_refresh = false) {
const promise = Promise.resolve(value);
if (!is_immediate_refresh) {
cache[cache_key] = promise;
}
if (__.id) {
refreshes[refreshes_key] = promise;
}
return promise.then(() => {
});
}
export {
get_response as a,
create_validator as c,
get_cache as g,
parse_remote_response as p,
query as q,
run_remote_function as r
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,85 @@
import { b as decode_params } from "./url.js";
function affects_path(segment) {
return segment !== "" && !/^\([^)]+\)$/.test(segment);
}
function get_route_segments(route) {
return route.slice(1).split("/").filter(affects_path);
}
function exec(match, params, matchers) {
const result = {};
const values = match.slice(1);
const values_needing_match = values.filter((value) => value !== void 0);
let buffered = 0;
for (let i = 0; i < params.length; i += 1) {
const param = params[i];
let value = values[i - buffered];
if (param.chained && param.rest && buffered) {
value = values.slice(i - buffered, i + 1).filter((s) => s).join("/");
buffered = 0;
}
if (value === void 0) {
if (param.rest) {
value = "";
} else {
continue;
}
}
if (!param.matcher || matchers[param.matcher](value)) {
result[param.name] = value;
const next_param = params[i + 1];
const next_value = values[i + 1];
if (next_param && !next_param.rest && next_param.optional && next_value && param.chained) {
buffered = 0;
}
if (!next_param && !next_value && Object.keys(result).length === values_needing_match.length) {
buffered = 0;
}
continue;
}
if (param.optional && param.chained) {
buffered++;
continue;
}
return;
}
if (buffered) return;
return result;
}
const basic_param_pattern = /\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
function resolve_route(id, params) {
const segments = get_route_segments(id);
const has_id_trailing_slash = id.endsWith("/");
return "/" + segments.map(
(segment) => segment.replace(basic_param_pattern, (_, optional, rest, name) => {
const param_value = params[name];
if (!param_value) {
if (optional) return "";
if (rest && param_value !== void 0) return "";
throw new Error(`Missing parameter '${name}' in route ${id}`);
}
if (param_value.startsWith("/") || param_value.endsWith("/"))
throw new Error(
`Parameter '${name}' in route ${id} cannot start or end with a slash -- this would cause an invalid route like foo//bar`
);
return param_value;
})
).filter(Boolean).join("/") + (has_id_trailing_slash ? "/" : "");
}
function find_route(path, routes, matchers) {
for (const route of routes) {
const match = route.pattern.exec(path);
if (!match) continue;
const matched = exec(match, route.params, matchers);
if (matched) {
return {
route,
params: decode_params(matched)
};
}
}
return null;
}
export {
find_route as f,
resolve_route as r
};

View File

@@ -0,0 +1,27 @@
let base = "";
let assets = base;
const app_dir = "_app";
const relative = true;
const initial = { base, assets };
const initial_base = initial.base;
function override(paths) {
base = paths.base;
assets = paths.assets;
}
function reset() {
base = initial.base;
assets = initial.assets;
}
function set_assets(path) {
assets = initial.assets = path;
}
export {
assets as a,
base as b,
app_dir as c,
reset as d,
initial_base as i,
override as o,
relative as r,
set_assets as s
};

View File

@@ -0,0 +1,14 @@
let private_env = {};
let public_env = {};
function set_private_env(environment) {
private_env = environment;
}
function set_public_env(environment) {
public_env = environment;
}
export {
set_public_env as a,
private_env as b,
public_env as p,
set_private_env as s
};

View File

@@ -0,0 +1,789 @@
import { json, text } from "@sveltejs/kit";
import { SvelteKitError, HttpError } from "@sveltejs/kit/internal";
import { with_request_store } from "@sveltejs/kit/internal/server";
import * as devalue from "devalue";
import { t as text_decoder, b as base64_encode, c as base64_decode } from "./utils.js";
const SVELTE_KIT_ASSETS = "/_svelte_kit_assets";
const ENDPOINT_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"];
const MUTATIVE_METHODS = ["POST", "PUT", "PATCH", "DELETE"];
const PAGE_METHODS = ["GET", "POST", "HEAD"];
function set_nested_value(object, path_string, value) {
if (path_string.startsWith("n:")) {
path_string = path_string.slice(2);
value = value === "" ? void 0 : parseFloat(value);
} else if (path_string.startsWith("b:")) {
path_string = path_string.slice(2);
value = value === "on";
}
deep_set(object, split_path(path_string), value);
}
function convert_formdata(data) {
const result = {};
for (let key of data.keys()) {
const is_array = key.endsWith("[]");
let values = data.getAll(key);
if (is_array) key = key.slice(0, -2);
if (values.length > 1 && !is_array) {
throw new Error(`Form cannot contain duplicated keys — "${key}" has ${values.length} values`);
}
values = values.filter(
(entry) => typeof entry === "string" || entry.name !== "" || entry.size > 0
);
if (key.startsWith("n:")) {
key = key.slice(2);
values = values.map((v) => v === "" ? void 0 : parseFloat(
/** @type {string} */
v
));
} else if (key.startsWith("b:")) {
key = key.slice(2);
values = values.map((v) => v === "on");
}
set_nested_value(result, key, is_array ? values : values[0]);
}
return result;
}
const BINARY_FORM_CONTENT_TYPE = "application/x-sveltekit-formdata";
const BINARY_FORM_VERSION = 0;
const HEADER_BYTES = 1 + 4 + 2;
async function deserialize_binary_form(request) {
if (request.headers.get("content-type") !== BINARY_FORM_CONTENT_TYPE) {
const form_data = await request.formData();
return { data: convert_formdata(form_data), meta: {}, form_data };
}
if (!request.body) {
throw deserialize_error("no body");
}
const content_length = parseInt(request.headers.get("content-length") ?? "");
if (Number.isNaN(content_length)) {
throw deserialize_error("invalid Content-Length header");
}
const reader = request.body.getReader();
const chunks = [];
function get_chunk(index) {
if (index in chunks) return chunks[index];
let i = chunks.length;
while (i <= index) {
chunks[i] = reader.read().then((chunk) => chunk.value);
i++;
}
return chunks[index];
}
async function get_buffer(offset, length) {
let start_chunk;
let chunk_start = 0;
let chunk_index;
for (chunk_index = 0; ; chunk_index++) {
const chunk = await get_chunk(chunk_index);
if (!chunk) return null;
const chunk_end = chunk_start + chunk.byteLength;
if (offset >= chunk_start && offset < chunk_end) {
start_chunk = chunk;
break;
}
chunk_start = chunk_end;
}
if (offset + length <= chunk_start + start_chunk.byteLength) {
return start_chunk.subarray(offset - chunk_start, offset + length - chunk_start);
}
const chunks2 = [start_chunk.subarray(offset - chunk_start)];
let cursor = start_chunk.byteLength - offset + chunk_start;
while (cursor < length) {
chunk_index++;
let chunk = await get_chunk(chunk_index);
if (!chunk) return null;
if (chunk.byteLength > length - cursor) {
chunk = chunk.subarray(0, length - cursor);
}
chunks2.push(chunk);
cursor += chunk.byteLength;
}
const buffer = new Uint8Array(length);
cursor = 0;
for (const chunk of chunks2) {
buffer.set(chunk, cursor);
cursor += chunk.byteLength;
}
return buffer;
}
const header = await get_buffer(0, HEADER_BYTES);
if (!header) throw deserialize_error("too short");
if (header[0] !== BINARY_FORM_VERSION) {
throw deserialize_error(`got version ${header[0]}, expected version ${BINARY_FORM_VERSION}`);
}
const header_view = new DataView(header.buffer, header.byteOffset, header.byteLength);
const data_length = header_view.getUint32(1, true);
if (HEADER_BYTES + data_length > content_length) {
throw deserialize_error("data overflow");
}
const file_offsets_length = header_view.getUint16(5, true);
if (HEADER_BYTES + data_length + file_offsets_length > content_length) {
throw deserialize_error("file offset table overflow");
}
const data_buffer = await get_buffer(HEADER_BYTES, data_length);
if (!data_buffer) throw deserialize_error("data too short");
let file_offsets;
let files_start_offset;
if (file_offsets_length > 0) {
const file_offsets_buffer = await get_buffer(HEADER_BYTES + data_length, file_offsets_length);
if (!file_offsets_buffer) throw deserialize_error("file offset table too short");
const parsed_offsets = JSON.parse(text_decoder.decode(file_offsets_buffer));
if (!Array.isArray(parsed_offsets) || parsed_offsets.some((n) => typeof n !== "number" || !Number.isInteger(n) || n < 0)) {
throw deserialize_error("invalid file offset table");
}
file_offsets = /** @type {Array<number>} */
parsed_offsets;
files_start_offset = HEADER_BYTES + data_length + file_offsets_length;
}
const file_spans = [];
const [data, meta] = devalue.parse(text_decoder.decode(data_buffer), {
File: ([name, type, size, last_modified, index]) => {
if (typeof name !== "string" || typeof type !== "string" || typeof size !== "number" || typeof last_modified !== "number" || typeof index !== "number") {
throw deserialize_error("invalid file metadata");
}
let offset = file_offsets[index];
if (offset === void 0) {
throw deserialize_error("duplicate file offset table index");
}
file_offsets[index] = void 0;
offset += files_start_offset;
if (offset + size > content_length) {
throw deserialize_error("file data overflow");
}
file_spans.push({ offset, size });
return new Proxy(new LazyFile(name, type, size, last_modified, get_chunk, offset), {
getPrototypeOf() {
return File.prototype;
}
});
}
});
file_spans.sort((a, b) => a.offset - b.offset || a.size - b.size);
for (let i = 1; i < file_spans.length; i++) {
const previous = file_spans[i - 1];
const current = file_spans[i];
const previous_end = previous.offset + previous.size;
if (previous_end < current.offset) {
throw deserialize_error("gaps in file data");
}
if (previous_end > current.offset) {
throw deserialize_error("overlapping file data");
}
}
void (async () => {
let has_more = true;
while (has_more) {
const chunk = await get_chunk(chunks.length);
has_more = !!chunk;
}
})();
return { data, meta, form_data: null };
}
function deserialize_error(message) {
return new SvelteKitError(400, "Bad Request", `Could not deserialize binary form: ${message}`);
}
class LazyFile {
/** @type {(index: number) => Promise<Uint8Array<ArrayBuffer> | undefined>} */
#get_chunk;
/** @type {number} */
#offset;
/**
* @param {string} name
* @param {string} type
* @param {number} size
* @param {number} last_modified
* @param {(index: number) => Promise<Uint8Array<ArrayBuffer> | undefined>} get_chunk
* @param {number} offset
*/
constructor(name, type, size, last_modified, get_chunk, offset) {
this.name = name;
this.type = type;
this.size = size;
this.lastModified = last_modified;
this.webkitRelativePath = "";
this.#get_chunk = get_chunk;
this.#offset = offset;
this.arrayBuffer = this.arrayBuffer.bind(this);
this.bytes = this.bytes.bind(this);
this.slice = this.slice.bind(this);
this.stream = this.stream.bind(this);
this.text = this.text.bind(this);
}
/** @type {ArrayBuffer | undefined} */
#buffer;
async arrayBuffer() {
this.#buffer ??= await new Response(this.stream()).arrayBuffer();
return this.#buffer;
}
async bytes() {
return new Uint8Array(await this.arrayBuffer());
}
/**
* @param {number=} start
* @param {number=} end
* @param {string=} contentType
*/
slice(start = 0, end = this.size, contentType = this.type) {
if (start < 0) {
start = Math.max(this.size + start, 0);
} else {
start = Math.min(start, this.size);
}
if (end < 0) {
end = Math.max(this.size + end, 0);
} else {
end = Math.min(end, this.size);
}
const size = Math.max(end - start, 0);
const file = new LazyFile(
this.name,
contentType,
size,
this.lastModified,
this.#get_chunk,
this.#offset + start
);
return file;
}
stream() {
let cursor = 0;
let chunk_index = 0;
return new ReadableStream({
start: async (controller) => {
let chunk_start = 0;
let start_chunk;
for (chunk_index = 0; ; chunk_index++) {
const chunk = await this.#get_chunk(chunk_index);
if (!chunk) return null;
const chunk_end = chunk_start + chunk.byteLength;
if (this.#offset >= chunk_start && this.#offset < chunk_end) {
start_chunk = chunk;
break;
}
chunk_start = chunk_end;
}
if (this.#offset + this.size <= chunk_start + start_chunk.byteLength) {
controller.enqueue(
start_chunk.subarray(this.#offset - chunk_start, this.#offset + this.size - chunk_start)
);
controller.close();
} else {
controller.enqueue(start_chunk.subarray(this.#offset - chunk_start));
cursor = start_chunk.byteLength - this.#offset + chunk_start;
}
},
pull: async (controller) => {
chunk_index++;
let chunk = await this.#get_chunk(chunk_index);
if (!chunk) {
controller.error("incomplete file data");
controller.close();
return;
}
if (chunk.byteLength > this.size - cursor) {
chunk = chunk.subarray(0, this.size - cursor);
}
controller.enqueue(chunk);
cursor += chunk.byteLength;
if (cursor >= this.size) {
controller.close();
}
}
});
}
async text() {
return text_decoder.decode(await this.arrayBuffer());
}
}
const path_regex = /^[a-zA-Z_$]\w*(\.[a-zA-Z_$]\w*|\[\d+\])*$/;
function split_path(path) {
if (!path_regex.test(path)) {
throw new Error(`Invalid path ${path}`);
}
return path.split(/\.|\[|\]/).filter(Boolean);
}
function check_prototype_pollution(key) {
if (key === "__proto__" || key === "constructor" || key === "prototype") {
throw new Error(
`Invalid key "${key}"`
);
}
}
function deep_set(object, keys, value) {
let current = object;
for (let i = 0; i < keys.length - 1; i += 1) {
const key = keys[i];
check_prototype_pollution(key);
const is_array = /^\d+$/.test(keys[i + 1]);
const exists = Object.hasOwn(current, key);
const inner = current[key];
if (exists && is_array !== Array.isArray(inner)) {
throw new Error(`Invalid array key ${keys[i + 1]}`);
}
if (!exists) {
current[key] = is_array ? [] : {};
}
current = current[key];
}
const final_key = keys[keys.length - 1];
check_prototype_pollution(final_key);
current[final_key] = value;
}
function normalize_issue(issue, server = false) {
const normalized = { name: "", path: [], message: issue.message, server };
if (issue.path !== void 0) {
let name = "";
for (const segment of issue.path) {
const key = (
/** @type {string | number} */
typeof segment === "object" ? segment.key : segment
);
normalized.path.push(key);
if (typeof key === "number") {
name += `[${key}]`;
} else if (typeof key === "string") {
name += name === "" ? key : "." + key;
}
}
normalized.name = name;
}
return normalized;
}
function flatten_issues(issues) {
const result = {};
for (const issue of issues) {
(result.$ ??= []).push(issue);
let name = "";
if (issue.path !== void 0) {
for (const key of issue.path) {
if (typeof key === "number") {
name += `[${key}]`;
} else if (typeof key === "string") {
name += name === "" ? key : "." + key;
}
(result[name] ??= []).push(issue);
}
}
}
return result;
}
function deep_get(object, path) {
let current = object;
for (const key of path) {
if (current == null || typeof current !== "object") {
return current;
}
current = current[key];
}
return current;
}
function create_field_proxy(target, get_input, set_input, get_issues, path = []) {
const get_value = () => {
return deep_get(get_input(), path);
};
return new Proxy(target, {
get(target2, prop) {
if (typeof prop === "symbol") return target2[prop];
if (/^\d+$/.test(prop)) {
return create_field_proxy({}, get_input, set_input, get_issues, [
...path,
parseInt(prop, 10)
]);
}
const key = build_path_string(path);
if (prop === "set") {
const set_func = function(newValue) {
set_input(path, newValue);
return newValue;
};
return create_field_proxy(set_func, get_input, set_input, get_issues, [...path, prop]);
}
if (prop === "value") {
return create_field_proxy(get_value, get_input, set_input, get_issues, [...path, prop]);
}
if (prop === "issues" || prop === "allIssues") {
const issues_func = () => {
const all_issues = get_issues()[key === "" ? "$" : key];
if (prop === "allIssues") {
return all_issues?.map((issue) => ({
path: issue.path,
message: issue.message
}));
}
return all_issues?.filter((issue) => issue.name === key)?.map((issue) => ({
path: issue.path,
message: issue.message
}));
};
return create_field_proxy(issues_func, get_input, set_input, get_issues, [...path, prop]);
}
if (prop === "as") {
const as_func = (type, input_value) => {
const is_array = type === "file multiple" || type === "select multiple" || type === "checkbox" && typeof input_value === "string";
const prefix = type === "number" || type === "range" ? "n:" : type === "checkbox" && !is_array ? "b:" : "";
const base_props = {
name: prefix + key + (is_array ? "[]" : ""),
get "aria-invalid"() {
const issues = get_issues();
return key in issues ? "true" : void 0;
}
};
if (type !== "text" && type !== "select" && type !== "select multiple") {
base_props.type = type === "file multiple" ? "file" : type;
}
if (type === "submit" || type === "hidden") {
return Object.defineProperties(base_props, {
value: { value: input_value, enumerable: true }
});
}
if (type === "select" || type === "select multiple") {
return Object.defineProperties(base_props, {
multiple: { value: is_array, enumerable: true },
value: {
enumerable: true,
get() {
return get_value();
}
}
});
}
if (type === "checkbox" || type === "radio") {
return Object.defineProperties(base_props, {
value: { value: input_value ?? "on", enumerable: true },
checked: {
enumerable: true,
get() {
const value = get_value();
if (type === "radio") {
return value === input_value;
}
if (is_array) {
return (value ?? []).includes(input_value);
}
return value;
}
}
});
}
if (type === "file" || type === "file multiple") {
return Object.defineProperties(base_props, {
multiple: { value: is_array, enumerable: true },
files: {
enumerable: true,
get() {
const value = get_value();
if (value instanceof File) {
if (typeof DataTransfer !== "undefined") {
const fileList = new DataTransfer();
fileList.items.add(value);
return fileList.files;
}
return { 0: value, length: 1 };
}
if (Array.isArray(value) && value.every((f) => f instanceof File)) {
if (typeof DataTransfer !== "undefined") {
const fileList = new DataTransfer();
value.forEach((file) => fileList.items.add(file));
return fileList.files;
}
const fileListLike = { length: value.length };
value.forEach((file, index) => {
fileListLike[index] = file;
});
return fileListLike;
}
return null;
}
}
});
}
return Object.defineProperties(base_props, {
value: {
enumerable: true,
get() {
const value = get_value();
return value != null ? String(value) : "";
}
}
});
};
return create_field_proxy(as_func, get_input, set_input, get_issues, [...path, "as"]);
}
return create_field_proxy({}, get_input, set_input, get_issues, [...path, prop]);
}
});
}
function build_path_string(path) {
let result = "";
for (const segment of path) {
if (typeof segment === "number") {
result += `[${segment}]`;
} else {
result += result === "" ? segment : "." + segment;
}
}
return result;
}
function negotiate(accept, types) {
const parts = [];
accept.split(",").forEach((str, i) => {
const match = /([^/ \t]+)\/([^; \t]+)[ \t]*(?:;[ \t]*q=([0-9.]+))?/.exec(str);
if (match) {
const [, type, subtype, q = "1"] = match;
parts.push({ type, subtype, q: +q, i });
}
});
parts.sort((a, b) => {
if (a.q !== b.q) {
return b.q - a.q;
}
if (a.subtype === "*" !== (b.subtype === "*")) {
return a.subtype === "*" ? 1 : -1;
}
if (a.type === "*" !== (b.type === "*")) {
return a.type === "*" ? 1 : -1;
}
return a.i - b.i;
});
let accepted;
let min_priority = Infinity;
for (const mimetype of types) {
const [type, subtype] = mimetype.split("/");
const priority = parts.findIndex(
(part) => (part.type === type || part.type === "*") && (part.subtype === subtype || part.subtype === "*")
);
if (priority !== -1 && priority < min_priority) {
accepted = mimetype;
min_priority = priority;
}
}
return accepted;
}
function is_content_type(request, ...types) {
const type = request.headers.get("content-type")?.split(";", 1)[0].trim() ?? "";
return types.includes(type.toLowerCase());
}
function is_form_content_type(request) {
return is_content_type(
request,
"application/x-www-form-urlencoded",
"multipart/form-data",
"text/plain",
BINARY_FORM_CONTENT_TYPE
);
}
function coalesce_to_error(err) {
return err instanceof Error || err && /** @type {any} */
err.name && /** @type {any} */
err.message ? (
/** @type {Error} */
err
) : new Error(JSON.stringify(err));
}
function normalize_error(error) {
return (
/** @type {import('../exports/internal/index.js').Redirect | HttpError | SvelteKitError | Error} */
error
);
}
function get_status(error) {
return error instanceof HttpError || error instanceof SvelteKitError ? error.status : 500;
}
function get_message(error) {
return error instanceof SvelteKitError ? error.text : "Internal Error";
}
const escape_html_attr_dict = {
"&": "&amp;",
'"': "&quot;"
// Svelte also escapes < because the escape function could be called inside a `noscript` there
// https://github.com/sveltejs/svelte/security/advisories/GHSA-8266-84wp-wv5c
// However, that doesn't apply in SvelteKit
};
const escape_html_dict = {
"&": "&amp;",
"<": "&lt;"
};
const surrogates = (
// high surrogate without paired low surrogate
"[\\ud800-\\udbff](?![\\udc00-\\udfff])|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\udc00-\\udfff]"
);
const escape_html_attr_regex = new RegExp(
`[${Object.keys(escape_html_attr_dict).join("")}]|` + surrogates,
"g"
);
const escape_html_regex = new RegExp(
`[${Object.keys(escape_html_dict).join("")}]|` + surrogates,
"g"
);
function escape_html(str, is_attr) {
const dict = is_attr ? escape_html_attr_dict : escape_html_dict;
const escaped_str = str.replace(is_attr ? escape_html_attr_regex : escape_html_regex, (match) => {
if (match.length === 2) {
return match;
}
return dict[match] ?? `&#${match.charCodeAt(0)};`;
});
return escaped_str;
}
function method_not_allowed(mod, method) {
return text(`${method} method not allowed`, {
status: 405,
headers: {
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405
// "The server must generate an Allow header field in a 405 status code response"
allow: allowed_methods(mod).join(", ")
}
});
}
function allowed_methods(mod) {
const allowed = ENDPOINT_METHODS.filter((method) => method in mod);
if ("GET" in mod && !("HEAD" in mod)) {
allowed.push("HEAD");
}
return allowed;
}
function get_global_name(options) {
return `__sveltekit_${options.version_hash}`;
}
function static_error_page(options, status, message) {
let page = options.templates.error({ status, message: escape_html(message) });
return text(page, {
headers: { "content-type": "text/html; charset=utf-8" },
status
});
}
async function handle_fatal_error(event, state, options, error) {
error = error instanceof HttpError ? error : coalesce_to_error(error);
const status = get_status(error);
const body = await handle_error_and_jsonify(event, state, options, error);
const type = negotiate(event.request.headers.get("accept") || "text/html", [
"application/json",
"text/html"
]);
if (event.isDataRequest || type === "application/json") {
return json(body, {
status
});
}
return static_error_page(options, status, body.message);
}
async function handle_error_and_jsonify(event, state, options, error) {
if (error instanceof HttpError) {
return { message: "Unknown Error", ...error.body };
}
const status = get_status(error);
const message = get_message(error);
return await with_request_store(
{ event, state },
() => options.hooks.handleError({ error, event, status, message })
) ?? { message };
}
function redirect_response(status, location) {
const response = new Response(void 0, {
status,
headers: { location }
});
return response;
}
function clarify_devalue_error(event, error) {
if (error.path) {
return `Data returned from \`load\` while rendering ${event.route.id} is not serializable: ${error.message} (${error.path}). If you need to serialize/deserialize custom types, use transport hooks: https://svelte.dev/docs/kit/hooks#Universal-hooks-transport.`;
}
if (error.path === "") {
return `Data returned from \`load\` while rendering ${event.route.id} is not a plain object`;
}
return error.message;
}
function serialize_uses(node) {
const uses = {};
if (node.uses && node.uses.dependencies.size > 0) {
uses.dependencies = Array.from(node.uses.dependencies);
}
if (node.uses && node.uses.search_params.size > 0) {
uses.search_params = Array.from(node.uses.search_params);
}
if (node.uses && node.uses.params.size > 0) {
uses.params = Array.from(node.uses.params);
}
if (node.uses?.parent) uses.parent = 1;
if (node.uses?.route) uses.route = 1;
if (node.uses?.url) uses.url = 1;
return uses;
}
function has_prerendered_path(manifest, pathname) {
return manifest._.prerendered_routes.has(pathname) || pathname.at(-1) === "/" && manifest._.prerendered_routes.has(pathname.slice(0, -1));
}
function format_server_error(status, error, event) {
const formatted_text = `
\x1B[1;31m[${status}] ${event.request.method} ${event.url.pathname}\x1B[0m`;
if (status === 404) {
return formatted_text;
}
return `${formatted_text}
${error.stack}`;
}
function get_node_type(node_id) {
const parts = node_id?.split("/");
const filename = parts?.at(-1);
if (!filename) return "unknown";
const dot_parts = filename.split(".");
return dot_parts.slice(0, -1).join(".");
}
const INVALIDATED_PARAM = "x-sveltekit-invalidated";
const TRAILING_SLASH_PARAM = "x-sveltekit-trailing-slash";
function stringify(data, transport) {
const encoders = Object.fromEntries(Object.entries(transport).map(([k, v]) => [k, v.encode]));
return devalue.stringify(data, encoders);
}
function stringify_remote_arg(value, transport) {
if (value === void 0) return "";
const json_string = stringify(value, transport);
const bytes = new TextEncoder().encode(json_string);
return base64_encode(bytes).replaceAll("=", "").replaceAll("+", "-").replaceAll("/", "_");
}
function parse_remote_arg(string, transport) {
if (!string) return void 0;
const json_string = text_decoder.decode(
// no need to add back `=` characters, atob can handle it
base64_decode(string.replaceAll("-", "+").replaceAll("_", "/"))
);
const decoders = Object.fromEntries(Object.entries(transport).map(([k, v]) => [k, v.decode]));
return devalue.parse(json_string, decoders);
}
function create_remote_key(id, payload) {
return id + "/" + payload;
}
export {
ENDPOINT_METHODS as E,
INVALIDATED_PARAM as I,
MUTATIVE_METHODS as M,
PAGE_METHODS as P,
SVELTE_KIT_ASSETS as S,
TRAILING_SLASH_PARAM as T,
normalize_error as a,
get_global_name as b,
clarify_devalue_error as c,
get_node_type as d,
escape_html as e,
create_remote_key as f,
get_status as g,
handle_error_and_jsonify as h,
is_form_content_type as i,
static_error_page as j,
stringify as k,
deserialize_binary_form as l,
method_not_allowed as m,
negotiate as n,
has_prerendered_path as o,
parse_remote_arg as p,
handle_fatal_error as q,
redirect_response as r,
serialize_uses as s,
format_server_error as t,
create_field_proxy as u,
normalize_issue as v,
set_nested_value as w,
flatten_issues as x,
deep_set as y,
stringify_remote_arg as z
};

View File

@@ -0,0 +1,18 @@
import "clsx";
import { n as noop } from "./index3.js";
import "./url.js";
import "@sveltejs/kit/internal/server";
import "./root.js";
const is_legacy = noop.toString().includes("$$") || /function \w+\(\) \{\}/.test(noop.toString());
if (is_legacy) {
({
data: {},
form: null,
error: null,
params: {},
route: { id: null },
state: {},
status: -1,
url: new URL("https://example.com")
});
}

View File

@@ -0,0 +1,106 @@
const SCHEME = /^[a-z][a-z\d+\-.]+:/i;
const internal = new URL("sveltekit-internal://");
function resolve(base, path) {
if (path[0] === "/" && path[1] === "/") return path;
let url = new URL(base, internal);
url = new URL(path, url);
return url.protocol === internal.protocol ? url.pathname + url.search + url.hash : url.href;
}
function normalize_path(path, trailing_slash) {
if (path === "/" || trailing_slash === "ignore") return path;
if (trailing_slash === "never") {
return path.endsWith("/") ? path.slice(0, -1) : path;
} else if (trailing_slash === "always" && !path.endsWith("/")) {
return path + "/";
}
return path;
}
function decode_pathname(pathname) {
return pathname.split("%25").map(decodeURI).join("%25");
}
function decode_params(params) {
for (const key in params) {
params[key] = decodeURIComponent(params[key]);
}
return params;
}
function make_trackable(url, callback, search_params_callback, allow_hash = false) {
const tracked = new URL(url);
Object.defineProperty(tracked, "searchParams", {
value: new Proxy(tracked.searchParams, {
get(obj, key) {
if (key === "get" || key === "getAll" || key === "has") {
return (param, ...rest) => {
search_params_callback(param);
return obj[key](param, ...rest);
};
}
callback();
const value = Reflect.get(obj, key);
return typeof value === "function" ? value.bind(obj) : value;
}
}),
enumerable: true,
configurable: true
});
const tracked_url_properties = ["href", "pathname", "search", "toString", "toJSON"];
if (allow_hash) tracked_url_properties.push("hash");
for (const property of tracked_url_properties) {
Object.defineProperty(tracked, property, {
get() {
callback();
return url[property];
},
enumerable: true,
configurable: true
});
}
{
tracked[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")] = (depth, opts, inspect) => {
return inspect(url, opts);
};
tracked.searchParams[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")] = (depth, opts, inspect) => {
return inspect(url.searchParams, opts);
};
}
if (!allow_hash) {
disable_hash(tracked);
}
return tracked;
}
function disable_hash(url) {
allow_nodejs_console_log(url);
Object.defineProperty(url, "hash", {
get() {
throw new Error(
"Cannot access event.url.hash. Consider using `page.url.hash` inside a component instead"
);
}
});
}
function disable_search(url) {
allow_nodejs_console_log(url);
for (const property of ["search", "searchParams"]) {
Object.defineProperty(url, property, {
get() {
throw new Error(`Cannot access url.${property} on a page with prerendering enabled`);
}
});
}
}
function allow_nodejs_console_log(url) {
{
url[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")] = (depth, opts, inspect) => {
return inspect(new URL(url), opts);
};
}
}
export {
SCHEME as S,
decode_pathname as a,
decode_params as b,
disable_search as d,
make_trackable as m,
normalize_path as n,
resolve as r
};

View File

@@ -0,0 +1,43 @@
const text_encoder = new TextEncoder();
const text_decoder = new TextDecoder();
function get_relative_path(from, to) {
const from_parts = from.split(/[/\\]/);
const to_parts = to.split(/[/\\]/);
from_parts.pop();
while (from_parts[0] === to_parts[0]) {
from_parts.shift();
to_parts.shift();
}
let i = from_parts.length;
while (i--) from_parts[i] = "..";
return from_parts.concat(to_parts).join("/");
}
function base64_encode(bytes) {
if (globalThis.Buffer) {
return globalThis.Buffer.from(bytes).toString("base64");
}
let binary = "";
for (let i = 0; i < bytes.length; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
function base64_decode(encoded) {
if (globalThis.Buffer) {
const buffer = globalThis.Buffer.from(encoded, "base64");
return new Uint8Array(buffer);
}
const binary = atob(encoded);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
export {
text_encoder as a,
base64_encode as b,
base64_decode as c,
get_relative_path as g,
text_decoder as t
};

View File

@@ -0,0 +1,25 @@
import { json } from "@sveltejs/kit";
import { d as db } from "../../../../chunks/index2.js";
import { sql } from "drizzle-orm";
const GET = async () => {
try {
await db.execute(sql`SELECT 1`);
return json({
status: "ok",
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
uptime: process.uptime()
});
} catch (e) {
return json(
{
status: "error",
error: "Database connection failed",
timestamp: (/* @__PURE__ */ new Date()).toISOString()
},
{ status: 503 }
);
}
};
export {
GET
};

View File

@@ -0,0 +1,24 @@
import { error, json } from "@sveltejs/kit";
import { d as db, m as mappool, a as mappoolSlot } from "../../../../../chunks/index2.js";
import { eq } from "drizzle-orm";
const GET = async ({ params, locals }) => {
if (!locals.user) error(401, "Not logged in");
const pool = await db.query.mappool.findFirst({
where: eq(mappool.id, params.id)
});
if (!pool) error(404, "Mappool not found");
const slots = await db.query.mappoolSlot.findMany({
where: eq(mappoolSlot.mappoolId, params.id),
orderBy: (s, { asc }) => [asc(s.category), asc(s.orderInCategory)]
});
return json({ ...pool, slots });
};
const DELETE = async ({ params, locals }) => {
if (!locals.user) error(401, "Not logged in");
await db.delete(mappool).where(eq(mappool.id, params.id));
return json({ ok: true });
};
export {
DELETE,
GET
};

View File

@@ -0,0 +1,27 @@
import { error, json } from "@sveltejs/kit";
import { d as db, a as mappoolSlot } from "../../../../../../chunks/index2.js";
import { and, eq } from "drizzle-orm";
const POST = async ({ params, request, locals }) => {
if (!locals.user) error(401, "Not logged in");
const { beatmapId, category, mods } = await request.json();
if (!beatmapId || !category) {
error(400, "beatmapId and category are required");
}
const existing = await db.query.mappoolSlot.findMany({
where: and(
eq(mappoolSlot.mappoolId, params.id),
eq(mappoolSlot.category, category.toUpperCase())
)
});
const [created] = await db.insert(mappoolSlot).values({
mappoolId: params.id,
beatmapId: String(beatmapId),
category: category.toUpperCase(),
orderInCategory: existing.length + 1,
mods: mods ?? []
}).returning();
return json(created, { status: 201 });
};
export {
POST
};

View File

@@ -0,0 +1,11 @@
import { error, json } from "@sveltejs/kit";
import { d as db, a as mappoolSlot } from "../../../../../../../chunks/index2.js";
import { eq } from "drizzle-orm";
const DELETE = async ({ params, locals }) => {
if (!locals.user) error(401, "Not logged in");
await db.delete(mappoolSlot).where(eq(mappoolSlot.id, params.slotId));
return json({ ok: true });
};
export {
DELETE
};

View File

@@ -0,0 +1,23 @@
import { error, json } from "@sveltejs/kit";
import { d as db, m as mappool } from "../../../../chunks/index2.js";
const GET = async ({ locals }) => {
if (!locals.user) error(401, "Not logged in");
const mappools = await db.query.mappool.findMany({
orderBy: (m, { desc }) => [desc(m.createdAt)]
});
return json(mappools);
};
const POST = async ({ request, locals }) => {
if (!locals.user) error(401, "Not logged in");
const { name } = await request.json();
if (!name?.trim()) error(400, "Name is required");
const [created] = await db.insert(mappool).values({
name: name.trim(),
createdBy: locals.user.id
}).returning();
return json(created, { status: 201 });
};
export {
GET,
POST
};

View File

@@ -0,0 +1,24 @@
import { error, json } from "@sveltejs/kit";
import { a as cancelMatch, g as getMatchFull } from "../../../../../chunks/engine.js";
const GET = async ({ params, locals }) => {
if (!locals.user) error(401, "Not logged in");
try {
const m = await getMatchFull(params.id);
return json(m);
} catch (e) {
error(404, e.message);
}
};
const DELETE = async ({ params, locals }) => {
if (!locals.user) error(401, "Not logged in");
try {
const m = await cancelMatch(params.id);
return json(m);
} catch (e) {
error(400, e.message);
}
};
export {
DELETE,
GET
};

View File

@@ -0,0 +1,15 @@
import { error, json } from "@sveltejs/kit";
import { m as moveToLobby } from "../../../../../../chunks/engine.js";
const POST = async ({ params, request, locals }) => {
if (!locals.user) error(401, "Not logged in");
const body = await request.json().catch(() => ({}));
try {
const m = await moveToLobby(params.id, body.osuLobbyId);
return json(m);
} catch (e) {
error(400, e.message);
}
};
export {
POST
};

View File

@@ -0,0 +1,18 @@
import { error, json } from "@sveltejs/kit";
import { p as pickMap } from "../../../../../../chunks/engine.js";
const POST = async ({ params, request, locals }) => {
if (!locals.user) error(401, "Not logged in");
const { participantId, mappoolSlotId } = await request.json();
if (!participantId || !mappoolSlotId) {
error(400, "participantId and mappoolSlotId required");
}
try {
const game = await pickMap(params.id, participantId, mappoolSlotId);
return json(game);
} catch (e) {
error(400, e.message);
}
};
export {
POST
};

View File

@@ -0,0 +1,18 @@
import { error, json } from "@sveltejs/kit";
import { s as submitRoll } from "../../../../../../chunks/engine.js";
const POST = async ({ params, request, locals }) => {
if (!locals.user) error(401, "Not logged in");
const { participantId, value } = await request.json();
if (!participantId || value == null) {
error(400, "participantId and value required");
}
try {
const m = await submitRoll(params.id, participantId, value);
return json(m);
} catch (e) {
error(400, e.message);
}
};
export {
POST
};

View File

@@ -0,0 +1,14 @@
import { error, json } from "@sveltejs/kit";
import { b as moveToRolling } from "../../../../../../chunks/engine.js";
const POST = async ({ params, locals }) => {
if (!locals.user) error(401, "Not logged in");
try {
const m = await moveToRolling(params.id);
return json(m);
} catch (e) {
error(400, e.message);
}
};
export {
POST
};

View File

@@ -0,0 +1,18 @@
import { error, json } from "@sveltejs/kit";
import { d as submitGameScores } from "../../../../../../chunks/engine.js";
const POST = async ({ request, locals }) => {
if (!locals.user) error(401, "Not logged in");
const { matchGameId, scores } = await request.json();
if (!matchGameId || !scores?.length) {
error(400, "matchGameId and scores required");
}
try {
const m = await submitGameScores(matchGameId, scores);
return json(m);
} catch (e) {
error(400, e.message);
}
};
export {
POST
};

View File

@@ -0,0 +1,37 @@
import { error, json } from "@sveltejs/kit";
import { d as db } from "../../../../chunks/index2.js";
import { c as createMatch } from "../../../../chunks/engine.js";
const GET = async ({ locals }) => {
if (!locals.user) error(401, "Not logged in");
const matches = await db.query.match.findMany({
with: {
participants: { with: { team: true } }
},
orderBy: (m, { desc }) => [desc(m.createdAt)]
});
return json(matches);
};
const POST = async ({ request, locals }) => {
if (!locals.user) error(401, "Not logged in");
const body = await request.json();
const { name, config, mappoolId, teams } = body;
if (!name || !config || !mappoolId || !teams?.length) {
error(400, "Missing required fields");
}
try {
const result = await createMatch({
name,
config,
mappoolId,
teams,
createdBy: locals.user.id
});
return json(result, { status: 201 });
} catch (e) {
error(400, e.message);
}
};
export {
GET,
POST
};

View File

@@ -0,0 +1,14 @@
import { error, json } from "@sveltejs/kit";
import { g as getBeatmap } from "../../../../../../chunks/api.js";
const GET = async ({ params, locals }) => {
if (!locals.user) error(401, "Not logged in");
try {
const beatmap = await getBeatmap(params.id);
return json(beatmap);
} catch {
error(404, "Beatmap not found");
}
};
export {
GET
};

View File

@@ -0,0 +1,36 @@
import { error, json } from "@sveltejs/kit";
import { l as leaveQueue, e as getQueueStatus, j as joinQueue } from "../../../../chunks/engine.js";
import { d as db, t as teamMember } from "../../../../chunks/index2.js";
import { eq } from "drizzle-orm";
const GET = async ({ locals }) => {
if (!locals.user) error(401, "Not logged in");
const status = await getQueueStatus(locals.user.id);
return json(status);
};
const POST = async ({ locals }) => {
if (!locals.user) error(401, "Not logged in");
const membership = await db.query.teamMember.findFirst({
where: eq(teamMember.userId, locals.user.id),
with: { team: true }
});
const personalTeam = membership?.team;
if (!personalTeam?.isPersonal) {
error(400, "No personal team found");
}
try {
const result = await joinQueue(locals.user.id, personalTeam.id);
return json({ matched: !!result, match: result });
} catch (e) {
error(400, e.message);
}
};
const DELETE = async ({ locals }) => {
if (!locals.user) error(401, "Not logged in");
await leaveQueue(locals.user.id);
return json({ ok: true });
};
export {
DELETE,
GET,
POST
};

View File

@@ -0,0 +1,9 @@
import "clsx";
function Layout($$renderer, $$props) {
let { children } = $$props;
children($$renderer);
$$renderer.push(`<!---->`);
}
export {
Layout as default
};

View File

@@ -0,0 +1,22 @@
import { b as building } from "../chunks/environment.js";
import { a as auth, s as svelteKitHandler } from "../chunks/auth.js";
import { d as db, u as user } from "../chunks/index2.js";
import { eq } from "drizzle-orm";
const handleBetterAuth = async ({ event, resolve }) => {
const session = await auth.api.getSession({ headers: event.request.headers });
if (session) {
event.locals.session = session.session;
const dbUser = await db.query.user.findFirst({
where: eq(user.id, session.user.id)
});
event.locals.user = {
...session.user,
role: dbUser?.role ?? "player"
};
}
return svelteKitHandler({ event, resolve, auth, building });
};
const handle = handleBetterAuth;
export {
handle
};

View File

@@ -0,0 +1,14 @@
const load = async ({ locals }) => {
return {
user: locals.user ? {
id: locals.user.id,
name: locals.user.name,
email: locals.user.email,
image: locals.user.image,
role: locals.user.role ?? "player"
} : null
};
};
export {
load
};

View File

@@ -0,0 +1,97 @@
import { a as ensure_array_like, b as attr, c as attr_class, s as stringify, e as escape_html, d as derived } from "../../../chunks/index3.js";
import { p as page } from "../../../chunks/index4.js";
import "@sveltejs/kit/internal";
import "../../../chunks/url.js";
import "../../../chunks/utils.js";
import "@sveltejs/kit/internal/server";
import "../../../chunks/root.js";
import "../../../chunks/exports.js";
import "../../../chunks/state.svelte.js";
function Sidebar($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
const user = derived(() => page.data?.user);
const nav = [
{ href: "/", label: "Dashboard", icon: "⌂" },
{ href: "/matches", label: "Matches", icon: "⚔" },
{ href: "/mappools", label: "Mappools", icon: "♫" },
{ href: "/teams", label: "Teams", icon: "⚑" }
];
function isActive(href) {
if (href === "/") return page.url.pathname === "/";
return page.url.pathname.startsWith(href);
}
const isAdmin = derived(() => user()?.role === "admin");
$$renderer2.push(`<aside class="fixed top-0 left-0 z-40 flex h-full w-56 flex-col border-r border-border bg-surface-800"><a href="/" class="flex items-center gap-2.5 px-5 py-5"><div class="font-800 flex h-8 w-8 items-center justify-center rounded-md bg-accent text-sm text-surface-900">V</div> <span class="font-700 text-base tracking-tight text-text-primary">Vash Esports</span></a> <nav class="mt-2 flex flex-1 flex-col gap-0.5 px-3"><!--[-->`);
const each_array = ensure_array_like(nav);
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let item = each_array[$$index];
$$renderer2.push(`<a${attr("href", item.href)}${attr_class(`font-500 flex items-center gap-3 rounded-md px-3 py-2 text-sm transition-colors ${stringify(isActive(item.href) ? "bg-accent-dim text-accent" : "text-text-secondary hover:bg-surface-700 hover:text-text-primary")}`)}><span class="text-base">${escape_html(item.icon)}</span> ${escape_html(item.label)}</a>`);
}
$$renderer2.push(`<!--]--> `);
if (isAdmin()) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="mt-4 mb-1 px-3"><p class="text-[10px] font-600 text-text-secondary uppercase tracking-widest">Staff</p></div> <a href="/admin"${attr_class(`font-500 flex items-center gap-3 rounded-md px-3 py-2 text-sm transition-colors ${stringify(isActive("/admin") ? "bg-red-500/10 text-red-400" : "text-text-secondary hover:bg-surface-700 hover:text-text-primary")}`)}><span class="text-base">⚡</span> Admin</a>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></nav> <div class="border-t border-border p-3"><a href="/settings"${attr_class(`font-500 flex items-center gap-3 rounded-md px-3 py-2 text-sm text-text-secondary transition-colors hover:bg-surface-700 hover:text-text-primary ${stringify(isActive("/settings") ? "bg-accent-dim text-accent" : "")}`)}><span class="text-base">⚙</span> Settings</a></div></aside>`);
});
}
function Header($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
const user = derived(() => page.data?.user);
const roleBadge = {
referee: { label: "REF", color: "bg-yellow-500/20 text-yellow-400" },
admin: { label: "ADMIN", color: "bg-red-500/20 text-red-400" }
};
const badge = derived(() => user()?.role ? roleBadge[user().role] : null);
$$renderer2.push(`<header class="sticky top-0 z-30 flex h-14 items-center justify-between border-b border-border bg-surface-900/80 px-6 backdrop-blur-md"><div></div> <div class="flex items-center gap-4">`);
if (user()) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="flex items-center gap-3">`);
if (badge()) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<span${attr_class(`rounded px-1.5 py-0.5 text-[10px] font-700 ${stringify(badge().color)}`)}>${escape_html(badge().label)}</span>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (user().image) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", user().image)}${attr("alt", user().name)} class="h-7 w-7 rounded-full"/>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <span class="font-500 text-sm text-text-primary">${escape_html(user().name)}</span> <form method="post" action="/settings?/logout"><button type="submit" class="rounded-md border border-border px-2.5 py-1 text-xs text-text-secondary transition-colors hover:border-red-500/30 hover:text-red-400">Logout</button></form></div>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<a href="/login" class="font-600 rounded-md bg-accent px-3.5 py-1.5 text-sm text-surface-900 transition-colors hover:bg-accent-hover">Sign in with osu!</a>`);
}
$$renderer2.push(`<!--]--></div></header>`);
});
}
function _layout($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
let { children } = $$props;
const user = derived(() => page.data?.user);
if (user()) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="flex min-h-dvh">`);
Sidebar($$renderer2);
$$renderer2.push(`<!----> <div class="ml-56 flex flex-1 flex-col">`);
Header($$renderer2);
$$renderer2.push(`<!----> <main class="flex-1 p-6">`);
children($$renderer2);
$$renderer2.push(`<!----></main></div></div>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<div class="min-h-dvh"><header class="flex h-14 items-center justify-between border-b border-border bg-surface-900/80 px-6 backdrop-blur-md"><a href="/" class="flex items-center gap-2.5"><div class="font-800 flex h-8 w-8 items-center justify-center rounded-md bg-accent text-sm text-surface-900">V</div> <span class="font-700 text-base tracking-tight text-text-primary">Vash Esports</span></a> <a href="/login" class="font-600 rounded-md bg-accent px-3.5 py-1.5 text-sm text-surface-900 transition-colors hover:bg-accent-hover">Sign in with osu!</a></header> <main class="p-6">`);
children($$renderer2);
$$renderer2.push(`<!----></main></div>`);
}
$$renderer2.push(`<!--]-->`);
});
}
export {
_layout as default
};

View File

@@ -0,0 +1,39 @@
import { d as db, b as match, c as team, m as mappool } from "../../../chunks/index2.js";
import { desc, inArray, count, eq } from "drizzle-orm";
const load = async ({ locals }) => {
if (!locals.user) {
return {
authenticated: false,
recentMatches: [],
liveMatches: [],
stats: { matches: 0, finished: 0, teams: 0, mappools: 0 }
};
}
const recentMatches = await db.query.match.findMany({
with: { participants: { with: { team: true } } },
orderBy: desc(match.createdAt),
limit: 5
});
const liveMatches = await db.query.match.findMany({
with: { participants: { with: { team: true } } },
where: inArray(match.state, ["LOBBY", "ROLLING", "PICKING", "PLAYING"])
});
const [matchCount] = await db.select({ count: count() }).from(match);
const [teamCount] = await db.select({ count: count() }).from(team);
const [poolCount] = await db.select({ count: count() }).from(mappool);
const [finishedCount] = await db.select({ count: count() }).from(match).where(eq(match.state, "FINISHED"));
return {
authenticated: true,
recentMatches,
liveMatches,
stats: {
matches: matchCount.count,
finished: finishedCount.count,
teams: teamCount.count,
mappools: poolCount.count
}
};
};
export {
load
};

View File

@@ -0,0 +1,118 @@
import { e as escape_html, a as ensure_array_like, b as attr, s as stringify, c as attr_class } from "../../../chunks/index3.js";
function _page($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
let { data } = $$props;
const stateConfig = {
CREATED: { label: "Created", color: "text-text-secondary" },
LOBBY: { label: "In Lobby", color: "text-yellow-400" },
ROLLING: {
label: "Rolling",
color: "text-yellow-400",
dot: "bg-yellow-400"
},
PICKING: { label: "Picking", color: "text-blue-400", dot: "bg-blue-400" },
PLAYING: { label: "Live", color: "text-green-400", dot: "bg-green-400" },
FINISHED: { label: "Finished", color: "text-text-secondary" },
CANCELLED: { label: "Cancelled", color: "text-red-400" }
};
let queueLoading = false;
function timeAgo(date) {
const d = new Date(date);
const diff = Date.now() - d.getTime();
const mins = Math.floor(diff / 6e4);
if (mins < 1) return "just now";
if (mins < 60) return `${mins}m ago`;
const hours = Math.floor(mins / 60);
if (hours < 24) return `${hours}h ago`;
const days = Math.floor(hours / 24);
return `${days}d ago`;
}
if (!data.user) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="flex min-h-[70vh] flex-col items-center justify-center text-center"><div class="font-800 mb-6 flex h-16 w-16 items-center justify-center rounded-xl bg-accent text-2xl text-surface-900">V</div> <h1 class="text-4xl font-800 tracking-tight">Welcome to <span class="text-accent">Vash Esports</span></h1> <p class="mt-3 max-w-md text-text-secondary">Automated tournament match management for osu! — lobbies, mappools, picks, bans, and
ELO tracking all in one place.</p> <a href="/login" class="font-600 mt-8 rounded-lg bg-accent px-6 py-3 text-surface-900 transition-colors hover:bg-accent-hover">Sign in with osu!</a> <p class="mt-4 text-xs text-text-secondary">Uses your osu! account. No extra registration needed.</p></div>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<div class="mx-auto max-w-5xl"><div><h1 class="text-2xl font-700 tracking-tight">Welcome back, <span class="text-accent">${escape_html(data.user.name)}</span></h1> <p class="mt-1 text-sm text-text-secondary">Automated esports match management for osu!</p></div> <div class="mt-6 grid grid-cols-2 gap-3 sm:grid-cols-4"><div class="rounded-lg border border-border bg-surface-800 p-4"><p class="text-2xl font-800 tabular-nums text-text-primary">${escape_html(data.stats.matches)}</p> <p class="mt-1 text-xs text-text-secondary">Total Matches</p></div> <div class="rounded-lg border border-border bg-surface-800 p-4"><p class="text-2xl font-800 tabular-nums text-green-400">${escape_html(data.stats.finished)}</p> <p class="mt-1 text-xs text-text-secondary">Completed</p></div> <div class="rounded-lg border border-border bg-surface-800 p-4"><p class="text-2xl font-800 tabular-nums text-text-primary">${escape_html(data.stats.teams)}</p> <p class="mt-1 text-xs text-text-secondary">Teams</p></div> <div class="rounded-lg border border-border bg-surface-800 p-4"><p class="text-2xl font-800 tabular-nums text-text-primary">${escape_html(data.stats.mappools)}</p> <p class="mt-1 text-xs text-text-secondary">Mappools</p></div></div> `);
if (data.liveMatches.length > 0) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="mt-8"><div class="flex items-center gap-2"><div class="relative h-2 w-2"><div class="absolute inset-0 animate-ping rounded-full bg-green-400 opacity-75"></div> <div class="relative h-2 w-2 rounded-full bg-green-400"></div></div> <h2 class="text-sm font-600">Live Now</h2></div> <div class="mt-3 flex flex-col gap-2"><!--[-->`);
const each_array = ensure_array_like(data.liveMatches);
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let m = each_array[$$index];
const p1 = m.participants[0];
const p2 = m.participants[1];
const sc = stateConfig[m.state];
$$renderer2.push(`<a${attr("href", `/matches/${stringify(m.id)}`)} class="flex items-center gap-4 rounded-lg border border-green-500/20 bg-surface-800 p-4 transition-all hover:border-green-500/40 hover:bg-surface-700"><div class="flex flex-1 items-center gap-3">`);
if (p1?.team.avatarUrl) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", p1.team.avatarUrl)} alt="" class="h-8 w-8 rounded-full"/>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <span class="text-sm font-600">${escape_html(p1?.team.name ?? "?")}</span></div> <div class="flex items-center gap-3"><span class="text-xl font-800 tabular-nums">${escape_html(p1?.score ?? 0)}</span> <span class="text-xs text-text-secondary">vs</span> <span class="text-xl font-800 tabular-nums">${escape_html(p2?.score ?? 0)}</span></div> <div class="flex flex-1 items-center justify-end gap-3"><span class="text-sm font-600">${escape_html(p2?.team.name ?? "?")}</span> `);
if (p2?.team.avatarUrl) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", p2.team.avatarUrl)} alt="" class="h-8 w-8 rounded-full"/>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div> <span${attr_class(`flex items-center gap-1.5 text-xs font-500 ${stringify(sc?.color ?? "")}`)}>`);
if (sc?.dot) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<span${attr_class(`h-1.5 w-1.5 rounded-full ${stringify(sc.dot)}`)}></span>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> ${escape_html(sc?.label)}</span></a>`);
}
$$renderer2.push(`<!--]--></div></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <div class="mt-6 rounded-lg border border-border bg-surface-800 p-5"><div class="flex items-center justify-between"><div><h2 class="text-sm font-600">Ranked Queue</h2> <p class="mt-0.5 text-xs text-text-secondary">Find a match at your skill level</p></div> `);
{
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<button${attr("disabled", queueLoading, true)} class="rounded-md bg-accent px-4 py-2 text-sm font-600 text-surface-900 transition-colors hover:bg-accent-hover disabled:opacity-50">${escape_html("Find Match")}</button>`);
}
$$renderer2.push(`<!--]--></div></div> <div class="mt-8 grid gap-4 lg:grid-cols-3"><div class="lg:col-span-1"><h2 class="text-sm font-600">Quick Actions</h2> <div class="mt-3 flex flex-col gap-2"><a href="/matches" class="flex items-center gap-3 rounded-lg border border-border bg-surface-800 p-3 transition-colors hover:border-accent/40 hover:bg-surface-700"><span class="flex h-8 w-8 items-center justify-center rounded-md bg-accent/10 text-accent">⚔</span> <div><p class="text-sm font-600">New Match</p> <p class="text-xs text-text-secondary">Start a 1v1</p></div></a> <a href="/mappools" class="flex items-center gap-3 rounded-lg border border-border bg-surface-800 p-3 transition-colors hover:border-accent/40 hover:bg-surface-700"><span class="flex h-8 w-8 items-center justify-center rounded-md bg-purple-500/10 text-purple-400">♫</span> <div><p class="text-sm font-600">Mappools</p> <p class="text-xs text-text-secondary">Build a pool</p></div></a> <a href="/teams" class="flex items-center gap-3 rounded-lg border border-border bg-surface-800 p-3 transition-colors hover:border-accent/40 hover:bg-surface-700"><span class="flex h-8 w-8 items-center justify-center rounded-md bg-blue-500/10 text-blue-400">⚑</span> <div><p class="text-sm font-600">Teams</p> <p class="text-xs text-text-secondary">Manage rosters</p></div></a></div></div> <div class="lg:col-span-2"><h2 class="text-sm font-600">Recent Matches</h2> <div class="mt-3 flex flex-col gap-2">`);
const each_array_1 = ensure_array_like(data.recentMatches);
if (each_array_1.length !== 0) {
$$renderer2.push("<!--[-->");
for (let $$index_1 = 0, $$length = each_array_1.length; $$index_1 < $$length; $$index_1++) {
let m = each_array_1[$$index_1];
const p1 = m.participants[0];
const p2 = m.participants[1];
const config = m.config;
const sc = stateConfig[m.state];
$$renderer2.push(`<a${attr("href", `/matches/${stringify(m.id)}`)} class="flex items-center gap-3 rounded-lg border border-border bg-surface-800 p-3 transition-colors hover:border-accent/30 hover:bg-surface-700"><div class="min-w-0 flex-1"><div class="flex items-center gap-2"><span class="text-sm font-600">${escape_html(p1?.team.name ?? "?")}</span> `);
if (m.state === "FINISHED") {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<span${attr_class(`text-xs font-700 tabular-nums ${stringify((p1?.score ?? 0) > (p2?.score ?? 0) ? "text-green-400" : "text-text-secondary")}`)}>${escape_html(p1?.score ?? 0)}</span> <span class="text-xs text-text-secondary">-</span> <span${attr_class(`text-xs font-700 tabular-nums ${stringify((p2?.score ?? 0) > (p1?.score ?? 0) ? "text-green-400" : "text-text-secondary")}`)}>${escape_html(p2?.score ?? 0)}</span>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<span class="text-xs text-text-secondary">vs</span>`);
}
$$renderer2.push(`<!--]--> <span class="text-sm font-600">${escape_html(p2?.team.name ?? "?")}</span></div> <p class="mt-0.5 text-xs text-text-secondary">${escape_html(m.name ? `${m.name} · ` : "")}BO${escape_html(config.bestOf)}
· ${escape_html(timeAgo(m.finishedAt ?? m.createdAt))}</p></div> `);
if (m.state === "FINISHED" && m.winnerId) {
$$renderer2.push("<!--[-->");
const winner = m.participants.find((p) => p.teamId === m.winnerId);
$$renderer2.push(`<span class="text-xs text-green-400">🏆 ${escape_html(winner?.team.name)}</span>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <span${attr_class(`text-xs ${stringify(sc?.color ?? "text-text-secondary")}`)}>${escape_html(sc?.label)}</span></a>`);
}
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<div class="rounded-lg border border-dashed border-border py-8 text-center"><p class="text-sm text-text-secondary">No matches yet. <a href="/matches" class="text-accent hover:underline">Create one</a></p></div>`);
}
$$renderer2.push(`<!--]--></div></div></div></div>`);
}
$$renderer2.push(`<!--]-->`);
});
}
export {
_page as default
};

View File

@@ -0,0 +1,70 @@
import { d as db, u as user, p as playerRating } from "../../../../chunks/index2.js";
import { eq, desc } from "drizzle-orm";
import { error } from "@sveltejs/kit";
const ROLE_HIERARCHY = {
player: 0,
referee: 1,
admin: 2
};
function hasRole(userRole, minRole) {
const level = ROLE_HIERARCHY[userRole] ?? 0;
const required = ROLE_HIERARCHY[minRole];
return level >= required;
}
function requireRole(locals, minRole, message = "Insufficient permissions") {
if (!locals.user) {
error(401, "Not logged in");
}
if (!hasRole(locals.user.role, minRole)) {
error(403, message);
}
}
async function setUserRole(userId, role) {
await db.update(user).set({ role }).where(eq(user.id, userId));
}
const load = async ({ locals }) => {
requireRole(locals, "admin");
const users = await db.query.user.findMany({
orderBy: desc(user.createdAt)
});
const usersWithRatings = await Promise.all(
users.map(async (u) => {
const rating = await db.query.playerRating.findFirst({
where: eq(playerRating.userId, u.id)
});
return {
id: u.id,
name: u.name,
email: u.email,
image: u.image,
role: u.role ?? "player",
createdAt: u.createdAt,
elo: rating?.elo ?? 1e3,
wins: rating?.wins ?? 0,
losses: rating?.losses ?? 0
};
})
);
return { users: usersWithRatings };
};
const actions = {
setRole: async ({ request, locals }) => {
requireRole(locals, "admin");
const form = await request.formData();
const userId = form.get("userId")?.toString();
const role = form.get("role")?.toString();
if (!userId || !role) return { error: "User ID and role are required" };
if (!["player", "referee", "admin"].includes(role)) {
return { error: "Invalid role" };
}
if (userId === locals.user.id && role !== "admin") {
return { error: "You can't demote yourself" };
}
await setUserRole(userId, role);
return { success: true };
}
};
export {
actions,
load
};

View File

@@ -0,0 +1,70 @@
import { e as escape_html, a as ensure_array_like, b as attr, s as stringify } from "../../../../chunks/index3.js";
import "@sveltejs/kit/internal";
import "../../../../chunks/url.js";
import "../../../../chunks/utils.js";
import "@sveltejs/kit/internal/server";
import "../../../../chunks/root.js";
import "../../../../chunks/exports.js";
import "../../../../chunks/state.svelte.js";
function _page($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
let { data } = $$props;
const roleBadge = {
player: {
label: "Player",
color: "bg-surface-600 text-text-secondary border-border"
},
referee: {
label: "Referee",
color: "bg-yellow-500/20 text-yellow-400 border-yellow-500/30"
},
admin: {
label: "Admin",
color: "bg-red-500/20 text-red-400 border-red-500/30"
}
};
$$renderer2.push(`<div class="mx-auto max-w-4xl"><div><h1 class="text-2xl font-700 tracking-tight">Admin Panel</h1> <p class="mt-1 text-sm text-text-secondary">${escape_html(data.users.length)} registered user${escape_html(data.users.length !== 1 ? "s" : "")}</p></div> `);
{
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <div class="mt-6 rounded-lg border border-border bg-surface-800"><div class="grid grid-cols-[auto_1fr_auto_auto_auto] gap-4 border-b border-border px-4 py-3"><span class="text-xs font-600 text-text-secondary">Avatar</span> <span class="text-xs font-600 text-text-secondary">User</span> <span class="text-xs font-600 text-text-secondary">ELO</span> <span class="text-xs font-600 text-text-secondary">W/L</span> <span class="text-xs font-600 text-text-secondary">Role</span></div> <!--[-->`);
const each_array = ensure_array_like(data.users);
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let u = each_array[$$index];
const badge = roleBadge[u.role] ?? roleBadge.player;
$$renderer2.push(`<div class="grid grid-cols-[auto_1fr_auto_auto_auto] items-center gap-4 border-b border-border/50 px-4 py-3 last:border-b-0">`);
if (u.image) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", u.image)} alt="" class="h-8 w-8 rounded-full"/>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<div class="flex h-8 w-8 items-center justify-center rounded-full bg-surface-600 text-xs font-700 text-text-secondary">${escape_html(u.name.charAt(0).toUpperCase())}</div>`);
}
$$renderer2.push(`<!--]--> <div class="min-w-0"><p class="truncate text-sm font-500">${escape_html(u.name)}</p> <p class="truncate text-xs text-text-secondary">${escape_html(u.email)}</p></div> <span class="text-sm font-600 tabular-nums text-text-primary">${escape_html(u.elo)}</span> <span class="text-xs tabular-nums text-text-secondary"><span class="text-green-400">${escape_html(u.wins)}W</span> / <span class="text-red-400">${escape_html(u.losses)}L</span></span> <form method="post" action="?/setRole" class="flex items-center gap-2"><input type="hidden" name="userId"${attr("value", u.id)}/> `);
$$renderer2.select(
{
name: "role",
value: u.role,
onchange: (e) => e.currentTarget.form?.requestSubmit(),
class: `rounded-md border px-2 py-1 text-xs font-500 ${stringify(badge.color)} cursor-pointer bg-transparent focus:outline-none`
},
($$renderer3) => {
$$renderer3.option({ value: "player", class: "bg-surface-800 text-text-primary" }, ($$renderer4) => {
$$renderer4.push(`Player`);
});
$$renderer3.option({ value: "referee", class: "bg-surface-800 text-text-primary" }, ($$renderer4) => {
$$renderer4.push(`Referee`);
});
$$renderer3.option({ value: "admin", class: "bg-surface-800 text-text-primary" }, ($$renderer4) => {
$$renderer4.push(`Admin`);
});
}
);
$$renderer2.push(`</form></div>`);
}
$$renderer2.push(`<!--]--></div></div>`);
});
}
export {
_page as default
};

View File

@@ -0,0 +1,100 @@
import { d as db, m as mappool, a as mappoolSlot } from "../../../../../chunks/index2.js";
import { eq, and } from "drizzle-orm";
import { redirect, error } from "@sveltejs/kit";
import { g as getBeatmap } from "../../../../../chunks/api.js";
const load = async ({ params, locals }) => {
if (!locals.user) redirect(302, "/");
const pool = await db.query.mappool.findFirst({
where: eq(mappool.id, params.id),
with: {
slots: {
orderBy: (s, { asc }) => [asc(s.category), asc(s.orderInCategory)]
}
}
});
if (!pool) error(404, "Mappool not found");
const slotsWithBeatmaps = await Promise.all(
pool.slots.map(async (slot) => {
try {
const beatmap = await getBeatmap(slot.beatmapId);
return {
...slot,
beatmap: {
title: beatmap.beatmapset.title,
artist: beatmap.beatmapset.artist,
version: beatmap.version,
starRating: beatmap.difficulty_rating,
bpm: beatmap.bpm,
totalLength: beatmap.total_length,
coverUrl: beatmap.beatmapset.covers["card@2x"],
url: beatmap.url
}
};
} catch {
return {
...slot,
beatmap: null
};
}
})
);
return {
pool: { ...pool, slots: slotsWithBeatmaps }
};
};
const actions = {
addSlot: async ({ params, request, locals }) => {
if (!locals.user) redirect(302, "/");
const form = await request.formData();
let beatmapId = form.get("beatmapId")?.toString()?.trim();
const category = form.get("category")?.toString()?.trim()?.toUpperCase();
if (!beatmapId || !category) {
return { error: "Beatmap ID and category are required" };
}
const urlMatch = beatmapId.match(/beatmaps\/(\d+)/);
const setMatch = beatmapId.match(/beatmapsets\/\d+#\w+\/(\d+)/);
if (urlMatch) beatmapId = urlMatch[1];
else if (setMatch) beatmapId = setMatch[1];
if (!/^\d+$/.test(beatmapId)) {
return { error: "Invalid beatmap ID" };
}
let beatmap;
try {
beatmap = await getBeatmap(beatmapId);
} catch {
return { error: "Beatmap not found on osu!" };
}
const existing = await db.query.mappoolSlot.findMany({
where: and(
eq(mappoolSlot.mappoolId, params.id),
eq(mappoolSlot.category, category)
)
});
await db.insert(mappoolSlot).values({
mappoolId: params.id,
beatmapId,
category,
orderInCategory: existing.length + 1,
starRating: beatmap.difficulty_rating,
mods: category === "NM" || category === "TB" || category === "FM" ? [] : [category]
});
return { success: true };
},
removeSlot: async ({ request, locals }) => {
if (!locals.user) redirect(302, "/");
const form = await request.formData();
const slotId = form.get("slotId")?.toString();
if (!slotId) return { error: "Missing slot ID" };
await db.delete(mappoolSlot).where(eq(mappoolSlot.id, slotId));
return { success: true };
},
deletePool: async ({ params, locals }) => {
if (!locals.user) redirect(302, "/");
await db.delete(mappool).where(eq(mappool.id, params.id));
redirect(303, "/mappools");
}
};
export {
actions,
load
};

View File

@@ -0,0 +1,98 @@
import { e as escape_html, a as ensure_array_like, b as attr, c as attr_class, d as derived, s as stringify } from "../../../../../chunks/index3.js";
import "@sveltejs/kit/internal";
import "../../../../../chunks/url.js";
import "../../../../../chunks/utils.js";
import "@sveltejs/kit/internal/server";
import "../../../../../chunks/root.js";
import "../../../../../chunks/exports.js";
import "../../../../../chunks/state.svelte.js";
function _page($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
let { data } = $$props;
const categories = ["NM", "HD", "HR", "DT", "FM", "TB"];
let addingCategory = "NM";
let beatmapInput = "";
const grouped = derived(() => () => {
const groups = {};
for (const cat of categories) {
const slots = data.pool.slots.filter((s) => s.category === cat);
if (slots.length > 0) groups[cat] = slots;
}
return groups;
});
function formatLength(seconds) {
const m = Math.floor(seconds / 60);
const s = seconds % 60;
return `${m}:${s.toString().padStart(2, "0")}`;
}
const categoryColors = {
NM: "bg-blue-500/20 text-blue-400 border-blue-500/30",
HD: "bg-yellow-500/20 text-yellow-400 border-yellow-500/30",
HR: "bg-red-500/20 text-red-400 border-red-500/30",
DT: "bg-purple-500/20 text-purple-400 border-purple-500/30",
FM: "bg-green-500/20 text-green-400 border-green-500/30",
TB: "bg-pink-500/20 text-pink-400 border-pink-500/30"
};
$$renderer2.push(`<div class="mx-auto max-w-4xl"><div class="flex items-center justify-between"><div class="flex items-center gap-3"><a href="/mappools" class="text-text-secondary transition-colors hover:text-text-primary">←</a> <div><h1 class="text-2xl font-700 tracking-tight">${escape_html(data.pool.name)}</h1> <p class="mt-1 text-sm text-text-secondary">${escape_html(data.pool.slots.length)} map${escape_html(data.pool.slots.length !== 1 ? "s" : "")}</p></div></div> <form method="post" action="?/deletePool"><button type="submit" class="rounded-md border border-red-500/30 px-3 py-1.5 text-sm text-red-400 transition-colors hover:bg-red-500/10">Delete Pool</button></form></div> <form method="post" action="?/addSlot" class="mt-6 rounded-lg border border-border bg-surface-800 p-4"><h2 class="text-sm font-600">Add Map</h2> <div class="mt-3 flex gap-3">`);
$$renderer2.select(
{
name: "category",
value: addingCategory,
class: "rounded-md border border-border bg-surface-700 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none"
},
($$renderer3) => {
$$renderer3.push(`<!--[-->`);
const each_array = ensure_array_like(categories);
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let cat = each_array[$$index];
$$renderer3.option({ value: cat }, ($$renderer4) => {
$$renderer4.push(`${escape_html(cat)}`);
});
}
$$renderer3.push(`<!--]-->`);
}
);
$$renderer2.push(` <input type="text" name="beatmapId"${attr("value", beatmapInput)} placeholder="Beatmap ID or URL (e.g. 75 or https://osu.ppy.sh/beatmaps/75)" class="flex-1 rounded-md border border-border bg-surface-700 px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary/50 focus:border-accent focus:outline-none"/> <button type="submit"${attr("disabled", !beatmapInput.trim(), true)} class="rounded-md bg-accent px-4 py-2 text-sm font-600 text-surface-900 transition-colors hover:bg-accent-hover disabled:opacity-50">${escape_html("Add")}</button></div> `);
{
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></form> <div class="mt-6 flex flex-col gap-6">`);
const each_array_1 = ensure_array_like(Object.entries(grouped()()));
if (each_array_1.length !== 0) {
$$renderer2.push("<!--[-->");
for (let $$index_2 = 0, $$length = each_array_1.length; $$index_2 < $$length; $$index_2++) {
let [category, slots] = each_array_1[$$index_2];
$$renderer2.push(`<div><div class="mb-2 flex items-center gap-2"><span${attr_class(`rounded border px-2 py-0.5 text-xs font-600 ${stringify(categoryColors[category] ?? "bg-surface-600 text-text-secondary border-border")}`)}>${escape_html(category)}</span> <span class="text-xs text-text-secondary">${escape_html(slots.length)} map${escape_html(slots.length !== 1 ? "s" : "")}</span></div> <div class="flex flex-col gap-2"><!--[-->`);
const each_array_2 = ensure_array_like(slots);
for (let i = 0, $$length2 = each_array_2.length; i < $$length2; i++) {
let slot = each_array_2[i];
$$renderer2.push(`<div class="group flex items-center gap-3 rounded-lg border border-border bg-surface-800 p-2 transition-colors hover:border-accent/30">`);
if (slot.beatmap?.coverUrl) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", slot.beatmap.coverUrl)} alt="" class="h-12 w-24 rounded object-cover"/>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<div class="flex h-12 w-24 items-center justify-center rounded bg-surface-700 text-xs text-text-secondary">No cover</div>`);
}
$$renderer2.push(`<!--]--> <div class="min-w-0 flex-1">`);
if (slot.beatmap) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<a${attr("href", slot.beatmap.url)} target="_blank" rel="noopener" class="truncate text-sm font-500 hover:text-accent">${escape_html(slot.beatmap.artist)} - ${escape_html(slot.beatmap.title)}</a> <div class="mt-0.5 flex items-center gap-3 text-xs text-text-secondary"><span>[${escape_html(slot.beatmap.version)}]</span> <span>★ ${escape_html(slot.beatmap.starRating.toFixed(2))}</span> <span>${escape_html(slot.beatmap.bpm)} BPM</span> <span>${escape_html(formatLength(slot.beatmap.totalLength))}</span></div>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<p class="text-sm text-text-secondary">Beatmap #${escape_html(slot.beatmapId)}</p>`);
}
$$renderer2.push(`<!--]--></div> <span class="text-xs font-600 text-text-secondary">${escape_html(category)}${escape_html(i + 1)}</span> <form method="post" action="?/removeSlot"><input type="hidden" name="slotId"${attr("value", slot.id)}/> <button type="submit" class="rounded p-1 text-text-secondary opacity-0 transition-all hover:bg-red-500/10 hover:text-red-400 group-hover:opacity-100">✕</button></form></div>`);
}
$$renderer2.push(`<!--]--></div></div>`);
}
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<div class="rounded-lg border border-dashed border-border py-12 text-center"><p class="text-sm text-text-secondary">No maps yet. Add your first map above.</p></div>`);
}
$$renderer2.push(`<!--]--></div></div>`);
});
}
export {
_page as default
};

View File

@@ -0,0 +1,24 @@
import { d as db, m as mappool } from "../../../../chunks/index2.js";
import { redirect } from "@sveltejs/kit";
const load = async ({ locals }) => {
if (!locals.user) redirect(302, "/");
const mappools = await db.query.mappool.findMany({
with: { slots: true },
orderBy: (m, { desc }) => [desc(m.createdAt)]
});
return { mappools };
};
const actions = {
create: async ({ request, locals }) => {
if (!locals.user) redirect(302, "/");
const form = await request.formData();
const name = form.get("name")?.toString()?.trim();
if (!name) return { error: "Name is required" };
const [created] = await db.insert(mappool).values({ name, createdBy: locals.user.id }).returning();
redirect(303, `/mappools/${created.id}`);
}
};
export {
actions,
load
};

View File

@@ -0,0 +1,34 @@
import { e as escape_html, a as ensure_array_like, b as attr, s as stringify } from "../../../../chunks/index3.js";
import "@sveltejs/kit/internal";
import "../../../../chunks/url.js";
import "../../../../chunks/utils.js";
import "@sveltejs/kit/internal/server";
import "../../../../chunks/root.js";
import "../../../../chunks/exports.js";
import "../../../../chunks/state.svelte.js";
function _page($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
let { data } = $$props;
$$renderer2.push(`<div class="mx-auto max-w-4xl"><div class="flex items-center justify-between"><div><h1 class="text-2xl font-700 tracking-tight">Mappools</h1> <p class="mt-1 text-sm text-text-secondary">Create and manage your beatmap pools</p></div> <button class="rounded-md bg-accent px-4 py-2 text-sm font-600 text-surface-900 transition-colors hover:bg-accent-hover">${escape_html("New Pool")}</button></div> `);
{
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <div class="mt-6 flex flex-col gap-3">`);
const each_array = ensure_array_like(data.mappools);
if (each_array.length !== 0) {
$$renderer2.push("<!--[-->");
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let pool = each_array[$$index];
$$renderer2.push(`<a${attr("href", `/mappools/${stringify(pool.id)}`)} class="group flex items-center justify-between rounded-lg border border-border bg-surface-800 p-4 transition-colors hover:border-accent/40 hover:bg-surface-700"><div><h2 class="text-sm font-600">${escape_html(pool.name)}</h2> <p class="mt-1 text-xs text-text-secondary">${escape_html(pool.slots.length)} map${escape_html(pool.slots.length !== 1 ? "s" : "")}
· Created ${escape_html(new Date(pool.createdAt).toLocaleDateString())}</p></div> <span class="text-text-secondary transition-colors group-hover:text-accent">→</span></a>`);
}
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<div class="rounded-lg border border-dashed border-border py-12 text-center"><p class="text-sm text-text-secondary">No mappools yet. Create one to get started.</p></div>`);
}
$$renderer2.push(`<!--]--></div></div>`);
});
}
export {
_page as default
};

View File

@@ -0,0 +1,129 @@
import { d as db, u as user } from "../../../../../chunks/index2.js";
import { a as cancelMatch, g as getMatchFull, p as pickMap, s as submitRoll } from "../../../../../chunks/engine.js";
import { c as closeLobby, f as forceStartGame, p as playPickedMap, g as getLobby } from "../../../../../chunks/orchestrator.js";
import { redirect, error } from "@sveltejs/kit";
import { g as getBeatmap } from "../../../../../chunks/api.js";
import { eq } from "drizzle-orm";
const load = async ({ params, locals }) => {
if (!locals.user) redirect(302, "/");
let m;
try {
m = await getMatchFull(params.id);
} catch {
error(404, "Match not found");
}
const beatmapCache = {};
if (m.mappool?.slots) {
await Promise.allSettled(
m.mappool.slots.map(async (slot) => {
try {
const bm = await getBeatmap(slot.beatmapId);
beatmapCache[slot.beatmapId] = {
title: bm.beatmapset.title,
artist: bm.beatmapset.artist,
version: bm.version,
starRating: bm.difficulty_rating,
bpm: bm.bpm,
totalLength: bm.total_length,
coverUrl: bm.beatmapset.covers["card@2x"],
listCoverUrl: bm.beatmapset.covers["list@2x"]
};
} catch {
}
})
);
}
return { match: m, beatmapCache, userId: locals.user.id };
};
const actions = {
reinvite: async ({ params, locals }) => {
if (!locals.user) redirect(302, "/");
const lobby = getLobby(params.id);
if (!lobby) return { error: "No active IRC lobby for this match" };
const m = await getMatchFull(params.id);
const invited = [];
for (const p of m.participants) {
for (const pl of p.players) {
const u = await db.query.user.findFirst({ where: eq(user.id, pl.userId) });
if (u?.name) {
await lobby.invite(u.name);
invited.push(u.name);
}
}
}
return { reinvited: invited };
},
roll: async ({ params, locals }) => {
if (!locals.user) redirect(302, "/");
const m = await getMatchFull(params.id);
let myParticipant = m.participants.find(
(p) => p.players.some((pl) => pl.userId === locals.user.id)
);
if (!myParticipant) {
return { error: "You are not in this match" };
}
if (myParticipant.rollValue !== null) {
const unrolled = m.participants.find((p) => p.rollValue === null);
if (unrolled) {
myParticipant = unrolled;
} else {
return { error: "All participants have already rolled" };
}
}
const value = Math.floor(Math.random() * 100) + 1;
await submitRoll(params.id, myParticipant.id, value);
const lobby = getLobby(params.id);
if (lobby) {
lobby.chat(`${myParticipant.team?.name ?? "Player"} rolled ${value} (via web)`).catch(() => {
});
const updated = await getMatchFull(params.id);
if (updated.state === "PICKING") {
const sorted = [...updated.participants].sort(
(a, b) => (a.pickOrder ?? 99) - (b.pickOrder ?? 99)
);
lobby.chat(
`Rolls complete! ${sorted[0]?.team.name} picks first. Use !pick <slot> (e.g. !pick NM1) or pick in web UI.`
).catch(() => {
});
}
}
return { rolled: value, participantId: myParticipant.id };
},
pick: async ({ params, request, locals }) => {
if (!locals.user) redirect(302, "/");
const form = await request.formData();
const slotId = form.get("slotId")?.toString();
if (!slotId) return { error: "No map selected" };
const m = await getMatchFull(params.id);
const sorted = [...m.participants].sort(
(a, b) => (a.pickOrder ?? 99) - (b.pickOrder ?? 99)
);
const expectedIdx = m.games.length % sorted.length;
const expectedPicker = sorted[expectedIdx];
if (!expectedPicker) return { error: "Cannot determine picker" };
try {
const game = await pickMap(params.id, expectedPicker.id, slotId);
playPickedMap(params.id, game.id).catch(
(err) => console.error("[Match] IRC play failed:", err.message)
);
return { picked: true, gameId: game.id };
} catch (e) {
return { error: e.message };
}
},
forceStart: async ({ params, locals }) => {
if (!locals.user) redirect(302, "/");
await forceStartGame(params.id);
return { started: true };
},
cancel: async ({ params, locals }) => {
if (!locals.user) redirect(302, "/");
await cancelMatch(params.id);
await closeLobby(params.id);
redirect(303, "/matches");
}
};
export {
actions,
load
};

View File

@@ -0,0 +1,323 @@
import { e as escape_html, b as attr, s as stringify, c as attr_class, a as ensure_array_like, d as derived } from "../../../../../chunks/index3.js";
import "@sveltejs/kit/internal";
import "../../../../../chunks/url.js";
import "../../../../../chunks/utils.js";
import "@sveltejs/kit/internal/server";
import "../../../../../chunks/root.js";
import "../../../../../chunks/exports.js";
import "../../../../../chunks/state.svelte.js";
function _page($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
let { data } = $$props;
let m = derived(() => data.match);
let p1 = derived(() => m().participants[0]);
let p2 = derived(() => m().participants[1]);
const config = derived(() => m().config);
const winsNeeded = derived(() => Math.ceil(config().bestOf / 2));
const playedSlotIds = derived(() => new Set(m().games.map((g) => g.mappoolSlotId)));
const sortedByPick = derived(() => [...m().participants].sort((a, b) => (a.pickOrder ?? 99) - (b.pickOrder ?? 99)));
const expectedPickerIdx = derived(() => m().games.length % sortedByPick().length);
const expectedPicker = derived(() => sortedByPick()[expectedPickerIdx()]);
const canRoll = derived(() => m().state === "ROLLING" && m().participants.some((p) => p.rollValue === null));
const catColors = {
NM: "bg-blue-500/20 text-blue-400 border-blue-500/30",
HD: "bg-yellow-500/20 text-yellow-400 border-yellow-500/30",
HR: "bg-red-500/20 text-red-400 border-red-500/30",
DT: "bg-purple-500/20 text-purple-400 border-purple-500/30",
FM: "bg-green-500/20 text-green-400 border-green-500/30",
TB: "bg-pink-500/20 text-pink-400 border-pink-500/30"
};
const groupedSlots = derived(() => () => {
if (!m().mappool?.slots) return {};
const groups = {};
for (const slot of m().mappool.slots) {
if (!groups[slot.category]) groups[slot.category] = [];
groups[slot.category].push(slot);
}
for (const cat of Object.keys(groups)) {
groups[cat].sort((a, b) => a.orderInCategory - b.orderInCategory);
}
return groups;
});
let rolling = false;
let picking = false;
let forceStarting = false;
function formatLength(seconds) {
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
return `${mins}:${secs.toString().padStart(2, "0")}`;
}
function stateLabel(s) {
return {
CREATED: "Waiting",
LOBBY: "In Lobby",
ROLLING: "Rolling",
PICKING: "Pick Phase",
PLAYING: "Playing",
FINISHED: "Finished",
CANCELLED: "Cancelled"
}[s] ?? s;
}
function stateBorder(s) {
return {
ROLLING: "border-yellow-500/30",
PICKING: "border-blue-500/30",
PLAYING: "border-green-500/30",
FINISHED: "border-accent/30"
}[s] ?? "border-border";
}
$$renderer2.push(`<div class="mx-auto max-w-5xl"><div class="flex items-center gap-3"><a href="/matches" class="text-text-secondary transition-colors hover:text-text-primary">←</a> <div class="flex-1"><h1 class="text-xl font-700 tracking-tight">${escape_html(m().name || "Match")}</h1> <p class="mt-0.5 text-xs text-text-secondary">Best of ${escape_html(config().bestOf)} · First to ${escape_html(winsNeeded())} `);
if (m().osuLobbyId) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`· <a${attr("href", `https://osu.ppy.sh/mp/${stringify(m().osuLobbyId)}`)} target="_blank" class="text-accent hover:underline">osu! mp/${escape_html(m().osuLobbyId)}</a>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></p></div> <span${attr_class(`rounded border px-2.5 py-1 text-xs font-600 ${stringify(stateBorder(m().state))}`)}>${escape_html(stateLabel(m().state))}</span> `);
if (!["FINISHED", "CANCELLED"].includes(m().state)) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<form method="post" action="?/cancel"><button type="submit" class="rounded-md border border-red-500/30 px-3 py-1.5 text-xs text-red-400 hover:bg-red-500/10">Cancel</button></form>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div> `);
if (p1() && p2()) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="mt-6 flex items-center gap-4"><div${attr_class(`flex flex-1 items-center gap-4 rounded-lg border p-4 ${stringify(m().winnerId === p1().teamId ? "border-green-500/40 bg-green-500/5" : "border-border bg-surface-800")}`)}>`);
if (p1().team.avatarUrl) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", p1().team.avatarUrl)} alt="" class="h-10 w-10 rounded-full"/>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <div class="flex-1"><p class="text-sm font-600">${escape_html(p1().team.name)}</p> `);
if (p1().rollValue != null) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<p class="text-xs text-text-secondary">Roll: ${escape_html(p1().rollValue)}${escape_html(p1().pickOrder === 1 ? " ★" : "")}</p>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div> <span${attr_class(`text-3xl font-800 tabular-nums ${stringify(p1().score >= winsNeeded() ? "text-green-400" : "text-text-primary")}`)}>${escape_html(p1().score)}</span></div> <span class="text-lg font-700 text-text-secondary">vs</span> <div${attr_class(`flex flex-1 items-center gap-4 rounded-lg border p-4 ${stringify(m().winnerId === p2().teamId ? "border-green-500/40 bg-green-500/5" : "border-border bg-surface-800")}`)}><span${attr_class(`text-3xl font-800 tabular-nums ${stringify(p2().score >= winsNeeded() ? "text-green-400" : "text-text-primary")}`)}>${escape_html(p2().score)}</span> <div class="flex-1 text-right"><p class="text-sm font-600">${escape_html(p2().team.name)}</p> `);
if (p2().rollValue != null) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<p class="text-xs text-text-secondary">${escape_html(p2().pickOrder === 1 ? "★ " : "")}Roll: ${escape_html(p2().rollValue)}</p>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div> `);
if (p2().team.avatarUrl) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", p2().team.avatarUrl)} alt="" class="h-10 w-10 rounded-full"/>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (["LOBBY", "ROLLING", "PICKING", "PLAYING"].includes(m().state)) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="mt-3 flex justify-center"><form method="post" action="?/reinvite"><button type="submit" class="rounded-md border border-border px-3 py-1.5 text-xs text-text-secondary transition-colors hover:border-accent/40 hover:text-accent">📨 Re-invite players to lobby</button></form></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (m().state === "ROLLING") {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"><div class="w-full max-w-md rounded-xl border border-yellow-500/30 bg-surface-800 p-8 text-center shadow-2xl"><h2 class="text-lg font-700">🎲 Roll Phase</h2> <p class="mt-2 text-sm text-text-secondary">Highest roll picks first</p> <div class="mt-6 flex justify-center gap-6"><!--[-->`);
const each_array = ensure_array_like(m().participants);
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let p = each_array[$$index];
$$renderer2.push(`<div class="rounded-lg border border-border bg-surface-700 px-6 py-4"><p class="text-xs text-text-secondary">${escape_html(p.team.name)}</p> `);
if (p.rollValue != null) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<p class="mt-1 text-2xl font-800 text-yellow-400">${escape_html(p.rollValue)}</p>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<p class="mt-1 text-2xl font-800 text-text-secondary/30">—</p>`);
}
$$renderer2.push(`<!--]--></div>`);
}
$$renderer2.push(`<!--]--></div> `);
if (canRoll()) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<form method="post" action="?/roll"><button type="submit"${attr("disabled", rolling, true)} class="mt-6 rounded-md bg-accent px-8 py-3 text-sm font-600 text-surface-900 transition-colors hover:bg-accent-hover disabled:opacity-50">${escape_html("🎲 Roll!")}</button></form> <p class="mt-3 text-xs text-text-secondary">or type <code class="rounded bg-surface-700 px-1.5 py-0.5 font-mono text-accent">!roll</code> in osu! chat</p>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<p class="mt-6 text-sm text-text-secondary animate-pulse">Waiting for all rolls...</p>`);
}
$$renderer2.push(`<!--]--></div></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (m().state === "PICKING") {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"><div class="w-full max-w-3xl max-h-[80vh] overflow-y-auto rounded-xl border border-blue-500/30 bg-surface-800 p-6 shadow-2xl"><div class="text-center"><h2 class="text-lg font-700">🎯 Pick a Map</h2> <p class="mt-1 text-sm"><span class="font-600 text-accent">${escape_html(expectedPicker()?.team.name)}</span>'s turn to pick</p> <p class="mt-1 text-xs text-text-secondary">or type <code class="rounded bg-surface-700 px-1.5 py-0.5 font-mono text-accent">!pick NM1</code> in osu! chat</p></div> `);
{
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <div class="mt-6 flex flex-col gap-4"><!--[-->`);
const each_array_1 = ensure_array_like(Object.entries(groupedSlots()()));
for (let $$index_2 = 0, $$length = each_array_1.length; $$index_2 < $$length; $$index_2++) {
let [category, slots] = each_array_1[$$index_2];
$$renderer2.push(`<div><span${attr_class(`mb-2 inline-block rounded border px-2 py-0.5 text-xs font-600 ${stringify(catColors[category] ?? "border-border")}`)}>${escape_html(category)}</span> <div class="grid grid-cols-1 gap-2 sm:grid-cols-2"><!--[-->`);
const each_array_2 = ensure_array_like(slots);
for (let i = 0, $$length2 = each_array_2.length; i < $$length2; i++) {
let slot = each_array_2[i];
const bm = data.beatmapCache[slot.beatmapId];
const isPlayed = playedSlotIds().has(slot.id);
$$renderer2.push(`<form method="post" action="?/pick"><input type="hidden" name="slotId"${attr("value", slot.id)}/> <button type="submit"${attr("disabled", isPlayed || picking, true)}${attr_class(`flex w-full items-center gap-3 rounded-lg border p-2 text-left transition-all ${stringify(isPlayed ? "border-border/50 bg-surface-900 opacity-30 cursor-not-allowed" : "border-border bg-surface-700 hover:border-accent hover:bg-surface-600 cursor-pointer")}`)}>`);
if (bm?.listCoverUrl) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", bm.listCoverUrl)} alt="" class="h-10 w-20 rounded object-cover"/>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<div class="flex h-10 w-20 items-center justify-center rounded bg-surface-600 text-xs text-text-secondary">?</div>`);
}
$$renderer2.push(`<!--]--> <div class="min-w-0 flex-1">`);
if (bm) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<p class="truncate text-xs font-500">${escape_html(bm.artist)} - ${escape_html(bm.title)}</p> <p class="text-xs text-text-secondary">[${escape_html(bm.version)}] · ★${escape_html(bm.starRating.toFixed(1))} · ${escape_html(bm.bpm)}bpm</p>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<p class="text-xs text-text-secondary">#${escape_html(slot.beatmapId)}</p>`);
}
$$renderer2.push(`<!--]--></div> <span class="text-xs font-600 text-text-secondary">${escape_html(category)}${escape_html(slot.orderInCategory)}</span> `);
if (isPlayed) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<span class="text-xs text-text-secondary">✓</span>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></button></form>`);
}
$$renderer2.push(`<!--]--></div></div>`);
}
$$renderer2.push(`<!--]--></div></div></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (m().state === "PLAYING") {
$$renderer2.push("<!--[-->");
const currentGame = m().games[m().games.length - 1];
const bm = currentGame ? data.beatmapCache[currentGame.slot?.beatmapId] : null;
$$renderer2.push(`<div class="mt-6 rounded-lg border border-green-500/30 bg-green-500/5 p-5 text-center"><div class="flex items-center justify-center gap-2"><div class="relative h-3 w-3"><div class="absolute inset-0 animate-ping rounded-full bg-green-400 opacity-75"></div> <div class="relative h-3 w-3 rounded-full bg-green-400"></div></div> <span class="text-sm font-600 text-green-400">Now Playing</span></div> `);
if (bm) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<p class="mt-2 text-sm">${escape_html(bm.artist)} - ${escape_html(bm.title)} <span class="text-text-secondary">[${escape_html(bm.version)}]</span></p> <p class="mt-1 text-xs text-text-secondary">★${escape_html(bm.starRating.toFixed(1))} · ${escape_html(bm.bpm)}bpm · ${escape_html(formatLength(bm.totalLength))}</p>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <p class="mt-3 text-xs text-text-secondary animate-pulse">Waiting for players to ready up &amp; play in osu!...</p> <form method="post" action="?/forceStart"><button type="submit"${attr("disabled", forceStarting, true)} class="mt-4 rounded-md border border-yellow-500/30 px-4 py-2 text-xs font-600 text-yellow-400 transition-colors hover:bg-yellow-500/10 disabled:opacity-50">${escape_html("Force Start (skip ready)")}</button></form></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (m().state === "FINISHED") {
$$renderer2.push("<!--[-->");
const winner = m().participants.find((p) => p.teamId === m().winnerId);
$$renderer2.push(`<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"><div class="w-full max-w-md rounded-xl border border-accent/30 bg-surface-800 p-8 text-center shadow-2xl"><div class="text-4xl">🏆</div> <h2 class="mt-4 text-2xl font-800"><span class="text-accent">${escape_html(winner?.team.name)}</span> wins!</h2> <p class="mt-2 text-lg font-700 tabular-nums text-text-secondary">${escape_html(p1()?.score)} – ${escape_html(p2()?.score)}</p> <div class="mt-6 flex flex-col gap-1"><!--[-->`);
const each_array_3 = ensure_array_like(m().games);
for (let $$index_3 = 0, $$length = each_array_3.length; $$index_3 < $$length; $$index_3++) {
let game = each_array_3[$$index_3];
const bm = data.beatmapCache[game.slot?.beatmapId];
const winnerP = m().participants.find((p) => p.id === game.winnerParticipantId);
$$renderer2.push(`<div class="flex items-center gap-2 rounded bg-surface-700 px-3 py-1.5 text-xs"><span${attr_class(`font-600 ${stringify(catColors[game.slot?.category]?.split(" ")[1] ?? "text-text-secondary")}`)}>${escape_html(game.slot?.category)}${escape_html(game.slot?.orderInCategory)}</span> <span class="flex-1 truncate text-text-secondary">${escape_html(bm ? `${bm.artist} - ${bm.title}` : `#${game.slot?.beatmapId}`)}</span> <span${attr_class(`font-600 ${stringify(winnerP?.id === p1()?.id ? "text-blue-400" : "text-red-400")}`)}>${escape_html(winnerP?.team.name)}</span></div>`);
}
$$renderer2.push(`<!--]--></div> <a href="/" class="mt-6 inline-block rounded-md bg-accent px-6 py-2.5 text-sm font-600 text-surface-900 transition-colors hover:bg-accent-hover">Back to Dashboard</a></div></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (m().games.length > 0) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="mt-6"><h2 class="text-sm font-600">Games Played</h2> <div class="mt-3 flex flex-col gap-2"><!--[-->`);
const each_array_4 = ensure_array_like(m().games);
for (let $$index_4 = 0, $$length = each_array_4.length; $$index_4 < $$length; $$index_4++) {
let game = each_array_4[$$index_4];
const bm = data.beatmapCache[game.slot?.beatmapId];
const pickerTeam = m().participants.find((p) => p.id === game.pickedByParticipantId)?.team;
const winnerTeam = m().participants.find((p) => p.id === game.winnerParticipantId)?.team;
$$renderer2.push(`<div class="flex items-center gap-3 rounded-lg border border-border bg-surface-800 p-3"><span class="w-6 text-center text-xs font-600 text-text-secondary">${escape_html(game.gameNumber)}</span> `);
if (bm?.listCoverUrl) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", bm.listCoverUrl)} alt="" class="h-8 w-16 rounded object-cover"/>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <div class="min-w-0 flex-1">`);
if (bm) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<p class="truncate text-sm font-500">${escape_html(bm.artist)} - ${escape_html(bm.title)} <span class="text-text-secondary">[${escape_html(bm.version)}]</span></p>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <div class="flex items-center gap-2 text-xs text-text-secondary"><span${attr_class(`rounded border px-1.5 py-0.5 ${stringify(catColors[game.slot?.category] ?? "border-border")}`)}>${escape_html(game.slot?.category)}${escape_html(game.slot?.orderInCategory)}</span> `);
if (pickerTeam) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<span>Picked by ${escape_html(pickerTeam.name)}</span>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div></div> `);
if (game.state === "FINISHED" && p1() && p2()) {
$$renderer2.push("<!--[-->");
const p1Score = game.scores.filter((s) => s.player?.participantId === p1().id).reduce((sum, s) => sum + s.score, 0);
const p2Score = game.scores.filter((s) => s.player?.participantId === p2().id).reduce((sum, s) => sum + s.score, 0);
$$renderer2.push(`<div class="flex items-center gap-2 font-mono text-sm tabular-nums"><span${attr_class(p1Score > p2Score ? "font-700 text-green-400" : "text-text-secondary")}>${escape_html(p1Score.toLocaleString())}</span> <span class="text-text-secondary">-</span> <span${attr_class(p2Score > p1Score ? "font-700 text-green-400" : "text-text-secondary")}>${escape_html(p2Score.toLocaleString())}</span></div>`);
} else if (game.state === "PLAYING") {
$$renderer2.push("<!--[1-->");
$$renderer2.push(`<span class="text-xs text-green-400 animate-pulse">Live</span>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (winnerTeam) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<span class="text-xs text-green-400">✓ ${escape_html(winnerTeam.name)}</span>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div>`);
}
$$renderer2.push(`<!--]--></div></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (m().state === "CREATED") {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="mt-6 rounded-lg border border-border bg-surface-800 p-6 text-center"><p class="text-sm text-text-secondary animate-pulse">Creating osu! lobby...</p></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (m().state === "LOBBY") {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="mt-6 rounded-lg border border-yellow-500/30 bg-yellow-500/5 p-6 text-center"><p class="text-sm text-text-secondary">Lobby created. Waiting for players to join...</p> `);
if (m().osuLobbyId) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<p class="mt-2 text-xs text-text-secondary"><a${attr("href", `https://osu.ppy.sh/mp/${stringify(m().osuLobbyId)}`)} target="_blank" class="text-accent hover:underline">osu! mp/${escape_html(m().osuLobbyId)}</a></p>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (m().state === "CANCELLED") {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="mt-6 rounded-lg border border-red-500/30 bg-red-500/5 p-6 text-center"><p class="text-sm text-red-400">This match was cancelled.</p></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div>`);
});
}
export {
_page as default
};

View File

@@ -0,0 +1,58 @@
import { d as db, b as match } from "../../../../chunks/index2.js";
import { redirect } from "@sveltejs/kit";
import { desc } from "drizzle-orm";
import { c as createMatch } from "../../../../chunks/engine.js";
import { i as initMatchLobby } from "../../../../chunks/orchestrator.js";
const load = async ({ locals }) => {
if (!locals.user) redirect(302, "/");
const matches = await db.query.match.findMany({
with: { participants: { with: { team: true } } },
orderBy: desc(match.createdAt),
limit: 50
});
const teams = await db.query.team.findMany({
orderBy: (t, { asc }) => [asc(t.name)]
});
const mappools = await db.query.mappool.findMany({
with: { slots: true },
orderBy: (m, { desc: desc2 }) => [desc2(m.createdAt)]
});
return { matches, teams, mappools };
};
const actions = {
createMatch: async ({ request, locals }) => {
if (!locals.user) redirect(302, "/");
const form = await request.formData();
const name = form.get("name")?.toString()?.trim() || "Custom Match";
const team1Id = form.get("team1")?.toString();
const team2Id = form.get("team2")?.toString();
const mappoolId = form.get("mappool")?.toString();
const bestOf = parseInt(form.get("bestOf")?.toString() ?? "7");
console.log("[Matches] CREATE:", { name, team1Id, team2Id, mappoolId, bestOf });
if (!team1Id || !team2Id || !mappoolId) {
return { error: "All fields are required" };
}
let result;
try {
result = await createMatch({
name,
config: { bestOf, teamSize: 1, scoringType: "score" },
mappoolId,
teams: [team1Id, team2Id],
createdBy: locals.user.id
});
console.log("[Matches] Created:", result.id);
} catch (e) {
console.error("[Matches] Error:", e);
return { error: e.message };
}
initMatchLobby(result.id).catch((err) => {
console.error("[Matches] IRC lobby failed:", err.message);
});
redirect(303, `/matches/${result.id}`);
}
};
export {
actions,
load
};

View File

@@ -0,0 +1,164 @@
import { e as escape_html, a as ensure_array_like, b as attr, s as stringify, c as attr_class, d as derived } from "../../../../chunks/index3.js";
import "@sveltejs/kit/internal";
import "../../../../chunks/url.js";
import "../../../../chunks/utils.js";
import "@sveltejs/kit/internal/server";
import "../../../../chunks/root.js";
import "../../../../chunks/exports.js";
import "../../../../chunks/state.svelte.js";
function _page($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
let { data } = $$props;
const stateConfig = {
CREATED: { label: "Created", color: "text-text-secondary border-border" },
LOBBY: {
label: "In Lobby",
color: "text-yellow-400 border-yellow-500/30"
},
ROLLING: {
label: "Rolling",
color: "text-yellow-400 border-yellow-500/30",
dot: "bg-yellow-400"
},
PICKING: {
label: "Picking",
color: "text-blue-400 border-blue-500/30",
dot: "bg-blue-400"
},
PLAYING: {
label: "Live",
color: "text-green-400 border-green-500/30",
dot: "bg-green-400"
},
FINISHED: {
label: "Finished",
color: "text-text-secondary border-border"
},
CANCELLED: { label: "Cancelled", color: "text-red-400 border-red-500/30" }
};
const liveStates = ["LOBBY", "ROLLING", "PICKING", "PLAYING"];
const liveMatches = derived(() => data.matches.filter((m) => liveStates.includes(m.state)));
const recentMatches = derived(() => data.matches.filter((m) => !liveStates.includes(m.state)));
function teamDisplay(m) {
const p1 = m.participants[0];
const p2 = m.participants[1];
return { p1, p2 };
}
function timeAgo(date) {
const d = new Date(date);
const diff = Date.now() - d.getTime();
const mins = Math.floor(diff / 6e4);
if (mins < 1) return "just now";
if (mins < 60) return `${mins}m ago`;
const hours = Math.floor(mins / 60);
if (hours < 24) return `${hours}h ago`;
const days = Math.floor(hours / 24);
return `${days}d ago`;
}
$$renderer2.push(`<div class="mx-auto max-w-5xl"><div class="flex items-center justify-between"><div><h1 class="text-2xl font-700 tracking-tight">Matches</h1> <p class="mt-1 text-sm text-text-secondary">${escape_html(data.matches.length)} match${escape_html(data.matches.length !== 1 ? "es" : "")} `);
if (liveMatches().length > 0) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`· <span class="text-green-400">${escape_html(liveMatches().length)} live</span>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></p></div> <button class="rounded-md bg-accent px-4 py-2 text-sm font-600 text-surface-900 transition-colors hover:bg-accent-hover">${escape_html("New Match")}</button></div> `);
{
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (liveMatches().length > 0) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="mt-6"><h2 class="flex items-center gap-2 text-sm font-600"><div class="relative h-2 w-2"><div class="absolute inset-0 animate-ping rounded-full bg-green-400 opacity-75"></div> <div class="relative h-2 w-2 rounded-full bg-green-400"></div></div> Live Now</h2> <div class="mt-3 flex flex-col gap-2"><!--[-->`);
const each_array_4 = ensure_array_like(liveMatches());
for (let $$index_4 = 0, $$length = each_array_4.length; $$index_4 < $$length; $$index_4++) {
let m = each_array_4[$$index_4];
const { p1, p2 } = teamDisplay(m);
const sc = stateConfig[m.state];
$$renderer2.push(`<a${attr("href", `/matches/${stringify(m.id)}`)} class="group flex items-center gap-4 rounded-lg border border-green-500/20 bg-surface-800 p-4 transition-all hover:border-green-500/40 hover:bg-surface-700"><div class="flex flex-1 items-center gap-3">`);
if (p1?.team.avatarUrl) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", p1.team.avatarUrl)} alt="" class="h-8 w-8 rounded-full"/>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <span class="text-sm font-600">${escape_html(p1?.team.name ?? "?")}</span></div> <div class="flex items-center gap-3"><span class="text-xl font-800 tabular-nums">${escape_html(p1?.score ?? 0)}</span> <span class="text-xs font-600 text-text-secondary">vs</span> <span class="text-xl font-800 tabular-nums">${escape_html(p2?.score ?? 0)}</span></div> <div class="flex flex-1 items-center justify-end gap-3"><span class="text-sm font-600">${escape_html(p2?.team.name ?? "?")}</span> `);
if (p2?.team.avatarUrl) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", p2.team.avatarUrl)} alt="" class="h-8 w-8 rounded-full"/>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div> <span${attr_class(`flex items-center gap-1.5 rounded border px-2 py-0.5 text-xs font-500 ${stringify(sc?.color ?? "border-border")}`)}>`);
if (sc?.dot) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<span${attr_class(`h-1.5 w-1.5 rounded-full ${stringify(sc.dot)}`)}></span>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> ${escape_html(sc?.label ?? m.state)}</span></a>`);
}
$$renderer2.push(`<!--]--></div></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <div class="mt-6">`);
if (liveMatches().length > 0) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<h2 class="text-sm font-600 text-text-secondary">Past Matches</h2>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <div class="mt-3 flex flex-col gap-2">`);
const each_array_5 = ensure_array_like(recentMatches());
if (each_array_5.length !== 0) {
$$renderer2.push("<!--[-->");
for (let $$index_5 = 0, $$length = each_array_5.length; $$index_5 < $$length; $$index_5++) {
let m = each_array_5[$$index_5];
const { p1, p2 } = teamDisplay(m);
const config = m.config;
const sc = stateConfig[m.state];
$$renderer2.push(`<a${attr("href", `/matches/${stringify(m.id)}`)} class="group flex items-center gap-4 rounded-lg border border-border bg-surface-800 p-3 transition-colors hover:border-accent/30 hover:bg-surface-700"><div class="min-w-0 flex-1"><div class="flex items-center gap-2"><span class="text-sm font-600">${escape_html(p1?.team.name ?? "?")}</span> `);
if (m.state === "FINISHED") {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<span${attr_class(`text-xs font-700 tabular-nums ${stringify((p1?.score ?? 0) > (p2?.score ?? 0) ? "text-green-400" : "text-text-secondary")}`)}>${escape_html(p1?.score ?? 0)}</span> <span class="text-xs text-text-secondary">-</span> <span${attr_class(`text-xs font-700 tabular-nums ${stringify((p2?.score ?? 0) > (p1?.score ?? 0) ? "text-green-400" : "text-text-secondary")}`)}>${escape_html(p2?.score ?? 0)}</span>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<span class="text-xs text-text-secondary">vs</span>`);
}
$$renderer2.push(`<!--]--> <span class="text-sm font-600">${escape_html(p2?.team.name ?? "?")}</span></div> <p class="mt-0.5 text-xs text-text-secondary">${escape_html(m.name ? `${m.name} · ` : "")}BO${escape_html(config.bestOf)} `);
if (m.finishedAt) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`· ${escape_html(timeAgo(m.finishedAt))}`);
} else if (m.createdAt) {
$$renderer2.push("<!--[1-->");
$$renderer2.push(`· ${escape_html(timeAgo(m.createdAt))}`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></p></div> `);
if (m.state === "FINISHED" && m.winnerId) {
$$renderer2.push("<!--[-->");
const winner = m.participants.find((p) => p.teamId === m.winnerId);
$$renderer2.push(`<span class="text-xs font-500 text-green-400">🏆 ${escape_html(winner?.team.name)}</span>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> <span${attr_class(`rounded border px-2 py-0.5 text-xs font-500 ${stringify(sc?.color ?? "border-border")}`)}>${escape_html(sc?.label ?? m.state)}</span></a>`);
}
} else {
$$renderer2.push("<!--[!-->");
if (liveMatches().length === 0) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="rounded-lg border border-dashed border-border py-12 text-center"><p class="text-sm text-text-secondary">No matches yet. Create one to get started.</p></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]-->`);
}
$$renderer2.push(`<!--]--></div></div></div>`);
});
}
export {
_page as default
};

View File

@@ -0,0 +1,37 @@
import { redirect } from "@sveltejs/kit";
import { a as auth } from "../../../../chunks/auth.js";
import { d as db, p as playerRating, j as account } from "../../../../chunks/index2.js";
import { eq, and } from "drizzle-orm";
const load = async ({ locals }) => {
if (!locals.user) redirect(302, "/");
const rating = await db.query.playerRating.findFirst({
where: eq(playerRating.userId, locals.user.id)
});
const osuAccount = await db.query.account.findFirst({
where: and(eq(account.userId, locals.user.id), eq(account.providerId, "osu"))
});
return {
profile: {
id: locals.user.id,
name: locals.user.name,
email: locals.user.email,
image: locals.user.image,
role: locals.user.role ?? "player",
createdAt: locals.user.createdAt
},
rating: rating ? { elo: rating.elo, wins: rating.wins, losses: rating.losses } : { elo: 1e3, wins: 0, losses: 0 },
hasOsuLinked: !!osuAccount
};
};
const actions = {
logout: async (event) => {
await auth.api.signOut({
headers: event.request.headers
});
redirect(302, "/");
}
};
export {
actions,
load
};

View File

@@ -0,0 +1,48 @@
import { b as attr, e as escape_html, c as attr_class, s as stringify, d as derived } from "../../../../chunks/index3.js";
import "@sveltejs/kit/internal";
import "../../../../chunks/url.js";
import "../../../../chunks/utils.js";
import "@sveltejs/kit/internal/server";
import "../../../../chunks/root.js";
import "../../../../chunks/exports.js";
import "../../../../chunks/state.svelte.js";
function _page($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
let { data } = $$props;
const roleBadge = {
player: { label: "Player", color: "bg-surface-600 text-text-secondary" },
referee: { label: "Referee", color: "bg-yellow-500/20 text-yellow-400" },
admin: { label: "Admin", color: "bg-red-500/20 text-red-400" }
};
const badge = derived(() => roleBadge[data.profile.role] ?? roleBadge.player);
const winRate = derived(() => data.rating.wins + data.rating.losses > 0 ? (data.rating.wins / (data.rating.wins + data.rating.losses) * 100).toFixed(1) : "—");
$$renderer2.push(`<div class="mx-auto max-w-2xl"><h1 class="text-2xl font-700 tracking-tight">Settings</h1> <p class="mt-1 text-sm text-text-secondary">Your profile and account settings</p> <div class="mt-6 rounded-lg border border-border bg-surface-800 p-6"><div class="flex items-center gap-4">`);
if (data.profile.image) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", data.profile.image)}${attr("alt", data.profile.name)} class="h-16 w-16 rounded-full"/>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<div class="flex h-16 w-16 items-center justify-center rounded-full bg-surface-600 text-xl font-700 text-text-secondary">${escape_html(data.profile.name.charAt(0).toUpperCase())}</div>`);
}
$$renderer2.push(`<!--]--> <div class="flex-1"><div class="flex items-center gap-2"><h2 class="text-lg font-700">${escape_html(data.profile.name)}</h2> <span${attr_class(`rounded px-2 py-0.5 text-xs font-600 ${stringify(badge().color)}`)}>${escape_html(badge().label)}</span></div> <p class="mt-0.5 text-sm text-text-secondary">${escape_html(data.profile.email)}</p></div></div> <div class="mt-6 border-t border-border pt-4"><h3 class="text-xs font-600 text-text-secondary uppercase tracking-wider">Connected Accounts</h3> <div class="mt-3 flex items-center gap-3 rounded-md bg-surface-700 px-4 py-3"><span class="text-lg">🎮</span> <div class="flex-1"><p class="text-sm font-500">osu!</p> <p class="text-xs text-text-secondary">`);
if (data.hasOsuLinked) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`Connected as ${escape_html(data.profile.name)}`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`Not connected`);
}
$$renderer2.push(`<!--]--></p></div> `);
if (data.hasOsuLinked) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<span class="rounded bg-green-500/20 px-2 py-0.5 text-xs font-500 text-green-400">Linked</span>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<a href="/api/auth/osu/login" class="rounded bg-accent px-3 py-1 text-xs font-600 text-surface-900 hover:bg-accent-hover">Connect</a>`);
}
$$renderer2.push(`<!--]--></div></div></div> <div class="mt-4 rounded-lg border border-border bg-surface-800 p-6"><h3 class="text-xs font-600 text-text-secondary uppercase tracking-wider">Ranked Stats</h3> <div class="mt-4 grid grid-cols-4 gap-4"><div><p class="text-2xl font-800 tabular-nums text-accent">${escape_html(data.rating.elo)}</p> <p class="mt-1 text-xs text-text-secondary">ELO Rating</p></div> <div><p class="text-2xl font-800 tabular-nums text-green-400">${escape_html(data.rating.wins)}</p> <p class="mt-1 text-xs text-text-secondary">Wins</p></div> <div><p class="text-2xl font-800 tabular-nums text-red-400">${escape_html(data.rating.losses)}</p> <p class="mt-1 text-xs text-text-secondary">Losses</p></div> <div><p class="text-2xl font-800 tabular-nums text-text-primary">${escape_html(winRate())}${escape_html(winRate() !== "—" ? "%" : "")}</p> <p class="mt-1 text-xs text-text-secondary">Win Rate</p></div></div></div> <div class="mt-4 rounded-lg border border-border bg-surface-800 p-6"><h3 class="text-xs font-600 text-red-400 uppercase tracking-wider">Account</h3> <div class="mt-4"><form method="post" action="?/logout"><button type="submit" class="rounded-md border border-red-500/30 px-4 py-2 text-sm font-500 text-red-400 transition-colors hover:bg-red-500/10">Sign Out</button></form></div></div></div>`);
});
}
export {
_page as default
};

View File

@@ -0,0 +1,88 @@
import { d as db, c as team, t as teamMember, u as user } from "../../../../chunks/index2.js";
import { eq } from "drizzle-orm";
import { redirect } from "@sveltejs/kit";
const load = async ({ locals }) => {
if (!locals.user) redirect(302, "/");
const teams = await db.query.team.findMany({
with: {
members: true
},
orderBy: (t, { desc }) => [desc(t.createdAt)]
});
const teamsWithUsers = await Promise.all(
teams.map(async (t) => {
const membersWithUsers = await Promise.all(
t.members.map(async (m) => {
const u = await db.query.user.findFirst({
where: eq(user.id, m.userId)
});
return { ...m, user: u ? { id: u.id, name: u.name, image: u.image } : null };
})
);
return { ...t, members: membersWithUsers };
})
);
return { teams: teamsWithUsers, userId: locals.user.id };
};
const actions = {
create: async ({ request, locals }) => {
if (!locals.user) redirect(302, "/");
const form = await request.formData();
const name = form.get("name")?.toString()?.trim();
if (!name) return { error: "Team name is required" };
const [created] = await db.insert(team).values({
name,
ownerId: locals.user.id,
isPersonal: false
}).returning();
await db.insert(teamMember).values({
teamId: created.id,
userId: locals.user.id,
role: "captain"
});
return { success: true };
},
addMember: async ({ request, locals }) => {
if (!locals.user) redirect(302, "/");
const form = await request.formData();
const teamId = form.get("teamId")?.toString();
const username = form.get("username")?.toString()?.trim();
if (!teamId || !username) return { error: "Team and username are required" };
const u = await db.query.user.findFirst({
where: eq(user.name, username)
});
if (!u) return { error: `User "${username}" not found. They need to log in first.` };
const existing = await db.query.teamMember.findFirst({
where: (m, { and, eq: eq2 }) => and(eq2(m.teamId, teamId), eq2(m.userId, u.id))
});
if (existing) return { error: `${username} is already on this team` };
await db.insert(teamMember).values({
teamId,
userId: u.id,
role: "member"
});
return { success: true };
},
removeMember: async ({ request, locals }) => {
if (!locals.user) redirect(302, "/");
const form = await request.formData();
const memberId = form.get("memberId")?.toString();
if (!memberId) return { error: "Missing member ID" };
await db.delete(teamMember).where(eq(teamMember.id, memberId));
return { success: true };
},
deleteTeam: async ({ request, locals }) => {
if (!locals.user) redirect(302, "/");
const form = await request.formData();
const teamId = form.get("teamId")?.toString();
if (!teamId) return { error: "Missing team ID" };
const t = await db.query.team.findFirst({ where: eq(team.id, teamId) });
if (!t || t.ownerId !== locals.user.id) return { error: "Not authorized" };
await db.delete(team).where(eq(team.id, teamId));
return { success: true };
}
};
export {
actions,
load
};

View File

@@ -0,0 +1,138 @@
import { e as escape_html, a as ensure_array_like, b as attr, c as attr_class, s as stringify, d as derived } from "../../../../chunks/index3.js";
import "@sveltejs/kit/internal";
import "../../../../chunks/url.js";
import "../../../../chunks/utils.js";
import "@sveltejs/kit/internal/server";
import "../../../../chunks/root.js";
import "../../../../chunks/exports.js";
import "../../../../chunks/state.svelte.js";
function _page($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
let { data } = $$props;
let expandedTeam = null;
let addingMemberTo = null;
let memberUsername = "";
const myTeams = derived(() => data.teams.filter((t) => t.members.some((m) => m.userId === data.userId)));
const otherTeams = derived(() => data.teams.filter((t) => !t.members.some((m) => m.userId === data.userId)));
function isOwner(t) {
return t.ownerId === data.userId;
}
$$renderer2.push(`<div class="mx-auto max-w-4xl"><div class="flex items-center justify-between"><div><h1 class="text-2xl font-700 tracking-tight">Teams</h1> <p class="mt-1 text-sm text-text-secondary">${escape_html(data.teams.length)} team${escape_html(data.teams.length !== 1 ? "s" : "")}</p></div> <button class="rounded-md bg-accent px-4 py-2 text-sm font-600 text-surface-900 transition-colors hover:bg-accent-hover">${escape_html("New Team")}</button></div> `);
{
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
{
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (myTeams().length > 0) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="mt-6"><h2 class="text-sm font-600 text-text-secondary">My Teams</h2> <div class="mt-3 flex flex-col gap-3"><!--[-->`);
const each_array = ensure_array_like(myTeams());
for (let $$index_1 = 0, $$length = each_array.length; $$index_1 < $$length; $$index_1++) {
let t = each_array[$$index_1];
$$renderer2.push(`<div class="rounded-lg border border-border bg-surface-800 transition-colors"><button class="flex w-full items-center gap-4 p-4 text-left transition-colors hover:bg-surface-700">`);
if (t.avatarUrl) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", t.avatarUrl)} alt="" class="h-10 w-10 rounded-full"/>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<div class="flex h-10 w-10 items-center justify-center rounded-full bg-surface-600 text-sm font-700 text-text-secondary">${escape_html(t.name.charAt(0).toUpperCase())}</div>`);
}
$$renderer2.push(`<!--]--> <div class="flex-1"><div class="flex items-center gap-2"><span class="text-sm font-600">${escape_html(t.name)}</span> `);
if (t.isPersonal) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<span class="rounded bg-surface-600 px-1.5 py-0.5 text-[10px] font-500 text-text-secondary">solo</span>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div> <p class="mt-0.5 text-xs text-text-secondary">${escape_html(t.members.length)} member${escape_html(t.members.length !== 1 ? "s" : "")}</p></div> <span${attr_class(`text-sm text-text-secondary transition-transform ${stringify(expandedTeam === t.id ? "rotate-90" : "")}`)}>›</span></button> `);
if (expandedTeam === t.id) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="border-t border-border px-4 pb-4 pt-3"><div class="flex flex-col gap-2"><!--[-->`);
const each_array_1 = ensure_array_like(t.members);
for (let $$index = 0, $$length2 = each_array_1.length; $$index < $$length2; $$index++) {
let member = each_array_1[$$index];
$$renderer2.push(`<div class="flex items-center gap-3 rounded-md bg-surface-700 px-3 py-2">`);
if (member.user?.image) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", member.user.image)} alt="" class="h-6 w-6 rounded-full"/>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<div class="h-6 w-6 rounded-full bg-surface-600"></div>`);
}
$$renderer2.push(`<!--]--> <span class="flex-1 text-sm">${escape_html(member.user?.name ?? "Unknown")}</span> <span class="text-xs text-text-secondary">${escape_html(member.role)}</span> `);
if (isOwner(t) && member.userId !== data.userId) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<form method="post" action="?/removeMember"><input type="hidden" name="memberId"${attr("value", member.id)}/> <button type="submit" class="text-xs text-red-400 opacity-50 transition-opacity hover:opacity-100">×</button></form>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div>`);
}
$$renderer2.push(`<!--]--></div> `);
if (isOwner(t) && !t.isPersonal) {
$$renderer2.push("<!--[-->");
if (addingMemberTo === t.id) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<form method="post" action="?/addMember" class="mt-3 flex gap-2"><input type="hidden" name="teamId"${attr("value", t.id)}/> <input type="text" name="username"${attr("value", memberUsername)} placeholder="osu! username" required="" class="flex-1 rounded-md border border-border bg-surface-600 px-3 py-1.5 text-sm text-text-primary placeholder:text-text-secondary/50 focus:border-accent focus:outline-none"/> <button type="submit" class="rounded-md bg-accent px-3 py-1.5 text-xs font-600 text-surface-900 hover:bg-accent-hover">Add</button> <button type="button" class="rounded-md border border-border px-3 py-1.5 text-xs text-text-secondary hover:bg-surface-600">Cancel</button></form>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<button class="mt-3 w-full rounded-md border border-dashed border-border py-2 text-xs text-text-secondary transition-colors hover:border-accent/40 hover:text-accent">+ Add Member</button>`);
}
$$renderer2.push(`<!--]-->`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (isOwner(t) && !t.isPersonal) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<form method="post" action="?/deleteTeam"><input type="hidden" name="teamId"${attr("value", t.id)}/> <button type="submit" class="mt-3 text-xs text-red-400 opacity-50 transition-opacity hover:opacity-100">Delete team</button></form>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div>`);
}
$$renderer2.push(`<!--]--></div></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (otherTeams().length > 0) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="mt-6"><h2 class="text-sm font-600 text-text-secondary">Other Teams</h2> <div class="mt-3 flex flex-col gap-2"><!--[-->`);
const each_array_2 = ensure_array_like(otherTeams());
for (let $$index_2 = 0, $$length = each_array_2.length; $$index_2 < $$length; $$index_2++) {
let t = each_array_2[$$index_2];
$$renderer2.push(`<div class="flex items-center gap-4 rounded-lg border border-border bg-surface-800 p-3">`);
if (t.avatarUrl) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<img${attr("src", t.avatarUrl)} alt="" class="h-8 w-8 rounded-full"/>`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`<div class="flex h-8 w-8 items-center justify-center rounded-full bg-surface-600 text-xs font-700 text-text-secondary">${escape_html(t.name.charAt(0).toUpperCase())}</div>`);
}
$$renderer2.push(`<!--]--> <div class="flex-1"><span class="text-sm font-600">${escape_html(t.name)}</span> <p class="text-xs text-text-secondary">${escape_html(t.members.length)} member${escape_html(t.members.length !== 1 ? "s" : "")}</p></div></div>`);
}
$$renderer2.push(`<!--]--></div></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--> `);
if (data.teams.length === 0) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`<div class="mt-6 rounded-lg border border-dashed border-border py-12 text-center"><p class="text-sm text-text-secondary">No teams yet. Your personal team is created when you sign in.</p></div>`);
} else {
$$renderer2.push("<!--[!-->");
}
$$renderer2.push(`<!--]--></div>`);
});
}
export {
_page as default
};

View File

@@ -0,0 +1,25 @@
import { e as escape_html } from "../../chunks/index3.js";
import "clsx";
import { p as page } from "../../chunks/index4.js";
function _error($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
$$renderer2.push(`<div class="flex min-h-dvh items-center justify-center bg-surface-900"><div class="text-center"><p class="text-6xl font-800 text-accent">${escape_html(page.status)}</p> <h1 class="mt-4 text-xl font-700 text-text-primary">`);
if (page.status === 404) {
$$renderer2.push("<!--[-->");
$$renderer2.push(`Page not found`);
} else if (page.status === 403) {
$$renderer2.push("<!--[1-->");
$$renderer2.push(`Access denied`);
} else if (page.status === 401) {
$$renderer2.push("<!--[2-->");
$$renderer2.push(`Not logged in`);
} else {
$$renderer2.push("<!--[!-->");
$$renderer2.push(`Something went wrong`);
}
$$renderer2.push(`<!--]--></h1> <p class="mt-2 text-sm text-text-secondary">${escape_html(page.error?.message ?? "An unexpected error occurred.")}</p> <a href="/" class="mt-6 inline-block rounded-md bg-accent px-5 py-2.5 text-sm font-600 text-surface-900 transition-colors hover:bg-accent-hover">Back to Dashboard</a></div></div>`);
});
}
export {
_error as default
};

View File

@@ -0,0 +1,31 @@
import { b as attr } from "../../../chunks/index3.js";
import { i as initial_base, b as base } from "../../../chunks/server.js";
import { r as resolve_route } from "../../../chunks/routing.js";
import "../../../chunks/url.js";
import { try_get_request_store } from "@sveltejs/kit/internal/server";
import "../../../chunks/root.js";
function resolve(id, params) {
const resolved = resolve_route(
id,
/** @type {Record<string, string>} */
params
);
{
const store = try_get_request_store();
if (store && !store.state.prerendering?.fallback) {
const after_base = store.event.url.pathname.slice(initial_base.length);
const segments = after_base.split("/").slice(2);
const prefix = segments.map(() => "..").join("/") || ".";
return prefix + resolved;
}
}
return base + resolved;
}
function _page($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
$$renderer2.push(`<a${attr("href", resolve("/demo/better-auth"))}>better-auth</a>`);
});
}
export {
_page as default
};

View File

@@ -0,0 +1,20 @@
import { redirect } from "@sveltejs/kit";
import { a as auth } from "../../../../chunks/auth.js";
const load = async (event) => {
if (!event.locals.user) {
return redirect(302, "/demo/better-auth/login");
}
return { user: event.locals.user };
};
const actions = {
signOut: async (event) => {
await auth.api.signOut({
headers: event.request.headers
});
return redirect(302, "/demo/better-auth/login");
}
};
export {
actions,
load
};

View File

@@ -0,0 +1,18 @@
import { e as escape_html } from "../../../../chunks/index3.js";
import "clsx";
import "@sveltejs/kit/internal";
import "../../../../chunks/url.js";
import "../../../../chunks/utils.js";
import "@sveltejs/kit/internal/server";
import "../../../../chunks/root.js";
import "../../../../chunks/exports.js";
import "../../../../chunks/state.svelte.js";
function _page($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
let { data } = $$props;
$$renderer2.push(`<h1>Hi, ${escape_html(data.user.name)}!</h1> <p>Your user ID is ${escape_html(data.user.id)}.</p> <form method="post" action="?/signOut"><button class="rounded-md bg-blue-600 px-4 py-2 text-white transition hover:bg-blue-700">Sign out</button></form>`);
});
}
export {
_page as default
};

View File

@@ -0,0 +1,75 @@
import { redirect, fail } from "@sveltejs/kit";
import { a as auth } from "../../../../../chunks/auth.js";
import "@better-auth/core/env";
import "@better-auth/core/utils";
import { APIError } from "better-call";
import "@better-auth/core/api";
const load = async (event) => {
if (event.locals.user) {
return redirect(302, "/demo/better-auth");
}
return {};
};
const actions = {
signInEmail: async (event) => {
const formData = await event.request.formData();
const email = formData.get("email")?.toString() ?? "";
const password = formData.get("password")?.toString() ?? "";
try {
await auth.api.signInEmail({
body: {
email,
password,
callbackURL: "/auth/verification-success"
}
});
} catch (error) {
if (error instanceof APIError) {
return fail(400, { message: error.message || "Signin failed" });
}
return fail(500, { message: "Unexpected error" });
}
return redirect(302, "/demo/better-auth");
},
signUpEmail: async (event) => {
const formData = await event.request.formData();
const email = formData.get("email")?.toString() ?? "";
const password = formData.get("password")?.toString() ?? "";
const name = formData.get("name")?.toString() ?? "";
try {
await auth.api.signUpEmail({
body: {
email,
password,
name,
callbackURL: "/auth/verification-success"
}
});
} catch (error) {
if (error instanceof APIError) {
return fail(400, { message: error.message || "Registration failed" });
}
return fail(500, { message: "Unexpected error" });
}
return redirect(302, "/demo/better-auth");
},
signInSocial: async (event) => {
const formData = await event.request.formData();
const provider = formData.get("provider")?.toString() ?? "osu";
const callbackURL = formData.get("callbackURL")?.toString() ?? "/demo/better-auth";
const result = await auth.api.signInSocial({
body: {
provider,
callbackURL
}
});
if (result.url) {
return redirect(302, result.url);
}
return fail(400, { message: "Social sign-in failed" });
}
};
export {
actions,
load
};

View File

@@ -0,0 +1,18 @@
import { e as escape_html } from "../../../../../chunks/index3.js";
import "clsx";
import "@sveltejs/kit/internal";
import "../../../../../chunks/url.js";
import "../../../../../chunks/utils.js";
import "@sveltejs/kit/internal/server";
import "../../../../../chunks/root.js";
import "../../../../../chunks/exports.js";
import "../../../../../chunks/state.svelte.js";
function _page($$renderer, $$props) {
$$renderer.component(($$renderer2) => {
let { form } = $$props;
$$renderer2.push(`<h1>Login</h1> <form method="post" action="?/signInEmail"><label>Email <input type="email" name="email" class="mt-1 rounded-md border border-gray-300 bg-white px-3 py-2 shadow-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none"/></label> <label>Password <input type="password" name="password" class="mt-1 rounded-md border border-gray-300 bg-white px-3 py-2 shadow-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none"/></label> <label>Name (for registration) <input name="name" class="mt-1 rounded-md border border-gray-300 bg-white px-3 py-2 shadow-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none"/></label> <button class="rounded-md bg-blue-600 px-4 py-2 text-white transition hover:bg-blue-700">Login</button> <button formaction="?/signUpEmail" class="rounded-md bg-blue-600 px-4 py-2 text-white transition hover:bg-blue-700">Register</button></form> <p class="text-red-500">${escape_html(form?.message ?? "")}</p> <hr class="my-4"/> <form method="post" action="?/signInSocial"><input type="hidden" name="provider" value="osu"/> <input type="hidden" name="callbackURL" value="/demo/better-auth"/> <button class="rounded-md bg-blue-600 px-4 py-2 text-white transition hover:bg-blue-700">Sign in with osu!</button></form>`);
});
}
export {
_page as default
};

View File

@@ -0,0 +1,16 @@
import { redirect } from "@sveltejs/kit";
import { a as auth } from "../../../chunks/auth.js";
const load = async (event) => {
if (event.locals.user) redirect(302, "/");
const result = await auth.api.signInSocial({
body: {
provider: "osu",
callbackURL: "/"
}
});
if (result.url) redirect(302, result.url);
return {};
};
export {
load
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
import "./chunks/root.js";
import { s, a } from "./chunks/environment.js";
import { s as s2 } from "./chunks/server.js";
import { g, o, a as a2, s as s3 } from "./chunks/internal.js";
import { s as s4, a as a3 } from "./chunks/shared-server.js";
export {
g as get_hooks,
o as options,
s2 as set_assets,
s as set_building,
a2 as set_manifest,
a as set_prerendering,
s4 as set_private_env,
a3 as set_public_env,
s3 as set_read_implementation
};

View File

@@ -0,0 +1,226 @@
export const manifest = (() => {
function __memo(fn) {
let value;
return () => value ??= (value = fn());
}
return {
appDir: "_app",
appPath: "_app",
assets: new Set(["android-chrome-192x192.png","android-chrome-512x512.png","apple-touch-icon.png","favicon-16x16.png","favicon-32x32.png","favicon.ico","robots.txt","site.webmanifest"]),
mimeTypes: {".png":"image/png",".txt":"text/plain",".webmanifest":"application/manifest+json"},
_: {
client: {start:"_app/immutable/entry/start.Df1GVxyt.js",app:"_app/immutable/entry/app.DL20j9gb.js",imports:["_app/immutable/entry/start.Df1GVxyt.js","_app/immutable/chunks/BkIq08el.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/DAtZQVjv.js","_app/immutable/entry/app.DL20j9gb.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/BQKoxf2Q.js","_app/immutable/chunks/kALFGdUG.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
nodes: [
__memo(() => import('./nodes/0.js')),
__memo(() => import('./nodes/1.js')),
__memo(() => import('./nodes/2.js')),
__memo(() => import('./nodes/3.js')),
__memo(() => import('./nodes/4.js')),
__memo(() => import('./nodes/5.js')),
__memo(() => import('./nodes/6.js')),
__memo(() => import('./nodes/7.js')),
__memo(() => import('./nodes/8.js')),
__memo(() => import('./nodes/9.js')),
__memo(() => import('./nodes/10.js')),
__memo(() => import('./nodes/11.js')),
__memo(() => import('./nodes/12.js')),
__memo(() => import('./nodes/13.js')),
__memo(() => import('./nodes/14.js'))
],
remotes: {
},
routes: [
{
id: "/(app)",
pattern: /^\/?$/,
params: [],
page: { layouts: [0,2,], errors: [1,,], leaf: 3 },
endpoint: null
},
{
id: "/(app)/admin",
pattern: /^\/admin\/?$/,
params: [],
page: { layouts: [0,2,], errors: [1,,], leaf: 4 },
endpoint: null
},
{
id: "/api/health",
pattern: /^\/api\/health\/?$/,
params: [],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/health/_server.ts.js'))
},
{
id: "/api/mappools",
pattern: /^\/api\/mappools\/?$/,
params: [],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/mappools/_server.ts.js'))
},
{
id: "/api/mappools/[id]",
pattern: /^\/api\/mappools\/([^/]+?)\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/mappools/_id_/_server.ts.js'))
},
{
id: "/api/mappools/[id]/slots",
pattern: /^\/api\/mappools\/([^/]+?)\/slots\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/mappools/_id_/slots/_server.ts.js'))
},
{
id: "/api/mappools/[id]/slots/[slotId]",
pattern: /^\/api\/mappools\/([^/]+?)\/slots\/([^/]+?)\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false},{"name":"slotId","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/mappools/_id_/slots/_slotId_/_server.ts.js'))
},
{
id: "/api/matches",
pattern: /^\/api\/matches\/?$/,
params: [],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_server.ts.js'))
},
{
id: "/api/matches/[id]",
pattern: /^\/api\/matches\/([^/]+?)\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_id_/_server.ts.js'))
},
{
id: "/api/matches/[id]/lobby",
pattern: /^\/api\/matches\/([^/]+?)\/lobby\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_id_/lobby/_server.ts.js'))
},
{
id: "/api/matches/[id]/pick",
pattern: /^\/api\/matches\/([^/]+?)\/pick\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_id_/pick/_server.ts.js'))
},
{
id: "/api/matches/[id]/rolling",
pattern: /^\/api\/matches\/([^/]+?)\/rolling\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_id_/rolling/_server.ts.js'))
},
{
id: "/api/matches/[id]/roll",
pattern: /^\/api\/matches\/([^/]+?)\/roll\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_id_/roll/_server.ts.js'))
},
{
id: "/api/matches/[id]/score",
pattern: /^\/api\/matches\/([^/]+?)\/score\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_id_/score/_server.ts.js'))
},
{
id: "/api/osu/beatmap/[id]",
pattern: /^\/api\/osu\/beatmap\/([^/]+?)\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/osu/beatmap/_id_/_server.ts.js'))
},
{
id: "/api/queue",
pattern: /^\/api\/queue\/?$/,
params: [],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/queue/_server.ts.js'))
},
{
id: "/demo",
pattern: /^\/demo\/?$/,
params: [],
page: { layouts: [0,], errors: [1,], leaf: 11 },
endpoint: null
},
{
id: "/demo/better-auth",
pattern: /^\/demo\/better-auth\/?$/,
params: [],
page: { layouts: [0,], errors: [1,], leaf: 12 },
endpoint: null
},
{
id: "/demo/better-auth/login",
pattern: /^\/demo\/better-auth\/login\/?$/,
params: [],
page: { layouts: [0,], errors: [1,], leaf: 13 },
endpoint: null
},
{
id: "/login",
pattern: /^\/login\/?$/,
params: [],
page: { layouts: [0,], errors: [1,], leaf: 14 },
endpoint: null
},
{
id: "/(app)/mappools",
pattern: /^\/mappools\/?$/,
params: [],
page: { layouts: [0,2,], errors: [1,,], leaf: 5 },
endpoint: null
},
{
id: "/(app)/mappools/[id]",
pattern: /^\/mappools\/([^/]+?)\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: { layouts: [0,2,], errors: [1,,], leaf: 6 },
endpoint: null
},
{
id: "/(app)/matches",
pattern: /^\/matches\/?$/,
params: [],
page: { layouts: [0,2,], errors: [1,,], leaf: 7 },
endpoint: null
},
{
id: "/(app)/matches/[id]",
pattern: /^\/matches\/([^/]+?)\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: { layouts: [0,2,], errors: [1,,], leaf: 8 },
endpoint: null
},
{
id: "/(app)/settings",
pattern: /^\/settings\/?$/,
params: [],
page: { layouts: [0,2,], errors: [1,,], leaf: 9 },
endpoint: null
},
{
id: "/(app)/teams",
pattern: /^\/teams\/?$/,
params: [],
page: { layouts: [0,2,], errors: [1,,], leaf: 10 },
endpoint: null
}
],
prerendered_routes: new Set([]),
matchers: async () => {
return { };
},
server_assets: {}
}
}
})();

View File

@@ -0,0 +1,230 @@
export const manifest = (() => {
function __memo(fn) {
let value;
return () => value ??= (value = fn());
}
return {
appDir: "_app",
appPath: "_app",
assets: new Set(["android-chrome-192x192.png","android-chrome-512x512.png","apple-touch-icon.png","favicon-16x16.png","favicon-32x32.png","favicon.ico","robots.txt","site.webmanifest"]),
mimeTypes: {".png":"image/png",".txt":"text/plain",".webmanifest":"application/manifest+json"},
_: {
client: {start:"_app/immutable/entry/start.Df1GVxyt.js",app:"_app/immutable/entry/app.DL20j9gb.js",imports:["_app/immutable/entry/start.Df1GVxyt.js","_app/immutable/chunks/BkIq08el.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/DAtZQVjv.js","_app/immutable/entry/app.DL20j9gb.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/BQKoxf2Q.js","_app/immutable/chunks/kALFGdUG.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
nodes: [
__memo(() => import('./nodes/0.js')),
__memo(() => import('./nodes/1.js')),
__memo(() => import('./nodes/2.js')),
__memo(() => import('./nodes/3.js')),
__memo(() => import('./nodes/4.js')),
__memo(() => import('./nodes/5.js')),
__memo(() => import('./nodes/6.js')),
__memo(() => import('./nodes/7.js')),
__memo(() => import('./nodes/8.js')),
__memo(() => import('./nodes/9.js')),
__memo(() => import('./nodes/10.js')),
__memo(() => import('./nodes/11.js')),
__memo(() => import('./nodes/12.js')),
__memo(() => import('./nodes/13.js')),
__memo(() => import('./nodes/14.js'))
],
remotes: {
},
routes: [
{
id: "/(app)",
pattern: /^\/?$/,
params: [],
page: { layouts: [0,2,], errors: [1,,], leaf: 3 },
endpoint: null
},
{
id: "/(app)/admin",
pattern: /^\/admin\/?$/,
params: [],
page: { layouts: [0,2,], errors: [1,,], leaf: 4 },
endpoint: null
},
{
id: "/api/health",
pattern: /^\/api\/health\/?$/,
params: [],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/health/_server.ts.js'))
},
{
id: "/api/mappools",
pattern: /^\/api\/mappools\/?$/,
params: [],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/mappools/_server.ts.js'))
},
{
id: "/api/mappools/[id]",
pattern: /^\/api\/mappools\/([^/]+?)\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/mappools/_id_/_server.ts.js'))
},
{
id: "/api/mappools/[id]/slots",
pattern: /^\/api\/mappools\/([^/]+?)\/slots\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/mappools/_id_/slots/_server.ts.js'))
},
{
id: "/api/mappools/[id]/slots/[slotId]",
pattern: /^\/api\/mappools\/([^/]+?)\/slots\/([^/]+?)\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false},{"name":"slotId","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/mappools/_id_/slots/_slotId_/_server.ts.js'))
},
{
id: "/api/matches",
pattern: /^\/api\/matches\/?$/,
params: [],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_server.ts.js'))
},
{
id: "/api/matches/[id]",
pattern: /^\/api\/matches\/([^/]+?)\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_id_/_server.ts.js'))
},
{
id: "/api/matches/[id]/lobby",
pattern: /^\/api\/matches\/([^/]+?)\/lobby\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_id_/lobby/_server.ts.js'))
},
{
id: "/api/matches/[id]/pick",
pattern: /^\/api\/matches\/([^/]+?)\/pick\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_id_/pick/_server.ts.js'))
},
{
id: "/api/matches/[id]/rolling",
pattern: /^\/api\/matches\/([^/]+?)\/rolling\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_id_/rolling/_server.ts.js'))
},
{
id: "/api/matches/[id]/roll",
pattern: /^\/api\/matches\/([^/]+?)\/roll\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_id_/roll/_server.ts.js'))
},
{
id: "/api/matches/[id]/score",
pattern: /^\/api\/matches\/([^/]+?)\/score\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/matches/_id_/score/_server.ts.js'))
},
{
id: "/api/osu/beatmap/[id]",
pattern: /^\/api\/osu\/beatmap\/([^/]+?)\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/osu/beatmap/_id_/_server.ts.js'))
},
{
id: "/api/queue",
pattern: /^\/api\/queue\/?$/,
params: [],
page: null,
endpoint: __memo(() => import('./entries/endpoints/api/queue/_server.ts.js'))
},
{
id: "/demo",
pattern: /^\/demo\/?$/,
params: [],
page: { layouts: [0,], errors: [1,], leaf: 11 },
endpoint: null
},
{
id: "/demo/better-auth",
pattern: /^\/demo\/better-auth\/?$/,
params: [],
page: { layouts: [0,], errors: [1,], leaf: 12 },
endpoint: null
},
{
id: "/demo/better-auth/login",
pattern: /^\/demo\/better-auth\/login\/?$/,
params: [],
page: { layouts: [0,], errors: [1,], leaf: 13 },
endpoint: null
},
{
id: "/login",
pattern: /^\/login\/?$/,
params: [],
page: { layouts: [0,], errors: [1,], leaf: 14 },
endpoint: null
},
{
id: "/(app)/mappools",
pattern: /^\/mappools\/?$/,
params: [],
page: { layouts: [0,2,], errors: [1,,], leaf: 5 },
endpoint: null
},
{
id: "/(app)/mappools/[id]",
pattern: /^\/mappools\/([^/]+?)\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: { layouts: [0,2,], errors: [1,,], leaf: 6 },
endpoint: null
},
{
id: "/(app)/matches",
pattern: /^\/matches\/?$/,
params: [],
page: { layouts: [0,2,], errors: [1,,], leaf: 7 },
endpoint: null
},
{
id: "/(app)/matches/[id]",
pattern: /^\/matches\/([^/]+?)\/?$/,
params: [{"name":"id","optional":false,"rest":false,"chained":false}],
page: { layouts: [0,2,], errors: [1,,], leaf: 8 },
endpoint: null
},
{
id: "/(app)/settings",
pattern: /^\/settings\/?$/,
params: [],
page: { layouts: [0,2,], errors: [1,,], leaf: 9 },
endpoint: null
},
{
id: "/(app)/teams",
pattern: /^\/teams\/?$/,
params: [],
page: { layouts: [0,2,], errors: [1,,], leaf: 10 },
endpoint: null
}
],
prerendered_routes: new Set([]),
matchers: async () => {
return { };
},
server_assets: {}
}
}
})();
export const prerendered = new Set([]);
export const base = "";

View File

@@ -0,0 +1,8 @@
export const index = 0;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/fallbacks/layout.svelte.js')).default;
export const imports = ["_app/immutable/nodes/0.9C686m9W.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/CyUoLS3q.js","_app/immutable/chunks/kALFGdUG.js"];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,8 @@
export const index = 1;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/pages/_error.svelte.js')).default;
export const imports = ["_app/immutable/nodes/1.RyK1bdTz.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/TpZZa089.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/BQKoxf2Q.js","_app/immutable/chunks/kALFGdUG.js","_app/immutable/chunks/D2SGgx9j.js","_app/immutable/chunks/DAtZQVjv.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/BkIq08el.js"];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,10 @@
import * as server from '../entries/pages/(app)/teams/_page.server.ts.js';
export const index = 10;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/pages/(app)/teams/_page.svelte.js')).default;
export { server };
export const server_id = "src/routes/(app)/teams/+page.server.ts";
export const imports = ["_app/immutable/nodes/10.BPlEN6_G.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/BQKoxf2Q.js","_app/immutable/chunks/kALFGdUG.js","_app/immutable/chunks/BLQQas77.js","_app/immutable/chunks/BAocuFgQ.js","_app/immutable/chunks/BkIq08el.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/DAtZQVjv.js","_app/immutable/chunks/BnX5ZnVA.js","_app/immutable/chunks/BqOsL1Vv.js","_app/immutable/chunks/CAkKRSSs.js"];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,8 @@
export const index = 11;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/pages/demo/_page.svelte.js')).default;
export const imports = ["_app/immutable/nodes/11.DR1Vz7m0.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/TpZZa089.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/BnX5ZnVA.js","_app/immutable/chunks/DAtZQVjv.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/DoLu9QLy.js"];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,10 @@
import * as server from '../entries/pages/demo/better-auth/_page.server.ts.js';
export const index = 12;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/pages/demo/better-auth/_page.svelte.js')).default;
export { server };
export const server_id = "src/routes/demo/better-auth/+page.server.ts";
export const imports = ["_app/immutable/nodes/12.C9UZWAjJ.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/BAocuFgQ.js","_app/immutable/chunks/BkIq08el.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/DAtZQVjv.js"];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,10 @@
import * as server from '../entries/pages/demo/better-auth/login/_page.server.ts.js';
export const index = 13;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/pages/demo/better-auth/login/_page.svelte.js')).default;
export { server };
export const server_id = "src/routes/demo/better-auth/login/+page.server.ts";
export const imports = ["_app/immutable/nodes/13.CyZ4e6yK.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/BAocuFgQ.js","_app/immutable/chunks/BkIq08el.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/DAtZQVjv.js"];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,8 @@
import * as server from '../entries/pages/login/_page.server.ts.js';
export const index = 14;
export { server };
export const server_id = "src/routes/login/+page.server.ts";
export const imports = [];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,10 @@
import * as server from '../entries/pages/(app)/_layout.server.ts.js';
export const index = 2;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/pages/(app)/_layout.svelte.js')).default;
export { server };
export const server_id = "src/routes/(app)/+layout.server.ts";
export const imports = ["_app/immutable/nodes/2.BsR2_q_w.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/CyUoLS3q.js","_app/immutable/chunks/kALFGdUG.js","_app/immutable/chunks/BQKoxf2Q.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/BLQQas77.js","_app/immutable/chunks/BnX5ZnVA.js","_app/immutable/chunks/BqOsL1Vv.js","_app/immutable/chunks/D2SGgx9j.js","_app/immutable/chunks/DAtZQVjv.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/BkIq08el.js","_app/immutable/chunks/BAocuFgQ.js"];
export const stylesheets = ["_app/immutable/assets/2.Dv2no-8m.css"];
export const fonts = [];

View File

@@ -0,0 +1,10 @@
import * as server from '../entries/pages/(app)/_page.server.ts.js';
export const index = 3;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/pages/(app)/_page.svelte.js')).default;
export { server };
export const server_id = "src/routes/(app)/+page.server.ts";
export const imports = ["_app/immutable/nodes/3.CMuy9Bx3.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/BQKoxf2Q.js","_app/immutable/chunks/kALFGdUG.js","_app/immutable/chunks/BLQQas77.js","_app/immutable/chunks/BnX5ZnVA.js","_app/immutable/chunks/BqOsL1Vv.js"];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,10 @@
import * as server from '../entries/pages/(app)/admin/_page.server.ts.js';
export const index = 4;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/pages/(app)/admin/_page.svelte.js')).default;
export { server };
export const server_id = "src/routes/(app)/admin/+page.server.ts";
export const imports = ["_app/immutable/nodes/4.BdC-uDW-.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/BQKoxf2Q.js","_app/immutable/chunks/kALFGdUG.js","_app/immutable/chunks/BLQQas77.js","_app/immutable/chunks/BAocuFgQ.js","_app/immutable/chunks/BkIq08el.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/DAtZQVjv.js","_app/immutable/chunks/BnX5ZnVA.js","_app/immutable/chunks/BqOsL1Vv.js","_app/immutable/chunks/Cy2QBcXt.js"];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,10 @@
import * as server from '../entries/pages/(app)/mappools/_page.server.ts.js';
export const index = 5;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/pages/(app)/mappools/_page.svelte.js')).default;
export { server };
export const server_id = "src/routes/(app)/mappools/+page.server.ts";
export const imports = ["_app/immutable/nodes/5.CyqZcxti.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/BQKoxf2Q.js","_app/immutable/chunks/kALFGdUG.js","_app/immutable/chunks/BLQQas77.js","_app/immutable/chunks/BAocuFgQ.js","_app/immutable/chunks/BkIq08el.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/DAtZQVjv.js","_app/immutable/chunks/BnX5ZnVA.js"];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,10 @@
import * as server from '../entries/pages/(app)/mappools/_id_/_page.server.ts.js';
export const index = 6;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/pages/(app)/mappools/_id_/_page.svelte.js')).default;
export { server };
export const server_id = "src/routes/(app)/mappools/[id]/+page.server.ts";
export const imports = ["_app/immutable/nodes/6.CEe0czaO.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/BQKoxf2Q.js","_app/immutable/chunks/kALFGdUG.js","_app/immutable/chunks/BLQQas77.js","_app/immutable/chunks/BAocuFgQ.js","_app/immutable/chunks/BkIq08el.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/DAtZQVjv.js","_app/immutable/chunks/BnX5ZnVA.js","_app/immutable/chunks/BqOsL1Vv.js","_app/immutable/chunks/CAkKRSSs.js","_app/immutable/chunks/Cy2QBcXt.js"];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,10 @@
import * as server from '../entries/pages/(app)/matches/_page.server.ts.js';
export const index = 7;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/pages/(app)/matches/_page.svelte.js')).default;
export { server };
export const server_id = "src/routes/(app)/matches/+page.server.ts";
export const imports = ["_app/immutable/nodes/7._nuD3LlN.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/BQKoxf2Q.js","_app/immutable/chunks/kALFGdUG.js","_app/immutable/chunks/BLQQas77.js","_app/immutable/chunks/BAocuFgQ.js","_app/immutable/chunks/BkIq08el.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/DAtZQVjv.js","_app/immutable/chunks/BnX5ZnVA.js","_app/immutable/chunks/BqOsL1Vv.js"];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,10 @@
import * as server from '../entries/pages/(app)/matches/_id_/_page.server.ts.js';
export const index = 8;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/pages/(app)/matches/_id_/_page.svelte.js')).default;
export { server };
export const server_id = "src/routes/(app)/matches/[id]/+page.server.ts";
export const imports = ["_app/immutable/nodes/8.CkbqikZq.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/BQKoxf2Q.js","_app/immutable/chunks/kALFGdUG.js","_app/immutable/chunks/BLQQas77.js","_app/immutable/chunks/BAocuFgQ.js","_app/immutable/chunks/BkIq08el.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/DAtZQVjv.js","_app/immutable/chunks/BnX5ZnVA.js","_app/immutable/chunks/BqOsL1Vv.js"];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,10 @@
import * as server from '../entries/pages/(app)/settings/_page.server.ts.js';
export const index = 9;
let component_cache;
export const component = async () => component_cache ??= (await import('../entries/pages/(app)/settings/_page.svelte.js')).default;
export { server };
export const server_id = "src/routes/(app)/settings/+page.server.ts";
export const imports = ["_app/immutable/nodes/9.BTBc_Eli.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/BxEwC6Zc.js","_app/immutable/chunks/DoLu9QLy.js","_app/immutable/chunks/BQKoxf2Q.js","_app/immutable/chunks/kALFGdUG.js","_app/immutable/chunks/BAocuFgQ.js","_app/immutable/chunks/BkIq08el.js","_app/immutable/chunks/CvGSsBh3.js","_app/immutable/chunks/DAtZQVjv.js","_app/immutable/chunks/BnX5ZnVA.js","_app/immutable/chunks/BqOsL1Vv.js"];
export const stylesheets = [];
export const fonts = [];

View File

@@ -0,0 +1,314 @@
import { get_request_store } from "@sveltejs/kit/internal/server";
import { c as create_validator, r as run_remote_function, g as get_cache, a as get_response, p as parse_remote_response } from "./chunks/query.js";
import { q } from "./chunks/query.js";
import { M as MUTATIVE_METHODS, u as create_field_proxy, v as normalize_issue, w as set_nested_value, x as flatten_issues, y as deep_set, z as stringify_remote_arg, k as stringify } from "./chunks/shared.js";
import { ValidationError } from "@sveltejs/kit/internal";
import { error, json } from "@sveltejs/kit";
import { D as DEV } from "./chunks/false.js";
import { b as base, c as app_dir } from "./chunks/server.js";
// @__NO_SIDE_EFFECTS__
function command(validate_or_fn, maybe_fn) {
const fn = maybe_fn ?? validate_or_fn;
const validate = create_validator(validate_or_fn, maybe_fn);
const __ = { type: "command", id: "", name: "" };
const wrapper = (arg) => {
const { event, state } = get_request_store();
if (!state.allows_commands) {
const disallowed_method = !MUTATIVE_METHODS.includes(event.request.method);
throw new Error(
`Cannot call a command (\`${__.name}(${maybe_fn ? "..." : ""})\`) ${disallowed_method ? `from a ${event.request.method} handler or ` : ""}during server-side rendering`
);
}
state.refreshes ??= {};
const promise = Promise.resolve(
run_remote_function(event, state, true, () => validate(arg), fn)
);
promise.updates = () => {
throw new Error(`Cannot call '${__.name}(...).updates(...)' on the server`);
};
return (
/** @type {ReturnType<RemoteCommand<Input, Output>>} */
promise
);
};
Object.defineProperty(wrapper, "__", { value: __ });
Object.defineProperty(wrapper, "pending", {
get: () => 0
});
return wrapper;
}
// @__NO_SIDE_EFFECTS__
function form(validate_or_fn, maybe_fn) {
const fn = maybe_fn ?? validate_or_fn;
const schema = !maybe_fn || validate_or_fn === "unchecked" ? null : (
/** @type {any} */
validate_or_fn
);
function create_instance(key) {
const instance = {};
instance.method = "POST";
Object.defineProperty(instance, "enhance", {
value: () => {
return { action: instance.action, method: instance.method };
}
});
const __ = {
type: "form",
name: "",
id: "",
fn: async (data, meta, form_data) => {
const output = {};
output.submission = true;
const { event, state } = get_request_store();
const validated = await schema?.["~standard"].validate(data);
if (meta.validate_only) {
return validated?.issues?.map((issue) => normalize_issue(issue, true)) ?? [];
}
if (validated?.issues !== void 0) {
handle_issues(output, validated.issues, form_data);
} else {
if (validated !== void 0) {
data = validated.value;
}
state.refreshes ??= {};
const issue = create_issues();
try {
output.result = await run_remote_function(
event,
state,
true,
() => data,
(data2) => !maybe_fn ? fn() : fn(data2, issue)
);
} catch (e) {
if (e instanceof ValidationError) {
handle_issues(output, e.issues, form_data);
} else {
throw e;
}
}
}
if (!event.isRemoteRequest) {
get_cache(__, state)[""] ??= output;
}
return output;
}
};
Object.defineProperty(instance, "__", { value: __ });
Object.defineProperty(instance, "action", {
get: () => `?/remote=${__.id}`,
enumerable: true
});
Object.defineProperty(instance, "fields", {
get() {
return create_field_proxy(
{},
() => get_cache(__)?.[""]?.input ?? {},
(path, value) => {
const cache = get_cache(__);
const data = cache[""];
if (data?.submission) {
return;
}
if (path.length === 0) {
(cache[""] ??= {}).input = value;
return;
}
const input = data?.input ?? {};
deep_set(input, path.map(String), value);
(cache[""] ??= {}).input = input;
},
() => flatten_issues(get_cache(__)?.[""]?.issues ?? [])
);
}
});
Object.defineProperty(instance, "result", {
get() {
try {
return get_cache(__)?.[""]?.result;
} catch {
return void 0;
}
}
});
Object.defineProperty(instance, "pending", {
get: () => 0
});
Object.defineProperty(instance, "preflight", {
// preflight is a noop on the server
value: () => instance
});
Object.defineProperty(instance, "validate", {
value: () => {
throw new Error("Cannot call validate() on the server");
}
});
if (key == void 0) {
Object.defineProperty(instance, "for", {
/** @type {RemoteForm<any, any>['for']} */
value: (key2) => {
const { state } = get_request_store();
const cache_key = __.id + "|" + JSON.stringify(key2);
let instance2 = (state.form_instances ??= /* @__PURE__ */ new Map()).get(cache_key);
if (!instance2) {
instance2 = create_instance(key2);
instance2.__.id = `${__.id}/${encodeURIComponent(JSON.stringify(key2))}`;
instance2.__.name = __.name;
state.form_instances.set(cache_key, instance2);
}
return instance2;
}
});
}
return instance;
}
return create_instance();
}
function handle_issues(output, issues, form_data) {
output.issues = issues.map((issue) => normalize_issue(issue, true));
if (form_data) {
output.input = {};
for (let key of form_data.keys()) {
if (/^[.\]]?_/.test(key)) continue;
const is_array = key.endsWith("[]");
const values = form_data.getAll(key).filter((value) => typeof value === "string");
if (is_array) key = key.slice(0, -2);
set_nested_value(
/** @type {Record<string, any>} */
output.input,
key,
is_array ? values : values[0]
);
}
}
}
function create_issues() {
return (
/** @type {InvalidField<any>} */
new Proxy(
/** @param {string} message */
(message) => {
if (typeof message !== "string") {
throw new Error(
"`invalid` should now be imported from `@sveltejs/kit` to throw validation issues. The second parameter provided to the form function (renamed to `issue`) is still used to construct issues, e.g. `invalid(issue.field('message'))`. For more info see https://github.com/sveltejs/kit/pulls/14768"
);
}
return create_issue(message);
},
{
get(target, prop) {
if (typeof prop === "symbol") return (
/** @type {any} */
target[prop]
);
return create_issue_proxy(prop, []);
}
}
)
);
function create_issue(message, path = []) {
return {
message,
path
};
}
function create_issue_proxy(key, path) {
const new_path = [...path, key];
const issue_func = (message) => create_issue(message, new_path);
return new Proxy(issue_func, {
get(target, prop) {
if (typeof prop === "symbol") return (
/** @type {any} */
target[prop]
);
if (/^\d+$/.test(prop)) {
return create_issue_proxy(parseInt(prop, 10), new_path);
}
return create_issue_proxy(prop, new_path);
}
});
}
}
// @__NO_SIDE_EFFECTS__
function prerender(validate_or_fn, fn_or_options, maybe_options) {
const maybe_fn = typeof fn_or_options === "function" ? fn_or_options : void 0;
const options = maybe_options ?? (maybe_fn ? void 0 : fn_or_options);
const fn = maybe_fn ?? validate_or_fn;
const validate = create_validator(validate_or_fn, maybe_fn);
const __ = {
type: "prerender",
id: "",
name: "",
has_arg: !!maybe_fn,
inputs: options?.inputs,
dynamic: options?.dynamic
};
const wrapper = (arg) => {
const promise = (async () => {
const { event, state } = get_request_store();
const payload = stringify_remote_arg(arg, state.transport);
const id = __.id;
const url = `${base}/${app_dir}/remote/${id}${payload ? `/${payload}` : ""}`;
if (!state.prerendering && !DEV && !event.isRemoteRequest) {
try {
return await get_response(__, arg, state, async () => {
const key = stringify_remote_arg(arg, state.transport);
const cache = get_cache(__, state);
const promise3 = cache[key] ??= fetch(new URL(url, event.url.origin).href).then(
async (response) => {
if (!response.ok) {
throw new Error("Prerendered response not found");
}
const prerendered = await response.json();
if (prerendered.type === "error") {
error(prerendered.status, prerendered.error);
}
return prerendered.result;
}
);
return parse_remote_response(await promise3, state.transport);
});
} catch {
}
}
if (state.prerendering?.remote_responses.has(url)) {
return (
/** @type {Promise<any>} */
state.prerendering.remote_responses.get(url)
);
}
const promise2 = get_response(
__,
arg,
state,
() => run_remote_function(event, state, false, () => validate(arg), fn)
);
if (state.prerendering) {
state.prerendering.remote_responses.set(url, promise2);
}
const result = await promise2;
if (state.prerendering) {
const body = { type: "result", result: stringify(result, state.transport) };
state.prerendering.dependencies.set(url, {
body: JSON.stringify(body),
response: json(body)
});
}
return result;
})();
promise.catch(() => {
});
return (
/** @type {RemoteResource<Output>} */
promise
);
};
Object.defineProperty(wrapper, "__", { value: __ });
return wrapper;
}
export {
command,
form,
prerender,
q as query
};

332
.svelte-kit/ambient.d.ts vendored Normal file
View File

@@ -0,0 +1,332 @@
// this file is generated — do not edit it
/// <reference types="@sveltejs/kit" />
/**
* This module provides access to environment variables that are injected _statically_ into your bundle at build time and are limited to _private_ access.
*
* | | Runtime | Build time |
* | ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
* | Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) |
* | Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) |
*
* Static environment variables are [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env` at build time and then statically injected into your bundle at build time, enabling optimisations like dead code elimination.
*
* **_Private_ access:**
*
* - This module cannot be imported into client-side code
* - This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured)
*
* For example, given the following build time environment:
*
* ```env
* ENVIRONMENT=production
* PUBLIC_BASE_URL=http://site.com
* ```
*
* With the default `publicPrefix` and `privatePrefix`:
*
* ```ts
* import { ENVIRONMENT, PUBLIC_BASE_URL } from '$env/static/private';
*
* console.log(ENVIRONMENT); // => "production"
* console.log(PUBLIC_BASE_URL); // => throws error during build
* ```
*
* The above values will be the same _even if_ different values for `ENVIRONMENT` or `PUBLIC_BASE_URL` are set at runtime, as they are statically replaced in your code with their build time values.
*/
declare module '$env/static/private' {
export const DATABASE_URL: string;
export const ORIGIN: string;
export const BETTER_AUTH_SECRET: string;
export const OSU_CLIENT_ID: string;
export const OSU_CLIENT_SECRET: string;
export const OSU_IRC_USERNAME: string;
export const OSU_IRC_PASSWORD: string;
export const NVM_INC: string;
export const TERM_PROGRAM: string;
export const NODE: string;
export const NVM_CD_FLAGS: string;
export const TERM: string;
export const SHELL: string;
export const HOMEBREW_REPOSITORY: string;
export const TMPDIR: string;
export const VSCODE_PYTHON_AUTOACTIVATE_GUARD: string;
export const TERM_PROGRAM_VERSION: string;
export const ZDOTDIR: string;
export const MallocNanoZone: string;
export const npm_config_local_prefix: string;
export const LC_ALL: string;
export const ZSH: string;
export const NVM_DIR: string;
export const USER: string;
export const LS_COLORS: string;
export const COMMAND_MODE: string;
export const CLAUDE_CODE_SSE_PORT: string;
export const SSH_AUTH_SOCK: string;
export const VSCODE_PROFILE_INITIALIZED: string;
export const __CF_USER_TEXT_ENCODING: string;
export const npm_execpath: string;
export const PAGER: string;
export const LSCOLORS: string;
export const PATH: string;
export const npm_package_json: string;
export const _: string;
export const LaunchInstanceID: string;
export const USER_ZDOTDIR: string;
export const __CFBundleIdentifier: string;
export const npm_command: string;
export const PWD: string;
export const npm_lifecycle_event: string;
export const EDITOR: string;
export const npm_package_name: string;
export const LANG: string;
export const PYTHONSTARTUP: string;
export const AWS_REGION: string;
export const BUN_INSPECT_CONNECT_TO: string;
export const VSCODE_GIT_ASKPASS_EXTRA_ARGS: string;
export const XPC_FLAGS: string;
export const npm_package_version: string;
export const XPC_SERVICE_NAME: string;
export const VSCODE_INJECTION: string;
export const SHLVL: string;
export const HOME: string;
export const VSCODE_GIT_ASKPASS_MAIN: string;
export const PYTHON_BASIC_REPL: string;
export const HOMEBREW_PREFIX: string;
export const LESS: string;
export const LOGNAME: string;
export const npm_lifecycle_script: string;
export const VSCODE_GIT_IPC_HANDLE: string;
export const NVM_BIN: string;
export const npm_config_user_agent: string;
export const INFOPATH: string;
export const HOMEBREW_CELLAR: string;
export const VSCODE_GIT_ASKPASS_NODE: string;
export const GIT_ASKPASS: string;
export const OSLogRateLimit: string;
export const SECURITYSESSIONID: string;
export const npm_node_execpath: string;
export const COLORTERM: string;
export const NODE_ENV: string;
export const PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS: string;
}
/**
* This module provides access to environment variables that are injected _statically_ into your bundle at build time and are _publicly_ accessible.
*
* | | Runtime | Build time |
* | ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
* | Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) |
* | Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) |
*
* Static environment variables are [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env` at build time and then statically injected into your bundle at build time, enabling optimisations like dead code elimination.
*
* **_Public_ access:**
*
* - This module _can_ be imported into client-side code
* - **Only** variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`) are included
*
* For example, given the following build time environment:
*
* ```env
* ENVIRONMENT=production
* PUBLIC_BASE_URL=http://site.com
* ```
*
* With the default `publicPrefix` and `privatePrefix`:
*
* ```ts
* import { ENVIRONMENT, PUBLIC_BASE_URL } from '$env/static/public';
*
* console.log(ENVIRONMENT); // => throws error during build
* console.log(PUBLIC_BASE_URL); // => "http://site.com"
* ```
*
* The above values will be the same _even if_ different values for `ENVIRONMENT` or `PUBLIC_BASE_URL` are set at runtime, as they are statically replaced in your code with their build time values.
*/
declare module '$env/static/public' {
}
/**
* This module provides access to environment variables set _dynamically_ at runtime and that are limited to _private_ access.
*
* | | Runtime | Build time |
* | ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
* | Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) |
* | Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) |
*
* Dynamic environment variables are defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/main/packages/adapter-node) (or running [`vite preview`](https://svelte.dev/docs/kit/cli)), this is equivalent to `process.env`.
*
* **_Private_ access:**
*
* - This module cannot be imported into client-side code
* - This module includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured)
*
* > [!NOTE] In `dev`, `$env/dynamic` includes environment variables from `.env`. In `prod`, this behavior will depend on your adapter.
*
* > [!NOTE] To get correct types, environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed:
* >
* > ```env
* > MY_FEATURE_FLAG=
* > ```
* >
* > You can override `.env` values from the command line like so:
* >
* > ```sh
* > MY_FEATURE_FLAG="enabled" npm run dev
* > ```
*
* For example, given the following runtime environment:
*
* ```env
* ENVIRONMENT=production
* PUBLIC_BASE_URL=http://site.com
* ```
*
* With the default `publicPrefix` and `privatePrefix`:
*
* ```ts
* import { env } from '$env/dynamic/private';
*
* console.log(env.ENVIRONMENT); // => "production"
* console.log(env.PUBLIC_BASE_URL); // => undefined
* ```
*/
declare module '$env/dynamic/private' {
export const env: {
DATABASE_URL: string;
ORIGIN: string;
BETTER_AUTH_SECRET: string;
OSU_CLIENT_ID: string;
OSU_CLIENT_SECRET: string;
OSU_IRC_USERNAME: string;
OSU_IRC_PASSWORD: string;
NVM_INC: string;
TERM_PROGRAM: string;
NODE: string;
NVM_CD_FLAGS: string;
TERM: string;
SHELL: string;
HOMEBREW_REPOSITORY: string;
TMPDIR: string;
VSCODE_PYTHON_AUTOACTIVATE_GUARD: string;
TERM_PROGRAM_VERSION: string;
ZDOTDIR: string;
MallocNanoZone: string;
npm_config_local_prefix: string;
LC_ALL: string;
ZSH: string;
NVM_DIR: string;
USER: string;
LS_COLORS: string;
COMMAND_MODE: string;
CLAUDE_CODE_SSE_PORT: string;
SSH_AUTH_SOCK: string;
VSCODE_PROFILE_INITIALIZED: string;
__CF_USER_TEXT_ENCODING: string;
npm_execpath: string;
PAGER: string;
LSCOLORS: string;
PATH: string;
npm_package_json: string;
_: string;
LaunchInstanceID: string;
USER_ZDOTDIR: string;
__CFBundleIdentifier: string;
npm_command: string;
PWD: string;
npm_lifecycle_event: string;
EDITOR: string;
npm_package_name: string;
LANG: string;
PYTHONSTARTUP: string;
AWS_REGION: string;
BUN_INSPECT_CONNECT_TO: string;
VSCODE_GIT_ASKPASS_EXTRA_ARGS: string;
XPC_FLAGS: string;
npm_package_version: string;
XPC_SERVICE_NAME: string;
VSCODE_INJECTION: string;
SHLVL: string;
HOME: string;
VSCODE_GIT_ASKPASS_MAIN: string;
PYTHON_BASIC_REPL: string;
HOMEBREW_PREFIX: string;
LESS: string;
LOGNAME: string;
npm_lifecycle_script: string;
VSCODE_GIT_IPC_HANDLE: string;
NVM_BIN: string;
npm_config_user_agent: string;
INFOPATH: string;
HOMEBREW_CELLAR: string;
VSCODE_GIT_ASKPASS_NODE: string;
GIT_ASKPASS: string;
OSLogRateLimit: string;
SECURITYSESSIONID: string;
npm_node_execpath: string;
COLORTERM: string;
NODE_ENV: string;
PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS: string;
[key: `PUBLIC_${string}`]: undefined;
[key: `${string}`]: string | undefined;
}
}
/**
* This module provides access to environment variables set _dynamically_ at runtime and that are _publicly_ accessible.
*
* | | Runtime | Build time |
* | ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
* | Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) |
* | Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) |
*
* Dynamic environment variables are defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/main/packages/adapter-node) (or running [`vite preview`](https://svelte.dev/docs/kit/cli)), this is equivalent to `process.env`.
*
* **_Public_ access:**
*
* - This module _can_ be imported into client-side code
* - **Only** variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`) are included
*
* > [!NOTE] In `dev`, `$env/dynamic` includes environment variables from `.env`. In `prod`, this behavior will depend on your adapter.
*
* > [!NOTE] To get correct types, environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed:
* >
* > ```env
* > MY_FEATURE_FLAG=
* > ```
* >
* > You can override `.env` values from the command line like so:
* >
* > ```sh
* > MY_FEATURE_FLAG="enabled" npm run dev
* > ```
*
* For example, given the following runtime environment:
*
* ```env
* ENVIRONMENT=production
* PUBLIC_BASE_URL=http://example.com
* ```
*
* With the default `publicPrefix` and `privatePrefix`:
*
* ```ts
* import { env } from '$env/dynamic/public';
* console.log(env.ENVIRONMENT); // => undefined, not public
* console.log(env.PUBLIC_BASE_URL); // => "http://example.com"
* ```
*
* ```
*
* ```
*/
declare module '$env/dynamic/public' {
export const env: {
[key: `PUBLIC_${string}`]: string | undefined;
}
}

View File

@@ -0,0 +1,52 @@
export { matchers } from './matchers.js';
export const nodes = [
() => import('./nodes/0'),
() => import('./nodes/1'),
() => import('./nodes/2'),
() => import('./nodes/3'),
() => import('./nodes/4'),
() => import('./nodes/5'),
() => import('./nodes/6'),
() => import('./nodes/7'),
() => import('./nodes/8'),
() => import('./nodes/9'),
() => import('./nodes/10'),
() => import('./nodes/11'),
() => import('./nodes/12'),
() => import('./nodes/13'),
() => import('./nodes/14')
];
export const server_loads = [2];
export const dictionary = {
"/(app)": [~3,[2]],
"/(app)/admin": [~4,[2]],
"/demo": [11],
"/demo/better-auth": [~12],
"/demo/better-auth/login": [~13],
"/login": [~14],
"/(app)/mappools": [~5,[2]],
"/(app)/mappools/[id]": [~6,[2]],
"/(app)/matches": [~7,[2]],
"/(app)/matches/[id]": [~8,[2]],
"/(app)/settings": [~9,[2]],
"/(app)/teams": [~10,[2]]
};
export const hooks = {
handleError: (({ error }) => { console.error(error) }),
reroute: (() => {}),
transport: {}
};
export const decoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.decode]));
export const encoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.encode]));
export const hash = false;
export const decode = (type, value) => decoders[type](value);
export { default as root } from '../root.js';

View File

@@ -0,0 +1 @@
export const matchers = {};

View File

@@ -0,0 +1 @@
export { default as component } from "../../../../node_modules/@sveltejs/kit/src/runtime/components/svelte-5/layout.svelte";

View File

@@ -0,0 +1 @@
export { default as component } from "../../../../src/routes/+error.svelte";

View File

@@ -0,0 +1 @@
export { default as component } from "../../../../src/routes/(app)/teams/+page.svelte";

View File

@@ -0,0 +1 @@
export { default as component } from "../../../../src/routes/demo/+page.svelte";

View File

@@ -0,0 +1 @@
export { default as component } from "../../../../src/routes/demo/better-auth/+page.svelte";

View File

@@ -0,0 +1 @@
export { default as component } from "../../../../src/routes/demo/better-auth/login/+page.svelte";

View File

@@ -0,0 +1 @@
export { default as component } from "../../../../src/routes/(app)/+layout.svelte";

View File

@@ -0,0 +1 @@
export { default as component } from "../../../../src/routes/(app)/+page.svelte";

Some files were not shown because too many files have changed in this diff Show More