diff --git a/packages/server/package.json b/packages/server/package.json index c3f2e83e..43870381 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -98,6 +98,16 @@ "types": "./dist/nuxt.d.cts", "default": "./dist/nuxt.cjs" } + }, + "./sveltekit": { + "import": { + "types": "./dist/sveltekit.d.ts", + "default": "./dist/sveltekit.js" + }, + "require": { + "types": "./dist/sveltekit.d.cts", + "default": "./dist/sveltekit.cjs" + } } }, "dependencies": { @@ -111,6 +121,7 @@ "zod-validation-error": "catalog:" }, "devDependencies": { + "@sveltejs/kit": "^2.48.3", "@types/body-parser": "^1.19.6", "@types/express": "^5.0.0", "@types/supertest": "^6.0.3", @@ -131,6 +142,7 @@ "zod": "~3.25.0" }, "peerDependencies": { + "@sveltejs/kit": "^2.0.0", "elysia": "^1.3.0", "express": "^5.0.0", "fastify": "^5.0.0", @@ -161,6 +173,9 @@ }, "nuxt": { "optional": true + }, + "@sveltejs/kit": { + "optional": true } } } diff --git a/packages/server/src/adapter/elysia/index.ts b/packages/server/src/adapter/elysia/index.ts index bc0d7e16..496e46b2 100644 --- a/packages/server/src/adapter/elysia/index.ts +++ b/packages/server/src/adapter/elysia/index.ts @@ -1 +1 @@ -export * from './handler'; \ No newline at end of file +export { createElysiaHandler, type ElysiaOptions } from './handler'; diff --git a/packages/server/src/adapter/express/index.ts b/packages/server/src/adapter/express/index.ts index 35fc53b7..40c97fee 100644 --- a/packages/server/src/adapter/express/index.ts +++ b/packages/server/src/adapter/express/index.ts @@ -1 +1 @@ -export { ZenStackMiddleware, type MiddlewareOptions } from './middleware'; +export { ZenStackMiddleware, type ExpressMiddlewareOptions } from './middleware'; diff --git a/packages/server/src/adapter/express/middleware.ts b/packages/server/src/adapter/express/middleware.ts index 0d35806a..415380b8 100644 --- a/packages/server/src/adapter/express/middleware.ts +++ b/packages/server/src/adapter/express/middleware.ts @@ -6,7 +6,7 @@ import { logInternalError, type CommonAdapterOptions } from '../common'; /** * Express middleware options */ -export interface MiddlewareOptions extends CommonAdapterOptions { +export interface ExpressMiddlewareOptions extends CommonAdapterOptions { /** * Callback for getting a ZenStackClient for the given request */ @@ -27,7 +27,7 @@ export interface MiddlewareOptions extends CommonAdapt /** * Creates an Express middleware for handling CRUD requests. */ -const factory = (options: MiddlewareOptions): Handler => { +const factory = (options: ExpressMiddlewareOptions): Handler => { const requestHandler = options.apiHandler; return async (request, response, next) => { diff --git a/packages/server/src/adapter/fastify/index.ts b/packages/server/src/adapter/fastify/index.ts index d433e4d9..94d6329b 100644 --- a/packages/server/src/adapter/fastify/index.ts +++ b/packages/server/src/adapter/fastify/index.ts @@ -1,2 +1,2 @@ -export { ZenStackFastifyPlugin, type PluginOptions } from './plugin'; +export { ZenStackFastifyPlugin, type FastifyPluginOptions } from './plugin'; diff --git a/packages/server/src/adapter/fastify/plugin.ts b/packages/server/src/adapter/fastify/plugin.ts index e64aa27a..a1ab0013 100644 --- a/packages/server/src/adapter/fastify/plugin.ts +++ b/packages/server/src/adapter/fastify/plugin.ts @@ -7,7 +7,7 @@ import { logInternalError, type CommonAdapterOptions } from '../common'; /** * Fastify plugin options */ -export interface PluginOptions extends CommonAdapterOptions { +export interface FastifyPluginOptions extends CommonAdapterOptions { /** * Url prefix, e.g.: /api @@ -23,7 +23,7 @@ export interface PluginOptions extends CommonAdapterOp /** * Fastify plugin for handling CRUD requests. */ -const pluginHandler: FastifyPluginCallback> = (fastify, options, done) => { +const pluginHandler: FastifyPluginCallback> = (fastify, options, done) => { const prefix = options.prefix ?? ''; fastify.all(`${prefix}/*`, async (request, reply) => { diff --git a/packages/server/src/adapter/hono/index.ts b/packages/server/src/adapter/hono/index.ts index 68ae53f6..b2d7f353 100644 --- a/packages/server/src/adapter/hono/index.ts +++ b/packages/server/src/adapter/hono/index.ts @@ -1 +1 @@ -export * from './handler'; +export { createHonoHandler, type HonoOptions } from './handler'; diff --git a/packages/server/src/adapter/nuxt/handler.ts b/packages/server/src/adapter/nuxt/handler.ts index 1dfa7cd4..01f26bdc 100644 --- a/packages/server/src/adapter/nuxt/handler.ts +++ b/packages/server/src/adapter/nuxt/handler.ts @@ -14,14 +14,14 @@ import { logInternalError, type CommonAdapterOptions } from '../common'; /** * Nuxt request handler options */ -export interface HandlerOptions extends CommonAdapterOptions { +export interface NuxtHandlerOptions extends CommonAdapterOptions { /** * Callback for getting a ZenStackClient for the given request */ getClient: (event: H3Event) => ClientContract | Promise>; } -export function createEventHandler(options: HandlerOptions) { +export function createEventHandler(options: NuxtHandlerOptions) { return defineEventHandler(async (event) => { const client = await options.getClient(event); if (!client) { diff --git a/packages/server/src/adapter/nuxt/index.ts b/packages/server/src/adapter/nuxt/index.ts index 68ae53f6..545a5173 100644 --- a/packages/server/src/adapter/nuxt/index.ts +++ b/packages/server/src/adapter/nuxt/index.ts @@ -1 +1 @@ -export * from './handler'; +export { createEventHandler, type NuxtHandlerOptions } from './handler'; diff --git a/packages/server/src/adapter/sveltekit/handler.ts b/packages/server/src/adapter/sveltekit/handler.ts new file mode 100644 index 00000000..355f7ee5 --- /dev/null +++ b/packages/server/src/adapter/sveltekit/handler.ts @@ -0,0 +1,78 @@ +import type { Handle, RequestEvent } from '@sveltejs/kit'; +import type { ClientContract } from '@zenstackhq/orm'; +import type { SchemaDef } from '@zenstackhq/orm/schema'; +import { logInternalError, type CommonAdapterOptions } from '../common'; + +/** + * SvelteKit request handler options + */ +export interface SvelteKitHandlerOptions extends CommonAdapterOptions { + /** + * Url prefix, e.g.: /api + */ + prefix: string; + + /** + * Callback for getting a ZenStackClient for the given request + */ + getClient: (event: RequestEvent) => ClientContract | Promise>; +} + +/** + * SvelteKit server hooks handler for handling CRUD requests. + */ +export default function createHandler(options: SvelteKitHandlerOptions): Handle { + return async ({ event, resolve }) => { + if (event.url.pathname.startsWith(options.prefix)) { + const client = await options.getClient(event); + if (!client) { + return new Response(JSON.stringify({ message: 'unable to get ZenStackClient from request context' }), { + status: 400, + headers: { + 'content-type': 'application/json', + }, + }); + } + + const query = Object.fromEntries(event.url.searchParams); + let requestBody: unknown; + if (event.request.body) { + const text = await event.request.text(); + if (text) { + requestBody = JSON.parse(text); + } + } + + const path = event.url.pathname.substring(options.prefix.length); + + try { + const r = await options.apiHandler.handleRequest({ + method: event.request.method, + path, + query, + requestBody, + client, + }); + + return new Response(JSON.stringify(r.body), { + status: r.status, + headers: { + 'content-type': 'application/json', + }, + }); + } catch (err) { + logInternalError(options.apiHandler.log, err); + return new Response(JSON.stringify({ message: 'An internal server error occurred' }), { + status: 500, + headers: { + 'content-type': 'application/json', + }, + }); + } + } + + return resolve(event); + }; +} + +export { createHandler as SvelteKitHandler }; diff --git a/packages/server/src/adapter/sveltekit/index.ts b/packages/server/src/adapter/sveltekit/index.ts new file mode 100644 index 00000000..d50661d7 --- /dev/null +++ b/packages/server/src/adapter/sveltekit/index.ts @@ -0,0 +1 @@ +export { SvelteKitHandler, type SvelteKitHandlerOptions } from './handler'; diff --git a/packages/server/test/adapter/sveltekit.test.ts b/packages/server/test/adapter/sveltekit.test.ts new file mode 100644 index 00000000..01ee8b09 --- /dev/null +++ b/packages/server/test/adapter/sveltekit.test.ts @@ -0,0 +1,154 @@ +import { createTestClient } from '@zenstackhq/testtools'; +import superjson from 'superjson'; +import { describe, expect, it } from 'vitest'; +import { SvelteKitHandler } from '../../src/adapter/sveltekit'; +import { RestApiHandler, RPCApiHandler } from '../../src/api'; +import { makeUrl, schema } from '../utils'; + +describe('SvelteKit adapter tests - rpc handler', () => { + it('properly handles requests', async () => { + const client = await createTestClient(schema); + + const handler = SvelteKitHandler({ prefix: '/api', getClient: () => client, apiHandler: new RPCApiHandler({ schema: client.schema }) }); + + let r = await handler(makeRequest('GET', makeUrl('/api/post/findMany', { where: { id: { equals: '1' } } }))); + expect(r.status).toBe(200); + expect((await unmarshal(r)).data).toHaveLength(0); + + r = await handler( + makeRequest('POST', '/api/user/create', { + include: { posts: true }, + data: { + id: 'user1', + email: 'user1@abc.com', + posts: { + create: [ + { title: 'post1', published: true, viewCount: 1 }, + { title: 'post2', published: false, viewCount: 2 }, + ], + }, + }, + }) + ); + expect(r.status).toBe(201); + expect((await unmarshal(r)).data).toMatchObject({ + email: 'user1@abc.com', + posts: expect.arrayContaining([ + expect.objectContaining({ title: 'post1' }), + expect.objectContaining({ title: 'post2' }), + ]), + }); + + r = await handler(makeRequest('GET', makeUrl('/api/post/findMany'))); + expect(r.status).toBe(200); + expect((await unmarshal(r)).data).toHaveLength(2); + + r = await handler(makeRequest('GET', makeUrl('/api/post/findMany', { where: { viewCount: { gt: 1 } } }))); + expect(r.status).toBe(200); + expect((await unmarshal(r)).data).toHaveLength(1); + + r = await handler( + makeRequest('PUT', '/api/user/update', { where: { id: 'user1' }, data: { email: 'user1@def.com' } }) + ); + expect(r.status).toBe(200); + expect((await unmarshal(r)).data.email).toBe('user1@def.com'); + + r = await handler(makeRequest('GET', makeUrl('/api/post/count', { where: { viewCount: { gt: 1 } } }))); + expect(r.status).toBe(200); + expect((await unmarshal(r)).data).toBe(1); + + r = await handler(makeRequest('GET', makeUrl('/api/post/aggregate', { _sum: { viewCount: true } }))); + expect(r.status).toBe(200); + expect((await unmarshal(r)).data._sum.viewCount).toBe(3); + + r = await handler( + makeRequest('GET', makeUrl('/api/post/groupBy', { by: ['published'], _sum: { viewCount: true } })) + ); + expect(r.status).toBe(200); + expect((await unmarshal(r)).data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ published: true, _sum: { viewCount: 1 } }), + expect.objectContaining({ published: false, _sum: { viewCount: 2 } }), + ]) + ); + + r = await handler(makeRequest('DELETE', makeUrl('/api/user/deleteMany', { where: { id: 'user1' } }))); + expect(r.status).toBe(200); + expect((await unmarshal(r)).data.count).toBe(1); + }); +}); + +describe('SvelteKit adapter tests - rest handler', () => { + it('properly handles requests', async () => { + const client = await createTestClient(schema); + + const handler = SvelteKitHandler({ + prefix: '/api', + getClient: () => client, + apiHandler: new RestApiHandler({ schema: client.schema, endpoint: 'http://localhost/api' }), + }); + + let r = await handler(makeRequest('GET', makeUrl('/api/post/1'))); + expect(r.status).toBe(404); + + r = await handler( + makeRequest('POST', '/api/user', { + data: { + type: 'user', + attributes: { id: 'user1', email: 'user1@abc.com' }, + }, + }) + ); + expect(r.status).toBe(201); + expect(await unmarshal(r)).toMatchObject({ + data: { + id: 'user1', + attributes: { + email: 'user1@abc.com', + }, + }, + }); + + r = await handler(makeRequest('GET', makeUrl('/api/user?filter[id]=user1'))); + expect(r.status).toBe(200); + expect((await unmarshal(r)).data).toHaveLength(1); + + r = await handler(makeRequest('GET', makeUrl('/api/user?filter[id]=user2'))); + expect(r.status).toBe(200); + expect((await unmarshal(r)).data).toHaveLength(0); + + r = await handler(makeRequest('GET', makeUrl('/api/user?filter[id]=user1&filter[email]=xyz'))); + expect(r.status).toBe(200); + expect((await unmarshal(r)).data).toHaveLength(0); + + r = await handler( + makeRequest('PUT', makeUrl('/api/user/user1'), { + data: { type: 'user', attributes: { email: 'user1@def.com' } }, + }) + ); + expect(r.status).toBe(200); + expect((await unmarshal(r)).data.attributes.email).toBe('user1@def.com'); + + r = await handler(makeRequest('DELETE', makeUrl('/api/user/user1'))); + expect(r.status).toBe(200); + expect(await client.user.findMany()).toHaveLength(0); + }); +}); + +function makeRequest(method: string, path: string, body?: any) { + const payload = body ? JSON.stringify(body) : undefined; + return { + event: { + request: new Request(`http://localhost${path}`, { method, body: payload }), + url: new URL(`http://localhost${path}`), + } as any, + resolve: async () => { + throw new Error('should not be called'); + }, + }; +} + +async function unmarshal(r: Response, useSuperJson = false) { + const text = await r.text(); + return (useSuperJson ? superjson.parse(text) : JSON.parse(text)) as any; +} diff --git a/packages/server/tsup.config.ts b/packages/server/tsup.config.ts index 79bcba0f..fcce984c 100644 --- a/packages/server/tsup.config.ts +++ b/packages/server/tsup.config.ts @@ -9,6 +9,7 @@ export default defineConfig({ elysia: 'src/adapter/elysia/index.ts', nuxt: 'src/adapter/nuxt/index.ts', hono: 'src/adapter/hono/index.ts', + sveltekit: 'src/adapter/sveltekit/index.ts', }, outDir: 'dist', splitting: false, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 177eb1ca..2e52d475 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -439,6 +439,9 @@ importers: specifier: 'catalog:' version: 4.0.1(zod@3.25.76) devDependencies: + '@sveltejs/kit': + specifier: ^2.48.3 + version: 2.48.3(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)))(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) '@types/body-parser': specifier: ^1.19.6 version: 1.19.6 @@ -2251,6 +2254,39 @@ packages: '@standard-schema/spec@1.0.0': resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} + '@sveltejs/acorn-typescript@1.0.6': + resolution: {integrity: sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ==} + peerDependencies: + acorn: ^8.9.0 + + '@sveltejs/kit@2.48.3': + resolution: {integrity: sha512-jf8mx3yctRXE9hvixgcqqK94YI2hDnbxI/12Upkz99XFMvxnJKCMzvz0j7lmbXSyBSNEycWO5xHvi7b73y9qkQ==} + engines: {node: '>=18.13'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.0.0 + '@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + + '@sveltejs/vite-plugin-svelte-inspector@5.0.1': + resolution: {integrity: sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA==} + engines: {node: ^20.19 || ^22.12 || >=24} + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^6.0.0-next.0 + svelte: ^5.0.0 + vite: ^6.3.0 || ^7.0.0 + + '@sveltejs/vite-plugin-svelte@6.2.1': + resolution: {integrity: sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==} + engines: {node: ^20.19 || ^22.12 || >=24} + peerDependencies: + svelte: ^5.0.0 + vite: ^6.3.0 || ^7.0.0 + '@swc/core-darwin-arm64@1.12.5': resolution: {integrity: sha512-3WF+naP/qkt5flrTfJr+p07b522JcixKvIivM7FgvllA6LjJxf+pheoILrTS8IwrNAK/XtHfKWYcGY+3eaA4mA==} engines: {node: '>=10'} @@ -2359,6 +2395,9 @@ packages: '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + '@types/cookie@0.6.0': + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + '@types/cookiejar@2.1.5': resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} @@ -2732,6 +2771,10 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} @@ -2770,6 +2813,10 @@ packages: avvio@9.1.0: resolution: {integrity: sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==} + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + b4a@1.7.3: resolution: {integrity: sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==} peerDependencies: @@ -2968,6 +3015,10 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + cluster-key-slot@1.1.2: resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} engines: {node: '>=0.10.0'} @@ -3056,6 +3107,10 @@ packages: resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} engines: {node: '>=6.6.0'} + cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + cookie@0.7.1: resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} @@ -3423,6 +3478,9 @@ packages: jiti: optional: true + esm-env@1.2.2: + resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} + espree@10.4.0: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3431,6 +3489,9 @@ packages: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} + esrap@2.1.1: + resolution: {integrity: sha512-ebTT9B6lOtZGMgJ3o5r12wBacHctG7oEWazIda8UlPfA3HD/Wrv8FdXoVo73vzdpwCxNyXjPauyN2bbJzMkB9A==} + esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} @@ -3905,6 +3966,9 @@ packages: is-reference@1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + is-reference@3.0.3: + resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + is-ssh@1.4.1: resolution: {integrity: sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==} @@ -4095,6 +4159,9 @@ packages: resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} engines: {node: '>=14'} + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -4283,6 +4350,10 @@ packages: mocked-exports@0.1.1: resolution: {integrity: sha512-aF7yRQr/Q0O2/4pIXm6PZ5G+jAd7QS4Yu8m+WEeEHGnbo+7mE36CbLSDQiXYV8bVL3NfmdeqPJct0tUlnjVSnA==} + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + mrmime@2.0.1: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} @@ -5134,6 +5205,10 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -5426,6 +5501,10 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + svelte@5.43.0: + resolution: {integrity: sha512-1sRxVbgJAB+UGzwkc3GUoiBSzEOf0jqzccMaVoI2+pI+kASUe9qubslxace8+Mzhqw19k4syTA5niCIJwfXpOA==} + engines: {node: '>=18'} + svgo@4.0.0: resolution: {integrity: sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==} engines: {node: '>=16'} @@ -5965,6 +6044,14 @@ packages: yaml: optional: true + vitefu@1.1.1: + resolution: {integrity: sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0 + peerDependenciesMeta: + vite: + optional: true + vitest@3.2.4: resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -6150,6 +6237,9 @@ packages: youch@4.1.0-beta.11: resolution: {integrity: sha512-sQi6PERyO/mT8w564ojOVeAlYTtVQmC2GaktQAf+IdI75/GKIggosBuvyVXvEV+FATAT6RbLdIjFoiIId4ozoQ==} + zimmerframe@1.1.4: + resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} + zip-stream@6.0.1: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} engines: {node: '>= 14'} @@ -6726,7 +6816,7 @@ snapshots: '@jridgewell/gen-mapping@0.3.13': dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/gen-mapping@0.3.8': @@ -6756,12 +6846,12 @@ snapshots: '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 '@kwsites/file-exists@1.1.1': dependencies: @@ -7616,6 +7706,50 @@ snapshots: '@standard-schema/spec@1.0.0': {} + '@sveltejs/acorn-typescript@1.0.6(acorn@8.15.0)': + dependencies: + acorn: 8.15.0 + + '@sveltejs/kit@2.48.3(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)))(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))': + dependencies: + '@standard-schema/spec': 1.0.0 + '@sveltejs/acorn-typescript': 1.0.6(acorn@8.15.0) + '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + '@types/cookie': 0.6.0 + acorn: 8.15.0 + cookie: 0.6.0 + devalue: 5.4.2 + esm-env: 1.2.2 + kleur: 4.1.5 + magic-string: 0.30.21 + mrmime: 2.0.1 + sade: 1.8.1 + set-cookie-parser: 2.7.2 + sirv: 3.0.2 + svelte: 5.43.0 + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + + '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)))(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))': + dependencies: + '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + debug: 4.4.1 + svelte: 5.43.0 + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + transitivePeerDependencies: + - supports-color + + '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1))': + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)))(svelte@5.43.0)(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + debug: 4.4.1 + deepmerge: 4.3.1 + magic-string: 0.30.21 + svelte: 5.43.0 + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vitefu: 1.1.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)) + transitivePeerDependencies: + - supports-color + '@swc/core-darwin-arm64@1.12.5': optional: true @@ -7714,6 +7848,8 @@ snapshots: dependencies: '@types/node': 20.17.24 + '@types/cookie@0.6.0': {} + '@types/cookiejar@2.1.5': {} '@types/deep-eql@4.0.2': {} @@ -8220,6 +8356,8 @@ snapshots: argparse@2.0.1: {} + aria-query@5.3.2: {} + asap@2.0.6: {} assertion-error@2.0.1: {} @@ -8257,6 +8395,8 @@ snapshots: '@fastify/error': 4.2.0 fastq: 1.19.1 + axobject-query@4.1.0: {} + b4a@1.7.3: {} balanced-match@1.0.2: {} @@ -8503,6 +8643,8 @@ snapshots: clone@1.0.4: {} + clsx@2.1.1: {} + cluster-key-slot@1.1.2: {} color-convert@2.0.1: @@ -8565,6 +8707,8 @@ snapshots: cookie-signature@1.2.2: {} + cookie@0.6.0: {} + cookie@0.7.1: {} cookie@1.0.2: {} @@ -8952,6 +9096,8 @@ snapshots: transitivePeerDependencies: - supports-color + esm-env@1.2.2: {} + espree@10.4.0: dependencies: acorn: 8.15.0 @@ -8962,6 +9108,10 @@ snapshots: dependencies: estraverse: 5.3.0 + esrap@2.1.1: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + esrecurse@4.3.0: dependencies: estraverse: 5.3.0 @@ -9496,6 +9646,10 @@ snapshots: dependencies: '@types/estree': 1.0.8 + is-reference@3.0.3: + dependencies: + '@types/estree': 1.0.8 + is-ssh@1.4.1: dependencies: protocols: 2.0.2 @@ -9682,6 +9836,8 @@ snapshots: pkg-types: 2.3.0 quansync: 0.2.11 + locate-character@3.0.0: {} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -9848,6 +10004,8 @@ snapshots: mocked-exports@0.1.1: {} + mri@1.2.0: {} + mrmime@2.0.1: {} ms@2.1.3: {} @@ -10927,6 +11085,10 @@ snapshots: dependencies: queue-microtask: 1.2.3 + sade@1.8.1: + dependencies: + mri: 1.2.0 + safe-buffer@5.1.2: {} safe-buffer@5.2.1: {} @@ -11253,6 +11415,23 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + svelte@5.43.0: + dependencies: + '@jridgewell/remapping': 2.3.5 + '@jridgewell/sourcemap-codec': 1.5.5 + '@sveltejs/acorn-typescript': 1.0.6(acorn@8.15.0) + '@types/estree': 1.0.8 + acorn: 8.15.0 + aria-query: 5.3.2 + axobject-query: 4.1.0 + clsx: 2.1.1 + esm-env: 1.2.2 + esrap: 2.1.1 + is-reference: 3.0.3 + locate-character: 3.0.0 + magic-string: 0.30.21 + zimmerframe: 1.1.4 + svgo@4.0.0: dependencies: commander: 11.1.0 @@ -11778,6 +11957,10 @@ snapshots: tsx: 4.20.3 yaml: 2.8.1 + vitefu@1.1.1(vite@7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1)): + optionalDependencies: + vite: 7.1.12(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) + vitest@3.2.4(@types/node@20.17.24)(jiti@2.6.1)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0): dependencies: '@types/chai': 5.2.2 @@ -11962,6 +12145,8 @@ snapshots: cookie: 1.0.2 youch-core: 0.3.3 + zimmerframe@1.1.4: {} + zip-stream@6.0.1: dependencies: archiver-utils: 5.0.2