From 045e04cd7b8e0a13b2f70dfbc28d465c76382dbb Mon Sep 17 00:00:00 2001 From: Exelo Date: Tue, 28 Apr 2026 14:47:59 +0900 Subject: [PATCH 01/58] chore: base of the refacto --- .env.example | 13 ++- src/app.d.ts | 1 + src/hooks.server.ts | 27 +------ .../server/actions/project/load.actions.ts | 79 +++++++++++++++++++ src/lib/server/api/base.repository.ts | 64 +++++++++++++++ src/lib/server/api/client.ts | 46 +++++++++++ src/lib/server/api/index.ts | 2 + .../middlewares/refresh-token.middleware.ts | 57 +++++++++++++ .../api/repositories/auth.repository.ts | 8 ++ .../api/repositories/projects.repository.ts | 8 ++ src/lib/server/api/types/auth.type.ts | 9 +++ src/lib/server/api/types/index.ts | 2 + src/lib/server/api/types/project.type.ts | 11 +++ .../server/file-system/file-system-error.ts | 7 ++ .../file-system/file-system.functions.ts | 9 +++ src/lib/server/file-system/file-system.ts | 26 ++++++ src/lib/server/file-system/index.ts | 1 + .../file-system/project-directory.ts | 13 ++- .../{utils => }/file-system/project-file.ts | 6 +- src/lib/server/project/index.ts | 2 + src/lib/server/project/load-project.ts | 23 ++++++ src/lib/server/project/project.type.ts | 4 + src/lib/server/session/index.ts | 5 ++ .../session/project/project-functions.ts | 37 +++++++++ .../server/session/project/project.const.ts | 1 + .../server/session/project/project.store.ts | 3 + .../server/session/project/project.type.ts | 7 ++ src/lib/server/session/session-functions.ts | 41 ++++++++++ src/lib/server/session/session-handle.ts | 23 ++++++ src/lib/server/session/session.const.ts | 1 + src/lib/server/session/session.store.ts | 3 + src/lib/server/session/session.type.ts | 4 + src/lib/server/utils/cookies/index.ts | 26 ++++++ src/lib/server/utils/exception.ts | 10 +++ .../utils/file-system/file-system-error.ts | 7 -- src/lib/server/utils/request-handler/body.ts | 6 ++ .../server/utils/request-handler/context.ts | 27 +++++++ .../server/utils/request-handler/handler.ts | 71 +++++++++++++++++ src/lib/server/utils/request-handler/index.ts | 4 + .../utils/request-handler/request-handler.ts | 36 +++++++++ .../utils/request-handler/request.policy.ts | 36 +++++++++ src/lib/server/utils/request-handler/types.ts | 28 +++++++ src/lib/server/utils/types/index.ts | 1 + src/lib/server/utils/types/tokens.type.ts | 4 + src/lib/{server => utils/http}/client.ts | 0 src/lib/utils/http/index.ts | 2 +- src/lib/utils/index.ts | 1 - src/lib/utils/string.ts | 6 ++ src/lib/utils/types/class.type.ts | 1 + src/lib/utils/types/index.ts | 2 + src/lib/utils/types/promise.type.ts | 1 + src/routes/actions/project/+page.server.ts | 5 ++ src/routes/fs/+page.server.ts | 6 +- src/routes/game-loader/+page.server.ts | 7 +- 54 files changed, 775 insertions(+), 55 deletions(-) create mode 100644 src/lib/server/actions/project/load.actions.ts create mode 100644 src/lib/server/api/base.repository.ts create mode 100644 src/lib/server/api/client.ts create mode 100644 src/lib/server/api/index.ts create mode 100644 src/lib/server/api/middlewares/refresh-token.middleware.ts create mode 100644 src/lib/server/api/repositories/auth.repository.ts create mode 100644 src/lib/server/api/repositories/projects.repository.ts create mode 100644 src/lib/server/api/types/auth.type.ts create mode 100644 src/lib/server/api/types/index.ts create mode 100644 src/lib/server/api/types/project.type.ts create mode 100644 src/lib/server/file-system/file-system-error.ts create mode 100644 src/lib/server/file-system/file-system.functions.ts create mode 100644 src/lib/server/file-system/file-system.ts create mode 100644 src/lib/server/file-system/index.ts rename src/lib/server/{utils => }/file-system/project-directory.ts (93%) rename src/lib/server/{utils => }/file-system/project-file.ts (96%) create mode 100644 src/lib/server/project/index.ts create mode 100644 src/lib/server/project/load-project.ts create mode 100644 src/lib/server/project/project.type.ts create mode 100644 src/lib/server/session/index.ts create mode 100644 src/lib/server/session/project/project-functions.ts create mode 100644 src/lib/server/session/project/project.const.ts create mode 100644 src/lib/server/session/project/project.store.ts create mode 100644 src/lib/server/session/project/project.type.ts create mode 100644 src/lib/server/session/session-functions.ts create mode 100644 src/lib/server/session/session-handle.ts create mode 100644 src/lib/server/session/session.const.ts create mode 100644 src/lib/server/session/session.store.ts create mode 100644 src/lib/server/session/session.type.ts create mode 100644 src/lib/server/utils/cookies/index.ts create mode 100644 src/lib/server/utils/exception.ts delete mode 100644 src/lib/server/utils/file-system/file-system-error.ts create mode 100644 src/lib/server/utils/request-handler/body.ts create mode 100644 src/lib/server/utils/request-handler/context.ts create mode 100644 src/lib/server/utils/request-handler/handler.ts create mode 100644 src/lib/server/utils/request-handler/index.ts create mode 100644 src/lib/server/utils/request-handler/request-handler.ts create mode 100644 src/lib/server/utils/request-handler/request.policy.ts create mode 100644 src/lib/server/utils/request-handler/types.ts create mode 100644 src/lib/server/utils/types/index.ts create mode 100644 src/lib/server/utils/types/tokens.type.ts rename src/lib/{server => utils/http}/client.ts (100%) delete mode 100644 src/lib/utils/index.ts create mode 100644 src/lib/utils/string.ts create mode 100644 src/lib/utils/types/class.type.ts create mode 100644 src/lib/utils/types/index.ts create mode 100644 src/lib/utils/types/promise.type.ts create mode 100644 src/routes/actions/project/+page.server.ts diff --git a/.env.example b/.env.example index 9194c4d..3b356af 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,16 @@ -# Leave empty for local environment / no api authentication -API_URL=http://localhost:3000 - # Set to production NODE_ENV=development +# OFFLINE or ONLINE, change editor mode beetween local execution and online execution +MODE=OFFLINE + +# Api params (required if MODE=ONLINE) +API_URL=http://localhost:3000 +API_KEY=test + +# Fs root dir read/write projects (leave empty to select current directory) (if you use relative path, it will be / +FS_ROOT= + # Leaving this empty will generate a new unique random session secret at start SESSION_SECRET= diff --git a/src/app.d.ts b/src/app.d.ts index ba56e29..ae3ea3f 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -14,6 +14,7 @@ declare global { declare module 'svelte-kit-sessions' { interface SessionData { + id: string; path: string; projectPid?: number; } diff --git a/src/hooks.server.ts b/src/hooks.server.ts index dcbf401..2b5b4b4 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -1,31 +1,8 @@ -import { type Handle, redirect } from '@sveltejs/kit'; +import { type Handle } from '@sveltejs/kit'; import { sequence } from '@sveltejs/kit/hooks'; -import * as crypto from 'node:crypto'; -import { sveltekitSessionHandle } from 'svelte-kit-sessions'; - -import { env } from '$env/dynamic/private'; import { paraglideMiddleware } from '$lib/paraglide/server'; - -if (!env.SESSION_SECRET) { - env.SESSION_SECRET = crypto.randomBytes(20).toString('hex'); - console.log(`SESSION_SECRET not found, generating a temporary one: ${env.SESSION_SECRET}`); -} - -const sessionHandle = sveltekitSessionHandle({ - secret: env.SESSION_SECRET, -}); - -const checkAuthorizationHandle: Handle = async ({ event, resolve }) => { - if ( - !event.locals.session.data.path && - event.url.pathname !== '/load-project' && - event.url.pathname + event.url.search !== '/cli?/new' - ) { - throw redirect(302, '/load-project'); - } - return resolve(event); -}; +import { checkAuthorizationHandle, sessionHandle } from '$lib/server/session'; const handleParaglide: Handle = ({ event, resolve }) => paraglideMiddleware(event.request, ({ request, locale }) => { diff --git a/src/lib/server/actions/project/load.actions.ts b/src/lib/server/actions/project/load.actions.ts new file mode 100644 index 0000000..0fce522 --- /dev/null +++ b/src/lib/server/actions/project/load.actions.ts @@ -0,0 +1,79 @@ +import { join } from 'path'; + +import { loadProject } from '$lib/server/project'; +import type { SessionProject } from '$lib/server/session'; + +import { Exception } from '@utils-server/exception'; +import { type Handler, useRequestHandler } from '@utils-server/request-handler'; + +class LoadProjectBody { + path?: string; + gitUrl?: string; + gatewayId?: string; +} + +const resolveSessionFromGatewayId = async ( + gatewayId: string, + { api, git, context }: Handler, +): Promise => { + if (!context.online) + throw new Exception('Bad Request', 'Cannot load project from gatewayId while offline', 400); + + const project = await api.projects.getProject(gatewayId); + const basePath = await git.clone( + project.gatewayProjectRegistryUrl, + project.gatewayProjectRegistryMetadata.sshKey, + ); + return { + path: join(basePath, project.gatewayProjectRegistryMetadata.dir ?? ''), + gateway: { id: gatewayId, sshKey: project.gatewayProjectRegistryMetadata.sshKey }, + }; +}; + +const resolveSessionFromGitUrl = async ( + gitUrl: string, + { git, context }: Handler, +): Promise => { + if (context.online) + throw new Exception('Bad Request', 'Cannot load project from gitUrl while online', 400); + + const path = await git.clone(gitUrl); + return { path }; +}; + +const resolveSessionFromPath = async ( + path: string, + { context }: Handler, +): Promise => { + if (context.online) + throw new Exception('Bad Request', 'Cannot load project from path while online', 400); + return { path }; +}; + +const resolveSessionFunctions: Record< + keyof LoadProjectBody, + (el: string, options: Handler) => Promise +> = { + path: resolveSessionFromPath, + gitUrl: resolveSessionFromGitUrl, + gatewayId: resolveSessionFromGatewayId, +}; + +export const loadProjectAction = useRequestHandler( + async (handler) => { + const { body } = handler; + + const el = Object.entries(body).find(([, value]) => value) as [keyof LoadProjectBody, string]; + if (!el) throw new Exception('Bad Request', 'No load origin provided', 400); + + const resolveSessionFunction = resolveSessionFunctions[el[0]]; + + const project = await resolveSessionFunction(el[1], handler); + + return await loadProject(project, handler); + }, + { + projectOptional: true, + body: LoadProjectBody, + }, +); diff --git a/src/lib/server/api/base.repository.ts b/src/lib/server/api/base.repository.ts new file mode 100644 index 0000000..33d6728 --- /dev/null +++ b/src/lib/server/api/base.repository.ts @@ -0,0 +1,64 @@ +import type { HttpClient, RequestOptions } from '@utils/http'; + +export class BaseRepository { + private readonly _client: HttpClient; + + constructor(client: HttpClient) { + this._client = client; + } + + protected get(path: string, options?: RequestOptions): Promise { + return this.runRequest('get', path, options); + } + + protected post( + path: string, + body?: I, + options?: RequestOptions, + ): Promise { + return this.runRequestBody('post', path, body, options); + } + + protected put( + path: string, + body?: I, + options?: RequestOptions, + ): Promise { + return this.runRequestBody('put', path, body, options); + } + + protected patch( + path: string, + body?: I, + options?: RequestOptions, + ): Promise { + return this.runRequestBody('patch', path, body, options); + } + + protected delete(path: string, options?: RequestOptions): Promise { + return this.runRequest('delete', path, options); + } + + private async runRequest( + request: 'get' | 'delete', + path: string, + options?: RequestOptions, + ): Promise { + return (await this._client[request](`/api${path}`, options)).content as R; + } + + private async runRequestBody( + request: 'post' | 'put' | 'patch', + path: string, + body?: I, + options?: RequestOptions, + ): Promise { + return ( + await this._client[request]( + `/api${path}`, + body === undefined ? undefined : JSON.stringify(body), + options, + ) + ).content as R; + } +} diff --git a/src/lib/server/api/client.ts b/src/lib/server/api/client.ts new file mode 100644 index 0000000..50dc98a --- /dev/null +++ b/src/lib/server/api/client.ts @@ -0,0 +1,46 @@ +import type { Cookies } from '@sveltejs/kit'; + +import { env } from '$env/dynamic/private'; + +import { HttpClient } from '@utils/http'; + +import type { Context } from '@utils-server/request-handler/context'; + +import { useTokenMiddleware } from './middlewares/refresh-token.middleware'; +import { AuthRepository } from './repositories/auth.repository'; +import { ProjectRepository } from './repositories/projects.repository'; + +export interface Api { + auth: AuthRepository; + projects: ProjectRepository; +} + +export const getNoAuthApi = () => { + if (env.MODE !== 'ONLINE') throw new Error('API is only available in online mode'); + if (!env.API_URL) throw new Error('API_URL is not defined'); + if (!env.API_KEY) throw new Error('API_KEY is not defined'); + + const client = new HttpClient(env.API_URL, { + headers: { + 'Content-Type': 'application/json', + 'Api-Key': env.API_KEY, + }, + }); + return { auth: new AuthRepository(client) }; +}; + +export const getApi = (context: Context, cookies: Cookies): Api => { + if (!context.online) throw new Error('API is only available in online mode'); + + if (!env.API_URL) throw new Error('API_URL is not defined'); + if (!env.API_KEY) throw new Error('API_KEY is not defined'); + + const client = new HttpClient(env.API_URL, { + headers: { + 'Content-Type': 'application/json', + 'Api-Key': env.API_KEY, + }, + }).useMiddlewares(useTokenMiddleware(cookies)); + + return { auth: new AuthRepository(client), projects: new ProjectRepository(client) }; +}; diff --git a/src/lib/server/api/index.ts b/src/lib/server/api/index.ts new file mode 100644 index 0000000..65fa846 --- /dev/null +++ b/src/lib/server/api/index.ts @@ -0,0 +1,2 @@ +export { getApi, type Api } from './client'; +export * from './types'; diff --git a/src/lib/server/api/middlewares/refresh-token.middleware.ts b/src/lib/server/api/middlewares/refresh-token.middleware.ts new file mode 100644 index 0000000..82fc7ec --- /dev/null +++ b/src/lib/server/api/middlewares/refresh-token.middleware.ts @@ -0,0 +1,57 @@ +import type { Cookies } from '@sveltejs/kit'; + +import { getNoAuthApi } from '$lib/server/api/client'; + +import type { MiddlewareNext, MiddlewareParams } from '@utils/http'; + +import { setTokensInCookies } from '@utils-server/cookies'; +import { Exception } from '@utils-server/exception'; + +const refreshToken = async (cookies: Cookies, force: boolean = false): Promise => { + let accessToken = force ? undefined : cookies.get('accessToken'); + const refreshToken = cookies.get('refreshToken'); + + if (!accessToken) { + if (!refreshToken) { + throw new Exception('Unauthorized', 'No token found', 401); + } + + try { + const tokens = await getNoAuthApi().auth.refreshToken({ + refreshToken, + }); + + setTokensInCookies(cookies, tokens); + accessToken = tokens.accessToken; + } catch { + throw new Exception('Unauthorized', 'Invalid refresh token', 401); + } + } + + return accessToken; +}; + +const getRequestParams = (params: MiddlewareParams, token: string): MiddlewareParams => ({ + ...params, + options: { + ...params.options, + headers: { + ...params.options.headers, + Authorization: `Bearer ${token}`, + }, + }, +}); + +export const useTokenMiddleware = (cookies: Cookies) => { + return async (params: MiddlewareParams, next: MiddlewareNext) => { + const accessToken = cookies.get('accessToken') ?? (await refreshToken(cookies)); + + const res = await next(getRequestParams(params, accessToken)); + + if (res.status === 401) { + const newAccessToken = await refreshToken(cookies, true); + return await next(getRequestParams(params, newAccessToken)); + } + return res; + }; +}; diff --git a/src/lib/server/api/repositories/auth.repository.ts b/src/lib/server/api/repositories/auth.repository.ts new file mode 100644 index 0000000..184be28 --- /dev/null +++ b/src/lib/server/api/repositories/auth.repository.ts @@ -0,0 +1,8 @@ +import { BaseRepository } from '../base.repository'; +import type { RefreshTokenInput, TokenResponse } from '../types'; + +export class AuthRepository extends BaseRepository { + refreshToken(input: RefreshTokenInput): Promise { + return this.post(`/auth/refresh-token`, input); + } +} diff --git a/src/lib/server/api/repositories/projects.repository.ts b/src/lib/server/api/repositories/projects.repository.ts new file mode 100644 index 0000000..3a4ffe2 --- /dev/null +++ b/src/lib/server/api/repositories/projects.repository.ts @@ -0,0 +1,8 @@ +import { BaseRepository } from '../base.repository'; +import type { ApiProject } from '../types'; + +export class ProjectRepository extends BaseRepository { + getProject(id: string): Promise { + return this.get(`/editor/projects/${id}`); + } +} diff --git a/src/lib/server/api/types/auth.type.ts b/src/lib/server/api/types/auth.type.ts new file mode 100644 index 0000000..1d77249 --- /dev/null +++ b/src/lib/server/api/types/auth.type.ts @@ -0,0 +1,9 @@ +export interface TokenResponse { + accessToken: string; + refreshToken: string; + tokenExpiresAt: string; +} + +export interface RefreshTokenInput { + refreshToken: string; +} diff --git a/src/lib/server/api/types/index.ts b/src/lib/server/api/types/index.ts new file mode 100644 index 0000000..e39b144 --- /dev/null +++ b/src/lib/server/api/types/index.ts @@ -0,0 +1,2 @@ +export * from './auth.type'; +export * from './project.type'; diff --git a/src/lib/server/api/types/project.type.ts b/src/lib/server/api/types/project.type.ts new file mode 100644 index 0000000..f842348 --- /dev/null +++ b/src/lib/server/api/types/project.type.ts @@ -0,0 +1,11 @@ +export interface ApiProject { + id: string; + code: string; + name: string; + description: string; + gatewayProjectRegistryUrl: string; + gatewayProjectRegistryMetadata: { + dir: string | null; + sshKey: string; + }; +} diff --git a/src/lib/server/file-system/file-system-error.ts b/src/lib/server/file-system/file-system-error.ts new file mode 100644 index 0000000..61712b1 --- /dev/null +++ b/src/lib/server/file-system/file-system-error.ts @@ -0,0 +1,7 @@ +import { Exception } from '@utils-server/exception'; + +export class FileSystemError extends Exception { + constructor(message: string) { + super('Bad Request', message, 400); + } +} diff --git a/src/lib/server/file-system/file-system.functions.ts b/src/lib/server/file-system/file-system.functions.ts new file mode 100644 index 0000000..f7c4e60 --- /dev/null +++ b/src/lib/server/file-system/file-system.functions.ts @@ -0,0 +1,9 @@ +import { join } from 'path'; + +import { env } from '$env/dynamic/private'; + +export const resolveRootPath = (userPath: string) => { + const rootPath = join(process.cwd(), env.FS_ROOT ?? ''); + + return join(rootPath, userPath); +}; diff --git a/src/lib/server/file-system/file-system.ts b/src/lib/server/file-system/file-system.ts new file mode 100644 index 0000000..430c45b --- /dev/null +++ b/src/lib/server/file-system/file-system.ts @@ -0,0 +1,26 @@ +import { Exception } from '@utils-server/exception'; +import type { Context } from '@utils-server/request-handler/context'; + +import { resolveRootPath } from './file-system.functions'; +import { ProjectDirectory } from './project-directory'; +import { ProjectFile } from './project-file'; + +export class FileSystem { + private readonly _rootPath: string; + + constructor(context: Context) { + if (!context.project) { + throw new Exception('Bad Request', 'Project is not defined', 400); + } + + this._rootPath = resolveRootPath(context.project.path); + } + + getDirectory(path: string) { + return new ProjectDirectory(path, this._rootPath); + } + + getFile(path: string) { + return new ProjectFile(path, this._rootPath); + } +} diff --git a/src/lib/server/file-system/index.ts b/src/lib/server/file-system/index.ts new file mode 100644 index 0000000..54aae6d --- /dev/null +++ b/src/lib/server/file-system/index.ts @@ -0,0 +1 @@ +export { FileSystem } from './file-system'; diff --git a/src/lib/server/utils/file-system/project-directory.ts b/src/lib/server/file-system/project-directory.ts similarity index 93% rename from src/lib/server/utils/file-system/project-directory.ts rename to src/lib/server/file-system/project-directory.ts index 9da8337..645fada 100644 --- a/src/lib/server/utils/file-system/project-directory.ts +++ b/src/lib/server/file-system/project-directory.ts @@ -5,7 +5,7 @@ import { FileSystemError } from './file-system-error'; export type DirectoryContent = { files: string[]; - directories: { [key: string]: DirectoryContent }; + directories: Record; }; export function directoryContentToFileEntries( @@ -18,6 +18,7 @@ export function directoryContentToFileEntries( entries.push(basePath + '/' + file); }); Object.entries(directoryContent.directories).forEach(([path, dirContent]) => { + if (!dirContent) return; entries.push(...directoryContentToFileEntries(dirContent, basePath + '/' + path)); }); return entries; @@ -30,10 +31,11 @@ export class ProjectDirectory { constructor(dirPath: string, projectPath: string) { this.path = path.resolve(projectPath, './' + dirPath); this.projectPath = projectPath; + + this._checkPathIsInsideProject(); } read(recursive: boolean = false): DirectoryContent { - this._checkPathIsInsideProject(); this._checkPathExists(); this._checkPathIsDir(); this._checkPathIsReadable(); @@ -41,14 +43,12 @@ export class ProjectDirectory { } create(): void { - this._checkPathIsInsideProject(); this._checkPathNotExists(); fs.mkdirSync(this.path, { recursive: true }); } delete(recursive: boolean = false): void { - this._checkPathIsInsideProject(); this._checkPathExists(); this._checkPathIsDir(); if (!recursive) { @@ -59,7 +59,6 @@ export class ProjectDirectory { rename(newPath: string): void { const absoluteNewDirPath = path.resolve(this.projectPath, './' + newPath); - this._checkPathIsInsideProject(); this._checkPathIsInsideProject(absoluteNewDirPath); this._checkPathExists(); this._checkPathIsDir(); @@ -125,7 +124,7 @@ export class ProjectDirectory { } private _readDirContent(path: string = this.path, recursive: boolean = false): DirectoryContent { - const dirContent: { files: string[]; directories: { [key: string]: any } } = { + const dirContent: DirectoryContent = { files: [], directories: {}, }; @@ -135,7 +134,7 @@ export class ProjectDirectory { } else if (item.isDirectory()) { dirContent.directories[item.name] = recursive ? this._readDirContent(path + '/' + item.name, recursive) - : {}; + : null; } }); return dirContent; diff --git a/src/lib/server/utils/file-system/project-file.ts b/src/lib/server/file-system/project-file.ts similarity index 96% rename from src/lib/server/utils/file-system/project-file.ts rename to src/lib/server/file-system/project-file.ts index 606dd60..7bf7f1b 100644 --- a/src/lib/server/utils/file-system/project-file.ts +++ b/src/lib/server/file-system/project-file.ts @@ -10,10 +10,11 @@ export class ProjectFile { constructor(filePath: string, projectPath: string) { this._path = path.resolve(projectPath, './' + filePath); this.projectPath = projectPath; + + this._checkPathIsInsideProject(); } get path(): string { - this._checkPathIsInsideProject(); this._checkPathExists(); return this._path; } @@ -30,7 +31,6 @@ export class ProjectFile { write(text: string): void { const folderPath = path.dirname(this._path); - this._checkPathIsInsideProject(); try { this._checkPathExists(); this._checkPathIsFile(); @@ -52,7 +52,6 @@ export class ProjectFile { } delete(): void { - this._checkPathIsInsideProject(); this._checkPathExists(); this._checkPathIsFile(); this._checkPathIsWritable(); @@ -74,7 +73,6 @@ export class ProjectFile { } isReadable(): void { - this._checkPathIsInsideProject(); this._checkPathExists(); this._checkPathIsFile(); this._checkPathIsReadable(); diff --git a/src/lib/server/project/index.ts b/src/lib/server/project/index.ts new file mode 100644 index 0000000..207836d --- /dev/null +++ b/src/lib/server/project/index.ts @@ -0,0 +1,2 @@ +export { loadProject } from './load-project'; +export type { Project } from './project.type'; diff --git a/src/lib/server/project/load-project.ts b/src/lib/server/project/load-project.ts new file mode 100644 index 0000000..8103c30 --- /dev/null +++ b/src/lib/server/project/load-project.ts @@ -0,0 +1,23 @@ +import type { SessionProject } from '$lib/server/session'; +import { tryAddProjectSession } from '$lib/server/session/project/project-functions'; +import { addProjectToSession } from '$lib/server/session/session-functions'; + +import { type Handler } from '@utils-server/request-handler'; + +import type { Project } from './project.type'; + +export const loadProject = async (session: SessionProject, handler: Handler): Promise => { + const projectId = tryAddProjectSession(session); + addProjectToSession(handler.context.session, projectId); + + handler.context = { ...handler.context, project: session }; + + const { fs } = handler; + + const pkg = await fs.getFile('package.json').readJson(); + + return { + id: projectId, + name: pkg.name, + }; +}; diff --git a/src/lib/server/project/project.type.ts b/src/lib/server/project/project.type.ts new file mode 100644 index 0000000..d7e3291 --- /dev/null +++ b/src/lib/server/project/project.type.ts @@ -0,0 +1,4 @@ +export interface Project { + id: string; + name: string; +} diff --git a/src/lib/server/session/index.ts b/src/lib/server/session/index.ts new file mode 100644 index 0000000..5efcf89 --- /dev/null +++ b/src/lib/server/session/index.ts @@ -0,0 +1,5 @@ +export * from './session-handle'; +export { resolveSession } from './session-functions'; +export type { Session } from './session.type'; +export { resolveProject } from './project/project-functions'; +export type { SessionProject } from './project/project.type'; diff --git a/src/lib/server/session/project/project-functions.ts b/src/lib/server/session/project/project-functions.ts new file mode 100644 index 0000000..0af1481 --- /dev/null +++ b/src/lib/server/session/project/project-functions.ts @@ -0,0 +1,37 @@ +import { generateKey } from '@utils/string'; + +import type { Session } from '../session.type'; +import { SESSION_PROJECT_HEADER } from './project.const'; +import { projectStore } from './project.store'; +import type { SessionProject } from './project.type'; + +export const isProjectExist = (id: string | null | undefined) => { + if (!id) return false; + if (!projectStore.has(id)) return false; + + return true; +}; + +export const hasRightToAccessProject = (id: string | null | undefined, session: Session) => { + if (!isProjectExist(id)) return false; + if (!session.projects.includes(id as string)) return false; + + return true; +}; + +export const resolveProject = (headers: Headers, session: Session) => { + if (!session) return null; + if (!session.projects.length) return null; + const id = headers.get(SESSION_PROJECT_HEADER); + + if (!hasRightToAccessProject(id, session)) return null; + + return projectStore.get(id as string) ?? null; +}; + +export const tryAddProjectSession = (session: SessionProject): string => { + let id = generateKey(10); + while (projectStore.has(id)) id = generateKey(10); + projectStore.set(id, session); + return id; +}; diff --git a/src/lib/server/session/project/project.const.ts b/src/lib/server/session/project/project.const.ts new file mode 100644 index 0000000..53c0e25 --- /dev/null +++ b/src/lib/server/session/project/project.const.ts @@ -0,0 +1 @@ +export const SESSION_PROJECT_HEADER = 'x-project-id'; diff --git a/src/lib/server/session/project/project.store.ts b/src/lib/server/session/project/project.store.ts new file mode 100644 index 0000000..1563222 --- /dev/null +++ b/src/lib/server/session/project/project.store.ts @@ -0,0 +1,3 @@ +import type { SessionProject } from '$lib/server/session/project/project.type'; + +export const projectStore = new Map(); diff --git a/src/lib/server/session/project/project.type.ts b/src/lib/server/session/project/project.type.ts new file mode 100644 index 0000000..6d0a5cb --- /dev/null +++ b/src/lib/server/session/project/project.type.ts @@ -0,0 +1,7 @@ +export interface SessionProject { + path: string; + gateway?: { + id: string; + sshKey: string; + }; +} diff --git a/src/lib/server/session/session-functions.ts b/src/lib/server/session/session-functions.ts new file mode 100644 index 0000000..4e7c920 --- /dev/null +++ b/src/lib/server/session/session-functions.ts @@ -0,0 +1,41 @@ +import { type Session as SvelteSession } from 'svelte-kit-sessions'; + +import { Exception } from '@utils-server/exception'; + +import { PUBLIC_PATHS } from './session.const'; +import { sessionStore } from './session.store'; +import type { Session } from './session.type'; + +export const isPublicPath = (url: URL) => { + if (PUBLIC_PATHS.includes(url.pathname)) return true; + if (url.pathname.startsWith('/api')) return true; + + return false; +}; + +export const resolveSession = async (sessionHandler: SvelteSession): Promise => { + const id = sessionHandler.data.id; + + if (!id) return null; + + if (!sessionStore.has(id)) { + await resetSession(sessionHandler); + throw new Exception('Bad Request', 'Invalid session', 400); + } + return sessionStore.get(id) as Session; +}; + +export const resetSession = (sessionHandler: SvelteSession): Promise => { + return sessionHandler.destroy(); +}; + +export const addProjectToSession = (session: Session, projectId: string): void => { + if (!sessionStore.has(session.id)) { + throw new Exception('Bad Request', 'Invalid session', 400); + } + + sessionStore.set(session.id, { + ...session, + projects: [...session.projects, projectId], + }); +}; diff --git a/src/lib/server/session/session-handle.ts b/src/lib/server/session/session-handle.ts new file mode 100644 index 0000000..c8cacc5 --- /dev/null +++ b/src/lib/server/session/session-handle.ts @@ -0,0 +1,23 @@ +import { type Handle, redirect } from '@sveltejs/kit'; +import { sveltekitSessionHandle } from 'svelte-kit-sessions'; + +import { env } from '$env/dynamic/private'; + +import { generateKey } from '@utils/string'; + +import { isPublicPath } from './session-functions'; + +export const sessionHandle = sveltekitSessionHandle({ + secret: env.SESSION_SECRET || generateKey(), +}); + +export const checkAuthorizationHandle: Handle = async ({ event, resolve }) => { + const sessionData = event.locals.session.data; + + if (isPublicPath(event.url)) return resolve(event); + + if (!sessionData.path) throw redirect(302, '/load-project'); + // Replace line above with it when new session are handled + // if (!isSessionExist(sessionData.id)) throw redirect(302, '/load-project'); + return resolve(event); +}; diff --git a/src/lib/server/session/session.const.ts b/src/lib/server/session/session.const.ts new file mode 100644 index 0000000..64b61c6 --- /dev/null +++ b/src/lib/server/session/session.const.ts @@ -0,0 +1 @@ +export const PUBLIC_PATHS = ['/load-project', '/cli?/new']; diff --git a/src/lib/server/session/session.store.ts b/src/lib/server/session/session.store.ts new file mode 100644 index 0000000..d38664c --- /dev/null +++ b/src/lib/server/session/session.store.ts @@ -0,0 +1,3 @@ +import type { Session } from './session.type'; + +export const sessionStore = new Map(); diff --git a/src/lib/server/session/session.type.ts b/src/lib/server/session/session.type.ts new file mode 100644 index 0000000..f1e09ff --- /dev/null +++ b/src/lib/server/session/session.type.ts @@ -0,0 +1,4 @@ +export interface Session { + id: string; + projects: string[]; +} diff --git a/src/lib/server/utils/cookies/index.ts b/src/lib/server/utils/cookies/index.ts new file mode 100644 index 0000000..02f3867 --- /dev/null +++ b/src/lib/server/utils/cookies/index.ts @@ -0,0 +1,26 @@ +import type { Cookies } from '@sveltejs/kit'; + +import { env } from '$env/dynamic/private'; + +import type { TokenResponse } from '$lib/server/api/types/auth.type'; + +export const setTokensInCookies = ( + cookies: Cookies, + { accessToken, refreshToken, tokenExpiresAt }: TokenResponse, +) => { + cookies.set('accessToken', accessToken, { + httpOnly: true, + secure: env.NODE_ENV === 'production', + sameSite: 'lax', + path: '/', + expires: new Date(tokenExpiresAt), + }); + + cookies.set('refreshToken', refreshToken, { + httpOnly: true, + secure: env.NODE_ENV === 'production', + sameSite: 'lax', + path: '/', + maxAge: 60 * 60 * 24 * 30, // 30 days + }); +}; diff --git a/src/lib/server/utils/exception.ts b/src/lib/server/utils/exception.ts new file mode 100644 index 0000000..e779554 --- /dev/null +++ b/src/lib/server/utils/exception.ts @@ -0,0 +1,10 @@ +export class Exception extends Error { + constructor( + public error: string, + public message: string, + public status: number, + options?: { cause?: Error }, + ) { + super(`${error}: ${message}`, options); + } +} diff --git a/src/lib/server/utils/file-system/file-system-error.ts b/src/lib/server/utils/file-system/file-system-error.ts deleted file mode 100644 index 00de3d5..0000000 --- a/src/lib/server/utils/file-system/file-system-error.ts +++ /dev/null @@ -1,7 +0,0 @@ -export class FileSystemError extends Error { - message: string; - constructor(message: string) { - super(); - this.message = message; - } -} diff --git a/src/lib/server/utils/request-handler/body.ts b/src/lib/server/utils/request-handler/body.ts new file mode 100644 index 0000000..62daae6 --- /dev/null +++ b/src/lib/server/utils/request-handler/body.ts @@ -0,0 +1,6 @@ +import type { ClassType } from '@utils/types'; + +export const parseBody = (baseBody: any, c: ClassType | undefined): Body => { + void c; + return baseBody as Body; +}; diff --git a/src/lib/server/utils/request-handler/context.ts b/src/lib/server/utils/request-handler/context.ts new file mode 100644 index 0000000..dcbbc7a --- /dev/null +++ b/src/lib/server/utils/request-handler/context.ts @@ -0,0 +1,27 @@ +import type { RequestEvent } from '@sveltejs/kit'; + +import { env } from '$env/dynamic/private'; + +import { + type Session, + type SessionProject, + resolveProject, + resolveSession, +} from '$lib/server/session'; + +export interface Context { + online: boolean; + session: Session; + project: SessionProject; +} + +export const getContext = async (event: RequestEvent): Promise => { + const session = (await resolveSession(event.locals.session)) as Session; + const project = resolveProject(event.request.headers, session) as SessionProject; + + return { + online: env.MODE === 'ONLINE', + session, + project, + }; +}; diff --git a/src/lib/server/utils/request-handler/handler.ts b/src/lib/server/utils/request-handler/handler.ts new file mode 100644 index 0000000..5158aa5 --- /dev/null +++ b/src/lib/server/utils/request-handler/handler.ts @@ -0,0 +1,71 @@ +import type { RequestEvent } from '@sveltejs/kit'; + +import { type Api, getApi } from '$lib/server/api'; +import { FileSystem } from '$lib/server/file-system'; + +import type { Context } from '@utils-server/request-handler/context'; + +export class Handler { + private _context: Context; + private readonly _event: RequestEvent; + private readonly _body: Body; + + private _apiCache: Api | undefined; + private _cliCache: any | undefined; + private _fsCache: FileSystem | undefined; + private _loaderCache: any | undefined; + private _gitCache: any | undefined; + + constructor(context: Context, event: RequestEvent, body: Body) { + this._context = context; + this._event = event; + this._body = body; + } + + get context(): Context { + return this._context; + } + + set context(context: Context) { + this._context = context; + + this._apiCache = undefined; + this._cliCache = undefined; + this._fsCache = undefined; + this._loaderCache = undefined; + this._gitCache = undefined; + } + + get event(): RequestEvent { + return this._event; + } + + get body(): Body { + return this._body; + } + + get api(): Api { + if (!this._apiCache) this._apiCache = getApi(this._context, this._event.cookies); + return this._apiCache; + } + + get cli(): any { + if (!this._cliCache) this._cliCache = {}; + return this._cliCache; + } + + get fs(): FileSystem { + if (!this._fsCache) this._fsCache = new FileSystem(this._context); + return this._fsCache; + } + + get loader(): any { + if (!this._loaderCache) this._loaderCache = {}; + return this._loaderCache; + } + + get git(): any { + if (!this._gitCache) this._gitCache = {}; + return this._gitCache; + } +} diff --git a/src/lib/server/utils/request-handler/index.ts b/src/lib/server/utils/request-handler/index.ts new file mode 100644 index 0000000..3302cad --- /dev/null +++ b/src/lib/server/utils/request-handler/index.ts @@ -0,0 +1,4 @@ +export * from './request-handler'; +export * from './context'; +export * from './handler'; +export * from './types'; diff --git a/src/lib/server/utils/request-handler/request-handler.ts b/src/lib/server/utils/request-handler/request-handler.ts new file mode 100644 index 0000000..090de89 --- /dev/null +++ b/src/lib/server/utils/request-handler/request-handler.ts @@ -0,0 +1,36 @@ +import { type Action, type ActionFailure, fail } from '@sveltejs/kit'; + +import { Exception } from '../exception'; +import { parseBody } from './body'; +import { getContext } from './context'; +import { Handler } from './handler'; +import { assertRequest } from './request.policy'; +import type { Callback, RequestHandlerOptions } from './types'; + +const handleError = (e: unknown): ActionFailure<{ error: string; message: unknown }> => { + if (e instanceof Exception) { + return fail(e.status, { error: e.error, message: e.message }); + } + return fail(500, { error: 'Internal Server Error', message: e }); +}; + +export const useRequestHandler = ( + callback: Callback, + options?: RequestHandlerOptions, +): Action => { + return async (event) => { + try { + const context = await getContext(event); + + const body = parseBody(await event.request.json(), options?.body); + + assertRequest(context, options); + + const handler = new Handler(context, event, body); + + return await callback(handler); + } catch (e) { + return handleError(e); + } + }; +}; diff --git a/src/lib/server/utils/request-handler/request.policy.ts b/src/lib/server/utils/request-handler/request.policy.ts new file mode 100644 index 0000000..f72eac5 --- /dev/null +++ b/src/lib/server/utils/request-handler/request.policy.ts @@ -0,0 +1,36 @@ +import { Exception } from '../exception'; +import type { Context } from './context'; +import type { RequestHandlerOptions } from './request-handler'; + +const DEFAULT_OPTIONS: RequestHandlerOptions = { + onlineOnly: false, + offlineOnly: false, + projectOptional: false, +}; + +const assertProject = (context: Context, options: RequestHandlerOptions): void | never => { + if (!options.projectOptional) return; + + if (!context.session) throw new Exception('Bad Request', 'No session', 400); + if (!context.project) throw new Exception('Bad Request', 'Request required a project', 400); + + if (context.online && !context.project.gateway) + throw new Exception('Internal Server Error', "Project don't have gateway on online mode", 500); +}; + +const assertMode = (context: Context, options: RequestHandlerOptions): void | never => { + if (options.onlineOnly && !context.online) + throw new Exception('Method Not Allowed', 'This action is not available offline', 405); + if (options.offlineOnly && context.online) + throw new Exception('Method Not Allowed', 'This action is not available online', 405); +}; + +export const assertRequest = ( + context: Context, + rawOptions?: RequestHandlerOptions, +): void | never => { + const options = { ...DEFAULT_OPTIONS, ...rawOptions }; + + assertMode(context, options); + assertProject(context, options); +}; diff --git a/src/lib/server/utils/request-handler/types.ts b/src/lib/server/utils/request-handler/types.ts new file mode 100644 index 0000000..c676e47 --- /dev/null +++ b/src/lib/server/utils/request-handler/types.ts @@ -0,0 +1,28 @@ +import { type RequestEvent } from '@sveltejs/kit'; + +import { type Api } from '$lib/server/api'; +import { type FileSystem } from '$lib/server/file-system'; + +import type { ClassType, MaybePromise } from '@utils/types'; + +import type { Context } from './context'; +import { type Handler } from './handler'; + +export interface CallbackOptions { + event: RequestEvent; + body: Body; + context: Context; + api: (context?: Context) => Api; + cli: (context?: Context) => void; + fs: (context?: Context) => FileSystem; + loader: (context?: Context) => void; +} + +export type Callback = (opts: Handler) => MaybePromise; + +export interface RequestHandlerOptions { + onlineOnly?: boolean; + offlineOnly?: boolean; + projectOptional?: boolean; + body?: ClassType; +} diff --git a/src/lib/server/utils/types/index.ts b/src/lib/server/utils/types/index.ts new file mode 100644 index 0000000..46fce1d --- /dev/null +++ b/src/lib/server/utils/types/index.ts @@ -0,0 +1 @@ +export * from './tokens.type'; diff --git a/src/lib/server/utils/types/tokens.type.ts b/src/lib/server/utils/types/tokens.type.ts new file mode 100644 index 0000000..20fabe0 --- /dev/null +++ b/src/lib/server/utils/types/tokens.type.ts @@ -0,0 +1,4 @@ +export interface Tokens { + accessToken: string; + refreshToken?: string; +} diff --git a/src/lib/server/client.ts b/src/lib/utils/http/client.ts similarity index 100% rename from src/lib/server/client.ts rename to src/lib/utils/http/client.ts diff --git a/src/lib/utils/http/index.ts b/src/lib/utils/http/index.ts index 866345e..2d6ee12 100644 --- a/src/lib/utils/http/index.ts +++ b/src/lib/utils/http/index.ts @@ -3,4 +3,4 @@ export { type MiddlewareNext, type MiddlewareParams, type RequestOptions, -} from '../../server/client'; +} from './client'; diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts deleted file mode 100644 index c202386..0000000 --- a/src/lib/utils/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './http'; diff --git a/src/lib/utils/string.ts b/src/lib/utils/string.ts new file mode 100644 index 0000000..08c33af --- /dev/null +++ b/src/lib/utils/string.ts @@ -0,0 +1,6 @@ +import crypto from 'crypto'; + +export const generateKey = (size = 50) => { + const buffer = crypto.randomBytes(size); + return buffer.toString('base64url').substring(0, size); +}; diff --git a/src/lib/utils/types/class.type.ts b/src/lib/utils/types/class.type.ts new file mode 100644 index 0000000..3b2428a --- /dev/null +++ b/src/lib/utils/types/class.type.ts @@ -0,0 +1 @@ +export type ClassType = new (...args: any[]) => T; diff --git a/src/lib/utils/types/index.ts b/src/lib/utils/types/index.ts new file mode 100644 index 0000000..160846b --- /dev/null +++ b/src/lib/utils/types/index.ts @@ -0,0 +1,2 @@ +export * from './class.type'; +export * from './promise.type'; diff --git a/src/lib/utils/types/promise.type.ts b/src/lib/utils/types/promise.type.ts new file mode 100644 index 0000000..9cd354b --- /dev/null +++ b/src/lib/utils/types/promise.type.ts @@ -0,0 +1 @@ +export type MaybePromise = T | Promise; diff --git a/src/routes/actions/project/+page.server.ts b/src/routes/actions/project/+page.server.ts new file mode 100644 index 0000000..fa377c9 --- /dev/null +++ b/src/routes/actions/project/+page.server.ts @@ -0,0 +1,5 @@ +import { loadProjectAction } from '$lib/server/actions/project/load.actions'; + +export const actions = { + load: loadProjectAction, +}; diff --git a/src/routes/fs/+page.server.ts b/src/routes/fs/+page.server.ts index c97dcaa..4ffa087 100644 --- a/src/routes/fs/+page.server.ts +++ b/src/routes/fs/+page.server.ts @@ -1,8 +1,8 @@ import { fail } from '@sveltejs/kit'; -import { FileSystemError } from '@utils-server/file-system/file-system-error'; -import { ProjectDirectory } from '@utils-server/file-system/project-directory'; -import { ProjectFile } from '@utils-server/file-system/project-file'; +import { FileSystemError } from '$lib/server/file-system/file-system-error'; +import { ProjectDirectory } from '$lib/server/file-system/project-directory'; +import { ProjectFile } from '$lib/server/file-system/project-file'; import type { Actions } from './$types'; diff --git a/src/routes/game-loader/+page.server.ts b/src/routes/game-loader/+page.server.ts index f709658..c07cb77 100644 --- a/src/routes/game-loader/+page.server.ts +++ b/src/routes/game-loader/+page.server.ts @@ -2,13 +2,12 @@ import { fail } from '@sveltejs/kit'; import type { Save } from '$lib/loader/client/types/save.type'; import { getGameEnv } from '$lib/loader/server/env'; - -import { FileSystemError } from '@utils-server/file-system/file-system-error'; +import { FileSystemError } from '$lib/server/file-system/file-system-error'; import { ProjectDirectory, directoryContentToFileEntries, -} from '@utils-server/file-system/project-directory'; -import { ProjectFile } from '@utils-server/file-system/project-file'; +} from '$lib/server/file-system/project-directory'; +import { ProjectFile } from '$lib/server/file-system/project-file'; import type { Actions } from './$types'; From f6c5f61f70ced1d9e099a87188a42bc6fb7e3b8f Mon Sep 17 00:00:00 2001 From: Exelo Date: Tue, 28 Apr 2026 21:47:18 +0900 Subject: [PATCH 02/58] chore: add git and cli handlers --- src/lib/server/cli/cli-defaults.ts | 34 ++++++ src/lib/server/cli/cli-error.ts | 7 ++ src/lib/server/cli/cli.ts | 115 ++++++++++++++++++ src/lib/server/cli/cli.type.ts | 75 ++++++++++++ src/lib/server/cli/index.ts | 1 + src/lib/server/git/git.ts | 57 +++++++++ src/lib/server/git/index.ts | 1 + src/lib/server/project/load-project.ts | 9 +- src/lib/server/session/index.ts | 4 +- .../session/project/project-functions.ts | 12 +- src/lib/server/session/session-functions.ts | 5 +- src/lib/server/utils/request-handler/body.ts | 1 + .../server/utils/request-handler/handler.ts | 12 +- src/lib/utils/string.ts | 3 + src/lib/utils/types/base.type.ts | 1 + 15 files changed, 314 insertions(+), 23 deletions(-) create mode 100644 src/lib/server/cli/cli-defaults.ts create mode 100644 src/lib/server/cli/cli-error.ts create mode 100644 src/lib/server/cli/cli.ts create mode 100644 src/lib/server/cli/cli.type.ts create mode 100644 src/lib/server/cli/index.ts create mode 100644 src/lib/server/git/git.ts create mode 100644 src/lib/server/git/index.ts create mode 100644 src/lib/utils/types/base.type.ts diff --git a/src/lib/server/cli/cli-defaults.ts b/src/lib/server/cli/cli-defaults.ts new file mode 100644 index 0000000..360d7d5 --- /dev/null +++ b/src/lib/server/cli/cli-defaults.ts @@ -0,0 +1,34 @@ +import type { WithOptional } from '@utils/types/base.type'; + +import type { + CliBuildOptions, + CliCreateOptions, + CliDevOptions, + CliGenerateOptions, + CliInstallOptions, + CliNewOptions, + CliStartOptions, +} from './cli.type'; + +export const CLI_NEW_DEFAULTS: WithOptional = { + packageManager: 'npm', + language: 'ts', + strict: false, + server: false, + skipInstall: false, + docker: false, + git: false, + gitRemote: false, +}; + +export const CLI_INSTALL_DEFAULTS: WithOptional = {}; + +export const CLI_BUILD_DEFAULTS: WithOptional = {}; + +export const CLI_START_DEFAULTS: WithOptional = {}; + +export const CLI_DEV_DEFAULTS: WithOptional = {}; + +export const CLI_GENERATE_DEFAULTS: WithOptional = {}; + +export const CLI_CREATE_DEFAULTS: WithOptional = {}; diff --git a/src/lib/server/cli/cli-error.ts b/src/lib/server/cli/cli-error.ts new file mode 100644 index 0000000..a127ed2 --- /dev/null +++ b/src/lib/server/cli/cli-error.ts @@ -0,0 +1,7 @@ +import { Exception } from '@utils-server/exception'; + +export class CliError extends Exception { + constructor(message: string) { + super('Internal Server Error', message, 500); + } +} diff --git a/src/lib/server/cli/cli.ts b/src/lib/server/cli/cli.ts new file mode 100644 index 0000000..4d24f67 --- /dev/null +++ b/src/lib/server/cli/cli.ts @@ -0,0 +1,115 @@ +import { camelToKebab } from '@utils/string'; + +import type { Context } from '@utils-server/request-handler'; + +import { CliError } from './cli-error'; +import type { + CliBuildOptions, + CliCreateOptions, + CliDevOptions, + CliGenerateOptions, + CliInstallOptions, + CliNewOptions, + CliPartial, + CliRunOptions, + CliStartOptions, +} from './cli.type'; + +export class Cli { + private readonly _projectPath?: string; + + constructor(context: Context) { + this._projectPath = context.project?.path; + } + + new(opts: CliPartial, runOpts?: CliRunOptions): void { + return this.runCommand('new', [], opts, runOpts); + } + + install( + pkgs: [string, ...string[]], + opts: CliPartial, + runOpts?: CliRunOptions, + ): void { + this.assertProject(); + return this.runCommand('install', pkgs, { ...opts, directory: this._projectPath }, runOpts); + } + + build(opts: CliPartial, runOpts?: CliRunOptions): void { + this.assertProject(); + return this.runCommand('build', [], { ...opts, directory: this._projectPath }, runOpts); + } + + start(opts: CliPartial, runOpts?: CliRunOptions): void { + this.assertProject(); + return this.runCommand('start', [], { ...opts, directory: this._projectPath }, runOpts); + } + + dev(opts: CliPartial, runOpts?: CliRunOptions): void { + this.assertProject(); + return this.runCommand('dev', [], { ...opts, directory: this._projectPath }, runOpts); + } + + generate(opts: CliPartial, runOpts?: CliRunOptions): void { + return this.runCommand('generate', [], { ...opts, directory: this._projectPath }, runOpts); + } + + create( + part: 'component' | 'system', + opts: CliPartial, + runOpts?: CliRunOptions, + ): void { + this.assertProject(); + return this.runCommand('create', [part], { ...opts, directory: this._projectPath }, runOpts); + } + + private runCommand( + command: string, + params: string[], + opts: Record, + { async = false }: CliRunOptions = {}, + ): void { + const fullCommand = ['nf', command, ...params, ...this.resolveParams(opts)]; + + if (async) { + const res = Bun.spawn(fullCommand, { stdout: 'pipe', stderr: 'pipe' }); + res.exited.then((exitCode) => { + if (exitCode !== 0) { + console.log(res.stdout.toString()); + console.error(res.stderr.toString()); + throw new CliError(res.stderr.toString()); + } + }); + } else { + const res = Bun.spawnSync(fullCommand, { stdout: 'pipe', stderr: 'pipe' }); + + if (res.exitCode !== 0) { + console.log(res.stdout.toString()); + console.error(res.stderr.toString()); + throw new CliError(res.stderr.toString()); + } + } + } + + private resolveParams(opts: Record): string[] { + const params = []; + for (const [key, value] of Object.entries(opts)) { + if (value === undefined) continue; + + const name = camelToKebab(key); + + if (typeof value === 'boolean') { + if (value) params.push(`--${name}`); + else params.push(`--no-${name}`); + } else { + params.push(`--${name}`, `'${value}'`); + } + } + return params; + } + + private assertProject() { + if (!this._projectPath) throw new CliError('No project path set'); + if (!Bun.file(this._projectPath).exists()) throw new CliError('Project does not exist'); + } +} diff --git a/src/lib/server/cli/cli.type.ts b/src/lib/server/cli/cli.type.ts new file mode 100644 index 0000000..4b805fc --- /dev/null +++ b/src/lib/server/cli/cli.type.ts @@ -0,0 +1,75 @@ +export type CliPartial = (T extends { directory?: string } + ? Omit, 'directory'> + : Partial) & + Pick; + +export interface CliRunOptions { + async?: boolean; +} + +export interface CliNewOptions { + directory?: string; + name: string; + path?: string; + packageManager: 'npm' | 'pnpm' | 'yarn' | 'bun'; + language: 'js' | 'ts'; + strict: boolean; + server: boolean; + initFunctions?: boolean; + skipInstall: boolean; + docker: boolean; + lint?: false; + editor?: true; + git: boolean; + gitRemote: string | false; +} + +export interface CliInstallOptions { + directory?: string; + lib?: true; + server?: true; +} + +export interface CliBuildOptions { + directory?: string; + config?: string; + clientEntry?: string; + serverEntry?: string; + clientStaticDir?: string; + serverStaticDir?: string; + clientOutDir?: string; + serverOutDir?: string; + editor?: true; + watch?: true; +} + +export interface CliStartOptions { + directory?: string; + config?: string; + clientDir?: string; + serverDir?: string; + watch?: true; + cert?: string; + key?: string; +} + +export interface CliDevOptions { + directory?: string; + config?: string; + generate?: true; +} + +export interface CliGenerateOptions { + directory?: string; + config?: string; + editor?: true; + watch?: true; +} + +export interface CliCreateOptions { + directory?: string; + config?: string; + name: string; + server?: true; + path?: string; +} diff --git a/src/lib/server/cli/index.ts b/src/lib/server/cli/index.ts new file mode 100644 index 0000000..52a6764 --- /dev/null +++ b/src/lib/server/cli/index.ts @@ -0,0 +1 @@ +export { Cli } from './cli'; diff --git a/src/lib/server/git/git.ts b/src/lib/server/git/git.ts new file mode 100644 index 0000000..46ee2de --- /dev/null +++ b/src/lib/server/git/git.ts @@ -0,0 +1,57 @@ +import { $ } from 'bun'; +import { join } from 'path'; + +import { env } from '$env/dynamic/private'; + +import { generateKey } from '@utils/string'; + +export class Git { + private readonly _rootPath: string; + + constructor() { + this._rootPath = join(process.cwd(), env.GIT_ROOT ?? ''); + } + + async clone(url: string, options?: { sshKey?: string }): Promise { + const path = await this.resolvePath(url); + await this.runCommand('clone', `${url} ${path}`, { ...options }); + return path; + } + + private async runCommand( + command: string, + params: string, + options?: { path?: string; sshKey?: string }, + ) { + let sshPath = undefined; + if (options?.sshKey) { + sshPath = await this.createSshKeyFile(options.sshKey); + } + const sshConfig = sshPath ? `-c core.sshCommand="ssh -i ${sshPath}" ` : ''; + const cwd = join(this._rootPath, options?.path ?? ''); + + await $`git ${command} ${sshConfig}${params}`.cwd(cwd); + if (sshPath) await this.deleteSshKeyFile(sshPath); + } + + private async createSshKeyFile(sshKey: string): Promise { + const path = `/tmp/nanoforge/${generateKey()}`; + await Bun.file(path).write(sshKey); + return path; + } + + private async deleteSshKeyFile(path: string): Promise { + await Bun.file(path).delete(); + } + + private async resolvePath(url: string) { + const basePath = url.split('/').pop()?.replace('.git', ''); + if (!basePath) throw new Error('Invalid URL'); + + const fullBasePath = join(this._rootPath, basePath); + let path = fullBasePath; + + while (await Bun.file(path).exists()) path = join(fullBasePath, generateKey(5)); + return path; + } +} diff --git a/src/lib/server/git/index.ts b/src/lib/server/git/index.ts new file mode 100644 index 0000000..3a6f073 --- /dev/null +++ b/src/lib/server/git/index.ts @@ -0,0 +1 @@ +export { Git } from './git'; diff --git a/src/lib/server/project/load-project.ts b/src/lib/server/project/load-project.ts index 8103c30..bc0208a 100644 --- a/src/lib/server/project/load-project.ts +++ b/src/lib/server/project/load-project.ts @@ -1,12 +1,15 @@ -import type { SessionProject } from '$lib/server/session'; -import { tryAddProjectSession } from '$lib/server/session/project/project-functions'; -import { addProjectToSession } from '$lib/server/session/session-functions'; +import { + type SessionProject, + addProjectToSession, + tryAddProjectSession, +} from '$lib/server/session'; import { type Handler } from '@utils-server/request-handler'; import type { Project } from './project.type'; export const loadProject = async (session: SessionProject, handler: Handler): Promise => { + // @todo add getOrCreateSession(handler.event.locals.session) and remove id from session const projectId = tryAddProjectSession(session); addProjectToSession(handler.context.session, projectId); diff --git a/src/lib/server/session/index.ts b/src/lib/server/session/index.ts index 5efcf89..df2eb97 100644 --- a/src/lib/server/session/index.ts +++ b/src/lib/server/session/index.ts @@ -1,5 +1,5 @@ export * from './session-handle'; -export { resolveSession } from './session-functions'; +export { resolveSession, addProjectToSession } from './session-functions'; export type { Session } from './session.type'; -export { resolveProject } from './project/project-functions'; +export { resolveProject, tryAddProjectSession } from './project/project-functions'; export type { SessionProject } from './project/project.type'; diff --git a/src/lib/server/session/project/project-functions.ts b/src/lib/server/session/project/project-functions.ts index 0af1481..ecbef10 100644 --- a/src/lib/server/session/project/project-functions.ts +++ b/src/lib/server/session/project/project-functions.ts @@ -5,18 +5,12 @@ import { SESSION_PROJECT_HEADER } from './project.const'; import { projectStore } from './project.store'; import type { SessionProject } from './project.type'; -export const isProjectExist = (id: string | null | undefined) => { - if (!id) return false; - if (!projectStore.has(id)) return false; - - return true; +export const projectExists = (id: string | null | undefined) => { + return !!id && projectStore.has(id); }; export const hasRightToAccessProject = (id: string | null | undefined, session: Session) => { - if (!isProjectExist(id)) return false; - if (!session.projects.includes(id as string)) return false; - - return true; + return projectExists(id) && session.projects.includes(id as string); }; export const resolveProject = (headers: Headers, session: Session) => { diff --git a/src/lib/server/session/session-functions.ts b/src/lib/server/session/session-functions.ts index 4e7c920..ac75d60 100644 --- a/src/lib/server/session/session-functions.ts +++ b/src/lib/server/session/session-functions.ts @@ -7,10 +7,7 @@ import { sessionStore } from './session.store'; import type { Session } from './session.type'; export const isPublicPath = (url: URL) => { - if (PUBLIC_PATHS.includes(url.pathname)) return true; - if (url.pathname.startsWith('/api')) return true; - - return false; + return PUBLIC_PATHS.includes(url.pathname) || url.pathname.startsWith('/actions'); }; export const resolveSession = async (sessionHandler: SvelteSession): Promise => { diff --git a/src/lib/server/utils/request-handler/body.ts b/src/lib/server/utils/request-handler/body.ts index 62daae6..bccee97 100644 --- a/src/lib/server/utils/request-handler/body.ts +++ b/src/lib/server/utils/request-handler/body.ts @@ -1,6 +1,7 @@ import type { ClassType } from '@utils/types'; export const parseBody = (baseBody: any, c: ClassType | undefined): Body => { + // @todo add class validation and class transformation void c; return baseBody as Body; }; diff --git a/src/lib/server/utils/request-handler/handler.ts b/src/lib/server/utils/request-handler/handler.ts index 5158aa5..c4fa424 100644 --- a/src/lib/server/utils/request-handler/handler.ts +++ b/src/lib/server/utils/request-handler/handler.ts @@ -1,7 +1,9 @@ import type { RequestEvent } from '@sveltejs/kit'; import { type Api, getApi } from '$lib/server/api'; +import { Cli } from '$lib/server/cli'; import { FileSystem } from '$lib/server/file-system'; +import { Git } from '$lib/server/git'; import type { Context } from '@utils-server/request-handler/context'; @@ -11,10 +13,10 @@ export class Handler { private readonly _body: Body; private _apiCache: Api | undefined; - private _cliCache: any | undefined; + private _cliCache: Cli | undefined; private _fsCache: FileSystem | undefined; private _loaderCache: any | undefined; - private _gitCache: any | undefined; + private _gitCache: Git | undefined; constructor(context: Context, event: RequestEvent, body: Body) { this._context = context; @@ -50,7 +52,7 @@ export class Handler { } get cli(): any { - if (!this._cliCache) this._cliCache = {}; + if (!this._cliCache) this._cliCache = new Cli(this._context); return this._cliCache; } @@ -64,8 +66,8 @@ export class Handler { return this._loaderCache; } - get git(): any { - if (!this._gitCache) this._gitCache = {}; + get git(): Git { + if (!this._gitCache) this._gitCache = new Git(); return this._gitCache; } } diff --git a/src/lib/utils/string.ts b/src/lib/utils/string.ts index 08c33af..b72b698 100644 --- a/src/lib/utils/string.ts +++ b/src/lib/utils/string.ts @@ -4,3 +4,6 @@ export const generateKey = (size = 50) => { const buffer = crypto.randomBytes(size); return buffer.toString('base64url').substring(0, size); }; + +export const camelToKebab = (str: string) => + str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`); diff --git a/src/lib/utils/types/base.type.ts b/src/lib/utils/types/base.type.ts new file mode 100644 index 0000000..c5187d9 --- /dev/null +++ b/src/lib/utils/types/base.type.ts @@ -0,0 +1 @@ +export type WithOptional = Omit & Partial>; From a1af88558e90fc4b793f2b56a90b0dec14978a84 Mon Sep 17 00:00:00 2001 From: Exelo Date: Tue, 28 Apr 2026 22:05:54 +0900 Subject: [PATCH 03/58] chore: fix build and upgrade deps --- package.json | 7 +- pnpm-lock.yaml | 1406 +++++++++++++++++++++---------------------- pnpm-workspace.yaml | 38 +- 3 files changed, 698 insertions(+), 753 deletions(-) diff --git a/package.json b/package.json index 4f66737..a73af83 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,9 @@ }, "funding": "https://github.com/NanoForge-dev/Editor?sponsor", "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview", + "dev": "bun --bun run vite dev", + "build": "bun --bun run vite build", + "preview": "bun --bun run vite preview", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "lint": "prettier --check . && eslint --format=pretty src", @@ -77,6 +77,7 @@ "@unocss/preset-wind4": "catalog:css", "@vitest/browser-playwright": "catalog:test", "@vitest/coverage-v8": "catalog:test", + "bun": "catalog:core", "eslint": "catalog:lint", "eslint-plugin-svelte": "catalog:lint", "flowbite": "catalog:components", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a85d308..8ed73b4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,12 +13,12 @@ catalogs: specifier: ^1.0.1 version: 1.0.1 typescript: - specifier: ^6.0.2 + specifier: ^6.0.3 version: 6.0.3 ci: '@commitlint/cli': - specifier: ^20.5.0 - version: 20.5.0 + specifier: ^20.5.2 + version: 20.5.2 '@commitlint/config-conventional': specifier: ^20.5.0 version: 20.5.0 @@ -26,8 +26,8 @@ catalogs: specifier: ^6.1.0 version: 6.1.0 '@nanoforge-dev/actions': - specifier: ^1.2.3 - version: 1.2.3 + specifier: ^1.3.0 + version: 1.3.0 husky: specifier: ^9.1.7 version: 9.1.7 @@ -45,24 +45,27 @@ catalogs: specifier: ^0.55.1 version: 0.55.1 svelte-sonner: - specifier: ^1.1.0 - version: 1.1.0 + specifier: ^1.1.1 + version: 1.1.1 core: '@nanoforge-dev/ecs-lib': specifier: ^1.1.2 version: 1.1.2 '@sveltejs/kit': - specifier: ^2.57.1 - version: 2.57.1 + specifier: ^2.58.0 + version: 2.58.0 '@sveltejs/vite-plugin-svelte': specifier: ^7.0.0 version: 7.0.0 '@types/bun': - specifier: ^1.3.12 - version: 1.3.12 + specifier: ^1.3.13 + version: 1.3.13 + bun: + specifier: ^1.3.13 + version: 1.3.13 svelte: - specifier: ^5.55.3 - version: 5.55.4 + specifier: ^5.55.5 + version: 5.55.5 svelte-check: specifier: ^4.4.6 version: 4.4.6 @@ -70,8 +73,8 @@ catalogs: specifier: ^0.4.0 version: 0.4.0 vite: - specifier: ^8.0.8 - version: 8.0.8 + specifier: ^8.0.10 + version: 8.0.10 css: '@alexanderniebuhr/prettier-plugin-unocss': specifier: ^0.0.4 @@ -93,15 +96,15 @@ catalogs: version: 66.6.8 i18n: '@inlang/paraglide-js': - specifier: ^2.15.3 - version: 2.16.0 + specifier: ^2.17.0 + version: 2.17.0 icons: '@iconify-json/ic': specifier: ^1.2.4 version: 1.2.4 '@iconify-json/material-icon-theme': - specifier: ^1.2.58 - version: 1.2.59 + specifier: ^1.2.61 + version: 1.2.61 '@iconify-json/solar': specifier: ^1.2.5 version: 1.2.5 @@ -116,39 +119,39 @@ catalogs: specifier: ^6.0.2 version: 6.0.2 eslint: - specifier: ^10.2.0 + specifier: ^10.2.1 version: 10.2.1 eslint-plugin-svelte: - specifier: ^3.17.0 - version: 3.17.0 + specifier: ^3.17.1 + version: 3.17.1 globals: specifier: ^17.5.0 version: 17.5.0 prettier: - specifier: ^3.8.2 + specifier: ^3.8.3 version: 3.8.3 prettier-plugin-svelte: specifier: ^3.5.1 version: 3.5.1 typescript-eslint: - specifier: ^8.58.2 - version: 8.58.2 + specifier: ^8.59.1 + version: 8.59.1 test: '@playwright/test': specifier: ^1.59.1 version: 1.59.1 '@vitest/browser-playwright': - specifier: ^4.1.4 - version: 4.1.4 + specifier: ^4.1.5 + version: 4.1.5 '@vitest/coverage-v8': - specifier: ^4.1.4 - version: 4.1.4 + specifier: ^4.1.5 + version: 4.1.5 playwright: specifier: ^1.59.1 version: 1.59.1 vitest: - specifier: ^4.1.4 - version: 4.1.4 + specifier: ^4.1.5 + version: 4.1.5 vitest-browser-svelte: specifier: ^2.1.1 version: 2.1.1 @@ -162,7 +165,7 @@ importers: version: 0.0.4 '@commitlint/cli': specifier: catalog:ci - version: 20.5.0(@types/node@25.6.0)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3) + version: 20.5.2(@types/node@25.6.0)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3) '@commitlint/config-conventional': specifier: catalog:ci version: 20.5.0 @@ -174,16 +177,16 @@ importers: version: 1.2.4 '@iconify-json/material-icon-theme': specifier: catalog:icons - version: 1.2.59 + version: 1.2.61 '@iconify-json/solar': specifier: catalog:icons version: 1.2.5 '@inlang/paraglide-js': specifier: catalog:i18n - version: 2.16.0 + version: 2.17.0 '@nanoforge-dev/actions': specifier: catalog:ci - version: 1.2.3 + version: 1.3.0 '@nanoforge-dev/ecs-lib': specifier: catalog:core version: 1.1.2 @@ -198,19 +201,19 @@ importers: version: 1.59.1 '@sveltejs/kit': specifier: catalog:core - version: 2.57.1(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.4(@typescript-eslint/types@8.58.2))(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.4(@typescript-eslint/types@8.58.2))(typescript@6.0.3)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + version: 2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) '@sveltejs/vite-plugin-svelte': specifier: catalog:core - version: 7.0.0(svelte@5.55.4(@typescript-eslint/types@8.58.2))(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + version: 7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier-plugin-svelte@3.5.1(prettier@3.8.3)(svelte@5.55.4(@typescript-eslint/types@8.58.2)))(prettier@3.8.3)(svelte@5.55.4(@typescript-eslint/types@8.58.2)) + version: 6.0.2(prettier-plugin-svelte@3.5.1(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1)))(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1)) '@tsconfig/svelte': specifier: catalog:build version: 5.0.8 '@types/bun': specifier: catalog:core - version: 1.3.12 + version: 1.3.13 '@unocss/extractor-svelte': specifier: catalog:css version: 66.6.8 @@ -225,22 +228,25 @@ importers: version: 66.6.8 '@vitest/browser-playwright': specifier: catalog:test - version: 4.1.4(playwright@1.59.1)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.4) + version: 4.1.5(playwright@1.59.1)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.5) '@vitest/coverage-v8': specifier: catalog:test - version: 4.1.4(@vitest/browser@4.1.4)(vitest@4.1.4) + version: 4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5) + bun: + specifier: catalog:core + version: 1.3.13 eslint: specifier: catalog:lint version: 10.2.1(jiti@2.6.1) eslint-plugin-svelte: specifier: catalog:lint - version: 3.17.0(eslint@10.2.1(jiti@2.6.1))(svelte@5.55.4(@typescript-eslint/types@8.58.2)) + version: 3.17.1(eslint@10.2.1(jiti@2.6.1))(svelte@5.55.5(@typescript-eslint/types@8.59.1)) flowbite: specifier: catalog:components version: 4.0.1 flowbite-svelte: specifier: catalog:components - version: 1.33.1(svelte@5.55.4(@typescript-eslint/types@8.58.2))(tailwindcss@4.2.2) + version: 1.33.1(svelte@5.55.5(@typescript-eslint/types@8.59.1))(tailwindcss@4.2.4) globals: specifier: catalog:lint version: 17.5.0 @@ -261,57 +267,57 @@ importers: version: 3.8.3 prettier-plugin-svelte: specifier: catalog:lint - version: 3.5.1(prettier@3.8.3)(svelte@5.55.4(@typescript-eslint/types@8.58.2)) + version: 3.5.1(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1)) svelte: specifier: catalog:core - version: 5.55.4(@typescript-eslint/types@8.58.2) + version: 5.55.5(@typescript-eslint/types@8.59.1) svelte-adapter-bun: specifier: catalog:build - version: 1.0.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.4(@typescript-eslint/types@8.58.2))(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.4(@typescript-eslint/types@8.58.2))(typescript@6.0.3)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(typescript@6.0.3) + version: 1.0.1(@sveltejs/kit@2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(typescript@6.0.3) svelte-check: specifier: catalog:core - version: 4.4.6(picomatch@4.0.4)(svelte@5.55.4(@typescript-eslint/types@8.58.2))(typescript@6.0.3) + version: 4.4.6(picomatch@4.0.4)(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3) svelte-kit-sessions: specifier: catalog:core - version: 0.4.0(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.4(@typescript-eslint/types@8.58.2))(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.4(@typescript-eslint/types@8.58.2))(typescript@6.0.3)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.4(@typescript-eslint/types@8.58.2)) + version: 0.4.0(@sveltejs/kit@2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1)) svelte-sonner: specifier: catalog:components - version: 1.1.0(svelte@5.55.4(@typescript-eslint/types@8.58.2)) + version: 1.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.1)) typescript: specifier: catalog:build version: 6.0.3 typescript-eslint: specifier: catalog:lint - version: 8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + version: 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) unocss: specifier: catalog:css - version: 66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + version: 66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) vite: specifier: catalog:core - version: 8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) + version: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) vitest: specifier: catalog:test - version: 4.1.4(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@4.1.4)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + version: 4.1.5(@types/node@25.6.0)(@vitest/browser-playwright@4.1.5)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) vitest-browser-svelte: specifier: catalog:test - version: 2.1.1(svelte@5.55.4(@typescript-eslint/types@8.58.2))(vitest@4.1.4) + version: 2.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vitest@4.1.5) packages: - '@actions/core@3.0.0': - resolution: {integrity: sha512-zYt6cz+ivnTmiT/ksRVriMBOiuoUpDCJJlZ5KPl2/FRdvwU3f7MPh9qftvbkXJThragzUZieit2nyHUyw53Seg==} + '@actions/core@3.0.1': + resolution: {integrity: sha512-a6d/Nwahm9fliVGRhdhofo40HjHQasUPusmc7vBfyky+7Z+P2A1J68zyFVaNcEclc/Se+eO595oAr5nwEIoIUA==} '@actions/exec@3.0.0': resolution: {integrity: sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw==} - '@actions/github@9.1.0': - resolution: {integrity: sha512-u0hDGQeCS+7VNoLA8hYG65RLdPLMaPGfka0sZ0up7P0AiShqfX6xcuXNteGkQ7X7Tod7AMNwHd4p7DS63i8zzA==} + '@actions/github@9.1.1': + resolution: {integrity: sha512-tL5JbYOBZHc0ngEnCsaDcryUizIUIlQyIMwy1Wkx93H5HzbBJ7TbiPx2PnFjBwZW0Vh05JmfFZhecE6gglYegA==} '@actions/http-client@3.0.2': resolution: {integrity: sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==} - '@actions/http-client@4.0.0': - resolution: {integrity: sha512-QuwPsgVMsD6qaPD57GLZi9sqzAZCtiJT8kVBCDpLtxhL5MydQ4gS+DrejtZZPdIYyB1e95uCK9Luyds7ybHI3g==} + '@actions/http-client@4.0.1': + resolution: {integrity: sha512-+Nvd1ImaOZBSoPbsUtEhv+1z99H12xzncCkz0a3RuehINE81FZSe2QTj3uvAPTcJX/SCzUQHQ0D1GrPMbrPitg==} '@actions/io@3.0.2': resolution: {integrity: sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==} @@ -370,8 +376,8 @@ packages: '@blazediff/core@1.9.1': resolution: {integrity: sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==} - '@commitlint/cli@20.5.0': - resolution: {integrity: sha512-yNkyN/tuKTJS3wdVfsZ2tXDM4G4Gi7z+jW54Cki8N8tZqwKBltbIvUUrSbT4hz1bhW/h0CdR+5sCSpXD+wMKaQ==} + '@commitlint/cli@20.5.2': + resolution: {integrity: sha512-IXr5xd3IX8SEG936P8gcpozRplkDeDSwJlt8UvoY1winwIy2udTbQ/cOCgbaaxcjdDqVoS29VUcz/wkwnSozbA==} engines: {node: '>=v18'} hasBin: true @@ -403,8 +409,8 @@ packages: resolution: {integrity: sha512-jiM3hNUdu04jFBf1VgPdjtIPvbuVfDTBAc6L98AWcoLjF5sYqkulBHBzlVWll4rMF1T5zeQFB6r//a+s+BBKlA==} engines: {node: '>=v18'} - '@commitlint/load@20.5.0': - resolution: {integrity: sha512-sLhhYTL/KxeOTZjjabKDhwidGZan84XKK1+XFkwDYL/4883kIajcz/dZFAhBJmZPtL8+nBx6bnkzA95YxPeDPw==} + '@commitlint/load@20.5.2': + resolution: {integrity: sha512-zmr0RGDz7vThxW1I8ohb9yBjnGuH9mqwJpn21hInjGla+IlLOkS9ey0+dD5HlkzFlY0lX2NYdA2lDW6/0rO7Gw==} engines: {node: '>=v18'} '@commitlint/message@20.4.3': @@ -419,8 +425,8 @@ packages: resolution: {integrity: sha512-JDEIJ2+GnWpK8QqwfmW7O42h0aycJEWNqcdkJnyzLD11nf9dW2dWLTVEa8Wtlo4IZFGLPATjR5neA5QlOvIH1w==} engines: {node: '>=v18'} - '@commitlint/resolve-extends@20.5.0': - resolution: {integrity: sha512-3SHPWUW2v0tyspCTcfSsYml0gses92l6TlogwzvM2cbxDgmhSRc+fldDjvGkCXJrjSM87BBaWYTPWwwyASZRrg==} + '@commitlint/resolve-extends@20.5.2': + resolution: {integrity: sha512-8EhSCU9eNos/5cI1yg64GW79UH1c64O69AfStCsj4zqy6An/qIphVEXj4/+2M6056T8coz00f+UXFn4WUUP1HQ==} engines: {node: '>=v18'} '@commitlint/rules@20.5.0': @@ -460,11 +466,11 @@ packages: '@dprint/toml@0.7.0': resolution: {integrity: sha512-eFaQTcfxKHB+YyTh83x7GEv+gDPuj9q5NFOTaoj5rZmQTbj6OgjjMxUicmS1R8zYcx8YAq5oA9J3YFa5U6x2gA==} - '@emnapi/core@1.9.2': - resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} - '@emnapi/runtime@1.9.2': - resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==} + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} '@emnapi/wasi-threads@1.2.1': resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} @@ -544,8 +550,8 @@ packages: '@iconify-json/ic@1.2.4': resolution: {integrity: sha512-pzPMmrZrBQuwT7nmtrYdkttun8KalRGgZPIL1Ny9KpF2zjRGIUPN+npTfuD3lrgO/OnSwAoJWuekQwBpt/Cqrw==} - '@iconify-json/material-icon-theme@1.2.59': - resolution: {integrity: sha512-tm5at2S/bm/WMkkQNDD9szc0v1F0Zx2nqdsu5F6SDmK60UJTOZeNqIDEflSXHjptVCepq05/sDh3vLgEHDhqnQ==} + '@iconify-json/material-icon-theme@1.2.61': + resolution: {integrity: sha512-g/JUDumQ0h7wdUffYSmeMP8qSi+iKRK9DUtIttHG9gIlz2KJFbu1bakx9B2qzk8n3mw7FE/tZPMNCwIPksVr0g==} '@iconify-json/solar@1.2.5': resolution: {integrity: sha512-WMAiNwchU8zhfrySww6KQBRIBbsQ6SvgIu2yA+CHGyMima/0KQwT5MXogrZPJGoQF+1Ye3Qj6K+1CiyNn3YkoA==} @@ -553,18 +559,18 @@ packages: '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} - '@iconify/utils@3.1.0': - resolution: {integrity: sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==} + '@iconify/utils@3.1.1': + resolution: {integrity: sha512-MwzoDtw9rO1x+qfgLTV/IVXsHDBqeYZoMIQC8SfxfYSlaSUG+oWiAcoiB1yajAda6mqblm4/1/w2E8tRu7a7Tw==} - '@inlang/paraglide-js@2.16.0': - resolution: {integrity: sha512-O7KKvVoTsGqPRt1VfSvd0UyfSjU2qHiABx968M2decgG7Af6TddW3dTJrTS3I78nOUgRAlYwCYfKefSGD4rGMA==} + '@inlang/paraglide-js@2.17.0': + resolution: {integrity: sha512-dY4yoQkQkF1En1m3qpO22cVGubluU2W78fatLb33s8qe6K8wDqP0mIGZ/oZ0/h609YC8/Y0CkceaLcYeJTcpwg==} hasBin: true '@inlang/recommend-sherlock@0.2.1': resolution: {integrity: sha512-ckv8HvHy/iTqaVAEKrr+gnl+p3XFNwe5D2+6w6wJk2ORV2XkcRkKOJ/XsTUJbPSiyi4PI+p+T3bqbmNx/rDUlg==} - '@inlang/sdk@2.9.1': - resolution: {integrity: sha512-y0C3xaKo6pSGDr3p5OdreRVT3THJpgKVe1lLvG3BE4v9lskp3UfI9cPCbN8X2dpfLt/4ljtehMb5SykpMfJrMg==} + '@inlang/sdk@2.9.2': + resolution: {integrity: sha512-H/iVZEcOtbowKaiq6yirnUR9eyffAOsXpgwWr4eAe45H7l1f1A1Wowb7hVkWQcAE62sL1g76qN4XkyOx2BkV2w==} engines: {node: '>=20.0.0'} '@isaacs/ttlcache@1.4.1': @@ -587,15 +593,15 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@lix-js/sdk@0.4.9': - resolution: {integrity: sha512-30mDkXpx704359oRrJI42bjfCspCiaMItngVBbPkiTGypS7xX4jYbHWQkXI8XuJ7VDB69D0MsVU6xfrBAIrM4A==} + '@lix-js/sdk@0.4.10': + resolution: {integrity: sha512-0dMInAJK/67guTG5rRZaCEhvzC5cCXENOjaePA5AqMXrCE97kaY7SRor9e2vnoGsFIiGqXKlT0MCIoZj36G0gg==} engines: {node: '>=18'} '@lix-js/server-protocol-schema@0.1.1': resolution: {integrity: sha512-jBeALB6prAbtr5q4vTuxnRZZv1M2rKe8iNqRQhFJ4Tv7150unEa0vKyz0hs8Gl3fUGsWaNJBh3J8++fpbrpRBQ==} - '@nanoforge-dev/actions@1.2.3': - resolution: {integrity: sha512-YVQ1e3H5MVHGBku2bA+lMLb+mkDXvJvYN228V6L0R+HXxo82X3Y1oVDKzlsnz+GRvYejJXEsY6jzPrV3pzbGwA==} + '@nanoforge-dev/actions@1.3.0': + resolution: {integrity: sha512-EmArilxSOkmpdBnNhuyIfsXxRNeRugA9LyEp5VRj7n+dhG95UEahgSJll/lautjtYQPX6Dh5ETWwqjjRDclreQ==} engines: {node: '25'} '@nanoforge-dev/common@1.1.0': @@ -668,6 +674,66 @@ packages: '@octokit/types@16.0.0': resolution: {integrity: sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==} + '@oven/bun-darwin-aarch64@1.3.13': + resolution: {integrity: sha512-qAS6Hg8Q14ckfBuqJ2Zh7gBQSVSUHeibSq4OFqBTv6DzyJuxYlr0sdYQzmYmnbPxbqobekqUDTa/4XEaqRi7vg==} + cpu: [arm64] + os: [darwin] + + '@oven/bun-darwin-x64-baseline@1.3.13': + resolution: {integrity: sha512-gMEQayUpmCPYaE9zkNBj9TiQqHupnhjOYcuSzxFjzIjHJBUO4VjNnrpbKVeXNs+rKHFothORDd2QKquu5paSPQ==} + cpu: [x64] + os: [darwin] + + '@oven/bun-darwin-x64@1.3.13': + resolution: {integrity: sha512-kGePeDD4IN4imo+H4uLjQGZLmvyYQg+nKr2P0nt4ksXXrWA4HE+mb0/TUPHfRI127DocXQpew+fvrHuHR5mpJQ==} + cpu: [x64] + os: [darwin] + + '@oven/bun-linux-aarch64-musl@1.3.13': + resolution: {integrity: sha512-UV9EE18VE5aRhWtV2L6MTAGGn3slhJJ2OW/m+FJM15maHm0qf1V7TaZY0FovxhdQRvnklSiQ7Ntv0H5TUX4w0g==} + cpu: [arm64] + os: [linux] + + '@oven/bun-linux-aarch64@1.3.13': + resolution: {integrity: sha512-NbLOJdr+RBFO1vFZ2YUFg4oVJ+2ua6zrwo4ZWRs0jKKcGJWtbY2wY5uz+i0PkwH6b9HYaYDgVTzE4ev06ncYZw==} + cpu: [arm64] + os: [linux] + + '@oven/bun-linux-x64-baseline@1.3.13': + resolution: {integrity: sha512-fOi4ziKzgJG4UrrNd4AicBs6Fu9GY5xOqg+9tC76nuZNDAdSh6++kzab6TNi1Ck0Yzq6zIBIdGit6/0uSbBn8A==} + cpu: [x64] + os: [linux] + + '@oven/bun-linux-x64-musl-baseline@1.3.13': + resolution: {integrity: sha512-fqBKuiiWLEu2dVkowZaXgKS98xfrvBqivdoxRtRP3eINcpI1dcelGbsOz+Xphn7tbGAuBiE1/0AelvvvdqS9rg==} + cpu: [x64] + os: [linux] + + '@oven/bun-linux-x64-musl@1.3.13': + resolution: {integrity: sha512-+VHhE44kEjCXcTFHyc81zfTxL9+vzh9RqIh7gM1iWNhxpctD9kzntbUkP3UTFTwwNjoou1o8VRyxQafvc4OepA==} + cpu: [x64] + os: [linux] + + '@oven/bun-linux-x64@1.3.13': + resolution: {integrity: sha512-UwttIUXoe9fS+40OcjoaRHgZw+HCPFqBVWEXkXqAJ3W7wA0XPZrWsoMAD9sGh3TaLqrwdiMo5xPogwpXhOtVXA==} + cpu: [x64] + os: [linux] + + '@oven/bun-windows-aarch64@1.3.13': + resolution: {integrity: sha512-+EvdRWRCRg95Xea4M2lqSJFTjzQBTJDQTMlbG8bmwFkVTN16MdmSH7xhfxVQWUOyZBLEpIwuNFIlBBxVCwSUyQ==} + cpu: [arm64] + os: [win32] + + '@oven/bun-windows-x64-baseline@1.3.13': + resolution: {integrity: sha512-6gy4hhQSjq/T/S9hC9m3NxY0RY+9Ww+XNlB+8koIMTsMSYEjk7Ho+hFHQz1Bn4W61Ub7Vykufg+jgDgPfa2GFA==} + cpu: [x64] + os: [win32] + + '@oven/bun-windows-x64@1.3.13': + resolution: {integrity: sha512-vqDEFX63ZZQF3YstPSpPD+RxNm5AILPdUuuKpNwsj7ld4NjhdHUYkAmLXDtKNWt9JMRL10bop//W8faY/LV+RQ==} + cpu: [x64] + os: [win32] + '@oxc-parser/binding-android-arm-eabi@0.124.0': resolution: {integrity: sha512-+R9zCafSL8ovjokdPtorUp3sXrh8zQ2AC2L0ivXNvlLR0WS+5WdPkNVrnENq5UvzagM4Xgl0NPsJKz3Hv9+y8g==} engines: {node: ^20.19.0 || >=22.12.0} @@ -798,8 +864,8 @@ packages: '@oxc-project/types@0.124.0': resolution: {integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==} - '@oxc-project/types@0.126.0': - resolution: {integrity: sha512-oGfVtjAgwQVVpfBrbtk4e1XDyWHRFta6BS3GWVzrF8xYBT2VGQAk39yJS/wFSMrZqoiCU4oghT3Ch0HaHGIHcQ==} + '@oxc-project/types@0.127.0': + resolution: {integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==} '@oxfmt/binding-android-arm-eabi@0.35.0': resolution: {integrity: sha512-BaRKlM3DyG81y/xWTsE6gZiv89F/3pHe2BqX2H4JbiB8HNVlWWtplzgATAE5IDSdwChdeuWLDTQzJ92Lglw3ZA==} @@ -941,201 +1007,103 @@ packages: '@quansync/fs@1.0.0': resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} - '@rolldown/binding-android-arm64@1.0.0-rc.15': - resolution: {integrity: sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [android] - - '@rolldown/binding-android-arm64@1.0.0-rc.16': - resolution: {integrity: sha512-rhY3k7Bsae9qQfOtph2Pm2jZEA+s8Gmjoz4hhmx70K9iMQ/ddeae+xhRQcM5IuVx5ry1+bGfkvMn7D6MJggVSA==} + '@rolldown/binding-android-arm64@1.0.0-rc.17': + resolution: {integrity: sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.0-rc.15': - resolution: {integrity: sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==} + '@rolldown/binding-darwin-arm64@1.0.0-rc.17': + resolution: {integrity: sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-arm64@1.0.0-rc.16': - resolution: {integrity: sha512-rNz0yK078yrNn3DrdgN+PKiMOW8HfQ92jQiXxwX8yW899ayV00MLVdaCNeVBhG/TbH3ouYVObo8/yrkiectkcQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [darwin] - - '@rolldown/binding-darwin-x64@1.0.0-rc.15': - resolution: {integrity: sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==} + '@rolldown/binding-darwin-x64@1.0.0-rc.17': + resolution: {integrity: sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-rc.16': - resolution: {integrity: sha512-r/OmdR00HmD4i79Z//xO06uEPOq5hRXdhw7nzkxQxwSavs3PSHa1ijntdpOiZ2mzOQ3fVVu8C1M19FoNM+dMUQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [darwin] - - '@rolldown/binding-freebsd-x64@1.0.0-rc.15': - resolution: {integrity: sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [freebsd] - - '@rolldown/binding-freebsd-x64@1.0.0-rc.16': - resolution: {integrity: sha512-KcRE5w8h0OnjUatG8pldyD14/CQ5Phs1oxfR+3pKDjboHRo9+MkqQaiIZlZRpsxC15paeXme/I127tUa9TXJ6g==} + '@rolldown/binding-freebsd-x64@1.0.0-rc.17': + resolution: {integrity: sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': - resolution: {integrity: sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.16': - resolution: {integrity: sha512-bT0guA1bpxEJ/ZhTRniQf7rNF8ybvXOuWbNIeLABaV5NGjx4EtOWBTSRGWFU9ZWVkPOZ+HNFP8RMcBokBiZ0Kg==} + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': + resolution: {integrity: sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': - resolution: {integrity: sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==} + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': + resolution: {integrity: sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.16': - resolution: {integrity: sha512-+tHktCHWV8BDQSjemUqm/Jl/TPk3QObCTIjmdDy/nlupcujZghmKK2962LYrqFpWu+ai01AN/REOH3NEpqvYQg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': - resolution: {integrity: sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.16': - resolution: {integrity: sha512-3fPzdREH806oRLxpTWW1Gt4tQHs0TitZFOECB2xzCFLPKnSOy90gwA7P29cksYilFO6XVRY1kzga0cL2nRjKPg==} + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': + resolution: {integrity: sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15': - resolution: {integrity: sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==} + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': + resolution: {integrity: sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.16': - resolution: {integrity: sha512-EKwI1tSrLs7YVw+JPJT/G2dJQ1jl9qlTTTEG0V2Ok/RdOenRfBw2PQdLPyjhIu58ocdBfP7vIRN/pvMsPxs/AQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15': - resolution: {integrity: sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.16': - resolution: {integrity: sha512-Uknladnb3Sxqu6SEcqBldQyJUpk8NleooZEc0MbRBJ4inEhRYWZX0NJu12vNf2mqAq7gsofAxHrGghiUYjhaLQ==} + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': + resolution: {integrity: sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': - resolution: {integrity: sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==} + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': + resolution: {integrity: sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.16': - resolution: {integrity: sha512-FIb8+uG49sZBtLTn+zt1AJ20TqVcqWeSIyoVt0or7uAWesgKaHbiBh6OpA/k9v0LTt+PTrb1Lao133kP4uVxkg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': - resolution: {integrity: sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [musl] - - '@rolldown/binding-linux-x64-musl@1.0.0-rc.16': - resolution: {integrity: sha512-RuERhF9/EgWxZEXYWCOaViUWHIboceK4/ivdtQ3R0T44NjLkIIlGIAVAuCddFxsZ7vnRHtNQUrt2vR2n2slB2w==} + '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': + resolution: {integrity: sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': - resolution: {integrity: sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==} + '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': + resolution: {integrity: sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-openharmony-arm64@1.0.0-rc.16': - resolution: {integrity: sha512-mXcXnvd9GpazCxeUCCnZ2+YF7nut+ZOEbE4GtaiPtyY6AkhZWbK70y1KK3j+RDhjVq5+U8FySkKRb/+w0EeUwA==} + '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': + resolution: {integrity: sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [openharmony] - - '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': - resolution: {integrity: sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==} - engines: {node: '>=14.0.0'} cpu: [wasm32] - '@rolldown/binding-wasm32-wasi@1.0.0-rc.16': - resolution: {integrity: sha512-3Q2KQxnC8IJOLqXmUMoYwyIPZU9hzRbnHaoV3Euz+VVnjZKcY8ktnNP8T9R4/GGQtb27C/UYKABxesKWb8lsvQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [wasm32] - - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': - resolution: {integrity: sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] - - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.16': - resolution: {integrity: sha512-tj7XRemQcOcFwv7qhpUxMTBbI5mWMlE4c1Omhg5+h8GuLXzyj8HviYgR+bB2DMDgRqUE+jiDleqSCRjx4aYk/Q==} + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': + resolution: {integrity: sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': - resolution: {integrity: sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [win32] - - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.16': - resolution: {integrity: sha512-PH5DRZT+F4f2PTXRXR8uJxnBq2po/xFtddyabTJVJs/ZYVHqXPEgNIr35IHTEa6bpa0Q8Awg+ymkTaGnKITw4g==} + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': + resolution: {integrity: sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0-rc.15': - resolution: {integrity: sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==} - - '@rolldown/pluginutils@1.0.0-rc.16': - resolution: {integrity: sha512-45+YtqxLYKDWQouLKCrpIZhke+nXxhsw+qAHVzHDVwttyBlHNBVs2K25rDXrZzhpTp9w1FlAlvweV1H++fdZoA==} + '@rolldown/pluginutils@1.0.0-rc.17': + resolution: {integrity: sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==} '@rollup/plugin-node-resolve@15.3.1': resolution: {integrity: sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==} @@ -1193,8 +1161,8 @@ packages: peerDependencies: acorn: ^8.9.0 - '@sveltejs/kit@2.57.1': - resolution: {integrity: sha512-VRdSbB96cI1EnRh09CqmnQqP/YJvET5buj8S6k7CxaJqBJD4bw4fRKDjcarAj/eX9k2eHifQfDH8NtOh+ZxxPw==} + '@sveltejs/kit@2.58.0': + resolution: {integrity: sha512-kT9GCN8yJTkCK1W+Gi/bvGooWAM7y7WXP+yd+rf6QOIjyoK1ERPrMwSufXJUNu2pMWIqruhFvmz+LbOqsEmKmA==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -1216,69 +1184,69 @@ packages: svelte: ^5.46.4 vite: ^8.0.0-beta.7 || ^8.0.0 - '@tailwindcss/node@4.2.2': - resolution: {integrity: sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==} + '@tailwindcss/node@4.2.4': + resolution: {integrity: sha512-Ai7+yQPxz3ddrDQzFfBKdHEVBg0w3Zl83jnjuwxnZOsnH9pGn93QHQtpU0p/8rYWxvbFZHneni6p1BSLK4DkGA==} - '@tailwindcss/oxide-android-arm64@4.2.2': - resolution: {integrity: sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==} + '@tailwindcss/oxide-android-arm64@4.2.4': + resolution: {integrity: sha512-e7MOr1SAn9U8KlZzPi1ZXGZHeC5anY36qjNwmZv9pOJ8E4Q6jmD1vyEHkQFmNOIN7twGPEMXRHmitN4zCMN03g==} engines: {node: '>= 20'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.2.2': - resolution: {integrity: sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==} + '@tailwindcss/oxide-darwin-arm64@4.2.4': + resolution: {integrity: sha512-tSC/Kbqpz/5/o/C2sG7QvOxAKqyd10bq+ypZNf+9Fi2TvbVbv1zNpcEptcsU7DPROaSbVgUXmrzKhurFvo5eDg==} engines: {node: '>= 20'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.2.2': - resolution: {integrity: sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==} + '@tailwindcss/oxide-darwin-x64@4.2.4': + resolution: {integrity: sha512-yPyUXn3yO/ufR6+Kzv0t4fCg2qNr90jxXc5QqBpjlPNd0NqyDXcmQb/6weunH/MEDXW5dhyEi+agTDiqa3WsGg==} engines: {node: '>= 20'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.2.2': - resolution: {integrity: sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==} + '@tailwindcss/oxide-freebsd-x64@4.2.4': + resolution: {integrity: sha512-BoMIB4vMQtZsXdGLVc2z+P9DbETkiopogfWZKbWwM8b/1Vinbs4YcUwo+kM/KeLkX3Ygrf4/PsRndKaYhS8Eiw==} engines: {node: '>= 20'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': - resolution: {integrity: sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.4': + resolution: {integrity: sha512-7pIHBLTHYRAlS7V22JNuTh33yLH4VElwKtB3bwchK/UaKUPpQ0lPQiOWcbm4V3WP2I6fNIJ23vABIvoy2izdwA==} engines: {node: '>= 20'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': - resolution: {integrity: sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==} + '@tailwindcss/oxide-linux-arm64-gnu@4.2.4': + resolution: {integrity: sha512-+E4wxJ0ZGOzSH325reXTWB48l42i93kQqMvDyz5gqfRzRZ7faNhnmvlV4EPGJU3QJM/3Ab5jhJ5pCRUsKn6OQw==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-arm64-musl@4.2.2': - resolution: {integrity: sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==} + '@tailwindcss/oxide-linux-arm64-musl@4.2.4': + resolution: {integrity: sha512-bBADEGAbo4ASnppIziaQJelekCxdMaxisrk+fB7Thit72IBnALp9K6ffA2G4ruj90G9XRS2VQ6q2bCKbfFV82g==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [musl] - '@tailwindcss/oxide-linux-x64-gnu@4.2.2': - resolution: {integrity: sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==} + '@tailwindcss/oxide-linux-x64-gnu@4.2.4': + resolution: {integrity: sha512-7Mx25E4WTfnht0TVRTyC00j3i0M+EeFe7wguMDTlX4mRxafznw0CA8WJkFjWYH5BlgELd1kSjuU2JiPnNZbJDA==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-x64-musl@4.2.2': - resolution: {integrity: sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==} + '@tailwindcss/oxide-linux-x64-musl@4.2.4': + resolution: {integrity: sha512-2wwJRF7nyhOR0hhHoChc04xngV3iS+akccHTGtz965FwF0up4b2lOdo6kI1EbDaEXKgvcrFBYcYQQ/rrnWFVfA==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [musl] - '@tailwindcss/oxide-wasm32-wasi@4.2.2': - resolution: {integrity: sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==} + '@tailwindcss/oxide-wasm32-wasi@4.2.4': + resolution: {integrity: sha512-FQsqApeor8Fo6gUEklzmaa9994orJZZDBAlQpK2Mq+DslRKFJeD6AjHpBQ0kZFQohVr8o85PPh8eOy86VlSCmw==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -1289,24 +1257,24 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': - resolution: {integrity: sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==} + '@tailwindcss/oxide-win32-arm64-msvc@4.2.4': + resolution: {integrity: sha512-L9BXqxC4ToVgwMFqj3pmZRqyHEztulpUJzCxUtLjobMCzTPsGt1Fa9enKbOpY2iIyVtaHNeNvAK8ERP/64sqGQ==} engines: {node: '>= 20'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.2.2': - resolution: {integrity: sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==} + '@tailwindcss/oxide-win32-x64-msvc@4.2.4': + resolution: {integrity: sha512-ESlKG0EpVJQwRjXDDa9rLvhEAh0mhP1sF7sap9dNZT0yyl9SAG6T7gdP09EH0vIv0UNTlo6jPWyujD6559fZvw==} engines: {node: '>= 20'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.2.2': - resolution: {integrity: sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==} + '@tailwindcss/oxide@4.2.4': + resolution: {integrity: sha512-9El/iI069DKDSXwTvB9J4BwdO5JhRrOweGaK25taBAvBXyXqJAX+Jqdvs8r8gKpsI/1m0LeJLyQYTf/WLrBT1Q==} engines: {node: '>= 20'} - '@tailwindcss/postcss@4.2.2': - resolution: {integrity: sha512-n4goKQbW8RVXIbNKRB/45LzyUqN451deQK0nzIeauVEqjlI49slUlgKYJM2QyUzap/PcpnS7kzSUmPb1sCRvYQ==} + '@tailwindcss/postcss@4.2.4': + resolution: {integrity: sha512-wgAVj6nUWAolAu8YFvzT2cTBIElWHkjZwFYovF+xsqKsW2ADxM/X2opxj5NsF/qVccAOjRNe8X2IdPzMsWyHTg==} '@testing-library/svelte-core@1.0.0': resolution: {integrity: sha512-VkUePoLV6oOYwSUvX6ShA8KLnJqZiYMIbP2JW2t0GLWLkJxKGvuH5qrrZBV/X7cXFnLGuFQEC7RheYiZOW68KQ==} @@ -1339,8 +1307,8 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} - '@types/bun@1.3.12': - resolution: {integrity: sha512-DBv81elK+/VSwXHDlnH3Qduw+KxkTIWi7TXkAeh24zpi5l0B2kUg9Ga3tb4nJaPcOFswflgi/yAvMVBPrxMB+A==} + '@types/bun@1.3.13': + resolution: {integrity: sha512-9fqXWk5YIHGGnUau9TEi+qdlTYDAnOj+xLCmSTwXfAIqXr2x4tytJb43E9uCvt09zJURKXwAtkoH4nLQfzeTXw==} '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} @@ -1372,63 +1340,63 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@typescript-eslint/eslint-plugin@8.58.2': - resolution: {integrity: sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==} + '@typescript-eslint/eslint-plugin@8.59.1': + resolution: {integrity: sha512-BOziFIfE+6osHO9FoJG4zjoHUcvI7fTNBSpdAwrNH0/TLvzjsk2oo8XSSOT2HhqUyhZPfHv4UOffoJ9oEEQ7Ag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.58.2 + '@typescript-eslint/parser': ^8.59.1 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.58.2': - resolution: {integrity: sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==} + '@typescript-eslint/parser@8.59.1': + resolution: {integrity: sha512-HDQH9O/47Dxi1ceDhBXdaldtf/WV9yRYMjbjCuNk3qnaTD564qwv61Y7+gTxwxRKzSrgO5uhtw584igXVuuZkA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.58.2': - resolution: {integrity: sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==} + '@typescript-eslint/project-service@8.59.1': + resolution: {integrity: sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.58.2': - resolution: {integrity: sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==} + '@typescript-eslint/scope-manager@8.59.1': + resolution: {integrity: sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.58.2': - resolution: {integrity: sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==} + '@typescript-eslint/tsconfig-utils@8.59.1': + resolution: {integrity: sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.58.2': - resolution: {integrity: sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==} + '@typescript-eslint/type-utils@8.59.1': + resolution: {integrity: sha512-klWPBR2ciQHS3f++ug/mVnWKPjBUo7icEL3FAO1lhAR1Z1i5NQYZ1EannMSRYcq5qCv5wNALlXr6fksRHyYl7w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.58.2': - resolution: {integrity: sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==} + '@typescript-eslint/types@8.59.1': + resolution: {integrity: sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.58.2': - resolution: {integrity: sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==} + '@typescript-eslint/typescript-estree@8.59.1': + resolution: {integrity: sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.58.2': - resolution: {integrity: sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==} + '@typescript-eslint/utils@8.59.1': + resolution: {integrity: sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.58.2': - resolution: {integrity: sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==} + '@typescript-eslint/visitor-keys@8.59.1': + resolution: {integrity: sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@unocss/cli@66.6.8': @@ -1515,31 +1483,31 @@ packages: peerDependencies: vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 || ^8.0.0-0 - '@vitest/browser-playwright@4.1.4': - resolution: {integrity: sha512-q3PchVhZINX23Pv+RERgAtDlp6wzVkID/smOPnZ5YGWpeWUe3jMNYppeVh15j4il3G7JIJty1d1Kicpm0HSMig==} + '@vitest/browser-playwright@4.1.5': + resolution: {integrity: sha512-CWy0lBQJq97nionyJJdnaU4961IXTl43a7UCu5nHy51IoKxAt6PVIJLo+76rVl7KOOgcWHNkG4kbJu/pW7knvA==} peerDependencies: playwright: '*' - vitest: 4.1.4 + vitest: 4.1.5 - '@vitest/browser@4.1.4': - resolution: {integrity: sha512-TrNaY/yVOwxtrxNsDUC/wQ56xSwplpytTeRAqF/197xV/ZddxxulBsxR6TrhVMyniJmp9in8d5u0AcDaNRY30w==} + '@vitest/browser@4.1.5': + resolution: {integrity: sha512-iCDGI8c4yg+xmjUg2VsygdAUSIIB4x5Rht/P68OXy1hPELKXHDkzh87lkuTcdYmemRChDkEpB426MmDjzC0ziA==} peerDependencies: - vitest: 4.1.4 + vitest: 4.1.5 - '@vitest/coverage-v8@4.1.4': - resolution: {integrity: sha512-x7FptB5oDruxNPDNY2+S8tCh0pcq7ymCe1gTHcsp733jYjrJl8V1gMUlVysuCD9Kz46Xz9t1akkv08dPcYDs1w==} + '@vitest/coverage-v8@4.1.5': + resolution: {integrity: sha512-38C0/Ddb7HcRG0Z4/DUem8x57d2p9jYgp18mkaYswEOQBGsI1CG4f/hjm0ZCeaJfWhSZ4k7jgs29V1Zom7Ki9A==} peerDependencies: - '@vitest/browser': 4.1.4 - vitest: 4.1.4 + '@vitest/browser': 4.1.5 + vitest: 4.1.5 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@4.1.4': - resolution: {integrity: sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww==} + '@vitest/expect@4.1.5': + resolution: {integrity: sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==} - '@vitest/mocker@4.1.4': - resolution: {integrity: sha512-R9HTZBhW6yCSGbGQnDnH3QHfJxokKN4KB+Yvk9Q1le7eQNYwiCyKxmLmurSpFy6BzJanSLuEUDrD+j97Q+ZLPg==} + '@vitest/mocker@4.1.5': + resolution: {integrity: sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1549,20 +1517,20 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.4': - resolution: {integrity: sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A==} + '@vitest/pretty-format@4.1.5': + resolution: {integrity: sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==} - '@vitest/runner@4.1.4': - resolution: {integrity: sha512-xTp7VZ5aXP5ZJrn15UtJUWlx6qXLnGtF6jNxHepdPHpMfz/aVPx+htHtgcAL2mDXJgKhpoo2e9/hVJsIeFbytQ==} + '@vitest/runner@4.1.5': + resolution: {integrity: sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==} - '@vitest/snapshot@4.1.4': - resolution: {integrity: sha512-MCjCFgaS8aZz+m5nTcEcgk/xhWv0rEH4Yl53PPlMXOZ1/Ka2VcZU6CJ+MgYCZbcJvzGhQRjVrGQNZqkGPttIKw==} + '@vitest/snapshot@4.1.5': + resolution: {integrity: sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==} - '@vitest/spy@4.1.4': - resolution: {integrity: sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ==} + '@vitest/spy@4.1.5': + resolution: {integrity: sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==} - '@vitest/utils@4.1.4': - resolution: {integrity: sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw==} + '@vitest/utils@4.1.5': + resolution: {integrity: sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} @@ -1574,11 +1542,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - ajv@6.14.0: - resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} - ajv@8.18.0: - resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} ansi-escapes@7.3.0: resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} @@ -1647,8 +1615,14 @@ packages: resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} engines: {node: 18 || 20 || >=22} - bun-types@1.3.12: - resolution: {integrity: sha512-HqOLj5PoFajAQciOMRiIZGNoKxDJSr6qigAttOX40vJuSp6DN/CxWp9s3C1Xwm4oH7ybueITwiaOcWXoYVoRkA==} + bun-types@1.3.13: + resolution: {integrity: sha512-QXKeHLlOLqQX9LgYaHJfzdBaV21T63HhFJnvuRCcjZiaUDpbs5ED1MgxbMra71CsryN/1dAoXuJJJwIv/2drVA==} + + bun@1.3.13: + resolution: {integrity: sha512-b9T4xZ8KqCHs4+TkHJv540LG1B8OD7noKu0Qaizusx3jFtMDHY6osNqgbaOlwW2B8RB2AKzz+sjzlGKIGxIjZw==} + cpu: [arm64, x64] + os: [darwin, linux, win32] + hasBin: true cac@7.0.0: resolution: {integrity: sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==} @@ -1845,8 +1819,8 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - enhanced-resolve@5.20.1: - resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==} + enhanced-resolve@5.21.0: + resolution: {integrity: sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==} engines: {node: '>=10.13.0'} env-paths@2.2.1: @@ -1864,8 +1838,8 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@2.0.0: - resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} @@ -1912,8 +1886,8 @@ packages: eslint-config-prettier: optional: true - eslint-plugin-svelte@3.17.0: - resolution: {integrity: sha512-sF6wgd5FLS2P8CCaOy2HdYYYEcZ6TwL251dLHUkNmtLnWECk1Dwc+j6VeulmmnFxr7Xs0WNtjweOA+bJ0PnaFw==} + eslint-plugin-svelte@3.17.1: + resolution: {integrity: sha512-NyiXHtS3Ni7e532RBwS9OXlMKDIrENg3gY+/+ODjZzQx2xhU3NlJ+nIl1a93iUUQeiJL3lS8KLmY+W8hklzweQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.1 || ^9.0.0 || ^10.0.0 @@ -2104,39 +2078,39 @@ packages: resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} engines: {node: '>=18'} - git-cliff-darwin-arm64@2.12.0: - resolution: {integrity: sha512-k3jzFDmkjc+6MjpnqvRenzMWRbZN5J+w3iQ8WNt9pSmPewNJIm92O/G6AbAxQaCbSfzQapeZ0e+5wSacVc62GA==} + git-cliff-darwin-arm64@2.13.1: + resolution: {integrity: sha512-3ebPUnUlLmrSZDHknSZQmyZV7DEJVtKse8I25Am0cENET5Py9u9Hg9k8IRXdiDtHtPDs6MYZx7BOi11WtcfqSg==} cpu: [arm64] os: [darwin] - git-cliff-darwin-x64@2.12.0: - resolution: {integrity: sha512-Kkoe+nfmXM/WMcZuC+OaIGA5vj847Ima6NEaaHnyb7Xsri+OAJryPXlABV7q6UeGfiiN2MlL8UsoHgnIEIQLqQ==} + git-cliff-darwin-x64@2.13.1: + resolution: {integrity: sha512-KZfggGAiw1EvZH3BOUclEU4eGCP2+Z+lH/N2Ni3FH9L2M1U7FYJqqaMhqgO8azTj67betvDshH8WBUkIkSsVxA==} cpu: [x64] os: [darwin] - git-cliff-linux-arm64@2.12.0: - resolution: {integrity: sha512-eTp2gZjV4LmfzdlhFsYFYuWf5mojALU03X/37r3VmnpuabaijuTEQo/zm/0BKP8gPiLKLR4ofdUvE1OSisCE1A==} + git-cliff-linux-arm64@2.13.1: + resolution: {integrity: sha512-clNRcNzdvk4GKyTt3ZhhWqcrjVRghcUcGNSV/Y87YJf3Mc/zl9ajUAhnXPOBSX/KWBr2od5SmkCt0qGYagY07g==} cpu: [arm64] os: [linux] - git-cliff-linux-x64@2.12.0: - resolution: {integrity: sha512-abidFG6dH2N5hPUF245/kRYdwViP11Pz7ZwIW/a86CJLZ/WSE7dJt0f2cUIkxTcFSsp11OwuLc5k1hAbwmiIRw==} + git-cliff-linux-x64@2.13.1: + resolution: {integrity: sha512-gZcIQhIQ1lDUMD8UieUSEZAYoyZN7nPd8O3VQoj1Ddhqll4UAS1Zxms1SU3U8pb0UTdc2m3ia/wtOnyhvbjdjQ==} cpu: [x64] os: [linux] - git-cliff-windows-arm64@2.12.0: - resolution: {integrity: sha512-rFuI+D/3Yq3jqafazZw5E68HsXEvcwI/B/5IPDIZD+QqZh8vETf4IXs7wVxYWWtHQJDC+G9ZrR3vE5648mdG3A==} + git-cliff-windows-arm64@2.13.1: + resolution: {integrity: sha512-+XubuQv68DuDwF0u6Af5d889MEf/RD48VBQS7ZmPi4sUSCXAZqRm1/ApCsStLqxMDCf1+7s05B/kNbm9wjV80A==} cpu: [arm64] os: [win32] - git-cliff-windows-x64@2.12.0: - resolution: {integrity: sha512-jskb3nyVGr4dekHSCDM/J6iho45t37wnmMGkPNq42kOoUp04JS96yMBrNRdXfXV9ViZsaZq3NaNu1e3QkhFlyA==} + git-cliff-windows-x64@2.13.1: + resolution: {integrity: sha512-Bi8ehp1VMkomY7M/356PgovKQ8CBRiuOOkq+aWC2evQuMFfXWjG0GBlPED9QkZoUJ4iQ5ygB5DYdK3BjhaOyPw==} cpu: [x64] os: [win32] - git-cliff@2.12.0: - resolution: {integrity: sha512-kjTm5439LsvMs/xRxndWBUetrA4aQfLE8DTbR/ER5H7fGn7ioeFG9YNAK1V7dpTtNi6k2uKYY4f3EvT8J1d+1Q==} - engines: {node: '>=18.19 || >=20.6 || >=21'} + git-cliff@2.13.1: + resolution: {integrity: sha512-2BzXwrom+SMHeNA5Ut+MtzqXejg0wbVwmzj3k7e9w62UQoyCDrM9UIcvtl6hnT3jocEQ1zLRQBaXXx97Gmnk7A==} + engines: {node: ^18.19 || >=20.6} hasBin: true git-raw-commits@5.0.1: @@ -2148,9 +2122,9 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - global-directory@4.0.1: - resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} - engines: {node: '>=18'} + global-directory@5.0.0: + resolution: {integrity: sha512-1pgFdhK3J2LeM+dVf2Pd424yHx2ou338lC0ErNP2hPx4j8eW1Sp0XqSjNxtk6Tc4Kr5wlWtSvz8cn2yb7/SG/w==} + engines: {node: '>=20'} globals@16.5.0: resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} @@ -2218,9 +2192,9 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - ini@4.1.1: - resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + ini@6.0.0: + resolution: {integrity: sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==} + engines: {node: ^20.17.0 || >=22.9.0} irregular-plurals@3.5.0: resolution: {integrity: sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==} @@ -2691,8 +2665,8 @@ packages: resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==} engines: {node: '>=4'} - postcss@8.5.10: - resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==} + postcss@8.5.12: + resolution: {integrity: sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -2770,13 +2744,8 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rolldown@1.0.0-rc.15: - resolution: {integrity: sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - - rolldown@1.0.0-rc.16: - resolution: {integrity: sha512-rzi5WqKzEZw3SooTt7cgm4eqIoujPIyGcJNGFL7iPEuajQw7vxMHUkXylu4/vhCkJGXsgRmxqMKXUpT6FEgl0g==} + rolldown@1.0.0-rc.17: + resolution: {integrity: sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -2855,8 +2824,8 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} - string-width@8.2.0: - resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==} + string-width@8.2.1: + resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} engines: {node: '>=20'} strip-ansi@6.0.1: @@ -2916,13 +2885,13 @@ packages: '@sveltejs/kit': ^1.0.0 || ^2.0.0 svelte: ^5.1.13 - svelte-sonner@1.1.0: - resolution: {integrity: sha512-3lYM6ZIqWe+p9vwwWHGWP/ZdvHiUtzURsud2quIxivrX4rvpXh6i+geBGn0m3JS6KwW6W8VgbOl3xQMcDuh6gg==} + svelte-sonner@1.1.1: + resolution: {integrity: sha512-5cd3p7wa4cq0NsqslMwdlPb7x1JglEZ/GKrLePWNr5bCxR1nagAVrY01FRFrXfUGs41miLt3C327+8XJo5BzZw==} peerDependencies: svelte: ^5.0.0 - svelte@5.55.4: - resolution: {integrity: sha512-q8DFohk6vUswSng95IZb9nzWJnbINZsK7OiM1snAa3qCjJBL0ZQpvMyAaVXjUukdM75J/m8UE8xwqat8Ors/zQ==} + svelte@5.55.5: + resolution: {integrity: sha512-2uCs/LZ9us+AktdzYJM8OcxQ8qnPS1kpaO7syGT/MgO+6Qr1Ybl+TqPq+97u7PHqmmMlye5ZkoyXONy5mjjAbw==} engines: {node: '>=18'} synckit@0.11.12: @@ -2942,11 +2911,11 @@ packages: tailwind-merge: optional: true - tailwindcss@4.2.2: - resolution: {integrity: sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==} + tailwindcss@4.2.4: + resolution: {integrity: sha512-HhKppgO81FQof5m6TEnuBWCZGgfRAWbaeOaGT00KOy/Pf/j6oUihdvBpA7ltCeAvZpFhW3j0PTclkxsd4IXYDA==} - tapable@2.3.2: - resolution: {integrity: sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==} + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} engines: {node: '>=6'} tinybench@2.9.0: @@ -2992,8 +2961,8 @@ packages: type-level-regexp@0.1.17: resolution: {integrity: sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg==} - typescript-eslint@8.58.2: - resolution: {integrity: sha512-V8iSng9mRbdZjl54VJ9NKr6ZB+dW0J3TzRXRGcSbLIej9jV86ZRtlYeTKDR/QLxXykocJ5icNzbsl2+5TzIvcQ==} + typescript-eslint@8.59.1: + resolution: {integrity: sha512-xqDcFVBmlrltH64lklOVp1wYxgJr6LVdg3NamBgH2OOQDLFdTKfIZXF5PfghrnXQKXZGTQs8tr1vL7fJvq8CTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 @@ -3059,16 +3028,12 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - uuid@10.0.0: - resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + uuid@14.0.0: + resolution: {integrity: sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==} hasBin: true - uuid@13.0.0: - resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} - hasBin: true - - vite@8.0.8: - resolution: {integrity: sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==} + vite@8.0.10: + resolution: {integrity: sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -3124,20 +3089,20 @@ packages: svelte: ^3 || ^4 || ^5 || ^5.0.0-next.0 vitest: ^4.0.0 - vitest@4.1.4: - resolution: {integrity: sha512-tFuJqTxKb8AvfyqMfnavXdzfy3h3sWZRWwfluGbkeR7n0HUev+FmNgZ8SDrRBTVrVCjgH5cA21qGbCffMNtWvg==} + vitest@4.1.5: + resolution: {integrity: sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.4 - '@vitest/browser-preview': 4.1.4 - '@vitest/browser-webdriverio': 4.1.4 - '@vitest/coverage-istanbul': 4.1.4 - '@vitest/coverage-v8': 4.1.4 - '@vitest/ui': 4.1.4 + '@vitest/browser-playwright': 4.1.5 + '@vitest/browser-preview': 4.1.5 + '@vitest/browser-webdriverio': 4.1.5 + '@vitest/coverage-istanbul': 4.1.5 + '@vitest/coverage-v8': 4.1.5 + '@vitest/ui': 4.1.5 happy-dom: '*' jsdom: '*' vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -3236,16 +3201,16 @@ packages: snapshots: - '@actions/core@3.0.0': + '@actions/core@3.0.1': dependencies: '@actions/exec': 3.0.0 - '@actions/http-client': 4.0.0 + '@actions/http-client': 4.0.1 '@actions/exec@3.0.0': dependencies: '@actions/io': 3.0.2 - '@actions/github@9.1.0': + '@actions/github@9.1.1': dependencies: '@actions/http-client': 3.0.2 '@octokit/core': 7.0.6 @@ -3260,7 +3225,7 @@ snapshots: tunnel: 0.0.6 undici: 6.25.0 - '@actions/http-client@4.0.0': + '@actions/http-client@4.0.1': dependencies: tunnel: 0.0.6 undici: 6.25.0 @@ -3331,11 +3296,11 @@ snapshots: '@blazediff/core@1.9.1': {} - '@commitlint/cli@20.5.0(@types/node@25.6.0)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3)': + '@commitlint/cli@20.5.2(@types/node@25.6.0)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3)': dependencies: '@commitlint/format': 20.5.0 '@commitlint/lint': 20.5.0 - '@commitlint/load': 20.5.0(@types/node@25.6.0)(typescript@6.0.3) + '@commitlint/load': 20.5.2(@types/node@25.6.0)(typescript@6.0.3) '@commitlint/read': 20.5.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) '@commitlint/types': 20.5.0 tinyexec: 1.1.1 @@ -3354,7 +3319,7 @@ snapshots: '@commitlint/config-validator@20.5.0': dependencies: '@commitlint/types': 20.5.0 - ajv: 8.18.0 + ajv: 8.20.0 '@commitlint/ensure@20.5.0': dependencies: @@ -3384,11 +3349,11 @@ snapshots: '@commitlint/rules': 20.5.0 '@commitlint/types': 20.5.0 - '@commitlint/load@20.5.0(@types/node@25.6.0)(typescript@6.0.3)': + '@commitlint/load@20.5.2(@types/node@25.6.0)(typescript@6.0.3)': dependencies: '@commitlint/config-validator': 20.5.0 '@commitlint/execute-rule': 20.0.0 - '@commitlint/resolve-extends': 20.5.0 + '@commitlint/resolve-extends': 20.5.2 '@commitlint/types': 20.5.0 cosmiconfig: 9.0.1(typescript@6.0.3) cosmiconfig-typescript-loader: 6.3.0(@types/node@25.6.0)(cosmiconfig@9.0.1(typescript@6.0.3))(typescript@6.0.3) @@ -3418,11 +3383,11 @@ snapshots: - conventional-commits-filter - conventional-commits-parser - '@commitlint/resolve-extends@20.5.0': + '@commitlint/resolve-extends@20.5.2': dependencies: '@commitlint/config-validator': 20.5.0 '@commitlint/types': 20.5.0 - global-directory: 4.0.1 + global-directory: 5.0.0 import-meta-resolve: 4.2.0 lodash.mergewith: 4.6.2 resolve-from: 5.0.0 @@ -3460,13 +3425,13 @@ snapshots: '@dprint/toml@0.7.0': {} - '@emnapi/core@1.9.2': + '@emnapi/core@1.10.0': dependencies: '@emnapi/wasi-threads': 1.2.1 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.9.2': + '@emnapi/runtime@1.10.0': dependencies: tslib: 2.8.1 optional: true @@ -3520,7 +3485,7 @@ snapshots: commander: 14.0.3 conventional-recommended-bump: 11.2.0 execa: 9.6.1 - git-cliff: 2.12.0 + git-cliff: 2.13.1 js-yaml: 4.1.1 semver: 7.7.4 smol-toml: 1.6.1 @@ -3560,7 +3525,7 @@ snapshots: dependencies: '@iconify/types': 2.0.0 - '@iconify-json/material-icon-theme@1.2.59': + '@iconify-json/material-icon-theme@1.2.61': dependencies: '@iconify/types': 2.0.0 @@ -3570,16 +3535,16 @@ snapshots: '@iconify/types@2.0.0': {} - '@iconify/utils@3.1.0': + '@iconify/utils@3.1.1': dependencies: '@antfu/install-pkg': 1.1.0 '@iconify/types': 2.0.0 mlly: 1.8.2 - '@inlang/paraglide-js@2.16.0': + '@inlang/paraglide-js@2.17.0': dependencies: '@inlang/recommend-sherlock': 0.2.1 - '@inlang/sdk': 2.9.1 + '@inlang/sdk': 2.9.2 commander: 11.1.0 consola: 3.4.0 json5: 2.2.3 @@ -3592,13 +3557,13 @@ snapshots: dependencies: comment-json: 4.6.2 - '@inlang/sdk@2.9.1': + '@inlang/sdk@2.9.2': dependencies: - '@lix-js/sdk': 0.4.9 + '@lix-js/sdk': 0.4.10 '@sinclair/typebox': 0.31.28 kysely: 0.28.16 sqlite-wasm-kysely: 0.3.0(kysely@0.28.16) - uuid: 13.0.0 + uuid: 14.0.0 transitivePeerDependencies: - babel-plugin-macros @@ -3623,7 +3588,7 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@lix-js/sdk@0.4.9': + '@lix-js/sdk@0.4.10': dependencies: '@lix-js/server-protocol-schema': 0.1.1 dedent: 1.5.1 @@ -3631,16 +3596,16 @@ snapshots: js-sha256: 0.11.1 kysely: 0.28.16 sqlite-wasm-kysely: 0.3.0(kysely@0.28.16) - uuid: 10.0.0 + uuid: 14.0.0 transitivePeerDependencies: - babel-plugin-macros '@lix-js/server-protocol-schema@0.1.1': {} - '@nanoforge-dev/actions@1.2.3': + '@nanoforge-dev/actions@1.3.0': dependencies: - '@actions/core': 3.0.0 - '@actions/github': 9.1.0 + '@actions/core': 3.0.1 + '@actions/github': 9.1.1 commander: 14.0.3 '@nanoforge-dev/common@1.1.0': {} @@ -3658,7 +3623,7 @@ snapshots: eslint-plugin-format: 1.5.0(eslint@10.2.1(jiti@2.6.1)) eslint-plugin-prettier: 5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.2.1(jiti@2.6.1)))(eslint@10.2.1(jiti@2.6.1))(prettier@3.8.3) globals: 16.5.0 - typescript-eslint: 8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + typescript-eslint: 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) transitivePeerDependencies: - '@types/eslint' - eslint @@ -3668,10 +3633,10 @@ snapshots: '@nanoforge-dev/utils-prettier-config@1.0.2': {} - '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: - '@emnapi/core': 1.9.2 - '@emnapi/runtime': 1.9.2 + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 '@tybys/wasm-util': 0.10.1 optional: true @@ -3734,6 +3699,42 @@ snapshots: dependencies: '@octokit/openapi-types': 27.0.0 + '@oven/bun-darwin-aarch64@1.3.13': + optional: true + + '@oven/bun-darwin-x64-baseline@1.3.13': + optional: true + + '@oven/bun-darwin-x64@1.3.13': + optional: true + + '@oven/bun-linux-aarch64-musl@1.3.13': + optional: true + + '@oven/bun-linux-aarch64@1.3.13': + optional: true + + '@oven/bun-linux-x64-baseline@1.3.13': + optional: true + + '@oven/bun-linux-x64-musl-baseline@1.3.13': + optional: true + + '@oven/bun-linux-x64-musl@1.3.13': + optional: true + + '@oven/bun-linux-x64@1.3.13': + optional: true + + '@oven/bun-windows-aarch64@1.3.13': + optional: true + + '@oven/bun-windows-x64-baseline@1.3.13': + optional: true + + '@oven/bun-windows-x64@1.3.13': + optional: true + '@oxc-parser/binding-android-arm-eabi@0.124.0': optional: true @@ -3782,9 +3783,9 @@ snapshots: '@oxc-parser/binding-openharmony-arm64@0.124.0': optional: true - '@oxc-parser/binding-wasm32-wasi@0.124.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + '@oxc-parser/binding-wasm32-wasi@0.124.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' @@ -3801,7 +3802,7 @@ snapshots: '@oxc-project/types@0.124.0': {} - '@oxc-project/types@0.126.0': {} + '@oxc-project/types@0.127.0': {} '@oxfmt/binding-android-arm-eabi@0.35.0': optional: true @@ -3874,107 +3875,56 @@ snapshots: dependencies: quansync: 1.0.0 - '@rolldown/binding-android-arm64@1.0.0-rc.15': - optional: true - - '@rolldown/binding-android-arm64@1.0.0-rc.16': - optional: true - - '@rolldown/binding-darwin-arm64@1.0.0-rc.15': - optional: true - - '@rolldown/binding-darwin-arm64@1.0.0-rc.16': - optional: true - - '@rolldown/binding-darwin-x64@1.0.0-rc.15': - optional: true - - '@rolldown/binding-darwin-x64@1.0.0-rc.16': - optional: true - - '@rolldown/binding-freebsd-x64@1.0.0-rc.15': - optional: true - - '@rolldown/binding-freebsd-x64@1.0.0-rc.16': - optional: true - - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': - optional: true - - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.16': - optional: true - - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': - optional: true - - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.16': - optional: true - - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': - optional: true - - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.16': + '@rolldown/binding-android-arm64@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15': + '@rolldown/binding-darwin-arm64@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.16': + '@rolldown/binding-darwin-x64@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15': + '@rolldown/binding-freebsd-x64@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.16': + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.16': + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-rc.16': + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-rc.16': + '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': - dependencies: - '@emnapi/core': 1.9.2 - '@emnapi/runtime': 1.9.2 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.16': + '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': dependencies: - '@emnapi/core': 1.9.2 - '@emnapi/runtime': 1.9.2 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) - optional: true - - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.16': + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.16': - optional: true - - '@rolldown/pluginutils@1.0.0-rc.15': {} - - '@rolldown/pluginutils@1.0.0-rc.16': {} + '@rolldown/pluginutils@1.0.0-rc.17': {} '@rollup/plugin-node-resolve@15.3.1': dependencies: @@ -4014,11 +3964,11 @@ snapshots: dependencies: acorn: 8.16.0 - '@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.4(@typescript-eslint/types@8.58.2))(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.4(@typescript-eslint/types@8.58.2))(typescript@6.0.3)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))': + '@sveltejs/kit@2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))': dependencies: '@standard-schema/spec': 1.1.0 '@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0) - '@sveltejs/vite-plugin-svelte': 7.0.0(svelte@5.55.4(@typescript-eslint/types@8.58.2))(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + '@sveltejs/vite-plugin-svelte': 7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) '@types/cookie': 0.6.0 acorn: 8.16.0 cookie: 0.6.0 @@ -4029,94 +3979,94 @@ snapshots: mrmime: 2.0.1 set-cookie-parser: 3.1.0 sirv: 3.0.2 - svelte: 5.55.4(@typescript-eslint/types@8.58.2) - vite: 8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) + svelte: 5.55.5(@typescript-eslint/types@8.59.1) + vite: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) optionalDependencies: typescript: 6.0.3 - '@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.4(@typescript-eslint/types@8.58.2))(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))': + '@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))': dependencies: deepmerge: 4.3.1 magic-string: 0.30.21 obug: 2.1.1 - svelte: 5.55.4(@typescript-eslint/types@8.58.2) - vite: 8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) - vitefu: 1.1.3(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + svelte: 5.55.5(@typescript-eslint/types@8.59.1) + vite: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) + vitefu: 1.1.3(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) - '@tailwindcss/node@4.2.2': + '@tailwindcss/node@4.2.4': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.20.1 + enhanced-resolve: 5.21.0 jiti: 2.6.1 lightningcss: 1.32.0 magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.2.2 + tailwindcss: 4.2.4 - '@tailwindcss/oxide-android-arm64@4.2.2': + '@tailwindcss/oxide-android-arm64@4.2.4': optional: true - '@tailwindcss/oxide-darwin-arm64@4.2.2': + '@tailwindcss/oxide-darwin-arm64@4.2.4': optional: true - '@tailwindcss/oxide-darwin-x64@4.2.2': + '@tailwindcss/oxide-darwin-x64@4.2.4': optional: true - '@tailwindcss/oxide-freebsd-x64@4.2.2': + '@tailwindcss/oxide-freebsd-x64@4.2.4': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.4': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': + '@tailwindcss/oxide-linux-arm64-gnu@4.2.4': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.2.2': + '@tailwindcss/oxide-linux-arm64-musl@4.2.4': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.2.2': + '@tailwindcss/oxide-linux-x64-gnu@4.2.4': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.2.2': + '@tailwindcss/oxide-linux-x64-musl@4.2.4': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.2.2': + '@tailwindcss/oxide-wasm32-wasi@4.2.4': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': + '@tailwindcss/oxide-win32-arm64-msvc@4.2.4': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.2.2': + '@tailwindcss/oxide-win32-x64-msvc@4.2.4': optional: true - '@tailwindcss/oxide@4.2.2': + '@tailwindcss/oxide@4.2.4': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.2.2 - '@tailwindcss/oxide-darwin-arm64': 4.2.2 - '@tailwindcss/oxide-darwin-x64': 4.2.2 - '@tailwindcss/oxide-freebsd-x64': 4.2.2 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.2 - '@tailwindcss/oxide-linux-arm64-gnu': 4.2.2 - '@tailwindcss/oxide-linux-arm64-musl': 4.2.2 - '@tailwindcss/oxide-linux-x64-gnu': 4.2.2 - '@tailwindcss/oxide-linux-x64-musl': 4.2.2 - '@tailwindcss/oxide-wasm32-wasi': 4.2.2 - '@tailwindcss/oxide-win32-arm64-msvc': 4.2.2 - '@tailwindcss/oxide-win32-x64-msvc': 4.2.2 - - '@tailwindcss/postcss@4.2.2': + '@tailwindcss/oxide-android-arm64': 4.2.4 + '@tailwindcss/oxide-darwin-arm64': 4.2.4 + '@tailwindcss/oxide-darwin-x64': 4.2.4 + '@tailwindcss/oxide-freebsd-x64': 4.2.4 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.4 + '@tailwindcss/oxide-linux-arm64-gnu': 4.2.4 + '@tailwindcss/oxide-linux-arm64-musl': 4.2.4 + '@tailwindcss/oxide-linux-x64-gnu': 4.2.4 + '@tailwindcss/oxide-linux-x64-musl': 4.2.4 + '@tailwindcss/oxide-wasm32-wasi': 4.2.4 + '@tailwindcss/oxide-win32-arm64-msvc': 4.2.4 + '@tailwindcss/oxide-win32-x64-msvc': 4.2.4 + + '@tailwindcss/postcss@4.2.4': dependencies: '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.2.2 - '@tailwindcss/oxide': 4.2.2 - postcss: 8.5.10 - tailwindcss: 4.2.2 + '@tailwindcss/node': 4.2.4 + '@tailwindcss/oxide': 4.2.4 + postcss: 8.5.12 + tailwindcss: 4.2.4 - '@testing-library/svelte-core@1.0.0(svelte@5.55.4(@typescript-eslint/types@8.58.2))': + '@testing-library/svelte-core@1.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))': dependencies: - svelte: 5.55.4(@typescript-eslint/types@8.58.2) + svelte: 5.55.5(@typescript-eslint/types@8.59.1) - '@trivago/prettier-plugin-sort-imports@6.0.2(prettier-plugin-svelte@3.5.1(prettier@3.8.3)(svelte@5.55.4(@typescript-eslint/types@8.58.2)))(prettier@3.8.3)(svelte@5.55.4(@typescript-eslint/types@8.58.2))': + '@trivago/prettier-plugin-sort-imports@6.0.2(prettier-plugin-svelte@3.5.1(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1)))(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1))': dependencies: '@babel/generator': 7.29.1 '@babel/parser': 7.29.2 @@ -4128,8 +4078,8 @@ snapshots: parse-imports-exports: 0.2.4 prettier: 3.8.3 optionalDependencies: - prettier-plugin-svelte: 3.5.1(prettier@3.8.3)(svelte@5.55.4(@typescript-eslint/types@8.58.2)) - svelte: 5.55.4(@typescript-eslint/types@8.58.2) + prettier-plugin-svelte: 3.5.1(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1)) + svelte: 5.55.5(@typescript-eslint/types@8.59.1) transitivePeerDependencies: - supports-color @@ -4140,9 +4090,9 @@ snapshots: tslib: 2.8.1 optional: true - '@types/bun@1.3.12': + '@types/bun@1.3.13': dependencies: - bun-types: 1.3.12 + bun-types: 1.3.13 '@types/chai@5.2.3': dependencies: @@ -4172,14 +4122,14 @@ snapshots: '@types/trusted-types@2.0.7': {} - '@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3))(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.59.1(@typescript-eslint/parser@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3))(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.58.2 - '@typescript-eslint/type-utils': 8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/utils': 8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.58.2 + '@typescript-eslint/parser': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.59.1 + '@typescript-eslint/type-utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.59.1 eslint: 10.2.1(jiti@2.6.1) ignore: 7.0.5 natural-compare: 1.4.0 @@ -4188,41 +4138,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/parser@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.58.2 - '@typescript-eslint/types': 8.58.2 - '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.58.2 + '@typescript-eslint/scope-manager': 8.59.1 + '@typescript-eslint/types': 8.59.1 + '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.59.1 debug: 4.4.3 eslint: 10.2.1(jiti@2.6.1) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.58.2(typescript@6.0.3)': + '@typescript-eslint/project-service@8.59.1(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.58.2(typescript@6.0.3) - '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/tsconfig-utils': 8.59.1(typescript@6.0.3) + '@typescript-eslint/types': 8.59.1 debug: 4.4.3 typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.58.2': + '@typescript-eslint/scope-manager@8.59.1': dependencies: - '@typescript-eslint/types': 8.58.2 - '@typescript-eslint/visitor-keys': 8.58.2 + '@typescript-eslint/types': 8.59.1 + '@typescript-eslint/visitor-keys': 8.59.1 - '@typescript-eslint/tsconfig-utils@8.58.2(typescript@6.0.3)': + '@typescript-eslint/tsconfig-utils@8.59.1(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': dependencies: - '@typescript-eslint/types': 8.58.2 - '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.3) - '@typescript-eslint/utils': 8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/types': 8.59.1 + '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) debug: 4.4.3 eslint: 10.2.1(jiti@2.6.1) ts-api-utils: 2.5.0(typescript@6.0.3) @@ -4230,14 +4180,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.58.2': {} + '@typescript-eslint/types@8.59.1': {} - '@typescript-eslint/typescript-estree@8.58.2(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.59.1(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.58.2(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.58.2(typescript@6.0.3) - '@typescript-eslint/types': 8.58.2 - '@typescript-eslint/visitor-keys': 8.58.2 + '@typescript-eslint/project-service': 8.59.1(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.59.1(typescript@6.0.3) + '@typescript-eslint/types': 8.59.1 + '@typescript-eslint/visitor-keys': 8.59.1 debug: 4.4.3 minimatch: 10.2.5 semver: 7.7.4 @@ -4247,20 +4197,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/utils@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.58.2 - '@typescript-eslint/types': 8.58.2 - '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.59.1 + '@typescript-eslint/types': 8.59.1 + '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) eslint: 10.2.1(jiti@2.6.1) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.58.2': + '@typescript-eslint/visitor-keys@8.59.1': dependencies: - '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/types': 8.59.1 eslint-visitor-keys: 5.0.1 '@unocss/cli@66.6.8': @@ -4312,7 +4262,7 @@ snapshots: '@unocss/preset-icons@66.6.8': dependencies: - '@iconify/utils': 3.1.0 + '@iconify/utils': 3.1.1 '@unocss/core': 66.6.8 ofetch: 1.5.1 @@ -4378,11 +4328,11 @@ snapshots: '@unocss/core': 66.6.8 magic-string: 0.30.21 - '@unocss/transformer-attributify-jsx@66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + '@unocss/transformer-attributify-jsx@66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: '@unocss/core': 66.6.8 - oxc-parser: 0.124.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) - oxc-walker: 0.7.0(oxc-parser@0.124.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)) + oxc-parser: 0.124.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + oxc-walker: 0.7.0(oxc-parser@0.124.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' @@ -4401,7 +4351,7 @@ snapshots: dependencies: '@unocss/core': 66.6.8 - '@unocss/vite@66.6.8(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))': + '@unocss/vite@66.6.8(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))': dependencies: '@jridgewell/remapping': 2.3.5 '@unocss/config': 66.6.8 @@ -4412,31 +4362,31 @@ snapshots: pathe: 2.0.3 tinyglobby: 0.2.16 unplugin-utils: 0.3.1 - vite: 8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) + vite: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) - '@vitest/browser-playwright@4.1.4(playwright@1.59.1)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.4)': + '@vitest/browser-playwright@4.1.5(playwright@1.59.1)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.5)': dependencies: - '@vitest/browser': 4.1.4(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.4) - '@vitest/mocker': 4.1.4(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + '@vitest/browser': 4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.5) + '@vitest/mocker': 4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) playwright: 1.59.1 tinyrainbow: 3.1.0 - vitest: 4.1.4(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@4.1.4)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + vitest: 4.1.5(@types/node@25.6.0)(@vitest/browser-playwright@4.1.5)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite - '@vitest/browser@4.1.4(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.4)': + '@vitest/browser@4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.5)': dependencies: '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.4(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) - '@vitest/utils': 4.1.4 + '@vitest/mocker': 4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + '@vitest/utils': 4.1.5 magic-string: 0.30.21 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.1.0 - vitest: 4.1.4(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@4.1.4)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + vitest: 4.1.5(@types/node@25.6.0)(@vitest/browser-playwright@4.1.5)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) ws: 8.20.0 transitivePeerDependencies: - bufferutil @@ -4444,10 +4394,10 @@ snapshots: - utf-8-validate - vite - '@vitest/coverage-v8@4.1.4(@vitest/browser@4.1.4)(vitest@4.1.4)': + '@vitest/coverage-v8@4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.4 + '@vitest/utils': 4.1.5 ast-v8-to-istanbul: 1.0.0 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 @@ -4456,48 +4406,48 @@ snapshots: obug: 2.1.1 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.4(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@4.1.4)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + vitest: 4.1.5(@types/node@25.6.0)(@vitest/browser-playwright@4.1.5)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) optionalDependencies: - '@vitest/browser': 4.1.4(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.4) + '@vitest/browser': 4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.5) - '@vitest/expect@4.1.4': + '@vitest/expect@4.1.5': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.1.4 - '@vitest/utils': 4.1.4 + '@vitest/spy': 4.1.5 + '@vitest/utils': 4.1.5 chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.4(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))': + '@vitest/mocker@4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))': dependencies: - '@vitest/spy': 4.1.4 + '@vitest/spy': 4.1.5 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) + vite: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) - '@vitest/pretty-format@4.1.4': + '@vitest/pretty-format@4.1.5': dependencies: tinyrainbow: 3.1.0 - '@vitest/runner@4.1.4': + '@vitest/runner@4.1.5': dependencies: - '@vitest/utils': 4.1.4 + '@vitest/utils': 4.1.5 pathe: 2.0.3 - '@vitest/snapshot@4.1.4': + '@vitest/snapshot@4.1.5': dependencies: - '@vitest/pretty-format': 4.1.4 - '@vitest/utils': 4.1.4 + '@vitest/pretty-format': 4.1.5 + '@vitest/utils': 4.1.5 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.1.4': {} + '@vitest/spy@4.1.5': {} - '@vitest/utils@4.1.4': + '@vitest/utils@4.1.5': dependencies: - '@vitest/pretty-format': 4.1.4 + '@vitest/pretty-format': 4.1.5 convert-source-map: 2.0.0 tinyrainbow: 3.1.0 @@ -4507,14 +4457,14 @@ snapshots: acorn@8.16.0: {} - ajv@6.14.0: + ajv@6.15.0: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.18.0: + ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 fast-uri: 3.1.0 @@ -4571,10 +4521,25 @@ snapshots: dependencies: balanced-match: 4.0.4 - bun-types@1.3.12: + bun-types@1.3.13: dependencies: '@types/node': 25.6.0 + bun@1.3.13: + optionalDependencies: + '@oven/bun-darwin-aarch64': 1.3.13 + '@oven/bun-darwin-x64': 1.3.13 + '@oven/bun-darwin-x64-baseline': 1.3.13 + '@oven/bun-linux-aarch64': 1.3.13 + '@oven/bun-linux-aarch64-musl': 1.3.13 + '@oven/bun-linux-x64': 1.3.13 + '@oven/bun-linux-x64-baseline': 1.3.13 + '@oven/bun-linux-x64-musl': 1.3.13 + '@oven/bun-linux-x64-musl-baseline': 1.3.13 + '@oven/bun-windows-aarch64': 1.3.13 + '@oven/bun-windows-x64': 1.3.13 + '@oven/bun-windows-x64-baseline': 1.3.13 + cac@7.0.0: {} callsites@3.1.0: {} @@ -4598,7 +4563,7 @@ snapshots: cli-truncate@5.2.0: dependencies: slice-ansi: 8.0.0 - string-width: 8.2.0 + string-width: 8.2.1 cliui@8.0.1: dependencies: @@ -4728,10 +4693,10 @@ snapshots: emoji-regex@8.0.0: {} - enhanced-resolve@5.20.1: + enhanced-resolve@5.21.0: dependencies: graceful-fs: 4.2.11 - tapable: 2.3.2 + tapable: 2.3.3 env-paths@2.2.1: {} @@ -4743,7 +4708,7 @@ snapshots: es-errors@1.3.0: {} - es-module-lexer@2.0.0: {} + es-module-lexer@2.1.0: {} escalade@3.2.0: {} @@ -4761,7 +4726,7 @@ snapshots: eslint-rule-docs: 1.1.235 log-symbols: 7.0.1 plur: 5.1.0 - string-width: 8.2.0 + string-width: 8.2.1 supports-hyperlinks: 4.4.0 eslint-formatting-reporter@0.0.0(eslint@10.2.1(jiti@2.6.1)): @@ -4794,7 +4759,7 @@ snapshots: '@types/eslint': 9.6.1 eslint-config-prettier: 10.1.8(eslint@10.2.1(jiti@2.6.1)) - eslint-plugin-svelte@3.17.0(eslint@10.2.1(jiti@2.6.1))(svelte@5.55.4(@typescript-eslint/types@8.58.2)): + eslint-plugin-svelte@3.17.1(eslint@10.2.1(jiti@2.6.1))(svelte@5.55.5(@typescript-eslint/types@8.59.1)): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1)) '@jridgewell/sourcemap-codec': 1.5.5 @@ -4802,13 +4767,13 @@ snapshots: esutils: 2.0.3 globals: 16.5.0 known-css-properties: 0.37.0 - postcss: 8.5.10 - postcss-load-config: 3.1.4(postcss@8.5.10) - postcss-safe-parser: 7.0.1(postcss@8.5.10) + postcss: 8.5.12 + postcss-load-config: 3.1.4(postcss@8.5.12) + postcss-safe-parser: 7.0.1(postcss@8.5.12) semver: 7.7.4 - svelte-eslint-parser: 1.6.0(svelte@5.55.4(@typescript-eslint/types@8.58.2)) + svelte-eslint-parser: 1.6.0(svelte@5.55.5(@typescript-eslint/types@8.59.1)) optionalDependencies: - svelte: 5.55.4(@typescript-eslint/types@8.58.2) + svelte: 5.55.5(@typescript-eslint/types@8.59.1) transitivePeerDependencies: - ts-node @@ -4844,7 +4809,7 @@ snapshots: '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 '@types/estree': 1.0.8 - ajv: 6.14.0 + ajv: 6.15.0 cross-spawn: 7.0.6 debug: 4.4.3 escape-string-regexp: 4.0.0 @@ -4889,11 +4854,11 @@ snapshots: dependencies: estraverse: 5.3.0 - esrap@2.2.5(@typescript-eslint/types@8.58.2): + esrap@2.2.5(@typescript-eslint/types@8.59.1): dependencies: '@jridgewell/sourcemap-codec': 1.5.5 optionalDependencies: - '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/types': 8.59.1 esrecurse@4.3.0: dependencies: @@ -4974,11 +4939,11 @@ snapshots: flowbite-datepicker@2.0.0: dependencies: '@rollup/plugin-node-resolve': 15.3.1 - '@tailwindcss/postcss': 4.2.2 + '@tailwindcss/postcss': 4.2.4 transitivePeerDependencies: - rollup - flowbite-svelte@1.33.1(svelte@5.55.4(@typescript-eslint/types@8.58.2))(tailwindcss@4.2.2): + flowbite-svelte@1.33.1(svelte@5.55.5(@typescript-eslint/types@8.59.1))(tailwindcss@4.2.4): dependencies: '@floating-ui/dom': 1.7.6 '@floating-ui/utils': 0.2.11 @@ -4987,10 +4952,10 @@ snapshots: date-fns: 4.1.0 esm-env: 1.2.2 flowbite: 3.1.2 - svelte: 5.55.4(@typescript-eslint/types@8.58.2) + svelte: 5.55.5(@typescript-eslint/types@8.59.1) tailwind-merge: 3.5.0 - tailwind-variants: 3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.2) - tailwindcss: 4.2.2 + tailwind-variants: 3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.4) + tailwindcss: 4.2.4 transitivePeerDependencies: - rollup @@ -5007,7 +4972,7 @@ snapshots: '@popperjs/core': 2.11.8 flowbite-datepicker: 1.3.2 mini-svg-data-uri: 1.4.4 - postcss: 8.5.10 + postcss: 8.5.12 transitivePeerDependencies: - rollup @@ -5016,8 +4981,8 @@ snapshots: '@popperjs/core': 2.11.8 flowbite-datepicker: 2.0.0 mini-svg-data-uri: 1.4.4 - postcss: 8.5.10 - tailwindcss: 4.2.2 + postcss: 8.5.12 + tailwindcss: 4.2.4 transitivePeerDependencies: - rollup @@ -5038,34 +5003,34 @@ snapshots: '@sec-ant/readable-stream': 0.4.1 is-stream: 4.0.1 - git-cliff-darwin-arm64@2.12.0: + git-cliff-darwin-arm64@2.13.1: optional: true - git-cliff-darwin-x64@2.12.0: + git-cliff-darwin-x64@2.13.1: optional: true - git-cliff-linux-arm64@2.12.0: + git-cliff-linux-arm64@2.13.1: optional: true - git-cliff-linux-x64@2.12.0: + git-cliff-linux-x64@2.13.1: optional: true - git-cliff-windows-arm64@2.12.0: + git-cliff-windows-arm64@2.13.1: optional: true - git-cliff-windows-x64@2.12.0: + git-cliff-windows-x64@2.13.1: optional: true - git-cliff@2.12.0: + git-cliff@2.13.1: dependencies: execa: 9.6.1 optionalDependencies: - git-cliff-darwin-arm64: 2.12.0 - git-cliff-darwin-x64: 2.12.0 - git-cliff-linux-arm64: 2.12.0 - git-cliff-linux-x64: 2.12.0 - git-cliff-windows-arm64: 2.12.0 - git-cliff-windows-x64: 2.12.0 + git-cliff-darwin-arm64: 2.13.1 + git-cliff-darwin-x64: 2.13.1 + git-cliff-linux-arm64: 2.13.1 + git-cliff-linux-x64: 2.13.1 + git-cliff-windows-arm64: 2.13.1 + git-cliff-windows-x64: 2.13.1 git-raw-commits@5.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0): dependencies: @@ -5079,9 +5044,9 @@ snapshots: dependencies: is-glob: 4.0.3 - global-directory@4.0.1: + global-directory@5.0.0: dependencies: - ini: 4.1.1 + ini: 6.0.0 globals@16.5.0: {} @@ -5127,7 +5092,7 @@ snapshots: imurmurhash@0.1.4: {} - ini@4.1.1: {} + ini@6.0.0: {} irregular-plurals@3.5.0: {} @@ -5423,7 +5388,7 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 - oxc-parser@0.124.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2): + oxc-parser@0.124.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0): dependencies: '@oxc-project/types': 0.124.0 optionalDependencies: @@ -5443,7 +5408,7 @@ snapshots: '@oxc-parser/binding-linux-x64-gnu': 0.124.0 '@oxc-parser/binding-linux-x64-musl': 0.124.0 '@oxc-parser/binding-openharmony-arm64': 0.124.0 - '@oxc-parser/binding-wasm32-wasi': 0.124.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@oxc-parser/binding-wasm32-wasi': 0.124.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) '@oxc-parser/binding-win32-arm64-msvc': 0.124.0 '@oxc-parser/binding-win32-ia32-msvc': 0.124.0 '@oxc-parser/binding-win32-x64-msvc': 0.124.0 @@ -5451,10 +5416,10 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' - oxc-walker@0.7.0(oxc-parser@0.124.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)): + oxc-walker@0.7.0(oxc-parser@0.124.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)): dependencies: magic-regexp: 0.10.0 - oxc-parser: 0.124.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + oxc-parser: 0.124.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) oxfmt@0.35.0: dependencies: @@ -5545,27 +5510,27 @@ snapshots: pngjs@7.0.0: {} - postcss-load-config@3.1.4(postcss@8.5.10): + postcss-load-config@3.1.4(postcss@8.5.12): dependencies: lilconfig: 2.1.0 yaml: 1.10.3 optionalDependencies: - postcss: 8.5.10 + postcss: 8.5.12 - postcss-safe-parser@7.0.1(postcss@8.5.10): + postcss-safe-parser@7.0.1(postcss@8.5.12): dependencies: - postcss: 8.5.10 + postcss: 8.5.12 - postcss-scss@4.0.9(postcss@8.5.10): + postcss-scss@4.0.9(postcss@8.5.12): dependencies: - postcss: 8.5.10 + postcss: 8.5.12 postcss-selector-parser@7.1.1: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss@8.5.10: + postcss@8.5.12: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 @@ -5577,10 +5542,10 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier-plugin-svelte@3.5.1(prettier@3.8.3)(svelte@5.55.4(@typescript-eslint/types@8.58.2)): + prettier-plugin-svelte@3.5.1(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1)): dependencies: prettier: 3.8.3 - svelte: 5.55.4(@typescript-eslint/types@8.58.2) + svelte: 5.55.5(@typescript-eslint/types@8.59.1) prettier@2.5.1: {} @@ -5622,52 +5587,31 @@ snapshots: rfdc@1.4.1: {} - rolldown@1.0.0-rc.15: + rolldown@1.0.0-rc.17: dependencies: - '@oxc-project/types': 0.124.0 - '@rolldown/pluginutils': 1.0.0-rc.15 + '@oxc-project/types': 0.127.0 + '@rolldown/pluginutils': 1.0.0-rc.17 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-rc.15 - '@rolldown/binding-darwin-arm64': 1.0.0-rc.15 - '@rolldown/binding-darwin-x64': 1.0.0-rc.15 - '@rolldown/binding-freebsd-x64': 1.0.0-rc.15 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.15 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.15 - '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.15 - '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.15 - '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.15 - '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.15 - '@rolldown/binding-linux-x64-musl': 1.0.0-rc.15 - '@rolldown/binding-openharmony-arm64': 1.0.0-rc.15 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.15 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.15 - '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.15 - - rolldown@1.0.0-rc.16: - dependencies: - '@oxc-project/types': 0.126.0 - '@rolldown/pluginutils': 1.0.0-rc.16 - optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-rc.16 - '@rolldown/binding-darwin-arm64': 1.0.0-rc.16 - '@rolldown/binding-darwin-x64': 1.0.0-rc.16 - '@rolldown/binding-freebsd-x64': 1.0.0-rc.16 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.16 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.16 - '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.16 - '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.16 - '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.16 - '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.16 - '@rolldown/binding-linux-x64-musl': 1.0.0-rc.16 - '@rolldown/binding-openharmony-arm64': 1.0.0-rc.16 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.16 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.16 - '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.16 - - runed@0.28.0(svelte@5.55.4(@typescript-eslint/types@8.58.2)): + '@rolldown/binding-android-arm64': 1.0.0-rc.17 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.17 + '@rolldown/binding-darwin-x64': 1.0.0-rc.17 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.17 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.17 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.17 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.17 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.17 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.17 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.17 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.17 + + runed@0.28.0(svelte@5.55.5(@typescript-eslint/types@8.59.1)): dependencies: esm-env: 1.2.2 - svelte: 5.55.4(@typescript-eslint/types@8.58.2) + svelte: 5.55.5(@typescript-eslint/types@8.59.1) sade@1.8.1: dependencies: @@ -5730,7 +5674,7 @@ snapshots: get-east-asian-width: 1.5.0 strip-ansi: 7.2.0 - string-width@8.2.0: + string-width@8.2.1: dependencies: get-east-asian-width: 1.5.0 strip-ansi: 7.2.0 @@ -5758,48 +5702,48 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-adapter-bun@1.0.1(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.4(@typescript-eslint/types@8.58.2))(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.4(@typescript-eslint/types@8.58.2))(typescript@6.0.3)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(typescript@6.0.3): + svelte-adapter-bun@1.0.1(@sveltejs/kit@2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(typescript@6.0.3): dependencies: - '@sveltejs/kit': 2.57.1(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.4(@typescript-eslint/types@8.58.2))(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.4(@typescript-eslint/types@8.58.2))(typescript@6.0.3)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) - rolldown: 1.0.0-rc.16 + '@sveltejs/kit': 2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + rolldown: 1.0.0-rc.17 typescript: 6.0.3 - svelte-check@4.4.6(picomatch@4.0.4)(svelte@5.55.4(@typescript-eslint/types@8.58.2))(typescript@6.0.3): + svelte-check@4.4.6(picomatch@4.0.4)(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3): dependencies: '@jridgewell/trace-mapping': 0.3.31 chokidar: 4.0.3 fdir: 6.5.0(picomatch@4.0.4) picocolors: 1.1.1 sade: 1.8.1 - svelte: 5.55.4(@typescript-eslint/types@8.58.2) + svelte: 5.55.5(@typescript-eslint/types@8.59.1) typescript: 6.0.3 transitivePeerDependencies: - picomatch - svelte-eslint-parser@1.6.0(svelte@5.55.4(@typescript-eslint/types@8.58.2)): + svelte-eslint-parser@1.6.0(svelte@5.55.5(@typescript-eslint/types@8.59.1)): dependencies: eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 - postcss: 8.5.10 - postcss-scss: 4.0.9(postcss@8.5.10) + postcss: 8.5.12 + postcss-scss: 4.0.9(postcss@8.5.12) postcss-selector-parser: 7.1.1 semver: 7.7.4 optionalDependencies: - svelte: 5.55.4(@typescript-eslint/types@8.58.2) + svelte: 5.55.5(@typescript-eslint/types@8.59.1) - svelte-kit-sessions@0.4.0(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.4(@typescript-eslint/types@8.58.2))(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.4(@typescript-eslint/types@8.58.2))(typescript@6.0.3)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.4(@typescript-eslint/types@8.58.2)): + svelte-kit-sessions@0.4.0(@sveltejs/kit@2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1)): dependencies: '@isaacs/ttlcache': 1.4.1 - '@sveltejs/kit': 2.57.1(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.4(@typescript-eslint/types@8.58.2))(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.4(@typescript-eslint/types@8.58.2))(typescript@6.0.3)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) - svelte: 5.55.4(@typescript-eslint/types@8.58.2) + '@sveltejs/kit': 2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + svelte: 5.55.5(@typescript-eslint/types@8.59.1) - svelte-sonner@1.1.0(svelte@5.55.4(@typescript-eslint/types@8.58.2)): + svelte-sonner@1.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.1)): dependencies: - runed: 0.28.0(svelte@5.55.4(@typescript-eslint/types@8.58.2)) - svelte: 5.55.4(@typescript-eslint/types@8.58.2) + runed: 0.28.0(svelte@5.55.5(@typescript-eslint/types@8.59.1)) + svelte: 5.55.5(@typescript-eslint/types@8.59.1) - svelte@5.55.4(@typescript-eslint/types@8.58.2): + svelte@5.55.5(@typescript-eslint/types@8.59.1): dependencies: '@jridgewell/remapping': 2.3.5 '@jridgewell/sourcemap-codec': 1.5.5 @@ -5812,7 +5756,7 @@ snapshots: clsx: 2.1.1 devalue: 5.7.1 esm-env: 1.2.2 - esrap: 2.2.5(@typescript-eslint/types@8.58.2) + esrap: 2.2.5(@typescript-eslint/types@8.59.1) is-reference: 3.0.3 locate-character: 3.0.0 magic-string: 0.30.21 @@ -5826,15 +5770,15 @@ snapshots: tailwind-merge@3.5.0: {} - tailwind-variants@3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.2): + tailwind-variants@3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.4): dependencies: - tailwindcss: 4.2.2 + tailwindcss: 4.2.4 optionalDependencies: tailwind-merge: 3.5.0 - tailwindcss@4.2.2: {} + tailwindcss@4.2.4: {} - tapable@2.3.2: {} + tapable@2.3.3: {} tinybench@2.9.0: {} @@ -5866,12 +5810,12 @@ snapshots: type-level-regexp@0.1.17: {} - typescript-eslint@8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3): + typescript-eslint@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.58.2(@typescript-eslint/parser@8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3))(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/parser': 8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.3) - '@typescript-eslint/utils': 8.58.2(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/eslint-plugin': 8.59.1(@typescript-eslint/parser@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3))(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/parser': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) eslint: 10.2.1(jiti@2.6.1) typescript: 6.0.3 transitivePeerDependencies: @@ -5902,7 +5846,7 @@ snapshots: universal-user-agent@7.0.3: {} - unocss@66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)): + unocss@66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)): dependencies: '@unocss/cli': 66.6.8 '@unocss/core': 66.6.8 @@ -5916,11 +5860,11 @@ snapshots: '@unocss/preset-wind': 66.6.8 '@unocss/preset-wind3': 66.6.8 '@unocss/preset-wind4': 66.6.8 - '@unocss/transformer-attributify-jsx': 66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@unocss/transformer-attributify-jsx': 66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) '@unocss/transformer-compile-class': 66.6.8 '@unocss/transformer-directives': 66.6.8 '@unocss/transformer-variant-group': 66.6.8 - '@unocss/vite': 66.6.8(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + '@unocss/vite': 66.6.8(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' @@ -5946,16 +5890,14 @@ snapshots: util-deprecate@1.0.2: {} - uuid@10.0.0: {} - - uuid@13.0.0: {} + uuid@14.0.0: {} - vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3): + vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 - postcss: 8.5.10 - rolldown: 1.0.0-rc.15 + postcss: 8.5.12 + rolldown: 1.0.0-rc.17 tinyglobby: 0.2.16 optionalDependencies: '@types/node': 25.6.0 @@ -5963,26 +5905,26 @@ snapshots: jiti: 2.6.1 yaml: 2.8.3 - vitefu@1.1.3(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)): + vitefu@1.1.3(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)): optionalDependencies: - vite: 8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) + vite: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) - vitest-browser-svelte@2.1.1(svelte@5.55.4(@typescript-eslint/types@8.58.2))(vitest@4.1.4): + vitest-browser-svelte@2.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vitest@4.1.5): dependencies: - '@testing-library/svelte-core': 1.0.0(svelte@5.55.4(@typescript-eslint/types@8.58.2)) - svelte: 5.55.4(@typescript-eslint/types@8.58.2) - vitest: 4.1.4(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@4.1.4)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + '@testing-library/svelte-core': 1.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1)) + svelte: 5.55.5(@typescript-eslint/types@8.59.1) + vitest: 4.1.5(@types/node@25.6.0)(@vitest/browser-playwright@4.1.5)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) - vitest@4.1.4(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@4.1.4)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)): + vitest@4.1.5(@types/node@25.6.0)(@vitest/browser-playwright@4.1.5)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)): dependencies: - '@vitest/expect': 4.1.4 - '@vitest/mocker': 4.1.4(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.4 - '@vitest/runner': 4.1.4 - '@vitest/snapshot': 4.1.4 - '@vitest/spy': 4.1.4 - '@vitest/utils': 4.1.4 - es-module-lexer: 2.0.0 + '@vitest/expect': 4.1.5 + '@vitest/mocker': 4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.5 + '@vitest/runner': 4.1.5 + '@vitest/snapshot': 4.1.5 + '@vitest/spy': 4.1.5 + '@vitest/utils': 4.1.5 + es-module-lexer: 2.1.0 expect-type: 1.3.0 magic-string: 0.30.21 obug: 2.1.1 @@ -5993,12 +5935,12 @@ snapshots: tinyexec: 1.1.1 tinyglobby: 0.2.16 tinyrainbow: 3.1.0 - vite: 8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) + vite: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.6.0 - '@vitest/browser-playwright': 4.1.4(playwright@1.59.1)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.4) - '@vitest/coverage-v8': 4.1.4(@vitest/browser@4.1.4)(vitest@4.1.4) + '@vitest/browser-playwright': 4.1.5(playwright@1.59.1)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.5) + '@vitest/coverage-v8': 4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5) transitivePeerDependencies: - msw diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 57782b5..c5369dd 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,29 +2,30 @@ catalogs: build: '@tsconfig/svelte': ^5.0.8 'svelte-adapter-bun': ^1.0.1 - typescript: ^6.0.2 + typescript: ^6.0.3 ci: - '@commitlint/cli': ^20.5.0 + '@commitlint/cli': ^20.5.2 '@commitlint/config-conventional': ^20.5.0 '@favware/cliff-jumper': ^6.1.0 - '@nanoforge-dev/actions': ^1.2.3 + '@nanoforge-dev/actions': ^1.3.0 husky: ^9.1.7 lint-staged: ^16.4.0 components: flowbite: ^4.0.1 flowbite-svelte: ^1.33.1 monaco-editor: ^0.55.1 - svelte-sonner: ^1.1.0 + svelte-sonner: ^1.1.1 core: '@nanoforge-dev/ecs-lib': ^1.1.2 '@sveltejs/adapter-auto': ^7.0.1 - '@sveltejs/kit': ^2.57.1 + '@sveltejs/kit': ^2.58.0 '@sveltejs/vite-plugin-svelte': ^7.0.0 - '@types/bun': ^1.3.12 - svelte: ^5.55.3 + '@types/bun': ^1.3.13 + bun: ^1.3.13 + svelte: ^5.55.5 svelte-check: ^4.4.6 - svelte-kit-sessions: "^0.4.0" - vite: ^8.0.8 + svelte-kit-sessions: ^0.4.0 + vite: ^8.0.10 css: '@alexanderniebuhr/prettier-plugin-unocss': ^0.0.4 '@unocss/extractor-svelte': ^66.6.8 @@ -33,28 +34,29 @@ catalogs: '@unocss/preset-wind4': ^66.6.8 unocss: ^66.6.8 i18n: - '@inlang/paraglide-js': ^2.15.3 + '@inlang/paraglide-js': ^2.17.0 icons: '@iconify-json/ic': ^1.2.4 - '@iconify-json/material-icon-theme': ^1.2.58 + '@iconify-json/material-icon-theme': ^1.2.61 '@iconify-json/solar': ^1.2.5 lint: '@nanoforge-dev/utils-eslint-config': ^1.0.2 '@nanoforge-dev/utils-prettier-config': ^1.0.2 '@trivago/prettier-plugin-sort-imports': ^6.0.2 - eslint: ^10.2.0 - eslint-plugin-svelte: ^3.17.0 + eslint: ^10.2.1 + eslint-plugin-svelte: ^3.17.1 globals: ^17.5.0 - prettier: ^3.8.2 + prettier: ^3.8.3 prettier-plugin-svelte: ^3.5.1 - typescript-eslint: ^8.58.2 + typescript-eslint: ^8.59.1 test: '@playwright/test': ^1.59.1 - '@vitest/browser-playwright': ^4.1.4 - '@vitest/coverage-v8': ^4.1.4 + '@vitest/browser-playwright': ^4.1.5 + '@vitest/coverage-v8': ^4.1.5 playwright: ^1.59.1 - vitest: ^4.1.4 + vitest: ^4.1.5 vitest-browser-svelte: ^2.1.1 onlyBuiltDependencies: + - bun - esbuild From 26ad49402ef372ebee62c037e1a27e1eb3dc9766 Mon Sep 17 00:00:00 2001 From: Exelo Date: Tue, 28 Apr 2026 23:05:19 +0900 Subject: [PATCH 04/58] chore: feat add base loader --- package.json | 1 + pnpm-lock.yaml | 13 +++++++ pnpm-workspace.yaml | 2 ++ src/lib/server/loader/env.ts | 35 +++++++++++++++++++ src/lib/server/loader/index.ts | 1 + src/lib/server/loader/loader.ts | 19 ++++++++++ .../server/utils/request-handler/handler.ts | 5 +-- 7 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 src/lib/server/loader/env.ts create mode 100644 src/lib/server/loader/index.ts create mode 100644 src/lib/server/loader/loader.ts diff --git a/package.json b/package.json index a73af83..8b055cd 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "@vitest/browser-playwright": "catalog:test", "@vitest/coverage-v8": "catalog:test", "bun": "catalog:core", + "dotenv": "catalog:back-libs", "eslint": "catalog:lint", "eslint-plugin-svelte": "catalog:lint", "flowbite": "catalog:components", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8ed73b4..515f729 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,6 +5,10 @@ settings: excludeLinksFromLockfile: false catalogs: + back-libs: + dotenv: + specifier: ^17.4.2 + version: 17.4.2 build: '@tsconfig/svelte': specifier: ^5.0.8 @@ -235,6 +239,9 @@ importers: bun: specifier: catalog:core version: 1.3.13 + dotenv: + specifier: catalog:back-libs + version: 17.4.2 eslint: specifier: catalog:lint version: 10.2.1(jiti@2.6.1) @@ -1810,6 +1817,10 @@ packages: resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} engines: {node: '>=8'} + dotenv@17.4.2: + resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==} + engines: {node: '>=12'} + duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} @@ -4687,6 +4698,8 @@ snapshots: dependencies: is-obj: 2.0.0 + dotenv@17.4.2: {} + duplexer@0.1.2: {} emoji-regex@10.6.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index c5369dd..34ec471 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,6 @@ catalogs: + back-libs: + dotenv: ^17.4.2 build: '@tsconfig/svelte': ^5.0.8 'svelte-adapter-bun': ^1.0.1 diff --git a/src/lib/server/loader/env.ts b/src/lib/server/loader/env.ts new file mode 100644 index 0000000..6c24390 --- /dev/null +++ b/src/lib/server/loader/env.ts @@ -0,0 +1,35 @@ +import { config } from 'dotenv'; +import { join } from 'path'; + +const PREFIX_CLIENT = 'NANOFORGE_CLIENT_'; +const PREFIX_SERVER = 'NANOFORGE_SERVER_'; +const PREFIX = 'NANOFORGE_'; + +const loadEnv = (path: string): Record => { + const env = {}; + config({ path, processEnv: env }); + return env; +}; + +const parseEnv = ( + part: 'client' | 'server', + env: Record, +): Record => { + return Object.fromEntries( + Object.entries(env) + .filter( + ([key]) => + key.startsWith(PREFIX) || + (part === 'client' && key.startsWith(PREFIX_CLIENT)) || + (part === 'server' && key.startsWith(PREFIX_SERVER)), + ) + .map(([key, value]) => [ + key.replace(part === 'client' ? PREFIX_CLIENT : PREFIX_SERVER, '').replace(PREFIX, ''), + value, + ]), + ); +}; + +export const resolveEnv = (part: 'client' | 'server', projectPath: string) => { + return parseEnv(part, loadEnv(join(projectPath, '.env'))); +}; diff --git a/src/lib/server/loader/index.ts b/src/lib/server/loader/index.ts new file mode 100644 index 0000000..0223844 --- /dev/null +++ b/src/lib/server/loader/index.ts @@ -0,0 +1 @@ +export { Loader } from './loader'; diff --git a/src/lib/server/loader/loader.ts b/src/lib/server/loader/loader.ts new file mode 100644 index 0000000..d1f101c --- /dev/null +++ b/src/lib/server/loader/loader.ts @@ -0,0 +1,19 @@ +import { Exception } from '@utils-server/exception'; +import type { Context } from '@utils-server/request-handler'; + +import { resolveEnv } from './env'; + +type Part = 'client' | 'server'; + +export class Loader { + private readonly _projectPath: string; + + constructor(context: Context) { + if (!context.project) throw new Exception('Bad Request', 'Project is not defined', 400); + this._projectPath = context.project.path; + } + + getEnv(part: Part) { + return resolveEnv(part, this._projectPath); + } +} diff --git a/src/lib/server/utils/request-handler/handler.ts b/src/lib/server/utils/request-handler/handler.ts index c4fa424..048e1cb 100644 --- a/src/lib/server/utils/request-handler/handler.ts +++ b/src/lib/server/utils/request-handler/handler.ts @@ -4,6 +4,7 @@ import { type Api, getApi } from '$lib/server/api'; import { Cli } from '$lib/server/cli'; import { FileSystem } from '$lib/server/file-system'; import { Git } from '$lib/server/git'; +import { Loader } from '$lib/server/loader'; import type { Context } from '@utils-server/request-handler/context'; @@ -15,7 +16,7 @@ export class Handler { private _apiCache: Api | undefined; private _cliCache: Cli | undefined; private _fsCache: FileSystem | undefined; - private _loaderCache: any | undefined; + private _loaderCache: Loader | undefined; private _gitCache: Git | undefined; constructor(context: Context, event: RequestEvent, body: Body) { @@ -62,7 +63,7 @@ export class Handler { } get loader(): any { - if (!this._loaderCache) this._loaderCache = {}; + if (!this._loaderCache) this._loaderCache = new Loader(this._context); return this._loaderCache; } From 3d2b10506fb1332a5f803d818b9cee6c32723a69 Mon Sep 17 00:00:00 2001 From: Exelo Date: Wed, 29 Apr 2026 00:50:03 +0900 Subject: [PATCH 05/58] chore: add full loader --- src/lib/loader/client/gameFiles.ts | 2 +- src/lib/loader/client/types/manifest.type.ts | 2 +- .../server/file-system/project-directory.ts | 8 ++--- src/lib/server/file-system/project-file.ts | 5 ++++ src/lib/server/loader/env.ts | 9 +++--- src/lib/server/loader/loader.ts | 29 +++++++++++++++++-- src/lib/server/loader/types.ts | 6 ++++ src/routes/game-loader/+page.server.ts | 2 +- 8 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 src/lib/server/loader/types.ts diff --git a/src/lib/loader/client/gameFiles.ts b/src/lib/loader/client/gameFiles.ts index b6defa2..808472a 100644 --- a/src/lib/loader/client/gameFiles.ts +++ b/src/lib/loader/client/gameFiles.ts @@ -27,7 +27,7 @@ const loadScript = async (file: IExtendedManifestFile): Promise }; export function fetchGameFiles(manifest: IManifest): Promise[] { - return manifest.files.map(async (filePath: string): Promise => { + return manifest.files.map(async ({ path: filePath }): Promise => { const fileIsWasm = filePath.endsWith('.wasm'); const fileContent = await localApi.getGameBuildFile( filePath, diff --git a/src/lib/loader/client/types/manifest.type.ts b/src/lib/loader/client/types/manifest.type.ts index 580f9a2..a9b59a4 100644 --- a/src/lib/loader/client/types/manifest.type.ts +++ b/src/lib/loader/client/types/manifest.type.ts @@ -1,6 +1,6 @@ export interface IManifest { version: string; - files: string[]; + files: { path: string }[]; } export interface IExtendedManifestFile { diff --git a/src/lib/server/file-system/project-directory.ts b/src/lib/server/file-system/project-directory.ts index 645fada..650cd3b 100644 --- a/src/lib/server/file-system/project-directory.ts +++ b/src/lib/server/file-system/project-directory.ts @@ -1,5 +1,5 @@ import fs from 'node:fs'; -import path from 'node:path'; +import { dirname, resolve } from 'path'; import { FileSystemError } from './file-system-error'; @@ -29,7 +29,7 @@ export class ProjectDirectory { private readonly projectPath: string; constructor(dirPath: string, projectPath: string) { - this.path = path.resolve(projectPath, './' + dirPath); + this.path = resolve(projectPath, './' + dirPath); this.projectPath = projectPath; this._checkPathIsInsideProject(); @@ -58,12 +58,12 @@ export class ProjectDirectory { } rename(newPath: string): void { - const absoluteNewDirPath = path.resolve(this.projectPath, './' + newPath); + const absoluteNewDirPath = resolve(this.projectPath, './' + newPath); this._checkPathIsInsideProject(absoluteNewDirPath); this._checkPathExists(); this._checkPathIsDir(); this._checkPathIsWritable(); - const newFolderPath = path.dirname(absoluteNewDirPath); + const newFolderPath = dirname(absoluteNewDirPath); this._checkPathExists(newFolderPath); this._checkPathIsWritable(newFolderPath); this._checkPathNotExists(absoluteNewDirPath); diff --git a/src/lib/server/file-system/project-file.ts b/src/lib/server/file-system/project-file.ts index 7bf7f1b..694790b 100644 --- a/src/lib/server/file-system/project-file.ts +++ b/src/lib/server/file-system/project-file.ts @@ -24,6 +24,11 @@ export class ProjectFile { return fs.readFileSync(this._path).toString(encoding); } + readStream(): fs.ReadStream { + this.isReadable(); + return fs.createReadStream(this._path); + } + readJson(): T { const raw = this.read(); return JSON.parse(raw) as T; diff --git a/src/lib/server/loader/env.ts b/src/lib/server/loader/env.ts index 6c24390..ccaa1be 100644 --- a/src/lib/server/loader/env.ts +++ b/src/lib/server/loader/env.ts @@ -1,6 +1,8 @@ import { config } from 'dotenv'; import { join } from 'path'; +import type { Part } from './types'; + const PREFIX_CLIENT = 'NANOFORGE_CLIENT_'; const PREFIX_SERVER = 'NANOFORGE_SERVER_'; const PREFIX = 'NANOFORGE_'; @@ -11,10 +13,7 @@ const loadEnv = (path: string): Record => { return env; }; -const parseEnv = ( - part: 'client' | 'server', - env: Record, -): Record => { +const parseEnv = (part: Part, env: Record): Record => { return Object.fromEntries( Object.entries(env) .filter( @@ -30,6 +29,6 @@ const parseEnv = ( ); }; -export const resolveEnv = (part: 'client' | 'server', projectPath: string) => { +export const resolveEnv = (part: Part, projectPath: string) => { return parseEnv(part, loadEnv(join(projectPath, '.env'))); }; diff --git a/src/lib/server/loader/loader.ts b/src/lib/server/loader/loader.ts index d1f101c..28eae35 100644 --- a/src/lib/server/loader/loader.ts +++ b/src/lib/server/loader/loader.ts @@ -1,19 +1,42 @@ +import type { ReadStream } from 'fs'; +import { join } from 'path'; + +import { FileSystem } from '$lib/server/file-system'; +import { directoryContentToFileEntries } from '$lib/server/file-system/project-directory'; + import { Exception } from '@utils-server/exception'; import type { Context } from '@utils-server/request-handler'; import { resolveEnv } from './env'; - -type Part = 'client' | 'server'; +import type { Manifest, Part } from './types'; export class Loader { private readonly _projectPath: string; + private readonly _fs: FileSystem; constructor(context: Context) { if (!context.project) throw new Exception('Bad Request', 'Project is not defined', 400); this._projectPath = context.project.path; + this._fs = new FileSystem(context); } - getEnv(part: Part) { + getEnv(part: Part): Record { return resolveEnv(part, this._projectPath); } + + getManifest(part: Part): Manifest { + const entries = directoryContentToFileEntries( + this._fs.getDirectory(join('.nanoforge', part)).read(true), + this._projectPath, + ); + return { + version: '1.0.0', + files: entries.map((path) => ({ path })), + }; + } + + getFile(part: Part, path: string): ReadStream { + const fullPath = join('.nanoforge', part, `${path.startsWith('/') ? path.slice(1) : path}`); + return this._fs.getFile(fullPath).readStream(); + } } diff --git a/src/lib/server/loader/types.ts b/src/lib/server/loader/types.ts new file mode 100644 index 0000000..92c242a --- /dev/null +++ b/src/lib/server/loader/types.ts @@ -0,0 +1,6 @@ +export type Part = 'client' | 'server'; + +export interface Manifest { + version: string; + files: { path: string }[]; +} diff --git a/src/routes/game-loader/+page.server.ts b/src/routes/game-loader/+page.server.ts index c07cb77..ec18e82 100644 --- a/src/routes/game-loader/+page.server.ts +++ b/src/routes/game-loader/+page.server.ts @@ -28,7 +28,7 @@ export const actions = { manifest: { files: directoryContentToFileEntries( new ProjectDirectory(`/.nanoforge/${data.side}/`, locals.session.data.path).read(true), - ), + ).map((path) => ({ path })), version: '0.0.0', }, }; From 915e4a9fab2515bd0863bce0eda56215817e8ebb Mon Sep 17 00:00:00 2001 From: Exelo Date: Wed, 6 May 2026 18:08:37 +0900 Subject: [PATCH 06/58] chore: add save handler --- .gitignore | 1 - src/lib/server/cli/cli.ts | 4 +- .../server/file-system/project-directory.ts | 6 +++ src/lib/server/loader/env.ts | 2 +- src/lib/server/loader/loader.ts | 4 +- src/lib/server/loader/types.ts | 2 - src/lib/server/project/index.ts | 2 + src/lib/server/project/project-handler.ts | 32 ++++++++++++++++ src/lib/server/project/project-manager.ts | 24 ++++++++++++ src/lib/server/project/save/save-handler.ts | 23 +++++++++++ .../server/utils/request-handler/handler.ts | 7 ++++ src/lib/utils/types/index.ts | 3 ++ src/lib/utils/types/part.type.ts | 1 + src/lib/utils/types/save.type.ts | 38 +++++++++++++++++++ 14 files changed, 143 insertions(+), 6 deletions(-) create mode 100644 src/lib/server/project/project-handler.ts create mode 100644 src/lib/server/project/project-manager.ts create mode 100644 src/lib/server/project/save/save-handler.ts create mode 100644 src/lib/utils/types/part.type.ts create mode 100644 src/lib/utils/types/save.type.ts diff --git a/.gitignore b/.gitignore index b2b5556..e8c9d59 100644 --- a/.gitignore +++ b/.gitignore @@ -229,6 +229,5 @@ dist .svelte-kit/ test-results/ -package public/ \ No newline at end of file diff --git a/src/lib/server/cli/cli.ts b/src/lib/server/cli/cli.ts index 4d24f67..803a715 100644 --- a/src/lib/server/cli/cli.ts +++ b/src/lib/server/cli/cli.ts @@ -1,3 +1,5 @@ +import { env } from '$env/dynamic/private'; + import { camelToKebab } from '@utils/string'; import type { Context } from '@utils-server/request-handler'; @@ -69,7 +71,7 @@ export class Cli { opts: Record, { async = false }: CliRunOptions = {}, ): void { - const fullCommand = ['nf', command, ...params, ...this.resolveParams(opts)]; + const fullCommand = [env.NF_CLI_PATH ?? 'nf', command, ...params, ...this.resolveParams(opts)]; if (async) { const res = Bun.spawn(fullCommand, { stdout: 'pipe', stderr: 'pipe' }); diff --git a/src/lib/server/file-system/project-directory.ts b/src/lib/server/file-system/project-directory.ts index 650cd3b..3821cd9 100644 --- a/src/lib/server/file-system/project-directory.ts +++ b/src/lib/server/file-system/project-directory.ts @@ -71,6 +71,12 @@ export class ProjectDirectory { this.path = absoluteNewDirPath; } + assertExists() { + this._checkPathExists(); + this._checkPathIsDir(); + this._checkPathIsReadable(); + } + private _checkPathIsInsideProject(path: string = this.path) { if (!path.startsWith(this.projectPath)) { throw new FileSystemError(`Path ${path} is outside of the project directory`); diff --git a/src/lib/server/loader/env.ts b/src/lib/server/loader/env.ts index ccaa1be..842a774 100644 --- a/src/lib/server/loader/env.ts +++ b/src/lib/server/loader/env.ts @@ -1,7 +1,7 @@ import { config } from 'dotenv'; import { join } from 'path'; -import type { Part } from './types'; +import type { Part } from '@utils/types'; const PREFIX_CLIENT = 'NANOFORGE_CLIENT_'; const PREFIX_SERVER = 'NANOFORGE_SERVER_'; diff --git a/src/lib/server/loader/loader.ts b/src/lib/server/loader/loader.ts index 28eae35..b688911 100644 --- a/src/lib/server/loader/loader.ts +++ b/src/lib/server/loader/loader.ts @@ -4,11 +4,13 @@ import { join } from 'path'; import { FileSystem } from '$lib/server/file-system'; import { directoryContentToFileEntries } from '$lib/server/file-system/project-directory'; +import type { Part } from '@utils/types'; + import { Exception } from '@utils-server/exception'; import type { Context } from '@utils-server/request-handler'; import { resolveEnv } from './env'; -import type { Manifest, Part } from './types'; +import type { Manifest } from './types'; export class Loader { private readonly _projectPath: string; diff --git a/src/lib/server/loader/types.ts b/src/lib/server/loader/types.ts index 92c242a..7973dea 100644 --- a/src/lib/server/loader/types.ts +++ b/src/lib/server/loader/types.ts @@ -1,5 +1,3 @@ -export type Part = 'client' | 'server'; - export interface Manifest { version: string; files: { path: string }[]; diff --git a/src/lib/server/project/index.ts b/src/lib/server/project/index.ts index 207836d..1df00d0 100644 --- a/src/lib/server/project/index.ts +++ b/src/lib/server/project/index.ts @@ -1,2 +1,4 @@ export { loadProject } from './load-project'; export type { Project } from './project.type'; +export { ProjectHandler } from './project-handler'; +export { ProjectManager } from './project-manager'; diff --git a/src/lib/server/project/project-handler.ts b/src/lib/server/project/project-handler.ts new file mode 100644 index 0000000..2dda6e9 --- /dev/null +++ b/src/lib/server/project/project-handler.ts @@ -0,0 +1,32 @@ +import { Cli } from '$lib/server/cli'; +import { FileSystem } from '$lib/server/file-system'; + +import type { Part } from '@utils/types'; + +import type { Context } from '@utils-server/request-handler'; + +import { SaveHandler } from './save/save-handler'; + +export class ProjectHandler { + public readonly _part: Part; + public readonly _cli: Cli; + public readonly _fs: FileSystem; + + private readonly _save: SaveHandler; + + constructor(context: Context, part: Part) { + this._part = part; + this._cli = new Cli(context); + this._fs = new FileSystem(context); + + this._fs.getDirectory(this._part).assertExists(); + + this._save = new SaveHandler(this); + } + + get save(): SaveHandler { + return this._save; + } + + // get components(): ComponentHandler; +} diff --git a/src/lib/server/project/project-manager.ts b/src/lib/server/project/project-manager.ts new file mode 100644 index 0000000..dcf6f68 --- /dev/null +++ b/src/lib/server/project/project-manager.ts @@ -0,0 +1,24 @@ +import { ProjectHandler } from '$lib/server/project/project-handler'; + +import type { Context } from '@utils-server/request-handler'; + +export class ProjectManager { + private readonly _context: Context; + + private _client: ProjectHandler | undefined; + private _server: ProjectHandler | undefined; + + constructor(context: Context) { + this._context = context; + } + + get client(): ProjectHandler { + if (!this._client) this._client = new ProjectHandler(this._context, 'client'); + return this._client; + } + + get server(): ProjectHandler { + if (!this._server) this._server = new ProjectHandler(this._context, 'server'); + return this._server; + } +} diff --git a/src/lib/server/project/save/save-handler.ts b/src/lib/server/project/save/save-handler.ts new file mode 100644 index 0000000..42ad5cc --- /dev/null +++ b/src/lib/server/project/save/save-handler.ts @@ -0,0 +1,23 @@ +import { type ProjectHandler } from '$lib/server/project'; + +import type { Save } from '@utils/types'; + +export class SaveHandler { + private readonly handler: ProjectHandler; + + constructor(handler: ProjectHandler) { + this.handler = handler; + } + + async getSave(): Promise { + return this.handler._fs.getFile(this.resolveSavePath()).readJson(); + } + + async updateSave(save: Save): Promise { + this.handler._fs.getFile(this.resolveSavePath()).writeJson(save); + } + + private resolveSavePath(): string { + return `.nanoforge/${this.handler._part}.save.json`; + } +} diff --git a/src/lib/server/utils/request-handler/handler.ts b/src/lib/server/utils/request-handler/handler.ts index 048e1cb..9854a85 100644 --- a/src/lib/server/utils/request-handler/handler.ts +++ b/src/lib/server/utils/request-handler/handler.ts @@ -5,6 +5,7 @@ import { Cli } from '$lib/server/cli'; import { FileSystem } from '$lib/server/file-system'; import { Git } from '$lib/server/git'; import { Loader } from '$lib/server/loader'; +import { ProjectManager } from '$lib/server/project'; import type { Context } from '@utils-server/request-handler/context'; @@ -18,6 +19,7 @@ export class Handler { private _fsCache: FileSystem | undefined; private _loaderCache: Loader | undefined; private _gitCache: Git | undefined; + private _projectCache: ProjectManager | undefined; constructor(context: Context, event: RequestEvent, body: Body) { this._context = context; @@ -71,4 +73,9 @@ export class Handler { if (!this._gitCache) this._gitCache = new Git(); return this._gitCache; } + + get project(): ProjectManager { + if (!this._projectCache) this._projectCache = new ProjectManager(this._context); + return this._projectCache; + } } diff --git a/src/lib/utils/types/index.ts b/src/lib/utils/types/index.ts index 160846b..0db0202 100644 --- a/src/lib/utils/types/index.ts +++ b/src/lib/utils/types/index.ts @@ -1,2 +1,5 @@ +export * from './base.type'; export * from './class.type'; +export * from './part.type'; export * from './promise.type'; +export * from './save.type'; diff --git a/src/lib/utils/types/part.type.ts b/src/lib/utils/types/part.type.ts new file mode 100644 index 0000000..b51b16c --- /dev/null +++ b/src/lib/utils/types/part.type.ts @@ -0,0 +1 @@ +export type Part = 'client' | 'server'; diff --git a/src/lib/utils/types/save.type.ts b/src/lib/utils/types/save.type.ts new file mode 100644 index 0000000..efadb04 --- /dev/null +++ b/src/lib/utils/types/save.type.ts @@ -0,0 +1,38 @@ +export enum SaveLibraryTypeEnum { + COMPONENT_SYSTEM = 'component-system', + GRAPHICS = 'graphics', + ASSET_MANAGER = 'asset-manager', + NETWORK = 'network', + INPUT = 'input', + SOUND = 'sound', +} + +export interface SaveLibrary { + id: string; + type: SaveLibraryTypeEnum | string; + name: string; + path: string; +} + +export interface SaveComponent { + name: string; + path: string; + paramsNames: string[]; +} + +export interface SaveSystem { + name: string; + path: string; +} + +export interface SaveEntity { + id: string; + components: Record>; +} + +export interface Save { + libraries: SaveLibrary[]; + components: SaveComponent[]; + systems: SaveSystem[]; + entities: SaveEntity[]; +} From 29e4c708d777291114a21a9f278278240091b024 Mon Sep 17 00:00:00 2001 From: Exelo Date: Wed, 6 May 2026 18:08:56 +0900 Subject: [PATCH 07/58] chore: add manifest resolver --- .../project/package/manifest-resolver.ts | 63 +++++++++++++++++++ src/routes/game-loader/+page.server.ts | 5 +- 2 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 src/lib/server/project/package/manifest-resolver.ts diff --git a/src/lib/server/project/package/manifest-resolver.ts b/src/lib/server/project/package/manifest-resolver.ts new file mode 100644 index 0000000..d411f50 --- /dev/null +++ b/src/lib/server/project/package/manifest-resolver.ts @@ -0,0 +1,63 @@ +import ts, { type Expression, type ObjectLiteralElementLike } from 'typescript'; + +const findManifestNode = (title: string, source: ts.SourceFile): ts.VariableDeclaration | null => { + let res = null; + source.forEachChild((node) => { + if (!ts.isVariableStatement(node)) return; + node.declarationList.declarations.forEach((decl) => { + if (!ts.isVariableDeclaration(decl)) return; + if (decl.name.getText() === title) res = decl; + }); + }); + return res; +}; + +const parseProperty = (prop: ObjectLiteralElementLike): any => { + if (!ts.isPropertyAssignment(prop)) return {}; + + const name = prop.name.getText(); + const value = prop.initializer; + if (!value) return {}; + + return { [name]: parseElement(value) }; +}; + +const parseElement = (value: Expression): any => { + if (ts.isStringLiteral(value)) return value.text; + if (ts.isNumericLiteral(value)) return Number(value.text); + if (ts.isLiteralTypeLiteral(value)) { + const txt = value.getText(); + if (txt === 'true') return true; + if (txt === 'false') return false; + if (txt === 'null') return null; + if (txt === 'undefined') return undefined; + } + if (ts.isArrayLiteralExpression(value)) return value.elements.map((el) => parseElement(el)); + if (ts.isObjectLiteralExpression(value)) + return value.properties.reduce((acc, prop) => { + return { ...acc, ...parseProperty(prop) }; + }, {}); + throw new Error('Unknown element type'); +}; + +const getManifestFromNode = (source: ts.VariableDeclaration | null): any | null => { + if (!source) return null; + + const init = source.initializer; + if (!init) return null; + if (!ts.isObjectLiteralExpression(init)) return null; + + return parseElement(init); +}; + +const parseManifest = (title: string, source: ts.SourceFile): any | null => { + return getManifestFromNode(findManifestNode(title, source)); +}; + +export const resolveManifest = (type: 'component' | 'system', content: string): any | null => { + const source = ts.createSourceFile('tmp.ts', content, ts.ScriptTarget.ESNext, true); + return parseManifest( + type === 'component' ? 'EDITOR_COMPONENT_MANIFEST' : 'EDITOR_SYSTEM_MANIFEST', + source, + ); +}; diff --git a/src/routes/game-loader/+page.server.ts b/src/routes/game-loader/+page.server.ts index ec18e82..1c4b904 100644 --- a/src/routes/game-loader/+page.server.ts +++ b/src/routes/game-loader/+page.server.ts @@ -8,6 +8,7 @@ import { directoryContentToFileEntries, } from '$lib/server/file-system/project-directory'; import { ProjectFile } from '$lib/server/file-system/project-file'; +import { resolveManifest } from '$lib/server/project/package/manifest-resolver'; import type { Actions } from './$types'; @@ -109,10 +110,10 @@ export const actions = { locals.session.data.path, ); projectComponentFile.isReadable(); - const componentModule = await import(/* @vite-ignore */ projectComponentFile.path); + const manifest = resolveManifest('component', projectComponentFile.read('utf-8')); return { success: true, - manifest: componentModule['EDITOR_COMPONENT_MANIFEST'], + manifest, }; } catch (e: unknown) { if (e instanceof FileSystemError) { From 29aeb319fa7135597a59ef8b15415db98e200d5e Mon Sep 17 00:00:00 2001 From: Exelo Date: Wed, 6 May 2026 21:59:36 +0900 Subject: [PATCH 08/58] chore: add package handler and session creation on load --- .../server/actions/project/load.actions.ts | 7 +- .../file-system/file-system.functions.ts | 6 +- src/lib/server/git/git.ts | 10 +- src/lib/server/loader/env.ts | 4 +- src/lib/server/project/load-project.ts | 16 ++- .../project/package/manifest-resolver.ts | 14 ++- .../server/project/package/package-handler.ts | 98 +++++++++++++++++++ .../server/project/package/package.type.ts | 4 + src/lib/server/project/project-handler.ts | 9 +- src/lib/server/session/index.ts | 2 +- src/lib/server/session/session-functions.ts | 13 +++ .../utils/request-handler/request.policy.ts | 4 +- src/lib/utils/format.ts | 30 ++++++ src/routes/load-project/+page.server.ts | 2 +- 14 files changed, 189 insertions(+), 30 deletions(-) create mode 100644 src/lib/server/project/package/package-handler.ts create mode 100644 src/lib/server/project/package/package.type.ts create mode 100644 src/lib/utils/format.ts diff --git a/src/lib/server/actions/project/load.actions.ts b/src/lib/server/actions/project/load.actions.ts index 0fce522..4506344 100644 --- a/src/lib/server/actions/project/load.actions.ts +++ b/src/lib/server/actions/project/load.actions.ts @@ -20,10 +20,9 @@ const resolveSessionFromGatewayId = async ( throw new Exception('Bad Request', 'Cannot load project from gatewayId while offline', 400); const project = await api.projects.getProject(gatewayId); - const basePath = await git.clone( - project.gatewayProjectRegistryUrl, - project.gatewayProjectRegistryMetadata.sshKey, - ); + const basePath = await git.clone(project.gatewayProjectRegistryUrl, { + sshKey: project.gatewayProjectRegistryMetadata.sshKey, + }); return { path: join(basePath, project.gatewayProjectRegistryMetadata.dir ?? ''), gateway: { id: gatewayId, sshKey: project.gatewayProjectRegistryMetadata.sshKey }, diff --git a/src/lib/server/file-system/file-system.functions.ts b/src/lib/server/file-system/file-system.functions.ts index f7c4e60..1872317 100644 --- a/src/lib/server/file-system/file-system.functions.ts +++ b/src/lib/server/file-system/file-system.functions.ts @@ -1,9 +1,9 @@ -import { join } from 'path'; +import { resolve } from 'path'; import { env } from '$env/dynamic/private'; export const resolveRootPath = (userPath: string) => { - const rootPath = join(process.cwd(), env.FS_ROOT ?? ''); + const rootPath = resolve(env.FS_ROOT ?? ''); - return join(rootPath, userPath); + return resolve(rootPath, userPath); }; diff --git a/src/lib/server/git/git.ts b/src/lib/server/git/git.ts index 46ee2de..94d4e2c 100644 --- a/src/lib/server/git/git.ts +++ b/src/lib/server/git/git.ts @@ -1,5 +1,5 @@ import { $ } from 'bun'; -import { join } from 'path'; +import { resolve } from 'path'; import { env } from '$env/dynamic/private'; @@ -9,7 +9,7 @@ export class Git { private readonly _rootPath: string; constructor() { - this._rootPath = join(process.cwd(), env.GIT_ROOT ?? ''); + this._rootPath = resolve(env.GIT_ROOT ?? ''); } async clone(url: string, options?: { sshKey?: string }): Promise { @@ -28,7 +28,7 @@ export class Git { sshPath = await this.createSshKeyFile(options.sshKey); } const sshConfig = sshPath ? `-c core.sshCommand="ssh -i ${sshPath}" ` : ''; - const cwd = join(this._rootPath, options?.path ?? ''); + const cwd = resolve(this._rootPath, options?.path ?? ''); await $`git ${command} ${sshConfig}${params}`.cwd(cwd); if (sshPath) await this.deleteSshKeyFile(sshPath); @@ -48,10 +48,10 @@ export class Git { const basePath = url.split('/').pop()?.replace('.git', ''); if (!basePath) throw new Error('Invalid URL'); - const fullBasePath = join(this._rootPath, basePath); + const fullBasePath = resolve(this._rootPath, basePath); let path = fullBasePath; - while (await Bun.file(path).exists()) path = join(fullBasePath, generateKey(5)); + while (await Bun.file(path).exists()) path = resolve(fullBasePath, generateKey(5)); return path; } } diff --git a/src/lib/server/loader/env.ts b/src/lib/server/loader/env.ts index 842a774..9ac1a1a 100644 --- a/src/lib/server/loader/env.ts +++ b/src/lib/server/loader/env.ts @@ -1,5 +1,5 @@ import { config } from 'dotenv'; -import { join } from 'path'; +import { resolve } from 'path'; import type { Part } from '@utils/types'; @@ -30,5 +30,5 @@ const parseEnv = (part: Part, env: Record): Record { - return parseEnv(part, loadEnv(join(projectPath, '.env'))); + return parseEnv(part, loadEnv(resolve(projectPath, '.env'))); }; diff --git a/src/lib/server/project/load-project.ts b/src/lib/server/project/load-project.ts index bc0208a..a3855cd 100644 --- a/src/lib/server/project/load-project.ts +++ b/src/lib/server/project/load-project.ts @@ -1,6 +1,7 @@ import { type SessionProject, addProjectToSession, + getOrCreateSession, tryAddProjectSession, } from '$lib/server/session'; @@ -8,12 +9,17 @@ import { type Handler } from '@utils-server/request-handler'; import type { Project } from './project.type'; -export const loadProject = async (session: SessionProject, handler: Handler): Promise => { - // @todo add getOrCreateSession(handler.event.locals.session) and remove id from session - const projectId = tryAddProjectSession(session); - addProjectToSession(handler.context.session, projectId); +export const loadProject = async ( + projectSession: SessionProject, + handler: Handler, +): Promise => { + // @todo remake this route and session system as it's set before the project is loaded - handler.context = { ...handler.context, project: session }; + const session = await getOrCreateSession(handler.event.locals.session); + const projectId = tryAddProjectSession(projectSession); + addProjectToSession(session, projectId); + + handler.context = { ...handler.context, project: projectSession }; const { fs } = handler; diff --git a/src/lib/server/project/package/manifest-resolver.ts b/src/lib/server/project/package/manifest-resolver.ts index d411f50..74f666e 100644 --- a/src/lib/server/project/package/manifest-resolver.ts +++ b/src/lib/server/project/package/manifest-resolver.ts @@ -1,5 +1,12 @@ import ts, { type Expression, type ObjectLiteralElementLike } from 'typescript'; +import { PackageTypeEnum } from './package.type'; + +export const MANIFEST_TITLES = { + [PackageTypeEnum.COMPONENT]: 'EDITOR_COMPONENT_MANIFEST', + [PackageTypeEnum.SYSTEM]: 'EDITOR_SYSTEM_MANIFEST', +} as const; + const findManifestNode = (title: string, source: ts.SourceFile): ts.VariableDeclaration | null => { let res = null; source.forEachChild((node) => { @@ -54,10 +61,7 @@ const parseManifest = (title: string, source: ts.SourceFile): any | null => { return getManifestFromNode(findManifestNode(title, source)); }; -export const resolveManifest = (type: 'component' | 'system', content: string): any | null => { +export const resolveManifest = (type: PackageTypeEnum, content: string): any | null => { const source = ts.createSourceFile('tmp.ts', content, ts.ScriptTarget.ESNext, true); - return parseManifest( - type === 'component' ? 'EDITOR_COMPONENT_MANIFEST' : 'EDITOR_SYSTEM_MANIFEST', - source, - ); + return parseManifest(MANIFEST_TITLES[type], source); }; diff --git a/src/lib/server/project/package/package-handler.ts b/src/lib/server/project/package/package-handler.ts new file mode 100644 index 0000000..bfec094 --- /dev/null +++ b/src/lib/server/project/package/package-handler.ts @@ -0,0 +1,98 @@ +import { join } from 'path'; + +import { type ProjectHandler } from '$lib/server/project'; + +import { toCamelCase, toKebabCase, toPascalCase } from '@utils/format'; + +import { resolveManifest } from './manifest-resolver'; +import { PackageTypeEnum } from './package.type'; + +export class PackageHandler { + private readonly handler: ProjectHandler; + + constructor(handler: ProjectHandler) { + this.handler = handler; + } + + /** + * Create a new component in the project and update the save file + * @beta function to be reworked + * + * @param {string} name - Name of the component + * @param {string} [path=./components] - Path from `/` + */ + async createComponent(name: string, path: string = './components'): Promise { + const fullPath = this._createPackage(PackageTypeEnum.COMPONENT, name, path); + const save = await this.handler.save.getSave(); + save.components = [ + ...save.components, + { + name: toPascalCase(name), + path: join(fullPath, toKebabCase(name)), + // Default params of the default component + paramsNames: ['paramA', 'paramB', 'paramC'], + }, + ]; + await this.handler.save.updateSave(save); + } + + /** + * Create a new system in the project and update the save file + * @beta function to be reworked + * + * @param {string} name - Name of the system + * @param {string} [path=./systems] - Path from `/` + */ + async createSystem(name: string, path: string = './systems'): Promise { + const fullPath = this._createPackage(PackageTypeEnum.SYSTEM, name, path); + const save = await this.handler.save.getSave(); + save.systems = [ + ...save.systems, + { name: toCamelCase(name), path: join(fullPath, toKebabCase(name)) }, + ]; + await this.handler.save.updateSave(save); + } + + /** + * Get the manifest of the component + * @beta function to be reworked + * + * @param {string} path - Path from `/` + * + * @returns Manifest of the component + */ + getComponentManifest(path: string): any { + return this._getPackageManifest(PackageTypeEnum.COMPONENT, path); + } + + /** + * Get the manifest of the system + * @beta function to be reworked + * + * @param {string} path - Path from `/` + * + * @returns Manifest of the system + */ + getSystemManifest(path: string): any { + return this._getPackageManifest(PackageTypeEnum.SYSTEM, path); + } + + private _createPackage(type: PackageTypeEnum, name: string, path: string): string { + const fullPath = this._resolvePartPath(path); + this.handler._cli.create(type, { + name, + path: fullPath, + server: this.handler._part === 'server' ? true : undefined, + }); + return fullPath; + } + + private _getPackageManifest(type: PackageTypeEnum, path: string): any { + const content = this.handler._fs.getFile(this._resolvePartPath(path)).read(); + return resolveManifest(type, content); + } + + private _resolvePartPath(path: string): string { + return join(this.handler._part, path); + } +} diff --git a/src/lib/server/project/package/package.type.ts b/src/lib/server/project/package/package.type.ts new file mode 100644 index 0000000..901436b --- /dev/null +++ b/src/lib/server/project/package/package.type.ts @@ -0,0 +1,4 @@ +export enum PackageTypeEnum { + COMPONENT = 'component', + SYSTEM = 'system', +} diff --git a/src/lib/server/project/project-handler.ts b/src/lib/server/project/project-handler.ts index 2dda6e9..a5d722e 100644 --- a/src/lib/server/project/project-handler.ts +++ b/src/lib/server/project/project-handler.ts @@ -5,6 +5,7 @@ import type { Part } from '@utils/types'; import type { Context } from '@utils-server/request-handler'; +import { PackageHandler } from './package/package-handler'; import { SaveHandler } from './save/save-handler'; export class ProjectHandler { @@ -13,6 +14,7 @@ export class ProjectHandler { public readonly _fs: FileSystem; private readonly _save: SaveHandler; + private readonly _package: PackageHandler; constructor(context: Context, part: Part) { this._part = part; @@ -22,11 +24,14 @@ export class ProjectHandler { this._fs.getDirectory(this._part).assertExists(); this._save = new SaveHandler(this); + this._package = new PackageHandler(this); + } + + get package(): PackageHandler { + return this._package; } get save(): SaveHandler { return this._save; } - - // get components(): ComponentHandler; } diff --git a/src/lib/server/session/index.ts b/src/lib/server/session/index.ts index df2eb97..6be6a3a 100644 --- a/src/lib/server/session/index.ts +++ b/src/lib/server/session/index.ts @@ -1,5 +1,5 @@ export * from './session-handle'; -export { resolveSession, addProjectToSession } from './session-functions'; +export { resolveSession, addProjectToSession, getOrCreateSession } from './session-functions'; export type { Session } from './session.type'; export { resolveProject, tryAddProjectSession } from './project/project-functions'; export type { SessionProject } from './project/project.type'; diff --git a/src/lib/server/session/session-functions.ts b/src/lib/server/session/session-functions.ts index ac75d60..8785b84 100644 --- a/src/lib/server/session/session-functions.ts +++ b/src/lib/server/session/session-functions.ts @@ -1,5 +1,7 @@ import { type Session as SvelteSession } from 'svelte-kit-sessions'; +import { generateKey } from '@utils/string'; + import { Exception } from '@utils-server/exception'; import { PUBLIC_PATHS } from './session.const'; @@ -36,3 +38,14 @@ export const addProjectToSession = (session: Session, projectId: string): void = projects: [...session.projects, projectId], }); }; + +export const getOrCreateSession = async (sessionHandler: SvelteSession): Promise => { + const session = await resolveSession(sessionHandler); + if (session) return session; + + const id = generateKey(10); + sessionStore.set(id, { id, projects: [] }); + await sessionHandler.setData({ id, path: '' }); + await sessionHandler.save(); + return sessionStore.get(id) as Session; +}; diff --git a/src/lib/server/utils/request-handler/request.policy.ts b/src/lib/server/utils/request-handler/request.policy.ts index f72eac5..9961d24 100644 --- a/src/lib/server/utils/request-handler/request.policy.ts +++ b/src/lib/server/utils/request-handler/request.policy.ts @@ -1,6 +1,6 @@ import { Exception } from '../exception'; import type { Context } from './context'; -import type { RequestHandlerOptions } from './request-handler'; +import type { RequestHandlerOptions } from './types'; const DEFAULT_OPTIONS: RequestHandlerOptions = { onlineOnly: false, @@ -9,7 +9,7 @@ const DEFAULT_OPTIONS: RequestHandlerOptions = { }; const assertProject = (context: Context, options: RequestHandlerOptions): void | never => { - if (!options.projectOptional) return; + if (options.projectOptional) return; if (!context.session) throw new Exception('Bad Request', 'No session', 400); if (!context.project) throw new Exception('Bad Request', 'Request required a project', 400); diff --git a/src/lib/utils/format.ts b/src/lib/utils/format.ts new file mode 100644 index 0000000..ebdfcd9 --- /dev/null +++ b/src/lib/utils/format.ts @@ -0,0 +1,30 @@ +const toWords = (str: string): string[] => { + return str + .replace(/([a-z])([A-Z])/g, '$1 $2') + .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2') + .replace(/[-_]+/g, ' ') + .trim() + .split(/\s+/) + .filter(Boolean); +}; + +export const toKebabCase = (str: string): string => { + return toWords(str) + .map((word) => word.toLowerCase()) + .join('-'); +}; + +export const toPascalCase = (str: string): string => { + return toWords(str) + .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join(''); +}; + +export const toCamelCase = (str: string): string => { + const words = toWords(str); + return words + .map((word, i) => + i === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(), + ) + .join(''); +}; diff --git a/src/routes/load-project/+page.server.ts b/src/routes/load-project/+page.server.ts index 4de722e..7a8d2a8 100644 --- a/src/routes/load-project/+page.server.ts +++ b/src/routes/load-project/+page.server.ts @@ -71,7 +71,7 @@ export const actions = { const session = locals.session; - await session.setData({ path: absoluteProjectPath }); + await session.setData({ path: absoluteProjectPath, id: '' }); await session.save(); return { From b3bf1694e6ead08fb457e0bb2bf0421e68ce8f7e Mon Sep 17 00:00:00 2001 From: Exelo Date: Thu, 7 May 2026 12:42:41 +0900 Subject: [PATCH 09/58] fix: review issues --- src/lib/components/Utils/api/local-api.ts | 3 +- .../Widget/EditorGame/game.svelte.ts | 3 +- .../EntityInspector/component-creator.ts | 3 +- src/lib/loader/client/types/game.type.ts | 3 +- src/lib/loader/client/types/save.type.ts | 38 ------------------- src/lib/server/api/base.repository.ts | 4 +- src/lib/server/cli/cli.ts | 2 +- src/lib/server/file-system/project-file.ts | 36 +++++++++++------- src/lib/server/loader/env.ts | 12 +++--- src/lib/utils/format.ts | 3 ++ src/lib/utils/string.ts | 3 -- src/routes/game-loader/+page.server.ts | 3 +- 12 files changed, 44 insertions(+), 69 deletions(-) delete mode 100644 src/lib/loader/client/types/save.type.ts diff --git a/src/lib/components/Utils/api/local-api.ts b/src/lib/components/Utils/api/local-api.ts index c856ecd..dc75034 100644 --- a/src/lib/components/Utils/api/local-api.ts +++ b/src/lib/components/Utils/api/local-api.ts @@ -5,7 +5,8 @@ import { deserialize } from '$app/forms'; import { type DirectoryRec, ProjectApi } from '$lib/components/Utils/api/project-api'; import { env, save } from '$lib/components/Widget/EditorGame/game.svelte'; import type { IManifest } from '$lib/loader/client/types/manifest.type'; -import type { Save } from '$lib/loader/client/types/save.type'; + +import type { Save } from '@utils/types'; import { FileSystemDirectory } from '@utils-client/file-system'; import { projectFileSystem } from '@utils-client/local-file-system/project-file-system'; diff --git a/src/lib/components/Widget/EditorGame/game.svelte.ts b/src/lib/components/Widget/EditorGame/game.svelte.ts index d690ff5..557ff1e 100644 --- a/src/lib/components/Widget/EditorGame/game.svelte.ts +++ b/src/lib/components/Widget/EditorGame/game.svelte.ts @@ -3,7 +3,8 @@ import { SvelteMap } from 'svelte/reactivity'; import { type Writable, get, writable } from 'svelte/store'; import { localApi } from '$lib/components/Utils/api/api'; -import type { Save } from '$lib/loader/client/types/save.type'; + +import type { Save } from '@utils/types'; export const mainModule: Writable = writable(undefined); export const env: Writable> = writable({}); diff --git a/src/lib/components/Widget/EntityInspector/component-creator.ts b/src/lib/components/Widget/EntityInspector/component-creator.ts index 92e0f66..6d2d2b8 100644 --- a/src/lib/components/Widget/EntityInspector/component-creator.ts +++ b/src/lib/components/Widget/EntityInspector/component-creator.ts @@ -3,7 +3,8 @@ import { get } from 'svelte/store'; import { localApi } from '$lib/components/Utils/api/api'; import { save } from '$lib/components/Widget/EditorGame/game.svelte'; -import type { SaveComponent } from '$lib/loader/client/types/save.type'; + +import type { SaveComponent } from '@utils/types'; export async function createDefaultComponent( componentName: string, diff --git a/src/lib/loader/client/types/game.type.ts b/src/lib/loader/client/types/game.type.ts index 05ca448..703f27d 100644 --- a/src/lib/loader/client/types/game.type.ts +++ b/src/lib/loader/client/types/game.type.ts @@ -1,5 +1,6 @@ +import type { Save } from '@utils/types'; + import type { IEventEmitter } from './event-emitter.type'; -import type { Save } from './save.type'; export interface IGameOptions { canvas: HTMLCanvasElement; diff --git a/src/lib/loader/client/types/save.type.ts b/src/lib/loader/client/types/save.type.ts deleted file mode 100644 index efadb04..0000000 --- a/src/lib/loader/client/types/save.type.ts +++ /dev/null @@ -1,38 +0,0 @@ -export enum SaveLibraryTypeEnum { - COMPONENT_SYSTEM = 'component-system', - GRAPHICS = 'graphics', - ASSET_MANAGER = 'asset-manager', - NETWORK = 'network', - INPUT = 'input', - SOUND = 'sound', -} - -export interface SaveLibrary { - id: string; - type: SaveLibraryTypeEnum | string; - name: string; - path: string; -} - -export interface SaveComponent { - name: string; - path: string; - paramsNames: string[]; -} - -export interface SaveSystem { - name: string; - path: string; -} - -export interface SaveEntity { - id: string; - components: Record>; -} - -export interface Save { - libraries: SaveLibrary[]; - components: SaveComponent[]; - systems: SaveSystem[]; - entities: SaveEntity[]; -} diff --git a/src/lib/server/api/base.repository.ts b/src/lib/server/api/base.repository.ts index 33d6728..fba394b 100644 --- a/src/lib/server/api/base.repository.ts +++ b/src/lib/server/api/base.repository.ts @@ -44,7 +44,7 @@ export class BaseRepository { path: string, options?: RequestOptions, ): Promise { - return (await this._client[request](`/api${path}`, options)).content as R; + return (await this._client[request](path, options)).content as R; } private async runRequestBody( @@ -55,7 +55,7 @@ export class BaseRepository { ): Promise { return ( await this._client[request]( - `/api${path}`, + path, body === undefined ? undefined : JSON.stringify(body), options, ) diff --git a/src/lib/server/cli/cli.ts b/src/lib/server/cli/cli.ts index 803a715..73a8b54 100644 --- a/src/lib/server/cli/cli.ts +++ b/src/lib/server/cli/cli.ts @@ -1,6 +1,6 @@ import { env } from '$env/dynamic/private'; -import { camelToKebab } from '@utils/string'; +import { camelToKebab } from '@utils/format'; import type { Context } from '@utils-server/request-handler'; diff --git a/src/lib/server/file-system/project-file.ts b/src/lib/server/file-system/project-file.ts index 694790b..46d9659 100644 --- a/src/lib/server/file-system/project-file.ts +++ b/src/lib/server/file-system/project-file.ts @@ -35,19 +35,7 @@ export class ProjectFile { } write(text: string): void { - const folderPath = path.dirname(this._path); - try { - this._checkPathExists(); - this._checkPathIsFile(); - this._checkPathIsWritable(); - } catch { - fs.mkdirSync(folderPath, { recursive: true }); - fs.writeFileSync(this._path, text, { flush: true }); - return; - } - this._checkPathExists(folderPath); - this._checkPathIsDir(folderPath); - this._checkPathIsWritable(folderPath); + this._checkWritableAndCreateFolder(); fs.writeFileSync(this._path, text, { flush: true }); } @@ -56,6 +44,11 @@ export class ProjectFile { this.write(raw); } + getWriteStream(): fs.WriteStream { + this._checkWritableAndCreateFolder(); + return fs.createWriteStream(this._path); + } + delete(): void { this._checkPathExists(); this._checkPathIsFile(); @@ -83,6 +76,23 @@ export class ProjectFile { this._checkPathIsReadable(); } + private _checkWritableAndCreateFolder(): void { + const folderPath = path.dirname(this._path); + try { + this._checkPathExists(folderPath); + } catch { + fs.mkdirSync(folderPath, { recursive: true }); + } + if (fs.existsSync(this._path)) { + this._checkPathIsFile(); + this._checkPathIsWritable(); + } else { + this._checkPathExists(folderPath); + this._checkPathIsDir(folderPath); + this._checkPathIsWritable(folderPath); + } + } + private _checkPathIsInsideProject(path: string = this._path) { if (!path.startsWith(this.projectPath)) { throw new FileSystemError(`Path ${path} is outside of the project directory`); diff --git a/src/lib/server/loader/env.ts b/src/lib/server/loader/env.ts index 9ac1a1a..c4834d0 100644 --- a/src/lib/server/loader/env.ts +++ b/src/lib/server/loader/env.ts @@ -14,18 +14,16 @@ const loadEnv = (path: string): Record => { }; const parseEnv = (part: Part, env: Record): Record => { + const partPrefix = part === 'client' ? PREFIX_CLIENT : PREFIX_SERVER; return Object.fromEntries( Object.entries(env) .filter( ([key]) => - key.startsWith(PREFIX) || - (part === 'client' && key.startsWith(PREFIX_CLIENT)) || - (part === 'server' && key.startsWith(PREFIX_SERVER)), + key.startsWith(PREFIX) && + ((part === 'client' && !key.startsWith(PREFIX_SERVER)) || + (part === 'server' && !key.startsWith(PREFIX_CLIENT))), ) - .map(([key, value]) => [ - key.replace(part === 'client' ? PREFIX_CLIENT : PREFIX_SERVER, '').replace(PREFIX, ''), - value, - ]), + .map(([key, value]) => [key.replace(new RegExp(`^${partPrefix}|${PREFIX}`), ''), value]), ); }; diff --git a/src/lib/utils/format.ts b/src/lib/utils/format.ts index ebdfcd9..de3e61e 100644 --- a/src/lib/utils/format.ts +++ b/src/lib/utils/format.ts @@ -28,3 +28,6 @@ export const toCamelCase = (str: string): string => { ) .join(''); }; + +export const camelToKebab = (str: string) => + str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`); diff --git a/src/lib/utils/string.ts b/src/lib/utils/string.ts index b72b698..08c33af 100644 --- a/src/lib/utils/string.ts +++ b/src/lib/utils/string.ts @@ -4,6 +4,3 @@ export const generateKey = (size = 50) => { const buffer = crypto.randomBytes(size); return buffer.toString('base64url').substring(0, size); }; - -export const camelToKebab = (str: string) => - str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`); diff --git a/src/routes/game-loader/+page.server.ts b/src/routes/game-loader/+page.server.ts index 1c4b904..f4ef434 100644 --- a/src/routes/game-loader/+page.server.ts +++ b/src/routes/game-loader/+page.server.ts @@ -1,6 +1,5 @@ import { fail } from '@sveltejs/kit'; -import type { Save } from '$lib/loader/client/types/save.type'; import { getGameEnv } from '$lib/loader/server/env'; import { FileSystemError } from '$lib/server/file-system/file-system-error'; import { @@ -10,6 +9,8 @@ import { import { ProjectFile } from '$lib/server/file-system/project-file'; import { resolveManifest } from '$lib/server/project/package/manifest-resolver'; +import type { Save } from '@utils/types'; + import type { Actions } from './$types'; export const actions = { From ee0f6a650848b04d533cf68513496ebdcf09fce5 Mon Sep 17 00:00:00 2001 From: Exelo Date: Tue, 12 May 2026 12:51:00 +0900 Subject: [PATCH 10/58] fix: change actions to form data and remove the old content property to json() --- src/lib/server/api/base.repository.ts | 4 +- src/lib/server/utils/request-handler/body.ts | 5 ++- .../utils/request-handler/request-handler.ts | 2 +- src/lib/utils/http/client.ts | 44 +++++++++++-------- 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/lib/server/api/base.repository.ts b/src/lib/server/api/base.repository.ts index fba394b..07a452c 100644 --- a/src/lib/server/api/base.repository.ts +++ b/src/lib/server/api/base.repository.ts @@ -44,7 +44,7 @@ export class BaseRepository { path: string, options?: RequestOptions, ): Promise { - return (await this._client[request](path, options)).content as R; + return (await this._client[request](path, options)).json() as Promise; } private async runRequestBody( @@ -59,6 +59,6 @@ export class BaseRepository { body === undefined ? undefined : JSON.stringify(body), options, ) - ).content as R; + ).json() as Promise; } } diff --git a/src/lib/server/utils/request-handler/body.ts b/src/lib/server/utils/request-handler/body.ts index bccee97..7b88ee7 100644 --- a/src/lib/server/utils/request-handler/body.ts +++ b/src/lib/server/utils/request-handler/body.ts @@ -1,6 +1,9 @@ import type { ClassType } from '@utils/types'; -export const parseBody = (baseBody: any, c: ClassType | undefined): Body => { +export const parseBody = (rawBody: FormData, c: ClassType | undefined): Body => { + const baseBody = Object.fromEntries( + Array.from(rawBody.entries()).map(([key, value]) => [key, JSON.parse(value)]), + ); // @todo add class validation and class transformation void c; return baseBody as Body; diff --git a/src/lib/server/utils/request-handler/request-handler.ts b/src/lib/server/utils/request-handler/request-handler.ts index 090de89..f3a92ac 100644 --- a/src/lib/server/utils/request-handler/request-handler.ts +++ b/src/lib/server/utils/request-handler/request-handler.ts @@ -22,7 +22,7 @@ export const useRequestHandler = ( try { const context = await getContext(event); - const body = parseBody(await event.request.json(), options?.body); + const body = parseBody(await event.request.formData(), options?.body); assertRequest(context, options); diff --git a/src/lib/utils/http/client.ts b/src/lib/utils/http/client.ts index b74bf1a..98f5895 100644 --- a/src/lib/utils/http/client.ts +++ b/src/lib/utils/http/client.ts @@ -6,16 +6,14 @@ export interface MiddlewareParams { options: RequestOptions; } -export type FullResponse = Response & { content: any }; - -export type MiddlewareNext = (params?: MiddlewareParams) => Promise; +export type MiddlewareNext = (params?: MiddlewareParams) => Promise; export type Middleware = ( params: MiddlewareParams, next: MiddlewareNext, -) => Promise | undefined; +) => Promise | undefined; -type BaseRequest = (path: string, options: RequestOptions) => Promise; +type BaseRequest = (path: string, options: RequestOptions) => Promise; export class HttpClient { private readonly _baseUrl: string; @@ -32,7 +30,7 @@ export class HttpClient { this._middlewares = []; } - get(path: string, options?: RequestOptions): Promise { + get(path: string, options?: RequestOptions): Promise { return this._applyMiddlewares(path, options, (newPath, newOptions) => { return this._request(newPath, { ...newOptions, @@ -41,7 +39,17 @@ export class HttpClient { }); } - post(path: string, body?: string, options?: RequestOptions): Promise { + post(path: string, body?: string, options?: RequestOptions): Promise { + return this._applyMiddlewares(path, options, (newPath, newOptions) => { + return this._request(newPath, { + ...newOptions, + method: 'POST', + body: body, + }); + }); + } + + postFormData(path: string, body?: FormData, options?: RequestOptions): Promise { return this._applyMiddlewares(path, options, (newPath, newOptions) => { return this._request(newPath, { ...newOptions, @@ -51,7 +59,7 @@ export class HttpClient { }); } - put(path: string, body?: string, options?: RequestOptions): Promise { + put(path: string, body?: string, options?: RequestOptions): Promise { return this._applyMiddlewares(path, options, (newPath, newOptions) => { return this._request(newPath, { ...newOptions, @@ -61,7 +69,7 @@ export class HttpClient { }); } - patch(path: string, body?: string, options?: RequestOptions): Promise { + patch(path: string, body?: string, options?: RequestOptions): Promise { return this._applyMiddlewares(path, options, async (newPath, newOptions) => { return this._request(newPath, { ...newOptions, @@ -71,12 +79,12 @@ export class HttpClient { }); } - delete(path: string, options?: RequestOptions): Promise { + delete(path: string, options?: RequestOptions): Promise { return this._applyMiddlewares(path, options, (newPath, newOptions) => { return this._request(newPath, { ...newOptions, method: 'DELETE', - }) as Promise; + }) as Promise; }); } @@ -85,17 +93,15 @@ export class HttpClient { return this; } - private async _request(path: string, request: RequestInit): Promise { - const res = (await fetch(path, request)) as FullResponse; - res.content = null; - return res; + private _request(path: string, request: RequestInit): Promise { + return fetch(path, request); } private _applyMiddlewares( path: string, options: RequestOptions | undefined, callback: BaseRequest, - ): Promise { + ): Promise { const baseParams = { path, fullPath: this._getUrl(path), @@ -105,14 +111,14 @@ export class HttpClient { }, }; const middlewares = this._middlewares.slice(); - let response: FullResponse; + let response: Response; - const execution = async (params?: MiddlewareParams): Promise => { + const execution = async (params?: MiddlewareParams): Promise => { if (!params) params = baseParams; const middleware = middlewares.shift(); - if (!middleware) response = (await callback(params.fullPath, params.options)) as FullResponse; + if (!middleware) response = (await callback(params.fullPath, params.options)) as Response; else response = (await middleware(params, execution)) ?? response; return response; From d34b6ebdcb4fd94aaddf774da93387545c8a8736 Mon Sep 17 00:00:00 2001 From: Exelo Date: Tue, 12 May 2026 14:10:55 +0900 Subject: [PATCH 11/58] fix: move loader to project handler to have the part handling --- .env.example | 3 ++ .../{load.actions.ts => load.action.ts} | 0 src/lib/server/cli/cli.ts | 1 + src/lib/server/loader/loader.ts | 44 ------------------- src/lib/server/{ => project}/loader/env.ts | 0 src/lib/server/{ => project}/loader/index.ts | 0 src/lib/server/project/loader/loader.ts | 40 +++++++++++++++++ src/lib/server/{ => project}/loader/types.ts | 0 src/lib/server/project/project-handler.ts | 16 +++++-- .../server/utils/request-handler/handler.ts | 8 ---- src/routes/actions/project/+page.server.ts | 2 +- 11 files changed, 57 insertions(+), 57 deletions(-) rename src/lib/server/actions/project/{load.actions.ts => load.action.ts} (100%) delete mode 100644 src/lib/server/loader/loader.ts rename src/lib/server/{ => project}/loader/env.ts (100%) rename src/lib/server/{ => project}/loader/index.ts (100%) create mode 100644 src/lib/server/project/loader/loader.ts rename src/lib/server/{ => project}/loader/types.ts (100%) diff --git a/.env.example b/.env.example index 3b356af..4d72840 100644 --- a/.env.example +++ b/.env.example @@ -11,6 +11,9 @@ API_KEY=test # Fs root dir read/write projects (leave empty to select current directory) (if you use relative path, it will be / FS_ROOT= +# Git root dir read/write/clone projects (leave empty to select current directory) (if you use relative path, it will be / +GIT_ROOT= + # Leaving this empty will generate a new unique random session secret at start SESSION_SECRET= diff --git a/src/lib/server/actions/project/load.actions.ts b/src/lib/server/actions/project/load.action.ts similarity index 100% rename from src/lib/server/actions/project/load.actions.ts rename to src/lib/server/actions/project/load.action.ts diff --git a/src/lib/server/cli/cli.ts b/src/lib/server/cli/cli.ts index 73a8b54..475665d 100644 --- a/src/lib/server/cli/cli.ts +++ b/src/lib/server/cli/cli.ts @@ -53,6 +53,7 @@ export class Cli { } generate(opts: CliPartial, runOpts?: CliRunOptions): void { + this.assertProject(); return this.runCommand('generate', [], { ...opts, directory: this._projectPath }, runOpts); } diff --git a/src/lib/server/loader/loader.ts b/src/lib/server/loader/loader.ts deleted file mode 100644 index b688911..0000000 --- a/src/lib/server/loader/loader.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { ReadStream } from 'fs'; -import { join } from 'path'; - -import { FileSystem } from '$lib/server/file-system'; -import { directoryContentToFileEntries } from '$lib/server/file-system/project-directory'; - -import type { Part } from '@utils/types'; - -import { Exception } from '@utils-server/exception'; -import type { Context } from '@utils-server/request-handler'; - -import { resolveEnv } from './env'; -import type { Manifest } from './types'; - -export class Loader { - private readonly _projectPath: string; - private readonly _fs: FileSystem; - - constructor(context: Context) { - if (!context.project) throw new Exception('Bad Request', 'Project is not defined', 400); - this._projectPath = context.project.path; - this._fs = new FileSystem(context); - } - - getEnv(part: Part): Record { - return resolveEnv(part, this._projectPath); - } - - getManifest(part: Part): Manifest { - const entries = directoryContentToFileEntries( - this._fs.getDirectory(join('.nanoforge', part)).read(true), - this._projectPath, - ); - return { - version: '1.0.0', - files: entries.map((path) => ({ path })), - }; - } - - getFile(part: Part, path: string): ReadStream { - const fullPath = join('.nanoforge', part, `${path.startsWith('/') ? path.slice(1) : path}`); - return this._fs.getFile(fullPath).readStream(); - } -} diff --git a/src/lib/server/loader/env.ts b/src/lib/server/project/loader/env.ts similarity index 100% rename from src/lib/server/loader/env.ts rename to src/lib/server/project/loader/env.ts diff --git a/src/lib/server/loader/index.ts b/src/lib/server/project/loader/index.ts similarity index 100% rename from src/lib/server/loader/index.ts rename to src/lib/server/project/loader/index.ts diff --git a/src/lib/server/project/loader/loader.ts b/src/lib/server/project/loader/loader.ts new file mode 100644 index 0000000..3002125 --- /dev/null +++ b/src/lib/server/project/loader/loader.ts @@ -0,0 +1,40 @@ +import type { ReadStream } from 'fs'; +import { join } from 'path'; + +import { directoryContentToFileEntries } from '$lib/server/file-system/project-directory'; + +import { type ProjectHandler } from '../project-handler'; +import { resolveEnv } from './env'; +import type { Manifest } from './types'; + +export class Loader { + private readonly handler: ProjectHandler; + + constructor(handler: ProjectHandler) { + this.handler = handler; + } + + getEnv(): Record { + return resolveEnv(this.handler._part, this.handler._path); + } + + getManifest(): Manifest { + const entries = directoryContentToFileEntries( + this.handler._fs.getDirectory(join('.nanoforge', this.handler._part)).read(true), + this.handler._path, + ); + return { + version: '1.0.0', + files: entries.map((path) => ({ path })), + }; + } + + getFile(path: string): ReadStream { + const fullPath = join( + '.nanoforge', + this.handler._part, + `${path.startsWith('/') ? path.slice(1) : path}`, + ); + return this.handler._fs.getFile(fullPath).readStream(); + } +} diff --git a/src/lib/server/loader/types.ts b/src/lib/server/project/loader/types.ts similarity index 100% rename from src/lib/server/loader/types.ts rename to src/lib/server/project/loader/types.ts diff --git a/src/lib/server/project/project-handler.ts b/src/lib/server/project/project-handler.ts index a5d722e..e12c07e 100644 --- a/src/lib/server/project/project-handler.ts +++ b/src/lib/server/project/project-handler.ts @@ -5,33 +5,41 @@ import type { Part } from '@utils/types'; import type { Context } from '@utils-server/request-handler'; +import { Loader } from './loader'; import { PackageHandler } from './package/package-handler'; import { SaveHandler } from './save/save-handler'; export class ProjectHandler { + public readonly _path: string; public readonly _part: Part; public readonly _cli: Cli; public readonly _fs: FileSystem; - private readonly _save: SaveHandler; - private readonly _package: PackageHandler; + private _loader: Loader | undefined; + private _save: SaveHandler | undefined; + private _package: PackageHandler | undefined; constructor(context: Context, part: Part) { + this._path = context.project?.path; this._part = part; this._cli = new Cli(context); this._fs = new FileSystem(context); this._fs.getDirectory(this._part).assertExists(); + } - this._save = new SaveHandler(this); - this._package = new PackageHandler(this); + get loader(): Loader { + if (!this._loader) this._loader = new Loader(this); + return this._loader; } get package(): PackageHandler { + if (!this._package) this._package = new PackageHandler(this); return this._package; } get save(): SaveHandler { + if (!this._save) this._save = new SaveHandler(this); return this._save; } } diff --git a/src/lib/server/utils/request-handler/handler.ts b/src/lib/server/utils/request-handler/handler.ts index 9854a85..131b945 100644 --- a/src/lib/server/utils/request-handler/handler.ts +++ b/src/lib/server/utils/request-handler/handler.ts @@ -4,7 +4,6 @@ import { type Api, getApi } from '$lib/server/api'; import { Cli } from '$lib/server/cli'; import { FileSystem } from '$lib/server/file-system'; import { Git } from '$lib/server/git'; -import { Loader } from '$lib/server/loader'; import { ProjectManager } from '$lib/server/project'; import type { Context } from '@utils-server/request-handler/context'; @@ -17,7 +16,6 @@ export class Handler { private _apiCache: Api | undefined; private _cliCache: Cli | undefined; private _fsCache: FileSystem | undefined; - private _loaderCache: Loader | undefined; private _gitCache: Git | undefined; private _projectCache: ProjectManager | undefined; @@ -37,7 +35,6 @@ export class Handler { this._apiCache = undefined; this._cliCache = undefined; this._fsCache = undefined; - this._loaderCache = undefined; this._gitCache = undefined; } @@ -64,11 +61,6 @@ export class Handler { return this._fsCache; } - get loader(): any { - if (!this._loaderCache) this._loaderCache = new Loader(this._context); - return this._loaderCache; - } - get git(): Git { if (!this._gitCache) this._gitCache = new Git(); return this._gitCache; diff --git a/src/routes/actions/project/+page.server.ts b/src/routes/actions/project/+page.server.ts index fa377c9..d514791 100644 --- a/src/routes/actions/project/+page.server.ts +++ b/src/routes/actions/project/+page.server.ts @@ -1,4 +1,4 @@ -import { loadProjectAction } from '$lib/server/actions/project/load.actions'; +import { loadProjectAction } from '$lib/server/actions/project/load.action'; export const actions = { load: loadProjectAction, From 5136d362f37517390b41cc7b09eb981aa801d2b3 Mon Sep 17 00:00:00 2001 From: Exelo Date: Wed, 13 May 2026 10:41:34 +0900 Subject: [PATCH 12/58] fix: change getting file to file stream --- src/lib/server/actions/config/fetch.action.ts | 14 ++++++++ src/lib/server/actions/project/load.action.ts | 4 +-- .../actions/project/loader/env.action.ts | 7 ++++ .../actions/project/loader/manifest.action.ts | 7 ++++ src/lib/server/file-system/file-system.ts | 11 ++++-- src/lib/server/file-system/index.ts | 2 ++ src/lib/server/file-system/project-file.ts | 5 +-- src/lib/server/project/loader/loader.ts | 25 +++++++------ .../server/project/package/package-handler.ts | 2 +- src/lib/server/project/project-handler.ts | 23 +++++++++--- src/lib/server/project/project-manager.ts | 8 +++++ src/lib/server/project/save/save-handler.ts | 4 +-- .../utils/request-handler/action-handler.ts | 36 +++++++++++++++++++ src/lib/server/utils/request-handler/body.ts | 10 +++++- src/lib/server/utils/request-handler/index.ts | 1 + .../utils/request-handler/request-handler.ts | 22 +++++++----- src/lib/server/utils/request-handler/types.ts | 16 --------- src/routes/actions/config/+page.server.ts | 5 +++ .../actions/project/loader/+page.server.ts | 7 ++++ src/routes/fs/build/+server.ts | 19 ++++++++++ src/routes/fs/project/+server.ts | 19 ++++++++++ 21 files changed, 194 insertions(+), 53 deletions(-) create mode 100644 src/lib/server/actions/config/fetch.action.ts create mode 100644 src/lib/server/actions/project/loader/env.action.ts create mode 100644 src/lib/server/actions/project/loader/manifest.action.ts create mode 100644 src/lib/server/utils/request-handler/action-handler.ts create mode 100644 src/routes/actions/config/+page.server.ts create mode 100644 src/routes/actions/project/loader/+page.server.ts create mode 100644 src/routes/fs/build/+server.ts create mode 100644 src/routes/fs/project/+server.ts diff --git a/src/lib/server/actions/config/fetch.action.ts b/src/lib/server/actions/config/fetch.action.ts new file mode 100644 index 0000000..30b6935 --- /dev/null +++ b/src/lib/server/actions/config/fetch.action.ts @@ -0,0 +1,14 @@ +import { useActionHandler } from '@utils-server/request-handler'; + +export const fetchConfigAction = useActionHandler( + async (handler) => { + const { context } = handler; + + return { + mode: context.online ? 'online' : 'offline', + }; + }, + { + projectOptional: true, + }, +); diff --git a/src/lib/server/actions/project/load.action.ts b/src/lib/server/actions/project/load.action.ts index 4506344..a104776 100644 --- a/src/lib/server/actions/project/load.action.ts +++ b/src/lib/server/actions/project/load.action.ts @@ -4,7 +4,7 @@ import { loadProject } from '$lib/server/project'; import type { SessionProject } from '$lib/server/session'; import { Exception } from '@utils-server/exception'; -import { type Handler, useRequestHandler } from '@utils-server/request-handler'; +import { type Handler, useActionHandler } from '@utils-server/request-handler'; class LoadProjectBody { path?: string; @@ -58,7 +58,7 @@ const resolveSessionFunctions: Record< gatewayId: resolveSessionFromGatewayId, }; -export const loadProjectAction = useRequestHandler( +export const loadProjectAction = useActionHandler( async (handler) => { const { body } = handler; diff --git a/src/lib/server/actions/project/loader/env.action.ts b/src/lib/server/actions/project/loader/env.action.ts new file mode 100644 index 0000000..84e61ce --- /dev/null +++ b/src/lib/server/actions/project/loader/env.action.ts @@ -0,0 +1,7 @@ +import { useActionHandler } from '@utils-server/request-handler'; + +export const fetchEnvLoaderAction = useActionHandler(async (handler) => { + const { project } = handler; + + return project.client.loader.getEnv(); +}); diff --git a/src/lib/server/actions/project/loader/manifest.action.ts b/src/lib/server/actions/project/loader/manifest.action.ts new file mode 100644 index 0000000..bf2a982 --- /dev/null +++ b/src/lib/server/actions/project/loader/manifest.action.ts @@ -0,0 +1,7 @@ +import { useActionHandler } from '@utils-server/request-handler'; + +export const fetchManifestLoaderAction = useActionHandler(async (handler) => { + const { project } = handler; + + return project.client.loader.getManifest(); +}); diff --git a/src/lib/server/file-system/file-system.ts b/src/lib/server/file-system/file-system.ts index 430c45b..5f26cd5 100644 --- a/src/lib/server/file-system/file-system.ts +++ b/src/lib/server/file-system/file-system.ts @@ -8,12 +8,17 @@ import { ProjectFile } from './project-file'; export class FileSystem { private readonly _rootPath: string; - constructor(context: Context) { - if (!context.project) { + constructor(arg: string | Context) { + if (typeof arg === 'string') { + this._rootPath = resolveRootPath(arg); + return; + } + + if (!arg.project) { throw new Exception('Bad Request', 'Project is not defined', 400); } - this._rootPath = resolveRootPath(context.project.path); + this._rootPath = resolveRootPath(arg.project.path); } getDirectory(path: string) { diff --git a/src/lib/server/file-system/index.ts b/src/lib/server/file-system/index.ts index 54aae6d..a4b242d 100644 --- a/src/lib/server/file-system/index.ts +++ b/src/lib/server/file-system/index.ts @@ -1 +1,3 @@ export { FileSystem } from './file-system'; +export { directoryContentToFileEntries, type ProjectDirectory } from './project-directory'; +export { type ProjectFile } from './project-file'; diff --git a/src/lib/server/file-system/project-file.ts b/src/lib/server/file-system/project-file.ts index 46d9659..a17e3c5 100644 --- a/src/lib/server/file-system/project-file.ts +++ b/src/lib/server/file-system/project-file.ts @@ -24,9 +24,10 @@ export class ProjectFile { return fs.readFileSync(this._path).toString(encoding); } - readStream(): fs.ReadStream { + readStream(): ReadableStream { this.isReadable(); - return fs.createReadStream(this._path); + const file = Bun.file(this._path); + return file.stream(); } readJson(): T { diff --git a/src/lib/server/project/loader/loader.ts b/src/lib/server/project/loader/loader.ts index 3002125..2ec3b53 100644 --- a/src/lib/server/project/loader/loader.ts +++ b/src/lib/server/project/loader/loader.ts @@ -1,7 +1,10 @@ -import type { ReadStream } from 'fs'; import { join } from 'path'; -import { directoryContentToFileEntries } from '$lib/server/file-system/project-directory'; +import { + FileSystem, + type ProjectFile, + directoryContentToFileEntries, +} from '$lib/server/file-system'; import { type ProjectHandler } from '../project-handler'; import { resolveEnv } from './env'; @@ -9,9 +12,13 @@ import type { Manifest } from './types'; export class Loader { private readonly handler: ProjectHandler; + private readonly _fs: FileSystem; + private readonly _basePath: string; constructor(handler: ProjectHandler) { this.handler = handler; + this._basePath = join(this.handler._path, '.nanoforge', this.handler._part); + this._fs = new FileSystem(this._basePath); } getEnv(): Record { @@ -19,22 +26,14 @@ export class Loader { } getManifest(): Manifest { - const entries = directoryContentToFileEntries( - this.handler._fs.getDirectory(join('.nanoforge', this.handler._part)).read(true), - this.handler._path, - ); + const entries = directoryContentToFileEntries(this._fs.getDirectory('.').read(true)); return { version: '1.0.0', files: entries.map((path) => ({ path })), }; } - getFile(path: string): ReadStream { - const fullPath = join( - '.nanoforge', - this.handler._part, - `${path.startsWith('/') ? path.slice(1) : path}`, - ); - return this.handler._fs.getFile(fullPath).readStream(); + getFile(path: string): ProjectFile { + return this._fs.getFile(path); } } diff --git a/src/lib/server/project/package/package-handler.ts b/src/lib/server/project/package/package-handler.ts index bfec094..6fc4aa2 100644 --- a/src/lib/server/project/package/package-handler.ts +++ b/src/lib/server/project/package/package-handler.ts @@ -88,7 +88,7 @@ export class PackageHandler { } private _getPackageManifest(type: PackageTypeEnum, path: string): any { - const content = this.handler._fs.getFile(this._resolvePartPath(path)).read(); + const content = this.handler._rootFs.getFile(this._resolvePartPath(path)).read(); return resolveManifest(type, content); } diff --git a/src/lib/server/project/project-handler.ts b/src/lib/server/project/project-handler.ts index e12c07e..503a0ea 100644 --- a/src/lib/server/project/project-handler.ts +++ b/src/lib/server/project/project-handler.ts @@ -1,8 +1,11 @@ +import { join } from 'path'; + import { Cli } from '$lib/server/cli'; import { FileSystem } from '$lib/server/file-system'; import type { Part } from '@utils/types'; +import { Exception } from '@utils-server/exception'; import type { Context } from '@utils-server/request-handler'; import { Loader } from './loader'; @@ -13,21 +16,33 @@ export class ProjectHandler { public readonly _path: string; public readonly _part: Part; public readonly _cli: Cli; - public readonly _fs: FileSystem; + public readonly _rootFs: FileSystem; + private _fs: FileSystem | undefined; private _loader: Loader | undefined; private _save: SaveHandler | undefined; private _package: PackageHandler | undefined; constructor(context: Context, part: Part) { - this._path = context.project?.path; + if (!context.project) throw new Exception('Bad Request', 'Project missing in context', 400); + this._path = context.project.path; this._part = part; this._cli = new Cli(context); - this._fs = new FileSystem(context); + this._rootFs = new FileSystem(context); + } - this._fs.getDirectory(this._part).assertExists(); + /** + * Get the file system of the project content + * This file system has his root at / + */ + get fs(): FileSystem { + if (!this._fs) this._fs = new FileSystem(join(this._path, this._part)); + return this._fs; } + /** + * Get the loader functions of the project + */ get loader(): Loader { if (!this._loader) this._loader = new Loader(this); return this._loader; diff --git a/src/lib/server/project/project-manager.ts b/src/lib/server/project/project-manager.ts index dcf6f68..5036021 100644 --- a/src/lib/server/project/project-manager.ts +++ b/src/lib/server/project/project-manager.ts @@ -12,11 +12,19 @@ export class ProjectManager { this._context = context; } + /** + * Get the client project handler + * @beta The separation between client and server projects is not the final goal of the project manager. + */ get client(): ProjectHandler { if (!this._client) this._client = new ProjectHandler(this._context, 'client'); return this._client; } + /** + * Get the server project handler + * @beta The separation between client and server projects is not the final goal of the project manager. + */ get server(): ProjectHandler { if (!this._server) this._server = new ProjectHandler(this._context, 'server'); return this._server; diff --git a/src/lib/server/project/save/save-handler.ts b/src/lib/server/project/save/save-handler.ts index 42ad5cc..53af39b 100644 --- a/src/lib/server/project/save/save-handler.ts +++ b/src/lib/server/project/save/save-handler.ts @@ -10,11 +10,11 @@ export class SaveHandler { } async getSave(): Promise { - return this.handler._fs.getFile(this.resolveSavePath()).readJson(); + return this.handler._rootFs.getFile(this.resolveSavePath()).readJson(); } async updateSave(save: Save): Promise { - this.handler._fs.getFile(this.resolveSavePath()).writeJson(save); + this.handler._rootFs.getFile(this.resolveSavePath()).writeJson(save); } private resolveSavePath(): string { diff --git a/src/lib/server/utils/request-handler/action-handler.ts b/src/lib/server/utils/request-handler/action-handler.ts new file mode 100644 index 0000000..6c728c7 --- /dev/null +++ b/src/lib/server/utils/request-handler/action-handler.ts @@ -0,0 +1,36 @@ +import { type Action, type ActionFailure, fail } from '@sveltejs/kit'; + +import { Exception } from '../exception'; +import { parseFormDataBody } from './body'; +import { getContext } from './context'; +import { Handler } from './handler'; +import { assertRequest } from './request.policy'; +import type { Callback, RequestHandlerOptions } from './types'; + +const handleError = (e: unknown): ActionFailure<{ error: string; message: unknown }> => { + if (e instanceof Exception) { + return fail(e.status, { error: e.error, message: e.message }); + } + return fail(500, { error: 'Internal Server Error', message: e }); +}; + +export const useActionHandler = ( + callback: Callback, + options?: RequestHandlerOptions, +): Action => { + return async (event) => { + try { + const context = await getContext(event); + + const body = parseFormDataBody(await event.request.formData(), options?.body); + + assertRequest(context, options); + + const handler = new Handler(context, event, body); + + return await callback(handler); + } catch (e) { + return handleError(e); + } + }; +}; diff --git a/src/lib/server/utils/request-handler/body.ts b/src/lib/server/utils/request-handler/body.ts index 7b88ee7..73a3b84 100644 --- a/src/lib/server/utils/request-handler/body.ts +++ b/src/lib/server/utils/request-handler/body.ts @@ -1,9 +1,17 @@ import type { ClassType } from '@utils/types'; -export const parseBody = (rawBody: FormData, c: ClassType | undefined): Body => { +export const parseFormDataBody = ( + rawBody: FormData, + c: ClassType | undefined, +): Body => { const baseBody = Object.fromEntries( Array.from(rawBody.entries()).map(([key, value]) => [key, JSON.parse(value)]), ); + // @todo add class validation and class transformation + return parseBody(baseBody, c); +}; + +export const parseBody = (baseBody: any, c: ClassType | undefined): Body => { // @todo add class validation and class transformation void c; return baseBody as Body; diff --git a/src/lib/server/utils/request-handler/index.ts b/src/lib/server/utils/request-handler/index.ts index 3302cad..a2343e0 100644 --- a/src/lib/server/utils/request-handler/index.ts +++ b/src/lib/server/utils/request-handler/index.ts @@ -1,3 +1,4 @@ +export * from './action-handler'; export * from './request-handler'; export * from './context'; export * from './handler'; diff --git a/src/lib/server/utils/request-handler/request-handler.ts b/src/lib/server/utils/request-handler/request-handler.ts index f3a92ac..61134c5 100644 --- a/src/lib/server/utils/request-handler/request-handler.ts +++ b/src/lib/server/utils/request-handler/request-handler.ts @@ -1,28 +1,32 @@ -import { type Action, type ActionFailure, fail } from '@sveltejs/kit'; +import type { RequestEvent } from '@sveltejs/kit'; + +import type { MaybePromise } from '@utils/types'; import { Exception } from '../exception'; import { parseBody } from './body'; import { getContext } from './context'; import { Handler } from './handler'; import { assertRequest } from './request.policy'; -import type { Callback, RequestHandlerOptions } from './types'; +import type { RequestHandlerOptions } from './types'; + +type Callback = (opts: Handler) => MaybePromise; -const handleError = (e: unknown): ActionFailure<{ error: string; message: unknown }> => { +const handleError = (e: unknown): Response => { if (e instanceof Exception) { - return fail(e.status, { error: e.error, message: e.message }); + return Response.json({ error: e.error, message: e.message }, { status: e.status }); } - return fail(500, { error: 'Internal Server Error', message: e }); + return Response.json({ error: 'Internal Server Error', message: e }, { status: 500 }); }; -export const useRequestHandler = ( +export const useRequestHandler = ( callback: Callback, options?: RequestHandlerOptions, -): Action => { - return async (event) => { +): ((event: RequestEvent) => MaybePromise) => { + return async (event: RequestEvent) => { try { const context = await getContext(event); - const body = parseBody(await event.request.formData(), options?.body); + const body = parseBody(await event.request.json(), options?.body); assertRequest(context, options); diff --git a/src/lib/server/utils/request-handler/types.ts b/src/lib/server/utils/request-handler/types.ts index c676e47..945b41f 100644 --- a/src/lib/server/utils/request-handler/types.ts +++ b/src/lib/server/utils/request-handler/types.ts @@ -1,23 +1,7 @@ -import { type RequestEvent } from '@sveltejs/kit'; - -import { type Api } from '$lib/server/api'; -import { type FileSystem } from '$lib/server/file-system'; - import type { ClassType, MaybePromise } from '@utils/types'; -import type { Context } from './context'; import { type Handler } from './handler'; -export interface CallbackOptions { - event: RequestEvent; - body: Body; - context: Context; - api: (context?: Context) => Api; - cli: (context?: Context) => void; - fs: (context?: Context) => FileSystem; - loader: (context?: Context) => void; -} - export type Callback = (opts: Handler) => MaybePromise; export interface RequestHandlerOptions { diff --git a/src/routes/actions/config/+page.server.ts b/src/routes/actions/config/+page.server.ts new file mode 100644 index 0000000..aee3449 --- /dev/null +++ b/src/routes/actions/config/+page.server.ts @@ -0,0 +1,5 @@ +import { fetchConfigAction } from '$lib/server/actions/config/fetch.action'; + +export const actions = { + fetch: fetchConfigAction, +}; diff --git a/src/routes/actions/project/loader/+page.server.ts b/src/routes/actions/project/loader/+page.server.ts new file mode 100644 index 0000000..5b5e889 --- /dev/null +++ b/src/routes/actions/project/loader/+page.server.ts @@ -0,0 +1,7 @@ +import { fetchEnvLoaderAction } from '$lib/server/actions/project/loader/env.action'; +import { fetchManifestLoaderAction } from '$lib/server/actions/project/loader/manifest.action'; + +export const actions = { + env: fetchEnvLoaderAction, + manifest: fetchManifestLoaderAction, +}; diff --git a/src/routes/fs/build/+server.ts b/src/routes/fs/build/+server.ts new file mode 100644 index 0000000..e3fa8c0 --- /dev/null +++ b/src/routes/fs/build/+server.ts @@ -0,0 +1,19 @@ +import { Exception } from '@utils-server/exception'; +import { useRequestHandler } from '@utils-server/request-handler'; + +/** + * To request a built file, use the following URL: + * /fs/build?path=path/to/file + * The path must be relative to /.nanoforge/client + * Only the client is handled for now + */ +export const GET = useRequestHandler(({ event, project }) => { + const path = event.url.searchParams.get('path'); + if (!path) throw new Exception('Bad Request', 'Missing path query param', 400); + + const file = project.client.loader.getFile(path); + + const stream = file.readStream(); + + return new Response(stream); +}); diff --git a/src/routes/fs/project/+server.ts b/src/routes/fs/project/+server.ts new file mode 100644 index 0000000..0a79bed --- /dev/null +++ b/src/routes/fs/project/+server.ts @@ -0,0 +1,19 @@ +import { Exception } from '@utils-server/exception'; +import { useRequestHandler } from '@utils-server/request-handler'; + +/** + * To request a project file, use the following URL: + * /fs/project?path=path/to/file + * The path must be relative to /client + * Only the client is handled for now + */ +export const GET = useRequestHandler(({ event, project }) => { + const path = event.url.searchParams.get('path'); + if (!path) throw new Exception('Bad Request', 'Missing path query param', 400); + + const file = project.client.fs.getFile(path); + + const stream = file.readStream(); + + return new Response(stream); +}); From b7972bd81f9955ac9c764050b20d8fdcc3008362 Mon Sep 17 00:00:00 2001 From: Exelo Date: Thu, 14 May 2026 09:36:06 +0900 Subject: [PATCH 13/58] fix: in env remove GIT_ROOT and set MODE public --- .env.example | 9 +++------ src/lib/server/api/client.ts | 2 +- src/lib/server/git/git.ts | 2 +- src/lib/server/utils/request-handler/context.ts | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index 4d72840..0cba235 100644 --- a/.env.example +++ b/.env.example @@ -2,18 +2,15 @@ NODE_ENV=development # OFFLINE or ONLINE, change editor mode beetween local execution and online execution -MODE=OFFLINE +PUBLIC_MODE=OFFLINE -# Api params (required if MODE=ONLINE) +# Api params (required if PUBLIC_MODE=ONLINE) API_URL=http://localhost:3000 API_KEY=test -# Fs root dir read/write projects (leave empty to select current directory) (if you use relative path, it will be / +# Fs root dir read/write projects (leave empty to select current directory) (if you use relative path, it will be /) FS_ROOT= -# Git root dir read/write/clone projects (leave empty to select current directory) (if you use relative path, it will be / -GIT_ROOT= - # Leaving this empty will generate a new unique random session secret at start SESSION_SECRET= diff --git a/src/lib/server/api/client.ts b/src/lib/server/api/client.ts index 50dc98a..26c46c2 100644 --- a/src/lib/server/api/client.ts +++ b/src/lib/server/api/client.ts @@ -16,7 +16,7 @@ export interface Api { } export const getNoAuthApi = () => { - if (env.MODE !== 'ONLINE') throw new Error('API is only available in online mode'); + if (env.PUBLIC_MODE !== 'ONLINE') throw new Error('API is only available in online mode'); if (!env.API_URL) throw new Error('API_URL is not defined'); if (!env.API_KEY) throw new Error('API_KEY is not defined'); diff --git a/src/lib/server/git/git.ts b/src/lib/server/git/git.ts index 94d4e2c..4583737 100644 --- a/src/lib/server/git/git.ts +++ b/src/lib/server/git/git.ts @@ -9,7 +9,7 @@ export class Git { private readonly _rootPath: string; constructor() { - this._rootPath = resolve(env.GIT_ROOT ?? ''); + this._rootPath = resolve(env.FS_ROOT ?? ''); } async clone(url: string, options?: { sshKey?: string }): Promise { diff --git a/src/lib/server/utils/request-handler/context.ts b/src/lib/server/utils/request-handler/context.ts index dcbbc7a..2163d91 100644 --- a/src/lib/server/utils/request-handler/context.ts +++ b/src/lib/server/utils/request-handler/context.ts @@ -20,7 +20,7 @@ export const getContext = async (event: RequestEvent): Promise => { const project = resolveProject(event.request.headers, session) as SessionProject; return { - online: env.MODE === 'ONLINE', + online: env.PUBLIC_MODE === 'ONLINE', session, project, }; From b35ed29d9f924cd9dbb6de277ac576d77edb077a Mon Sep 17 00:00:00 2001 From: Exelo Date: Thu, 14 May 2026 09:40:31 +0900 Subject: [PATCH 14/58] chore: upgrade deps --- pnpm-lock.yaml | 1979 +++++++++++++++++++++++-------------------- pnpm-workspace.yaml | 42 +- 2 files changed, 1079 insertions(+), 942 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 515f729..39bc470 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,11 +21,11 @@ catalogs: version: 6.0.3 ci: '@commitlint/cli': - specifier: ^20.5.2 - version: 20.5.2 + specifier: ^21.0.1 + version: 21.0.1 '@commitlint/config-conventional': - specifier: ^20.5.0 - version: 20.5.0 + specifier: ^21.0.1 + version: 21.0.1 '@favware/cliff-jumper': specifier: ^6.1.0 version: 6.1.0 @@ -36,12 +36,12 @@ catalogs: specifier: ^9.1.7 version: 9.1.7 lint-staged: - specifier: ^16.4.0 - version: 16.4.0 + specifier: ^17.0.4 + version: 17.0.4 components: flowbite: - specifier: ^4.0.1 - version: 4.0.1 + specifier: ^4.0.2 + version: 4.0.2 flowbite-svelte: specifier: ^1.33.1 version: 1.33.1 @@ -56,29 +56,29 @@ catalogs: specifier: ^1.1.2 version: 1.1.2 '@sveltejs/kit': - specifier: ^2.58.0 - version: 2.58.0 + specifier: ^2.59.1 + version: 2.59.1 '@sveltejs/vite-plugin-svelte': - specifier: ^7.0.0 - version: 7.0.0 + specifier: ^7.1.2 + version: 7.1.2 '@types/bun': - specifier: ^1.3.13 - version: 1.3.13 + specifier: ^1.3.14 + version: 1.3.14 bun: - specifier: ^1.3.13 - version: 1.3.13 + specifier: ^1.3.14 + version: 1.3.14 svelte: specifier: ^5.55.5 version: 5.55.5 svelte-check: - specifier: ^4.4.6 - version: 4.4.6 + specifier: ^4.4.8 + version: 4.4.8 svelte-kit-sessions: specifier: ^0.4.0 version: 0.4.0 vite: - specifier: ^8.0.10 - version: 8.0.10 + specifier: ^8.0.12 + version: 8.0.12 css: '@alexanderniebuhr/prettier-plugin-unocss': specifier: ^0.0.4 @@ -100,15 +100,15 @@ catalogs: version: 66.6.8 i18n: '@inlang/paraglide-js': - specifier: ^2.17.0 - version: 2.17.0 + specifier: ^2.18.0 + version: 2.18.0 icons: '@iconify-json/ic': specifier: ^1.2.4 version: 1.2.4 '@iconify-json/material-icon-theme': - specifier: ^1.2.61 - version: 1.2.61 + specifier: ^1.2.64 + version: 1.2.64 '@iconify-json/solar': specifier: ^1.2.5 version: 1.2.5 @@ -123,39 +123,39 @@ catalogs: specifier: ^6.0.2 version: 6.0.2 eslint: - specifier: ^10.2.1 - version: 10.2.1 + specifier: ^10.3.0 + version: 10.3.0 eslint-plugin-svelte: specifier: ^3.17.1 version: 3.17.1 globals: - specifier: ^17.5.0 - version: 17.5.0 + specifier: ^17.6.0 + version: 17.6.0 prettier: specifier: ^3.8.3 version: 3.8.3 prettier-plugin-svelte: - specifier: ^3.5.1 - version: 3.5.1 + specifier: ^3.5.2 + version: 3.5.2 typescript-eslint: - specifier: ^8.59.1 - version: 8.59.1 + specifier: ^8.59.3 + version: 8.59.3 test: '@playwright/test': - specifier: ^1.59.1 - version: 1.59.1 + specifier: ^1.60.0 + version: 1.60.0 '@vitest/browser-playwright': - specifier: ^4.1.5 - version: 4.1.5 + specifier: ^4.1.6 + version: 4.1.6 '@vitest/coverage-v8': - specifier: ^4.1.5 - version: 4.1.5 + specifier: ^4.1.6 + version: 4.1.6 playwright: - specifier: ^1.59.1 - version: 1.59.1 + specifier: ^1.60.0 + version: 1.60.0 vitest: - specifier: ^4.1.5 - version: 4.1.5 + specifier: ^4.1.6 + version: 4.1.6 vitest-browser-svelte: specifier: ^2.1.1 version: 2.1.1 @@ -169,10 +169,10 @@ importers: version: 0.0.4 '@commitlint/cli': specifier: catalog:ci - version: 20.5.2(@types/node@25.6.0)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3) + version: 21.0.1(@types/node@25.7.0)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3) '@commitlint/config-conventional': specifier: catalog:ci - version: 20.5.0 + version: 21.0.1 '@favware/cliff-jumper': specifier: catalog:ci version: 6.1.0 @@ -181,13 +181,13 @@ importers: version: 1.2.4 '@iconify-json/material-icon-theme': specifier: catalog:icons - version: 1.2.61 + version: 1.2.64 '@iconify-json/solar': specifier: catalog:icons version: 1.2.5 '@inlang/paraglide-js': specifier: catalog:i18n - version: 2.17.0 + version: 2.18.0(typescript@6.0.3) '@nanoforge-dev/actions': specifier: catalog:ci version: 1.3.0 @@ -196,28 +196,28 @@ importers: version: 1.1.2 '@nanoforge-dev/utils-eslint-config': specifier: catalog:lint - version: 1.0.2(@types/eslint@9.6.1)(eslint@10.2.1(jiti@2.6.1))(prettier@3.8.3)(typescript@6.0.3) + version: 1.0.2(@types/eslint@9.6.1)(eslint@10.3.0(jiti@2.7.0))(prettier@3.8.3)(typescript@6.0.3) '@nanoforge-dev/utils-prettier-config': specifier: catalog:lint version: 1.0.2 '@playwright/test': specifier: catalog:test - version: 1.59.1 + version: 1.60.0 '@sveltejs/kit': specifier: catalog:core - version: 2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + version: 2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) '@sveltejs/vite-plugin-svelte': specifier: catalog:core - version: 7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + version: 7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier-plugin-svelte@3.5.1(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1)))(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1)) + version: 6.0.2(prettier-plugin-svelte@3.5.2(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3)))(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3)) '@tsconfig/svelte': specifier: catalog:build version: 5.0.8 '@types/bun': specifier: catalog:core - version: 1.3.13 + version: 1.3.14 '@unocss/extractor-svelte': specifier: catalog:css version: 66.6.8 @@ -232,82 +232,82 @@ importers: version: 66.6.8 '@vitest/browser-playwright': specifier: catalog:test - version: 4.1.5(playwright@1.59.1)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.5) + version: 4.1.6(playwright@1.60.0)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6) '@vitest/coverage-v8': specifier: catalog:test - version: 4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5) + version: 4.1.6(@vitest/browser@4.1.6)(vitest@4.1.6) bun: specifier: catalog:core - version: 1.3.13 + version: 1.3.14 dotenv: specifier: catalog:back-libs version: 17.4.2 eslint: specifier: catalog:lint - version: 10.2.1(jiti@2.6.1) + version: 10.3.0(jiti@2.7.0) eslint-plugin-svelte: specifier: catalog:lint - version: 3.17.1(eslint@10.2.1(jiti@2.6.1))(svelte@5.55.5(@typescript-eslint/types@8.59.1)) + version: 3.17.1(eslint@10.3.0(jiti@2.7.0))(svelte@5.55.5(@typescript-eslint/types@8.59.3)) flowbite: specifier: catalog:components - version: 4.0.1 + version: 4.0.2 flowbite-svelte: specifier: catalog:components - version: 1.33.1(svelte@5.55.5(@typescript-eslint/types@8.59.1))(tailwindcss@4.2.4) + version: 1.33.1(svelte@5.55.5(@typescript-eslint/types@8.59.3))(tailwindcss@4.3.0) globals: specifier: catalog:lint - version: 17.5.0 + version: 17.6.0 husky: specifier: catalog:ci version: 9.1.7 lint-staged: specifier: catalog:ci - version: 16.4.0 + version: 17.0.4 monaco-editor: specifier: catalog:components version: 0.55.1 playwright: specifier: catalog:test - version: 1.59.1 + version: 1.60.0 prettier: specifier: catalog:lint version: 3.8.3 prettier-plugin-svelte: specifier: catalog:lint - version: 3.5.1(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1)) + version: 3.5.2(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3)) svelte: specifier: catalog:core - version: 5.55.5(@typescript-eslint/types@8.59.1) + version: 5.55.5(@typescript-eslint/types@8.59.3) svelte-adapter-bun: specifier: catalog:build - version: 1.0.1(@sveltejs/kit@2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(typescript@6.0.3) + version: 1.0.1(@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(typescript@6.0.3) svelte-check: specifier: catalog:core - version: 4.4.6(picomatch@4.0.4)(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3) + version: 4.4.8(picomatch@4.0.4)(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3) svelte-kit-sessions: specifier: catalog:core - version: 0.4.0(@sveltejs/kit@2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1)) + version: 0.4.0(@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3)) svelte-sonner: specifier: catalog:components - version: 1.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.1)) + version: 1.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.3)) typescript: specifier: catalog:build version: 6.0.3 typescript-eslint: specifier: catalog:lint - version: 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + version: 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) unocss: specifier: catalog:css - version: 66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + version: 66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) vite: specifier: catalog:core - version: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) + version: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) vitest: specifier: catalog:test - version: 4.1.5(@types/node@25.6.0)(@vitest/browser-playwright@4.1.5)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + version: 4.1.6(@types/node@25.7.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) vitest-browser-svelte: specifier: catalog:test - version: 2.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vitest@4.1.5) + version: 2.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vitest@4.1.6) packages: @@ -359,8 +359,8 @@ packages: resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/parser@7.29.2': - resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + '@babel/parser@7.29.3': + resolution: {integrity: sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==} engines: {node: '>=6.0.0'} hasBin: true @@ -383,74 +383,74 @@ packages: '@blazediff/core@1.9.1': resolution: {integrity: sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==} - '@commitlint/cli@20.5.2': - resolution: {integrity: sha512-IXr5xd3IX8SEG936P8gcpozRplkDeDSwJlt8UvoY1winwIy2udTbQ/cOCgbaaxcjdDqVoS29VUcz/wkwnSozbA==} - engines: {node: '>=v18'} + '@commitlint/cli@21.0.1': + resolution: {integrity: sha512-8vq10krmbJwBkvzXKhbs4o4JQEVscd3pqOlWuDUaDBwbeL694/P33UC29tZQFTAgPU9fVJ2+f2m3zw16yKWxHg==} + engines: {node: '>=22.12.0'} hasBin: true - '@commitlint/config-conventional@20.5.0': - resolution: {integrity: sha512-t3Ni88rFw1XMa4nZHgOKJ8fIAT9M2j5TnKyTqJzsxea7FUetlNdYFus9dz+MhIRZmc16P0PPyEfh6X2d/qw8SA==} - engines: {node: '>=v18'} + '@commitlint/config-conventional@21.0.1': + resolution: {integrity: sha512-gRorrkfWOh/+V5X8GYWWbQvrzPczopGMS4CCNrQdHkK4xWElv82BDvIsDhJZWTlI7TazOlYea6VATufCsFs+sw==} + engines: {node: '>=22.12.0'} - '@commitlint/config-validator@20.5.0': - resolution: {integrity: sha512-T/Uh6iJUzyx7j35GmHWdIiGRQB+ouZDk0pwAaYq4SXgB54KZhFdJ0vYmxiW6AMYICTIWuyMxDBl1jK74oFp/Gw==} - engines: {node: '>=v18'} + '@commitlint/config-validator@21.0.1': + resolution: {integrity: sha512-Zd2UFdndeMMaW2O96HK0tdfT4gOImUvidMpAd/pws2zZ4m1nrAZ/9b/v2JYuE8fs86GpXv9F7LNaIuCIWhY+pA==} + engines: {node: '>=22.12.0'} - '@commitlint/ensure@20.5.0': - resolution: {integrity: sha512-IpHqAUesBeW1EDDdjzJeaOxU9tnogLAyXLRBn03SHlj1SGENn2JGZqSWGkFvBJkJzfXAuCNtsoYzax+ZPS+puw==} - engines: {node: '>=v18'} + '@commitlint/ensure@21.0.1': + resolution: {integrity: sha512-jJ1037967wU7YN/xkv+iRlOBlmaOXPhPO5KQSqya6GyXzBlwuLzELBFao16DVg9dZyqmNrhewzwZ3SAibetHBQ==} + engines: {node: '>=22.12.0'} - '@commitlint/execute-rule@20.0.0': - resolution: {integrity: sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==} - engines: {node: '>=v18'} + '@commitlint/execute-rule@21.0.1': + resolution: {integrity: sha512-RifH+FmImozKBE6mozhF4K3r2RRKP7SMi/Q/zLCmExtp5e05lhHOUYqGBlFBAGNHaZxU/WYw1XuugYK9jQzqnA==} + engines: {node: '>=22.12.0'} - '@commitlint/format@20.5.0': - resolution: {integrity: sha512-TI9EwFU/qZWSK7a5qyXMpKPPv3qta7FO4tKW+Wt2al7sgMbLWTsAcDpX1cU8k16TRdsiiet9aOw0zpvRXNJu7Q==} - engines: {node: '>=v18'} + '@commitlint/format@21.0.1': + resolution: {integrity: sha512-ksmG2+cHGtuDPQQbhBbC4unwm444+6TiPw0d1bKf67hntgZqZ8E0g1MuYKUuyT5IH4IMmXZhKq22/Z3jBvtQIw==} + engines: {node: '>=22.12.0'} - '@commitlint/is-ignored@20.5.0': - resolution: {integrity: sha512-JWLarAsurHJhPozbuAH6GbP4p/hdOCoqS9zJMfqwswne+/GPs5V0+rrsfOkP68Y8PSLphwtFXV0EzJ+GTXTTGg==} - engines: {node: '>=v18'} + '@commitlint/is-ignored@21.0.1': + resolution: {integrity: sha512-iNDP8SFdw8JEkM0CHZ2XFnhTN4Zg5jKUY2d8kBOSFrI2aA+3YJI7fcqVpfgbpJ9xtxFVYpi+DBATU5AvhoTq8g==} + engines: {node: '>=22.12.0'} - '@commitlint/lint@20.5.0': - resolution: {integrity: sha512-jiM3hNUdu04jFBf1VgPdjtIPvbuVfDTBAc6L98AWcoLjF5sYqkulBHBzlVWll4rMF1T5zeQFB6r//a+s+BBKlA==} - engines: {node: '>=v18'} + '@commitlint/lint@21.0.1': + resolution: {integrity: sha512-gF+iYtUw1gBG3HUH9z3VxwUjGg2R2G5j+nmvPs8aIeYkiB7TtneBu3wO85I0bUl93bYNsvsCNI9Nte2fmDUMww==} + engines: {node: '>=22.12.0'} - '@commitlint/load@20.5.2': - resolution: {integrity: sha512-zmr0RGDz7vThxW1I8ohb9yBjnGuH9mqwJpn21hInjGla+IlLOkS9ey0+dD5HlkzFlY0lX2NYdA2lDW6/0rO7Gw==} - engines: {node: '>=v18'} + '@commitlint/load@21.0.1': + resolution: {integrity: sha512-Btg1q1mKmiihN4W3x0EsPDrJMOQfMa9NIqlzlJyXAfxvsOGdGXOW5p3R3RcSxDCaY7JabY9flIl+Om1af3PSrw==} + engines: {node: '>=22.12.0'} - '@commitlint/message@20.4.3': - resolution: {integrity: sha512-6akwCYrzcrFcTYz9GyUaWlhisY4lmQ3KvrnabmhoeAV8nRH4dXJAh4+EUQ3uArtxxKQkvxJS78hNX2EU3USgxQ==} - engines: {node: '>=v18'} + '@commitlint/message@21.0.1': + resolution: {integrity: sha512-R3dVQeJQ0B6yqrZEjkUHD4r7UJYLV9Lvk2xs3PTOmtWk2G3mI6Xgc+YdRxL1PwcDfBiUjv2SkIkW4AUc976w1w==} + engines: {node: '>=22.12.0'} - '@commitlint/parse@20.5.0': - resolution: {integrity: sha512-SeKWHBMk7YOTnnEWUhx+d1a9vHsjjuo6Uo1xRfPNfeY4bdYFasCH1dDpAv13Lyn+dDPOels+jP6D2GRZqzc5fA==} - engines: {node: '>=v18'} + '@commitlint/parse@21.0.1': + resolution: {integrity: sha512-oh/nCSOqdoeQNA1tO8aAmxkq5EBo8/NzcFQRvv66AWc9HpED28sL2iSicCKU6hPintWuscL6BJEWi77Wq1LPMQ==} + engines: {node: '>=22.12.0'} - '@commitlint/read@20.5.0': - resolution: {integrity: sha512-JDEIJ2+GnWpK8QqwfmW7O42h0aycJEWNqcdkJnyzLD11nf9dW2dWLTVEa8Wtlo4IZFGLPATjR5neA5QlOvIH1w==} - engines: {node: '>=v18'} + '@commitlint/read@21.0.1': + resolution: {integrity: sha512-pMEu4lbpC8W0ZgKJj2U6WaobXIZWdFlULpIEewYhkPXx+WZcnoO53YrVPc7QErQuNolq2Me8dP58Wu7YAVXVOA==} + engines: {node: '>=22.12.0'} - '@commitlint/resolve-extends@20.5.2': - resolution: {integrity: sha512-8EhSCU9eNos/5cI1yg64GW79UH1c64O69AfStCsj4zqy6An/qIphVEXj4/+2M6056T8coz00f+UXFn4WUUP1HQ==} - engines: {node: '>=v18'} + '@commitlint/resolve-extends@21.0.1': + resolution: {integrity: sha512-0DhjYWL6uYrY16Efa032fYk3woGJDU4AGWiG1XXltT9AMUNYKyb5cIZU2ivbaMZ3+kKFqUjikD2cjh66Sbh/Sg==} + engines: {node: '>=22.12.0'} - '@commitlint/rules@20.5.0': - resolution: {integrity: sha512-5NdQXQEdnDPT5pK8O39ZA7HohzPRHEsDGU23cyVCNPQy4WegAbAwrQk3nIu7p2sl3dutPk8RZd91yKTrMTnRkQ==} - engines: {node: '>=v18'} + '@commitlint/rules@21.0.1': + resolution: {integrity: sha512-VMooYpz4nJg7xlaUso6CCOWEz8D/ChkvsvZUMARcoJ1ZpfKPyFCGrHNha2tbsETNAb6ErgiRuCr2DvghrvPDYQ==} + engines: {node: '>=22.12.0'} - '@commitlint/to-lines@20.0.0': - resolution: {integrity: sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw==} - engines: {node: '>=v18'} + '@commitlint/to-lines@21.0.1': + resolution: {integrity: sha512-bd1BFII7p1EQZre9Kaj+kKaMFP3cFCdt21K7DItVux9XP5WjLgJ0/Uy1pJJh9aPwVJ6SKg62PxqlZaHI8hQAXw==} + engines: {node: '>=22.12.0'} - '@commitlint/top-level@20.4.3': - resolution: {integrity: sha512-qD9xfP6dFg5jQ3NMrOhG0/w5y3bBUsVGyJvXxdWEwBm8hyx4WOk3kKXw28T5czBYvyeCVJgJJ6aoJZUWDpaacQ==} - engines: {node: '>=v18'} + '@commitlint/top-level@21.0.1': + resolution: {integrity: sha512-4esUYqzY7K0FCgcJ/1xWEZekV7Ch4yZT1+xjEb7KzqbJ05XEkxHVsTfC8ADKNNtlCE2pj98KEbPGZWw9WwEnVw==} + engines: {node: '>=22.12.0'} - '@commitlint/types@20.5.0': - resolution: {integrity: sha512-ZJoS8oSq2CAZEpc/YI9SulLrdiIyXeHb/OGqGrkUP6Q7YV+0ouNAa7GjqRdXeQPncHQIDz/jbCTlHScvYvO/gA==} - engines: {node: '>=v18'} + '@commitlint/types@21.0.1': + resolution: {integrity: sha512-4u7w8jcoCUFWhjWnASYzZHAP34OqOtuFBN87nQmFvqda03YU0T6z+yB4w0gSAMpekiRqqGk5rt+qSlW+a2vSEg==} + engines: {node: '>=22.12.0'} '@conventional-changelog/git-client@2.7.0': resolution: {integrity: sha512-j7A8/LBEQ+3rugMzPXoKYzyUPpw/0CBQCyvtTR7Lmu4olG4yRC/Tfkq79Mr3yuPs0SUitlO2HwGP3gitMJnRFw==} @@ -557,8 +557,8 @@ packages: '@iconify-json/ic@1.2.4': resolution: {integrity: sha512-pzPMmrZrBQuwT7nmtrYdkttun8KalRGgZPIL1Ny9KpF2zjRGIUPN+npTfuD3lrgO/OnSwAoJWuekQwBpt/Cqrw==} - '@iconify-json/material-icon-theme@1.2.61': - resolution: {integrity: sha512-g/JUDumQ0h7wdUffYSmeMP8qSi+iKRK9DUtIttHG9gIlz2KJFbu1bakx9B2qzk8n3mw7FE/tZPMNCwIPksVr0g==} + '@iconify-json/material-icon-theme@1.2.64': + resolution: {integrity: sha512-YUTQ7IQ919XwcSz7qKDixj5+63PD8lDgimtRtQwo5clcLZAwf9SyzeUOTLTPR17plPNo0xjlgDi4UcMXfz2xFQ==} '@iconify-json/solar@1.2.5': resolution: {integrity: sha512-WMAiNwchU8zhfrySww6KQBRIBbsQ6SvgIu2yA+CHGyMima/0KQwT5MXogrZPJGoQF+1Ye3Qj6K+1CiyNn3YkoA==} @@ -566,18 +566,23 @@ packages: '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} - '@iconify/utils@3.1.1': - resolution: {integrity: sha512-MwzoDtw9rO1x+qfgLTV/IVXsHDBqeYZoMIQC8SfxfYSlaSUG+oWiAcoiB1yajAda6mqblm4/1/w2E8tRu7a7Tw==} + '@iconify/utils@3.1.3': + resolution: {integrity: sha512-LPKOXPn/zV+zis1oOfGWogaXVpqUybF3ZS6SCZIsz8vg0ivVp9+fVqyYB7xq0aiST/VhUQYGO1qo6uoYSiEJqw==} - '@inlang/paraglide-js@2.17.0': - resolution: {integrity: sha512-dY4yoQkQkF1En1m3qpO22cVGubluU2W78fatLb33s8qe6K8wDqP0mIGZ/oZ0/h609YC8/Y0CkceaLcYeJTcpwg==} + '@inlang/paraglide-js@2.18.0': + resolution: {integrity: sha512-Acp6htA5W7rS2kL3iMjhSr08eECz696MYsud+FBKrmahzM7PdywPVq9UOr9MaC/aV7AZPElrYcqYZOOlUri5fg==} hasBin: true + peerDependencies: + typescript: '>=5' + peerDependenciesMeta: + typescript: + optional: true '@inlang/recommend-sherlock@0.2.1': resolution: {integrity: sha512-ckv8HvHy/iTqaVAEKrr+gnl+p3XFNwe5D2+6w6wJk2ORV2XkcRkKOJ/XsTUJbPSiyi4PI+p+T3bqbmNx/rDUlg==} - '@inlang/sdk@2.9.2': - resolution: {integrity: sha512-H/iVZEcOtbowKaiq6yirnUR9eyffAOsXpgwWr4eAe45H7l1f1A1Wowb7hVkWQcAE62sL1g76qN4XkyOx2BkV2w==} + '@inlang/sdk@2.9.3': + resolution: {integrity: sha512-E/SxcSji8WIt4DqQG9APlOs6tVtJxrrOUS3dE4ho3pWRCLLIY0PIVzgNwSukuFT+m8LuJDFwpRY5VY3ryzyGWQ==} engines: {node: '>=20.0.0'} '@isaacs/ttlcache@1.4.1': @@ -674,70 +679,90 @@ packages: resolution: {integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==} engines: {node: '>= 20'} - '@octokit/request@10.0.8': - resolution: {integrity: sha512-SJZNwY9pur9Agf7l87ywFi14W+Hd9Jg6Ifivsd33+/bGUQIjNujdFiXII2/qSlN2ybqUHfp5xpekMEjIBTjlSw==} + '@octokit/request@10.0.9': + resolution: {integrity: sha512-o8Bi3f608eyM+7BmBiUWxFsdjLb3/ym1cQek5LZOv9KkZcxRrHCPhhRzm6xjO6HVZ85ItD6+sTsjxo821SVa/A==} engines: {node: '>= 20'} '@octokit/types@16.0.0': resolution: {integrity: sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==} - '@oven/bun-darwin-aarch64@1.3.13': - resolution: {integrity: sha512-qAS6Hg8Q14ckfBuqJ2Zh7gBQSVSUHeibSq4OFqBTv6DzyJuxYlr0sdYQzmYmnbPxbqobekqUDTa/4XEaqRi7vg==} + '@oven/bun-darwin-aarch64@1.3.14': + resolution: {integrity: sha512-Omj20SuiHBOUjUBIyqtkNjSUIjOtEOJwmbix/ZyFH4BaQ6OZTaaRWIR4TjHVz0yadHgli6lLTiAh1uarnvD49A==} cpu: [arm64] os: [darwin] - '@oven/bun-darwin-x64-baseline@1.3.13': - resolution: {integrity: sha512-gMEQayUpmCPYaE9zkNBj9TiQqHupnhjOYcuSzxFjzIjHJBUO4VjNnrpbKVeXNs+rKHFothORDd2QKquu5paSPQ==} + '@oven/bun-darwin-x64-baseline@1.3.14': + resolution: {integrity: sha512-OSfsTZstc898HHElhU4NccaBGOSSDn5VfahiVTnidZ9B/+wb7WTyfZJaBeJcfjwJ9H2W9uTh2TGtl3UfcXgV9g==} cpu: [x64] os: [darwin] - '@oven/bun-darwin-x64@1.3.13': - resolution: {integrity: sha512-kGePeDD4IN4imo+H4uLjQGZLmvyYQg+nKr2P0nt4ksXXrWA4HE+mb0/TUPHfRI127DocXQpew+fvrHuHR5mpJQ==} + '@oven/bun-darwin-x64@1.3.14': + resolution: {integrity: sha512-FFj3QdU/OhlDyZOJ8CWfN5eWLpRlT4qjZg7lMQi7jA6GuoY5ajlO1zWLP/MuHYRSbXQUvV52RejNi8DVnAp13w==} cpu: [x64] os: [darwin] - '@oven/bun-linux-aarch64-musl@1.3.13': - resolution: {integrity: sha512-UV9EE18VE5aRhWtV2L6MTAGGn3slhJJ2OW/m+FJM15maHm0qf1V7TaZY0FovxhdQRvnklSiQ7Ntv0H5TUX4w0g==} + '@oven/bun-freebsd-aarch64@1.3.14': + resolution: {integrity: sha512-LIKrXaFxAHybVO5Pf+9XP2FHUj/5APvXTUKk9dqHm5iFz4oH+W24cmhjkJirNujh9hKeTyrpWSe3no9JZKowIw==} + cpu: [arm64] + os: [freebsd] + + '@oven/bun-freebsd-x64@1.3.14': + resolution: {integrity: sha512-uwD+fGUH1ADpIF3B1U2jWzzb20QwRLZfj5QZ28GUCGrAJ/nTmWrD6YYGsblCY1wuhldRez3lU40AyuvSCyLYmw==} + cpu: [x64] + os: [freebsd] + + '@oven/bun-linux-aarch64-android@1.3.14': + resolution: {integrity: sha512-y4kq5b85lsrmFb9Xvi4w9mA5IEFJkLMrSmYn06q24KjL9rUWDWO3VFZEtteZxUN5+ec3Zm5S8OnJw1umaCbVjA==} + cpu: [arm64] + os: [android] + + '@oven/bun-linux-aarch64-musl@1.3.14': + resolution: {integrity: sha512-jmqOA92Cd1NL/1XBd4bFkJLxQ86K0RW7ohxS2qzzAvuitO4JiIxjjTeCspoU44zCozH72HpfZfUE2On31OjnWA==} cpu: [arm64] os: [linux] - '@oven/bun-linux-aarch64@1.3.13': - resolution: {integrity: sha512-NbLOJdr+RBFO1vFZ2YUFg4oVJ+2ua6zrwo4ZWRs0jKKcGJWtbY2wY5uz+i0PkwH6b9HYaYDgVTzE4ev06ncYZw==} + '@oven/bun-linux-aarch64@1.3.14': + resolution: {integrity: sha512-X5SsPZHs+iYO8R/efIcRtc7gT2Q2DgPfliCxEkx4cXBumwkw0c/EsHMNwH3EgGpCDaZ7IYVPhpCG/xBOQHEwZw==} cpu: [arm64] os: [linux] - '@oven/bun-linux-x64-baseline@1.3.13': - resolution: {integrity: sha512-fOi4ziKzgJG4UrrNd4AicBs6Fu9GY5xOqg+9tC76nuZNDAdSh6++kzab6TNi1Ck0Yzq6zIBIdGit6/0uSbBn8A==} + '@oven/bun-linux-x64-android@1.3.14': + resolution: {integrity: sha512-qe9e1d+3VAEU7nAA2ol9Jvmy/o99PVMSgZhHn7Q/9O3YcDrfEqyQ8zm4zoe5qTEo8HZH0dN03Le0Ys2eQPs7eg==} + cpu: [x64] + os: [android] + + '@oven/bun-linux-x64-baseline@1.3.14': + resolution: {integrity: sha512-q/8EdOC0yUE8FPeoOVq8/Pw5I9/tJaYmUfO/uDUAREx8IUnOJH1RJ5A3BjFqre8pvJoiZA9AovPJq5FnNNjSxA==} cpu: [x64] os: [linux] - '@oven/bun-linux-x64-musl-baseline@1.3.13': - resolution: {integrity: sha512-fqBKuiiWLEu2dVkowZaXgKS98xfrvBqivdoxRtRP3eINcpI1dcelGbsOz+Xphn7tbGAuBiE1/0AelvvvdqS9rg==} + '@oven/bun-linux-x64-musl-baseline@1.3.14': + resolution: {integrity: sha512-n6iE71G4lQE4XkrZhQQcL5YUlxDbnq6nqV7zeQi33PMsLT/0kYE+RvHOtBWZ3w0wMdXZfINmp63hIb9ijUBGtw==} cpu: [x64] os: [linux] - '@oven/bun-linux-x64-musl@1.3.13': - resolution: {integrity: sha512-+VHhE44kEjCXcTFHyc81zfTxL9+vzh9RqIh7gM1iWNhxpctD9kzntbUkP3UTFTwwNjoou1o8VRyxQafvc4OepA==} + '@oven/bun-linux-x64-musl@1.3.14': + resolution: {integrity: sha512-GBCB/k/sIqcr06eTNgg7g46qiUv35Jasx4XiccJ/n7RGqrE4RWUD/XJBbWFprVPjvqd59+QtSnS99XGqvftHfg==} cpu: [x64] os: [linux] - '@oven/bun-linux-x64@1.3.13': - resolution: {integrity: sha512-UwttIUXoe9fS+40OcjoaRHgZw+HCPFqBVWEXkXqAJ3W7wA0XPZrWsoMAD9sGh3TaLqrwdiMo5xPogwpXhOtVXA==} + '@oven/bun-linux-x64@1.3.14': + resolution: {integrity: sha512-7OVTAKvwfPmSbIV1HpdOoVVx5VRc427GuPPne93N6vk4eQBPId9nXmZDh9/zGaKPdbVjVtQSZafWQoUjx38Utw==} cpu: [x64] os: [linux] - '@oven/bun-windows-aarch64@1.3.13': - resolution: {integrity: sha512-+EvdRWRCRg95Xea4M2lqSJFTjzQBTJDQTMlbG8bmwFkVTN16MdmSH7xhfxVQWUOyZBLEpIwuNFIlBBxVCwSUyQ==} + '@oven/bun-windows-aarch64@1.3.14': + resolution: {integrity: sha512-T7s3x/BsVKQObGU6QDkZeI6wKynzqGbBH1yI77jrrj5siElclxr3DQrDIk8CV4G5/SJq2HHq4kpLyYY2DKCSmA==} cpu: [arm64] os: [win32] - '@oven/bun-windows-x64-baseline@1.3.13': - resolution: {integrity: sha512-6gy4hhQSjq/T/S9hC9m3NxY0RY+9Ww+XNlB+8koIMTsMSYEjk7Ho+hFHQz1Bn4W61Ub7Vykufg+jgDgPfa2GFA==} + '@oven/bun-windows-x64-baseline@1.3.14': + resolution: {integrity: sha512-uIjLUC1S9DWgICzuoMba7vurBJnBruE4S5CxnvmZkdqWVXRzx1Rgu636HoH+k0qeaQCFh3jeG3JQ1y6fRHv0sw==} cpu: [x64] os: [win32] - '@oven/bun-windows-x64@1.3.13': - resolution: {integrity: sha512-vqDEFX63ZZQF3YstPSpPD+RxNm5AILPdUuuKpNwsj7ld4NjhdHUYkAmLXDtKNWt9JMRL10bop//W8faY/LV+RQ==} + '@oven/bun-windows-x64@1.3.14': + resolution: {integrity: sha512-mUFWL3BoYkNpjd8e9PqROiFF/1Xeotq20mABJsiQH62jM1g5zqWh4khw1RZ6bX8Q8fWvlPaxG1PjofkmjUi3vg==} cpu: [x64] os: [win32] @@ -871,8 +896,11 @@ packages: '@oxc-project/types@0.124.0': resolution: {integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==} - '@oxc-project/types@0.127.0': - resolution: {integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==} + '@oxc-project/types@0.129.0': + resolution: {integrity: sha512-3oz8m3FGdr2nDXVqmFUw7jolKliC4MoyXYIG2c7gpjBnzUWQpUGIYcXYKxTdTi+N2jusvt610ckTMkxdwHkYEg==} + + '@oxc-project/types@0.130.0': + resolution: {integrity: sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==} '@oxfmt/binding-android-arm-eabi@0.35.0': resolution: {integrity: sha512-BaRKlM3DyG81y/xWTsE6gZiv89F/3pHe2BqX2H4JbiB8HNVlWWtplzgATAE5IDSdwChdeuWLDTQzJ92Lglw3ZA==} @@ -1000,8 +1028,8 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@playwright/test@1.59.1': - resolution: {integrity: sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==} + '@playwright/test@1.60.0': + resolution: {integrity: sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==} engines: {node: '>=18'} hasBin: true @@ -1014,103 +1042,201 @@ packages: '@quansync/fs@1.0.0': resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} - '@rolldown/binding-android-arm64@1.0.0-rc.17': - resolution: {integrity: sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==} + '@rolldown/binding-android-arm64@1.0.0': + resolution: {integrity: sha512-TWMZnRLMe63C2Lhyicviu7ZHaU4kxa6PS3rofvc9GmcvptzNN11BcfQ4Sl7MwTOsisQoa2keB/EBdNCAnUo8vA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-android-arm64@1.0.1': + resolution: {integrity: sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.0-rc.17': - resolution: {integrity: sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==} + '@rolldown/binding-darwin-arm64@1.0.0': + resolution: {integrity: sha512-6XcD+8k0gPVItNagEw78/qqcBDwKcwDYS8V2hRmVsfUSIrd8cWe/CBvRDI5toqFyPfj+FJr6t8U6Xj2P2prEew==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-arm64@1.0.1': + resolution: {integrity: sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-rc.17': - resolution: {integrity: sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==} + '@rolldown/binding-darwin-x64@1.0.0': + resolution: {integrity: sha512-iN/tWVXRQDWvmZlKdceP1Dwug9GDpEymhb9p4xnEe6zvCg5lFmzVljl+1qR1NVx3yfGpr2Na+CuLmv5IU8uzfQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.0-rc.17': - resolution: {integrity: sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==} + '@rolldown/binding-darwin-x64@1.0.1': + resolution: {integrity: sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0': + resolution: {integrity: sha512-jjQMDvvwSOuhOwMszD/klSOjyWMM3zI64hWTj9KT5x4MxRbZAf+7vLQ6qouRhtsLVFHr3f0ILaJAfgENPiQdAQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-freebsd-x64@1.0.1': + resolution: {integrity: sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': - resolution: {integrity: sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==} + '@rolldown/binding-linux-arm-gnueabihf@1.0.0': + resolution: {integrity: sha512-d//Dtg2x6/m3mbV64yUGNnDGNZaDGRpDLLNGerHQUVObuNaIQaaDp25yUiqGXtHEXX+NP2d0wAlmKgpYgIAJ2A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': - resolution: {integrity: sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==} + '@rolldown/binding-linux-arm-gnueabihf@1.0.1': + resolution: {integrity: sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0': + resolution: {integrity: sha512-n7Ofp0mx+aB2cC+Sdy5YtMnXtY9lchnHbY+3Yt0uq9JsWQExf4f5Whu0tK0R8Jdc9S6RchTHjIFY7uc92puOVQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-gnu@1.0.1': + resolution: {integrity: sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': - resolution: {integrity: sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==} + '@rolldown/binding-linux-arm64-musl@1.0.0': + resolution: {integrity: sha512-EIVjy2cgd7uuMMo94FVkBp7F6DhcZAUwNURkSG3RwUmvAXR6s0ISxM81U+IydcZByPG0pZIHsf1b6kTxoFDgJA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-arm64-musl@1.0.1': + resolution: {integrity: sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': - resolution: {integrity: sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==} + '@rolldown/binding-linux-ppc64-gnu@1.0.0': + resolution: {integrity: sha512-JEwwOPcwTLAcpDQlqSmjEmfs63xJnSiUNIGvLcDLUHCWK4XowpS/7c7tUsUH6uT/ct6bMUTdXKfI8967FYj6mg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': - resolution: {integrity: sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==} + '@rolldown/binding-linux-ppc64-gnu@1.0.1': + resolution: {integrity: sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.0.0': + resolution: {integrity: sha512-0wjCFhLrihtAubnT9iA0N++0pSV0z5Hg7tNGdNJ4RFaINceHadoF+kiFGyY1qSSNVIAZtLotG8Ju1bgDPkjnFA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': - resolution: {integrity: sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==} + '@rolldown/binding-linux-s390x-gnu@1.0.1': + resolution: {integrity: sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.0.0': + resolution: {integrity: sha512-Dfn7iak9BcMMePxcoJfpSbWqnEyrp/dRF63/8qW/eHBdOZov6x5aShLLEYGYdIeSJ6vMLK/XCVB+lGIxm41bQA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.0.1': + resolution: {integrity: sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': - resolution: {integrity: sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==} + '@rolldown/binding-linux-x64-musl@1.0.0': + resolution: {integrity: sha512-5/utzzDmD/pD/bmuaUcbTf/sZYy0aztwIVlfpoW1fTjCZ0BaPOMVWGZL1zvgxyi7ZIVYWlxKONHmSbHuiOh8Jw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': - resolution: {integrity: sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==} + '@rolldown/binding-linux-x64-musl@1.0.1': + resolution: {integrity: sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.0.0': + resolution: {integrity: sha512-ouJs8VcUomfLfpbUECqFMRqdV4x6aeAK3MA4m6vTrJJjKyWTV5KnxZx7Jd9G+GlDaQQxubcba00x16OyJ1meig==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': - resolution: {integrity: sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==} + '@rolldown/binding-openharmony-arm64@1.0.1': + resolution: {integrity: sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0': + resolution: {integrity: sha512-E+oHKGiDA+lsKMmFtffDDw91EryDT7uJocrIuCHqhm6bCTM6xFK+3gaCkYOHfPwQr0cCNarSM2xaELoQDz9jJg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': - resolution: {integrity: sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==} + '@rolldown/binding-wasm32-wasi@1.0.1': + resolution: {integrity: sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0': + resolution: {integrity: sha512-yYK02n8Rngo+gbm1y6G0+7jk1sJ/2Wt7K0me0Y7k/ErBpyf+LJ2gFpqWVTcRV1rUepBlQRmpgWkTQCiiwrK0Ow==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-arm64-msvc@1.0.1': + resolution: {integrity: sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': - resolution: {integrity: sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==} + '@rolldown/binding-win32-x64-msvc@1.0.0': + resolution: {integrity: sha512-14bpChMahXRRXiTwahSl+zzHPW6qQTXtkMuJBFlbo+pqSAews2d4BdCSHfrJ/MBsCZtpmTafsY+1QhBzitcmdg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.1': + resolution: {integrity: sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0-rc.17': - resolution: {integrity: sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==} + '@rolldown/pluginutils@1.0.0': + resolution: {integrity: sha512-aKs/3GSWyV0mrhNmt/96/Z3yczC3yvrzYATCiCXQebBsGyYzjNdUphRVLeJQ67ySKVXRfMxt2lm12pmXvbPFQQ==} + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} '@rollup/plugin-node-resolve@15.3.1': resolution: {integrity: sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==} @@ -1168,8 +1294,8 @@ packages: peerDependencies: acorn: ^8.9.0 - '@sveltejs/kit@2.58.0': - resolution: {integrity: sha512-kT9GCN8yJTkCK1W+Gi/bvGooWAM7y7WXP+yd+rf6QOIjyoK1ERPrMwSufXJUNu2pMWIqruhFvmz+LbOqsEmKmA==} + '@sveltejs/kit@2.59.1': + resolution: {integrity: sha512-d8OON70AphLdDesuTIl//M2O6fRTIicX8aYv8vhCiYEhTTI2OboKqey0Hu1A4VFhqwgqtq0vKDmPFGkw8kKmgw==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -1184,76 +1310,76 @@ packages: typescript: optional: true - '@sveltejs/vite-plugin-svelte@7.0.0': - resolution: {integrity: sha512-ILXmxC7HAsnkK2eslgPetrqqW1BKSL7LktsFgqzNj83MaivMGZzluWq32m25j2mDOjmSKX7GGWahePhuEs7P/g==} + '@sveltejs/vite-plugin-svelte@7.1.2': + resolution: {integrity: sha512-DrUBA2UXRfDmUX/ZTiEopd3X40yavsJF1FX2RygcuIScHL7o5YX1fMvoYnDhjeJQC4weCOklirpNWlcb2NiSeA==} engines: {node: ^20.19 || ^22.12 || >=24} peerDependencies: svelte: ^5.46.4 vite: ^8.0.0-beta.7 || ^8.0.0 - '@tailwindcss/node@4.2.4': - resolution: {integrity: sha512-Ai7+yQPxz3ddrDQzFfBKdHEVBg0w3Zl83jnjuwxnZOsnH9pGn93QHQtpU0p/8rYWxvbFZHneni6p1BSLK4DkGA==} + '@tailwindcss/node@4.3.0': + resolution: {integrity: sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==} - '@tailwindcss/oxide-android-arm64@4.2.4': - resolution: {integrity: sha512-e7MOr1SAn9U8KlZzPi1ZXGZHeC5anY36qjNwmZv9pOJ8E4Q6jmD1vyEHkQFmNOIN7twGPEMXRHmitN4zCMN03g==} + '@tailwindcss/oxide-android-arm64@4.3.0': + resolution: {integrity: sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==} engines: {node: '>= 20'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.2.4': - resolution: {integrity: sha512-tSC/Kbqpz/5/o/C2sG7QvOxAKqyd10bq+ypZNf+9Fi2TvbVbv1zNpcEptcsU7DPROaSbVgUXmrzKhurFvo5eDg==} + '@tailwindcss/oxide-darwin-arm64@4.3.0': + resolution: {integrity: sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==} engines: {node: '>= 20'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.2.4': - resolution: {integrity: sha512-yPyUXn3yO/ufR6+Kzv0t4fCg2qNr90jxXc5QqBpjlPNd0NqyDXcmQb/6weunH/MEDXW5dhyEi+agTDiqa3WsGg==} + '@tailwindcss/oxide-darwin-x64@4.3.0': + resolution: {integrity: sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==} engines: {node: '>= 20'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.2.4': - resolution: {integrity: sha512-BoMIB4vMQtZsXdGLVc2z+P9DbETkiopogfWZKbWwM8b/1Vinbs4YcUwo+kM/KeLkX3Ygrf4/PsRndKaYhS8Eiw==} + '@tailwindcss/oxide-freebsd-x64@4.3.0': + resolution: {integrity: sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==} engines: {node: '>= 20'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.4': - resolution: {integrity: sha512-7pIHBLTHYRAlS7V22JNuTh33yLH4VElwKtB3bwchK/UaKUPpQ0lPQiOWcbm4V3WP2I6fNIJ23vABIvoy2izdwA==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0': + resolution: {integrity: sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==} engines: {node: '>= 20'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.2.4': - resolution: {integrity: sha512-+E4wxJ0ZGOzSH325reXTWB48l42i93kQqMvDyz5gqfRzRZ7faNhnmvlV4EPGJU3QJM/3Ab5jhJ5pCRUsKn6OQw==} + '@tailwindcss/oxide-linux-arm64-gnu@4.3.0': + resolution: {integrity: sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-arm64-musl@4.2.4': - resolution: {integrity: sha512-bBADEGAbo4ASnppIziaQJelekCxdMaxisrk+fB7Thit72IBnALp9K6ffA2G4ruj90G9XRS2VQ6q2bCKbfFV82g==} + '@tailwindcss/oxide-linux-arm64-musl@4.3.0': + resolution: {integrity: sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [musl] - '@tailwindcss/oxide-linux-x64-gnu@4.2.4': - resolution: {integrity: sha512-7Mx25E4WTfnht0TVRTyC00j3i0M+EeFe7wguMDTlX4mRxafznw0CA8WJkFjWYH5BlgELd1kSjuU2JiPnNZbJDA==} + '@tailwindcss/oxide-linux-x64-gnu@4.3.0': + resolution: {integrity: sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-x64-musl@4.2.4': - resolution: {integrity: sha512-2wwJRF7nyhOR0hhHoChc04xngV3iS+akccHTGtz965FwF0up4b2lOdo6kI1EbDaEXKgvcrFBYcYQQ/rrnWFVfA==} + '@tailwindcss/oxide-linux-x64-musl@4.3.0': + resolution: {integrity: sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [musl] - '@tailwindcss/oxide-wasm32-wasi@4.2.4': - resolution: {integrity: sha512-FQsqApeor8Fo6gUEklzmaa9994orJZZDBAlQpK2Mq+DslRKFJeD6AjHpBQ0kZFQohVr8o85PPh8eOy86VlSCmw==} + '@tailwindcss/oxide-wasm32-wasi@4.3.0': + resolution: {integrity: sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -1264,24 +1390,24 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.2.4': - resolution: {integrity: sha512-L9BXqxC4ToVgwMFqj3pmZRqyHEztulpUJzCxUtLjobMCzTPsGt1Fa9enKbOpY2iIyVtaHNeNvAK8ERP/64sqGQ==} + '@tailwindcss/oxide-win32-arm64-msvc@4.3.0': + resolution: {integrity: sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==} engines: {node: '>= 20'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.2.4': - resolution: {integrity: sha512-ESlKG0EpVJQwRjXDDa9rLvhEAh0mhP1sF7sap9dNZT0yyl9SAG6T7gdP09EH0vIv0UNTlo6jPWyujD6559fZvw==} + '@tailwindcss/oxide-win32-x64-msvc@4.3.0': + resolution: {integrity: sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==} engines: {node: '>= 20'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.2.4': - resolution: {integrity: sha512-9El/iI069DKDSXwTvB9J4BwdO5JhRrOweGaK25taBAvBXyXqJAX+Jqdvs8r8gKpsI/1m0LeJLyQYTf/WLrBT1Q==} + '@tailwindcss/oxide@4.3.0': + resolution: {integrity: sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==} engines: {node: '>= 20'} - '@tailwindcss/postcss@4.2.4': - resolution: {integrity: sha512-wgAVj6nUWAolAu8YFvzT2cTBIElWHkjZwFYovF+xsqKsW2ADxM/X2opxj5NsF/qVccAOjRNe8X2IdPzMsWyHTg==} + '@tailwindcss/postcss@4.3.0': + resolution: {integrity: sha512-Jm05Tjx+9yCLGv5qw1c+84Psds8MnyrEQYCB+FFk2lgGiUjlRqdxke4mVTuYrj2xnVZqKim2Apr5ySuQRYAw/w==} '@testing-library/svelte-core@1.0.0': resolution: {integrity: sha512-VkUePoLV6oOYwSUvX6ShA8KLnJqZiYMIbP2JW2t0GLWLkJxKGvuH5qrrZBV/X7cXFnLGuFQEC7RheYiZOW68KQ==} @@ -1311,11 +1437,11 @@ packages: '@tsconfig/svelte@5.0.8': resolution: {integrity: sha512-UkNnw1/oFEfecR8ypyHIQuWYdkPvHiwcQ78sh+ymIiYoF+uc5H1UBetbjyqT+vgGJ3qQN6nhucJviX6HesWtKQ==} - '@tybys/wasm-util@0.10.1': - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@tybys/wasm-util@0.10.2': + resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} - '@types/bun@1.3.13': - resolution: {integrity: sha512-9fqXWk5YIHGGnUau9TEi+qdlTYDAnOj+xLCmSTwXfAIqXr2x4tytJb43E9uCvt09zJURKXwAtkoH4nLQfzeTXw==} + '@types/bun@1.3.14': + resolution: {integrity: sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw==} '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} @@ -1332,14 +1458,14 @@ packages: '@types/esrecurse@4.3.1': resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@25.6.0': - resolution: {integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==} + '@types/node@25.7.0': + resolution: {integrity: sha512-z+pdZyxE+RTQE9AcboAZCb4otwcrvgHD+GlBpPgn0emDVt0ohrTMhAwlr2Wd9nZ+nihhYFxO2pThz3C5qSu2Eg==} '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -1347,63 +1473,63 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@typescript-eslint/eslint-plugin@8.59.1': - resolution: {integrity: sha512-BOziFIfE+6osHO9FoJG4zjoHUcvI7fTNBSpdAwrNH0/TLvzjsk2oo8XSSOT2HhqUyhZPfHv4UOffoJ9oEEQ7Ag==} + '@typescript-eslint/eslint-plugin@8.59.3': + resolution: {integrity: sha512-PwFvSKsXGShKGW6n5bZOhGHEcCZXM8HofLK9fNsEwZXzFRjoY+XT1Vsf1zgyXdwTr0ZYz1/2tkZ0DBTT9jZjhw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.59.1 + '@typescript-eslint/parser': ^8.59.3 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.59.1': - resolution: {integrity: sha512-HDQH9O/47Dxi1ceDhBXdaldtf/WV9yRYMjbjCuNk3qnaTD564qwv61Y7+gTxwxRKzSrgO5uhtw584igXVuuZkA==} + '@typescript-eslint/parser@8.59.3': + resolution: {integrity: sha512-HPwA+hVkfcriajbNvTmZv4VRauibay+cWArYUYq7u7W7PmGShMxbPxLvrwDme55a6d5alG3nrYfhyJ/G28XlLg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.59.1': - resolution: {integrity: sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg==} + '@typescript-eslint/project-service@8.59.3': + resolution: {integrity: sha512-ECiUWa/KYRGDFUqTNehaRgzDshnJfkTABJxVemHk4ko22gcr0ukloKjWvyQ64g8YCV/UI47kN1dbmjf/GaQYng==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.59.1': - resolution: {integrity: sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg==} + '@typescript-eslint/scope-manager@8.59.3': + resolution: {integrity: sha512-t2LvZnoEfzKtnPjgeEu41xw5gxq9mQVfYy4OoZ4Vlt0sk3JwxmhCca/AR7DwOiHrjWgjAj6as4AhRLKSDfvZIA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.59.1': - resolution: {integrity: sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA==} + '@typescript-eslint/tsconfig-utils@8.59.3': + resolution: {integrity: sha512-PcIJHjmaREXLgIAIzLnSY9VucEzz8FKXsRgFa1DmdGCK/5tJpW03TKJF01Q6VZd1lLdz2sIKPWaDUZN9dp//dw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.59.1': - resolution: {integrity: sha512-klWPBR2ciQHS3f++ug/mVnWKPjBUo7icEL3FAO1lhAR1Z1i5NQYZ1EannMSRYcq5qCv5wNALlXr6fksRHyYl7w==} + '@typescript-eslint/type-utils@8.59.3': + resolution: {integrity: sha512-g71d8QD8UaiHGvrJwyIS1hCX5r63w6Jll+4VEYhEAHXTDIqX1JgxhTAbEHtKntL9kuc4jRo7/GWw5xfCepSccQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.59.1': - resolution: {integrity: sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A==} + '@typescript-eslint/types@8.59.3': + resolution: {integrity: sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.59.1': - resolution: {integrity: sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g==} + '@typescript-eslint/typescript-estree@8.59.3': + resolution: {integrity: sha512-CbRjVRAf7Lr9Kr8RopKcbY45p2VfmmHrm0ygOCYFi7oU8q19m0Fs/6iHS7kNOmwpp+ob07ZVcAqlxUod9lYdmg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.59.1': - resolution: {integrity: sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA==} + '@typescript-eslint/utils@8.59.3': + resolution: {integrity: sha512-JAvT14goBzRzzzZyqq3P9BLArIxTtQURUtFgQ/V7FO+eU+Gg6ES+5ymOPP1wRxXcxAYeivCk4uS3jCKWI1K8Zg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.59.1': - resolution: {integrity: sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg==} + '@typescript-eslint/visitor-keys@8.59.3': + resolution: {integrity: sha512-f1UQF7ggd42YiwI5wGrRaPsa+P0CINBlrkLPmGfpq/u/I/oVtecoEIfFR9ag/oa1sLOsRNZ6xehf6qMZhQGBDg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@unocss/cli@66.6.8': @@ -1490,31 +1616,31 @@ packages: peerDependencies: vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 || ^8.0.0-0 - '@vitest/browser-playwright@4.1.5': - resolution: {integrity: sha512-CWy0lBQJq97nionyJJdnaU4961IXTl43a7UCu5nHy51IoKxAt6PVIJLo+76rVl7KOOgcWHNkG4kbJu/pW7knvA==} + '@vitest/browser-playwright@4.1.6': + resolution: {integrity: sha512-4csoeyl/qwHyxU2zNL0++WaoDr8YJDXOQPwWPNJoTZ+QzcdO3INYKgF5Zfz730Io7zbkuv914aZmfQ+QE+1Hvw==} peerDependencies: playwright: '*' - vitest: 4.1.5 + vitest: 4.1.6 - '@vitest/browser@4.1.5': - resolution: {integrity: sha512-iCDGI8c4yg+xmjUg2VsygdAUSIIB4x5Rht/P68OXy1hPELKXHDkzh87lkuTcdYmemRChDkEpB426MmDjzC0ziA==} + '@vitest/browser@4.1.6': + resolution: {integrity: sha512-ynsspTubXGSpa58JFJ24xIQt4z4A25epSbugEyaTmmrV1//Wec9EgE/LtoaC6yxUrXi5P7erGHRrkdZIHaVQuA==} peerDependencies: - vitest: 4.1.5 + vitest: 4.1.6 - '@vitest/coverage-v8@4.1.5': - resolution: {integrity: sha512-38C0/Ddb7HcRG0Z4/DUem8x57d2p9jYgp18mkaYswEOQBGsI1CG4f/hjm0ZCeaJfWhSZ4k7jgs29V1Zom7Ki9A==} + '@vitest/coverage-v8@4.1.6': + resolution: {integrity: sha512-36l628fQ/9a/8ihy97eOtEnvWQEdqULQOJtcaxtoNq0G1w3Mxd4szSahOaMM9/NGyZ+hyKcMtIW/WIxq0XQViQ==} peerDependencies: - '@vitest/browser': 4.1.5 - vitest: 4.1.5 + '@vitest/browser': 4.1.6 + vitest: 4.1.6 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@4.1.5': - resolution: {integrity: sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==} + '@vitest/expect@4.1.6': + resolution: {integrity: sha512-7EHDquPthALSV0jhhjgEW8FXaviMx7rSqu8W6oqCoAuOhKov814P99QDV1pxMA3QPv21YudvJngIhjrNI4opLg==} - '@vitest/mocker@4.1.5': - resolution: {integrity: sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==} + '@vitest/mocker@4.1.6': + resolution: {integrity: sha512-MCFc63czMjEInOlcY2cpQCvCN+KgbAn+60xu9cMgP4sKaLC5JNAKw7JH8QdAnoAC88hW1IiSNZ+GgVXlN1UcMQ==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1524,20 +1650,20 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.5': - resolution: {integrity: sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==} + '@vitest/pretty-format@4.1.6': + resolution: {integrity: sha512-h5SxD/IzNhZYnrSZRsUZQIC+vD0GY8cUvq0iwsmkFKixRCKLLWqCXa/FIQ4S1R+sI+PGoojkHsdNrbZiM9Qpgw==} - '@vitest/runner@4.1.5': - resolution: {integrity: sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==} + '@vitest/runner@4.1.6': + resolution: {integrity: sha512-nOPCmn2+yD0ZNmKdsXGv/UxMMWbMuKeD6GyYncNwdkYDxpQvrPSKYj2rWuDjC2Y4b6w6hjip5dBKFzEUuZe3vA==} - '@vitest/snapshot@4.1.5': - resolution: {integrity: sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==} + '@vitest/snapshot@4.1.6': + resolution: {integrity: sha512-YhsdE6xAVfTDmzjxL2ZDUvjj+ZsgyOKe+TdQzqkD72wIOmHka8NuGQ6NpTNZv9D2Z63fbwWKJPeVpEw4EQgYxw==} - '@vitest/spy@4.1.5': - resolution: {integrity: sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==} + '@vitest/spy@4.1.6': + resolution: {integrity: sha512-JFKxMx6udhwKh/Ldo270e17QX710vgunMkuPAvXjHSvC6oqLWAHhVhjg/I71q0u0CBSErIODV1Kjv0FQNSWjdg==} - '@vitest/utils@4.1.5': - resolution: {integrity: sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==} + '@vitest/utils@4.1.6': + resolution: {integrity: sha512-FxIY+U81R3LGKCxaHHFRQ5+g6/iRgGLmeHWdp2Amj4ljQRrEIWHmZyDfDYBRZlpyqA7qKxtS9DD1dhk8RnRIVQ==} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} @@ -1559,24 +1685,16 @@ packages: resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} engines: {node: '>=18'} - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - ansi-regex@6.2.2: resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - ansi-styles@6.2.3: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} - apexcharts@5.10.6: - resolution: {integrity: sha512-FJQGbso3iRuOwUYnj0yUhkWeKeJE6aboVol+ae09lsc+lbLMWZqSRbrAWVa/qishLiaeG2icxdvmVkm+9n6kOQ==} + apexcharts@5.11.0: + resolution: {integrity: sha512-iIXnZ1DhndVgY4G5fmAbyUtGBTR5j4LlMEb561eAd4+wkJB7wJXXKLMr9u+4V5aQEPXeVYWgkAbuw9Y1z6MIrg==} argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1618,17 +1736,17 @@ packages: brace-expansion@2.1.0: resolution: {integrity: sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==} - brace-expansion@5.0.5: - resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + brace-expansion@5.0.6: + resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} engines: {node: 18 || 20 || >=22} - bun-types@1.3.13: - resolution: {integrity: sha512-QXKeHLlOLqQX9LgYaHJfzdBaV21T63HhFJnvuRCcjZiaUDpbs5ED1MgxbMra71CsryN/1dAoXuJJJwIv/2drVA==} + bun-types@1.3.14: + resolution: {integrity: sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ==} - bun@1.3.13: - resolution: {integrity: sha512-b9T4xZ8KqCHs4+TkHJv540LG1B8OD7noKu0Qaizusx3jFtMDHY6osNqgbaOlwW2B8RB2AKzz+sjzlGKIGxIjZw==} + bun@1.3.14: + resolution: {integrity: sha512-aB6GVd42x1Y5ie1K16SF+oLGtgSkwX9hgoDdIW88pjvfTccU8F1vfpoOt34QLv0dZ1v3XimtaxPlZUG81Gx9Zg==} cpu: [arm64, x64] - os: [darwin, linux, win32] + os: [darwin, linux, android, freebsd, win32] hasBin: true cac@7.0.0: @@ -1663,21 +1781,14 @@ packages: resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} engines: {node: '>=20'} - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} + cliui@9.0.1: + resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} + engines: {node: '>=20'} clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} @@ -1707,6 +1818,10 @@ packages: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} + content-type@2.0.0: + resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} + engines: {node: '>=18'} + conventional-changelog-angular@8.3.1: resolution: {integrity: sha512-6gfI3otXK5Ph5DfCOI1dblr+kN3FAm5a97hYoQkqNZxOaYa5WKfXH+AnpsmS+iUH2mgVC2Cg2Qw9m5OKcmNrIg==} engines: {node: '>=18'} @@ -1807,8 +1922,8 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} - devalue@5.7.1: - resolution: {integrity: sha512-MUbZ586EgQqdRnC4yDrlod3BEdyvE4TapGYHMW2CiaW+KkkFmWEFqBUaLltEZCGi0iFXCEjRF0OjF0DV2QHjOA==} + devalue@5.8.0: + resolution: {integrity: sha512-2zA9pFEsnp7vWBZbXF5JAgAq0fsUIt/1XPbRiAmRV3lp/2C3upzH+sADiyy66aFCihoLEsrQHxNM5w1gIDfsBg==} dompurify@3.2.7: resolution: {integrity: sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==} @@ -1827,11 +1942,8 @@ packages: emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - enhanced-resolve@5.21.0: - resolution: {integrity: sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==} + enhanced-resolve@5.21.3: + resolution: {integrity: sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==} engines: {node: '>=10.13.0'} env-paths@2.2.1: @@ -1852,6 +1964,9 @@ packages: es-module-lexer@2.1.0: resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} + es-toolkit@1.46.1: + resolution: {integrity: sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==} + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -1930,8 +2045,8 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.2.1: - resolution: {integrity: sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q==} + eslint@10.3.0: + resolution: {integrity: sha512-XbEXaRva5cF0ZQB8w6MluHA0kZZfV2DuCMJ3ozyEOHLwDpZX2Lmm/7Pp0xdJmI0GL1W05VH5VwIFHEm1Vcw2gw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: @@ -1960,8 +2075,8 @@ packages: resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} - esrap@2.2.5: - resolution: {integrity: sha512-/yLB1538mag+dn0wsePTe8C0rDIjUOaJpMs2McodSzmM2msWcZsBSdRtg6HOBt0A/r82BN+Md3pgwSc/uWt2Ig==} + esrap@2.2.8: + resolution: {integrity: sha512-MPweq2EvEGj8jwOI7Hgycw/QIHzqA1EbAM8lG7p+FBfZbZq/hQ6h3AMsqnu/djzisH1KVWNzbb7LSgIVtMlPSg==} peerDependencies: '@typescript-eslint/types': ^8.2.0 peerDependenciesMeta: @@ -2012,8 +2127,8 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-uri@3.1.0: - resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} @@ -2061,8 +2176,8 @@ packages: flowbite@3.1.2: resolution: {integrity: sha512-MkwSgbbybCYgMC+go6Da5idEKUFfMqc/AmSjm/2ZbdmvoKf5frLPq/eIhXc9P+rC8t9boZtUXzHDgt5whZ6A/Q==} - flowbite@4.0.1: - resolution: {integrity: sha512-UwUjvnqrQTiFm3uMJ0WWnzKXKoDyNyfyEzoNnxmZo6KyDzCedjqZw1UW0Oqdn+E0iYVdPu0fizydJN6e4pP9Rw==} + flowbite@4.0.2: + resolution: {integrity: sha512-TxBdfZpd3HktHH4ashiYjirrSZeVPtG1OCRZMKTeXUa9FOlMxSF98zgjMB/AxE49KZ+rlfgWynAlaNpWxrqZmA==} fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} @@ -2081,8 +2196,8 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-east-asian-width@1.5.0: - resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + get-east-asian-width@1.6.0: + resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} engines: {node: '>=18'} get-stream@9.0.1: @@ -2141,8 +2256,8 @@ packages: resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} engines: {node: '>=18'} - globals@17.5.0: - resolution: {integrity: sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==} + globals@17.6.0: + resolution: {integrity: sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==} engines: {node: '>=18'} graceful-fs@4.2.11: @@ -2214,18 +2329,14 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + is-core-module@2.16.2: + resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} engines: {node: '>= 0.4'} is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - is-fullwidth-code-point@5.1.0: resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} engines: {node: '>=18'} @@ -2278,6 +2389,10 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + js-sha256@0.11.1: resolution: {integrity: sha512-o6WSo/LUvY2uC4j7mO50a2ms7E/EAdbP0swigLV+nzHKTTaYnaLIWJ02VdXrsJX0vGedDESQnLsOekr94ryfjg==} @@ -2329,8 +2444,8 @@ packages: known-css-properties@0.37.0: resolution: {integrity: sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==} - kysely@0.28.16: - resolution: {integrity: sha512-3i5pmOiZvMDj00qhrIVbH0AnioVTx22DMP7Vn5At4yJO46iy+FM8Y/g61ltenLVSo3fiO8h8Q3QOFgf/gQ72ww==} + kysely@0.28.17: + resolution: {integrity: sha512-nbD8lB9EB3wNdMhOCdx5Li8DxnLbvKByylRLcJ1h+4SkrowVeECAyZlyiKMThF7xFdRz0jSQ2MoJr+wXux2y0Q==} engines: {node: '>=20.0.0'} levn@0.4.1: @@ -2418,14 +2533,14 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lint-staged@16.4.0: - resolution: {integrity: sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==} - engines: {node: '>=20.17'} + lint-staged@17.0.4: + resolution: {integrity: sha512-+rU9lSUyVOZ/hDUmRLVGzyS2v73cDdQjX+XQz1AaOdIE4RysLq0HoPW2HrrgeNCLklkhi904VBU1bmgWLHVnkA==} + engines: {node: '>=22.22.1'} hasBin: true - listr2@9.0.5: - resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} - engines: {node: '>=20.0.0'} + listr2@10.2.1: + resolution: {integrity: sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==} + engines: {node: '>=22.13.0'} locate-character@3.0.0: resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} @@ -2437,24 +2552,6 @@ packages: lodash-es@4.18.1: resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} - lodash.camelcase@4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - - lodash.kebabcase@4.1.1: - resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} - - lodash.mergewith@4.6.2: - resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} - - lodash.snakecase@4.1.1: - resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} - - lodash.startcase@4.4.0: - resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} - - lodash.upperfirst@4.3.1: - resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} - log-symbols@7.0.1: resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==} engines: {node: '>=18'} @@ -2504,9 +2601,6 @@ packages: resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} engines: {node: '>=16 || 14 >=14.17'} - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - mlly@1.8.2: resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} @@ -2524,8 +2618,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -2630,13 +2724,13 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - playwright-core@1.59.1: - resolution: {integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==} + playwright-core@1.60.0: + resolution: {integrity: sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==} engines: {node: '>=18'} hasBin: true - playwright@1.59.1: - resolution: {integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==} + playwright@1.60.0: + resolution: {integrity: sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==} engines: {node: '>=18'} hasBin: true @@ -2676,8 +2770,8 @@ packages: resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==} engines: {node: '>=4'} - postcss@8.5.12: - resolution: {integrity: sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==} + postcss@8.5.14: + resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -2688,8 +2782,8 @@ packages: resolution: {integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==} engines: {node: '>=6.0.0'} - prettier-plugin-svelte@3.5.1: - resolution: {integrity: sha512-65+fr5+cgIKWKiqM1Doum4uX6bY8iFCdztvvp2RcF+AJoieaw9kJOFMNcJo/bkmKYsxFaM9OsVZK/gWauG/5mg==} + prettier-plugin-svelte@3.5.2: + resolution: {integrity: sha512-ItFouLvzSFE3ulNl4DKoWM3BGcbDCNVpIyy/Y3F2gC3aNiGLxtFUdffVqO5Z5hhYG+DFT5KULWaxmeFFpdbvaQ==} peerDependencies: prettier: ^3.0.0 svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 @@ -2727,10 +2821,6 @@ packages: resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -2755,8 +2845,13 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rolldown@1.0.0-rc.17: - resolution: {integrity: sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==} + rolldown@1.0.0: + resolution: {integrity: sha512-yD986aXDESFGS95spT1LAv0jssywP4npMEjmMHyN2/5+eE8qQJUype2AaKkRiLgBgyD0LFlubwAht7VmY8rGoA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rolldown@1.0.1: + resolution: {integrity: sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -2769,8 +2864,8 @@ packages: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} engines: {node: '>=6'} - semver@7.7.4: - resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + semver@7.8.0: + resolution: {integrity: sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==} engines: {node: '>=10'} hasBin: true @@ -2827,10 +2922,6 @@ packages: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - string-width@7.2.0: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} @@ -2839,10 +2930,6 @@ packages: resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} engines: {node: '>=20'} - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - strip-ansi@7.2.0: resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} engines: {node: '>=12'} @@ -2873,17 +2960,17 @@ packages: '@sveltejs/kit': ^2.4.0 typescript: ^5 - svelte-check@4.4.6: - resolution: {integrity: sha512-kP1zG81EWaFe9ZyTv4ZXv44Csi6Pkdpb7S3oj6m+K2ec/IcDg/a8LsFsnVLqm2nxtkSwsd5xPj/qFkTBgXHXjg==} + svelte-check@4.4.8: + resolution: {integrity: sha512-67adfgBox5eNSNIvIIwgFizKGdcRrGpiMoNO2obHcYuLz7iTa8Xgm/NGU3ntMFnNm8K1grFOIG6HhMLX/vcN8w==} engines: {node: '>= 18.0.0'} hasBin: true peerDependencies: svelte: ^4.0.0 || ^5.0.0-next.0 typescript: '>=5.0.0' - svelte-eslint-parser@1.6.0: - resolution: {integrity: sha512-qoB1ehychT6OxEtQAqc/guSqLS20SlA53Uijl7x375s8nlUT0lb9ol/gzraEEatQwsyPTJo87s2CmKL9Xab+Uw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0, pnpm: 10.30.3} + svelte-eslint-parser@1.6.1: + resolution: {integrity: sha512-hhvSH6kRj46UzrBVO5TaotD+Iuvruj5ccKBcO4wAhVcPTLmIc/c32D8UllBTYO0on4LzYuM0rNzf1lM/gBlkSQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0, pnpm: 10.33.0} peerDependencies: svelte: ^3.37.0 || ^4.0.0 || ^5.0.0 peerDependenciesMeta: @@ -2909,8 +2996,8 @@ packages: resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} engines: {node: ^14.18.0 || >=16.0.0} - tailwind-merge@3.5.0: - resolution: {integrity: sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==} + tailwind-merge@3.6.0: + resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==} tailwind-variants@3.2.2: resolution: {integrity: sha512-Mi4kHeMTLvKlM98XPnK+7HoBPmf4gygdFmqQPaDivc3DpYS6aIY6KiG/PgThrGvii5YZJqRsPz0aPyhoFzmZgg==} @@ -2922,8 +3009,8 @@ packages: tailwind-merge: optional: true - tailwindcss@4.2.4: - resolution: {integrity: sha512-HhKppgO81FQof5m6TEnuBWCZGgfRAWbaeOaGT00KOy/Pf/j6oUihdvBpA7ltCeAvZpFhW3j0PTclkxsd4IXYDA==} + tailwindcss@4.3.0: + resolution: {integrity: sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==} tapable@2.3.3: resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} @@ -2932,8 +3019,8 @@ packages: tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyexec@1.1.1: - resolution: {integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==} + tinyexec@1.1.2: + resolution: {integrity: sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==} engines: {node: '>=18'} tinyglobby@0.2.16: @@ -2972,8 +3059,8 @@ packages: type-level-regexp@0.1.17: resolution: {integrity: sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg==} - typescript-eslint@8.59.1: - resolution: {integrity: sha512-xqDcFVBmlrltH64lklOVp1wYxgJr6LVdg3NamBgH2OOQDLFdTKfIZXF5PfghrnXQKXZGTQs8tr1vL7fJvq8CTQ==} + typescript-eslint@8.59.3: + resolution: {integrity: sha512-KgusgyDgG4LI8Ih/sWaCtZ06tckLAS5CvT5A4D1Q7bYVoAAyzwiZvE4BmwDHkhRVkvhRBepKeASoFzQetha7Fg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 @@ -2984,8 +3071,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - ufo@1.6.3: - resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} unconfig-core@7.5.0: resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} @@ -2993,8 +3080,8 @@ packages: unconfig@7.5.0: resolution: {integrity: sha512-oi8Qy2JV4D3UQ0PsopR28CzdQ3S/5A1zwsUwp/rosSbfhJ5z7b90bIyTwi/F7hCLD4SGcZVjDzd4XoUQcEanvA==} - undici-types@7.19.2: - resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==} + undici-types@7.21.0: + resolution: {integrity: sha512-w9IMgQrz4O0YN1LtB7K5P63vhlIOvC7opSmouCJ+ZywlPAlO9gIkJ+otk6LvGpAs2wg4econaCz3TvQ9xPoyuQ==} undici@6.25.0: resolution: {integrity: sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==} @@ -3043,13 +3130,13 @@ packages: resolution: {integrity: sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==} hasBin: true - vite@8.0.10: - resolution: {integrity: sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==} + vite@8.0.12: + resolution: {integrity: sha512-w2dDofOWv2QB09ZITZBsvKTVAlYvPR4IAmrY/v0ir9KvLs0xybR7i48wxhM1/oyBWO34wPns+bPGw5ZrZqDpZg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.1.0 + '@vitejs/devtools': ^0.1.18 esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' less: ^4.0.0 @@ -3100,20 +3187,20 @@ packages: svelte: ^3 || ^4 || ^5 || ^5.0.0-next.0 vitest: ^4.0.0 - vitest@4.1.5: - resolution: {integrity: sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==} + vitest@4.1.6: + resolution: {integrity: sha512-6lvjbS3p9b4CrdCmguzbh2/4uoXhGE2q71R4OX5sqF9R1bo9Xd6fGrMAfvp5wnCzlBnFVdCOp6onuTQVbo8iUQ==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.5 - '@vitest/browser-preview': 4.1.5 - '@vitest/browser-webdriverio': 4.1.5 - '@vitest/coverage-istanbul': 4.1.5 - '@vitest/coverage-v8': 4.1.5 - '@vitest/ui': 4.1.5 + '@vitest/browser-playwright': 4.1.6 + '@vitest/browser-preview': 4.1.6 + '@vitest/browser-webdriverio': 4.1.6 + '@vitest/coverage-istanbul': 4.1.6 + '@vitest/coverage-v8': 4.1.6 + '@vitest/ui': 4.1.6 happy-dom: '*' jsdom: '*' vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -3158,16 +3245,16 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + wrap-ansi@10.0.0: + resolution: {integrity: sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==} + engines: {node: '>=20'} wrap-ansi@9.0.2: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} - ws@8.20.0: - resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + ws@8.20.1: + resolution: {integrity: sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -3186,18 +3273,18 @@ packages: resolution: {integrity: sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==} engines: {node: '>= 6'} - yaml@2.8.3: - resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} engines: {node: '>= 14.6'} hasBin: true - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} + yargs-parser@22.0.0: + resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} + yargs@18.0.0: + resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} @@ -3227,7 +3314,7 @@ snapshots: '@octokit/core': 7.0.6 '@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.6) '@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.6) - '@octokit/request': 10.0.8 + '@octokit/request': 10.0.9 '@octokit/request-error': 7.1.0 undici: 6.25.0 @@ -3254,7 +3341,7 @@ snapshots: '@antfu/install-pkg@1.1.0': dependencies: package-manager-detector: 1.6.0 - tinyexec: 1.1.1 + tinyexec: 1.1.2 '@babel/code-frame@7.29.0': dependencies: @@ -3264,7 +3351,7 @@ snapshots: '@babel/generator@7.29.1': dependencies: - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.3 '@babel/types': 7.29.0 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 @@ -3276,14 +3363,14 @@ snapshots: '@babel/helper-validator-identifier@7.28.5': {} - '@babel/parser@7.29.2': + '@babel/parser@7.29.3': dependencies: '@babel/types': 7.29.0 '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.3 '@babel/types': 7.29.0 '@babel/traverse@7.29.0': @@ -3291,7 +3378,7 @@ snapshots: '@babel/code-frame': 7.29.0 '@babel/generator': 7.29.1 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.3 '@babel/template': 7.28.6 '@babel/types': 7.29.0 debug: 4.4.3 @@ -3307,116 +3394,110 @@ snapshots: '@blazediff/core@1.9.1': {} - '@commitlint/cli@20.5.2(@types/node@25.6.0)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3)': + '@commitlint/cli@21.0.1(@types/node@25.7.0)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3)': dependencies: - '@commitlint/format': 20.5.0 - '@commitlint/lint': 20.5.0 - '@commitlint/load': 20.5.2(@types/node@25.6.0)(typescript@6.0.3) - '@commitlint/read': 20.5.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) - '@commitlint/types': 20.5.0 - tinyexec: 1.1.1 - yargs: 17.7.2 + '@commitlint/format': 21.0.1 + '@commitlint/lint': 21.0.1 + '@commitlint/load': 21.0.1(@types/node@25.7.0)(typescript@6.0.3) + '@commitlint/read': 21.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) + '@commitlint/types': 21.0.1 + tinyexec: 1.1.2 + yargs: 18.0.0 transitivePeerDependencies: - '@types/node' - conventional-commits-filter - conventional-commits-parser - typescript - '@commitlint/config-conventional@20.5.0': + '@commitlint/config-conventional@21.0.1': dependencies: - '@commitlint/types': 20.5.0 + '@commitlint/types': 21.0.1 conventional-changelog-conventionalcommits: 9.3.1 - '@commitlint/config-validator@20.5.0': + '@commitlint/config-validator@21.0.1': dependencies: - '@commitlint/types': 20.5.0 + '@commitlint/types': 21.0.1 ajv: 8.20.0 - '@commitlint/ensure@20.5.0': + '@commitlint/ensure@21.0.1': dependencies: - '@commitlint/types': 20.5.0 - lodash.camelcase: 4.3.0 - lodash.kebabcase: 4.1.1 - lodash.snakecase: 4.1.1 - lodash.startcase: 4.4.0 - lodash.upperfirst: 4.3.1 + '@commitlint/types': 21.0.1 + es-toolkit: 1.46.1 - '@commitlint/execute-rule@20.0.0': {} + '@commitlint/execute-rule@21.0.1': {} - '@commitlint/format@20.5.0': + '@commitlint/format@21.0.1': dependencies: - '@commitlint/types': 20.5.0 + '@commitlint/types': 21.0.1 picocolors: 1.1.1 - '@commitlint/is-ignored@20.5.0': + '@commitlint/is-ignored@21.0.1': dependencies: - '@commitlint/types': 20.5.0 - semver: 7.7.4 + '@commitlint/types': 21.0.1 + semver: 7.8.0 - '@commitlint/lint@20.5.0': + '@commitlint/lint@21.0.1': dependencies: - '@commitlint/is-ignored': 20.5.0 - '@commitlint/parse': 20.5.0 - '@commitlint/rules': 20.5.0 - '@commitlint/types': 20.5.0 + '@commitlint/is-ignored': 21.0.1 + '@commitlint/parse': 21.0.1 + '@commitlint/rules': 21.0.1 + '@commitlint/types': 21.0.1 - '@commitlint/load@20.5.2(@types/node@25.6.0)(typescript@6.0.3)': + '@commitlint/load@21.0.1(@types/node@25.7.0)(typescript@6.0.3)': dependencies: - '@commitlint/config-validator': 20.5.0 - '@commitlint/execute-rule': 20.0.0 - '@commitlint/resolve-extends': 20.5.2 - '@commitlint/types': 20.5.0 + '@commitlint/config-validator': 21.0.1 + '@commitlint/execute-rule': 21.0.1 + '@commitlint/resolve-extends': 21.0.1 + '@commitlint/types': 21.0.1 cosmiconfig: 9.0.1(typescript@6.0.3) - cosmiconfig-typescript-loader: 6.3.0(@types/node@25.6.0)(cosmiconfig@9.0.1(typescript@6.0.3))(typescript@6.0.3) + cosmiconfig-typescript-loader: 6.3.0(@types/node@25.7.0)(cosmiconfig@9.0.1(typescript@6.0.3))(typescript@6.0.3) + es-toolkit: 1.46.1 is-plain-obj: 4.1.0 - lodash.mergewith: 4.6.2 picocolors: 1.1.1 transitivePeerDependencies: - '@types/node' - typescript - '@commitlint/message@20.4.3': {} + '@commitlint/message@21.0.1': {} - '@commitlint/parse@20.5.0': + '@commitlint/parse@21.0.1': dependencies: - '@commitlint/types': 20.5.0 + '@commitlint/types': 21.0.1 conventional-changelog-angular: 8.3.1 conventional-commits-parser: 6.4.0 - '@commitlint/read@20.5.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)': + '@commitlint/read@21.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)': dependencies: - '@commitlint/top-level': 20.4.3 - '@commitlint/types': 20.5.0 + '@commitlint/top-level': 21.0.1 + '@commitlint/types': 21.0.1 git-raw-commits: 5.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) - minimist: 1.2.8 - tinyexec: 1.1.1 + tinyexec: 1.1.2 transitivePeerDependencies: - conventional-commits-filter - conventional-commits-parser - '@commitlint/resolve-extends@20.5.2': + '@commitlint/resolve-extends@21.0.1': dependencies: - '@commitlint/config-validator': 20.5.0 - '@commitlint/types': 20.5.0 + '@commitlint/config-validator': 21.0.1 + '@commitlint/types': 21.0.1 + es-toolkit: 1.46.1 global-directory: 5.0.0 - import-meta-resolve: 4.2.0 - lodash.mergewith: 4.6.2 resolve-from: 5.0.0 - '@commitlint/rules@20.5.0': + '@commitlint/rules@21.0.1': dependencies: - '@commitlint/ensure': 20.5.0 - '@commitlint/message': 20.4.3 - '@commitlint/to-lines': 20.0.0 - '@commitlint/types': 20.5.0 + '@commitlint/ensure': 21.0.1 + '@commitlint/message': 21.0.1 + '@commitlint/to-lines': 21.0.1 + '@commitlint/types': 21.0.1 - '@commitlint/to-lines@20.0.0': {} + '@commitlint/to-lines@21.0.1': {} - '@commitlint/top-level@20.4.3': + '@commitlint/top-level@21.0.1': dependencies: escalade: 3.2.0 - '@commitlint/types@20.5.0': + '@commitlint/types@21.0.1': dependencies: conventional-commits-parser: 6.4.0 picocolors: 1.1.1 @@ -3425,7 +3506,7 @@ snapshots: dependencies: '@simple-libs/child-process-utils': 1.0.2 '@simple-libs/stream-utils': 1.2.0 - semver: 7.7.4 + semver: 7.8.0 optionalDependencies: conventional-commits-filter: 5.0.0 conventional-commits-parser: 6.4.0 @@ -3452,9 +3533,9 @@ snapshots: tslib: 2.8.1 optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.2.1(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.9.1(eslint@10.3.0(jiti@2.7.0))': dependencies: - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.7.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -3498,7 +3579,7 @@ snapshots: execa: 9.6.1 git-cliff: 2.13.1 js-yaml: 4.1.1 - semver: 7.7.4 + semver: 7.8.0 smol-toml: 1.6.1 '@favware/colorette-spinner@1.0.1': @@ -3536,7 +3617,7 @@ snapshots: dependencies: '@iconify/types': 2.0.0 - '@iconify-json/material-icon-theme@1.2.61': + '@iconify-json/material-icon-theme@1.2.64': dependencies: '@iconify/types': 2.0.0 @@ -3546,21 +3627,23 @@ snapshots: '@iconify/types@2.0.0': {} - '@iconify/utils@3.1.1': + '@iconify/utils@3.1.3': dependencies: '@antfu/install-pkg': 1.1.0 '@iconify/types': 2.0.0 - mlly: 1.8.2 + import-meta-resolve: 4.2.0 - '@inlang/paraglide-js@2.17.0': + '@inlang/paraglide-js@2.18.0(typescript@6.0.3)': dependencies: '@inlang/recommend-sherlock': 0.2.1 - '@inlang/sdk': 2.9.2 + '@inlang/sdk': 2.9.3 commander: 11.1.0 consola: 3.4.0 json5: 2.2.3 unplugin: 2.3.11 urlpattern-polyfill: 10.1.0 + optionalDependencies: + typescript: 6.0.3 transitivePeerDependencies: - babel-plugin-macros @@ -3568,12 +3651,12 @@ snapshots: dependencies: comment-json: 4.6.2 - '@inlang/sdk@2.9.2': + '@inlang/sdk@2.9.3': dependencies: '@lix-js/sdk': 0.4.10 '@sinclair/typebox': 0.31.28 - kysely: 0.28.16 - sqlite-wasm-kysely: 0.3.0(kysely@0.28.16) + kysely: 0.28.17 + sqlite-wasm-kysely: 0.3.0(kysely@0.28.17) uuid: 14.0.0 transitivePeerDependencies: - babel-plugin-macros @@ -3605,8 +3688,8 @@ snapshots: dedent: 1.5.1 human-id: 4.1.3 js-sha256: 0.11.1 - kysely: 0.28.16 - sqlite-wasm-kysely: 0.3.0(kysely@0.28.16) + kysely: 0.28.17 + sqlite-wasm-kysely: 0.3.0(kysely@0.28.17) uuid: 14.0.0 transitivePeerDependencies: - babel-plugin-macros @@ -3625,16 +3708,16 @@ snapshots: dependencies: '@nanoforge-dev/common': 1.1.0 - '@nanoforge-dev/utils-eslint-config@1.0.2(@types/eslint@9.6.1)(eslint@10.2.1(jiti@2.6.1))(prettier@3.8.3)(typescript@6.0.3)': + '@nanoforge-dev/utils-eslint-config@1.0.2(@types/eslint@9.6.1)(eslint@10.3.0(jiti@2.7.0))(prettier@3.8.3)(typescript@6.0.3)': dependencies: '@eslint/js': 9.39.4 '@favware/cliff-jumper': 6.1.0 - eslint-config-prettier: 10.1.8(eslint@10.2.1(jiti@2.6.1)) + eslint-config-prettier: 10.1.8(eslint@10.3.0(jiti@2.7.0)) eslint-formatter-pretty: 7.1.0 - eslint-plugin-format: 1.5.0(eslint@10.2.1(jiti@2.6.1)) - eslint-plugin-prettier: 5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.2.1(jiti@2.6.1)))(eslint@10.2.1(jiti@2.6.1))(prettier@3.8.3) + eslint-plugin-format: 1.5.0(eslint@10.3.0(jiti@2.7.0)) + eslint-plugin-prettier: 5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.3.0(jiti@2.7.0)))(eslint@10.3.0(jiti@2.7.0))(prettier@3.8.3) globals: 16.5.0 - typescript-eslint: 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + typescript-eslint: 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) transitivePeerDependencies: - '@types/eslint' - eslint @@ -3648,7 +3731,7 @@ snapshots: dependencies: '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 - '@tybys/wasm-util': 0.10.1 + '@tybys/wasm-util': 0.10.2 optional: true '@octokit/auth-token@6.0.0': {} @@ -3657,7 +3740,7 @@ snapshots: dependencies: '@octokit/auth-token': 6.0.0 '@octokit/graphql': 9.0.3 - '@octokit/request': 10.0.8 + '@octokit/request': 10.0.9 '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 before-after-hook: 4.0.0 @@ -3670,7 +3753,7 @@ snapshots: '@octokit/graphql@9.0.3': dependencies: - '@octokit/request': 10.0.8 + '@octokit/request': 10.0.9 '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 @@ -3697,11 +3780,12 @@ snapshots: dependencies: '@octokit/types': 16.0.0 - '@octokit/request@10.0.8': + '@octokit/request@10.0.9': dependencies: '@octokit/endpoint': 11.0.3 '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 + content-type: 2.0.0 fast-content-type-parse: 3.0.0 json-with-bigint: 3.5.8 universal-user-agent: 7.0.3 @@ -3710,40 +3794,52 @@ snapshots: dependencies: '@octokit/openapi-types': 27.0.0 - '@oven/bun-darwin-aarch64@1.3.13': + '@oven/bun-darwin-aarch64@1.3.14': optional: true - '@oven/bun-darwin-x64-baseline@1.3.13': + '@oven/bun-darwin-x64-baseline@1.3.14': optional: true - '@oven/bun-darwin-x64@1.3.13': + '@oven/bun-darwin-x64@1.3.14': optional: true - '@oven/bun-linux-aarch64-musl@1.3.13': + '@oven/bun-freebsd-aarch64@1.3.14': optional: true - '@oven/bun-linux-aarch64@1.3.13': + '@oven/bun-freebsd-x64@1.3.14': optional: true - '@oven/bun-linux-x64-baseline@1.3.13': + '@oven/bun-linux-aarch64-android@1.3.14': optional: true - '@oven/bun-linux-x64-musl-baseline@1.3.13': + '@oven/bun-linux-aarch64-musl@1.3.14': optional: true - '@oven/bun-linux-x64-musl@1.3.13': + '@oven/bun-linux-aarch64@1.3.14': optional: true - '@oven/bun-linux-x64@1.3.13': + '@oven/bun-linux-x64-android@1.3.14': optional: true - '@oven/bun-windows-aarch64@1.3.13': + '@oven/bun-linux-x64-baseline@1.3.14': optional: true - '@oven/bun-windows-x64-baseline@1.3.13': + '@oven/bun-linux-x64-musl-baseline@1.3.14': optional: true - '@oven/bun-windows-x64@1.3.13': + '@oven/bun-linux-x64-musl@1.3.14': + optional: true + + '@oven/bun-linux-x64@1.3.14': + optional: true + + '@oven/bun-windows-aarch64@1.3.14': + optional: true + + '@oven/bun-windows-x64-baseline@1.3.14': + optional: true + + '@oven/bun-windows-x64@1.3.14': optional: true '@oxc-parser/binding-android-arm-eabi@0.124.0': @@ -3813,7 +3909,9 @@ snapshots: '@oxc-project/types@0.124.0': {} - '@oxc-project/types@0.127.0': {} + '@oxc-project/types@0.129.0': {} + + '@oxc-project/types@0.130.0': {} '@oxfmt/binding-android-arm-eabi@0.35.0': optional: true @@ -3874,9 +3972,9 @@ snapshots: '@pkgr/core@0.2.9': {} - '@playwright/test@1.59.1': + '@playwright/test@1.60.0': dependencies: - playwright: 1.59.1 + playwright: 1.60.0 '@polka/url@1.0.0-next.29': {} @@ -3886,56 +3984,107 @@ snapshots: dependencies: quansync: 1.0.0 - '@rolldown/binding-android-arm64@1.0.0-rc.17': + '@rolldown/binding-android-arm64@1.0.0': + optional: true + + '@rolldown/binding-android-arm64@1.0.1': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.1': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0': + optional: true + + '@rolldown/binding-darwin-x64@1.0.1': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-rc.17': + '@rolldown/binding-freebsd-x64@1.0.1': optional: true - '@rolldown/binding-darwin-x64@1.0.0-rc.17': + '@rolldown/binding-linux-arm-gnueabihf@1.0.0': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-rc.17': + '@rolldown/binding-linux-arm-gnueabihf@1.0.1': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': + '@rolldown/binding-linux-arm64-gnu@1.0.0': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': + '@rolldown/binding-linux-arm64-gnu@1.0.1': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': + '@rolldown/binding-linux-arm64-musl@1.0.0': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': + '@rolldown/binding-linux-arm64-musl@1.0.1': optional: true - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': + '@rolldown/binding-linux-ppc64-gnu@1.0.0': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': + '@rolldown/binding-linux-ppc64-gnu@1.0.1': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': + '@rolldown/binding-linux-s390x-gnu@1.0.0': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': + '@rolldown/binding-linux-s390x-gnu@1.0.1': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': + '@rolldown/binding-linux-x64-gnu@1.0.0': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.1': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.1': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.1': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.1': dependencies: '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': + '@rolldown/binding-win32-arm64-msvc@1.0.0': + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.1': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': + '@rolldown/binding-win32-x64-msvc@1.0.1': optional: true - '@rolldown/pluginutils@1.0.0-rc.17': {} + '@rolldown/pluginutils@1.0.0': {} + + '@rolldown/pluginutils@1.0.1': {} '@rollup/plugin-node-resolve@15.3.1': dependencies: @@ -3947,7 +4096,7 @@ snapshots: '@rollup/pluginutils@5.3.0': dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 estree-walker: 2.0.2 picomatch: 4.0.4 @@ -3975,112 +4124,112 @@ snapshots: dependencies: acorn: 8.16.0 - '@sveltejs/kit@2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))': + '@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@standard-schema/spec': 1.1.0 '@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0) - '@sveltejs/vite-plugin-svelte': 7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + '@sveltejs/vite-plugin-svelte': 7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) '@types/cookie': 0.6.0 acorn: 8.16.0 cookie: 0.6.0 - devalue: 5.7.1 + devalue: 5.8.0 esm-env: 1.2.2 kleur: 4.1.5 magic-string: 0.30.21 mrmime: 2.0.1 set-cookie-parser: 3.1.0 sirv: 3.0.2 - svelte: 5.55.5(@typescript-eslint/types@8.59.1) - vite: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) + svelte: 5.55.5(@typescript-eslint/types@8.59.3) + vite: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) optionalDependencies: typescript: 6.0.3 - '@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))': + '@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))': dependencies: deepmerge: 4.3.1 magic-string: 0.30.21 obug: 2.1.1 - svelte: 5.55.5(@typescript-eslint/types@8.59.1) - vite: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) - vitefu: 1.1.3(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + svelte: 5.55.5(@typescript-eslint/types@8.59.3) + vite: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) + vitefu: 1.1.3(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) - '@tailwindcss/node@4.2.4': + '@tailwindcss/node@4.3.0': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.21.0 - jiti: 2.6.1 + enhanced-resolve: 5.21.3 + jiti: 2.7.0 lightningcss: 1.32.0 magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.2.4 + tailwindcss: 4.3.0 - '@tailwindcss/oxide-android-arm64@4.2.4': + '@tailwindcss/oxide-android-arm64@4.3.0': optional: true - '@tailwindcss/oxide-darwin-arm64@4.2.4': + '@tailwindcss/oxide-darwin-arm64@4.3.0': optional: true - '@tailwindcss/oxide-darwin-x64@4.2.4': + '@tailwindcss/oxide-darwin-x64@4.3.0': optional: true - '@tailwindcss/oxide-freebsd-x64@4.2.4': + '@tailwindcss/oxide-freebsd-x64@4.3.0': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.4': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.2.4': + '@tailwindcss/oxide-linux-arm64-gnu@4.3.0': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.2.4': + '@tailwindcss/oxide-linux-arm64-musl@4.3.0': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.2.4': + '@tailwindcss/oxide-linux-x64-gnu@4.3.0': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.2.4': + '@tailwindcss/oxide-linux-x64-musl@4.3.0': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.2.4': + '@tailwindcss/oxide-wasm32-wasi@4.3.0': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.2.4': + '@tailwindcss/oxide-win32-arm64-msvc@4.3.0': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.2.4': + '@tailwindcss/oxide-win32-x64-msvc@4.3.0': optional: true - '@tailwindcss/oxide@4.2.4': + '@tailwindcss/oxide@4.3.0': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.2.4 - '@tailwindcss/oxide-darwin-arm64': 4.2.4 - '@tailwindcss/oxide-darwin-x64': 4.2.4 - '@tailwindcss/oxide-freebsd-x64': 4.2.4 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.4 - '@tailwindcss/oxide-linux-arm64-gnu': 4.2.4 - '@tailwindcss/oxide-linux-arm64-musl': 4.2.4 - '@tailwindcss/oxide-linux-x64-gnu': 4.2.4 - '@tailwindcss/oxide-linux-x64-musl': 4.2.4 - '@tailwindcss/oxide-wasm32-wasi': 4.2.4 - '@tailwindcss/oxide-win32-arm64-msvc': 4.2.4 - '@tailwindcss/oxide-win32-x64-msvc': 4.2.4 - - '@tailwindcss/postcss@4.2.4': + '@tailwindcss/oxide-android-arm64': 4.3.0 + '@tailwindcss/oxide-darwin-arm64': 4.3.0 + '@tailwindcss/oxide-darwin-x64': 4.3.0 + '@tailwindcss/oxide-freebsd-x64': 4.3.0 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.0 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.0 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.0 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.0 + '@tailwindcss/oxide-linux-x64-musl': 4.3.0 + '@tailwindcss/oxide-wasm32-wasi': 4.3.0 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.0 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.0 + + '@tailwindcss/postcss@4.3.0': dependencies: '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.2.4 - '@tailwindcss/oxide': 4.2.4 - postcss: 8.5.12 - tailwindcss: 4.2.4 + '@tailwindcss/node': 4.3.0 + '@tailwindcss/oxide': 4.3.0 + postcss: 8.5.14 + tailwindcss: 4.3.0 - '@testing-library/svelte-core@1.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))': + '@testing-library/svelte-core@1.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.3))': dependencies: - svelte: 5.55.5(@typescript-eslint/types@8.59.1) + svelte: 5.55.5(@typescript-eslint/types@8.59.3) - '@trivago/prettier-plugin-sort-imports@6.0.2(prettier-plugin-svelte@3.5.1(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1)))(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1))': + '@trivago/prettier-plugin-sort-imports@6.0.2(prettier-plugin-svelte@3.5.2(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3)))(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3))': dependencies: '@babel/generator': 7.29.1 - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.3 '@babel/traverse': 7.29.0 '@babel/types': 7.29.0 javascript-natural-sort: 0.7.1 @@ -4089,21 +4238,21 @@ snapshots: parse-imports-exports: 0.2.4 prettier: 3.8.3 optionalDependencies: - prettier-plugin-svelte: 3.5.1(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1)) - svelte: 5.55.5(@typescript-eslint/types@8.59.1) + prettier-plugin-svelte: 3.5.2(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3)) + svelte: 5.55.5(@typescript-eslint/types@8.59.3) transitivePeerDependencies: - supports-color '@tsconfig/svelte@5.0.8': {} - '@tybys/wasm-util@0.10.1': + '@tybys/wasm-util@0.10.2': dependencies: tslib: 2.8.1 optional: true - '@types/bun@1.3.13': + '@types/bun@1.3.14': dependencies: - bun-types: 1.3.13 + bun-types: 1.3.14 '@types/chai@5.2.3': dependencies: @@ -4116,32 +4265,32 @@ snapshots: '@types/eslint@9.6.1': dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 '@types/json-schema': 7.0.15 '@types/esrecurse@4.3.1': {} - '@types/estree@1.0.8': {} + '@types/estree@1.0.9': {} '@types/json-schema@7.0.15': {} - '@types/node@25.6.0': + '@types/node@25.7.0': dependencies: - undici-types: 7.19.2 + undici-types: 7.21.0 '@types/resolve@1.20.2': {} '@types/trusted-types@2.0.7': {} - '@typescript-eslint/eslint-plugin@8.59.1(@typescript-eslint/parser@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3))(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.59.1 - '@typescript-eslint/type-utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.59.1 - eslint: 10.2.1(jiti@2.6.1) + '@typescript-eslint/parser': 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.59.3 + '@typescript-eslint/type-utils': 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.59.3 + eslint: 10.3.0(jiti@2.7.0) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@6.0.3) @@ -4149,79 +4298,79 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/parser@8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.59.1 - '@typescript-eslint/types': 8.59.1 - '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.59.1 + '@typescript-eslint/scope-manager': 8.59.3 + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.59.3 debug: 4.4.3 - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.7.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.59.1(typescript@6.0.3)': + '@typescript-eslint/project-service@8.59.3(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.59.1(typescript@6.0.3) - '@typescript-eslint/types': 8.59.1 + '@typescript-eslint/tsconfig-utils': 8.59.3(typescript@6.0.3) + '@typescript-eslint/types': 8.59.3 debug: 4.4.3 typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.59.1': + '@typescript-eslint/scope-manager@8.59.3': dependencies: - '@typescript-eslint/types': 8.59.1 - '@typescript-eslint/visitor-keys': 8.59.1 + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/visitor-keys': 8.59.3 - '@typescript-eslint/tsconfig-utils@8.59.1(typescript@6.0.3)': + '@typescript-eslint/tsconfig-utils@8.59.3(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@typescript-eslint/types': 8.59.1 - '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) debug: 4.4.3 - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.7.0) ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.59.1': {} + '@typescript-eslint/types@8.59.3': {} - '@typescript-eslint/typescript-estree@8.59.1(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.59.3(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.59.1(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.59.1(typescript@6.0.3) - '@typescript-eslint/types': 8.59.1 - '@typescript-eslint/visitor-keys': 8.59.1 + '@typescript-eslint/project-service': 8.59.3(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.59.3(typescript@6.0.3) + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/visitor-keys': 8.59.3 debug: 4.4.3 minimatch: 10.2.5 - semver: 7.7.4 + semver: 7.8.0 tinyglobby: 0.2.16 ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/utils@8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.59.1 - '@typescript-eslint/types': 8.59.1 - '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) - eslint: 10.2.1(jiti@2.6.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.7.0)) + '@typescript-eslint/scope-manager': 8.59.3 + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3) + eslint: 10.3.0(jiti@2.7.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.59.1': + '@typescript-eslint/visitor-keys@8.59.3': dependencies: - '@typescript-eslint/types': 8.59.1 + '@typescript-eslint/types': 8.59.3 eslint-visitor-keys: 5.0.1 '@unocss/cli@66.6.8': @@ -4273,7 +4422,7 @@ snapshots: '@unocss/preset-icons@66.6.8': dependencies: - '@iconify/utils': 3.1.1 + '@iconify/utils': 3.1.3 '@unocss/core': 66.6.8 ofetch: 1.5.1 @@ -4362,7 +4511,7 @@ snapshots: dependencies: '@unocss/core': 66.6.8 - '@unocss/vite@66.6.8(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))': + '@unocss/vite@66.6.8(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@jridgewell/remapping': 2.3.5 '@unocss/config': 66.6.8 @@ -4373,42 +4522,42 @@ snapshots: pathe: 2.0.3 tinyglobby: 0.2.16 unplugin-utils: 0.3.1 - vite: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) + vite: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) - '@vitest/browser-playwright@4.1.5(playwright@1.59.1)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.5)': + '@vitest/browser-playwright@4.1.6(playwright@1.60.0)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6)': dependencies: - '@vitest/browser': 4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.5) - '@vitest/mocker': 4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) - playwright: 1.59.1 + '@vitest/browser': 4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6) + '@vitest/mocker': 4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + playwright: 1.60.0 tinyrainbow: 3.1.0 - vitest: 4.1.5(@types/node@25.6.0)(@vitest/browser-playwright@4.1.5)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + vitest: 4.1.6(@types/node@25.7.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite - '@vitest/browser@4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.5)': + '@vitest/browser@4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6)': dependencies: '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) - '@vitest/utils': 4.1.5 + '@vitest/mocker': 4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + '@vitest/utils': 4.1.6 magic-string: 0.30.21 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.1.0 - vitest: 4.1.5(@types/node@25.6.0)(@vitest/browser-playwright@4.1.5)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) - ws: 8.20.0 + vitest: 4.1.6(@types/node@25.7.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + ws: 8.20.1 transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite - '@vitest/coverage-v8@4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5)': + '@vitest/coverage-v8@4.1.6(@vitest/browser@4.1.6)(vitest@4.1.6)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.5 + '@vitest/utils': 4.1.6 ast-v8-to-istanbul: 1.0.0 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 @@ -4417,48 +4566,48 @@ snapshots: obug: 2.1.1 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.5(@types/node@25.6.0)(@vitest/browser-playwright@4.1.5)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + vitest: 4.1.6(@types/node@25.7.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) optionalDependencies: - '@vitest/browser': 4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.5) + '@vitest/browser': 4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6) - '@vitest/expect@4.1.5': + '@vitest/expect@4.1.6': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.1.5 - '@vitest/utils': 4.1.5 + '@vitest/spy': 4.1.6 + '@vitest/utils': 4.1.6 chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))': + '@vitest/mocker@4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))': dependencies: - '@vitest/spy': 4.1.5 + '@vitest/spy': 4.1.6 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) + vite: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) - '@vitest/pretty-format@4.1.5': + '@vitest/pretty-format@4.1.6': dependencies: tinyrainbow: 3.1.0 - '@vitest/runner@4.1.5': + '@vitest/runner@4.1.6': dependencies: - '@vitest/utils': 4.1.5 + '@vitest/utils': 4.1.6 pathe: 2.0.3 - '@vitest/snapshot@4.1.5': + '@vitest/snapshot@4.1.6': dependencies: - '@vitest/pretty-format': 4.1.5 - '@vitest/utils': 4.1.5 + '@vitest/pretty-format': 4.1.6 + '@vitest/utils': 4.1.6 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.1.5': {} + '@vitest/spy@4.1.6': {} - '@vitest/utils@4.1.5': + '@vitest/utils@4.1.6': dependencies: - '@vitest/pretty-format': 4.1.5 + '@vitest/pretty-format': 4.1.6 convert-source-map: 2.0.0 tinyrainbow: 3.1.0 @@ -4478,7 +4627,7 @@ snapshots: ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 + fast-uri: 3.1.2 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -4486,17 +4635,11 @@ snapshots: dependencies: environment: 1.1.0 - ansi-regex@5.0.1: {} - ansi-regex@6.2.2: {} - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - ansi-styles@6.2.3: {} - apexcharts@5.10.6: {} + apexcharts@5.11.0: {} argparse@2.0.1: {} @@ -4528,28 +4671,32 @@ snapshots: dependencies: balanced-match: 1.0.2 - brace-expansion@5.0.5: + brace-expansion@5.0.6: dependencies: balanced-match: 4.0.4 - bun-types@1.3.13: + bun-types@1.3.14: dependencies: - '@types/node': 25.6.0 + '@types/node': 25.7.0 - bun@1.3.13: + bun@1.3.14: optionalDependencies: - '@oven/bun-darwin-aarch64': 1.3.13 - '@oven/bun-darwin-x64': 1.3.13 - '@oven/bun-darwin-x64-baseline': 1.3.13 - '@oven/bun-linux-aarch64': 1.3.13 - '@oven/bun-linux-aarch64-musl': 1.3.13 - '@oven/bun-linux-x64': 1.3.13 - '@oven/bun-linux-x64-baseline': 1.3.13 - '@oven/bun-linux-x64-musl': 1.3.13 - '@oven/bun-linux-x64-musl-baseline': 1.3.13 - '@oven/bun-windows-aarch64': 1.3.13 - '@oven/bun-windows-x64': 1.3.13 - '@oven/bun-windows-x64-baseline': 1.3.13 + '@oven/bun-darwin-aarch64': 1.3.14 + '@oven/bun-darwin-x64': 1.3.14 + '@oven/bun-darwin-x64-baseline': 1.3.14 + '@oven/bun-freebsd-aarch64': 1.3.14 + '@oven/bun-freebsd-x64': 1.3.14 + '@oven/bun-linux-aarch64': 1.3.14 + '@oven/bun-linux-aarch64-android': 1.3.14 + '@oven/bun-linux-aarch64-musl': 1.3.14 + '@oven/bun-linux-x64': 1.3.14 + '@oven/bun-linux-x64-android': 1.3.14 + '@oven/bun-linux-x64-baseline': 1.3.14 + '@oven/bun-linux-x64-musl': 1.3.14 + '@oven/bun-linux-x64-musl-baseline': 1.3.14 + '@oven/bun-windows-aarch64': 1.3.14 + '@oven/bun-windows-x64': 1.3.14 + '@oven/bun-windows-x64-baseline': 1.3.14 cac@7.0.0: {} @@ -4576,20 +4723,14 @@ snapshots: slice-ansi: 8.0.0 string-width: 8.2.1 - cliui@8.0.1: + cliui@9.0.1: dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 + string-width: 7.2.0 + strip-ansi: 7.2.0 + wrap-ansi: 9.0.2 clsx@2.1.1: {} - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - colorette@2.0.20: {} commander@11.1.0: {} @@ -4612,6 +4753,8 @@ snapshots: consola@3.4.2: {} + content-type@2.0.0: {} + conventional-changelog-angular@8.3.1: dependencies: compare-func: 2.0.0 @@ -4641,9 +4784,9 @@ snapshots: cookie@0.6.0: {} - cosmiconfig-typescript-loader@6.3.0(@types/node@25.6.0)(cosmiconfig@9.0.1(typescript@6.0.3))(typescript@6.0.3): + cosmiconfig-typescript-loader@6.3.0(@types/node@25.7.0)(cosmiconfig@9.0.1(typescript@6.0.3))(typescript@6.0.3): dependencies: - '@types/node': 25.6.0 + '@types/node': 25.7.0 cosmiconfig: 9.0.1(typescript@6.0.3) jiti: 2.6.1 typescript: 6.0.3 @@ -4688,7 +4831,7 @@ snapshots: detect-libc@2.1.2: {} - devalue@5.7.1: {} + devalue@5.8.0: {} dompurify@3.2.7: optionalDependencies: @@ -4704,9 +4847,7 @@ snapshots: emoji-regex@10.6.0: {} - emoji-regex@8.0.0: {} - - enhanced-resolve@5.21.0: + enhanced-resolve@5.21.3: dependencies: graceful-fs: 4.2.11 tapable: 2.3.3 @@ -4723,13 +4864,15 @@ snapshots: es-module-lexer@2.1.0: {} + es-toolkit@1.46.1: {} + escalade@3.2.0: {} escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@10.2.1(jiti@2.6.1)): + eslint-config-prettier@10.1.8(eslint@10.3.0(jiti@2.7.0)): dependencies: - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.7.0) eslint-formatter-pretty@7.1.0: dependencies: @@ -4742,51 +4885,51 @@ snapshots: string-width: 8.2.1 supports-hyperlinks: 4.4.0 - eslint-formatting-reporter@0.0.0(eslint@10.2.1(jiti@2.6.1)): + eslint-formatting-reporter@0.0.0(eslint@10.3.0(jiti@2.7.0)): dependencies: - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.7.0) prettier-linter-helpers: 1.0.1 eslint-parser-plain@0.1.1: {} - eslint-plugin-format@1.5.0(eslint@10.2.1(jiti@2.6.1)): + eslint-plugin-format@1.5.0(eslint@10.3.0(jiti@2.7.0)): dependencies: '@dprint/formatter': 0.5.1 '@dprint/markdown': 0.21.1 '@dprint/toml': 0.7.0 - eslint: 10.2.1(jiti@2.6.1) - eslint-formatting-reporter: 0.0.0(eslint@10.2.1(jiti@2.6.1)) + eslint: 10.3.0(jiti@2.7.0) + eslint-formatting-reporter: 0.0.0(eslint@10.3.0(jiti@2.7.0)) eslint-parser-plain: 0.1.1 ohash: 2.0.11 oxfmt: 0.35.0 prettier: 3.8.3 synckit: 0.11.12 - eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.2.1(jiti@2.6.1)))(eslint@10.2.1(jiti@2.6.1))(prettier@3.8.3): + eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.3.0(jiti@2.7.0)))(eslint@10.3.0(jiti@2.7.0))(prettier@3.8.3): dependencies: - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.7.0) prettier: 3.8.3 prettier-linter-helpers: 1.0.1 synckit: 0.11.12 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 10.1.8(eslint@10.2.1(jiti@2.6.1)) + eslint-config-prettier: 10.1.8(eslint@10.3.0(jiti@2.7.0)) - eslint-plugin-svelte@3.17.1(eslint@10.2.1(jiti@2.6.1))(svelte@5.55.5(@typescript-eslint/types@8.59.1)): + eslint-plugin-svelte@3.17.1(eslint@10.3.0(jiti@2.7.0))(svelte@5.55.5(@typescript-eslint/types@8.59.3)): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.7.0)) '@jridgewell/sourcemap-codec': 1.5.5 - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.7.0) esutils: 2.0.3 globals: 16.5.0 known-css-properties: 0.37.0 - postcss: 8.5.12 - postcss-load-config: 3.1.4(postcss@8.5.12) - postcss-safe-parser: 7.0.1(postcss@8.5.12) - semver: 7.7.4 - svelte-eslint-parser: 1.6.0(svelte@5.55.5(@typescript-eslint/types@8.59.1)) + postcss: 8.5.14 + postcss-load-config: 3.1.4(postcss@8.5.14) + postcss-safe-parser: 7.0.1(postcss@8.5.14) + semver: 7.8.0 + svelte-eslint-parser: 1.6.1(svelte@5.55.5(@typescript-eslint/types@8.59.3)) optionalDependencies: - svelte: 5.55.5(@typescript-eslint/types@8.59.1) + svelte: 5.55.5(@typescript-eslint/types@8.59.3) transitivePeerDependencies: - ts-node @@ -4800,7 +4943,7 @@ snapshots: eslint-scope@9.1.2: dependencies: '@types/esrecurse': 4.3.1 - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 esrecurse: 4.3.0 estraverse: 5.3.0 @@ -4810,9 +4953,9 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.2.1(jiti@2.6.1): + eslint@10.3.0(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.7.0)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.23.5 '@eslint/config-helpers': 0.5.5 @@ -4821,7 +4964,7 @@ snapshots: '@humanfs/node': 0.16.8 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 ajv: 6.15.0 cross-spawn: 7.0.6 debug: 4.4.3 @@ -4843,7 +4986,7 @@ snapshots: natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: - jiti: 2.6.1 + jiti: 2.7.0 transitivePeerDependencies: - supports-color @@ -4867,11 +5010,11 @@ snapshots: dependencies: estraverse: 5.3.0 - esrap@2.2.5(@typescript-eslint/types@8.59.1): + esrap@2.2.8(@typescript-eslint/types@8.59.3): dependencies: '@jridgewell/sourcemap-codec': 1.5.5 optionalDependencies: - '@typescript-eslint/types': 8.59.1 + '@typescript-eslint/types': 8.59.3 esrecurse@4.3.0: dependencies: @@ -4883,7 +5026,7 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 esutils@2.0.3: {} @@ -4916,7 +5059,7 @@ snapshots: fast-levenshtein@2.0.6: {} - fast-uri@3.1.0: {} + fast-uri@3.1.2: {} fdir@6.5.0(picomatch@4.0.4): optionalDependencies: @@ -4952,23 +5095,23 @@ snapshots: flowbite-datepicker@2.0.0: dependencies: '@rollup/plugin-node-resolve': 15.3.1 - '@tailwindcss/postcss': 4.2.4 + '@tailwindcss/postcss': 4.3.0 transitivePeerDependencies: - rollup - flowbite-svelte@1.33.1(svelte@5.55.5(@typescript-eslint/types@8.59.1))(tailwindcss@4.2.4): + flowbite-svelte@1.33.1(svelte@5.55.5(@typescript-eslint/types@8.59.3))(tailwindcss@4.3.0): dependencies: '@floating-ui/dom': 1.7.6 '@floating-ui/utils': 0.2.11 - apexcharts: 5.10.6 + apexcharts: 5.11.0 clsx: 2.1.1 date-fns: 4.1.0 esm-env: 1.2.2 flowbite: 3.1.2 - svelte: 5.55.5(@typescript-eslint/types@8.59.1) - tailwind-merge: 3.5.0 - tailwind-variants: 3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.4) - tailwindcss: 4.2.4 + svelte: 5.55.5(@typescript-eslint/types@8.59.3) + tailwind-merge: 3.6.0 + tailwind-variants: 3.2.2(tailwind-merge@3.6.0)(tailwindcss@4.3.0) + tailwindcss: 4.3.0 transitivePeerDependencies: - rollup @@ -4985,17 +5128,17 @@ snapshots: '@popperjs/core': 2.11.8 flowbite-datepicker: 1.3.2 mini-svg-data-uri: 1.4.4 - postcss: 8.5.12 + postcss: 8.5.14 transitivePeerDependencies: - rollup - flowbite@4.0.1: + flowbite@4.0.2: dependencies: '@popperjs/core': 2.11.8 flowbite-datepicker: 2.0.0 mini-svg-data-uri: 1.4.4 - postcss: 8.5.12 - tailwindcss: 4.2.4 + postcss: 8.5.14 + tailwindcss: 4.3.0 transitivePeerDependencies: - rollup @@ -5009,7 +5152,7 @@ snapshots: get-caller-file@2.0.5: {} - get-east-asian-width@1.5.0: {} + get-east-asian-width@1.6.0: {} get-stream@9.0.1: dependencies: @@ -5063,7 +5206,7 @@ snapshots: globals@16.5.0: {} - globals@17.5.0: {} + globals@17.6.0: {} graceful-fs@4.2.11: {} @@ -5111,17 +5254,15 @@ snapshots: is-arrayish@0.2.1: {} - is-core-module@2.16.1: + is-core-module@2.16.2: dependencies: hasown: 2.0.3 is-extglob@2.1.1: {} - is-fullwidth-code-point@3.0.0: {} - is-fullwidth-code-point@5.1.0: dependencies: - get-east-asian-width: 1.5.0 + get-east-asian-width: 1.6.0 is-glob@4.0.3: dependencies: @@ -5135,7 +5276,7 @@ snapshots: is-reference@3.0.3: dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 is-stream@4.0.1: {} @@ -5160,6 +5301,8 @@ snapshots: jiti@2.6.1: {} + jiti@2.7.0: {} + js-sha256@0.11.1: {} js-tokens@10.0.0: {} @@ -5194,7 +5337,7 @@ snapshots: known-css-properties@0.37.0: {} - kysely@0.28.16: {} + kysely@0.28.17: {} levn@0.4.1: dependencies: @@ -5254,23 +5397,22 @@ snapshots: lines-and-columns@1.2.4: {} - lint-staged@16.4.0: + lint-staged@17.0.4: dependencies: - commander: 14.0.3 - listr2: 9.0.5 + listr2: 10.2.1 picomatch: 4.0.4 string-argv: 0.3.2 - tinyexec: 1.1.1 - yaml: 2.8.3 + tinyexec: 1.1.2 + optionalDependencies: + yaml: 2.9.0 - listr2@9.0.5: + listr2@10.2.1: dependencies: cli-truncate: 5.2.0 - colorette: 2.0.20 eventemitter3: 5.0.4 log-update: 6.1.0 rfdc: 1.4.1 - wrap-ansi: 9.0.2 + wrap-ansi: 10.0.0 locate-character@3.0.0: {} @@ -5280,18 +5422,6 @@ snapshots: lodash-es@4.18.1: {} - lodash.camelcase@4.3.0: {} - - lodash.kebabcase@4.1.1: {} - - lodash.mergewith@4.6.2: {} - - lodash.snakecase@4.1.1: {} - - lodash.startcase@4.4.0: {} - - lodash.upperfirst@4.3.1: {} - log-symbols@7.0.1: dependencies: is-unicode-supported: 2.1.0 @@ -5312,7 +5442,7 @@ snapshots: mlly: 1.8.2 regexp-tree: 0.1.27 type-level-regexp: 0.1.17 - ufo: 1.6.3 + ufo: 1.6.4 unplugin: 2.3.11 magic-string@0.30.21: @@ -5321,13 +5451,13 @@ snapshots: magicast@0.5.2: dependencies: - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.3 '@babel/types': 7.29.0 source-map-js: 1.2.1 make-dir@4.0.0: dependencies: - semver: 7.7.4 + semver: 7.8.0 marked@14.0.0: {} @@ -5341,20 +5471,18 @@ snapshots: minimatch@10.2.5: dependencies: - brace-expansion: 5.0.5 + brace-expansion: 5.0.6 minimatch@9.0.9: dependencies: brace-expansion: 2.1.0 - minimist@1.2.8: {} - mlly@1.8.2: dependencies: acorn: 8.16.0 pathe: 2.0.3 pkg-types: 1.3.1 - ufo: 1.6.3 + ufo: 1.6.4 monaco-editor@0.55.1: dependencies: @@ -5367,7 +5495,7 @@ snapshots: ms@2.1.3: {} - nanoid@3.3.11: {} + nanoid@3.3.12: {} natural-compare@1.4.0: {} @@ -5384,7 +5512,7 @@ snapshots: dependencies: destr: 2.0.5 node-fetch-native: 1.6.7 - ufo: 1.6.3 + ufo: 1.6.4 ohash@2.0.11: {} @@ -5509,11 +5637,11 @@ snapshots: mlly: 1.8.2 pathe: 2.0.3 - playwright-core@1.59.1: {} + playwright-core@1.60.0: {} - playwright@1.59.1: + playwright@1.60.0: dependencies: - playwright-core: 1.59.1 + playwright-core: 1.60.0 optionalDependencies: fsevents: 2.3.2 @@ -5523,29 +5651,29 @@ snapshots: pngjs@7.0.0: {} - postcss-load-config@3.1.4(postcss@8.5.12): + postcss-load-config@3.1.4(postcss@8.5.14): dependencies: lilconfig: 2.1.0 yaml: 1.10.3 optionalDependencies: - postcss: 8.5.12 + postcss: 8.5.14 - postcss-safe-parser@7.0.1(postcss@8.5.12): + postcss-safe-parser@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.12 + postcss: 8.5.14 - postcss-scss@4.0.9(postcss@8.5.12): + postcss-scss@4.0.9(postcss@8.5.14): dependencies: - postcss: 8.5.12 + postcss: 8.5.14 postcss-selector-parser@7.1.1: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss@8.5.12: + postcss@8.5.14: dependencies: - nanoid: 3.3.11 + nanoid: 3.3.12 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -5555,10 +5683,10 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier-plugin-svelte@3.5.1(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.1)): + prettier-plugin-svelte@3.5.2(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3)): dependencies: prettier: 3.8.3 - svelte: 5.55.5(@typescript-eslint/types@8.59.1) + svelte: 5.55.5(@typescript-eslint/types@8.59.3) prettier@2.5.1: {} @@ -5578,8 +5706,6 @@ snapshots: regexp-tree@0.1.27: {} - require-directory@2.1.1: {} - require-from-string@2.0.2: {} resolve-from@4.0.0: {} @@ -5589,7 +5715,7 @@ snapshots: resolve@1.22.12: dependencies: es-errors: 1.3.0 - is-core-module: 2.16.1 + is-core-module: 2.16.2 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -5600,37 +5726,58 @@ snapshots: rfdc@1.4.1: {} - rolldown@1.0.0-rc.17: + rolldown@1.0.0: dependencies: - '@oxc-project/types': 0.127.0 - '@rolldown/pluginutils': 1.0.0-rc.17 + '@oxc-project/types': 0.129.0 + '@rolldown/pluginutils': 1.0.0 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-rc.17 - '@rolldown/binding-darwin-arm64': 1.0.0-rc.17 - '@rolldown/binding-darwin-x64': 1.0.0-rc.17 - '@rolldown/binding-freebsd-x64': 1.0.0-rc.17 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.17 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.17 - '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.17 - '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.17 - '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.17 - '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.17 - '@rolldown/binding-linux-x64-musl': 1.0.0-rc.17 - '@rolldown/binding-openharmony-arm64': 1.0.0-rc.17 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.17 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.17 - '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.17 - - runed@0.28.0(svelte@5.55.5(@typescript-eslint/types@8.59.1)): + '@rolldown/binding-android-arm64': 1.0.0 + '@rolldown/binding-darwin-arm64': 1.0.0 + '@rolldown/binding-darwin-x64': 1.0.0 + '@rolldown/binding-freebsd-x64': 1.0.0 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0 + '@rolldown/binding-linux-arm64-gnu': 1.0.0 + '@rolldown/binding-linux-arm64-musl': 1.0.0 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0 + '@rolldown/binding-linux-s390x-gnu': 1.0.0 + '@rolldown/binding-linux-x64-gnu': 1.0.0 + '@rolldown/binding-linux-x64-musl': 1.0.0 + '@rolldown/binding-openharmony-arm64': 1.0.0 + '@rolldown/binding-wasm32-wasi': 1.0.0 + '@rolldown/binding-win32-arm64-msvc': 1.0.0 + '@rolldown/binding-win32-x64-msvc': 1.0.0 + + rolldown@1.0.1: + dependencies: + '@oxc-project/types': 0.130.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.1 + '@rolldown/binding-darwin-arm64': 1.0.1 + '@rolldown/binding-darwin-x64': 1.0.1 + '@rolldown/binding-freebsd-x64': 1.0.1 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.1 + '@rolldown/binding-linux-arm64-gnu': 1.0.1 + '@rolldown/binding-linux-arm64-musl': 1.0.1 + '@rolldown/binding-linux-ppc64-gnu': 1.0.1 + '@rolldown/binding-linux-s390x-gnu': 1.0.1 + '@rolldown/binding-linux-x64-gnu': 1.0.1 + '@rolldown/binding-linux-x64-musl': 1.0.1 + '@rolldown/binding-openharmony-arm64': 1.0.1 + '@rolldown/binding-wasm32-wasi': 1.0.1 + '@rolldown/binding-win32-arm64-msvc': 1.0.1 + '@rolldown/binding-win32-x64-msvc': 1.0.1 + + runed@0.28.0(svelte@5.55.5(@typescript-eslint/types@8.59.3)): dependencies: esm-env: 1.2.2 - svelte: 5.55.5(@typescript-eslint/types@8.59.1) + svelte: 5.55.5(@typescript-eslint/types@8.59.3) sade@1.8.1: dependencies: mri: 1.2.0 - semver@7.7.4: {} + semver@7.8.0: {} set-cookie-parser@3.1.0: {} @@ -5664,10 +5811,10 @@ snapshots: source-map-js@1.2.1: {} - sqlite-wasm-kysely@0.3.0(kysely@0.28.16): + sqlite-wasm-kysely@0.3.0(kysely@0.28.17): dependencies: '@sqlite.org/sqlite-wasm': 3.48.0-build4 - kysely: 0.28.16 + kysely: 0.28.17 stackback@0.0.2: {} @@ -5675,27 +5822,17 @@ snapshots: string-argv@0.3.2: {} - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - string-width@7.2.0: dependencies: emoji-regex: 10.6.0 - get-east-asian-width: 1.5.0 + get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 string-width@8.2.1: dependencies: - get-east-asian-width: 1.5.0 + get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - strip-ansi@7.2.0: dependencies: ansi-regex: 6.2.2 @@ -5715,61 +5852,61 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-adapter-bun@1.0.1(@sveltejs/kit@2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(typescript@6.0.3): + svelte-adapter-bun@1.0.1(@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(typescript@6.0.3): dependencies: - '@sveltejs/kit': 2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) - rolldown: 1.0.0-rc.17 + '@sveltejs/kit': 2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + rolldown: 1.0.1 typescript: 6.0.3 - svelte-check@4.4.6(picomatch@4.0.4)(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3): + svelte-check@4.4.8(picomatch@4.0.4)(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3): dependencies: '@jridgewell/trace-mapping': 0.3.31 chokidar: 4.0.3 fdir: 6.5.0(picomatch@4.0.4) picocolors: 1.1.1 sade: 1.8.1 - svelte: 5.55.5(@typescript-eslint/types@8.59.1) + svelte: 5.55.5(@typescript-eslint/types@8.59.3) typescript: 6.0.3 transitivePeerDependencies: - picomatch - svelte-eslint-parser@1.6.0(svelte@5.55.5(@typescript-eslint/types@8.59.1)): + svelte-eslint-parser@1.6.1(svelte@5.55.5(@typescript-eslint/types@8.59.3)): dependencies: eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 - postcss: 8.5.12 - postcss-scss: 4.0.9(postcss@8.5.12) + postcss: 8.5.14 + postcss-scss: 4.0.9(postcss@8.5.14) postcss-selector-parser: 7.1.1 - semver: 7.7.4 + semver: 7.8.0 optionalDependencies: - svelte: 5.55.5(@typescript-eslint/types@8.59.1) + svelte: 5.55.5(@typescript-eslint/types@8.59.3) - svelte-kit-sessions@0.4.0(@sveltejs/kit@2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1)): + svelte-kit-sessions@0.4.0(@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3)): dependencies: '@isaacs/ttlcache': 1.4.1 - '@sveltejs/kit': 2.58.0(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)))(svelte@5.55.5(@typescript-eslint/types@8.59.1))(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) - svelte: 5.55.5(@typescript-eslint/types@8.59.1) + '@sveltejs/kit': 2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + svelte: 5.55.5(@typescript-eslint/types@8.59.3) - svelte-sonner@1.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.1)): + svelte-sonner@1.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.3)): dependencies: - runed: 0.28.0(svelte@5.55.5(@typescript-eslint/types@8.59.1)) - svelte: 5.55.5(@typescript-eslint/types@8.59.1) + runed: 0.28.0(svelte@5.55.5(@typescript-eslint/types@8.59.3)) + svelte: 5.55.5(@typescript-eslint/types@8.59.3) - svelte@5.55.5(@typescript-eslint/types@8.59.1): + svelte@5.55.5(@typescript-eslint/types@8.59.3): dependencies: '@jridgewell/remapping': 2.3.5 '@jridgewell/sourcemap-codec': 1.5.5 '@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0) - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 '@types/trusted-types': 2.0.7 acorn: 8.16.0 aria-query: 5.3.1 axobject-query: 4.1.0 clsx: 2.1.1 - devalue: 5.7.1 + devalue: 5.8.0 esm-env: 1.2.2 - esrap: 2.2.5(@typescript-eslint/types@8.59.1) + esrap: 2.2.8(@typescript-eslint/types@8.59.3) is-reference: 3.0.3 locate-character: 3.0.0 magic-string: 0.30.21 @@ -5781,21 +5918,21 @@ snapshots: dependencies: '@pkgr/core': 0.2.9 - tailwind-merge@3.5.0: {} + tailwind-merge@3.6.0: {} - tailwind-variants@3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.4): + tailwind-variants@3.2.2(tailwind-merge@3.6.0)(tailwindcss@4.3.0): dependencies: - tailwindcss: 4.2.4 + tailwindcss: 4.3.0 optionalDependencies: - tailwind-merge: 3.5.0 + tailwind-merge: 3.6.0 - tailwindcss@4.2.4: {} + tailwindcss@4.3.0: {} tapable@2.3.3: {} tinybench@2.9.0: {} - tinyexec@1.1.1: {} + tinyexec@1.1.2: {} tinyglobby@0.2.16: dependencies: @@ -5823,20 +5960,20 @@ snapshots: type-level-regexp@0.1.17: {} - typescript-eslint@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3): + typescript-eslint@8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.59.1(@typescript-eslint/parser@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3))(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/parser': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - eslint: 10.2.1(jiti@2.6.1) + '@typescript-eslint/eslint-plugin': 8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/parser': 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) + eslint: 10.3.0(jiti@2.7.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color typescript@6.0.3: {} - ufo@1.6.3: {} + ufo@1.6.4: {} unconfig-core@7.5.0: dependencies: @@ -5847,11 +5984,11 @@ snapshots: dependencies: '@quansync/fs': 1.0.0 defu: 6.1.7 - jiti: 2.6.1 + jiti: 2.7.0 quansync: 1.0.0 unconfig-core: 7.5.0 - undici-types@7.19.2: {} + undici-types@7.21.0: {} undici@6.25.0: {} @@ -5859,7 +5996,7 @@ snapshots: universal-user-agent@7.0.3: {} - unocss@66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)): + unocss@66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)): dependencies: '@unocss/cli': 66.6.8 '@unocss/core': 66.6.8 @@ -5877,7 +6014,7 @@ snapshots: '@unocss/transformer-compile-class': 66.6.8 '@unocss/transformer-directives': 66.6.8 '@unocss/transformer-variant-group': 66.6.8 - '@unocss/vite': 66.6.8(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + '@unocss/vite': 66.6.8(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' @@ -5905,38 +6042,38 @@ snapshots: uuid@14.0.0: {} - vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3): + vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 - postcss: 8.5.12 - rolldown: 1.0.0-rc.17 + postcss: 8.5.14 + rolldown: 1.0.0 tinyglobby: 0.2.16 optionalDependencies: - '@types/node': 25.6.0 + '@types/node': 25.7.0 fsevents: 2.3.3 - jiti: 2.6.1 - yaml: 2.8.3 + jiti: 2.7.0 + yaml: 2.9.0 - vitefu@1.1.3(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)): + vitefu@1.1.3(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)): optionalDependencies: - vite: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) + vite: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) - vitest-browser-svelte@2.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.1))(vitest@4.1.5): + vitest-browser-svelte@2.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vitest@4.1.6): dependencies: - '@testing-library/svelte-core': 1.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.1)) - svelte: 5.55.5(@typescript-eslint/types@8.59.1) - vitest: 4.1.5(@types/node@25.6.0)(@vitest/browser-playwright@4.1.5)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) + '@testing-library/svelte-core': 1.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.3)) + svelte: 5.55.5(@typescript-eslint/types@8.59.3) + vitest: 4.1.6(@types/node@25.7.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) - vitest@4.1.5(@types/node@25.6.0)(@vitest/browser-playwright@4.1.5)(@vitest/coverage-v8@4.1.5)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)): + vitest@4.1.6(@types/node@25.7.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)): dependencies: - '@vitest/expect': 4.1.5 - '@vitest/mocker': 4.1.5(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.5 - '@vitest/runner': 4.1.5 - '@vitest/snapshot': 4.1.5 - '@vitest/spy': 4.1.5 - '@vitest/utils': 4.1.5 + '@vitest/expect': 4.1.6 + '@vitest/mocker': 4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.6 + '@vitest/runner': 4.1.6 + '@vitest/snapshot': 4.1.6 + '@vitest/spy': 4.1.6 + '@vitest/utils': 4.1.6 es-module-lexer: 2.1.0 expect-type: 1.3.0 magic-string: 0.30.21 @@ -5945,15 +6082,15 @@ snapshots: picomatch: 4.0.4 std-env: 4.1.0 tinybench: 2.9.0 - tinyexec: 1.1.1 + tinyexec: 1.1.2 tinyglobby: 0.2.16 tinyrainbow: 3.1.0 - vite: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3) + vite: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 25.6.0 - '@vitest/browser-playwright': 4.1.5(playwright@1.59.1)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(yaml@2.8.3))(vitest@4.1.5) - '@vitest/coverage-v8': 4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5) + '@types/node': 25.7.0 + '@vitest/browser-playwright': 4.1.6(playwright@1.60.0)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6) + '@vitest/coverage-v8': 4.1.6(@vitest/browser@4.1.6)(vitest@4.1.6) transitivePeerDependencies: - msw @@ -5970,11 +6107,11 @@ snapshots: word-wrap@1.2.5: {} - wrap-ansi@7.0.0: + wrap-ansi@10.0.0: dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 + ansi-styles: 6.2.3 + string-width: 8.2.1 + strip-ansi: 7.2.0 wrap-ansi@9.0.2: dependencies: @@ -5982,25 +6119,25 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.2.0 - ws@8.20.0: {} + ws@8.20.1: {} y18n@5.0.8: {} yaml@1.10.3: {} - yaml@2.8.3: {} + yaml@2.9.0: + optional: true - yargs-parser@21.1.1: {} + yargs-parser@22.0.0: {} - yargs@17.7.2: + yargs@18.0.0: dependencies: - cliui: 8.0.1 + cliui: 9.0.1 escalade: 3.2.0 get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 + string-width: 7.2.0 y18n: 5.0.8 - yargs-parser: 21.1.1 + yargs-parser: 22.0.0 yocto-queue@0.1.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 34ec471..fdd5fe9 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -6,28 +6,28 @@ catalogs: 'svelte-adapter-bun': ^1.0.1 typescript: ^6.0.3 ci: - '@commitlint/cli': ^20.5.2 - '@commitlint/config-conventional': ^20.5.0 + '@commitlint/cli': ^21.0.1 + '@commitlint/config-conventional': ^21.0.1 '@favware/cliff-jumper': ^6.1.0 '@nanoforge-dev/actions': ^1.3.0 husky: ^9.1.7 - lint-staged: ^16.4.0 + lint-staged: ^17.0.4 components: - flowbite: ^4.0.1 + flowbite: ^4.0.2 flowbite-svelte: ^1.33.1 monaco-editor: ^0.55.1 svelte-sonner: ^1.1.1 core: '@nanoforge-dev/ecs-lib': ^1.1.2 '@sveltejs/adapter-auto': ^7.0.1 - '@sveltejs/kit': ^2.58.0 - '@sveltejs/vite-plugin-svelte': ^7.0.0 - '@types/bun': ^1.3.13 - bun: ^1.3.13 + '@sveltejs/kit': ^2.59.1 + '@sveltejs/vite-plugin-svelte': ^7.1.2 + '@types/bun': ^1.3.14 + bun: ^1.3.14 svelte: ^5.55.5 - svelte-check: ^4.4.6 + svelte-check: ^4.4.8 svelte-kit-sessions: ^0.4.0 - vite: ^8.0.10 + vite: ^8.0.12 css: '@alexanderniebuhr/prettier-plugin-unocss': ^0.0.4 '@unocss/extractor-svelte': ^66.6.8 @@ -36,27 +36,27 @@ catalogs: '@unocss/preset-wind4': ^66.6.8 unocss: ^66.6.8 i18n: - '@inlang/paraglide-js': ^2.17.0 + '@inlang/paraglide-js': ^2.18.0 icons: '@iconify-json/ic': ^1.2.4 - '@iconify-json/material-icon-theme': ^1.2.61 + '@iconify-json/material-icon-theme': ^1.2.64 '@iconify-json/solar': ^1.2.5 lint: '@nanoforge-dev/utils-eslint-config': ^1.0.2 '@nanoforge-dev/utils-prettier-config': ^1.0.2 '@trivago/prettier-plugin-sort-imports': ^6.0.2 - eslint: ^10.2.1 + eslint: ^10.3.0 eslint-plugin-svelte: ^3.17.1 - globals: ^17.5.0 + globals: ^17.6.0 prettier: ^3.8.3 - prettier-plugin-svelte: ^3.5.1 - typescript-eslint: ^8.59.1 + prettier-plugin-svelte: ^3.5.2 + typescript-eslint: ^8.59.3 test: - '@playwright/test': ^1.59.1 - '@vitest/browser-playwright': ^4.1.5 - '@vitest/coverage-v8': ^4.1.5 - playwright: ^1.59.1 - vitest: ^4.1.5 + '@playwright/test': ^1.60.0 + '@vitest/browser-playwright': ^4.1.6 + '@vitest/coverage-v8': ^4.1.6 + playwright: ^1.60.0 + vitest: ^4.1.6 vitest-browser-svelte: ^2.1.1 onlyBuiltDependencies: From b0409f7fb7fdbfbaf718f7bedae2c86dd2dce231 Mon Sep 17 00:00:00 2001 From: Exelo Date: Thu, 14 May 2026 09:41:23 +0900 Subject: [PATCH 15/58] chore: base front refacto --- src/lib/client/action/base.repository.ts | 48 ++++++++++++++ src/lib/client/action/client.ts | 22 +++++++ src/lib/client/action/index.ts | 2 + .../action/repositories/config.repository.ts | 8 +++ .../action/repositories/project.repository.ts | 8 +++ src/lib/client/action/types/config.type.ts | 3 + src/lib/client/action/types/index.ts | 2 + src/lib/client/action/types/project.type.ts | 9 +++ src/lib/client/config/config.ts | 9 +++ src/lib/client/config/config.type.ts | 3 + src/lib/client/config/index.ts | 2 + src/lib/client/file-system/file-system.ts | 5 ++ src/lib/client/file-system/index.ts | 1 + src/lib/client/info/index.ts | 1 + src/lib/client/info/info.store.ts | 5 ++ src/lib/client/info/info.ts | 33 ++++++++++ src/lib/client/info/info.type.ts | 3 + src/lib/client/project/index.ts | 1 + src/lib/client/project/project.ts | 30 +++++++++ .../file-system-api/file-system-directory.ts | 66 +++++++++++++++++++ .../utils/file-system-api/file-system-file.ts | 53 +++++++++++++++ .../file-system-api/file-system-handler.ts | 66 +++++++++++++++++++ .../file-system-api/file-system-manager.ts | 47 +++++++++++++ src/lib/client/utils/file-system-api/index.ts | 3 + src/stores/auth.store.ts | 11 ---- src/stores/project.ts | 3 - 26 files changed, 430 insertions(+), 14 deletions(-) create mode 100644 src/lib/client/action/base.repository.ts create mode 100644 src/lib/client/action/client.ts create mode 100644 src/lib/client/action/index.ts create mode 100644 src/lib/client/action/repositories/config.repository.ts create mode 100644 src/lib/client/action/repositories/project.repository.ts create mode 100644 src/lib/client/action/types/config.type.ts create mode 100644 src/lib/client/action/types/index.ts create mode 100644 src/lib/client/action/types/project.type.ts create mode 100644 src/lib/client/config/config.ts create mode 100644 src/lib/client/config/config.type.ts create mode 100644 src/lib/client/config/index.ts create mode 100644 src/lib/client/file-system/file-system.ts create mode 100644 src/lib/client/file-system/index.ts create mode 100644 src/lib/client/info/index.ts create mode 100644 src/lib/client/info/info.store.ts create mode 100644 src/lib/client/info/info.ts create mode 100644 src/lib/client/info/info.type.ts create mode 100644 src/lib/client/project/index.ts create mode 100644 src/lib/client/project/project.ts create mode 100644 src/lib/client/utils/file-system-api/file-system-directory.ts create mode 100644 src/lib/client/utils/file-system-api/file-system-file.ts create mode 100644 src/lib/client/utils/file-system-api/file-system-handler.ts create mode 100644 src/lib/client/utils/file-system-api/file-system-manager.ts create mode 100644 src/lib/client/utils/file-system-api/index.ts delete mode 100644 src/stores/auth.store.ts delete mode 100644 src/stores/project.ts diff --git a/src/lib/client/action/base.repository.ts b/src/lib/client/action/base.repository.ts new file mode 100644 index 0000000..adc109d --- /dev/null +++ b/src/lib/client/action/base.repository.ts @@ -0,0 +1,48 @@ +import { deserialize } from '$app/forms'; + +import type { HttpClient, RequestOptions } from '@utils/http'; + +export class BaseRepository { + private readonly _client: HttpClient; + + constructor(client: HttpClient) { + this._client = client; + } + + protected run( + path: string, + body?: I, + options?: RequestOptions, + ): Promise { + return this.runRequestBody(path, body, options); + } + + private async runRequestBody(path: string, body?: I, options?: RequestOptions): Promise { + const rawResult = await this._client.postFormData( + path, + this._parseBodyToFormData(body), + options, + ); + const result = deserialize(await rawResult.text()); + + if (result.type === 'redirect') + throw new Error(`Redirect (${result.status}) - ${result.location}`); + if (result.type === 'error') throw new Error(`Error (${result.status}) - ${result.error}`); + if (result.type === 'failure') throw new Error(`Failure (${result.status}) - ${result.data}`); + + return result.data as R; + } + + private _parseBodyToFormData(body?: any): FormData { + const formData = new FormData(); + if (body) { + for (const [key, baseValue] of Object.entries(body)) { + let value: Blob | string; + if (baseValue instanceof File) value = baseValue; + else value = JSON.stringify(baseValue); + formData.append(key, value); + } + } + return formData; + } +} diff --git a/src/lib/client/action/client.ts b/src/lib/client/action/client.ts new file mode 100644 index 0000000..48eb359 --- /dev/null +++ b/src/lib/client/action/client.ts @@ -0,0 +1,22 @@ +import { HttpClient } from '@utils/http'; + +import { ConfigRepository } from './repositories/config.repository'; +import { ProjectRepository } from './repositories/project.repository'; + +export interface ActionClient { + config: ConfigRepository; + project: ProjectRepository; +} + +export const getActionClient = (): ActionClient => { + const client = new HttpClient('', { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }); + + return { + config: new ConfigRepository(client), + project: new ProjectRepository(client), + }; +}; diff --git a/src/lib/client/action/index.ts b/src/lib/client/action/index.ts new file mode 100644 index 0000000..d21081d --- /dev/null +++ b/src/lib/client/action/index.ts @@ -0,0 +1,2 @@ +export { getActionClient, type ActionClient } from './client'; +export * from './types'; diff --git a/src/lib/client/action/repositories/config.repository.ts b/src/lib/client/action/repositories/config.repository.ts new file mode 100644 index 0000000..7cd30c7 --- /dev/null +++ b/src/lib/client/action/repositories/config.repository.ts @@ -0,0 +1,8 @@ +import { BaseRepository } from '../base.repository'; +import type { ActionConfig } from '../types'; + +export class ConfigRepository extends BaseRepository { + fetch(): Promise { + return this.run(`/actions/config?/fetch`); + } +} diff --git a/src/lib/client/action/repositories/project.repository.ts b/src/lib/client/action/repositories/project.repository.ts new file mode 100644 index 0000000..4c5836a --- /dev/null +++ b/src/lib/client/action/repositories/project.repository.ts @@ -0,0 +1,8 @@ +import { BaseRepository } from '../base.repository'; +import type { ActionProject, LoadProjectActionInput } from '../types'; + +export class ProjectRepository extends BaseRepository { + load(input: LoadProjectActionInput): Promise { + return this.run(`/actions/project?/load`, input); + } +} diff --git a/src/lib/client/action/types/config.type.ts b/src/lib/client/action/types/config.type.ts new file mode 100644 index 0000000..715e72b --- /dev/null +++ b/src/lib/client/action/types/config.type.ts @@ -0,0 +1,3 @@ +import type { Config } from '$lib/client/config'; + +export type ActionConfig = Config; diff --git a/src/lib/client/action/types/index.ts b/src/lib/client/action/types/index.ts new file mode 100644 index 0000000..c95bd98 --- /dev/null +++ b/src/lib/client/action/types/index.ts @@ -0,0 +1,2 @@ +export * from './config.type'; +export * from './project.type'; diff --git a/src/lib/client/action/types/project.type.ts b/src/lib/client/action/types/project.type.ts new file mode 100644 index 0000000..43a9ac6 --- /dev/null +++ b/src/lib/client/action/types/project.type.ts @@ -0,0 +1,9 @@ +import type { Project } from '$lib/server/project'; + +export type ActionProject = Project; + +export interface LoadProjectActionInput { + path?: string; + gitUrl?: string; + gatewayId?: string; +} diff --git a/src/lib/client/config/config.ts b/src/lib/client/config/config.ts new file mode 100644 index 0000000..098f8fc --- /dev/null +++ b/src/lib/client/config/config.ts @@ -0,0 +1,9 @@ +import { env } from '$env/dynamic/public'; + +import type { Config } from './config.type'; + +export const getConfig = (): Config => { + return { + mode: env.PUBLIC_MODE === 'offline' ? 'offline' : 'online', + }; +}; diff --git a/src/lib/client/config/config.type.ts b/src/lib/client/config/config.type.ts new file mode 100644 index 0000000..0b54c05 --- /dev/null +++ b/src/lib/client/config/config.type.ts @@ -0,0 +1,3 @@ +export interface Config { + mode: 'offline' | 'online'; +} diff --git a/src/lib/client/config/index.ts b/src/lib/client/config/index.ts new file mode 100644 index 0000000..7bd6087 --- /dev/null +++ b/src/lib/client/config/index.ts @@ -0,0 +1,2 @@ +export type { Config } from './config.type'; +export { fetchConfig } from './config'; diff --git a/src/lib/client/file-system/file-system.ts b/src/lib/client/file-system/file-system.ts new file mode 100644 index 0000000..bcd8bfe --- /dev/null +++ b/src/lib/client/file-system/file-system.ts @@ -0,0 +1,5 @@ +import type { Project } from '$lib/client/project'; + +export class ProjectFileSystem { + constructor(private readonly core: Project) {} +} diff --git a/src/lib/client/file-system/index.ts b/src/lib/client/file-system/index.ts new file mode 100644 index 0000000..7471867 --- /dev/null +++ b/src/lib/client/file-system/index.ts @@ -0,0 +1 @@ +export { ProjectFileSystem } from './file-system'; diff --git a/src/lib/client/info/index.ts b/src/lib/client/info/index.ts new file mode 100644 index 0000000..6297afe --- /dev/null +++ b/src/lib/client/info/index.ts @@ -0,0 +1 @@ +export { InfoHandler } from './info'; diff --git a/src/lib/client/info/info.store.ts b/src/lib/client/info/info.store.ts new file mode 100644 index 0000000..3fb9af4 --- /dev/null +++ b/src/lib/client/info/info.store.ts @@ -0,0 +1,5 @@ +import { writable } from 'svelte/store'; + +import type { ProjectInfo } from './info.type'; + +export const infoStore = writable(); diff --git a/src/lib/client/info/info.ts b/src/lib/client/info/info.ts new file mode 100644 index 0000000..76b8cdf --- /dev/null +++ b/src/lib/client/info/info.ts @@ -0,0 +1,33 @@ +import { get } from 'svelte/store'; + +import { type Project } from '$lib/client/project'; + +import { infoStore } from './info.store'; +import type { ProjectInfo } from './info.type'; + +export class InfoHandler { + static reset(): void { + infoStore.set(null); + } + + constructor(private readonly core: Project) {} + + get(cacheOnly: true): ProjectInfo | null; + get(): Promise; + get(cacheOnly?: boolean): ProjectInfo | null | Promise { + if (cacheOnly) return get(infoStore); + return this.fetch(); + } + + fetch(noCache: boolean = false): Promise { + // @todo implement + void noCache; + return Promise.reject('Not implemented yet'); + } + + async set(input: Partial): Promise { + // @todo implement + void input; + await this.fetch(true); + } +} diff --git a/src/lib/client/info/info.type.ts b/src/lib/client/info/info.type.ts new file mode 100644 index 0000000..0f6b8da --- /dev/null +++ b/src/lib/client/info/info.type.ts @@ -0,0 +1,3 @@ +export interface ProjectInfo { + name: string; +} diff --git a/src/lib/client/project/index.ts b/src/lib/client/project/index.ts new file mode 100644 index 0000000..745ffa0 --- /dev/null +++ b/src/lib/client/project/index.ts @@ -0,0 +1 @@ +export { Project } from './project'; diff --git a/src/lib/client/project/project.ts b/src/lib/client/project/project.ts new file mode 100644 index 0000000..8998b0d --- /dev/null +++ b/src/lib/client/project/project.ts @@ -0,0 +1,30 @@ +import { type ActionClient, getActionClient } from '$lib/client/action'; +import { ProjectFileSystem } from '$lib/client/file-system'; +import { InfoHandler } from '$lib/client/info'; + +export class Project { + private _info: InfoHandler | undefined; + private _actions: ActionClient | undefined; + private _fs: ProjectFileSystem | undefined; + + static reset(): void { + InfoHandler.reset(); + } + + constructor(public id: string) {} + + get info(): InfoHandler { + if (!this._info) this._info = new InfoHandler(this); + return this._info; + } + + get actions(): ActionClient { + if (!this._actions) this._actions = getActionClient(); + return this._actions; + } + + get fs(): ProjectFileSystem { + if (!this._fs) this._fs = new ProjectFileSystem(this); + return this._fs; + } +} diff --git a/src/lib/client/utils/file-system-api/file-system-directory.ts b/src/lib/client/utils/file-system-api/file-system-directory.ts new file mode 100644 index 0000000..7a6ee6e --- /dev/null +++ b/src/lib/client/utils/file-system-api/file-system-directory.ts @@ -0,0 +1,66 @@ +import { FileSystemFile } from './file-system-file'; + +export type FileSystemMapChildren = Map; +export type FileSystemMapDirectoryChildren = Map; + +export type FileSystemMapEntry = [string, FileSystemDirectory | FileSystemFile]; +export type FileSystemMapEntryDirectory = [string, FileSystemDirectory]; + +export class FileSystemDirectory { + readonly handle: FileSystemDirectoryHandle; + + constructor(handle: FileSystemDirectoryHandle) { + this.handle = handle; + } + + getName(): string { + return this.handle.name; + } + + async getFile(name: string, create = true): Promise { + return new FileSystemFile(await this.handle.getFileHandle(name, { create })); + } + + async getDirectory(name: string, create = true): Promise { + return new FileSystemDirectory(await this.handle.getDirectoryHandle(name, { create })); + } + + async getChildren(): Promise { + const result: FileSystemMapChildren = new Map(); + const entries = this.handle.entries(); + + for await (const [name, handle] of entries) { + result.set( + name, + handle instanceof FileSystemDirectoryHandle + ? new FileSystemDirectory(handle) + : new FileSystemFile(handle), + ); + } + return result; + } + + async removeChild(name: string, recursive = true): Promise { + return this.handle.removeEntry(name, { recursive }); + } + + async getParents(root: FileSystemDirectory): Promise { + const parentsFolderNames = await root.handle.resolve(this.handle); + const parents: FileSystemDirectory[] = []; + let previousParent: FileSystemDirectory = root; + + if (!parentsFolderNames) return null; + + for (const folder of parentsFolderNames) { + previousParent = await previousParent.getDirectory(folder); + parents.push(previousParent); + } + return parents; + } + + async clear(): Promise { + for await (const name of this.handle.keys()) { + await this.removeChild(name); + } + } +} diff --git a/src/lib/client/utils/file-system-api/file-system-file.ts b/src/lib/client/utils/file-system-api/file-system-file.ts new file mode 100644 index 0000000..a3d9737 --- /dev/null +++ b/src/lib/client/utils/file-system-api/file-system-file.ts @@ -0,0 +1,53 @@ +export class FileSystemFile { + readonly handle: FileSystemFileHandle; + + constructor(handle: FileSystemFileHandle) { + this.handle = handle; + } + + getName(): string { + return this.handle.name; + } + + getFile(): Promise { + return this.handle.getFile(); + } + + async isSameFile(file: FileSystemFile): Promise { + return await this.handle.isSameEntry(file.handle); + } + + async read(): Promise { + const file = await this.handle.getFile(); + return file.text(); + } + + async readJson(): Promise { + const raw = await this.read(); + return JSON.parse(raw) as T; + } + + async write(text: string): Promise { + const writable = await this.handle.createWritable(); + await writable.write(text); + await writable.close(); + } + + async writeBinary(base64: string): Promise { + const binary = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0)); + const writable = await this.handle.createWritable(); + await writable.write(binary); + await writable.close(); + } + + async writeJson(content: any): Promise { + const raw = JSON.stringify(content); + return this.write(raw); + } + + async getUrl(fileType: string): Promise { + const file = await this.handle.getFile(); + const blob = new Blob([await file.arrayBuffer()], { type: fileType }); + return URL.createObjectURL(blob); + } +} diff --git a/src/lib/client/utils/file-system-api/file-system-handler.ts b/src/lib/client/utils/file-system-api/file-system-handler.ts new file mode 100644 index 0000000..199bb5c --- /dev/null +++ b/src/lib/client/utils/file-system-api/file-system-handler.ts @@ -0,0 +1,66 @@ +export class FileSystemHandler { + private fs!: FileSystemDirectoryHandle; + private readonly rootPath: string; + + constructor(root: string) { + this.rootPath = root; + } + + async getDirectory(path?: string, create?: boolean): Promise { + await this._checkRootHandle(); + if (!path) return this.fs; + return this._getSubDirFromRawPath(this.fs, path, create); + } + + async getFile(path: string, create = true): Promise { + await this._checkRootHandle(); + const paths = this._parsePath(path); + const fileName = paths.pop(); + if (!fileName) { + throw new Error(); + } + const handle = await this._getSubDirFromPath(this.fs, paths, create); + return handle.getFileHandle(fileName, { create }); + } + + private async _checkRootHandle(): Promise { + if (!this.fs) await this._initRootHandle(); + } + + private async _initRootHandle() { + const rootHandle = await navigator.storage.getDirectory(); + this.fs = await this._getSubDirFromRawPath(rootHandle, this.rootPath); + } + + private async _getSubDirFromRawPath( + handle: FileSystemDirectoryHandle, + rawPath: string, + create?: boolean, + ): Promise { + const path = this._parsePath(rawPath); + return this._getSubDirFromPath(handle, path, create); + } + + private async _getSubDirFromPath( + handle: FileSystemDirectoryHandle, + path: string[], + create?: boolean, + ): Promise { + for (const dir of path) { + handle = await this._getSubDir(handle, dir, create); + } + return handle; + } + + private async _getSubDir( + handle: FileSystemDirectoryHandle, + name: string, + create = true, + ): Promise { + return handle.getDirectoryHandle(name, { create }); + } + + private _parsePath(path: string): string[] { + return path.split('/').filter((path: string) => !!path); + } +} diff --git a/src/lib/client/utils/file-system-api/file-system-manager.ts b/src/lib/client/utils/file-system-api/file-system-manager.ts new file mode 100644 index 0000000..8385b50 --- /dev/null +++ b/src/lib/client/utils/file-system-api/file-system-manager.ts @@ -0,0 +1,47 @@ +import { FileSystemDirectory } from './file-system-directory'; +import { FileSystemFile } from './file-system-file'; +import { FileSystemHandler } from './file-system-handler'; + +export class FileSystemManager { + private readonly fs: FileSystemHandler; + + constructor(root: string) { + this.fs = new FileSystemHandler(root); + } + + async getFile(path: string, create?: boolean): Promise { + return new FileSystemFile(await this.fs.getFile(path, create)); + } + + async getDirectory(path?: string, create?: boolean): Promise { + return new FileSystemDirectory(await this.fs.getDirectory(path, create)); + } + + async fileExist(path: string): Promise { + try { + await this.getFile(path, false); + return true; + } catch { + return false; + } + } + + async directoryExist(path: string): Promise { + try { + await this.getDirectory(path, false); + return true; + } catch { + return false; + } + } + + async clear(): Promise { + try { + const dir = await this.getDirectory('/'); + await dir.clear(); + return true; + } catch { + return false; + } + } +} diff --git a/src/lib/client/utils/file-system-api/index.ts b/src/lib/client/utils/file-system-api/index.ts new file mode 100644 index 0000000..830dc1b --- /dev/null +++ b/src/lib/client/utils/file-system-api/index.ts @@ -0,0 +1,3 @@ +export { FileSystemDirectory } from './file-system-directory'; +export { FileSystemFile } from './file-system-file'; +export { FileSystemManager } from './file-system-manager'; diff --git a/src/stores/auth.store.ts b/src/stores/auth.store.ts deleted file mode 100644 index b8fcb5f..0000000 --- a/src/stores/auth.store.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { writable } from 'svelte/store'; - -export const authStore = writable<{ - accessToken: string | null; - refreshToken: string | null; - tokenExpiresAt: Date | null; -}>({ - accessToken: null, - refreshToken: null, - tokenExpiresAt: null, -}); diff --git a/src/stores/project.ts b/src/stores/project.ts deleted file mode 100644 index 74a9c72..0000000 --- a/src/stores/project.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { type Writable, writable } from 'svelte/store'; - -export const projectPathStore: Writable = writable(''); From 87a292d49bc2222d1827b9cc59332c5685019f4c Mon Sep 17 00:00:00 2001 From: Exelo Date: Fri, 15 May 2026 13:00:41 +0900 Subject: [PATCH 16/58] chore: add loader and fs sync --- eslint.config.js | 1 + src/lib/client/action/client.ts | 3 + .../action/repositories/loader.repository.ts | 12 ++ src/lib/client/action/types/index.ts | 1 + src/lib/client/action/types/loader.type.ts | 5 + src/lib/client/file-system/file-system.ts | 5 - src/lib/client/file-system/index.ts | 1 - src/lib/client/loader/index.ts | 4 + src/lib/client/loader/loader.ts | 91 +++++++++++ .../client/loader/types/event-emitter.type.ts | 27 ++++ src/lib/client/loader/types/game.type.ts | 14 ++ src/lib/client/loader/types/manifest.type.ts | 9 ++ src/lib/client/project/project.ts | 15 +- src/lib/client/sync-file-system/index.ts | 3 + .../client/sync-file-system/sfs-directory.ts | 29 ++++ src/lib/client/sync-file-system/sfs-file.ts | 82 ++++++++++ src/lib/client/sync-file-system/sfs.ts | 35 +++++ .../utils}/event-emitter.ts | 0 .../file-system-api/file-system-directory.ts | 66 -------- .../utils/file-system-api/file-system-file.ts | 53 ------- .../file-system/file-system-directory.ts | 11 +- .../utils/file-system/file-system-file.ts | 146 ++++++++++++++++++ .../file-system-handler.ts | 0 .../file-system-manager.ts | 0 .../{file-system-api => file-system}/index.ts | 0 .../local-file-system/project-file-system.ts | 0 src/lib/loader/client/gameFiles.ts | 2 +- .../loader/client/types/event-emitter.type.ts | 28 +--- src/lib/loader/client/types/game.type.ts | 15 +- src/lib/loader/client/types/manifest.type.ts | 10 +- .../file-system/file-system-file.ts | 53 ------- .../file-system/file-system-handler.ts | 66 -------- .../file-system/file-system-manager.ts | 47 ------ src/lib/utils-client/file-system/index.ts | 3 - src/routes/fs/build/+server.ts | 2 +- src/routes/fs/project/+server.ts | 2 +- svelte.config.js | 2 +- 37 files changed, 490 insertions(+), 353 deletions(-) create mode 100644 src/lib/client/action/repositories/loader.repository.ts create mode 100644 src/lib/client/action/types/loader.type.ts delete mode 100644 src/lib/client/file-system/file-system.ts delete mode 100644 src/lib/client/file-system/index.ts create mode 100644 src/lib/client/loader/index.ts create mode 100644 src/lib/client/loader/loader.ts create mode 100644 src/lib/client/loader/types/event-emitter.type.ts create mode 100644 src/lib/client/loader/types/game.type.ts create mode 100644 src/lib/client/loader/types/manifest.type.ts create mode 100644 src/lib/client/sync-file-system/index.ts create mode 100644 src/lib/client/sync-file-system/sfs-directory.ts create mode 100644 src/lib/client/sync-file-system/sfs-file.ts create mode 100644 src/lib/client/sync-file-system/sfs.ts rename src/lib/{utils-client => client/utils}/event-emitter.ts (100%) delete mode 100644 src/lib/client/utils/file-system-api/file-system-directory.ts delete mode 100644 src/lib/client/utils/file-system-api/file-system-file.ts rename src/lib/{utils-client => client/utils}/file-system/file-system-directory.ts (90%) create mode 100644 src/lib/client/utils/file-system/file-system-file.ts rename src/lib/client/utils/{file-system-api => file-system}/file-system-handler.ts (100%) rename src/lib/client/utils/{file-system-api => file-system}/file-system-manager.ts (100%) rename src/lib/client/utils/{file-system-api => file-system}/index.ts (100%) rename src/lib/{utils-client => client/utils}/local-file-system/project-file-system.ts (100%) delete mode 100644 src/lib/utils-client/file-system/file-system-file.ts delete mode 100644 src/lib/utils-client/file-system/file-system-handler.ts delete mode 100644 src/lib/utils-client/file-system/file-system-manager.ts delete mode 100644 src/lib/utils-client/file-system/index.ts diff --git a/eslint.config.js b/eslint.config.js index 5fa6710..670c9dd 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -24,6 +24,7 @@ export default [ { rules: { 'svelte/no-unused-svelte-ignore': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', }, }, ]; diff --git a/src/lib/client/action/client.ts b/src/lib/client/action/client.ts index 48eb359..2b233eb 100644 --- a/src/lib/client/action/client.ts +++ b/src/lib/client/action/client.ts @@ -1,10 +1,12 @@ import { HttpClient } from '@utils/http'; import { ConfigRepository } from './repositories/config.repository'; +import { ProjectLoaderRepository } from './repositories/loader.repository'; import { ProjectRepository } from './repositories/project.repository'; export interface ActionClient { config: ConfigRepository; + loader: ProjectLoaderRepository; project: ProjectRepository; } @@ -17,6 +19,7 @@ export const getActionClient = (): ActionClient => { return { config: new ConfigRepository(client), + loader: new ProjectLoaderRepository(client), project: new ProjectRepository(client), }; }; diff --git a/src/lib/client/action/repositories/loader.repository.ts b/src/lib/client/action/repositories/loader.repository.ts new file mode 100644 index 0000000..c5782c8 --- /dev/null +++ b/src/lib/client/action/repositories/loader.repository.ts @@ -0,0 +1,12 @@ +import { BaseRepository } from '../base.repository'; +import type { ActionLoaderEnv, ActionLoaderManifest } from '../types'; + +export class ProjectLoaderRepository extends BaseRepository { + env(): Promise { + return this.run(`/actions/project/loader?/env`); + } + + manifest(): Promise { + return this.run(`/actions/project/loader?/manifest`); + } +} diff --git a/src/lib/client/action/types/index.ts b/src/lib/client/action/types/index.ts index c95bd98..6d10516 100644 --- a/src/lib/client/action/types/index.ts +++ b/src/lib/client/action/types/index.ts @@ -1,2 +1,3 @@ export * from './config.type'; +export * from './loader.type'; export * from './project.type'; diff --git a/src/lib/client/action/types/loader.type.ts b/src/lib/client/action/types/loader.type.ts new file mode 100644 index 0000000..4381c56 --- /dev/null +++ b/src/lib/client/action/types/loader.type.ts @@ -0,0 +1,5 @@ +import type { IManifest } from '$lib/client/loader'; + +export type ActionLoaderManifest = IManifest; + +export type ActionLoaderEnv = Record; diff --git a/src/lib/client/file-system/file-system.ts b/src/lib/client/file-system/file-system.ts deleted file mode 100644 index bcd8bfe..0000000 --- a/src/lib/client/file-system/file-system.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { Project } from '$lib/client/project'; - -export class ProjectFileSystem { - constructor(private readonly core: Project) {} -} diff --git a/src/lib/client/file-system/index.ts b/src/lib/client/file-system/index.ts deleted file mode 100644 index 7471867..0000000 --- a/src/lib/client/file-system/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ProjectFileSystem } from './file-system'; diff --git a/src/lib/client/loader/index.ts b/src/lib/client/loader/index.ts new file mode 100644 index 0000000..7fcc917 --- /dev/null +++ b/src/lib/client/loader/index.ts @@ -0,0 +1,4 @@ +export { Loader } from './loader'; +export * from './types/event-emitter.type'; +export * from './types/game.type'; +export * from './types/manifest.type'; diff --git a/src/lib/client/loader/loader.ts b/src/lib/client/loader/loader.ts new file mode 100644 index 0000000..4d12428 --- /dev/null +++ b/src/lib/client/loader/loader.ts @@ -0,0 +1,91 @@ +import type { Project } from '$lib/client/project'; +import { SyncFileSystem } from '$lib/client/sync-file-system'; + +import { EventEmitter } from '@utils-client/event-emitter'; + +import type { IGameOptions } from './types/game.type'; +import type { IExtendedManifestFile, IManifest } from './types/manifest.type'; + +type MainFunction = (options: IGameOptions) => Promise; + +// @todo tmp events emitters +export const coreEvents = new EventEmitter(); +export const editorEvents = new EventEmitter(); + +export class Loader { + private readonly fs: SyncFileSystem; + + constructor(private readonly core: Project) { + this.fs = new SyncFileSystem(this.core, 'build'); + } + + async start(canvas: HTMLCanvasElement): Promise { + const manifest = await this.fetchManifest(); + const env = await this.fetchEnv(); + const { mainFile, files } = await this.resolveGameFiles(manifest); + // @todo to implement + const save = { + libraries: [], + components: [], + systems: [], + entities: [], + }; + + const main = await this.loadMainFile(mainFile); + + main({ + files, + env, + editor: { + save, + coreEvents: coreEvents, + editorEvents: editorEvents, + }, + canvas, + }).then(() => console.log('Game ended')); + } + + private async loadMainFile(file: string): Promise { + const res = await import(/* @vite-ignore */ file); + if (res['main']) return res['main']; + throw new Error('No main function found in the main.js file'); + } + + private fetchEnv(): Promise> { + return this.core.actions.loader.env(); + } + + private fetchManifest(): Promise { + return this.core.actions.loader.manifest(); + } + + private async resolveGameFiles( + manifest: IManifest, + ): Promise<{ mainFile: string; files: Map }> { + const files = await this.fetchFiles(manifest); + + let mainFile: string | undefined; + const resMap = new Map(); + + for (const file of files) { + if (file.gamePath === '/main.js') { + mainFile = file.localPath; + continue; + } + resMap.set(file.gamePath, file.localPath); + } + + if (!mainFile) throw new Error('No main.js file found in the manifest'); + return { mainFile, files: resMap }; + } + + private async fetchFiles(manifest: IManifest): Promise { + return await Promise.all( + manifest.files.map(async ({ path }) => { + const file = await this.fs.getFile(path); + await file.fetch(); + return { gamePath: path, localPath: await file.getUrl() }; + }), + ); + } +} diff --git a/src/lib/client/loader/types/event-emitter.type.ts b/src/lib/client/loader/types/event-emitter.type.ts new file mode 100644 index 0000000..7941327 --- /dev/null +++ b/src/lib/client/loader/types/event-emitter.type.ts @@ -0,0 +1,27 @@ +export enum EventTypeEnum { + HOT_RELOAD = 'hot-reload', + HARD_RELOAD = 'hard-reload', + PAUSE_GAME = 'pause-game', + STOP_GAME = 'stop-game', + UNPAUSE_GAME = 'unpause-game', +} + +export type ListenerType = (...args: any[]) => void; + +export interface IEventEmitter { + listeners: Record; + eventQueue: { event: EventTypeEnum | string; args: any[] }[]; + + runEvents: () => void; + + emitEvent: (event: EventTypeEnum, ...args: any) => void; + + addListener: (event: EventTypeEnum | string, listener: ListenerType) => void; + on: (event: EventTypeEnum | string, listener: ListenerType) => void; + + removeListener: (event: EventTypeEnum | string, listener: ListenerType) => void; + off: (event: EventTypeEnum | string, listener: ListenerType) => void; + + removeListenersForEvent: (event: EventTypeEnum | string) => void; + removeAllListeners: () => void; +} diff --git a/src/lib/client/loader/types/game.type.ts b/src/lib/client/loader/types/game.type.ts new file mode 100644 index 0000000..703f27d --- /dev/null +++ b/src/lib/client/loader/types/game.type.ts @@ -0,0 +1,14 @@ +import type { Save } from '@utils/types'; + +import type { IEventEmitter } from './event-emitter.type'; + +export interface IGameOptions { + canvas: HTMLCanvasElement; + files: Map; + env: Record; + editor: { + save: Save; + coreEvents: IEventEmitter; + editorEvents: IEventEmitter; + }; +} diff --git a/src/lib/client/loader/types/manifest.type.ts b/src/lib/client/loader/types/manifest.type.ts new file mode 100644 index 0000000..a9b59a4 --- /dev/null +++ b/src/lib/client/loader/types/manifest.type.ts @@ -0,0 +1,9 @@ +export interface IManifest { + version: string; + files: { path: string }[]; +} + +export interface IExtendedManifestFile { + gamePath: string; + localPath: string; +} diff --git a/src/lib/client/project/project.ts b/src/lib/client/project/project.ts index 8998b0d..7e80048 100644 --- a/src/lib/client/project/project.ts +++ b/src/lib/client/project/project.ts @@ -1,11 +1,13 @@ import { type ActionClient, getActionClient } from '$lib/client/action'; -import { ProjectFileSystem } from '$lib/client/file-system'; import { InfoHandler } from '$lib/client/info'; +import { Loader } from '$lib/client/loader'; +import { SyncFileSystem } from '$lib/client/sync-file-system'; export class Project { private _info: InfoHandler | undefined; private _actions: ActionClient | undefined; - private _fs: ProjectFileSystem | undefined; + private _fs: SyncFileSystem | undefined; + private _loader: Loader | undefined; static reset(): void { InfoHandler.reset(); @@ -23,8 +25,13 @@ export class Project { return this._actions; } - get fs(): ProjectFileSystem { - if (!this._fs) this._fs = new ProjectFileSystem(this); + get fs(): SyncFileSystem { + if (!this._fs) this._fs = new SyncFileSystem(this, 'project'); return this._fs; } + + get loader(): Loader { + if (!this._loader) this._loader = new Loader(this); + return this._loader; + } } diff --git a/src/lib/client/sync-file-system/index.ts b/src/lib/client/sync-file-system/index.ts new file mode 100644 index 0000000..e99e9d6 --- /dev/null +++ b/src/lib/client/sync-file-system/index.ts @@ -0,0 +1,3 @@ +export { SyncFileSystem } from './sfs'; +export { SfsDirectory } from './sfs-directory'; +export { SfsFile } from './sfs-file'; diff --git a/src/lib/client/sync-file-system/sfs-directory.ts b/src/lib/client/sync-file-system/sfs-directory.ts new file mode 100644 index 0000000..12a0076 --- /dev/null +++ b/src/lib/client/sync-file-system/sfs-directory.ts @@ -0,0 +1,29 @@ +import { type SyncFileSystem } from '$lib/client/sync-file-system/sfs'; + +import { type FileSystemDirectory } from '@utils-client/file-system'; + +import { SfsFile } from './sfs-file'; + +export class SfsDirectory { + constructor( + private readonly _handler: SyncFileSystem, + private _cache: FileSystemDirectory, + private readonly _path: string, + ) {} + + get path(): string { + return this._path; + } + + async getFile(path: string): Promise { + const fullPath = `${this._path}/${path}`; + if (await this._cache.fileExist(path)) + return new SfsFile(this._handler, await this._cache?.getFile(path, false), fullPath); + return new SfsFile(this._handler, null, fullPath); + } + + async getDirectory(path: string): Promise { + const fullPath = `${this._path}/${path}`; + return new SfsDirectory(this._handler, await this._cache.getDirectory(path, true), fullPath); + } +} diff --git a/src/lib/client/sync-file-system/sfs-file.ts b/src/lib/client/sync-file-system/sfs-file.ts new file mode 100644 index 0000000..eb4f100 --- /dev/null +++ b/src/lib/client/sync-file-system/sfs-file.ts @@ -0,0 +1,82 @@ +import type { SyncFileSystem } from '$lib/client/sync-file-system/sfs'; + +import { type FileSystemFile } from '@utils-client/file-system'; + +export class SfsFile { + private readonly _route: string; + + constructor( + private readonly _handler: SyncFileSystem, + private _cache: FileSystemFile | null, + private readonly _path: string, + ) { + this._route = `/fs/${this._handler.route}?path=${this._path}`; + } + + get path(): string { + return this._path; + } + + async getUrl(): Promise { + await this._preRead(); + return this._cache!.getUrl(); + } + + async read(): Promise { + await this._preRead(); + return this._cache!.read(); + } + + async readJson(): Promise { + await this._preRead(); + return this._cache!.readJson(); + } + + async fetch(): Promise { + await this._preWrite(); + const res = await fetch(this._route, { + method: 'GET', + }); + if (!res.ok) { + throw new Error('Failed to fetch file'); + } + const b = await res.blob(); + const stream = await this._cache!.handle.createWritable(); + await stream.write(b); + await stream.close(); + } + + async write(test: string): Promise { + await this._preWrite(); + await this._cache!.write(test); + await this.sync(); + } + + async writeJson(content: any): Promise { + await this._preWrite(); + await this._cache!.writeJson(content); + await this.sync(); + } + + async sync(): Promise { + if (!this._cache) return; + const file = await this._cache.getFile(); + const res = await fetch(this._route, { + body: file.stream(), + method: 'POST', + }); + if (!res.ok) throw new Error('Failed to sync file'); + } + + private async _preRead() { + if (!this._cache) { + await this.fetch(); + } + } + + private async _preWrite() { + if (!this._cache) { + this._cache = await this._handler.cache.getFile(this.path, true); + } + } +} diff --git a/src/lib/client/sync-file-system/sfs.ts b/src/lib/client/sync-file-system/sfs.ts new file mode 100644 index 0000000..5558ece --- /dev/null +++ b/src/lib/client/sync-file-system/sfs.ts @@ -0,0 +1,35 @@ +import type { Project } from '$lib/client/project'; + +import { FileSystemManager } from '@utils-client/file-system'; + +import { SfsDirectory } from './sfs-directory'; +import { SfsFile } from './sfs-file'; + +export type SyncFileSystemPart = 'build' | 'project'; + +const FS_ROUTE: Record = { + build: '/fs/build', + project: '/fs/project', +}; + +export class SyncFileSystem { + public readonly route: string; + public readonly cache: FileSystemManager; + + constructor(project: Project, part: SyncFileSystemPart) { + this.route = FS_ROUTE[part]; + this.cache = new FileSystemManager(`projects/${project.id}/${part}`); + } + + async getFile(path: string): Promise { + return new SfsFile( + this, + (await this.cache.fileExist(path)) ? await this.cache.getFile(path, false) : null, + path, + ); + } + + async getDirectory(path?: string): Promise { + return new SfsDirectory(this, await this.cache.getDirectory(path, true), path ?? ''); + } +} diff --git a/src/lib/utils-client/event-emitter.ts b/src/lib/client/utils/event-emitter.ts similarity index 100% rename from src/lib/utils-client/event-emitter.ts rename to src/lib/client/utils/event-emitter.ts diff --git a/src/lib/client/utils/file-system-api/file-system-directory.ts b/src/lib/client/utils/file-system-api/file-system-directory.ts deleted file mode 100644 index 7a6ee6e..0000000 --- a/src/lib/client/utils/file-system-api/file-system-directory.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { FileSystemFile } from './file-system-file'; - -export type FileSystemMapChildren = Map; -export type FileSystemMapDirectoryChildren = Map; - -export type FileSystemMapEntry = [string, FileSystemDirectory | FileSystemFile]; -export type FileSystemMapEntryDirectory = [string, FileSystemDirectory]; - -export class FileSystemDirectory { - readonly handle: FileSystemDirectoryHandle; - - constructor(handle: FileSystemDirectoryHandle) { - this.handle = handle; - } - - getName(): string { - return this.handle.name; - } - - async getFile(name: string, create = true): Promise { - return new FileSystemFile(await this.handle.getFileHandle(name, { create })); - } - - async getDirectory(name: string, create = true): Promise { - return new FileSystemDirectory(await this.handle.getDirectoryHandle(name, { create })); - } - - async getChildren(): Promise { - const result: FileSystemMapChildren = new Map(); - const entries = this.handle.entries(); - - for await (const [name, handle] of entries) { - result.set( - name, - handle instanceof FileSystemDirectoryHandle - ? new FileSystemDirectory(handle) - : new FileSystemFile(handle), - ); - } - return result; - } - - async removeChild(name: string, recursive = true): Promise { - return this.handle.removeEntry(name, { recursive }); - } - - async getParents(root: FileSystemDirectory): Promise { - const parentsFolderNames = await root.handle.resolve(this.handle); - const parents: FileSystemDirectory[] = []; - let previousParent: FileSystemDirectory = root; - - if (!parentsFolderNames) return null; - - for (const folder of parentsFolderNames) { - previousParent = await previousParent.getDirectory(folder); - parents.push(previousParent); - } - return parents; - } - - async clear(): Promise { - for await (const name of this.handle.keys()) { - await this.removeChild(name); - } - } -} diff --git a/src/lib/client/utils/file-system-api/file-system-file.ts b/src/lib/client/utils/file-system-api/file-system-file.ts deleted file mode 100644 index a3d9737..0000000 --- a/src/lib/client/utils/file-system-api/file-system-file.ts +++ /dev/null @@ -1,53 +0,0 @@ -export class FileSystemFile { - readonly handle: FileSystemFileHandle; - - constructor(handle: FileSystemFileHandle) { - this.handle = handle; - } - - getName(): string { - return this.handle.name; - } - - getFile(): Promise { - return this.handle.getFile(); - } - - async isSameFile(file: FileSystemFile): Promise { - return await this.handle.isSameEntry(file.handle); - } - - async read(): Promise { - const file = await this.handle.getFile(); - return file.text(); - } - - async readJson(): Promise { - const raw = await this.read(); - return JSON.parse(raw) as T; - } - - async write(text: string): Promise { - const writable = await this.handle.createWritable(); - await writable.write(text); - await writable.close(); - } - - async writeBinary(base64: string): Promise { - const binary = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0)); - const writable = await this.handle.createWritable(); - await writable.write(binary); - await writable.close(); - } - - async writeJson(content: any): Promise { - const raw = JSON.stringify(content); - return this.write(raw); - } - - async getUrl(fileType: string): Promise { - const file = await this.handle.getFile(); - const blob = new Blob([await file.arrayBuffer()], { type: fileType }); - return URL.createObjectURL(blob); - } -} diff --git a/src/lib/utils-client/file-system/file-system-directory.ts b/src/lib/client/utils/file-system/file-system-directory.ts similarity index 90% rename from src/lib/utils-client/file-system/file-system-directory.ts rename to src/lib/client/utils/file-system/file-system-directory.ts index 7a6ee6e..b1656eb 100644 --- a/src/lib/utils-client/file-system/file-system-directory.ts +++ b/src/lib/client/utils/file-system/file-system-directory.ts @@ -13,7 +13,7 @@ export class FileSystemDirectory { this.handle = handle; } - getName(): string { + get name(): string { return this.handle.name; } @@ -21,6 +21,15 @@ export class FileSystemDirectory { return new FileSystemFile(await this.handle.getFileHandle(name, { create })); } + async fileExist(name: string): Promise { + try { + await this.handle.getFileHandle(name, { create: false }); + return true; + } catch { + return false; + } + } + async getDirectory(name: string, create = true): Promise { return new FileSystemDirectory(await this.handle.getDirectoryHandle(name, { create })); } diff --git a/src/lib/client/utils/file-system/file-system-file.ts b/src/lib/client/utils/file-system/file-system-file.ts new file mode 100644 index 0000000..c3ab740 --- /dev/null +++ b/src/lib/client/utils/file-system/file-system-file.ts @@ -0,0 +1,146 @@ +const FILE_TYPES = { + aac: 'audio/aac', + abw: 'application/x-abiword', + apng: 'image/apng', + arc: 'application/x-freearc', + avi: 'video/x-msvideo', + avif: 'image/avif', + azw: 'application/vnd.amazon.ebook', + bin: 'application/octet-stream', + bmp: 'image/bmp', + bz: 'application/x-bzip', + bz2: 'application/x-bzip2', + cda: 'application/x-cdf', + cjs: 'text/javascript', + csh: 'application/x-csh', + css: 'text/css', + csv: 'text/csv', + doc: 'application/msword', + docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + eot: 'application/vnd.ms-fontobject', + epub: 'application/epub+zip', + gz: 'application/gzip', + gif: 'image/gif', + htm: 'text/html', + html: 'text/html', + ico: 'image/vnd.microsoft.icon', + ics: 'text/calendar', + jar: 'application/java-archive', + jpeg: 'image/jpeg', + jpg: 'image/jpeg', + js: 'application/javascript', + json: 'application/json', + jsonld: 'application/ld+json', + md: 'text/markdown', + mid: 'audio/midi', + midi: 'audio/midi', + mjs: 'text/javascript', + mp3: 'audio/mpeg', + mp4: 'video/mp4', + mpeg: 'video/mpeg', + mpkg: 'application/vnd.apple.installer+xml', + odp: 'application/vnd.oasis.opendocument.presentation', + ods: 'application/vnd.oasis.opendocument.spreadsheet', + odt: 'application/vnd.oasis.opendocument.text', + oga: 'audio/ogg', + ogv: 'video/ogg', + ogx: 'application/ogg', + opus: 'audio/ogg', + otf: 'font/otf', + png: 'image/png', + pdf: 'application/pdf', + php: 'application/x-httpd-php', + ppt: 'application/vnd.ms-powerpoint', + pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + rar: 'application/vnd.rar', + rtf: 'application/rtf', + sh: 'application/x-sh', + svg: 'image/svg+xml', + swf: 'application/x-shockwave-flash', + tar: 'application/x-tar', + tif: 'image/tiff', + tiff: 'image/tiff', + ts: 'text/plain', + ttf: 'font/ttf', + txt: 'text/plain', + vsd: 'application/vnd.visio', + wasm: 'application/wasm', + wav: 'audio/x-wav', + weba: 'audio/webm', + webm: 'video/webm', + webmanifest: 'application/manifest+json', + webp: 'image/webp', + wgsl: 'text/wgsl', + woff: 'font/woff', + woff2: 'font/woff2', + xhtml: 'application/xhtml+xml', + xls: 'application/vnd.ms-excel', + xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + xml: 'application/xml', + xul: 'application/vnd.mozilla.xul+xml', + zip: 'application/zip', + '3gp': 'video/3gpp', + '3g2': 'video/3gpp2', + '7z': 'application/x-7z-compressed', +}; + +export class FileSystemFile { + readonly handle: FileSystemFileHandle; + + constructor(handle: FileSystemFileHandle) { + this.handle = handle; + } + + getName(): string { + return this.handle.name; + } + + getFile(): Promise { + return this.handle.getFile(); + } + + async isSameFile(file: FileSystemFile): Promise { + return await this.handle.isSameEntry(file.handle); + } + + async read(): Promise { + const file = await this.handle.getFile(); + return file.text(); + } + + async readJson(): Promise { + const raw = await this.read(); + return JSON.parse(raw) as T; + } + + async write(text: string): Promise { + const writable = await this.handle.createWritable(); + await writable.write(text); + await writable.close(); + } + + async writeBinary(base64: string): Promise { + const binary = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0)); + const writable = await this.handle.createWritable(); + await writable.write(binary); + await writable.close(); + } + + async writeJson(content: any): Promise { + const raw = JSON.stringify(content); + return this.write(raw); + } + + async getUrl(): Promise { + const file = await this.handle.getFile(); + const blob = new Blob([await file.arrayBuffer()], { type: this._resolveFileType(file.name) }); + return URL.createObjectURL(blob); + } + + private _resolveFileType(name: string): string { + const extension = name.split('.').pop(); + const type = FILE_TYPES[extension as keyof typeof FILE_TYPES]; + if (type) return type; + return 'text/plain'; + } +} diff --git a/src/lib/client/utils/file-system-api/file-system-handler.ts b/src/lib/client/utils/file-system/file-system-handler.ts similarity index 100% rename from src/lib/client/utils/file-system-api/file-system-handler.ts rename to src/lib/client/utils/file-system/file-system-handler.ts diff --git a/src/lib/client/utils/file-system-api/file-system-manager.ts b/src/lib/client/utils/file-system/file-system-manager.ts similarity index 100% rename from src/lib/client/utils/file-system-api/file-system-manager.ts rename to src/lib/client/utils/file-system/file-system-manager.ts diff --git a/src/lib/client/utils/file-system-api/index.ts b/src/lib/client/utils/file-system/index.ts similarity index 100% rename from src/lib/client/utils/file-system-api/index.ts rename to src/lib/client/utils/file-system/index.ts diff --git a/src/lib/utils-client/local-file-system/project-file-system.ts b/src/lib/client/utils/local-file-system/project-file-system.ts similarity index 100% rename from src/lib/utils-client/local-file-system/project-file-system.ts rename to src/lib/client/utils/local-file-system/project-file-system.ts diff --git a/src/lib/loader/client/gameFiles.ts b/src/lib/loader/client/gameFiles.ts index 808472a..a987058 100644 --- a/src/lib/loader/client/gameFiles.ts +++ b/src/lib/loader/client/gameFiles.ts @@ -48,7 +48,7 @@ export function fetchGameFiles(manifest: IManifest): Promise void; - -export interface IEventEmitter { - listeners: Record; - eventQueue: { event: EventTypeEnum | string; args: any[] }[]; - - runEvents: () => void; - - emitEvent: (event: EventTypeEnum, ...args: any) => void; - - addListener: (event: EventTypeEnum | string, listener: ListenerType) => void; - on: (event: EventTypeEnum | string, listener: ListenerType) => void; - - removeListener: (event: EventTypeEnum | string, listener: ListenerType) => void; - off: (event: EventTypeEnum | string, listener: ListenerType) => void; - - removeListenersForEvent: (event: EventTypeEnum | string) => void; - removeAllListeners: () => void; -} +export { type IEventEmitter, EventTypeEnum, type ListenerType } from '$lib/client/loader'; diff --git a/src/lib/loader/client/types/game.type.ts b/src/lib/loader/client/types/game.type.ts index 703f27d..ecf39bd 100644 --- a/src/lib/loader/client/types/game.type.ts +++ b/src/lib/loader/client/types/game.type.ts @@ -1,14 +1 @@ -import type { Save } from '@utils/types'; - -import type { IEventEmitter } from './event-emitter.type'; - -export interface IGameOptions { - canvas: HTMLCanvasElement; - files: Map; - env: Record; - editor: { - save: Save; - coreEvents: IEventEmitter; - editorEvents: IEventEmitter; - }; -} +export { type IGameOptions } from '$lib/client/loader'; diff --git a/src/lib/loader/client/types/manifest.type.ts b/src/lib/loader/client/types/manifest.type.ts index a9b59a4..9459ada 100644 --- a/src/lib/loader/client/types/manifest.type.ts +++ b/src/lib/loader/client/types/manifest.type.ts @@ -1,9 +1 @@ -export interface IManifest { - version: string; - files: { path: string }[]; -} - -export interface IExtendedManifestFile { - gamePath: string; - localPath: string; -} +export type { IManifest, IExtendedManifestFile } from '$lib/client/loader'; diff --git a/src/lib/utils-client/file-system/file-system-file.ts b/src/lib/utils-client/file-system/file-system-file.ts deleted file mode 100644 index a3d9737..0000000 --- a/src/lib/utils-client/file-system/file-system-file.ts +++ /dev/null @@ -1,53 +0,0 @@ -export class FileSystemFile { - readonly handle: FileSystemFileHandle; - - constructor(handle: FileSystemFileHandle) { - this.handle = handle; - } - - getName(): string { - return this.handle.name; - } - - getFile(): Promise { - return this.handle.getFile(); - } - - async isSameFile(file: FileSystemFile): Promise { - return await this.handle.isSameEntry(file.handle); - } - - async read(): Promise { - const file = await this.handle.getFile(); - return file.text(); - } - - async readJson(): Promise { - const raw = await this.read(); - return JSON.parse(raw) as T; - } - - async write(text: string): Promise { - const writable = await this.handle.createWritable(); - await writable.write(text); - await writable.close(); - } - - async writeBinary(base64: string): Promise { - const binary = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0)); - const writable = await this.handle.createWritable(); - await writable.write(binary); - await writable.close(); - } - - async writeJson(content: any): Promise { - const raw = JSON.stringify(content); - return this.write(raw); - } - - async getUrl(fileType: string): Promise { - const file = await this.handle.getFile(); - const blob = new Blob([await file.arrayBuffer()], { type: fileType }); - return URL.createObjectURL(blob); - } -} diff --git a/src/lib/utils-client/file-system/file-system-handler.ts b/src/lib/utils-client/file-system/file-system-handler.ts deleted file mode 100644 index 199bb5c..0000000 --- a/src/lib/utils-client/file-system/file-system-handler.ts +++ /dev/null @@ -1,66 +0,0 @@ -export class FileSystemHandler { - private fs!: FileSystemDirectoryHandle; - private readonly rootPath: string; - - constructor(root: string) { - this.rootPath = root; - } - - async getDirectory(path?: string, create?: boolean): Promise { - await this._checkRootHandle(); - if (!path) return this.fs; - return this._getSubDirFromRawPath(this.fs, path, create); - } - - async getFile(path: string, create = true): Promise { - await this._checkRootHandle(); - const paths = this._parsePath(path); - const fileName = paths.pop(); - if (!fileName) { - throw new Error(); - } - const handle = await this._getSubDirFromPath(this.fs, paths, create); - return handle.getFileHandle(fileName, { create }); - } - - private async _checkRootHandle(): Promise { - if (!this.fs) await this._initRootHandle(); - } - - private async _initRootHandle() { - const rootHandle = await navigator.storage.getDirectory(); - this.fs = await this._getSubDirFromRawPath(rootHandle, this.rootPath); - } - - private async _getSubDirFromRawPath( - handle: FileSystemDirectoryHandle, - rawPath: string, - create?: boolean, - ): Promise { - const path = this._parsePath(rawPath); - return this._getSubDirFromPath(handle, path, create); - } - - private async _getSubDirFromPath( - handle: FileSystemDirectoryHandle, - path: string[], - create?: boolean, - ): Promise { - for (const dir of path) { - handle = await this._getSubDir(handle, dir, create); - } - return handle; - } - - private async _getSubDir( - handle: FileSystemDirectoryHandle, - name: string, - create = true, - ): Promise { - return handle.getDirectoryHandle(name, { create }); - } - - private _parsePath(path: string): string[] { - return path.split('/').filter((path: string) => !!path); - } -} diff --git a/src/lib/utils-client/file-system/file-system-manager.ts b/src/lib/utils-client/file-system/file-system-manager.ts deleted file mode 100644 index 8385b50..0000000 --- a/src/lib/utils-client/file-system/file-system-manager.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { FileSystemDirectory } from './file-system-directory'; -import { FileSystemFile } from './file-system-file'; -import { FileSystemHandler } from './file-system-handler'; - -export class FileSystemManager { - private readonly fs: FileSystemHandler; - - constructor(root: string) { - this.fs = new FileSystemHandler(root); - } - - async getFile(path: string, create?: boolean): Promise { - return new FileSystemFile(await this.fs.getFile(path, create)); - } - - async getDirectory(path?: string, create?: boolean): Promise { - return new FileSystemDirectory(await this.fs.getDirectory(path, create)); - } - - async fileExist(path: string): Promise { - try { - await this.getFile(path, false); - return true; - } catch { - return false; - } - } - - async directoryExist(path: string): Promise { - try { - await this.getDirectory(path, false); - return true; - } catch { - return false; - } - } - - async clear(): Promise { - try { - const dir = await this.getDirectory('/'); - await dir.clear(); - return true; - } catch { - return false; - } - } -} diff --git a/src/lib/utils-client/file-system/index.ts b/src/lib/utils-client/file-system/index.ts deleted file mode 100644 index 830dc1b..0000000 --- a/src/lib/utils-client/file-system/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { FileSystemDirectory } from './file-system-directory'; -export { FileSystemFile } from './file-system-file'; -export { FileSystemManager } from './file-system-manager'; diff --git a/src/routes/fs/build/+server.ts b/src/routes/fs/build/+server.ts index e3fa8c0..d329ab2 100644 --- a/src/routes/fs/build/+server.ts +++ b/src/routes/fs/build/+server.ts @@ -11,7 +11,7 @@ export const GET = useRequestHandler(({ event, project }) => { const path = event.url.searchParams.get('path'); if (!path) throw new Exception('Bad Request', 'Missing path query param', 400); - const file = project.client.loader.getFile(path); + const file = project.client.loader.getFile(decodeURIComponent(path)); const stream = file.readStream(); diff --git a/src/routes/fs/project/+server.ts b/src/routes/fs/project/+server.ts index 0a79bed..35c315a 100644 --- a/src/routes/fs/project/+server.ts +++ b/src/routes/fs/project/+server.ts @@ -11,7 +11,7 @@ export const GET = useRequestHandler(({ event, project }) => { const path = event.url.searchParams.get('path'); if (!path) throw new Exception('Bad Request', 'Missing path query param', 400); - const file = project.client.fs.getFile(path); + const file = project.client.fs.getFile(decodeURIComponent(path)); const stream = file.readStream(); diff --git a/svelte.config.js b/svelte.config.js index 5e2c92e..563ec9d 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -14,7 +14,7 @@ export default { }), alias: { '@utils/*': './src/lib/utils/*', - '@utils-client/*': './src/lib/utils-client/*', + '@utils-client/*': './src/lib/client/utils/*', '@utils-server/*': './src/lib/server/utils/*', }, }, From 91d46a6281144017f51e2fdd603aa93babc65451 Mon Sep 17 00:00:00 2001 From: Tchips46 Date: Fri, 15 May 2026 14:18:06 +0900 Subject: [PATCH 17/58] refactor(back): implement cli routes --- .../project/cli/add-component.action.ts | 26 +++++ .../actions/project/cli/add-system.action.ts | 26 +++++ .../actions/project/cli/build.action.ts | 5 + .../actions/project/cli/generate.action.ts | 5 + .../server/actions/project/cli/new.action.ts | 42 ++++++++ src/lib/server/api/base.repository.ts | 8 +- src/lib/server/api/client.ts | 13 ++- .../api/repositories/auth.repository.ts | 1 + .../api/repositories/projects.repository.ts | 1 + .../api/repositories/registry.repository.ts | 8 ++ src/lib/server/api/types/index.ts | 1 + src/lib/server/api/types/registry.type.ts | 7 ++ src/lib/server/cli/cli-defaults.ts | 1 + src/lib/server/cli/cli.ts | 88 ++++++++++++++--- src/lib/server/utils/cli/cli-error.ts | 7 -- src/lib/server/utils/cli/cli-interface.ts | 99 ------------------- .../server/utils/request-handler/handler.ts | 2 +- src/routes/actions/project/+page.server.ts | 10 ++ src/routes/cli/+page.server.ts | 93 ----------------- 19 files changed, 225 insertions(+), 218 deletions(-) create mode 100644 src/lib/server/actions/project/cli/add-component.action.ts create mode 100644 src/lib/server/actions/project/cli/add-system.action.ts create mode 100644 src/lib/server/actions/project/cli/build.action.ts create mode 100644 src/lib/server/actions/project/cli/generate.action.ts create mode 100644 src/lib/server/actions/project/cli/new.action.ts create mode 100644 src/lib/server/api/repositories/registry.repository.ts create mode 100644 src/lib/server/api/types/registry.type.ts delete mode 100644 src/lib/server/utils/cli/cli-error.ts delete mode 100644 src/lib/server/utils/cli/cli-interface.ts delete mode 100644 src/routes/cli/+page.server.ts diff --git a/src/lib/server/actions/project/cli/add-component.action.ts b/src/lib/server/actions/project/cli/add-component.action.ts new file mode 100644 index 0000000..4b1918f --- /dev/null +++ b/src/lib/server/actions/project/cli/add-component.action.ts @@ -0,0 +1,26 @@ +import { useActionHandler } from '@utils-server/request-handler'; + +class AddComponentBody { + componentNames!: [string, ...string[]]; + server: true | undefined; +} +export const addComponentProjectAction = useActionHandler( + async ({ api, body, cli }) => { + const registryComponents = await Promise.all( + body.componentNames.map(async (c) => { + const rc = await api.registry.getComponent(c); + if (rc.type !== 'component') + throw new Error(`Can only add component: ${c} is a ${rc.type}`); + return rc; + }), + ); + + cli.install(body.componentNames, { server: body.server }); + return { + newComponentsPaths: registryComponents.map((rc) => rc._file), + }; + }, + { + body: AddComponentBody, + }, +); diff --git a/src/lib/server/actions/project/cli/add-system.action.ts b/src/lib/server/actions/project/cli/add-system.action.ts new file mode 100644 index 0000000..8105d0b --- /dev/null +++ b/src/lib/server/actions/project/cli/add-system.action.ts @@ -0,0 +1,26 @@ +import { useActionHandler } from '@utils-server/request-handler'; + +class AddSystemBody { + systemNames!: [string, ...string[]]; + server: true | undefined; +} + +export const addSystemProjectAction = useActionHandler( + async ({ api, body, cli }) => { + const registrySystems = await Promise.all( + body.systemNames.map(async (c) => { + const rc = await api.registry.getComponent(c); + if (rc.type !== 'system') throw new Error(`Can only add system: ${c} is a ${rc.type}`); + return rc; + }), + ); + + cli.install(body.systemNames, { server: body.server }); + return { + newSystemsPaths: registrySystems.map((rc) => rc._file), + }; + }, + { + body: AddSystemBody, + }, +); diff --git a/src/lib/server/actions/project/cli/build.action.ts b/src/lib/server/actions/project/cli/build.action.ts new file mode 100644 index 0000000..2ec1f6a --- /dev/null +++ b/src/lib/server/actions/project/cli/build.action.ts @@ -0,0 +1,5 @@ +import { useActionHandler } from '@utils-server/request-handler'; + +export const buildProjectAction = useActionHandler(async ({ cli }) => { + cli.build({ editor: true }); +}); diff --git a/src/lib/server/actions/project/cli/generate.action.ts b/src/lib/server/actions/project/cli/generate.action.ts new file mode 100644 index 0000000..0cd82b8 --- /dev/null +++ b/src/lib/server/actions/project/cli/generate.action.ts @@ -0,0 +1,5 @@ +import { useActionHandler } from '@utils-server/request-handler'; + +export const generateProjectAction = useActionHandler(async ({ cli }) => { + cli.generate({ editor: true }); +}); diff --git a/src/lib/server/actions/project/cli/new.action.ts b/src/lib/server/actions/project/cli/new.action.ts new file mode 100644 index 0000000..5435e51 --- /dev/null +++ b/src/lib/server/actions/project/cli/new.action.ts @@ -0,0 +1,42 @@ +import { resolve } from 'path'; + +import { loadProject } from '$lib/server/project'; + +import { useActionHandler } from '@utils-server/request-handler'; + +class CreateProjectBody { + projectName!: string; + + projectPath?: string; + packageManager?: 'npm' | 'pnpm' | 'yarn' | 'bun'; + language?: 'js' | 'ts'; + multiplayerServer?: boolean; + dockerContainerization?: boolean; + createGitRepository?: boolean; + gitRemote?: string | false; +} + +export const createProjectAction = useActionHandler( + async (handler) => { + const { body, cli } = handler; + cli.new({ + editor: true, + directory: body.projectPath, + name: body.projectName, + path: body.projectName, + packageManager: body.packageManager, + language: body.language, + server: body.multiplayerServer, + docker: body.dockerContainerization, + git: body.createGitRepository, + gitRemote: body.gitRemote, + }); + + return await loadProject({ path: resolve(body.projectPath || '.', body.projectName) }, handler); + }, + { + body: CreateProjectBody, + offlineOnly: true, + projectOptional: true, + }, +); diff --git a/src/lib/server/api/base.repository.ts b/src/lib/server/api/base.repository.ts index 07a452c..08473b5 100644 --- a/src/lib/server/api/base.repository.ts +++ b/src/lib/server/api/base.repository.ts @@ -2,9 +2,11 @@ import type { HttpClient, RequestOptions } from '@utils/http'; export class BaseRepository { private readonly _client: HttpClient; + private readonly _online: boolean; - constructor(client: HttpClient) { + constructor(client: HttpClient, online: boolean) { this._client = client; + this._online = online; } protected get(path: string, options?: RequestOptions): Promise { @@ -39,6 +41,10 @@ export class BaseRepository { return this.runRequest('delete', path, options); } + protected assertOnline() { + if (!this._online) throw new Error('This route is only available in online mode'); + } + private async runRequest( request: 'get' | 'delete', path: string, diff --git a/src/lib/server/api/client.ts b/src/lib/server/api/client.ts index 26c46c2..55a9696 100644 --- a/src/lib/server/api/client.ts +++ b/src/lib/server/api/client.ts @@ -9,10 +9,12 @@ import type { Context } from '@utils-server/request-handler/context'; import { useTokenMiddleware } from './middlewares/refresh-token.middleware'; import { AuthRepository } from './repositories/auth.repository'; import { ProjectRepository } from './repositories/projects.repository'; +import { RegistryRepository } from './repositories/registry.repository'; export interface Api { auth: AuthRepository; projects: ProjectRepository; + registry: RegistryRepository; } export const getNoAuthApi = () => { @@ -26,12 +28,10 @@ export const getNoAuthApi = () => { 'Api-Key': env.API_KEY, }, }); - return { auth: new AuthRepository(client) }; + return { auth: new AuthRepository(client, true) }; }; export const getApi = (context: Context, cookies: Cookies): Api => { - if (!context.online) throw new Error('API is only available in online mode'); - if (!env.API_URL) throw new Error('API_URL is not defined'); if (!env.API_KEY) throw new Error('API_KEY is not defined'); @@ -41,6 +41,9 @@ export const getApi = (context: Context, cookies: Cookies): Api => { 'Api-Key': env.API_KEY, }, }).useMiddlewares(useTokenMiddleware(cookies)); - - return { auth: new AuthRepository(client), projects: new ProjectRepository(client) }; + return { + auth: new AuthRepository(client, context.online), + projects: new ProjectRepository(client, context.online), + registry: new RegistryRepository(client, context.online), + }; }; diff --git a/src/lib/server/api/repositories/auth.repository.ts b/src/lib/server/api/repositories/auth.repository.ts index 184be28..7543e75 100644 --- a/src/lib/server/api/repositories/auth.repository.ts +++ b/src/lib/server/api/repositories/auth.repository.ts @@ -3,6 +3,7 @@ import type { RefreshTokenInput, TokenResponse } from '../types'; export class AuthRepository extends BaseRepository { refreshToken(input: RefreshTokenInput): Promise { + this.assertOnline(); return this.post(`/auth/refresh-token`, input); } } diff --git a/src/lib/server/api/repositories/projects.repository.ts b/src/lib/server/api/repositories/projects.repository.ts index 3a4ffe2..ed4a369 100644 --- a/src/lib/server/api/repositories/projects.repository.ts +++ b/src/lib/server/api/repositories/projects.repository.ts @@ -3,6 +3,7 @@ import type { ApiProject } from '../types'; export class ProjectRepository extends BaseRepository { getProject(id: string): Promise { + this.assertOnline(); return this.get(`/editor/projects/${id}`); } } diff --git a/src/lib/server/api/repositories/registry.repository.ts b/src/lib/server/api/repositories/registry.repository.ts new file mode 100644 index 0000000..04c1612 --- /dev/null +++ b/src/lib/server/api/repositories/registry.repository.ts @@ -0,0 +1,8 @@ +import { BaseRepository } from '../base.repository'; +import type { RegistryComponentType } from '../types'; + +export class RegistryRepository extends BaseRepository { + getComponent(packageName: string): Promise { + return this.get(`/registry/${packageName}`); + } +} diff --git a/src/lib/server/api/types/index.ts b/src/lib/server/api/types/index.ts index e39b144..24d88b4 100644 --- a/src/lib/server/api/types/index.ts +++ b/src/lib/server/api/types/index.ts @@ -1,2 +1,3 @@ export * from './auth.type'; export * from './project.type'; +export * from './registry.type'; diff --git a/src/lib/server/api/types/registry.type.ts b/src/lib/server/api/types/registry.type.ts new file mode 100644 index 0000000..ea8bcd8 --- /dev/null +++ b/src/lib/server/api/types/registry.type.ts @@ -0,0 +1,7 @@ +export interface RegistryComponentType { + name: string; + type: string; + description: string; + tags: string[]; + _file: string; +} diff --git a/src/lib/server/cli/cli-defaults.ts b/src/lib/server/cli/cli-defaults.ts index 360d7d5..38636b2 100644 --- a/src/lib/server/cli/cli-defaults.ts +++ b/src/lib/server/cli/cli-defaults.ts @@ -11,6 +11,7 @@ import type { } from './cli.type'; export const CLI_NEW_DEFAULTS: WithOptional = { + directory: '.', packageManager: 'npm', language: 'ts', strict: false, diff --git a/src/lib/server/cli/cli.ts b/src/lib/server/cli/cli.ts index 475665d..4a342dc 100644 --- a/src/lib/server/cli/cli.ts +++ b/src/lib/server/cli/cli.ts @@ -1,5 +1,15 @@ import { env } from '$env/dynamic/private'; +import { + CLI_BUILD_DEFAULTS, + CLI_CREATE_DEFAULTS, + CLI_DEV_DEFAULTS, + CLI_GENERATE_DEFAULTS, + CLI_INSTALL_DEFAULTS, + CLI_NEW_DEFAULTS, + CLI_START_DEFAULTS, +} from '$lib/server/cli/cli-defaults'; + import { camelToKebab } from '@utils/format'; import type { Context } from '@utils-server/request-handler'; @@ -25,7 +35,7 @@ export class Cli { } new(opts: CliPartial, runOpts?: CliRunOptions): void { - return this.runCommand('new', [], opts, runOpts); + return this.runCommand('new', [], { ...CLI_NEW_DEFAULTS, ...opts }, CLI_NEW_DEFAULTS, runOpts); } install( @@ -34,27 +44,57 @@ export class Cli { runOpts?: CliRunOptions, ): void { this.assertProject(); - return this.runCommand('install', pkgs, { ...opts, directory: this._projectPath }, runOpts); + return this.runCommand( + 'install', + pkgs, + { ...opts, directory: this._projectPath }, + CLI_INSTALL_DEFAULTS, + runOpts, + ); } build(opts: CliPartial, runOpts?: CliRunOptions): void { this.assertProject(); - return this.runCommand('build', [], { ...opts, directory: this._projectPath }, runOpts); + return this.runCommand( + 'build', + [], + { ...opts, directory: this._projectPath }, + CLI_BUILD_DEFAULTS, + runOpts, + ); } start(opts: CliPartial, runOpts?: CliRunOptions): void { this.assertProject(); - return this.runCommand('start', [], { ...opts, directory: this._projectPath }, runOpts); + return this.runCommand( + 'start', + [], + { ...opts, directory: this._projectPath }, + CLI_START_DEFAULTS, + runOpts, + ); } dev(opts: CliPartial, runOpts?: CliRunOptions): void { this.assertProject(); - return this.runCommand('dev', [], { ...opts, directory: this._projectPath }, runOpts); + return this.runCommand( + 'dev', + [], + { ...opts, directory: this._projectPath }, + CLI_DEV_DEFAULTS, + runOpts, + ); } generate(opts: CliPartial, runOpts?: CliRunOptions): void { this.assertProject(); - return this.runCommand('generate', [], { ...opts, directory: this._projectPath }, runOpts); + return this.runCommand( + 'generate', + [], + { ...opts, directory: this._projectPath }, + CLI_GENERATE_DEFAULTS, + runOpts, + ); } create( @@ -63,16 +103,28 @@ export class Cli { runOpts?: CliRunOptions, ): void { this.assertProject(); - return this.runCommand('create', [part], { ...opts, directory: this._projectPath }, runOpts); + return this.runCommand( + 'create', + [part], + { ...opts, directory: this._projectPath }, + CLI_CREATE_DEFAULTS, + runOpts, + ); } private runCommand( command: string, params: string[], opts: Record, + defaultOpts: Record, { async = false }: CliRunOptions = {}, ): void { - const fullCommand = [env.NF_CLI_PATH ?? 'nf', command, ...params, ...this.resolveParams(opts)]; + const fullCommand = [ + env.NF_CLI_PATH ?? 'nf', + command, + ...params, + ...this.resolveParams(opts, defaultOpts), + ]; if (async) { const res = Bun.spawn(fullCommand, { stdout: 'pipe', stderr: 'pipe' }); @@ -94,11 +146,23 @@ export class Cli { } } - private resolveParams(opts: Record): string[] { - const params = []; - for (const [key, value] of Object.entries(opts)) { - if (value === undefined) continue; + private mergeParams(...opts: Record[]) { + const merged: any = {}; + for (const opt of opts) { + for (const [key, value] of Object.entries(opt)) { + if (value === undefined) continue; + merged[key] = value; + } + } + return merged; + } + private resolveParams( + opts: Record, + defaultOpts: Record, + ): string[] { + const params = []; + for (const [key, value] of this.mergeParams(defaultOpts, opts)) { const name = camelToKebab(key); if (typeof value === 'boolean') { diff --git a/src/lib/server/utils/cli/cli-error.ts b/src/lib/server/utils/cli/cli-error.ts deleted file mode 100644 index 834113b..0000000 --- a/src/lib/server/utils/cli/cli-error.ts +++ /dev/null @@ -1,7 +0,0 @@ -export class CliError extends Error { - message: string; - constructor(message: string) { - super(); - this.message = message; - } -} diff --git a/src/lib/server/utils/cli/cli-interface.ts b/src/lib/server/utils/cli/cli-interface.ts deleted file mode 100644 index d46f481..0000000 --- a/src/lib/server/utils/cli/cli-interface.ts +++ /dev/null @@ -1,99 +0,0 @@ -import child_process from 'node:child_process'; - -import { env } from '$env/dynamic/private'; - -import { CliError } from '@utils-server/cli/cli-error'; - -export class CliInterface { - private readonly projectPath: string; - - constructor(projectPath: string) { - this.projectPath = projectPath; - } - - new( - projectName: string, - packageManager: 'npm' | 'yarn' | 'pnpm' | 'bun', - language: 'js' | 'ts', - strictTypeChecking?: boolean, - multiplayerServer?: boolean, - dockerContainerization?: boolean, - generateLintFiles?: boolean, - editor?: boolean, - createGitRepository?: boolean, - gitRemote?: string, - ) { - this._runCliSync([ - `new`, - `-d`, - this.projectPath, - `--name`, - projectName, - `--package-manager`, - packageManager, - `--language`, - language, - strictTypeChecking ? '--strict' : '--no-strict', - multiplayerServer ? '--server' : '--no-server', - '--init-functions', - '--no-skip-install', - dockerContainerization ? '--docker' : '--no-docker', - generateLintFiles ? undefined : '--no-lint', - editor ? '--editor' : undefined, - createGitRepository ? '--git' : '--no-git', - gitRemote ? '--git-remote' : '--no-git-remote', - gitRemote, - ]); - } - - build(editor?: boolean) { - this._runCliSync(['build', `-d`, this.projectPath, editor ? '--editor' : undefined]); - } - - generate(editor?: boolean) { - this._runCliSync(['generate', `-d`, this.projectPath, editor ? '--editor' : undefined]); - } - - addComponent(componentName: string) { - this._runCliSync(['add', `-d`, this.projectPath, componentName]); - } - - private _runCliSync(params: (string | undefined)[]) { - const res = child_process.spawnSync( - env.NF_CLI_PATH, - params.filter((e) => e !== undefined), - ); - if (res.status === null) { - throw new CliError(`Executable ${env.NF_CLI_PATH} cannot be found or executed`); - } - if (res.status !== 0) { - console.log(res.stdout.toString()); - console.error(res.stderr.toString()); - throw new CliError(res.stderr.toString()); - } - } - - private _runCliAsync(params: string[]): number { - const res = child_process.spawn(env.NF_CLI_PATH, params); - - const startTime = Date.now(); - while (res.pid === undefined && Date.now() - startTime < 100) { - /* if I remove this comment the linter is crying */ - } - if (res.pid === undefined) { - throw new CliError('Failed to start process: pid not available'); - } - - res.on('error', () => { - throw new CliError(res.stderr.toString()); - }); - res.on('exit', (code) => { - if (code !== 0 && code !== null) { - console.log(res.stdout.read()?.toString()); - console.log(res.stderr.read()?.toString()); - throw new CliError(`Process exited with code ${code}`); - } - }); - return res.pid; - } -} diff --git a/src/lib/server/utils/request-handler/handler.ts b/src/lib/server/utils/request-handler/handler.ts index 131b945..6f589b5 100644 --- a/src/lib/server/utils/request-handler/handler.ts +++ b/src/lib/server/utils/request-handler/handler.ts @@ -51,7 +51,7 @@ export class Handler { return this._apiCache; } - get cli(): any { + get cli(): Cli { if (!this._cliCache) this._cliCache = new Cli(this._context); return this._cliCache; } diff --git a/src/routes/actions/project/+page.server.ts b/src/routes/actions/project/+page.server.ts index d514791..ac42755 100644 --- a/src/routes/actions/project/+page.server.ts +++ b/src/routes/actions/project/+page.server.ts @@ -1,5 +1,15 @@ +import { addComponentProjectAction } from '$lib/server/actions/project/cli/add-component.action'; +import { addSystemProjectAction } from '$lib/server/actions/project/cli/add-system.action'; +import { buildProjectAction } from '$lib/server/actions/project/cli/build.action'; +import { generateProjectAction } from '$lib/server/actions/project/cli/generate.action'; +import { createProjectAction } from '$lib/server/actions/project/cli/new.action'; import { loadProjectAction } from '$lib/server/actions/project/load.action'; export const actions = { load: loadProjectAction, + new: createProjectAction, + generate: generateProjectAction, + build: buildProjectAction, + addComponent: addComponentProjectAction, + addSystem: addSystemProjectAction, }; diff --git a/src/routes/cli/+page.server.ts b/src/routes/cli/+page.server.ts deleted file mode 100644 index 0ce73a1..0000000 --- a/src/routes/cli/+page.server.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { fail } from '@sveltejs/kit'; - -import { CliError } from '@utils-server/cli/cli-error'; -import { CliInterface } from '@utils-server/cli/cli-interface'; - -import type { Actions } from './$types'; - -export const actions = { - new: async ({ request }) => { - const data = await request.json(); - - if (!data.projectPath) { - return fail(403, { success: false, errorMsg: "Missing arg: 'projectPath'" }); - } - if (!data.projectName) { - return fail(403, { success: false, errorMsg: "Missing arg: 'projectName'" }); - } - if (!data.packageManager) { - return fail(403, { success: false, errorMsg: "Missing arg: 'packageManager'" }); - } - if (!data.language) { - return fail(403, { success: false, errorMsg: "Missing arg: 'language'" }); - } - - try { - new CliInterface(data.projectPath).new( - data.projectName, - data.packageManager, - data.language, - false, - data.multiplayerServer, - data.dockerContainerization, - false, - true, - data.createGitRepository, - data.gitRemote, - ); - return { - success: true, - }; - } catch (e: unknown) { - if (e instanceof CliError) { - return fail(403, { success: false, errorMsg: e.message }); - } - throw e; - } - }, - generate: async ({ locals }) => { - try { - new CliInterface(locals.session.data.path).generate(true); - return { - success: true, - }; - } catch (e: unknown) { - if (e instanceof CliError) { - return fail(403, { success: false, errorMsg: e.message }); - } - throw e; - } - }, - build: async ({ locals }) => { - try { - new CliInterface(locals.session.data.path).build(true); - return { - success: true, - }; - } catch (e: unknown) { - if (e instanceof CliError) { - return fail(403, { success: false, errorMsg: e.message }); - } - throw e; - } - }, - addComponent: async ({ request, locals }) => { - const data = await request.json(); - - if (!data.componentName) { - return fail(403, { success: false, errorMsg: "Missing arg: 'componentName'" }); - } - - try { - new CliInterface(locals.session.data.path).addComponent(data.componentName); - return { - success: true, - }; - } catch (e: unknown) { - if (e instanceof CliError) { - return fail(403, { success: false, errorMsg: e.message }); - } - throw e; - } - }, -} satisfies Actions; From bf627f725be61fec900129e7c28699b67fd7756c Mon Sep 17 00:00:00 2001 From: Tchips46 Date: Fri, 15 May 2026 17:13:46 +0900 Subject: [PATCH 18/58] feat(front): route cli on project repository --- .../action/repositories/project.repository.ts | 24 +++++++++++++++- src/lib/client/action/types/project.type.ts | 28 +++++++++++++++++++ src/lib/client/loader/loader.ts | 4 +-- src/lib/client/utils/event-emitter.ts | 8 +++--- .../project/cli/add-component.action.ts | 1 + 5 files changed, 58 insertions(+), 7 deletions(-) diff --git a/src/lib/client/action/repositories/project.repository.ts b/src/lib/client/action/repositories/project.repository.ts index 4c5836a..161b9ff 100644 --- a/src/lib/client/action/repositories/project.repository.ts +++ b/src/lib/client/action/repositories/project.repository.ts @@ -1,8 +1,30 @@ import { BaseRepository } from '../base.repository'; -import type { ActionProject, LoadProjectActionInput } from '../types'; +import type { + ActionProject, + AddComponentActionInput, + AddRegistryComponentActionResult, + AddSystemActionInput, + CreateProjectActionInput, + LoadProjectActionInput, +} from '../types'; export class ProjectRepository extends BaseRepository { load(input: LoadProjectActionInput): Promise { return this.run(`/actions/project?/load`, input); } + new(input: CreateProjectActionInput): Promise { + return this.run(`/actions/project?/new`, input); + } + generate(): Promise { + return this.run(`/actions/project?/generate`); + } + build(): Promise { + return this.run(`/actions/project?/build`); + } + addComponent(input: AddComponentActionInput): Promise { + return this.run(`/actions/project?/addComponent`, input); + } + addSystem(input: AddSystemActionInput): Promise { + return this.run(`/actions/project?/addSystem`, input); + } } diff --git a/src/lib/client/action/types/project.type.ts b/src/lib/client/action/types/project.type.ts index 43a9ac6..e9fce61 100644 --- a/src/lib/client/action/types/project.type.ts +++ b/src/lib/client/action/types/project.type.ts @@ -7,3 +7,31 @@ export interface LoadProjectActionInput { gitUrl?: string; gatewayId?: string; } + +export interface CreateProjectActionInput { + projectName: string; + + projectPath?: string; + packageManager?: 'npm' | 'pnpm' | 'yarn' | 'bun'; + language?: 'js' | 'ts'; + multiplayerServer?: boolean; + dockerContainerization?: boolean; + createGitRepository?: boolean; + gitRemote?: string | false; +} + +export interface AddRegistryComponentActionResult { + newComponentsPaths: string[]; +} + +export interface AddComponentActionInput { + componentNames: [string, ...string[]]; + + server: true | undefined; +} + +export interface AddSystemActionInput { + systemNames: [string, ...string[]]; + + server: true | undefined; +} diff --git a/src/lib/client/loader/loader.ts b/src/lib/client/loader/loader.ts index 4d12428..4744bc2 100644 --- a/src/lib/client/loader/loader.ts +++ b/src/lib/client/loader/loader.ts @@ -38,8 +38,8 @@ export class Loader { env, editor: { save, - coreEvents: coreEvents, - editorEvents: editorEvents, + coreEvents, + editorEvents, }, canvas, }).then(() => console.log('Game ended')); diff --git a/src/lib/client/utils/event-emitter.ts b/src/lib/client/utils/event-emitter.ts index 68fd197..8f32760 100644 --- a/src/lib/client/utils/event-emitter.ts +++ b/src/lib/client/utils/event-emitter.ts @@ -1,7 +1,7 @@ -import { - type EventTypeEnum, - type IEventEmitter, - type ListenerType, +import type { + EventTypeEnum, + IEventEmitter, + ListenerType, } from '$lib/loader/client/types/event-emitter.type'; export class EventEmitter implements IEventEmitter { diff --git a/src/lib/server/actions/project/cli/add-component.action.ts b/src/lib/server/actions/project/cli/add-component.action.ts index 4b1918f..aa25b0f 100644 --- a/src/lib/server/actions/project/cli/add-component.action.ts +++ b/src/lib/server/actions/project/cli/add-component.action.ts @@ -4,6 +4,7 @@ class AddComponentBody { componentNames!: [string, ...string[]]; server: true | undefined; } + export const addComponentProjectAction = useActionHandler( async ({ api, body, cli }) => { const registryComponents = await Promise.all( From 56228e14bfffc5aa4fb1e152d1b56ec0102acaf8 Mon Sep 17 00:00:00 2001 From: Tchips46 Date: Mon, 18 May 2026 00:42:24 +0900 Subject: [PATCH 19/58] fix(backend): review and create components --- .../action/repositories/project.repository.ts | 31 +++-- src/lib/client/action/types/project.type.ts | 36 ++++-- .../client/project/package/package-handler.ts | 30 +++++ src/lib/client/project/project.ts | 10 ++ .../project/cli/add-component.action.ts | 23 ++-- .../actions/project/cli/add-system.action.ts | 20 +--- .../project/cli/create-component.action.ts | 16 +++ .../project/cli/create-system.action.ts | 16 +++ .../actions/project/loader/env.action.ts | 4 +- .../actions/project/loader/manifest.action.ts | 4 +- .../actions/project/{cli => }/new.action.ts | 0 .../actions/project/save/get-save.action.ts | 5 + .../actions/project/save/set-save.action.ts | 16 +++ src/lib/server/api/base.repository.ts | 2 +- src/lib/server/api/client.ts | 23 ++-- .../api/repositories/registry.repository.ts | 4 +- src/lib/server/api/types/registry.type.ts | 2 +- .../server/project/package/package-handler.ts | 106 ++++++++++++------ .../server/project/package/package.type.ts | 14 +++ .../server/utils/request-handler/handler.ts | 4 +- src/routes/actions/project/+page.server.ts | 18 ++- 21 files changed, 283 insertions(+), 101 deletions(-) create mode 100644 src/lib/client/project/package/package-handler.ts create mode 100644 src/lib/server/actions/project/cli/create-component.action.ts create mode 100644 src/lib/server/actions/project/cli/create-system.action.ts rename src/lib/server/actions/project/{cli => }/new.action.ts (100%) create mode 100644 src/lib/server/actions/project/save/get-save.action.ts create mode 100644 src/lib/server/actions/project/save/set-save.action.ts diff --git a/src/lib/client/action/repositories/project.repository.ts b/src/lib/client/action/repositories/project.repository.ts index 161b9ff..537c0ca 100644 --- a/src/lib/client/action/repositories/project.repository.ts +++ b/src/lib/client/action/repositories/project.repository.ts @@ -1,11 +1,16 @@ import { BaseRepository } from '../base.repository'; import type { ActionProject, - AddComponentActionInput, - AddRegistryComponentActionResult, - AddSystemActionInput, + AddComponentsActionInput, + AddSystemsActionInput, + CreateComponentActionInput, CreateProjectActionInput, + CreateSystemActionInput, + GetSaveResult, LoadProjectActionInput, + NewComponentPackageResult, + NewSystemPackageResult, + SetSaveInput, } from '../types'; export class ProjectRepository extends BaseRepository { @@ -21,10 +26,22 @@ export class ProjectRepository extends BaseRepository { build(): Promise { return this.run(`/actions/project?/build`); } - addComponent(input: AddComponentActionInput): Promise { - return this.run(`/actions/project?/addComponent`, input); + addComponents(input: AddComponentsActionInput): Promise { + return this.run(`/actions/project?/addComponents`, input); } - addSystem(input: AddSystemActionInput): Promise { - return this.run(`/actions/project?/addSystem`, input); + addSystems(input: AddSystemsActionInput): Promise { + return this.run(`/actions/project?/addSystems`, input); + } + createComponent(input: CreateComponentActionInput): Promise { + return this.run(`/actions/project?/createComponent`, input); + } + createSystem(input: CreateSystemActionInput): Promise { + return this.run(`/actions/project?/createSystem`, input); + } + getSave(): Promise { + return this.run(`/actions/project?/getSave`); + } + setSave(input: SetSaveInput): Promise { + return this.run(`/actions/project?/setSave`, input); } } diff --git a/src/lib/client/action/types/project.type.ts b/src/lib/client/action/types/project.type.ts index e9fce61..31b2ecf 100644 --- a/src/lib/client/action/types/project.type.ts +++ b/src/lib/client/action/types/project.type.ts @@ -1,5 +1,9 @@ +import type { EditorComponentManifest, EditorSystemManifest } from '@nanoforge-dev/ecs-lib'; + import type { Project } from '$lib/server/project'; +import type { Save, SaveComponent, SaveSystem } from '@utils/types'; + export type ActionProject = Project; export interface LoadProjectActionInput { @@ -20,18 +24,36 @@ export interface CreateProjectActionInput { gitRemote?: string | false; } -export interface AddRegistryComponentActionResult { - newComponentsPaths: string[]; +export interface NewComponentPackageResult { + manifest: EditorComponentManifest; + save: SaveComponent; } -export interface AddComponentActionInput { - componentNames: [string, ...string[]]; +export interface NewSystemPackageResult { + manifest: EditorSystemManifest; + save: SaveSystem; +} - server: true | undefined; +export interface AddComponentsActionInput { + componentNames: [string, ...string[]]; } -export interface AddSystemActionInput { +export interface AddSystemsActionInput { systemNames: [string, ...string[]]; +} + +export interface CreateComponentActionInput { + componentName: string; +} + +export interface CreateSystemActionInput { + systemName: string; +} + +export interface GetSaveResult { + save: Save; +} - server: true | undefined; +export interface SetSaveInput { + save: Save; } diff --git a/src/lib/client/project/package/package-handler.ts b/src/lib/client/project/package/package-handler.ts new file mode 100644 index 0000000..63b60c7 --- /dev/null +++ b/src/lib/client/project/package/package-handler.ts @@ -0,0 +1,30 @@ +import { get } from 'svelte/store'; + +import { type Project } from '$lib/client/project'; +import { save } from '$lib/components/Widget/EditorGame/game.svelte'; + +export class PackageHandler { + private readonly handler: Project; + + constructor(handler: Project) { + this.handler = handler; + } + + async installComponent(name: string): Promise { + const newComponent = ( + await this.handler.actions.project.addComponents({ componentNames: [name] }) + )[0]; + + const s = get(save); + s.components.push(newComponent.save); + save.set(s); + } + + async installSystem(name: string): Promise { + const newSystem = (await this.handler.actions.project.addSystems({ systemNames: [name] }))[0]; + + const s = get(save); + s.systems.push(newSystem.save); + save.set(s); + } +} diff --git a/src/lib/client/project/project.ts b/src/lib/client/project/project.ts index 7e80048..fc294ee 100644 --- a/src/lib/client/project/project.ts +++ b/src/lib/client/project/project.ts @@ -3,11 +3,14 @@ import { InfoHandler } from '$lib/client/info'; import { Loader } from '$lib/client/loader'; import { SyncFileSystem } from '$lib/client/sync-file-system'; +import type { Save } from '@utils/types'; + export class Project { private _info: InfoHandler | undefined; private _actions: ActionClient | undefined; private _fs: SyncFileSystem | undefined; private _loader: Loader | undefined; + private _save: Save | undefined; static reset(): void { InfoHandler.reset(); @@ -34,4 +37,11 @@ export class Project { if (!this._loader) this._loader = new Loader(this); return this._loader; } + + async save(): Promise { + if (!this._save) { + this._save = (await this.actions.project.getSave()).save; + } + return this._save; + } } diff --git a/src/lib/server/actions/project/cli/add-component.action.ts b/src/lib/server/actions/project/cli/add-component.action.ts index aa25b0f..2916efa 100644 --- a/src/lib/server/actions/project/cli/add-component.action.ts +++ b/src/lib/server/actions/project/cli/add-component.action.ts @@ -1,25 +1,18 @@ +import type { NewComponentPackage } from '$lib/server/project/package/package.type'; + import { useActionHandler } from '@utils-server/request-handler'; class AddComponentBody { componentNames!: [string, ...string[]]; - server: true | undefined; } -export const addComponentProjectAction = useActionHandler( - async ({ api, body, cli }) => { - const registryComponents = await Promise.all( - body.componentNames.map(async (c) => { - const rc = await api.registry.getComponent(c); - if (rc.type !== 'component') - throw new Error(`Can only add component: ${c} is a ${rc.type}`); - return rc; - }), +export const addComponentsProjectAction = useActionHandler( + async ({ body, project }): Promise => { + return await Promise.all( + body.componentNames.map((componentName) => + project.client.package.installComponent(componentName), + ), ); - - cli.install(body.componentNames, { server: body.server }); - return { - newComponentsPaths: registryComponents.map((rc) => rc._file), - }; }, { body: AddComponentBody, diff --git a/src/lib/server/actions/project/cli/add-system.action.ts b/src/lib/server/actions/project/cli/add-system.action.ts index 8105d0b..c62bf4a 100644 --- a/src/lib/server/actions/project/cli/add-system.action.ts +++ b/src/lib/server/actions/project/cli/add-system.action.ts @@ -1,24 +1,16 @@ +import type { NewSystemPackage } from '$lib/server/project/package/package.type'; + import { useActionHandler } from '@utils-server/request-handler'; class AddSystemBody { systemNames!: [string, ...string[]]; - server: true | undefined; } -export const addSystemProjectAction = useActionHandler( - async ({ api, body, cli }) => { - const registrySystems = await Promise.all( - body.systemNames.map(async (c) => { - const rc = await api.registry.getComponent(c); - if (rc.type !== 'system') throw new Error(`Can only add system: ${c} is a ${rc.type}`); - return rc; - }), +export const addSystemsProjectAction = useActionHandler( + async ({ body, project }): Promise => { + return await Promise.all( + body.systemNames.map((systemName) => project.client.package.installSystem(systemName)), ); - - cli.install(body.systemNames, { server: body.server }); - return { - newSystemsPaths: registrySystems.map((rc) => rc._file), - }; }, { body: AddSystemBody, diff --git a/src/lib/server/actions/project/cli/create-component.action.ts b/src/lib/server/actions/project/cli/create-component.action.ts new file mode 100644 index 0000000..ac0ac61 --- /dev/null +++ b/src/lib/server/actions/project/cli/create-component.action.ts @@ -0,0 +1,16 @@ +import type { NewComponentPackage } from '$lib/server/project/package/package.type'; + +import { useActionHandler } from '@utils-server/request-handler'; + +class CreateComponentBody { + componentName!: string; +} + +export const createComponentProjectAction = useActionHandler( + async ({ body, project }): Promise => { + return project.client.package.createComponent(body.componentName); + }, + { + body: CreateComponentBody, + }, +); diff --git a/src/lib/server/actions/project/cli/create-system.action.ts b/src/lib/server/actions/project/cli/create-system.action.ts new file mode 100644 index 0000000..7a48219 --- /dev/null +++ b/src/lib/server/actions/project/cli/create-system.action.ts @@ -0,0 +1,16 @@ +import type { NewSystemPackage } from '$lib/server/project/package/package.type'; + +import { useActionHandler } from '@utils-server/request-handler'; + +class CreateSystemBody { + systemName!: string; +} + +export const createSystemProjectAction = useActionHandler( + async ({ body, project }): Promise => { + return project.client.package.createSystem(body.systemName); + }, + { + body: CreateSystemBody, + }, +); diff --git a/src/lib/server/actions/project/loader/env.action.ts b/src/lib/server/actions/project/loader/env.action.ts index 84e61ce..adc11ef 100644 --- a/src/lib/server/actions/project/loader/env.action.ts +++ b/src/lib/server/actions/project/loader/env.action.ts @@ -1,7 +1,5 @@ import { useActionHandler } from '@utils-server/request-handler'; -export const fetchEnvLoaderAction = useActionHandler(async (handler) => { - const { project } = handler; - +export const fetchEnvLoaderAction = useActionHandler(async ({ project }) => { return project.client.loader.getEnv(); }); diff --git a/src/lib/server/actions/project/loader/manifest.action.ts b/src/lib/server/actions/project/loader/manifest.action.ts index bf2a982..89fec5d 100644 --- a/src/lib/server/actions/project/loader/manifest.action.ts +++ b/src/lib/server/actions/project/loader/manifest.action.ts @@ -1,7 +1,5 @@ import { useActionHandler } from '@utils-server/request-handler'; -export const fetchManifestLoaderAction = useActionHandler(async (handler) => { - const { project } = handler; - +export const fetchManifestLoaderAction = useActionHandler(async ({ project }) => { return project.client.loader.getManifest(); }); diff --git a/src/lib/server/actions/project/cli/new.action.ts b/src/lib/server/actions/project/new.action.ts similarity index 100% rename from src/lib/server/actions/project/cli/new.action.ts rename to src/lib/server/actions/project/new.action.ts diff --git a/src/lib/server/actions/project/save/get-save.action.ts b/src/lib/server/actions/project/save/get-save.action.ts new file mode 100644 index 0000000..a2c7748 --- /dev/null +++ b/src/lib/server/actions/project/save/get-save.action.ts @@ -0,0 +1,5 @@ +import { useActionHandler } from '@utils-server/request-handler'; + +export const getSaveAction = useActionHandler(async ({ project }) => { + return project.client.save.getSave(); +}); diff --git a/src/lib/server/actions/project/save/set-save.action.ts b/src/lib/server/actions/project/save/set-save.action.ts new file mode 100644 index 0000000..4e4ebc9 --- /dev/null +++ b/src/lib/server/actions/project/save/set-save.action.ts @@ -0,0 +1,16 @@ +import { type Save } from '@utils/types'; + +import { useActionHandler } from '@utils-server/request-handler'; + +class SetSaveBody { + save!: Save; +} + +export const setSaveAction = useActionHandler( + async ({ project, body }) => { + return project.client.save.updateSave(body.save); + }, + { + body: SetSaveBody, + }, +); diff --git a/src/lib/server/api/base.repository.ts b/src/lib/server/api/base.repository.ts index 08473b5..65ace14 100644 --- a/src/lib/server/api/base.repository.ts +++ b/src/lib/server/api/base.repository.ts @@ -4,7 +4,7 @@ export class BaseRepository { private readonly _client: HttpClient; private readonly _online: boolean; - constructor(client: HttpClient, online: boolean) { + constructor(client: HttpClient, online: boolean = true) { this._client = client; this._online = online; } diff --git a/src/lib/server/api/client.ts b/src/lib/server/api/client.ts index 55a9696..a9fa4eb 100644 --- a/src/lib/server/api/client.ts +++ b/src/lib/server/api/client.ts @@ -4,8 +4,6 @@ import { env } from '$env/dynamic/private'; import { HttpClient } from '@utils/http'; -import type { Context } from '@utils-server/request-handler/context'; - import { useTokenMiddleware } from './middlewares/refresh-token.middleware'; import { AuthRepository } from './repositories/auth.repository'; import { ProjectRepository } from './repositories/projects.repository'; @@ -13,12 +11,11 @@ import { RegistryRepository } from './repositories/registry.repository'; export interface Api { auth: AuthRepository; - projects: ProjectRepository; + projects?: ProjectRepository; registry: RegistryRepository; } -export const getNoAuthApi = () => { - if (env.PUBLIC_MODE !== 'ONLINE') throw new Error('API is only available in online mode'); +export const getNoAuthApi = (): Api => { if (!env.API_URL) throw new Error('API_URL is not defined'); if (!env.API_KEY) throw new Error('API_KEY is not defined'); @@ -28,10 +25,16 @@ export const getNoAuthApi = () => { 'Api-Key': env.API_KEY, }, }); - return { auth: new AuthRepository(client, true) }; + const isOnline = env.PUBLIC_MODE === 'ONLINE'; + + return { + auth: new AuthRepository(client, isOnline), + registry: new RegistryRepository(client, isOnline), + }; }; -export const getApi = (context: Context, cookies: Cookies): Api => { +export const getApi = (cookies: Cookies): Api => { + if (env.PUBLIC_MODE !== 'ONLINE') throw new Error('API is only available in online mode'); if (!env.API_URL) throw new Error('API_URL is not defined'); if (!env.API_KEY) throw new Error('API_KEY is not defined'); @@ -42,8 +45,8 @@ export const getApi = (context: Context, cookies: Cookies): Api => { }, }).useMiddlewares(useTokenMiddleware(cookies)); return { - auth: new AuthRepository(client, context.online), - projects: new ProjectRepository(client, context.online), - registry: new RegistryRepository(client, context.online), + auth: new AuthRepository(client), + projects: new ProjectRepository(client), + registry: new RegistryRepository(client), }; }; diff --git a/src/lib/server/api/repositories/registry.repository.ts b/src/lib/server/api/repositories/registry.repository.ts index 04c1612..fa299a7 100644 --- a/src/lib/server/api/repositories/registry.repository.ts +++ b/src/lib/server/api/repositories/registry.repository.ts @@ -1,8 +1,8 @@ import { BaseRepository } from '../base.repository'; -import type { RegistryComponentType } from '../types'; +import type { RegistryPackageType } from '../types'; export class RegistryRepository extends BaseRepository { - getComponent(packageName: string): Promise { + getPackage(packageName: string): Promise { return this.get(`/registry/${packageName}`); } } diff --git a/src/lib/server/api/types/registry.type.ts b/src/lib/server/api/types/registry.type.ts index ea8bcd8..b90b67f 100644 --- a/src/lib/server/api/types/registry.type.ts +++ b/src/lib/server/api/types/registry.type.ts @@ -1,4 +1,4 @@ -export interface RegistryComponentType { +export interface RegistryPackageType { name: string; type: string; description: string; diff --git a/src/lib/server/project/package/package-handler.ts b/src/lib/server/project/package/package-handler.ts index 6fc4aa2..4212b02 100644 --- a/src/lib/server/project/package/package-handler.ts +++ b/src/lib/server/project/package/package-handler.ts @@ -1,11 +1,14 @@ +import type { EditorComponentManifest, EditorSystemManifest } from '@nanoforge-dev/ecs-lib'; import { join } from 'path'; +import { getNoAuthApi } from '$lib/server/api/client'; +import { FileSystemError } from '$lib/server/file-system/file-system-error'; import { type ProjectHandler } from '$lib/server/project'; import { toCamelCase, toKebabCase, toPascalCase } from '@utils/format'; import { resolveManifest } from './manifest-resolver'; -import { PackageTypeEnum } from './package.type'; +import { type NewComponentPackage, type NewSystemPackage, PackageTypeEnum } from './package.type'; export class PackageHandler { private readonly handler: ProjectHandler; @@ -14,26 +17,34 @@ export class PackageHandler { this.handler = handler; } + async installComponent(name: string): Promise { + const rc = await getNoAuthApi().registry.getPackage(name); + if (rc.type !== 'component') throw new Error(`Can only add component: ${name} is a ${rc.type}`); + this.handler._cli.install([name], { server: this.handler._part === 'server' || undefined }); + + return this._getNewComponentPackage(rc.name, rc._file); + } + + async installSystem(name: string): Promise { + const rs = await getNoAuthApi().registry.getPackage(name); + if (rs.type !== 'system') throw new Error(`Can only add system: ${name} is a ${rs.type}`); + this.handler._cli.install([name], { server: this.handler._part === 'server' || undefined }); + + return this._getNewSystemPackage(rs.name, rs._file); + } + /** - * Create a new component in the project and update the save file + * Create a new component in the project * @beta function to be reworked * * @param {string} name - Name of the component - * @param {string} [path=./components] - Path from `/` */ - async createComponent(name: string, path: string = './components'): Promise { - const fullPath = this._createPackage(PackageTypeEnum.COMPONENT, name, path); - const save = await this.handler.save.getSave(); - save.components = [ - ...save.components, - { - name: toPascalCase(name), - path: join(fullPath, toKebabCase(name)), - // Default params of the default component - paramsNames: ['paramA', 'paramB', 'paramC'], - }, - ]; - await this.handler.save.updateSave(save); + createComponent(name: string): NewComponentPackage { + this._createPackage(PackageTypeEnum.COMPONENT, name); + return this._getNewComponentPackage( + toPascalCase(name) + 'Component', + toKebabCase(name) + '.component', + ); } /** @@ -41,16 +52,10 @@ export class PackageHandler { * @beta function to be reworked * * @param {string} name - Name of the system - * @param {string} [path=./systems] - Path from `/` */ - async createSystem(name: string, path: string = './systems'): Promise { - const fullPath = this._createPackage(PackageTypeEnum.SYSTEM, name, path); - const save = await this.handler.save.getSave(); - save.systems = [ - ...save.systems, - { name: toCamelCase(name), path: join(fullPath, toKebabCase(name)) }, - ]; - await this.handler.save.updateSave(save); + createSystem(name: string): NewSystemPackage { + this._createPackage(PackageTypeEnum.SYSTEM, name); + return this._getNewSystemPackage(toCamelCase(name) + 'System', toKebabCase(name) + '.system'); } /** @@ -61,7 +66,7 @@ export class PackageHandler { * * @returns Manifest of the component */ - getComponentManifest(path: string): any { + getComponentManifest(path: string): EditorComponentManifest { return this._getPackageManifest(PackageTypeEnum.COMPONENT, path); } @@ -73,18 +78,55 @@ export class PackageHandler { * * @returns Manifest of the system */ - getSystemManifest(path: string): any { + getSystemManifest(path: string): EditorSystemManifest { return this._getPackageManifest(PackageTypeEnum.SYSTEM, path); } - private _createPackage(type: PackageTypeEnum, name: string, path: string): string { - const fullPath = this._resolvePartPath(path); + private _getNewComponentPackage(name: string, fileName: string): NewComponentPackage { + const path = `./components/${fileName}`; + + const manifest = this._findPackageManifest(this.getComponentManifest, path); + + return { + manifest, + save: { + name, + path, + paramsNames: manifest.params.map(({ name }) => name), + }, + }; + } + + private _getNewSystemPackage(name: string, fileName: string): NewSystemPackage { + const path = './systems/' + fileName; + return { + manifest: this._findPackageManifest(this.getSystemManifest, path), + save: { name, path }, + }; + } + + private _findPackageManifest(manifestGetter: (path: string) => T, path: string): T { + const manifest = ['', '.ts', '.js'].reduce((result: T | undefined, p) => { + if (result) return result; + + try { + return manifestGetter(path + p); + } catch (e) { + if (!(e instanceof FileSystemError)) throw e; + } + }, undefined); + + if (!manifest) { + throw new FileSystemError("Can't find package manifest"); + } + return manifest; + } + + private _createPackage(type: PackageTypeEnum, name: string): void { this.handler._cli.create(type, { name, - path: fullPath, - server: this.handler._part === 'server' ? true : undefined, + server: this.handler._part === 'server' || undefined, }); - return fullPath; } private _getPackageManifest(type: PackageTypeEnum, path: string): any { diff --git a/src/lib/server/project/package/package.type.ts b/src/lib/server/project/package/package.type.ts index 901436b..ce231b2 100644 --- a/src/lib/server/project/package/package.type.ts +++ b/src/lib/server/project/package/package.type.ts @@ -1,4 +1,18 @@ +import type { EditorComponentManifest, EditorSystemManifest } from '@nanoforge-dev/ecs-lib'; + +import type { SaveComponent, SaveSystem } from '@utils/types'; + export enum PackageTypeEnum { COMPONENT = 'component', SYSTEM = 'system', } + +export interface NewComponentPackage { + manifest: EditorComponentManifest; + save: SaveComponent; +} + +export interface NewSystemPackage { + manifest: EditorSystemManifest; + save: SaveSystem; +} diff --git a/src/lib/server/utils/request-handler/handler.ts b/src/lib/server/utils/request-handler/handler.ts index 6f589b5..8cf9bc6 100644 --- a/src/lib/server/utils/request-handler/handler.ts +++ b/src/lib/server/utils/request-handler/handler.ts @@ -1,6 +1,7 @@ import type { RequestEvent } from '@sveltejs/kit'; import { type Api, getApi } from '$lib/server/api'; +import { getNoAuthApi } from '$lib/server/api/client'; import { Cli } from '$lib/server/cli'; import { FileSystem } from '$lib/server/file-system'; import { Git } from '$lib/server/git'; @@ -47,7 +48,8 @@ export class Handler { } get api(): Api { - if (!this._apiCache) this._apiCache = getApi(this._context, this._event.cookies); + if (!this._apiCache) + this._apiCache = this._context.online ? getApi(this._event.cookies) : getNoAuthApi(); return this._apiCache; } diff --git a/src/routes/actions/project/+page.server.ts b/src/routes/actions/project/+page.server.ts index ac42755..05e7166 100644 --- a/src/routes/actions/project/+page.server.ts +++ b/src/routes/actions/project/+page.server.ts @@ -1,15 +1,23 @@ -import { addComponentProjectAction } from '$lib/server/actions/project/cli/add-component.action'; -import { addSystemProjectAction } from '$lib/server/actions/project/cli/add-system.action'; +import { addComponentsProjectAction } from '$lib/server/actions/project/cli/add-component.action'; +import { addSystemsProjectAction } from '$lib/server/actions/project/cli/add-system.action'; import { buildProjectAction } from '$lib/server/actions/project/cli/build.action'; +import { createComponentProjectAction } from '$lib/server/actions/project/cli/create-component.action'; +import { createSystemProjectAction } from '$lib/server/actions/project/cli/create-system.action'; import { generateProjectAction } from '$lib/server/actions/project/cli/generate.action'; -import { createProjectAction } from '$lib/server/actions/project/cli/new.action'; import { loadProjectAction } from '$lib/server/actions/project/load.action'; +import { createProjectAction } from '$lib/server/actions/project/new.action'; +import { getSaveAction } from '$lib/server/actions/project/save/get-save.action'; +import { setSaveAction } from '$lib/server/actions/project/save/set-save.action'; export const actions = { load: loadProjectAction, new: createProjectAction, generate: generateProjectAction, build: buildProjectAction, - addComponent: addComponentProjectAction, - addSystem: addSystemProjectAction, + addComponents: addComponentsProjectAction, + addSystems: addSystemsProjectAction, + createComponent: createComponentProjectAction, + createSystem: createSystemProjectAction, + getSave: getSaveAction, + setSave: setSaveAction, }; From f642736f7c9aef12122bf4f7345242bd75491f6a Mon Sep 17 00:00:00 2001 From: Exelo Date: Tue, 19 May 2026 14:45:02 +0900 Subject: [PATCH 20/58] chore: add forms and create project form --- package.json | 5 +- pnpm-lock.yaml | 682 +++++++----------- pnpm-workspace.yaml | 6 +- src/lib/client/action/base.repository.ts | 6 +- src/lib/client/action/client.ts | 6 +- .../project/project-loader/project-loader.ts | 19 + .../utils/file-system/file-system-file.ts | 2 +- .../ProjectLoader/CreateProject.svelte | 269 +++---- .../ContentBrowserItemCard.svelte | 9 +- .../ContentBrowserWidget.svelte | 2 +- src/lib/components/forms/Form.svelte | 37 + src/lib/components/forms/FormField.svelte | 31 + src/lib/components/forms/form.svelte.ts | 68 ++ src/lib/components/forms/form.type.ts | 1 + .../forms/inputs/FormFieldInput.svelte | 32 + src/lib/server/cli/cli.ts | 10 +- .../utils/request-handler/action-handler.ts | 3 +- src/lib/utils/http/client.ts | 12 +- src/lib/utils/null.ts | 3 + src/lib/utils/object.ts | 27 + 20 files changed, 642 insertions(+), 588 deletions(-) create mode 100644 src/lib/client/project/project-loader/project-loader.ts create mode 100644 src/lib/components/forms/Form.svelte create mode 100644 src/lib/components/forms/FormField.svelte create mode 100644 src/lib/components/forms/form.svelte.ts create mode 100644 src/lib/components/forms/form.type.ts create mode 100644 src/lib/components/forms/inputs/FormFieldInput.svelte create mode 100644 src/lib/utils/null.ts create mode 100644 src/lib/utils/object.ts diff --git a/package.json b/package.json index 8b055cd..32e93c9 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "@vitest/browser-playwright": "catalog:test", "@vitest/coverage-v8": "catalog:test", "bun": "catalog:core", - "dotenv": "catalog:back-libs", + "dotenv": "catalog:libs-back", "eslint": "catalog:lint", "eslint-plugin-svelte": "catalog:lint", "flowbite": "catalog:components", @@ -100,7 +100,8 @@ "unocss": "catalog:css", "vite": "catalog:core", "vitest": "catalog:test", - "vitest-browser-svelte": "catalog:test" + "vitest-browser-svelte": "catalog:test", + "zod": "catalog:libs-front" }, "packageManager": "pnpm@10.33.0", "engines": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 39bc470..df48f9e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,10 +5,6 @@ settings: excludeLinksFromLockfile: false catalogs: - back-libs: - dotenv: - specifier: ^17.4.2 - version: 17.4.2 build: '@tsconfig/svelte': specifier: ^5.0.8 @@ -31,13 +27,13 @@ catalogs: version: 6.1.0 '@nanoforge-dev/actions': specifier: ^1.3.0 - version: 1.3.0 + version: 1.4.2 husky: specifier: ^9.1.7 version: 9.1.7 lint-staged: specifier: ^17.0.4 - version: 17.0.4 + version: 17.0.5 components: flowbite: specifier: ^4.0.2 @@ -57,7 +53,7 @@ catalogs: version: 1.1.2 '@sveltejs/kit': specifier: ^2.59.1 - version: 2.59.1 + version: 2.60.1 '@sveltejs/vite-plugin-svelte': specifier: ^7.1.2 version: 7.1.2 @@ -69,7 +65,7 @@ catalogs: version: 1.3.14 svelte: specifier: ^5.55.5 - version: 5.55.5 + version: 5.55.8 svelte-check: specifier: ^4.4.8 version: 4.4.8 @@ -78,7 +74,7 @@ catalogs: version: 0.4.0 vite: specifier: ^8.0.12 - version: 8.0.12 + version: 8.0.13 css: '@alexanderniebuhr/prettier-plugin-unocss': specifier: ^0.0.4 @@ -112,6 +108,14 @@ catalogs: '@iconify-json/solar': specifier: ^1.2.5 version: 1.2.5 + libs-back: + dotenv: + specifier: ^17.4.2 + version: 17.4.2 + libs-front: + zod: + specifier: ^4.4.3 + version: 4.4.3 lint: '@nanoforge-dev/utils-eslint-config': specifier: ^1.0.2 @@ -124,7 +128,7 @@ catalogs: version: 6.0.2 eslint: specifier: ^10.3.0 - version: 10.3.0 + version: 10.4.0 eslint-plugin-svelte: specifier: ^3.17.1 version: 3.17.1 @@ -139,7 +143,7 @@ catalogs: version: 3.5.2 typescript-eslint: specifier: ^8.59.3 - version: 8.59.3 + version: 8.59.4 test: '@playwright/test': specifier: ^1.60.0 @@ -169,7 +173,7 @@ importers: version: 0.0.4 '@commitlint/cli': specifier: catalog:ci - version: 21.0.1(@types/node@25.7.0)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3) + version: 21.0.1(@types/node@25.9.0)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3) '@commitlint/config-conventional': specifier: catalog:ci version: 21.0.1 @@ -190,13 +194,13 @@ importers: version: 2.18.0(typescript@6.0.3) '@nanoforge-dev/actions': specifier: catalog:ci - version: 1.3.0 + version: 1.4.2 '@nanoforge-dev/ecs-lib': specifier: catalog:core version: 1.1.2 '@nanoforge-dev/utils-eslint-config': specifier: catalog:lint - version: 1.0.2(@types/eslint@9.6.1)(eslint@10.3.0(jiti@2.7.0))(prettier@3.8.3)(typescript@6.0.3) + version: 1.0.2(@types/eslint@9.6.1)(eslint@10.4.0(jiti@2.7.0))(prettier@3.8.3)(typescript@6.0.3) '@nanoforge-dev/utils-prettier-config': specifier: catalog:lint version: 1.0.2 @@ -205,13 +209,13 @@ importers: version: 1.60.0 '@sveltejs/kit': specifier: catalog:core - version: 2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + version: 2.60.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.8(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) '@sveltejs/vite-plugin-svelte': specifier: catalog:core - version: 7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + version: 7.1.2(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier-plugin-svelte@3.5.2(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3)))(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3)) + version: 6.0.2(prettier-plugin-svelte@3.5.2(prettier@3.8.3)(svelte@5.55.8(@typescript-eslint/types@8.59.4)))(prettier@3.8.3)(svelte@5.55.8(@typescript-eslint/types@8.59.4)) '@tsconfig/svelte': specifier: catalog:build version: 5.0.8 @@ -232,7 +236,7 @@ importers: version: 66.6.8 '@vitest/browser-playwright': specifier: catalog:test - version: 4.1.6(playwright@1.60.0)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6) + version: 4.1.6(playwright@1.60.0)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6) '@vitest/coverage-v8': specifier: catalog:test version: 4.1.6(@vitest/browser@4.1.6)(vitest@4.1.6) @@ -240,20 +244,20 @@ importers: specifier: catalog:core version: 1.3.14 dotenv: - specifier: catalog:back-libs + specifier: catalog:libs-back version: 17.4.2 eslint: specifier: catalog:lint - version: 10.3.0(jiti@2.7.0) + version: 10.4.0(jiti@2.7.0) eslint-plugin-svelte: specifier: catalog:lint - version: 3.17.1(eslint@10.3.0(jiti@2.7.0))(svelte@5.55.5(@typescript-eslint/types@8.59.3)) + version: 3.17.1(eslint@10.4.0(jiti@2.7.0))(svelte@5.55.8(@typescript-eslint/types@8.59.4)) flowbite: specifier: catalog:components version: 4.0.2 flowbite-svelte: specifier: catalog:components - version: 1.33.1(svelte@5.55.5(@typescript-eslint/types@8.59.3))(tailwindcss@4.3.0) + version: 1.33.1(svelte@5.55.8(@typescript-eslint/types@8.59.4))(tailwindcss@4.3.0) globals: specifier: catalog:lint version: 17.6.0 @@ -262,7 +266,7 @@ importers: version: 9.1.7 lint-staged: specifier: catalog:ci - version: 17.0.4 + version: 17.0.5 monaco-editor: specifier: catalog:components version: 0.55.1 @@ -274,40 +278,43 @@ importers: version: 3.8.3 prettier-plugin-svelte: specifier: catalog:lint - version: 3.5.2(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3)) + version: 3.5.2(prettier@3.8.3)(svelte@5.55.8(@typescript-eslint/types@8.59.4)) svelte: specifier: catalog:core - version: 5.55.5(@typescript-eslint/types@8.59.3) + version: 5.55.8(@typescript-eslint/types@8.59.4) svelte-adapter-bun: specifier: catalog:build - version: 1.0.1(@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(typescript@6.0.3) + version: 1.0.1(@sveltejs/kit@2.60.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.8(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)))(typescript@6.0.3) svelte-check: specifier: catalog:core - version: 4.4.8(picomatch@4.0.4)(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3) + version: 4.4.8(picomatch@4.0.4)(svelte@5.55.8(@typescript-eslint/types@8.59.4))(typescript@6.0.3) svelte-kit-sessions: specifier: catalog:core - version: 0.4.0(@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3)) + version: 0.4.0(@sveltejs/kit@2.60.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.8(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.8(@typescript-eslint/types@8.59.4)) svelte-sonner: specifier: catalog:components - version: 1.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.3)) + version: 1.1.1(svelte@5.55.8(@typescript-eslint/types@8.59.4)) typescript: specifier: catalog:build version: 6.0.3 typescript-eslint: specifier: catalog:lint - version: 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) + version: 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) unocss: specifier: catalog:css - version: 66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + version: 66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) vite: specifier: catalog:core - version: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) + version: 8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0) vitest: specifier: catalog:test - version: 4.1.6(@types/node@25.7.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + version: 4.1.6(@types/node@25.9.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) vitest-browser-svelte: specifier: catalog:test - version: 2.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vitest@4.1.6) + version: 2.1.1(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vitest@4.1.6) + zod: + specifier: catalog:libs-front + version: 4.4.3 packages: @@ -496,8 +503,8 @@ packages: resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/config-helpers@0.5.5': - resolution: {integrity: sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==} + '@eslint/config-helpers@0.6.0': + resolution: {integrity: sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@eslint/core@1.2.1': @@ -612,8 +619,8 @@ packages: '@lix-js/server-protocol-schema@0.1.1': resolution: {integrity: sha512-jBeALB6prAbtr5q4vTuxnRZZv1M2rKe8iNqRQhFJ4Tv7150unEa0vKyz0hs8Gl3fUGsWaNJBh3J8++fpbrpRBQ==} - '@nanoforge-dev/actions@1.3.0': - resolution: {integrity: sha512-EmArilxSOkmpdBnNhuyIfsXxRNeRugA9LyEp5VRj7n+dhG95UEahgSJll/lautjtYQPX6Dh5ETWwqjjRDclreQ==} + '@nanoforge-dev/actions@1.4.2': + resolution: {integrity: sha512-7oUAcsNLxGDjLIzYe2z57qPS/OkOFBf8jKPF0Xn1lC5fZzpej7U+x3TG2J3JsmmX4ar1D5QYRkRgR4E9wD9VNw==} engines: {node: '25'} '@nanoforge-dev/common@1.1.0': @@ -896,9 +903,6 @@ packages: '@oxc-project/types@0.124.0': resolution: {integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==} - '@oxc-project/types@0.129.0': - resolution: {integrity: sha512-3oz8m3FGdr2nDXVqmFUw7jolKliC4MoyXYIG2c7gpjBnzUWQpUGIYcXYKxTdTi+N2jusvt610ckTMkxdwHkYEg==} - '@oxc-project/types@0.130.0': resolution: {integrity: sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==} @@ -1042,73 +1046,36 @@ packages: '@quansync/fs@1.0.0': resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} - '@rolldown/binding-android-arm64@1.0.0': - resolution: {integrity: sha512-TWMZnRLMe63C2Lhyicviu7ZHaU4kxa6PS3rofvc9GmcvptzNN11BcfQ4Sl7MwTOsisQoa2keB/EBdNCAnUo8vA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [android] - '@rolldown/binding-android-arm64@1.0.1': resolution: {integrity: sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.0': - resolution: {integrity: sha512-6XcD+8k0gPVItNagEw78/qqcBDwKcwDYS8V2hRmVsfUSIrd8cWe/CBvRDI5toqFyPfj+FJr6t8U6Xj2P2prEew==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [darwin] - '@rolldown/binding-darwin-arm64@1.0.1': resolution: {integrity: sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0': - resolution: {integrity: sha512-iN/tWVXRQDWvmZlKdceP1Dwug9GDpEymhb9p4xnEe6zvCg5lFmzVljl+1qR1NVx3yfGpr2Na+CuLmv5IU8uzfQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [darwin] - '@rolldown/binding-darwin-x64@1.0.1': resolution: {integrity: sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.0': - resolution: {integrity: sha512-jjQMDvvwSOuhOwMszD/klSOjyWMM3zI64hWTj9KT5x4MxRbZAf+7vLQ6qouRhtsLVFHr3f0ILaJAfgENPiQdAQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [freebsd] - '@rolldown/binding-freebsd-x64@1.0.1': resolution: {integrity: sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0': - resolution: {integrity: sha512-d//Dtg2x6/m3mbV64yUGNnDGNZaDGRpDLLNGerHQUVObuNaIQaaDp25yUiqGXtHEXX+NP2d0wAlmKgpYgIAJ2A==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - '@rolldown/binding-linux-arm-gnueabihf@1.0.1': resolution: {integrity: sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0': - resolution: {integrity: sha512-n7Ofp0mx+aB2cC+Sdy5YtMnXtY9lchnHbY+3Yt0uq9JsWQExf4f5Whu0tK0R8Jdc9S6RchTHjIFY7uc92puOVQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [glibc] - '@rolldown/binding-linux-arm64-gnu@1.0.1': resolution: {integrity: sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1116,13 +1083,6 @@ packages: os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.0.0': - resolution: {integrity: sha512-EIVjy2cgd7uuMMo94FVkBp7F6DhcZAUwNURkSG3RwUmvAXR6s0ISxM81U+IydcZByPG0pZIHsf1b6kTxoFDgJA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [musl] - '@rolldown/binding-linux-arm64-musl@1.0.1': resolution: {integrity: sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1130,13 +1090,6 @@ packages: os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.0.0': - resolution: {integrity: sha512-JEwwOPcwTLAcpDQlqSmjEmfs63xJnSiUNIGvLcDLUHCWK4XowpS/7c7tUsUH6uT/ct6bMUTdXKfI8967FYj6mg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [ppc64] - os: [linux] - libc: [glibc] - '@rolldown/binding-linux-ppc64-gnu@1.0.1': resolution: {integrity: sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1144,13 +1097,6 @@ packages: os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.0.0': - resolution: {integrity: sha512-0wjCFhLrihtAubnT9iA0N++0pSV0z5Hg7tNGdNJ4RFaINceHadoF+kiFGyY1qSSNVIAZtLotG8Ju1bgDPkjnFA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [s390x] - os: [linux] - libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.0.1': resolution: {integrity: sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1158,13 +1104,6 @@ packages: os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.0': - resolution: {integrity: sha512-Dfn7iak9BcMMePxcoJfpSbWqnEyrp/dRF63/8qW/eHBdOZov6x5aShLLEYGYdIeSJ6vMLK/XCVB+lGIxm41bQA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.1': resolution: {integrity: sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1172,13 +1111,6 @@ packages: os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.0.0': - resolution: {integrity: sha512-5/utzzDmD/pD/bmuaUcbTf/sZYy0aztwIVlfpoW1fTjCZ0BaPOMVWGZL1zvgxyi7ZIVYWlxKONHmSbHuiOh8Jw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [musl] - '@rolldown/binding-linux-x64-musl@1.0.1': resolution: {integrity: sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1186,55 +1118,29 @@ packages: os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.0.0': - resolution: {integrity: sha512-ouJs8VcUomfLfpbUECqFMRqdV4x6aeAK3MA4m6vTrJJjKyWTV5KnxZx7Jd9G+GlDaQQxubcba00x16OyJ1meig==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [openharmony] - '@rolldown/binding-openharmony-arm64@1.0.1': resolution: {integrity: sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.0': - resolution: {integrity: sha512-E+oHKGiDA+lsKMmFtffDDw91EryDT7uJocrIuCHqhm6bCTM6xFK+3gaCkYOHfPwQr0cCNarSM2xaELoQDz9jJg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [wasm32] - '@rolldown/binding-wasm32-wasi@1.0.1': resolution: {integrity: sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.0.0': - resolution: {integrity: sha512-yYK02n8Rngo+gbm1y6G0+7jk1sJ/2Wt7K0me0Y7k/ErBpyf+LJ2gFpqWVTcRV1rUepBlQRmpgWkTQCiiwrK0Ow==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] - '@rolldown/binding-win32-arm64-msvc@1.0.1': resolution: {integrity: sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0': - resolution: {integrity: sha512-14bpChMahXRRXiTwahSl+zzHPW6qQTXtkMuJBFlbo+pqSAews2d4BdCSHfrJ/MBsCZtpmTafsY+1QhBzitcmdg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.1': resolution: {integrity: sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0': - resolution: {integrity: sha512-aKs/3GSWyV0mrhNmt/96/Z3yczC3yvrzYATCiCXQebBsGyYzjNdUphRVLeJQ67ySKVXRfMxt2lm12pmXvbPFQQ==} - '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} @@ -1294,8 +1200,8 @@ packages: peerDependencies: acorn: ^8.9.0 - '@sveltejs/kit@2.59.1': - resolution: {integrity: sha512-d8OON70AphLdDesuTIl//M2O6fRTIicX8aYv8vhCiYEhTTI2OboKqey0Hu1A4VFhqwgqtq0vKDmPFGkw8kKmgw==} + '@sveltejs/kit@2.60.1': + resolution: {integrity: sha512-mQjlkNo+rJvpln7V2IGY2j99BqhcFbS4UN0AQNKNYfhBAFZTuCDAdW3a1sgf330mvtNvsBXn3HpAhcmvdJTcIQ==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -1464,8 +1370,8 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@25.7.0': - resolution: {integrity: sha512-z+pdZyxE+RTQE9AcboAZCb4otwcrvgHD+GlBpPgn0emDVt0ohrTMhAwlr2Wd9nZ+nihhYFxO2pThz3C5qSu2Eg==} + '@types/node@25.9.0': + resolution: {integrity: sha512-AOQwYUNolgy3VosiRqXrACUXTN8nJUtPl7FJXMqZVyxiiCLhQuG3jXKvCS1ALr+Y2OmZhzzLVlYPEqJaiqkaJQ==} '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -1473,63 +1379,63 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@typescript-eslint/eslint-plugin@8.59.3': - resolution: {integrity: sha512-PwFvSKsXGShKGW6n5bZOhGHEcCZXM8HofLK9fNsEwZXzFRjoY+XT1Vsf1zgyXdwTr0ZYz1/2tkZ0DBTT9jZjhw==} + '@typescript-eslint/eslint-plugin@8.59.4': + resolution: {integrity: sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.59.3 + '@typescript-eslint/parser': ^8.59.4 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.59.3': - resolution: {integrity: sha512-HPwA+hVkfcriajbNvTmZv4VRauibay+cWArYUYq7u7W7PmGShMxbPxLvrwDme55a6d5alG3nrYfhyJ/G28XlLg==} + '@typescript-eslint/parser@8.59.4': + resolution: {integrity: sha512-zORHqO/tuhxY1zWuTvMUqddRxpiFJ72xVfcNoWpqdLjs6lfPbuQBJuW4pk+49/uBMy7Ssr4bzgjiKmmDB1UbZQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.59.3': - resolution: {integrity: sha512-ECiUWa/KYRGDFUqTNehaRgzDshnJfkTABJxVemHk4ko22gcr0ukloKjWvyQ64g8YCV/UI47kN1dbmjf/GaQYng==} + '@typescript-eslint/project-service@8.59.4': + resolution: {integrity: sha512-Ly00Vu4oAacfDeHp2Zg85ioNG6l8HG+tN1D7J+xTHSxu9y0awYKJ2zH1rFBn8ZSfuGK+7FxK3Cgl3uAz0aZZLg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.59.3': - resolution: {integrity: sha512-t2LvZnoEfzKtnPjgeEu41xw5gxq9mQVfYy4OoZ4Vlt0sk3JwxmhCca/AR7DwOiHrjWgjAj6as4AhRLKSDfvZIA==} + '@typescript-eslint/scope-manager@8.59.4': + resolution: {integrity: sha512-mUeR/3H1WrTAddJrwut8OoPjfauaztMQmRwV5fQTUyNVJCLiUXXe4lGEyYIL2oFDpP7UtgbGJXCt72wT0z2S3Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.59.3': - resolution: {integrity: sha512-PcIJHjmaREXLgIAIzLnSY9VucEzz8FKXsRgFa1DmdGCK/5tJpW03TKJF01Q6VZd1lLdz2sIKPWaDUZN9dp//dw==} + '@typescript-eslint/tsconfig-utils@8.59.4': + resolution: {integrity: sha512-DLCpnKgD4alVxTBSKulK+gU1KCqOgUXfDRDXh2mZgzokQKa/70ax93I2uVO3m/LLvIAtWZIFoiifudmIqAxpMA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.59.3': - resolution: {integrity: sha512-g71d8QD8UaiHGvrJwyIS1hCX5r63w6Jll+4VEYhEAHXTDIqX1JgxhTAbEHtKntL9kuc4jRo7/GWw5xfCepSccQ==} + '@typescript-eslint/type-utils@8.59.4': + resolution: {integrity: sha512-uonTuPAAKr9XaBGqJ3LjYTh72zy5DyGesljO9gtmk/eFW0W1fRHjnwVYKB35Lm8d5Q5CluEW3gPHjTvZTmgrfA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.59.3': - resolution: {integrity: sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg==} + '@typescript-eslint/types@8.59.4': + resolution: {integrity: sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.59.3': - resolution: {integrity: sha512-CbRjVRAf7Lr9Kr8RopKcbY45p2VfmmHrm0ygOCYFi7oU8q19m0Fs/6iHS7kNOmwpp+ob07ZVcAqlxUod9lYdmg==} + '@typescript-eslint/typescript-estree@8.59.4': + resolution: {integrity: sha512-F+RuOmcDXo4+TPdfd/TCLS3m2nw8gE9XXyZLrA3JBfaA5tz9TtdkyD3YJFmPxulyc2cKbEok/CvFE3MgSLWnag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.59.3': - resolution: {integrity: sha512-JAvT14goBzRzzzZyqq3P9BLArIxTtQURUtFgQ/V7FO+eU+Gg6ES+5ymOPP1wRxXcxAYeivCk4uS3jCKWI1K8Zg==} + '@typescript-eslint/utils@8.59.4': + resolution: {integrity: sha512-cYXeNAUsG4lJo5dbc1FcKm+JwIWrj1/UpTORsC6tGMjEZ81DYcvIr9/ueikhMa/Y/gDQYGp+YX9/xQrXje5BJw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.59.3': - resolution: {integrity: sha512-f1UQF7ggd42YiwI5wGrRaPsa+P0CINBlrkLPmGfpq/u/I/oVtecoEIfFR9ag/oa1sLOsRNZ6xehf6qMZhQGBDg==} + '@typescript-eslint/visitor-keys@8.59.4': + resolution: {integrity: sha512-U3gxVaDVnuZKhSspW/MzMxE1kq7zOdc072FcSNoqA1I9p8HyKbBFfEHoWckBAMgNMph4MamwS5iTVzFmrnt8TQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@unocss/cli@66.6.8': @@ -1693,8 +1599,8 @@ packages: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} - apexcharts@5.11.0: - resolution: {integrity: sha512-iIXnZ1DhndVgY4G5fmAbyUtGBTR5j4LlMEb561eAd4+wkJB7wJXXKLMr9u+4V5aQEPXeVYWgkAbuw9Y1z6MIrg==} + apexcharts@5.12.0: + resolution: {integrity: sha512-vNCw62M5rhVg09FHFCL/ztpH7VlTOF8/+lWLUVjBdQffIAgQaxtyDGfojCyYoZHM3Hh17srWwz6rrD/XzblRSw==} argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1885,8 +1791,8 @@ packages: engines: {node: '>=4'} hasBin: true - date-fns@4.1.0: - resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + date-fns@4.2.1: + resolution: {integrity: sha512-37RhSdxaG1suen6VDCza6rNrQfooyQh57HFVPwQGEq2QWliVLzPQZ8Oa017weOu+HZCnzI7N3Pf/wyoBKfEqrA==} debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} @@ -1922,8 +1828,8 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} - devalue@5.8.0: - resolution: {integrity: sha512-2zA9pFEsnp7vWBZbXF5JAgAq0fsUIt/1XPbRiAmRV3lp/2C3upzH+sADiyy66aFCihoLEsrQHxNM5w1gIDfsBg==} + devalue@5.8.1: + resolution: {integrity: sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==} dompurify@3.2.7: resolution: {integrity: sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==} @@ -1942,8 +1848,8 @@ packages: emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} - enhanced-resolve@5.21.3: - resolution: {integrity: sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==} + enhanced-resolve@5.21.4: + resolution: {integrity: sha512-wE4fDO8OjJhrPFH69HUQStq5oKvGRTNXEyW+k5C/pUQLASSsTu7obd2V3GvCDgPcY9AWjhJ4jz9Kh7iRvrxhJg==} engines: {node: '>=10.13.0'} env-paths@2.2.1: @@ -2045,8 +1951,8 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.3.0: - resolution: {integrity: sha512-XbEXaRva5cF0ZQB8w6MluHA0kZZfV2DuCMJ3ozyEOHLwDpZX2Lmm/7Pp0xdJmI0GL1W05VH5VwIFHEm1Vcw2gw==} + eslint@10.4.0: + resolution: {integrity: sha512-loXy6bWOoP3EP6JA7jo6p5jMpBJmHmsNZM5SFRHLdh1MGOPurMnNBj4ZlAbaqUAaQWbCr7jHV4P7gzAyryZWkQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: @@ -2075,8 +1981,8 @@ packages: resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} - esrap@2.2.8: - resolution: {integrity: sha512-MPweq2EvEGj8jwOI7Hgycw/QIHzqA1EbAM8lG7p+FBfZbZq/hQ6h3AMsqnu/djzisH1KVWNzbb7LSgIVtMlPSg==} + esrap@2.2.9: + resolution: {integrity: sha512-4KijP+NxCWthMCUC3qHbE6n4vCjqgJS1uAYKhuT/GWfFTf1Qyive2TgOjep+gzbSzRfnNyaN/UU9YmdOt8Eg0A==} peerDependencies: '@typescript-eslint/types': ^8.2.0 peerDependenciesMeta: @@ -2533,8 +2439,8 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lint-staged@17.0.4: - resolution: {integrity: sha512-+rU9lSUyVOZ/hDUmRLVGzyS2v73cDdQjX+XQz1AaOdIE4RysLq0HoPW2HrrgeNCLklkhi904VBU1bmgWLHVnkA==} + lint-staged@17.0.5: + resolution: {integrity: sha512-d12yC+/e8RhBjZtaxZn71FyrgU/P5e+uAPifhCLwdosQZP/zamSdKRWDC30ocVIbzDKiFG1McHc/LUgB92GIPw==} engines: {node: '>=22.22.1'} hasBin: true @@ -2566,8 +2472,8 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - magicast@0.5.2: - resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} + magicast@0.5.3: + resolution: {integrity: sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -2845,11 +2751,6 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rolldown@1.0.0: - resolution: {integrity: sha512-yD986aXDESFGS95spT1LAv0jssywP4npMEjmMHyN2/5+eE8qQJUype2AaKkRiLgBgyD0LFlubwAht7VmY8rGoA==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - rolldown@1.0.1: resolution: {integrity: sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2988,8 +2889,8 @@ packages: peerDependencies: svelte: ^5.0.0 - svelte@5.55.5: - resolution: {integrity: sha512-2uCs/LZ9us+AktdzYJM8OcxQ8qnPS1kpaO7syGT/MgO+6Qr1Ybl+TqPq+97u7PHqmmMlye5ZkoyXONy5mjjAbw==} + svelte@5.55.8: + resolution: {integrity: sha512-4D6lyrMHmDaZalQOEBMCWCCidyZjSnec14/oPn0k627G6goxcck9xqMwz1tFLlQz+ZFvtTTHfFOlUayuAz0z6Q==} engines: {node: '>=18'} synckit@0.11.12: @@ -3059,8 +2960,8 @@ packages: type-level-regexp@0.1.17: resolution: {integrity: sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg==} - typescript-eslint@8.59.3: - resolution: {integrity: sha512-KgusgyDgG4LI8Ih/sWaCtZ06tckLAS5CvT5A4D1Q7bYVoAAyzwiZvE4BmwDHkhRVkvhRBepKeASoFzQetha7Fg==} + typescript-eslint@8.59.4: + resolution: {integrity: sha512-Rw6+44QNFaXtgHSjPy+Kw8hrJniMYzR85E9yLmOLcfZ91/rz+JXQbDTCmc6ccxMPY6K6PgAq26f0JCBfR7LIPQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 @@ -3080,8 +2981,8 @@ packages: unconfig@7.5.0: resolution: {integrity: sha512-oi8Qy2JV4D3UQ0PsopR28CzdQ3S/5A1zwsUwp/rosSbfhJ5z7b90bIyTwi/F7hCLD4SGcZVjDzd4XoUQcEanvA==} - undici-types@7.21.0: - resolution: {integrity: sha512-w9IMgQrz4O0YN1LtB7K5P63vhlIOvC7opSmouCJ+ZywlPAlO9gIkJ+otk6LvGpAs2wg4econaCz3TvQ9xPoyuQ==} + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} undici@6.25.0: resolution: {integrity: sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==} @@ -3130,8 +3031,8 @@ packages: resolution: {integrity: sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==} hasBin: true - vite@8.0.12: - resolution: {integrity: sha512-w2dDofOWv2QB09ZITZBsvKTVAlYvPR4IAmrY/v0ir9KvLs0xybR7i48wxhM1/oyBWO34wPns+bPGw5ZrZqDpZg==} + vite@8.0.13: + resolution: {integrity: sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -3297,6 +3198,9 @@ packages: zimmerframe@1.1.4: resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + snapshots: '@actions/core@3.0.1': @@ -3394,11 +3298,11 @@ snapshots: '@blazediff/core@1.9.1': {} - '@commitlint/cli@21.0.1(@types/node@25.7.0)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3)': + '@commitlint/cli@21.0.1(@types/node@25.9.0)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3)': dependencies: '@commitlint/format': 21.0.1 '@commitlint/lint': 21.0.1 - '@commitlint/load': 21.0.1(@types/node@25.7.0)(typescript@6.0.3) + '@commitlint/load': 21.0.1(@types/node@25.9.0)(typescript@6.0.3) '@commitlint/read': 21.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) '@commitlint/types': 21.0.1 tinyexec: 1.1.2 @@ -3443,14 +3347,14 @@ snapshots: '@commitlint/rules': 21.0.1 '@commitlint/types': 21.0.1 - '@commitlint/load@21.0.1(@types/node@25.7.0)(typescript@6.0.3)': + '@commitlint/load@21.0.1(@types/node@25.9.0)(typescript@6.0.3)': dependencies: '@commitlint/config-validator': 21.0.1 '@commitlint/execute-rule': 21.0.1 '@commitlint/resolve-extends': 21.0.1 '@commitlint/types': 21.0.1 cosmiconfig: 9.0.1(typescript@6.0.3) - cosmiconfig-typescript-loader: 6.3.0(@types/node@25.7.0)(cosmiconfig@9.0.1(typescript@6.0.3))(typescript@6.0.3) + cosmiconfig-typescript-loader: 6.3.0(@types/node@25.9.0)(cosmiconfig@9.0.1(typescript@6.0.3))(typescript@6.0.3) es-toolkit: 1.46.1 is-plain-obj: 4.1.0 picocolors: 1.1.1 @@ -3533,9 +3437,9 @@ snapshots: tslib: 2.8.1 optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.3.0(jiti@2.7.0))': + '@eslint-community/eslint-utils@4.9.1(eslint@10.4.0(jiti@2.7.0))': dependencies: - eslint: 10.3.0(jiti@2.7.0) + eslint: 10.4.0(jiti@2.7.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -3548,7 +3452,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.5.5': + '@eslint/config-helpers@0.6.0': dependencies: '@eslint/core': 1.2.1 @@ -3696,7 +3600,7 @@ snapshots: '@lix-js/server-protocol-schema@0.1.1': {} - '@nanoforge-dev/actions@1.3.0': + '@nanoforge-dev/actions@1.4.2': dependencies: '@actions/core': 3.0.1 '@actions/github': 9.1.1 @@ -3708,16 +3612,16 @@ snapshots: dependencies: '@nanoforge-dev/common': 1.1.0 - '@nanoforge-dev/utils-eslint-config@1.0.2(@types/eslint@9.6.1)(eslint@10.3.0(jiti@2.7.0))(prettier@3.8.3)(typescript@6.0.3)': + '@nanoforge-dev/utils-eslint-config@1.0.2(@types/eslint@9.6.1)(eslint@10.4.0(jiti@2.7.0))(prettier@3.8.3)(typescript@6.0.3)': dependencies: '@eslint/js': 9.39.4 '@favware/cliff-jumper': 6.1.0 - eslint-config-prettier: 10.1.8(eslint@10.3.0(jiti@2.7.0)) + eslint-config-prettier: 10.1.8(eslint@10.4.0(jiti@2.7.0)) eslint-formatter-pretty: 7.1.0 - eslint-plugin-format: 1.5.0(eslint@10.3.0(jiti@2.7.0)) - eslint-plugin-prettier: 5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.3.0(jiti@2.7.0)))(eslint@10.3.0(jiti@2.7.0))(prettier@3.8.3) + eslint-plugin-format: 1.5.0(eslint@10.4.0(jiti@2.7.0)) + eslint-plugin-prettier: 5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.4.0(jiti@2.7.0)))(eslint@10.4.0(jiti@2.7.0))(prettier@3.8.3) globals: 16.5.0 - typescript-eslint: 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) + typescript-eslint: 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) transitivePeerDependencies: - '@types/eslint' - eslint @@ -3909,8 +3813,6 @@ snapshots: '@oxc-project/types@0.124.0': {} - '@oxc-project/types@0.129.0': {} - '@oxc-project/types@0.130.0': {} '@oxfmt/binding-android-arm-eabi@0.35.0': @@ -3984,85 +3886,42 @@ snapshots: dependencies: quansync: 1.0.0 - '@rolldown/binding-android-arm64@1.0.0': - optional: true - '@rolldown/binding-android-arm64@1.0.1': optional: true - '@rolldown/binding-darwin-arm64@1.0.0': - optional: true - '@rolldown/binding-darwin-arm64@1.0.1': optional: true - '@rolldown/binding-darwin-x64@1.0.0': - optional: true - '@rolldown/binding-darwin-x64@1.0.1': optional: true - '@rolldown/binding-freebsd-x64@1.0.0': - optional: true - '@rolldown/binding-freebsd-x64@1.0.1': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0': - optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.1': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0': - optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.1': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0': - optional: true - '@rolldown/binding-linux-arm64-musl@1.0.1': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.0.0': - optional: true - '@rolldown/binding-linux-ppc64-gnu@1.0.1': optional: true - '@rolldown/binding-linux-s390x-gnu@1.0.0': - optional: true - '@rolldown/binding-linux-s390x-gnu@1.0.1': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0': - optional: true - '@rolldown/binding-linux-x64-gnu@1.0.1': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0': - optional: true - '@rolldown/binding-linux-x64-musl@1.0.1': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0': - optional: true - '@rolldown/binding-openharmony-arm64@1.0.1': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0': - dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) - optional: true - '@rolldown/binding-wasm32-wasi@1.0.1': dependencies: '@emnapi/core': 1.10.0 @@ -4070,20 +3929,12 @@ snapshots: '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0': - optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.1': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0': - optional: true - '@rolldown/binding-win32-x64-msvc@1.0.1': optional: true - '@rolldown/pluginutils@1.0.0': {} - '@rolldown/pluginutils@1.0.1': {} '@rollup/plugin-node-resolve@15.3.1': @@ -4124,39 +3975,39 @@ snapshots: dependencies: acorn: 8.16.0 - '@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))': + '@sveltejs/kit@2.60.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.8(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@standard-schema/spec': 1.1.0 '@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0) - '@sveltejs/vite-plugin-svelte': 7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + '@sveltejs/vite-plugin-svelte': 7.1.2(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) '@types/cookie': 0.6.0 acorn: 8.16.0 cookie: 0.6.0 - devalue: 5.8.0 + devalue: 5.8.1 esm-env: 1.2.2 kleur: 4.1.5 magic-string: 0.30.21 mrmime: 2.0.1 set-cookie-parser: 3.1.0 sirv: 3.0.2 - svelte: 5.55.5(@typescript-eslint/types@8.59.3) - vite: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) + svelte: 5.55.8(@typescript-eslint/types@8.59.4) + vite: 8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0) optionalDependencies: typescript: 6.0.3 - '@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))': + '@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0))': dependencies: deepmerge: 4.3.1 magic-string: 0.30.21 obug: 2.1.1 - svelte: 5.55.5(@typescript-eslint/types@8.59.3) - vite: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) - vitefu: 1.1.3(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + svelte: 5.55.8(@typescript-eslint/types@8.59.4) + vite: 8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0) + vitefu: 1.1.3(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) '@tailwindcss/node@4.3.0': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.21.3 + enhanced-resolve: 5.21.4 jiti: 2.7.0 lightningcss: 1.32.0 magic-string: 0.30.21 @@ -4222,11 +4073,11 @@ snapshots: postcss: 8.5.14 tailwindcss: 4.3.0 - '@testing-library/svelte-core@1.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.3))': + '@testing-library/svelte-core@1.0.0(svelte@5.55.8(@typescript-eslint/types@8.59.4))': dependencies: - svelte: 5.55.5(@typescript-eslint/types@8.59.3) + svelte: 5.55.8(@typescript-eslint/types@8.59.4) - '@trivago/prettier-plugin-sort-imports@6.0.2(prettier-plugin-svelte@3.5.2(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3)))(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3))': + '@trivago/prettier-plugin-sort-imports@6.0.2(prettier-plugin-svelte@3.5.2(prettier@3.8.3)(svelte@5.55.8(@typescript-eslint/types@8.59.4)))(prettier@3.8.3)(svelte@5.55.8(@typescript-eslint/types@8.59.4))': dependencies: '@babel/generator': 7.29.1 '@babel/parser': 7.29.3 @@ -4238,8 +4089,8 @@ snapshots: parse-imports-exports: 0.2.4 prettier: 3.8.3 optionalDependencies: - prettier-plugin-svelte: 3.5.2(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3)) - svelte: 5.55.5(@typescript-eslint/types@8.59.3) + prettier-plugin-svelte: 3.5.2(prettier@3.8.3)(svelte@5.55.8(@typescript-eslint/types@8.59.4)) + svelte: 5.55.8(@typescript-eslint/types@8.59.4) transitivePeerDependencies: - supports-color @@ -4274,23 +4125,23 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/node@25.7.0': + '@types/node@25.9.0': dependencies: - undici-types: 7.21.0 + undici-types: 7.24.6 '@types/resolve@1.20.2': {} '@types/trusted-types@2.0.7': {} - '@typescript-eslint/eslint-plugin@8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.59.4(@typescript-eslint/parser@8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.59.3 - '@typescript-eslint/type-utils': 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.59.3 - eslint: 10.3.0(jiti@2.7.0) + '@typescript-eslint/parser': 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.59.4 + '@typescript-eslint/type-utils': 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.59.4 + eslint: 10.4.0(jiti@2.7.0) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@6.0.3) @@ -4298,56 +4149,56 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)': + '@typescript-eslint/parser@8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.59.3 - '@typescript-eslint/types': 8.59.3 - '@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.59.3 + '@typescript-eslint/scope-manager': 8.59.4 + '@typescript-eslint/types': 8.59.4 + '@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.59.4 debug: 4.4.3 - eslint: 10.3.0(jiti@2.7.0) + eslint: 10.4.0(jiti@2.7.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.59.3(typescript@6.0.3)': + '@typescript-eslint/project-service@8.59.4(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.59.3(typescript@6.0.3) - '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/tsconfig-utils': 8.59.4(typescript@6.0.3) + '@typescript-eslint/types': 8.59.4 debug: 4.4.3 typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.59.3': + '@typescript-eslint/scope-manager@8.59.4': dependencies: - '@typescript-eslint/types': 8.59.3 - '@typescript-eslint/visitor-keys': 8.59.3 + '@typescript-eslint/types': 8.59.4 + '@typescript-eslint/visitor-keys': 8.59.4 - '@typescript-eslint/tsconfig-utils@8.59.3(typescript@6.0.3)': + '@typescript-eslint/tsconfig-utils@8.59.4(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@typescript-eslint/types': 8.59.3 - '@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/types': 8.59.4 + '@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) debug: 4.4.3 - eslint: 10.3.0(jiti@2.7.0) + eslint: 10.4.0(jiti@2.7.0) ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.59.3': {} + '@typescript-eslint/types@8.59.4': {} - '@typescript-eslint/typescript-estree@8.59.3(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.59.4(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.59.3(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.59.3(typescript@6.0.3) - '@typescript-eslint/types': 8.59.3 - '@typescript-eslint/visitor-keys': 8.59.3 + '@typescript-eslint/project-service': 8.59.4(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.59.4(typescript@6.0.3) + '@typescript-eslint/types': 8.59.4 + '@typescript-eslint/visitor-keys': 8.59.4 debug: 4.4.3 minimatch: 10.2.5 semver: 7.8.0 @@ -4357,20 +4208,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)': + '@typescript-eslint/utils@8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.7.0)) - '@typescript-eslint/scope-manager': 8.59.3 - '@typescript-eslint/types': 8.59.3 - '@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3) - eslint: 10.3.0(jiti@2.7.0) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0(jiti@2.7.0)) + '@typescript-eslint/scope-manager': 8.59.4 + '@typescript-eslint/types': 8.59.4 + '@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3) + eslint: 10.4.0(jiti@2.7.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.59.3': + '@typescript-eslint/visitor-keys@8.59.4': dependencies: - '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/types': 8.59.4 eslint-visitor-keys: 5.0.1 '@unocss/cli@66.6.8': @@ -4511,7 +4362,7 @@ snapshots: dependencies: '@unocss/core': 66.6.8 - '@unocss/vite@66.6.8(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))': + '@unocss/vite@66.6.8(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@jridgewell/remapping': 2.3.5 '@unocss/config': 66.6.8 @@ -4522,31 +4373,31 @@ snapshots: pathe: 2.0.3 tinyglobby: 0.2.16 unplugin-utils: 0.3.1 - vite: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) + vite: 8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0) - '@vitest/browser-playwright@4.1.6(playwright@1.60.0)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6)': + '@vitest/browser-playwright@4.1.6(playwright@1.60.0)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6)': dependencies: - '@vitest/browser': 4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6) - '@vitest/mocker': 4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + '@vitest/browser': 4.1.6(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6) + '@vitest/mocker': 4.1.6(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) playwright: 1.60.0 tinyrainbow: 3.1.0 - vitest: 4.1.6(@types/node@25.7.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + vitest: 4.1.6(@types/node@25.9.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite - '@vitest/browser@4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6)': + '@vitest/browser@4.1.6(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6)': dependencies: '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + '@vitest/mocker': 4.1.6(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) '@vitest/utils': 4.1.6 magic-string: 0.30.21 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.1.0 - vitest: 4.1.6(@types/node@25.7.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + vitest: 4.1.6(@types/node@25.9.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) ws: 8.20.1 transitivePeerDependencies: - bufferutil @@ -4562,13 +4413,13 @@ snapshots: istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-reports: 3.2.0 - magicast: 0.5.2 + magicast: 0.5.3 obug: 2.1.1 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.6(@types/node@25.7.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + vitest: 4.1.6(@types/node@25.9.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) optionalDependencies: - '@vitest/browser': 4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6) + '@vitest/browser': 4.1.6(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6) '@vitest/expect@4.1.6': dependencies: @@ -4579,13 +4430,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))': + '@vitest/mocker@4.1.6(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.6 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) + vite: 8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0) '@vitest/pretty-format@4.1.6': dependencies: @@ -4639,7 +4490,7 @@ snapshots: ansi-styles@6.2.3: {} - apexcharts@5.11.0: {} + apexcharts@5.12.0: {} argparse@2.0.1: {} @@ -4677,7 +4528,7 @@ snapshots: bun-types@1.3.14: dependencies: - '@types/node': 25.7.0 + '@types/node': 25.9.0 bun@1.3.14: optionalDependencies: @@ -4784,9 +4635,9 @@ snapshots: cookie@0.6.0: {} - cosmiconfig-typescript-loader@6.3.0(@types/node@25.7.0)(cosmiconfig@9.0.1(typescript@6.0.3))(typescript@6.0.3): + cosmiconfig-typescript-loader@6.3.0(@types/node@25.9.0)(cosmiconfig@9.0.1(typescript@6.0.3))(typescript@6.0.3): dependencies: - '@types/node': 25.7.0 + '@types/node': 25.9.0 cosmiconfig: 9.0.1(typescript@6.0.3) jiti: 2.6.1 typescript: 6.0.3 @@ -4813,7 +4664,7 @@ snapshots: cssesc@3.0.0: {} - date-fns@4.1.0: {} + date-fns@4.2.1: {} debug@4.4.3: dependencies: @@ -4831,7 +4682,7 @@ snapshots: detect-libc@2.1.2: {} - devalue@5.8.0: {} + devalue@5.8.1: {} dompurify@3.2.7: optionalDependencies: @@ -4847,7 +4698,7 @@ snapshots: emoji-regex@10.6.0: {} - enhanced-resolve@5.21.3: + enhanced-resolve@5.21.4: dependencies: graceful-fs: 4.2.11 tapable: 2.3.3 @@ -4870,9 +4721,9 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@10.3.0(jiti@2.7.0)): + eslint-config-prettier@10.1.8(eslint@10.4.0(jiti@2.7.0)): dependencies: - eslint: 10.3.0(jiti@2.7.0) + eslint: 10.4.0(jiti@2.7.0) eslint-formatter-pretty@7.1.0: dependencies: @@ -4885,41 +4736,41 @@ snapshots: string-width: 8.2.1 supports-hyperlinks: 4.4.0 - eslint-formatting-reporter@0.0.0(eslint@10.3.0(jiti@2.7.0)): + eslint-formatting-reporter@0.0.0(eslint@10.4.0(jiti@2.7.0)): dependencies: - eslint: 10.3.0(jiti@2.7.0) + eslint: 10.4.0(jiti@2.7.0) prettier-linter-helpers: 1.0.1 eslint-parser-plain@0.1.1: {} - eslint-plugin-format@1.5.0(eslint@10.3.0(jiti@2.7.0)): + eslint-plugin-format@1.5.0(eslint@10.4.0(jiti@2.7.0)): dependencies: '@dprint/formatter': 0.5.1 '@dprint/markdown': 0.21.1 '@dprint/toml': 0.7.0 - eslint: 10.3.0(jiti@2.7.0) - eslint-formatting-reporter: 0.0.0(eslint@10.3.0(jiti@2.7.0)) + eslint: 10.4.0(jiti@2.7.0) + eslint-formatting-reporter: 0.0.0(eslint@10.4.0(jiti@2.7.0)) eslint-parser-plain: 0.1.1 ohash: 2.0.11 oxfmt: 0.35.0 prettier: 3.8.3 synckit: 0.11.12 - eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.3.0(jiti@2.7.0)))(eslint@10.3.0(jiti@2.7.0))(prettier@3.8.3): + eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.4.0(jiti@2.7.0)))(eslint@10.4.0(jiti@2.7.0))(prettier@3.8.3): dependencies: - eslint: 10.3.0(jiti@2.7.0) + eslint: 10.4.0(jiti@2.7.0) prettier: 3.8.3 prettier-linter-helpers: 1.0.1 synckit: 0.11.12 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 10.1.8(eslint@10.3.0(jiti@2.7.0)) + eslint-config-prettier: 10.1.8(eslint@10.4.0(jiti@2.7.0)) - eslint-plugin-svelte@3.17.1(eslint@10.3.0(jiti@2.7.0))(svelte@5.55.5(@typescript-eslint/types@8.59.3)): + eslint-plugin-svelte@3.17.1(eslint@10.4.0(jiti@2.7.0))(svelte@5.55.8(@typescript-eslint/types@8.59.4)): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0(jiti@2.7.0)) '@jridgewell/sourcemap-codec': 1.5.5 - eslint: 10.3.0(jiti@2.7.0) + eslint: 10.4.0(jiti@2.7.0) esutils: 2.0.3 globals: 16.5.0 known-css-properties: 0.37.0 @@ -4927,9 +4778,9 @@ snapshots: postcss-load-config: 3.1.4(postcss@8.5.14) postcss-safe-parser: 7.0.1(postcss@8.5.14) semver: 7.8.0 - svelte-eslint-parser: 1.6.1(svelte@5.55.5(@typescript-eslint/types@8.59.3)) + svelte-eslint-parser: 1.6.1(svelte@5.55.8(@typescript-eslint/types@8.59.4)) optionalDependencies: - svelte: 5.55.5(@typescript-eslint/types@8.59.3) + svelte: 5.55.8(@typescript-eslint/types@8.59.4) transitivePeerDependencies: - ts-node @@ -4953,12 +4804,12 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.3.0(jiti@2.7.0): + eslint@10.4.0(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0(jiti@2.7.0)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.23.5 - '@eslint/config-helpers': 0.5.5 + '@eslint/config-helpers': 0.6.0 '@eslint/core': 1.2.1 '@eslint/plugin-kit': 0.7.1 '@humanfs/node': 0.16.8 @@ -5010,11 +4861,11 @@ snapshots: dependencies: estraverse: 5.3.0 - esrap@2.2.8(@typescript-eslint/types@8.59.3): + esrap@2.2.9(@typescript-eslint/types@8.59.4): dependencies: '@jridgewell/sourcemap-codec': 1.5.5 optionalDependencies: - '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/types': 8.59.4 esrecurse@4.3.0: dependencies: @@ -5099,16 +4950,16 @@ snapshots: transitivePeerDependencies: - rollup - flowbite-svelte@1.33.1(svelte@5.55.5(@typescript-eslint/types@8.59.3))(tailwindcss@4.3.0): + flowbite-svelte@1.33.1(svelte@5.55.8(@typescript-eslint/types@8.59.4))(tailwindcss@4.3.0): dependencies: '@floating-ui/dom': 1.7.6 '@floating-ui/utils': 0.2.11 - apexcharts: 5.11.0 + apexcharts: 5.12.0 clsx: 2.1.1 - date-fns: 4.1.0 + date-fns: 4.2.1 esm-env: 1.2.2 flowbite: 3.1.2 - svelte: 5.55.5(@typescript-eslint/types@8.59.3) + svelte: 5.55.8(@typescript-eslint/types@8.59.4) tailwind-merge: 3.6.0 tailwind-variants: 3.2.2(tailwind-merge@3.6.0)(tailwindcss@4.3.0) tailwindcss: 4.3.0 @@ -5397,7 +5248,7 @@ snapshots: lines-and-columns@1.2.4: {} - lint-staged@17.0.4: + lint-staged@17.0.5: dependencies: listr2: 10.2.1 picomatch: 4.0.4 @@ -5449,7 +5300,7 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - magicast@0.5.2: + magicast@0.5.3: dependencies: '@babel/parser': 7.29.3 '@babel/types': 7.29.0 @@ -5683,10 +5534,10 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier-plugin-svelte@3.5.2(prettier@3.8.3)(svelte@5.55.5(@typescript-eslint/types@8.59.3)): + prettier-plugin-svelte@3.5.2(prettier@3.8.3)(svelte@5.55.8(@typescript-eslint/types@8.59.4)): dependencies: prettier: 3.8.3 - svelte: 5.55.5(@typescript-eslint/types@8.59.3) + svelte: 5.55.8(@typescript-eslint/types@8.59.4) prettier@2.5.1: {} @@ -5726,27 +5577,6 @@ snapshots: rfdc@1.4.1: {} - rolldown@1.0.0: - dependencies: - '@oxc-project/types': 0.129.0 - '@rolldown/pluginutils': 1.0.0 - optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0 - '@rolldown/binding-darwin-arm64': 1.0.0 - '@rolldown/binding-darwin-x64': 1.0.0 - '@rolldown/binding-freebsd-x64': 1.0.0 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0 - '@rolldown/binding-linux-arm64-gnu': 1.0.0 - '@rolldown/binding-linux-arm64-musl': 1.0.0 - '@rolldown/binding-linux-ppc64-gnu': 1.0.0 - '@rolldown/binding-linux-s390x-gnu': 1.0.0 - '@rolldown/binding-linux-x64-gnu': 1.0.0 - '@rolldown/binding-linux-x64-musl': 1.0.0 - '@rolldown/binding-openharmony-arm64': 1.0.0 - '@rolldown/binding-wasm32-wasi': 1.0.0 - '@rolldown/binding-win32-arm64-msvc': 1.0.0 - '@rolldown/binding-win32-x64-msvc': 1.0.0 - rolldown@1.0.1: dependencies: '@oxc-project/types': 0.130.0 @@ -5768,10 +5598,10 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.1 '@rolldown/binding-win32-x64-msvc': 1.0.1 - runed@0.28.0(svelte@5.55.5(@typescript-eslint/types@8.59.3)): + runed@0.28.0(svelte@5.55.8(@typescript-eslint/types@8.59.4)): dependencies: esm-env: 1.2.2 - svelte: 5.55.5(@typescript-eslint/types@8.59.3) + svelte: 5.55.8(@typescript-eslint/types@8.59.4) sade@1.8.1: dependencies: @@ -5852,25 +5682,25 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-adapter-bun@1.0.1(@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(typescript@6.0.3): + svelte-adapter-bun@1.0.1(@sveltejs/kit@2.60.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.8(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)))(typescript@6.0.3): dependencies: - '@sveltejs/kit': 2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + '@sveltejs/kit': 2.60.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.8(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) rolldown: 1.0.1 typescript: 6.0.3 - svelte-check@4.4.8(picomatch@4.0.4)(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3): + svelte-check@4.4.8(picomatch@4.0.4)(svelte@5.55.8(@typescript-eslint/types@8.59.4))(typescript@6.0.3): dependencies: '@jridgewell/trace-mapping': 0.3.31 chokidar: 4.0.3 fdir: 6.5.0(picomatch@4.0.4) picocolors: 1.1.1 sade: 1.8.1 - svelte: 5.55.5(@typescript-eslint/types@8.59.3) + svelte: 5.55.8(@typescript-eslint/types@8.59.4) typescript: 6.0.3 transitivePeerDependencies: - picomatch - svelte-eslint-parser@1.6.1(svelte@5.55.5(@typescript-eslint/types@8.59.3)): + svelte-eslint-parser@1.6.1(svelte@5.55.8(@typescript-eslint/types@8.59.4)): dependencies: eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -5880,20 +5710,20 @@ snapshots: postcss-selector-parser: 7.1.1 semver: 7.8.0 optionalDependencies: - svelte: 5.55.5(@typescript-eslint/types@8.59.3) + svelte: 5.55.8(@typescript-eslint/types@8.59.4) - svelte-kit-sessions@0.4.0(@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3)): + svelte-kit-sessions@0.4.0(@sveltejs/kit@2.60.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.8(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.8(@typescript-eslint/types@8.59.4)): dependencies: '@isaacs/ttlcache': 1.4.1 - '@sveltejs/kit': 2.59.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.5(@typescript-eslint/types@8.59.3))(typescript@6.0.3)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) - svelte: 5.55.5(@typescript-eslint/types@8.59.3) + '@sveltejs/kit': 2.60.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.8(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) + svelte: 5.55.8(@typescript-eslint/types@8.59.4) - svelte-sonner@1.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.3)): + svelte-sonner@1.1.1(svelte@5.55.8(@typescript-eslint/types@8.59.4)): dependencies: - runed: 0.28.0(svelte@5.55.5(@typescript-eslint/types@8.59.3)) - svelte: 5.55.5(@typescript-eslint/types@8.59.3) + runed: 0.28.0(svelte@5.55.8(@typescript-eslint/types@8.59.4)) + svelte: 5.55.8(@typescript-eslint/types@8.59.4) - svelte@5.55.5(@typescript-eslint/types@8.59.3): + svelte@5.55.8(@typescript-eslint/types@8.59.4): dependencies: '@jridgewell/remapping': 2.3.5 '@jridgewell/sourcemap-codec': 1.5.5 @@ -5904,9 +5734,9 @@ snapshots: aria-query: 5.3.1 axobject-query: 4.1.0 clsx: 2.1.1 - devalue: 5.8.0 + devalue: 5.8.1 esm-env: 1.2.2 - esrap: 2.2.8(@typescript-eslint/types@8.59.3) + esrap: 2.2.9(@typescript-eslint/types@8.59.4) is-reference: 3.0.3 locate-character: 3.0.0 magic-string: 0.30.21 @@ -5960,13 +5790,13 @@ snapshots: type-level-regexp@0.1.17: {} - typescript-eslint@8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3): + typescript-eslint@8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/parser': 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.3(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) - eslint: 10.3.0(jiti@2.7.0) + '@typescript-eslint/eslint-plugin': 8.59.4(@typescript-eslint/parser@8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/parser': 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) + eslint: 10.4.0(jiti@2.7.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color @@ -5988,7 +5818,7 @@ snapshots: quansync: 1.0.0 unconfig-core: 7.5.0 - undici-types@7.21.0: {} + undici-types@7.24.6: {} undici@6.25.0: {} @@ -5996,7 +5826,7 @@ snapshots: universal-user-agent@7.0.3: {} - unocss@66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)): + unocss@66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)): dependencies: '@unocss/cli': 66.6.8 '@unocss/core': 66.6.8 @@ -6014,7 +5844,7 @@ snapshots: '@unocss/transformer-compile-class': 66.6.8 '@unocss/transformer-directives': 66.6.8 '@unocss/transformer-variant-group': 66.6.8 - '@unocss/vite': 66.6.8(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + '@unocss/vite': 66.6.8(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' @@ -6042,33 +5872,33 @@ snapshots: uuid@14.0.0: {} - vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0): + vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 postcss: 8.5.14 - rolldown: 1.0.0 + rolldown: 1.0.1 tinyglobby: 0.2.16 optionalDependencies: - '@types/node': 25.7.0 + '@types/node': 25.9.0 fsevents: 2.3.3 jiti: 2.7.0 yaml: 2.9.0 - vitefu@1.1.3(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)): + vitefu@1.1.3(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)): optionalDependencies: - vite: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) + vite: 8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0) - vitest-browser-svelte@2.1.1(svelte@5.55.5(@typescript-eslint/types@8.59.3))(vitest@4.1.6): + vitest-browser-svelte@2.1.1(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vitest@4.1.6): dependencies: - '@testing-library/svelte-core': 1.0.0(svelte@5.55.5(@typescript-eslint/types@8.59.3)) - svelte: 5.55.5(@typescript-eslint/types@8.59.3) - vitest: 4.1.6(@types/node@25.7.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + '@testing-library/svelte-core': 1.0.0(svelte@5.55.8(@typescript-eslint/types@8.59.4)) + svelte: 5.55.8(@typescript-eslint/types@8.59.4) + vitest: 4.1.6(@types/node@25.9.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) - vitest@4.1.6(@types/node@25.7.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)): + vitest@4.1.6(@types/node@25.9.0)(@vitest/browser-playwright@4.1.6)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.6 - '@vitest/mocker': 4.1.6(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0)) + '@vitest/mocker': 4.1.6(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.6 '@vitest/runner': 4.1.6 '@vitest/snapshot': 4.1.6 @@ -6085,11 +5915,11 @@ snapshots: tinyexec: 1.1.2 tinyglobby: 0.2.16 tinyrainbow: 3.1.0 - vite: 8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0) + vite: 8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 25.7.0 - '@vitest/browser-playwright': 4.1.6(playwright@1.60.0)(vite@8.0.12(@types/node@25.7.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6) + '@types/node': 25.9.0 + '@vitest/browser-playwright': 4.1.6(playwright@1.60.0)(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.6) '@vitest/coverage-v8': 4.1.6(@vitest/browser@4.1.6)(vitest@4.1.6) transitivePeerDependencies: - msw @@ -6144,3 +5974,5 @@ snapshots: yoctocolors@2.1.2: {} zimmerframe@1.1.4: {} + + zod@4.4.3: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index fdd5fe9..fc2a960 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,6 +1,4 @@ catalogs: - back-libs: - dotenv: ^17.4.2 build: '@tsconfig/svelte': ^5.0.8 'svelte-adapter-bun': ^1.0.1 @@ -41,6 +39,10 @@ catalogs: '@iconify-json/ic': ^1.2.4 '@iconify-json/material-icon-theme': ^1.2.64 '@iconify-json/solar': ^1.2.5 + libs-back: + dotenv: ^17.4.2 + libs-front: + zod: ^4.4.3 lint: '@nanoforge-dev/utils-eslint-config': ^1.0.2 '@nanoforge-dev/utils-prettier-config': ^1.0.2 diff --git a/src/lib/client/action/base.repository.ts b/src/lib/client/action/base.repository.ts index adc109d..e1812c4 100644 --- a/src/lib/client/action/base.repository.ts +++ b/src/lib/client/action/base.repository.ts @@ -18,11 +18,7 @@ export class BaseRepository { } private async runRequestBody(path: string, body?: I, options?: RequestOptions): Promise { - const rawResult = await this._client.postFormData( - path, - this._parseBodyToFormData(body), - options, - ); + const rawResult = await this._client.post(path, this._parseBodyToFormData(body), options); const result = deserialize(await rawResult.text()); if (result.type === 'redirect') diff --git a/src/lib/client/action/client.ts b/src/lib/client/action/client.ts index 2b233eb..42a716b 100644 --- a/src/lib/client/action/client.ts +++ b/src/lib/client/action/client.ts @@ -11,11 +11,7 @@ export interface ActionClient { } export const getActionClient = (): ActionClient => { - const client = new HttpClient('', { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }); + const client = new HttpClient('', {}); return { config: new ConfigRepository(client), diff --git a/src/lib/client/project/project-loader/project-loader.ts b/src/lib/client/project/project-loader/project-loader.ts new file mode 100644 index 0000000..4699323 --- /dev/null +++ b/src/lib/client/project/project-loader/project-loader.ts @@ -0,0 +1,19 @@ +import { + type ActionProject, + type CreateProjectActionInput, + getActionClient, +} from '$lib/client/action'; +import { type Project } from '$lib/client/project'; + +export class ProjectLoader { + static async create(input: CreateProjectActionInput) { + const res = await getActionClient().project.new(input); + + return ProjectLoader.load(res); + } + + static load(project: ActionProject): Project { + void project; + throw new Error('Not implemented yet'); + } +} diff --git a/src/lib/client/utils/file-system/file-system-file.ts b/src/lib/client/utils/file-system/file-system-file.ts index c3ab740..e13237e 100644 --- a/src/lib/client/utils/file-system/file-system-file.ts +++ b/src/lib/client/utils/file-system/file-system-file.ts @@ -91,7 +91,7 @@ export class FileSystemFile { this.handle = handle; } - getName(): string { + get name(): string { return this.handle.name; } diff --git a/src/lib/components/ProjectLoader/CreateProject.svelte b/src/lib/components/ProjectLoader/CreateProject.svelte index 97adcef..50465da 100644 --- a/src/lib/components/ProjectLoader/CreateProject.svelte +++ b/src/lib/components/ProjectLoader/CreateProject.svelte @@ -1,7 +1,12 @@ @@ -54,37 +63,21 @@ onclick={(e) => e.target === e.currentTarget && (show = false)} onkeydown={handleClose} > -
{ - e.preventDefault(); - const formData = new FormData(e.currentTarget); - projectLoading = localApi.createProject(formData); - }} + - New project - - Project Name - - - - Project local path - - -
+ + +
-
- - - - - - - - - - - - - - - - - - - - - {#if createGitRepository} - - Git Remote + + {#if showAdvancedSettings} + + + + {#snippet children({ id, name, value, handleChange })} + + {/snippet} + + + + {#snippet children({ id, name, value, handleChange })} + + {/snippet} + + + + {#snippet children({ id, name, value, handleChange })} - - {/if} -
+ {/snippet} + + + + {#snippet children({ id, name, value, handleChange })} + + {/snippet} + + + + {#snippet children({ id, name, value, handleChange })} + + {/snippet} + - {error} + {#if form.values.createGitRepository} + + {/if} + {/if}
- +
- +
+ {#if projectLoading !== null} newProject()} + callback={() => newProject(form.values)} /> {/if} diff --git a/src/lib/components/Widget/ContentBrowser/ContentBrowserItemCard.svelte b/src/lib/components/Widget/ContentBrowser/ContentBrowserItemCard.svelte index eeb93b1..6f158f5 100644 --- a/src/lib/components/Widget/ContentBrowser/ContentBrowserItemCard.svelte +++ b/src/lib/components/Widget/ContentBrowser/ContentBrowserItemCard.svelte @@ -24,19 +24,20 @@ return; } - let tabType = contentBrowserItemType.find((type) => handle.getName().endsWith(type.suffix)) - ?.type as TabTypeId | undefined; + let tabType = contentBrowserItemType.find((type) => handle.name.endsWith(type.suffix))?.type as + | TabTypeId + | undefined; if (!tabType) return; tabsStore.openTab({ type: tabType, - title: handle.getName(), + title: handle.name, file: handle, }); } onMount(() => { - fileType = contentBrowserItemType.find((type) => handle.getName().endsWith(type.suffix)); + fileType = contentBrowserItemType.find((type) => handle.name.endsWith(type.suffix)); }); diff --git a/src/lib/components/Widget/ContentBrowser/ContentBrowserWidget.svelte b/src/lib/components/Widget/ContentBrowser/ContentBrowserWidget.svelte index 2281366..64cd655 100644 --- a/src/lib/components/Widget/ContentBrowser/ContentBrowserWidget.svelte +++ b/src/lib/components/Widget/ContentBrowser/ContentBrowserWidget.svelte @@ -73,7 +73,7 @@ {/if} ($CurrentDirectory = folder)}>{folder.name} {/each} diff --git a/src/lib/components/forms/Form.svelte b/src/lib/components/forms/Form.svelte new file mode 100644 index 0000000..24d4211 --- /dev/null +++ b/src/lib/components/forms/Form.svelte @@ -0,0 +1,37 @@ + + +
+ {@render children()} +
diff --git a/src/lib/components/forms/FormField.svelte b/src/lib/components/forms/FormField.svelte new file mode 100644 index 0000000..b07ec94 --- /dev/null +++ b/src/lib/components/forms/FormField.svelte @@ -0,0 +1,31 @@ + + +
+ {#if label} + + {/if} + {@render children({ + id: `form-${name}`, + name, + value: form.values[name], + handleChange: form.handleChange, + })} + {#if form.errors[name]} + {form.errors[name]} + {/if} +
diff --git a/src/lib/components/forms/form.svelte.ts b/src/lib/components/forms/form.svelte.ts new file mode 100644 index 0000000..2ea69f4 --- /dev/null +++ b/src/lib/components/forms/form.svelte.ts @@ -0,0 +1,68 @@ +import type { ZodType } from 'zod'; + +export type FormErrors = { + [K in keyof T]?: string; +}; + +export const useForm = ( + config: { + defaultValues?: Partial; + schema?: ZodType; + onSubmit?: (values: T) => void | Promise; + } = {}, +) => { + const values = $state({ ...(config.defaultValues ?? {}) } as T); + let errors = $state>({}); + let isSubmitting = $state(false); + + function handleChange(event: Event): void { + const el = event.target as HTMLInputElement; + const field = el.name as keyof T; + (values as any)[field] = el.type === 'checkbox' ? el.checked : el.value; + } + + const handleSubmit = async (event: Event): Promise => { + event.preventDefault(); + + if (config.schema) { + const result = config.schema.safeParse(values); + errors = {} as FormErrors; + if (!result.success) { + for (const issue of result.error.issues) { + const key = issue.path[0] as keyof T; + if (key && !(errors as any)[key]) (errors as any)[key] = issue.message; + } + return; + } + } + + isSubmitting = true; + try { + await config.onSubmit?.(values); + } finally { + isSubmitting = false; + } + }; + + const reset = (): void => { + Object.assign(values, { ...(config.defaultValues ?? {}) }); + errors = {} as FormErrors; + }; + + return { + get values() { + return values; + }, + get errors() { + return errors; + }, + get isSubmitting() { + return isSubmitting; + }, + handleChange, + handleSubmit, + reset, + }; +}; + +export type FormInstance = ReturnType>; diff --git a/src/lib/components/forms/form.type.ts b/src/lib/components/forms/form.type.ts new file mode 100644 index 0000000..dc13cd0 --- /dev/null +++ b/src/lib/components/forms/form.type.ts @@ -0,0 +1 @@ +export type { FormErrors, FormInstance } from './form.svelte'; diff --git a/src/lib/components/forms/inputs/FormFieldInput.svelte b/src/lib/components/forms/inputs/FormFieldInput.svelte new file mode 100644 index 0000000..a7a298c --- /dev/null +++ b/src/lib/components/forms/inputs/FormFieldInput.svelte @@ -0,0 +1,32 @@ + + + + {#snippet children({ id, name, value, handleChange })} + + {/snippet} + diff --git a/src/lib/server/cli/cli.ts b/src/lib/server/cli/cli.ts index 4a342dc..30dbd60 100644 --- a/src/lib/server/cli/cli.ts +++ b/src/lib/server/cli/cli.ts @@ -146,8 +146,10 @@ export class Cli { } } - private mergeParams(...opts: Record[]) { - const merged: any = {}; + private mergeParams( + ...opts: Record[] + ): Record { + const merged: Record = {}; for (const opt of opts) { for (const [key, value] of Object.entries(opt)) { if (value === undefined) continue; @@ -162,14 +164,14 @@ export class Cli { defaultOpts: Record, ): string[] { const params = []; - for (const [key, value] of this.mergeParams(defaultOpts, opts)) { + for (const [key, value] of Object.entries(this.mergeParams(defaultOpts, opts))) { const name = camelToKebab(key); if (typeof value === 'boolean') { if (value) params.push(`--${name}`); else params.push(`--no-${name}`); } else { - params.push(`--${name}`, `'${value}'`); + params.push(`--${name}`, `${value}`); } } return params; diff --git a/src/lib/server/utils/request-handler/action-handler.ts b/src/lib/server/utils/request-handler/action-handler.ts index 6c728c7..b45b621 100644 --- a/src/lib/server/utils/request-handler/action-handler.ts +++ b/src/lib/server/utils/request-handler/action-handler.ts @@ -8,10 +8,11 @@ import { assertRequest } from './request.policy'; import type { Callback, RequestHandlerOptions } from './types'; const handleError = (e: unknown): ActionFailure<{ error: string; message: unknown }> => { + console.error(e); if (e instanceof Exception) { return fail(e.status, { error: e.error, message: e.message }); } - return fail(500, { error: 'Internal Server Error', message: e }); + return fail(500, { error: 'Internal Server Error', message: (e as any).toString() }); }; export const useActionHandler = ( diff --git a/src/lib/utils/http/client.ts b/src/lib/utils/http/client.ts index 98f5895..6fdd45a 100644 --- a/src/lib/utils/http/client.ts +++ b/src/lib/utils/http/client.ts @@ -39,17 +39,7 @@ export class HttpClient { }); } - post(path: string, body?: string, options?: RequestOptions): Promise { - return this._applyMiddlewares(path, options, (newPath, newOptions) => { - return this._request(newPath, { - ...newOptions, - method: 'POST', - body: body, - }); - }); - } - - postFormData(path: string, body?: FormData, options?: RequestOptions): Promise { + post(path: string, body?: string | FormData, options?: RequestOptions): Promise { return this._applyMiddlewares(path, options, (newPath, newOptions) => { return this._request(newPath, { ...newOptions, diff --git a/src/lib/utils/null.ts b/src/lib/utils/null.ts new file mode 100644 index 0000000..2aa9bb9 --- /dev/null +++ b/src/lib/utils/null.ts @@ -0,0 +1,3 @@ +export const isNullish = (value: any): boolean => { + return value === undefined || value === null; +}; diff --git a/src/lib/utils/object.ts b/src/lib/utils/object.ts new file mode 100644 index 0000000..a293376 --- /dev/null +++ b/src/lib/utils/object.ts @@ -0,0 +1,27 @@ +import { isNullish } from '@utils/null'; + +export const cloneDeep = (obj: T): T => JSON.parse(JSON.stringify(obj)); + +type AssignType = { + [K in keyof T]: T[K] extends object ? AssignType : V; +}; + +export const assignDeep = , V>(obj: T, value: V): AssignType => { + const copy: any = {}; + for (const key in obj) { + copy[key] = + !isNullish(obj[key]) && typeof obj[key] === 'object' ? assignDeep(obj[key], value) : value; + } + return copy; +}; + +export const flatObjectValues = (object: any): any[] => { + let results: any[] = []; + + for (const value of Object.values(object)) { + const values = typeof value === 'object' ? flatObjectValues(value) : [value]; + results = [...results, ...values]; + } + + return results; +}; From 569e2e5b46f0f4c216a8954c8b96942626159c14 Mon Sep 17 00:00:00 2001 From: Exelo Date: Tue, 19 May 2026 15:45:07 +0900 Subject: [PATCH 21/58] chore: add init in project loader --- src/lib/client/action/client.ts | 4 ++- src/lib/client/action/index.ts | 2 +- src/lib/client/project/index.ts | 1 + .../project/project-loader/project-loader.ts | 33 ++++++++++++------- src/lib/client/project/project.ts | 9 +++-- 5 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/lib/client/action/client.ts b/src/lib/client/action/client.ts index 42a716b..c1316af 100644 --- a/src/lib/client/action/client.ts +++ b/src/lib/client/action/client.ts @@ -10,7 +10,7 @@ export interface ActionClient { project: ProjectRepository; } -export const getActionClient = (): ActionClient => { +const getActionClient = (): ActionClient => { const client = new HttpClient('', {}); return { @@ -19,3 +19,5 @@ export const getActionClient = (): ActionClient => { project: new ProjectRepository(client), }; }; + +export const actions = getActionClient(); diff --git a/src/lib/client/action/index.ts b/src/lib/client/action/index.ts index d21081d..79df45b 100644 --- a/src/lib/client/action/index.ts +++ b/src/lib/client/action/index.ts @@ -1,2 +1,2 @@ -export { getActionClient, type ActionClient } from './client'; +export { actions, type ActionClient } from './client'; export * from './types'; diff --git a/src/lib/client/project/index.ts b/src/lib/client/project/index.ts index 745ffa0..4ce11e4 100644 --- a/src/lib/client/project/index.ts +++ b/src/lib/client/project/index.ts @@ -1 +1,2 @@ export { Project } from './project'; +export { ProjectLoader, useProject } from './project-loader/project-loader'; diff --git a/src/lib/client/project/project-loader/project-loader.ts b/src/lib/client/project/project-loader/project-loader.ts index 4699323..d2e9a71 100644 --- a/src/lib/client/project/project-loader/project-loader.ts +++ b/src/lib/client/project/project-loader/project-loader.ts @@ -1,19 +1,30 @@ -import { - type ActionProject, - type CreateProjectActionInput, - getActionClient, -} from '$lib/client/action'; -import { type Project } from '$lib/client/project'; +import { get, writable } from 'svelte/store'; + +import { type ActionProject, type CreateProjectActionInput, actions } from '$lib/client/action'; +import { Project } from '$lib/client/project'; + +const projectStore = writable(null); export class ProjectLoader { static async create(input: CreateProjectActionInput) { - const res = await getActionClient().project.new(input); + const res = await actions.project.new(input); + + return ProjectLoader.init(res); + } - return ProjectLoader.load(res); + static unload() { + projectStore.set(null); + Project.reset(); } - static load(project: ActionProject): Project { - void project; - throw new Error('Not implemented yet'); + static async init(input: ActionProject): Promise { + Project.reset(); + + const project = new Project(input.id); + await project.init(); + projectStore.set(project); + return project; } } + +export const useProject = () => get(projectStore); diff --git a/src/lib/client/project/project.ts b/src/lib/client/project/project.ts index fc294ee..07158fe 100644 --- a/src/lib/client/project/project.ts +++ b/src/lib/client/project/project.ts @@ -1,4 +1,4 @@ -import { type ActionClient, getActionClient } from '$lib/client/action'; +import { type ActionClient, actions } from '$lib/client/action'; import { InfoHandler } from '$lib/client/info'; import { Loader } from '$lib/client/loader'; import { SyncFileSystem } from '$lib/client/sync-file-system'; @@ -18,13 +18,18 @@ export class Project { constructor(public id: string) {} + async init(): Promise { + // @todo add init of sub parts like save + return this; + } + get info(): InfoHandler { if (!this._info) this._info = new InfoHandler(this); return this._info; } get actions(): ActionClient { - if (!this._actions) this._actions = getActionClient(); + if (!this._actions) this._actions = actions; return this._actions; } From 53550d946da32e424ca08aa378bfb3ea61a3d028 Mon Sep 17 00:00:00 2001 From: Tchips46 Date: Wed, 20 May 2026 10:37:04 +0900 Subject: [PATCH 22/58] feat: save and package handling front --- src/app.d.ts | 3 - .../action/repositories/project.repository.ts | 12 +++ src/lib/client/action/types/project.type.ts | 8 ++ src/lib/client/project/package-handler.ts | 59 ++++++++++++ .../client/project/package/package-handler.ts | 30 ------- .../project/project-loader/project-loader.ts | 13 ++- src/lib/client/project/project.ts | 23 +++-- src/lib/client/project/save-handler.ts | 58 ++++++++++++ .../ProjectLoader/CreateProject.svelte | 20 ++--- .../ProjectLoader/LoadProject.svelte | 90 ++++++++++--------- .../Widget/ECSTree/EntityItem.svelte | 2 +- .../EntityInspector/ComponentSelector.svelte | 4 +- .../EntityInspectorWidget.svelte | 2 +- ...ent.action.ts => add-components.action.ts} | 4 +- ...system.action.ts => add-systems.action.ts} | 4 +- .../get-components-manifests.action.ts | 18 ++++ .../package/get-systems-manifests.action.ts | 18 ++++ src/lib/server/api/client.ts | 5 +- .../server/project/package/package-handler.ts | 10 +-- src/lib/server/project/project-handler.ts | 10 +-- src/routes/actions/project/+page.server.ts | 8 +- src/routes/load-project/+page.server.ts | 81 ----------------- src/routes/load-project/load-project.spec.ts | 24 ----- 23 files changed, 283 insertions(+), 223 deletions(-) create mode 100644 src/lib/client/project/package-handler.ts delete mode 100644 src/lib/client/project/package/package-handler.ts create mode 100644 src/lib/client/project/save-handler.ts rename src/lib/server/actions/project/cli/{add-component.action.ts => add-components.action.ts} (75%) rename src/lib/server/actions/project/cli/{add-system.action.ts => add-systems.action.ts} (80%) create mode 100644 src/lib/server/actions/project/package/get-components-manifests.action.ts create mode 100644 src/lib/server/actions/project/package/get-systems-manifests.action.ts delete mode 100644 src/routes/load-project/+page.server.ts delete mode 100644 src/routes/load-project/load-project.spec.ts diff --git a/src/app.d.ts b/src/app.d.ts index ae3ea3f..f91269f 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -1,7 +1,5 @@ // See https://svelte.dev/docs/kit/types#app.d.ts // for information about these interfaces -import child_process from 'node:child_process'; - declare global { namespace App { // interface Error {} @@ -16,7 +14,6 @@ declare module 'svelte-kit-sessions' { interface SessionData { id: string; path: string; - projectPid?: number; } } diff --git a/src/lib/client/action/repositories/project.repository.ts b/src/lib/client/action/repositories/project.repository.ts index 537c0ca..37cf7aa 100644 --- a/src/lib/client/action/repositories/project.repository.ts +++ b/src/lib/client/action/repositories/project.repository.ts @@ -1,3 +1,5 @@ +import type { EditorComponentManifest, EditorSystemManifest } from '@nanoforge-dev/ecs-lib'; + import { BaseRepository } from '../base.repository'; import type { ActionProject, @@ -6,7 +8,9 @@ import type { CreateComponentActionInput, CreateProjectActionInput, CreateSystemActionInput, + GetComponentsManifestsActionInput, GetSaveResult, + GetSystemsManifestsActionInput, LoadProjectActionInput, NewComponentPackageResult, NewSystemPackageResult, @@ -38,6 +42,14 @@ export class ProjectRepository extends BaseRepository { createSystem(input: CreateSystemActionInput): Promise { return this.run(`/actions/project?/createSystem`, input); } + getComponentsManifests( + input: GetComponentsManifestsActionInput, + ): Promise { + return this.run(`/actions/project?/getComponentsManifests`, input); + } + getSystemsManifests(input: GetSystemsManifestsActionInput): Promise { + return this.run(`/actions/project?/getSystemsManifests`, input); + } getSave(): Promise { return this.run(`/actions/project?/getSave`); } diff --git a/src/lib/client/action/types/project.type.ts b/src/lib/client/action/types/project.type.ts index 31b2ecf..f5d7509 100644 --- a/src/lib/client/action/types/project.type.ts +++ b/src/lib/client/action/types/project.type.ts @@ -42,6 +42,14 @@ export interface AddSystemsActionInput { systemNames: [string, ...string[]]; } +export interface GetComponentsManifestsActionInput { + componentPaths: string[]; +} + +export interface GetSystemsManifestsActionInput { + systemPaths: string[]; +} + export interface CreateComponentActionInput { componentName: string; } diff --git a/src/lib/client/project/package-handler.ts b/src/lib/client/project/package-handler.ts new file mode 100644 index 0000000..874561b --- /dev/null +++ b/src/lib/client/project/package-handler.ts @@ -0,0 +1,59 @@ +import type { EditorComponentManifest, EditorSystemManifest } from '@nanoforge-dev/ecs-lib'; + +import type { Project } from '$lib/client/project'; + +export class PackageHandler { + private _project: Project; + + private _componentsManifests: EditorComponentManifest[] = []; + private _systemsManifests: EditorSystemManifest[] = []; + + constructor(project: Project) { + this._project = project; + } + + async init() { + if (this._project.save.save.components.length > 0) { + await this._project.actions.project.getComponentsManifests({ + componentPaths: this._project.save.save.components.map((c) => c.path), + }); + } + if (this._project.save.save.systems.length > 0) { + await this._project.actions.project.getSystemsManifests({ + systemPaths: this._project.save.save.systems.map((s) => s.path), + }); + } + } + + get componentsManifests(): EditorComponentManifest[] { + return this._componentsManifests; + } + + get systemsManifests(): EditorSystemManifest[] { + return this._systemsManifests; + } + + async installComponent(name: string): Promise { + const newComponent = ( + await this._project.actions.project.addComponents({ componentNames: [name] }) + )[0]; + + this._project.save.save.components.push(newComponent.save); + this._componentsManifests.push(newComponent.manifest); + } + + async installSystem(name: string): Promise { + const newSystem = (await this._project.actions.project.addSystems({ systemNames: [name] }))[0]; + + this._project.save.save.systems.push(newSystem.save); + this._systemsManifests.push(newSystem.manifest); + } + + addComponentManifest(component: EditorComponentManifest) { + this._componentsManifests.push(component); + } + + addSystemManifest(system: EditorSystemManifest) { + this._systemsManifests.push(system); + } +} diff --git a/src/lib/client/project/package/package-handler.ts b/src/lib/client/project/package/package-handler.ts deleted file mode 100644 index 63b60c7..0000000 --- a/src/lib/client/project/package/package-handler.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { get } from 'svelte/store'; - -import { type Project } from '$lib/client/project'; -import { save } from '$lib/components/Widget/EditorGame/game.svelte'; - -export class PackageHandler { - private readonly handler: Project; - - constructor(handler: Project) { - this.handler = handler; - } - - async installComponent(name: string): Promise { - const newComponent = ( - await this.handler.actions.project.addComponents({ componentNames: [name] }) - )[0]; - - const s = get(save); - s.components.push(newComponent.save); - save.set(s); - } - - async installSystem(name: string): Promise { - const newSystem = (await this.handler.actions.project.addSystems({ systemNames: [name] }))[0]; - - const s = get(save); - s.systems.push(newSystem.save); - save.set(s); - } -} diff --git a/src/lib/client/project/project-loader/project-loader.ts b/src/lib/client/project/project-loader/project-loader.ts index d2e9a71..9503ed2 100644 --- a/src/lib/client/project/project-loader/project-loader.ts +++ b/src/lib/client/project/project-loader/project-loader.ts @@ -1,6 +1,11 @@ import { get, writable } from 'svelte/store'; -import { type ActionProject, type CreateProjectActionInput, actions } from '$lib/client/action'; +import { + type ActionProject, + type CreateProjectActionInput, + type LoadProjectActionInput, + actions, +} from '$lib/client/action'; import { Project } from '$lib/client/project'; const projectStore = writable(null); @@ -12,6 +17,12 @@ export class ProjectLoader { return ProjectLoader.init(res); } + static async load(input: LoadProjectActionInput) { + const res = await actions.project.load(input); + + return ProjectLoader.init(res); + } + static unload() { projectStore.set(null); Project.reset(); diff --git a/src/lib/client/project/project.ts b/src/lib/client/project/project.ts index 07158fe..349d147 100644 --- a/src/lib/client/project/project.ts +++ b/src/lib/client/project/project.ts @@ -1,22 +1,26 @@ import { type ActionClient, actions } from '$lib/client/action'; import { InfoHandler } from '$lib/client/info'; import { Loader } from '$lib/client/loader'; +import { PackageHandler } from '$lib/client/project/package-handler'; +import { SaveHandler } from '$lib/client/project/save-handler'; import { SyncFileSystem } from '$lib/client/sync-file-system'; -import type { Save } from '@utils/types'; - export class Project { private _info: InfoHandler | undefined; private _actions: ActionClient | undefined; private _fs: SyncFileSystem | undefined; private _loader: Loader | undefined; - private _save: Save | undefined; + private _save: SaveHandler | undefined; + private _packageHandler: PackageHandler | undefined; static reset(): void { InfoHandler.reset(); } - constructor(public id: string) {} + constructor(public id: string) { + this._save = new SaveHandler(this); + this._packageHandler = new PackageHandler(this); + } async init(): Promise { // @todo add init of sub parts like save @@ -43,10 +47,13 @@ export class Project { return this._loader; } - async save(): Promise { - if (!this._save) { - this._save = (await this.actions.project.getSave()).save; - } + get save(): SaveHandler { + if (!this._save) this._save = new SaveHandler(this); return this._save; } + + get package(): PackageHandler { + if (!this._packageHandler) this._packageHandler = new PackageHandler(this); + return this._packageHandler; + } } diff --git a/src/lib/client/project/save-handler.ts b/src/lib/client/project/save-handler.ts new file mode 100644 index 0000000..f1b429c --- /dev/null +++ b/src/lib/client/project/save-handler.ts @@ -0,0 +1,58 @@ +import type { EditorComponentManifest } from '@nanoforge-dev/ecs-lib'; +import { type Writable, get, writable } from 'svelte/store'; + +import type { Project } from '$lib/client/project'; + +import type { Save, SaveComponent, SaveEntity, SaveSystem } from '@utils/types'; + +export class SaveHandler { + private _project: Project; + private _save: Writable = writable({ + libraries: [], + entities: [], + components: [], + systems: [], + }); + + constructor(project: Project) { + this._project = project; + } + + async init() { + await this.fetchFromServer(); + } + + async fetchFromServer() { + this._save.set((await this._project.actions.project.getSave()).save); + } + + get save(): Save { + return get(this._save); + } + + addComponent(component: SaveComponent) { + get(this._save).components.push(component); + } + + addEntity(entity: SaveEntity) { + get(this._save).entities.push(entity); + } + + addSystem(system: SaveSystem) { + get(this._save).systems.push(system); + } + + addComponentToEntity( + entityId: string, + componentName: string, + componentManifest: EditorComponentManifest, + ) { + const entity = get(this._save).entities.find((e) => e.id === entityId); + if (!entity) { + throw new Error('Entity not found: ' + entityId); + } + const newComp: Record = {}; + componentManifest.params.forEach((c) => (newComp[c.name] = c.default)); + entity.components[componentName] = newComp; + } +} diff --git a/src/lib/components/ProjectLoader/CreateProject.svelte b/src/lib/components/ProjectLoader/CreateProject.svelte index 50465da..83fde9e 100644 --- a/src/lib/components/ProjectLoader/CreateProject.svelte +++ b/src/lib/components/ProjectLoader/CreateProject.svelte @@ -14,7 +14,7 @@ } let { show = $bindable(), callback }: Props = $props(); - let projectLoading: Promise | null = $state(null); + let creationPromises: Promise[] = $state([]); let showAdvancedSettings: boolean = $state(false); const schema = z.object({ @@ -50,7 +50,10 @@ } async function newProject(values: ProjectForm) { - const project = await ProjectLoader.create(values); + const projectPromise = ProjectLoader.create(values); + creationPromises.push(projectPromise); + + const project = await projectPromise; callback?.(project.id); } @@ -196,11 +199,8 @@ -{#if projectLoading !== null} - newProject(form.values)} - /> -{/if} + 0} +/> diff --git a/src/lib/components/ProjectLoader/LoadProject.svelte b/src/lib/components/ProjectLoader/LoadProject.svelte index e58c4a9..73fcbe8 100644 --- a/src/lib/components/ProjectLoader/LoadProject.svelte +++ b/src/lib/components/ProjectLoader/LoadProject.svelte @@ -1,5 +1,11 @@ @@ -42,40 +52,38 @@ onclick={(e) => e.target === e.currentTarget && (show = false)} onkeydown={handleClose} > -
{ - e.preventDefault(); - const formData = new FormData(e.currentTarget); - loadProject(formData); - }} + - Load project - - Project local path - - - - {error} +
- + Create +
- + + + 0} +/> diff --git a/src/lib/components/Widget/ECSTree/EntityItem.svelte b/src/lib/components/Widget/ECSTree/EntityItem.svelte index bc9d38c..d34400f 100644 --- a/src/lib/components/Widget/ECSTree/EntityItem.svelte +++ b/src/lib/components/Widget/ECSTree/EntityItem.svelte @@ -1,6 +1,6 @@ -
- - + + Create project +
diff --git a/src/lib/components/ProjectLoader/LoadProject.svelte b/src/lib/components/ProjectLoader/LoadProject.svelte index 73fcbe8..b2e9f8a 100644 --- a/src/lib/components/ProjectLoader/LoadProject.svelte +++ b/src/lib/components/ProjectLoader/LoadProject.svelte @@ -5,7 +5,7 @@ import FormFieldInput from '$lib/components/forms/inputs/FormFieldInput.svelte'; import Form from '$lib/components/forms/Form.svelte'; import ProgressBar from '$lib/components/ProjectLoader/ProgressBar.svelte'; - import { Button } from 'flowbite-svelte'; + import { Button } from '$lib/components/ui/button'; interface Props { show: boolean; @@ -21,14 +21,16 @@ type ProjectForm = z.infer; - const form = useForm({ + const sf = useForm({ + schema, defaultValues: { path: '', }, - schema, onSubmit: loadProject, }); + const { submitting } = sf; + function handleClose(event: KeyboardEvent) { if (event.key === 'Escape') { show = false; @@ -36,7 +38,7 @@ } export async function loadProject(values: ProjectForm) { - const projectPromise = ProjectLoader.load(values); + const projectPromise = ProjectLoader.load(values.path); creationPromises.push(projectPromise); const project = await projectPromise; @@ -53,15 +55,10 @@ onkeydown={handleClose} >
- +
0} /> diff --git a/src/lib/components/forms/Form.svelte b/src/lib/components/forms/Form.svelte index 24d4211..83bf0b4 100644 --- a/src/lib/components/forms/Form.svelte +++ b/src/lib/components/forms/Form.svelte @@ -1,37 +1,20 @@ -
+ {@render children()}
diff --git a/src/lib/components/forms/FormField.svelte b/src/lib/components/forms/FormField.svelte index b07ec94..5cc30b2 100644 --- a/src/lib/components/forms/FormField.svelte +++ b/src/lib/components/forms/FormField.svelte @@ -1,31 +1,40 @@ -
- {#if label} - - {/if} - {@render children({ - id: `form-${name}`, - name, - value: form.values[name], - handleChange: form.handleChange, - })} - {#if form.errors[name]} - {form.errors[name]} + + + {#snippet children({ props })} + {#if label} + {label} + {/if} + {@render fieldChildren({ props })} + {/snippet} + + {#if description} + {description} {/if} -
+ + diff --git a/src/lib/components/forms/form.svelte.ts b/src/lib/components/forms/form.svelte.ts index 2ea69f4..ac1ed62 100644 --- a/src/lib/components/forms/form.svelte.ts +++ b/src/lib/components/forms/form.svelte.ts @@ -1,68 +1,29 @@ +import { type SuperForm, defaults, superForm } from 'sveltekit-superforms'; +import { zod4, zodClient } from 'sveltekit-superforms/adapters'; import type { ZodType } from 'zod'; -export type FormErrors = { - [K in keyof T]?: string; -}; - -export const useForm = ( - config: { - defaultValues?: Partial; - schema?: ZodType; - onSubmit?: (values: T) => void | Promise; - } = {}, -) => { - const values = $state({ ...(config.defaultValues ?? {}) } as T); - let errors = $state>({}); - let isSubmitting = $state(false); - - function handleChange(event: Event): void { - const el = event.target as HTMLInputElement; - const field = el.name as keyof T; - (values as any)[field] = el.type === 'checkbox' ? el.checked : el.value; - } - - const handleSubmit = async (event: Event): Promise => { - event.preventDefault(); - - if (config.schema) { - const result = config.schema.safeParse(values); - errors = {} as FormErrors; - if (!result.success) { - for (const issue of result.error.issues) { - const key = issue.path[0] as keyof T; - if (key && !(errors as any)[key]) (errors as any)[key] = issue.message; - } - return; +export const useForm = >(config: { + schema: ZodType; + defaultValues?: Partial; + onSubmit?: (values: T) => void | Promise; +}): SuperForm => { + const result = superForm(defaults(zod4(config.schema as any)), { + SPA: true, + validators: zodClient(config.schema as any), + resetForm: false, + onUpdate: async ({ form: f }) => { + console.log(f.data); + if (f.valid) { + await config.onSubmit?.(f.data as T); } - } - - isSubmitting = true; - try { - await config.onSubmit?.(values); - } finally { - isSubmitting = false; - } - }; + }, + }); - const reset = (): void => { - Object.assign(values, { ...(config.defaultValues ?? {}) }); - errors = {} as FormErrors; - }; + if (config.defaultValues) { + result.form.update((v) => ({ ...v, ...config.defaultValues })); + } - return { - get values() { - return values; - }, - get errors() { - return errors; - }, - get isSubmitting() { - return isSubmitting; - }, - handleChange, - handleSubmit, - reset, - }; + return result as unknown as SuperForm; }; -export type FormInstance = ReturnType>; +export type FormInstance = SuperForm; diff --git a/src/lib/components/forms/form.type.ts b/src/lib/components/forms/form.type.ts index dc13cd0..396b9e7 100644 --- a/src/lib/components/forms/form.type.ts +++ b/src/lib/components/forms/form.type.ts @@ -1 +1 @@ -export type { FormErrors, FormInstance } from './form.svelte'; +export type { FormInstance } from './form.svelte'; diff --git a/src/lib/components/forms/inputs/FormFieldInput.svelte b/src/lib/components/forms/inputs/FormFieldInput.svelte index a7a298c..9667a5a 100644 --- a/src/lib/components/forms/inputs/FormFieldInput.svelte +++ b/src/lib/components/forms/inputs/FormFieldInput.svelte @@ -1,5 +1,8 @@ - - {#snippet children({ id, name, value, handleChange })} - + {#snippet children({ props })} + form.update((v) => ({ ...v, [name]: e.currentTarget.value }))} /> {/snippet} diff --git a/src/lib/components/forms/inputs/FormFieldMultiSelect.svelte b/src/lib/components/forms/inputs/FormFieldMultiSelect.svelte new file mode 100644 index 0000000..7b39f85 --- /dev/null +++ b/src/lib/components/forms/inputs/FormFieldMultiSelect.svelte @@ -0,0 +1,50 @@ + + + + {#snippet children({ props })} + form.update((s) => ({ ...s, [name]: v }))} + /> + {/snippet} + diff --git a/src/lib/components/forms/inputs/FormFieldSelect.svelte b/src/lib/components/forms/inputs/FormFieldSelect.svelte new file mode 100644 index 0000000..91c0437 --- /dev/null +++ b/src/lib/components/forms/inputs/FormFieldSelect.svelte @@ -0,0 +1,59 @@ + + + + {#snippet children({ props })} + form.update((s) => ({ ...s, [name]: v }))} + > + + {triggerContent} + + + {#each options as option (option.value)} + + {/each} + + + {/snippet} + diff --git a/src/lib/components/forms/inputs/FormFieldSwitch.svelte b/src/lib/components/forms/inputs/FormFieldSwitch.svelte new file mode 100644 index 0000000..7740886 --- /dev/null +++ b/src/lib/components/forms/inputs/FormFieldSwitch.svelte @@ -0,0 +1,30 @@ + + + + {#snippet children({ props })} + form.update((s) => ({ ...s, [name]: v }))} + /> + {/snippet} + diff --git a/src/lib/components/ui/button/button.svelte b/src/lib/components/ui/button/button.svelte new file mode 100644 index 0000000..5a572e1 --- /dev/null +++ b/src/lib/components/ui/button/button.svelte @@ -0,0 +1,89 @@ + + + + +{#if href} + + {@render children?.()} + +{:else} + +{/if} diff --git a/src/lib/components/ui/button/index.ts b/src/lib/components/ui/button/index.ts new file mode 100644 index 0000000..66c1087 --- /dev/null +++ b/src/lib/components/ui/button/index.ts @@ -0,0 +1,17 @@ +import Root, { + type ButtonProps, + type ButtonSize, + type ButtonVariant, + buttonVariants, +} from './button.svelte'; + +export { + Root, + type ButtonProps as Props, + // + Root as Button, + buttonVariants, + type ButtonProps, + type ButtonSize, + type ButtonVariant, +}; diff --git a/src/lib/components/ui/checkbox/checkbox.svelte b/src/lib/components/ui/checkbox/checkbox.svelte new file mode 100644 index 0000000..0921fbd --- /dev/null +++ b/src/lib/components/ui/checkbox/checkbox.svelte @@ -0,0 +1,39 @@ + + + + {#snippet children({ checked, indeterminate })} +
+ {#if checked} + + {:else if indeterminate} + + {/if} +
+ {/snippet} +
diff --git a/src/lib/components/ui/checkbox/index.ts b/src/lib/components/ui/checkbox/index.ts new file mode 100644 index 0000000..f52cb02 --- /dev/null +++ b/src/lib/components/ui/checkbox/index.ts @@ -0,0 +1,7 @@ +import Root from './checkbox.svelte'; + +export { + Root, + // + Root as Checkbox, +}; diff --git a/src/lib/components/ui/form/form-button.svelte b/src/lib/components/ui/form/form-button.svelte new file mode 100644 index 0000000..0133709 --- /dev/null +++ b/src/lib/components/ui/form/form-button.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/multi-select/index.ts b/src/lib/components/ui/multi-select/index.ts new file mode 100644 index 0000000..cbd18dc --- /dev/null +++ b/src/lib/components/ui/multi-select/index.ts @@ -0,0 +1,7 @@ +import Root from './multi-select.svelte'; + +export { + Root, + // + Root as MultiSelect, +}; diff --git a/src/lib/components/ui/multi-select/multi-select.svelte b/src/lib/components/ui/multi-select/multi-select.svelte new file mode 100644 index 0000000..7f05f98 --- /dev/null +++ b/src/lib/components/ui/multi-select/multi-select.svelte @@ -0,0 +1,106 @@ + + + + + {selectedLabels} + + + + + + + + onValueChange?.(v)} + class="flex flex-col p-1" + > + {#each options as option (option.value)} + + {/each} + + + + diff --git a/src/lib/components/ui/select/index.ts b/src/lib/components/ui/select/index.ts new file mode 100644 index 0000000..06762f3 --- /dev/null +++ b/src/lib/components/ui/select/index.ts @@ -0,0 +1,37 @@ +import Content from './select-content.svelte'; +import GroupHeading from './select-group-heading.svelte'; +import Group from './select-group.svelte'; +import Item from './select-item.svelte'; +import Label from './select-label.svelte'; +import Portal from './select-portal.svelte'; +import ScrollDownButton from './select-scroll-down-button.svelte'; +import ScrollUpButton from './select-scroll-up-button.svelte'; +import Separator from './select-separator.svelte'; +import Trigger from './select-trigger.svelte'; +import Root from './select.svelte'; + +export { + Root, + Group, + Label, + Item, + Content, + Trigger, + Separator, + ScrollDownButton, + ScrollUpButton, + GroupHeading, + Portal, + // + Root as Select, + Group as SelectGroup, + Label as SelectLabel, + Item as SelectItem, + Content as SelectContent, + Trigger as SelectTrigger, + Separator as SelectSeparator, + ScrollDownButton as SelectScrollDownButton, + ScrollUpButton as SelectScrollUpButton, + GroupHeading as SelectGroupHeading, + Portal as SelectPortal, +}; diff --git a/src/lib/components/ui/select/select-content.svelte b/src/lib/components/ui/select/select-content.svelte new file mode 100644 index 0000000..ba64c87 --- /dev/null +++ b/src/lib/components/ui/select/select-content.svelte @@ -0,0 +1,44 @@ + + + + + + + {@render children?.()} + + + + diff --git a/src/lib/components/ui/select/select-group-heading.svelte b/src/lib/components/ui/select/select-group-heading.svelte new file mode 100644 index 0000000..f73f87d --- /dev/null +++ b/src/lib/components/ui/select/select-group-heading.svelte @@ -0,0 +1,21 @@ + + + + {@render children?.()} + diff --git a/src/lib/components/ui/select/select-group.svelte b/src/lib/components/ui/select/select-group.svelte new file mode 100644 index 0000000..4f2e5b7 --- /dev/null +++ b/src/lib/components/ui/select/select-group.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/select/select-item.svelte b/src/lib/components/ui/select/select-item.svelte new file mode 100644 index 0000000..5217b07 --- /dev/null +++ b/src/lib/components/ui/select/select-item.svelte @@ -0,0 +1,38 @@ + + + + {#snippet children({ selected, highlighted })} + + {#if selected} + + {/if} + + {#if childrenProp} + {@render childrenProp({ selected, highlighted })} + {:else} + {label || value} + {/if} + {/snippet} + diff --git a/src/lib/components/ui/select/select-label.svelte b/src/lib/components/ui/select/select-label.svelte new file mode 100644 index 0000000..c1e803d --- /dev/null +++ b/src/lib/components/ui/select/select-label.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/select/select-portal.svelte b/src/lib/components/ui/select/select-portal.svelte new file mode 100644 index 0000000..fa48d6a --- /dev/null +++ b/src/lib/components/ui/select/select-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/select/select-scroll-down-button.svelte b/src/lib/components/ui/select/select-scroll-down-button.svelte new file mode 100644 index 0000000..5cbf4cc --- /dev/null +++ b/src/lib/components/ui/select/select-scroll-down-button.svelte @@ -0,0 +1,23 @@ + + + + + diff --git a/src/lib/components/ui/select/select-scroll-up-button.svelte b/src/lib/components/ui/select/select-scroll-up-button.svelte new file mode 100644 index 0000000..387ab53 --- /dev/null +++ b/src/lib/components/ui/select/select-scroll-up-button.svelte @@ -0,0 +1,23 @@ + + + + + diff --git a/src/lib/components/ui/select/select-separator.svelte b/src/lib/components/ui/select/select-separator.svelte new file mode 100644 index 0000000..a79a22f --- /dev/null +++ b/src/lib/components/ui/select/select-separator.svelte @@ -0,0 +1,18 @@ + + + diff --git a/src/lib/components/ui/select/select-trigger.svelte b/src/lib/components/ui/select/select-trigger.svelte new file mode 100644 index 0000000..a97cc85 --- /dev/null +++ b/src/lib/components/ui/select/select-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/src/lib/components/ui/select/select.svelte b/src/lib/components/ui/select/select.svelte new file mode 100644 index 0000000..ec122f3 --- /dev/null +++ b/src/lib/components/ui/select/select.svelte @@ -0,0 +1,11 @@ + + + diff --git a/src/lib/components/ui/separator/index.ts b/src/lib/components/ui/separator/index.ts new file mode 100644 index 0000000..56b2767 --- /dev/null +++ b/src/lib/components/ui/separator/index.ts @@ -0,0 +1,7 @@ +import Root from './separator.svelte'; + +export { + Root, + // + Root as Separator, +}; diff --git a/src/lib/components/ui/separator/separator.svelte b/src/lib/components/ui/separator/separator.svelte new file mode 100644 index 0000000..2b33e4a --- /dev/null +++ b/src/lib/components/ui/separator/separator.svelte @@ -0,0 +1,23 @@ + + + diff --git a/src/lib/components/ui/switch/index.ts b/src/lib/components/ui/switch/index.ts new file mode 100644 index 0000000..19be952 --- /dev/null +++ b/src/lib/components/ui/switch/index.ts @@ -0,0 +1,7 @@ +import Root from './switch.svelte'; + +export { + Root, + // + Root as Switch, +}; diff --git a/src/lib/components/ui/switch/switch.svelte b/src/lib/components/ui/switch/switch.svelte new file mode 100644 index 0000000..10826a9 --- /dev/null +++ b/src/lib/components/ui/switch/switch.svelte @@ -0,0 +1,31 @@ + + + + + diff --git a/src/lib/server/actions/project/new.action.ts b/src/lib/server/actions/project/new.action.ts index 5435e51..7b16bb0 100644 --- a/src/lib/server/actions/project/new.action.ts +++ b/src/lib/server/actions/project/new.action.ts @@ -19,11 +19,16 @@ class CreateProjectBody { export const createProjectAction = useActionHandler( async (handler) => { const { body, cli } = handler; + + const fullPath = body.projectPath?.split('/'); + const path = fullPath?.slice(-1)[0]; + const directory = fullPath?.slice(0, -1).join('/'); + cli.new({ editor: true, - directory: body.projectPath, + directory: directory || undefined, name: body.projectName, - path: body.projectName, + path: path || undefined, packageManager: body.packageManager, language: body.language, server: body.multiplayerServer, @@ -32,7 +37,7 @@ export const createProjectAction = useActionHandler( gitRemote: body.gitRemote, }); - return await loadProject({ path: resolve(body.projectPath || '.', body.projectName) }, handler); + return await loadProject({ path: resolve(body.projectPath || body.projectName) }, handler); }, { body: CreateProjectBody, diff --git a/src/lib/server/api/client.ts b/src/lib/server/api/client.ts index d76378b..9b9e0c5 100644 --- a/src/lib/server/api/client.ts +++ b/src/lib/server/api/client.ts @@ -11,15 +11,16 @@ import { RegistryRepository } from './repositories/registry.repository'; export interface Api { auth: AuthRepository; - projects?: ProjectRepository; + projects: ProjectRepository; registry: RegistryRepository; } +const DEFAULT_API_URL = 'https://api.nanoforge.eu'; + export const getNoAuthApi = (): Api => { const client = new HttpClient(env.API_URL || 'https://api.nanoforge.eu', { headers: { 'Content-Type': 'application/json', - 'Api-Key': env.API_KEY, }, }); const isOnline = env.PUBLIC_MODE === 'ONLINE'; @@ -27,15 +28,12 @@ export const getNoAuthApi = (): Api => { return { auth: new AuthRepository(client, isOnline), registry: new RegistryRepository(client, isOnline), - }; + } as Api; }; export const getApi = (cookies: Cookies): Api => { if (env.PUBLIC_MODE !== 'ONLINE') throw new Error('API is only available in online mode'); - if (!env.API_URL) throw new Error('API_URL is not defined'); - if (!env.API_KEY) throw new Error('API_KEY is not defined'); - - const client = new HttpClient(env.API_URL, { + const client = new HttpClient(env.API_URL ?? DEFAULT_API_URL, { headers: { 'Content-Type': 'application/json', 'Api-Key': env.API_KEY, diff --git a/src/lib/server/cli/cli-defaults.ts b/src/lib/server/cli/cli-defaults.ts index 38636b2..360d7d5 100644 --- a/src/lib/server/cli/cli-defaults.ts +++ b/src/lib/server/cli/cli-defaults.ts @@ -11,7 +11,6 @@ import type { } from './cli.type'; export const CLI_NEW_DEFAULTS: WithOptional = { - directory: '.', packageManager: 'npm', language: 'ts', strict: false, diff --git a/src/lib/server/cli/cli.ts b/src/lib/server/cli/cli.ts index 30dbd60..6835deb 100644 --- a/src/lib/server/cli/cli.ts +++ b/src/lib/server/cli/cli.ts @@ -35,7 +35,7 @@ export class Cli { } new(opts: CliPartial, runOpts?: CliRunOptions): void { - return this.runCommand('new', [], { ...CLI_NEW_DEFAULTS, ...opts }, CLI_NEW_DEFAULTS, runOpts); + return this.runCommand('new', [], { ...opts }, CLI_NEW_DEFAULTS, runOpts); } install( diff --git a/src/lib/utils/ui.ts b/src/lib/utils/ui.ts new file mode 100644 index 0000000..ebfd273 --- /dev/null +++ b/src/lib/utils/ui.ts @@ -0,0 +1,10 @@ +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export type { WithElementRef, WithoutChild, WithChildren, WithoutChildrenOrChild } from 'bits-ui'; + +export type WithoutChildren = Omit; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/src/routes/load-project/+page.svelte b/src/routes/load-project/+page.svelte index a0f0a0b..d123ac5 100644 --- a/src/routes/load-project/+page.svelte +++ b/src/routes/load-project/+page.svelte @@ -136,7 +136,7 @@ - + ({ '--un-enter-opacity': `${Number(n) / 100}` })], + [/^fade-out-(\d+)$/, ([, n]) => ({ '--un-exit-opacity': `${Number(n) / 100}` })], + [/^zoom-in-(\d+)$/, ([, n]) => ({ '--un-enter-scale': `${Number(n) / 100}` })], + [/^zoom-out-(\d+)$/, ([, n]) => ({ '--un-exit-scale': `${Number(n) / 100}` })], + [ + /^slide-in-from-top-(\d+)$/, + ([, n]) => ({ '--un-enter-translate-y': `-${Number(n) * 0.25}rem` }), + ], + [ + /^slide-in-from-bottom-(\d+)$/, + ([, n]) => ({ '--un-enter-translate-y': `${Number(n) * 0.25}rem` }), + ], + [ + /^slide-in-from-left-(\d+)$/, + ([, n]) => ({ '--un-enter-translate-x': `-${Number(n) * 0.25}rem` }), + ], + [ + /^slide-in-from-right-(\d+)$/, + ([, n]) => ({ '--un-enter-translate-x': `${Number(n) * 0.25}rem` }), + ], + [ + /^slide-out-to-top-(\d+)$/, + ([, n]) => ({ '--un-exit-translate-y': `-${Number(n) * 0.25}rem` }), + ], + [ + /^slide-out-to-bottom-(\d+)$/, + ([, n]) => ({ '--un-exit-translate-y': `${Number(n) * 0.25}rem` }), + ], + [ + /^slide-out-to-left-(\d+)$/, + ([, n]) => ({ '--un-exit-translate-x': `-${Number(n) * 0.25}rem` }), + ], + [ + /^slide-out-to-right-(\d+)$/, + ([, n]) => ({ '--un-exit-translate-x': `${Number(n) * 0.25}rem` }), + ], + ], shortcuts: [ [ - 'btn', - 'px-4 py-1 rounded inline-block bg-teal-700 text-white cursor-pointer !outline-none hover:bg-teal-800 disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50', + 'modal-overlay', + 'fixed inset-0 bg-black/70 backdrop-blur-sm flex items-center justify-center z-50 p-4', + ], + ['modal-card', 'bg-card rounded-2xl w-full max-w-md overflow-hidden'], + ['modal-header', 'px-6 pt-7 pb-5 flex items-center gap-3.5'], + ['modal-body', 'px-6 py-5 flex flex-col gap-5'], + ['modal-footer', 'px-6 pb-6 flex items-center justify-end gap-2'], + [ + 'modal-icon-badge', + 'shrink-0 size-10 rounded-xl bg-primary/10 flex items-center justify-center', + ], + ['modal-divider', 'h-px bg-white/[0.04]'], + [ + 'toggle-row', + 'flex items-center justify-between px-3 py-2.5 rounded-lg hover:bg-muted/40 transition-colors text-left', ], + ['toggle-row-title', 'text-sm text-foreground font-medium leading-tight'], + ['toggle-row-desc', 'text-xs text-muted-foreground mt-0.5'], + ['btn-ghost', 'px-4 py-2 text-sm rounded-lg transition-all duration-150 cursor-pointer'], [ - 'icon-btn', - 'inline-block cursor-pointer select-none opacity-75 transition duration-200 ease-in-out hover:opacity-100 hover:text-teal-600', + 'btn-primary', + 'flex items-center hover:bg-primary/80 gap-2 px-5 py-2 text-sm font-medium rounded-lg transition-colors duration-150 disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer', ], ], presets: [ From 03ecf8fec1d386451dac7fc5433e445d39934f23 Mon Sep 17 00:00:00 2001 From: Exelo Date: Thu, 21 May 2026 13:59:50 +0900 Subject: [PATCH 26/58] chore: add demo test for ci to pass --- src/demo.spec.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/demo.spec.ts diff --git a/src/demo.spec.ts b/src/demo.spec.ts new file mode 100644 index 0000000..e2efa47 --- /dev/null +++ b/src/demo.spec.ts @@ -0,0 +1,5 @@ +import { expect, it } from 'vitest'; + +it('expect 1 + 2 = 3', async () => { + expect(1 + 2).equal(3); +}); From ae908c4ba511985bbebab71256db2389c283c128 Mon Sep 17 00:00:00 2001 From: Exelo Date: Thu, 21 May 2026 17:42:47 +0900 Subject: [PATCH 27/58] chore: refactor index page --- .env.example | 3 + package.json | 1 + pnpm-lock.yaml | 18 ++ src/lib/client/config/config.ts | 2 +- .../client/project/project-loader/cache.ts | 0 .../ProjectLoader/CreateProject.svelte | 263 ++++++++---------- .../Utils/LocalStorage/ProjectCache.ts | 1 + src/lib/components/ui/card/card-action.svelte | 23 ++ .../components/ui/card/card-content.svelte | 20 ++ .../ui/card/card-description.svelte | 20 ++ src/lib/components/ui/card/card-footer.svelte | 23 ++ src/lib/components/ui/card/card-header.svelte | 23 ++ src/lib/components/ui/card/card-title.svelte | 20 ++ src/lib/components/ui/card/card.svelte | 25 ++ src/lib/components/ui/card/index.ts | 25 ++ .../components/ui/dialog/dialog-close.svelte | 11 + .../ui/dialog/dialog-content.svelte | 48 ++++ .../ui/dialog/dialog-description.svelte | 20 ++ .../components/ui/dialog/dialog-footer.svelte | 35 +++ .../components/ui/dialog/dialog-header.svelte | 20 ++ .../ui/dialog/dialog-overlay.svelte | 20 ++ .../components/ui/dialog/dialog-portal.svelte | 7 + .../components/ui/dialog/dialog-title.svelte | 17 ++ .../ui/dialog/dialog-trigger.svelte | 11 + src/lib/components/ui/dialog/dialog.svelte | 7 + src/lib/components/ui/dialog/index.ts | 34 +++ .../ui/loading-button/loading-button.svelte | 16 +- src/lib/components/ui/skeleton/index.ts | 7 + .../components/ui/skeleton/skeleton.svelte | 17 ++ src/lib/components/ui/spinner/index.ts | 1 + src/lib/components/ui/spinner/spinner.svelte | 26 ++ src/lib/server/session/session-handle.ts | 2 +- src/lib/server/session/session.const.ts | 2 +- src/routes/+layout.svelte | 16 +- src/routes/+page.svelte | 131 +++++---- .../cache-project-list-skeleton.svelte | 15 + src/routes/components/cache-project.svelte | 27 ++ .../components/create-project-dialog.svelte | 20 ++ src/routes/components/header.svelte | 10 + src/routes/components/index.ts | 15 + .../components/offline-project-buttons.svelte | 30 ++ .../components/online-project-buttons.svelte | 30 ++ src/routes/dashboard/+page.svelte | 58 ++++ src/routes/load-project/+page.svelte | 6 +- uno.config.ts | 1 + 45 files changed, 913 insertions(+), 214 deletions(-) create mode 100644 src/lib/client/project/project-loader/cache.ts create mode 100644 src/lib/components/ui/card/card-action.svelte create mode 100644 src/lib/components/ui/card/card-content.svelte create mode 100644 src/lib/components/ui/card/card-description.svelte create mode 100644 src/lib/components/ui/card/card-footer.svelte create mode 100644 src/lib/components/ui/card/card-header.svelte create mode 100644 src/lib/components/ui/card/card-title.svelte create mode 100644 src/lib/components/ui/card/card.svelte create mode 100644 src/lib/components/ui/card/index.ts create mode 100644 src/lib/components/ui/dialog/dialog-close.svelte create mode 100644 src/lib/components/ui/dialog/dialog-content.svelte create mode 100644 src/lib/components/ui/dialog/dialog-description.svelte create mode 100644 src/lib/components/ui/dialog/dialog-footer.svelte create mode 100644 src/lib/components/ui/dialog/dialog-header.svelte create mode 100644 src/lib/components/ui/dialog/dialog-overlay.svelte create mode 100644 src/lib/components/ui/dialog/dialog-portal.svelte create mode 100644 src/lib/components/ui/dialog/dialog-title.svelte create mode 100644 src/lib/components/ui/dialog/dialog-trigger.svelte create mode 100644 src/lib/components/ui/dialog/dialog.svelte create mode 100644 src/lib/components/ui/dialog/index.ts create mode 100644 src/lib/components/ui/skeleton/index.ts create mode 100644 src/lib/components/ui/skeleton/skeleton.svelte create mode 100644 src/lib/components/ui/spinner/index.ts create mode 100644 src/lib/components/ui/spinner/spinner.svelte create mode 100644 src/routes/components/cache-project-list-skeleton.svelte create mode 100644 src/routes/components/cache-project.svelte create mode 100644 src/routes/components/create-project-dialog.svelte create mode 100644 src/routes/components/header.svelte create mode 100644 src/routes/components/index.ts create mode 100644 src/routes/components/offline-project-buttons.svelte create mode 100644 src/routes/components/online-project-buttons.svelte create mode 100644 src/routes/dashboard/+page.svelte diff --git a/.env.example b/.env.example index 0cba235..b5ac4cd 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,9 @@ NODE_ENV=development # OFFLINE or ONLINE, change editor mode beetween local execution and online execution PUBLIC_MODE=OFFLINE +# Project Manager +PUBLIC_PM_URL=https://projects.nanoforge.eu + # Api params (required if PUBLIC_MODE=ONLINE) API_URL=http://localhost:3000 API_KEY=test diff --git a/package.json b/package.json index 12edb3d..ff4c0f6 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "@playwright/test": "catalog:test", "@sveltejs/kit": "catalog:core", "@sveltejs/vite-plugin-svelte": "catalog:core", + "@tanstack/svelte-query": "^6.1.30", "@trivago/prettier-plugin-sort-imports": "catalog:lint", "@tsconfig/svelte": "catalog:build", "@types/bun": "catalog:core", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c4ebc27..81343f9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -219,6 +219,9 @@ importers: '@sveltejs/vite-plugin-svelte': specifier: catalog:core version: 7.1.2(svelte@5.55.8(@typescript-eslint/types@8.59.4))(vite@8.0.13(@types/node@25.9.0)(jiti@2.7.0)(yaml@2.9.0)) + '@tanstack/svelte-query': + specifier: ^6.1.30 + version: 6.1.30(svelte@5.55.8(@typescript-eslint/types@8.59.4)) '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint version: 6.0.2(prettier-plugin-svelte@3.5.2(prettier@3.8.3)(svelte@5.55.8(@typescript-eslint/types@8.59.4)))(prettier@3.8.3)(svelte@5.55.8(@typescript-eslint/types@8.59.4)) @@ -1384,6 +1387,14 @@ packages: '@tailwindcss/postcss@4.3.0': resolution: {integrity: sha512-Jm05Tjx+9yCLGv5qw1c+84Psds8MnyrEQYCB+FFk2lgGiUjlRqdxke4mVTuYrj2xnVZqKim2Apr5ySuQRYAw/w==} + '@tanstack/query-core@5.100.11': + resolution: {integrity: sha512-lmE0994apShXPj8CUxgx4ch5yUJhE9k/+tVwihBvPOyerACWdBocfFg24t8+0RhtlTd7tEgchDkhlCxNssvDxw==} + + '@tanstack/svelte-query@6.1.30': + resolution: {integrity: sha512-4yqDsEGF8ESvQJj+bcpe2/rlOejo4gboQe1an2ned7Q3OcivXTe4nrak+EYcvuVeY7lfxRC1ouBGFkNAimM7LA==} + peerDependencies: + svelte: ^5.25.0 + '@testing-library/svelte-core@1.0.0': resolution: {integrity: sha512-VkUePoLV6oOYwSUvX6ShA8KLnJqZiYMIbP2JW2t0GLWLkJxKGvuH5qrrZBV/X7cXFnLGuFQEC7RheYiZOW68KQ==} engines: {node: '>=16'} @@ -4373,6 +4384,13 @@ snapshots: postcss: 8.5.14 tailwindcss: 4.3.0 + '@tanstack/query-core@5.100.11': {} + + '@tanstack/svelte-query@6.1.30(svelte@5.55.8(@typescript-eslint/types@8.59.4))': + dependencies: + '@tanstack/query-core': 5.100.11 + svelte: 5.55.8(@typescript-eslint/types@8.59.4) + '@testing-library/svelte-core@1.0.0(svelte@5.55.8(@typescript-eslint/types@8.59.4))': dependencies: svelte: 5.55.8(@typescript-eslint/types@8.59.4) diff --git a/src/lib/client/config/config.ts b/src/lib/client/config/config.ts index 098f8fc..c2bf540 100644 --- a/src/lib/client/config/config.ts +++ b/src/lib/client/config/config.ts @@ -4,6 +4,6 @@ import type { Config } from './config.type'; export const getConfig = (): Config => { return { - mode: env.PUBLIC_MODE === 'offline' ? 'offline' : 'online', + mode: env.PUBLIC_MODE === 'online' ? 'online' : 'offline', }; }; diff --git a/src/lib/client/project/project-loader/cache.ts b/src/lib/client/project/project-loader/cache.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/components/ProjectLoader/CreateProject.svelte b/src/lib/components/ProjectLoader/CreateProject.svelte index bf6593a..f9703e3 100644 --- a/src/lib/components/ProjectLoader/CreateProject.svelte +++ b/src/lib/components/ProjectLoader/CreateProject.svelte @@ -11,9 +11,9 @@ import { Button } from '$lib/components/ui/button'; interface Props { - show: boolean; + onClose?: () => void; } - let { show = $bindable() }: Props = $props(); + let { onClose }: Props = $props(); let creationPromises: Promise[] = $state([]); let showAdvancedSettings: boolean = $state(false); @@ -48,10 +48,6 @@ const { form, submitting } = formCtx; - function handleClose(event: KeyboardEvent) { - if (event.key === 'Escape') show = false; - } - async function newProject(values: ProjectForm) { const projectPromise = ProjectLoader.create(values); creationPromises.push(projectPromise); @@ -60,153 +56,140 @@ } -