From c3c925e35415963da626354df56683b1c59892ce Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Thu, 28 Aug 2025 04:27:13 +0000 Subject: [PATCH 01/23] Initialized sveltekit example app --- cspell.json | 4 + examples/sveltekit/.gitignore | 23 + examples/sveltekit/.npmrc | 1 + examples/sveltekit/README.md | 38 + examples/sveltekit/eslint.config.js | 39 + examples/sveltekit/package.json | 42 + examples/sveltekit/src/app.css | 1 + examples/sveltekit/src/app.d.ts | 13 + examples/sveltekit/src/app.html | 11 + examples/sveltekit/src/lib/assets/favicon.svg | 1 + examples/sveltekit/src/lib/index.ts | 1 + examples/sveltekit/src/routes/+layout.svelte | 12 + examples/sveltekit/src/routes/+page.svelte | 2 + examples/sveltekit/static/robots.txt | 3 + examples/sveltekit/svelte.config.js | 18 + examples/sveltekit/tsconfig.json | 19 + examples/sveltekit/vite.config.ts | 7 + package.json | 7 +- pnpm-lock.yaml | 784 ++++++++++++++++-- pnpm-workspace.yaml | 1 + 20 files changed, 946 insertions(+), 81 deletions(-) create mode 100644 examples/sveltekit/.gitignore create mode 100644 examples/sveltekit/.npmrc create mode 100644 examples/sveltekit/README.md create mode 100644 examples/sveltekit/eslint.config.js create mode 100644 examples/sveltekit/package.json create mode 100644 examples/sveltekit/src/app.css create mode 100644 examples/sveltekit/src/app.d.ts create mode 100644 examples/sveltekit/src/app.html create mode 100644 examples/sveltekit/src/lib/assets/favicon.svg create mode 100644 examples/sveltekit/src/lib/index.ts create mode 100644 examples/sveltekit/src/routes/+layout.svelte create mode 100644 examples/sveltekit/src/routes/+page.svelte create mode 100644 examples/sveltekit/static/robots.txt create mode 100644 examples/sveltekit/svelte.config.js create mode 100644 examples/sveltekit/tsconfig.json create mode 100644 examples/sveltekit/vite.config.ts diff --git a/cspell.json b/cspell.json index 5f240a731..7e39020c7 100644 --- a/cspell.json +++ b/cspell.json @@ -4,6 +4,8 @@ "activitypub", "activitystreams", "aitertools", + "amqp", + "amqplib", "apidoc", "authdocloader", "bccs", @@ -89,6 +91,8 @@ "subproperty", "superproperty", "supertypes", + "sveltejs", + "sveltekit", "tempserver", "traceparent", "ts-nocheck", diff --git a/examples/sveltekit/.gitignore b/examples/sveltekit/.gitignore new file mode 100644 index 000000000..3b462cb0c --- /dev/null +++ b/examples/sveltekit/.gitignore @@ -0,0 +1,23 @@ +node_modules + +# Output +.output +.vercel +.netlify +.wrangler +/.svelte-kit +/build + +# OS +.DS_Store +Thumbs.db + +# Env +.env +.env.* +!.env.example +!.env.test + +# Vite +vite.config.js.timestamp-* +vite.config.ts.timestamp-* diff --git a/examples/sveltekit/.npmrc b/examples/sveltekit/.npmrc new file mode 100644 index 000000000..b6f27f135 --- /dev/null +++ b/examples/sveltekit/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/examples/sveltekit/README.md b/examples/sveltekit/README.md new file mode 100644 index 000000000..75842c404 --- /dev/null +++ b/examples/sveltekit/README.md @@ -0,0 +1,38 @@ +# sv + +Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli). + +## Creating a project + +If you're seeing this, you've probably already done this step. Congrats! + +```sh +# create a new project in the current directory +npx sv create + +# create a new project in my-app +npx sv create my-app +``` + +## Developing + +Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: + +```sh +npm run dev + +# or start the server and open the app in a new browser tab +npm run dev -- --open +``` + +## Building + +To create a production version of your app: + +```sh +npm run build +``` + +You can preview the production build with `npm run preview`. + +> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment. diff --git a/examples/sveltekit/eslint.config.js b/examples/sveltekit/eslint.config.js new file mode 100644 index 000000000..2616f386b --- /dev/null +++ b/examples/sveltekit/eslint.config.js @@ -0,0 +1,39 @@ +import { includeIgnoreFile } from '@eslint/compat'; +import js from '@eslint/js'; +import svelte from 'eslint-plugin-svelte'; +import globals from 'globals'; +import { fileURLToPath } from 'node:url'; +import ts from 'typescript-eslint'; +import svelteConfig from './svelte.config.js'; + +const gitignorePath = fileURLToPath(new URL('./.gitignore', import.meta.url)); + +export default ts.config( + includeIgnoreFile(gitignorePath), + js.configs.recommended, + ...ts.configs.recommended, + ...svelte.configs.recommended, + { + languageOptions: { + globals: { ...globals.browser, ...globals.node } + }, + rules: { // typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects. + // see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors + "no-undef": 'off' } + }, + { + files: [ + '**/*.svelte', + '**/*.svelte.ts', + '**/*.svelte.js' + ], + languageOptions: { + parserOptions: { + projectService: true, + extraFileExtensions: ['.svelte'], + parser: ts.parser, + svelteConfig + } + } + } +); diff --git a/examples/sveltekit/package.json b/examples/sveltekit/package.json new file mode 100644 index 000000000..abfef71e1 --- /dev/null +++ b/examples/sveltekit/package.json @@ -0,0 +1,42 @@ +{ + "name": "sveltekit", + "private": true, + "version": "0.0.1", + "type": "module", + "description": "Fedify app with SvelteKit integration", + "author": { + "name": "Chanhaeng Lee", + "email": "2chanhaeng@gmail.com", + "url": "https://chomu.dev" + }, + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "prepare": "svelte-kit sync || echo ''", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "lint": "eslint ." + }, + "dependencies": { + "@fedify/fedify": "workspace:^", + "@fedify/sveltekit": "workspace:^" + }, + "devDependencies": { + "@eslint/compat": "^1.2.5", + "@eslint/js": "^9.18.0", + "@sveltejs/adapter-auto": "^6.0.0", + "@sveltejs/kit": "^2.22.0", + "@sveltejs/vite-plugin-svelte": "^6.0.0", + "@tailwindcss/vite": "^4.0.0", + "eslint": "^9.18.0", + "eslint-plugin-svelte": "^3.0.0", + "globals": "^16.0.0", + "svelte": "^5.0.0", + "svelte-check": "^4.0.0", + "tailwindcss": "^4.0.0", + "typescript": "^5.0.0", + "typescript-eslint": "^8.20.0", + "vite": "^7.0.4" + } +} diff --git a/examples/sveltekit/src/app.css b/examples/sveltekit/src/app.css new file mode 100644 index 000000000..d4b507858 --- /dev/null +++ b/examples/sveltekit/src/app.css @@ -0,0 +1 @@ +@import 'tailwindcss'; diff --git a/examples/sveltekit/src/app.d.ts b/examples/sveltekit/src/app.d.ts new file mode 100644 index 000000000..da08e6da5 --- /dev/null +++ b/examples/sveltekit/src/app.d.ts @@ -0,0 +1,13 @@ +// See https://svelte.dev/docs/kit/types#app.d.ts +// for information about these interfaces +declare global { + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface PageState {} + // interface Platform {} + } +} + +export {}; diff --git a/examples/sveltekit/src/app.html b/examples/sveltekit/src/app.html new file mode 100644 index 000000000..f273cc58f --- /dev/null +++ b/examples/sveltekit/src/app.html @@ -0,0 +1,11 @@ + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/examples/sveltekit/src/lib/assets/favicon.svg b/examples/sveltekit/src/lib/assets/favicon.svg new file mode 100644 index 000000000..cc5dc66a3 --- /dev/null +++ b/examples/sveltekit/src/lib/assets/favicon.svg @@ -0,0 +1 @@ +svelte-logo \ No newline at end of file diff --git a/examples/sveltekit/src/lib/index.ts b/examples/sveltekit/src/lib/index.ts new file mode 100644 index 000000000..856f2b6c3 --- /dev/null +++ b/examples/sveltekit/src/lib/index.ts @@ -0,0 +1 @@ +// place files you want to import through the `$lib` alias in this folder. diff --git a/examples/sveltekit/src/routes/+layout.svelte b/examples/sveltekit/src/routes/+layout.svelte new file mode 100644 index 000000000..9cba825ad --- /dev/null +++ b/examples/sveltekit/src/routes/+layout.svelte @@ -0,0 +1,12 @@ + + + + + + +{@render children?.()} diff --git a/examples/sveltekit/src/routes/+page.svelte b/examples/sveltekit/src/routes/+page.svelte new file mode 100644 index 000000000..cc88df0ea --- /dev/null +++ b/examples/sveltekit/src/routes/+page.svelte @@ -0,0 +1,2 @@ +

Welcome to SvelteKit

+

Visit svelte.dev/docs/kit to read the documentation

diff --git a/examples/sveltekit/static/robots.txt b/examples/sveltekit/static/robots.txt new file mode 100644 index 000000000..b6dd6670c --- /dev/null +++ b/examples/sveltekit/static/robots.txt @@ -0,0 +1,3 @@ +# allow crawling everything by default +User-agent: * +Disallow: diff --git a/examples/sveltekit/svelte.config.js b/examples/sveltekit/svelte.config.js new file mode 100644 index 000000000..1295460d1 --- /dev/null +++ b/examples/sveltekit/svelte.config.js @@ -0,0 +1,18 @@ +import adapter from '@sveltejs/adapter-auto'; +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + // Consult https://svelte.dev/docs/kit/integrations + // for more information about preprocessors + preprocess: vitePreprocess(), + + kit: { + // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list. + // If your environment is not supported, or you settled on a specific environment, switch out the adapter. + // See https://svelte.dev/docs/kit/adapters for more information about adapters. + adapter: adapter() + } +}; + +export default config; diff --git a/examples/sveltekit/tsconfig.json b/examples/sveltekit/tsconfig.json new file mode 100644 index 000000000..a5567ee6b --- /dev/null +++ b/examples/sveltekit/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler" + } + // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias + // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files + // + // To make changes to top-level options such as include and exclude, we recommend extending + // the generated config; see https://svelte.dev/docs/kit/configuration#typescript +} diff --git a/examples/sveltekit/vite.config.ts b/examples/sveltekit/vite.config.ts new file mode 100644 index 000000000..2d35c4f5a --- /dev/null +++ b/examples/sveltekit/vite.config.ts @@ -0,0 +1,7 @@ +import tailwindcss from '@tailwindcss/vite'; +import { sveltekit } from '@sveltejs/kit/vite'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [tailwindcss(), sveltekit()] +}); diff --git a/package.json b/package.json index f226c4cf3..f423aff73 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,9 @@ "pnpm": { "patchedDependencies": { "vitepress@1.6.3": "patches/vitepress@1.6.3.patch" - } + }, + "onlyBuiltDependencies": [ + "esbuild" + ] } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9018279b2..f08f96587 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -333,10 +333,10 @@ importers: version: 19.1.6(@types/react@19.1.8) eslint: specifier: ^9 - version: 9.32.0(jiti@2.4.2) + version: 9.32.0(jiti@2.5.1) eslint-config-next: specifier: 15.5.0 - version: 15.5.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2) + version: 15.5.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) tailwindcss: specifier: ^4 version: 4.1.11 @@ -425,10 +425,10 @@ importers: version: 19.1.6(@types/react@19.1.8) eslint: specifier: ^9 - version: 9.32.0(jiti@2.4.2) + version: 9.32.0(jiti@2.5.1) eslint-config-next: specifier: 15.3.1 - version: 15.3.1(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2) + version: 15.3.1(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) tailwindcss: specifier: ^4 version: 4.1.11 @@ -436,6 +436,61 @@ importers: specifier: 'catalog:' version: 5.9.2 + examples/sveltekit: + dependencies: + '@fedify/fedify': + specifier: workspace:^ + version: link:../../packages/fedify + '@fedify/sveltekit': + specifier: workspace:^ + version: link:../../packages/sveltekit + devDependencies: + '@eslint/compat': + specifier: ^1.2.5 + version: 1.3.2(eslint@9.32.0(jiti@2.5.1)) + '@eslint/js': + specifier: ^9.18.0 + version: 9.32.0 + '@sveltejs/adapter-auto': + specifier: ^6.0.0 + version: 6.1.0(@sveltejs/kit@2.36.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)))(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0))) + '@sveltejs/kit': + specifier: ^2.22.0 + version: 2.36.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)))(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)) + '@sveltejs/vite-plugin-svelte': + specifier: ^6.0.0 + version: 6.1.3(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)) + '@tailwindcss/vite': + specifier: ^4.0.0 + version: 4.1.12(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)) + eslint: + specifier: ^9.18.0 + version: 9.32.0(jiti@2.5.1) + eslint-plugin-svelte: + specifier: ^3.0.0 + version: 3.11.0(eslint@9.32.0(jiti@2.5.1))(svelte@5.38.3) + globals: + specifier: ^16.0.0 + version: 16.3.0 + svelte: + specifier: ^5.0.0 + version: 5.38.3 + svelte-check: + specifier: ^4.0.0 + version: 4.3.1(picomatch@4.0.3)(svelte@5.38.3)(typescript@5.9.2) + tailwindcss: + specifier: ^4.0.0 + version: 4.1.11 + typescript: + specifier: ^5.0.0 + version: 5.9.2 + typescript-eslint: + specifier: ^8.20.0 + version: 8.41.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + vite: + specifier: ^7.0.4 + version: 7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0) + packages/amqp: dependencies: '@fedify/fedify': @@ -784,7 +839,7 @@ importers: version: link:../fedify '@sveltejs/kit': specifier: 'catalog:' - version: 2.36.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1)))(svelte@5.38.3)(vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1)) + version: 2.36.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)))(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)) devDependencies: tsdown: specifier: 'catalog:' @@ -1521,6 +1576,15 @@ packages: resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint/compat@1.3.2': + resolution: {integrity: sha512-jRNwzTbd6p2Rw4sZ1CgWRS8YMtqG15YyZf7zvb6gY2rB2u6n+2Z+ELW0GtL0fQgyl0pr4Y/BzBfng/BdsereRA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.40 || 9 + peerDependenciesMeta: + eslint: + optional: true + '@eslint/config-array@0.21.0': resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2807,6 +2871,11 @@ packages: peerDependencies: acorn: ^8.9.0 + '@sveltejs/adapter-auto@6.1.0': + resolution: {integrity: sha512-shOuLI5D2s+0zTv2ab5M5PqfknXqWbKi+0UwB9yLTRIdzsK1R93JOO8jNhIYSHdW+IYXIYnLniu+JZqXs7h9Wg==} + peerDependencies: + '@sveltejs/kit': ^2.0.0 + '@sveltejs/kit@2.36.2': resolution: {integrity: sha512-WlBGY060nHe4UE5QrDAJAbls5hOsG6mljtrDGkM8jJCDQ4JEcAEH04XrTVmQ0Ex1CU8nzoZto0EE75aiLA3G8Q==} engines: {node: '>=18.13'} @@ -2847,60 +2916,117 @@ packages: '@tailwindcss/node@4.1.11': resolution: {integrity: sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==} + '@tailwindcss/node@4.1.12': + resolution: {integrity: sha512-3hm9brwvQkZFe++SBt+oLjo4OLDtkvlE8q2WalaD/7QWaeM7KEJbAiY/LJZUaCs7Xa8aUu4xy3uoyX4q54UVdQ==} + '@tailwindcss/oxide-android-arm64@4.1.11': resolution: {integrity: sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==} engines: {node: '>= 10'} cpu: [arm64] os: [android] + '@tailwindcss/oxide-android-arm64@4.1.12': + resolution: {integrity: sha512-oNY5pq+1gc4T6QVTsZKwZaGpBb2N1H1fsc1GD4o7yinFySqIuRZ2E4NvGasWc6PhYJwGK2+5YT1f9Tp80zUQZQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + '@tailwindcss/oxide-darwin-arm64@4.1.11': resolution: {integrity: sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] + '@tailwindcss/oxide-darwin-arm64@4.1.12': + resolution: {integrity: sha512-cq1qmq2HEtDV9HvZlTtrj671mCdGB93bVY6J29mwCyaMYCP/JaUBXxrQQQm7Qn33AXXASPUb2HFZlWiiHWFytw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + '@tailwindcss/oxide-darwin-x64@4.1.11': resolution: {integrity: sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] + '@tailwindcss/oxide-darwin-x64@4.1.12': + resolution: {integrity: sha512-6UCsIeFUcBfpangqlXay9Ffty9XhFH1QuUFn0WV83W8lGdX8cD5/+2ONLluALJD5+yJ7k8mVtwy3zMZmzEfbLg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + '@tailwindcss/oxide-freebsd-x64@4.1.11': resolution: {integrity: sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] + '@tailwindcss/oxide-freebsd-x64@4.1.12': + resolution: {integrity: sha512-JOH/f7j6+nYXIrHobRYCtoArJdMJh5zy5lr0FV0Qu47MID/vqJAY3r/OElPzx1C/wdT1uS7cPq+xdYYelny1ww==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.11': resolution: {integrity: sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==} engines: {node: '>= 10'} cpu: [arm] os: [linux] + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.12': + resolution: {integrity: sha512-v4Ghvi9AU1SYgGr3/j38PD8PEe6bRfTnNSUE3YCMIRrrNigCFtHZ2TCm8142X8fcSqHBZBceDx+JlFJEfNg5zQ==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + '@tailwindcss/oxide-linux-arm64-gnu@4.1.11': resolution: {integrity: sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + '@tailwindcss/oxide-linux-arm64-gnu@4.1.12': + resolution: {integrity: sha512-YP5s1LmetL9UsvVAKusHSyPlzSRqYyRB0f+Kl/xcYQSPLEw/BvGfxzbH+ihUciePDjiXwHh+p+qbSP3SlJw+6g==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + '@tailwindcss/oxide-linux-arm64-musl@4.1.11': resolution: {integrity: sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + '@tailwindcss/oxide-linux-arm64-musl@4.1.12': + resolution: {integrity: sha512-V8pAM3s8gsrXcCv6kCHSuwyb/gPsd863iT+v1PGXC4fSL/OJqsKhfK//v8P+w9ThKIoqNbEnsZqNy+WDnwQqCA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + '@tailwindcss/oxide-linux-x64-gnu@4.1.11': resolution: {integrity: sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + '@tailwindcss/oxide-linux-x64-gnu@4.1.12': + resolution: {integrity: sha512-xYfqYLjvm2UQ3TZggTGrwxjYaLB62b1Wiysw/YE3Yqbh86sOMoTn0feF98PonP7LtjsWOWcXEbGqDL7zv0uW8Q==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + '@tailwindcss/oxide-linux-x64-musl@4.1.11': resolution: {integrity: sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + '@tailwindcss/oxide-linux-x64-musl@4.1.12': + resolution: {integrity: sha512-ha0pHPamN+fWZY7GCzz5rKunlv9L5R8kdh+YNvP5awe3LtuXb5nRi/H27GeL2U+TdhDOptU7T6Is7mdwh5Ar3A==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + '@tailwindcss/oxide-wasm32-wasi@4.1.11': resolution: {integrity: sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==} engines: {node: '>=14.0.0'} @@ -2913,25 +3039,58 @@ packages: - '@emnapi/wasi-threads' - tslib + '@tailwindcss/oxide-wasm32-wasi@4.1.12': + resolution: {integrity: sha512-4tSyu3dW+ktzdEpuk6g49KdEangu3eCYoqPhWNsZgUhyegEda3M9rG0/j1GV/JjVVsj+lG7jWAyrTlLzd/WEBg==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + '@tailwindcss/oxide-win32-arm64-msvc@4.1.11': resolution: {integrity: sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] + '@tailwindcss/oxide-win32-arm64-msvc@4.1.12': + resolution: {integrity: sha512-iGLyD/cVP724+FGtMWslhcFyg4xyYyM+5F4hGvKA7eifPkXHRAUDFaimu53fpNg9X8dfP75pXx/zFt/jlNF+lg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + '@tailwindcss/oxide-win32-x64-msvc@4.1.11': resolution: {integrity: sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] + '@tailwindcss/oxide-win32-x64-msvc@4.1.12': + resolution: {integrity: sha512-NKIh5rzw6CpEodv/++r0hGLlfgT/gFN+5WNdZtvh6wpU2BpGNgdjvj6H2oFc8nCM839QM1YOhjpgbAONUb4IxA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + '@tailwindcss/oxide@4.1.11': resolution: {integrity: sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==} engines: {node: '>= 10'} + '@tailwindcss/oxide@4.1.12': + resolution: {integrity: sha512-gM5EoKHW/ukmlEtphNwaGx45fGoEmP10v51t9unv55voWh6WrOL19hfuIdo2FjxIaZzw776/BUQg7Pck++cIVw==} + engines: {node: '>= 10'} + '@tailwindcss/postcss@4.1.11': resolution: {integrity: sha512-q/EAIIpF6WpLhKEuQSEVMZNMIY8KhWoAemZ9eylNAih9jxMGAYPPWBn3I9QL/2jZ+e7OEz/tZkX5HwbBR4HohA==} + '@tailwindcss/vite@4.1.12': + resolution: {integrity: sha512-4pt0AMFDx7gzIrAOIYgYP0KCBuKWqyW8ayrdiLEjoJTT4pKTjrzG/e4uzWtTLDziC+66R9wbUqZBccJalSE5vQ==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 + '@teidesu/deno-types@2.1.10': resolution: {integrity: sha512-oxMkUtshAL2tzRT//GcMDtfXelu9tLn8PFdg6qoPg1yFUfVp0YHCbQQRtZaOU0SyALFM9PCOBXu3V8hef2Geug==} deprecated: as of late 2024, deno started publishing official typings at @types/deno, making this package obsolete and no longer supported @@ -3188,6 +3347,14 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/eslint-plugin@8.41.0': + resolution: {integrity: sha512-8fz6oa6wEKZrhXWro/S3n2eRJqlRcIa6SlDh59FXJ5Wp5XRZ8B9ixpJDcjadHq47hMx0u+HW6SNa6LjJQ6NLtw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.41.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/parser@7.18.0': resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==} engines: {node: ^18.18.0 || >=20.0.0} @@ -3205,12 +3372,25 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/parser@8.41.0': + resolution: {integrity: sha512-gTtSdWX9xiMPA/7MV9STjJOOYtWwIJIYxkQxnSV1U3xcE+mnJSH3f6zI0RYP+ew66WSlZ5ed+h0VCxsvdC1jJg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/project-service@8.38.0': resolution: {integrity: sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/project-service@8.41.0': + resolution: {integrity: sha512-b8V9SdGBQzQdjJ/IO3eDifGpDBJfvrNTp2QD9P2BeqWTGrRibgfgIlBSw6z3b6R7dPzg752tOs4u/7yCLxksSQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/scope-manager@7.18.0': resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} engines: {node: ^18.18.0 || >=20.0.0} @@ -3219,12 +3399,22 @@ packages: resolution: {integrity: sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.41.0': + resolution: {integrity: sha512-n6m05bXn/Cd6DZDGyrpXrELCPVaTnLdPToyhBoFkLIMznRUQUEQdSp96s/pcWSQdqOhrgR1mzJ+yItK7T+WPMQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/tsconfig-utils@8.38.0': resolution: {integrity: sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/tsconfig-utils@8.41.0': + resolution: {integrity: sha512-TDhxYFPUYRFxFhuU5hTIJk+auzM/wKvWgoNYOPcOf6i4ReYlOoYN8q1dV5kOTjNQNJgzWN3TUUQMtlLOcUgdUw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/type-utils@7.18.0': resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==} engines: {node: ^18.18.0 || >=20.0.0} @@ -3242,6 +3432,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/type-utils@8.41.0': + resolution: {integrity: sha512-63qt1h91vg3KsjVVonFJWjgSK7pZHSQFKH6uwqxAH9bBrsyRhO6ONoKyXxyVBzG1lJnFAJcKAcxLS54N1ee1OQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/types@7.18.0': resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} engines: {node: ^18.18.0 || >=20.0.0} @@ -3250,6 +3447,10 @@ packages: resolution: {integrity: sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.41.0': + resolution: {integrity: sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@7.18.0': resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} engines: {node: ^18.18.0 || >=20.0.0} @@ -3265,6 +3466,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/typescript-estree@8.41.0': + resolution: {integrity: sha512-D43UwUYJmGhuwHfY7MtNKRZMmfd8+p/eNSfFe6tH5mbVDto+VQCayeAt35rOx3Cs6wxD16DQtIKw/YXxt5E0UQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/utils@7.18.0': resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} engines: {node: ^18.18.0 || >=20.0.0} @@ -3278,6 +3485,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/utils@8.41.0': + resolution: {integrity: sha512-udbCVstxZ5jiPIXrdH+BZWnPatjlYwJuJkDA4Tbo3WyYLh8NvB+h/bKeSZHDOFKfphsZYJQqaFtLeXEqurQn1A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/visitor-keys@7.18.0': resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} engines: {node: ^18.18.0 || >=20.0.0} @@ -3286,6 +3500,10 @@ packages: resolution: {integrity: sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.41.0': + resolution: {integrity: sha512-+GeGMebMCy0elMNg67LRNoVnUFPIm37iu5CmHESVx56/9Jsfdpsvbv605DQ81Pi/x11IdKUsS5nzgTYbCQU9fg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript/vfs@1.6.1': resolution: {integrity: sha512-JwoxboBh7Oz1v38tPbkrZ62ZXNHAk9bJ7c9x0eI5zBfBnBYGhURdbnh7Z4smN/MV48Y5OCcZb58n972UtbazsA==} peerDependencies: @@ -4236,6 +4454,10 @@ packages: resolution: {integrity: sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==} engines: {node: '>=10.13.0'} + enhanced-resolve@5.18.3: + resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} + engines: {node: '>=10.13.0'} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -4403,6 +4625,16 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + eslint-plugin-svelte@3.11.0: + resolution: {integrity: sha512-KliWlkieHyEa65aQIkRwUFfHzT5Cn4u3BQQsu3KlkJOs7c1u7ryn84EWaOjEzilbKgttT4OfBURA8Uc4JBSQIw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.1 || ^9.0.0 + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + svelte: + optional: true + eslint-scope@7.2.2: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4545,6 +4777,15 @@ packages: picomatch: optional: true + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + fetch-blob@3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} @@ -4701,6 +4942,10 @@ packages: resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} engines: {node: '>=18'} + globals@16.3.0: + resolution: {integrity: sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==} + engines: {node: '>=18'} + globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -5001,6 +5246,10 @@ packages: resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} hasBin: true + jiti@2.5.1: + resolution: {integrity: sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==} + hasBin: true + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -5062,6 +5311,9 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} + known-css-properties@0.37.0: + resolution: {integrity: sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==} + kolorist@1.8.0: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} @@ -5164,6 +5416,10 @@ packages: resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==} engines: {node: '>= 12.0.0'} + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + lilconfig@3.1.3: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} @@ -5730,8 +5986,8 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - picomatch@4.0.2: - resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} pify@2.3.0: @@ -5774,6 +6030,18 @@ packages: peerDependencies: postcss: ^8.4.21 + postcss-load-config@3.1.4: + resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} + engines: {node: '>= 10'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + postcss-load-config@4.0.2: resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} engines: {node: '>= 14'} @@ -5792,10 +6060,26 @@ packages: peerDependencies: postcss: ^8.2.14 + postcss-safe-parser@7.0.1: + resolution: {integrity: sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==} + engines: {node: '>=18.0'} + peerDependencies: + postcss: ^8.4.31 + + postcss-scss@4.0.9: + resolution: {integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.4.29 + postcss-selector-parser@6.1.2: resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} + postcss-selector-parser@7.1.0: + resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==} + engines: {node: '>=4'} + postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} @@ -6337,6 +6621,23 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + svelte-check@4.3.1: + resolution: {integrity: sha512-lkh8gff5gpHLjxIV+IaApMxQhTGnir2pNUAqcNgeKkvK5bT/30Ey/nzBxNLDlkztCH4dP7PixkMt9SWEKFPBWg==} + 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.3.1: + resolution: {integrity: sha512-0Iztj5vcOVOVkhy1pbo5uA9r+d3yaVoE5XPc9eABIWDOSJZ2mOsZ4D+t45rphWCOr0uMw3jtSG2fh2e7GvKnPg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + svelte: + optional: true + svelte@5.38.3: resolution: {integrity: sha512-ldbPzKdjUy7IALMBn15jzBM/TNxdXMxKeQZ538zzdABUjLg7e7/OIwnlaMQ+OR6s91W7DbDmJYjxHThHH7r9xA==} engines: {node: '>=18'} @@ -6352,6 +6653,9 @@ packages: tailwindcss@4.1.11: resolution: {integrity: sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==} + tailwindcss@4.1.12: + resolution: {integrity: sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==} + tapable@2.2.2: resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==} engines: {node: '>=6'} @@ -6503,6 +6807,13 @@ packages: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} + typescript-eslint@8.41.0: + resolution: {integrity: sha512-n66rzs5OBXW3SFSnZHr2T685q1i4ODm2nulFJhMZBotaTavsS8TrI3d7bDlRSs9yWo7HmyWrN9qDu14Qv7Y0Dw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + typescript@5.8.3: resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} engines: {node: '>=14.17'} @@ -6652,6 +6963,46 @@ packages: terser: optional: true + vite@7.1.3: + resolution: {integrity: sha512-OOUi5zjkDxYrKhTV3V7iKsoS37VUM7v40+HuwEmcrsf11Cdx9y3DIr2Px6liIcZFwt3XSRpQvFpL3WVy7ApkGw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + vitefu@1.1.1: resolution: {integrity: sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==} peerDependencies: @@ -6810,6 +7161,10 @@ packages: resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} engines: {node: '>=18'} + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + yaml@2.8.0: resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==} engines: {node: '>= 14.6'} @@ -7337,13 +7692,17 @@ snapshots: eslint: 8.57.1 eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.7.0(eslint@9.32.0(jiti@2.4.2))': + '@eslint-community/eslint-utils@4.7.0(eslint@9.32.0(jiti@2.5.1))': dependencies: - eslint: 9.32.0(jiti@2.4.2) + eslint: 9.32.0(jiti@2.5.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} + '@eslint/compat@1.3.2(eslint@9.32.0(jiti@2.5.1))': + optionalDependencies: + eslint: 9.32.0(jiti@2.5.1) + '@eslint/config-array@0.21.0': dependencies: '@eslint/object-schema': 2.1.6 @@ -8671,11 +9030,15 @@ snapshots: dependencies: acorn: 8.15.0 - '@sveltejs/kit@2.36.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1)))(svelte@5.38.3)(vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1))': + '@sveltejs/adapter-auto@6.1.0(@sveltejs/kit@2.36.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)))(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)))': + dependencies: + '@sveltejs/kit': 2.36.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)))(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)) + + '@sveltejs/kit@2.36.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)))(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0))': dependencies: '@standard-schema/spec': 1.0.0 '@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0) - '@sveltejs/vite-plugin-svelte': 6.1.3(svelte@5.38.3)(vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1)) + '@sveltejs/vite-plugin-svelte': 6.1.3(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)) '@types/cookie': 0.6.0 acorn: 8.15.0 cookie: 0.6.0 @@ -8688,29 +9051,29 @@ snapshots: set-cookie-parser: 2.7.1 sirv: 3.0.1 svelte: 5.38.3 - vite: 5.4.19(@types/node@24.3.0)(lightningcss@1.30.1) + vite: 7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0) optionalDependencies: '@opentelemetry/api': 1.9.0 - '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1)))(svelte@5.38.3)(vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1))': + '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)))(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 6.1.3(svelte@5.38.3)(vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1)) + '@sveltejs/vite-plugin-svelte': 6.1.3(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)) debug: 4.4.1 svelte: 5.38.3 - vite: 5.4.19(@types/node@24.3.0)(lightningcss@1.30.1) + vite: 7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1))': + '@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1)))(svelte@5.38.3)(vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1)) + '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)))(svelte@5.38.3)(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)) debug: 4.4.1 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.17 svelte: 5.38.3 - vite: 5.4.19(@types/node@24.3.0)(lightningcss@1.30.1) - vitefu: 1.1.1(vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1)) + vite: 7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0) + vitefu: 1.1.1(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)) transitivePeerDependencies: - supports-color @@ -8735,42 +9098,88 @@ snapshots: source-map-js: 1.2.1 tailwindcss: 4.1.11 + '@tailwindcss/node@4.1.12': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.18.3 + jiti: 2.5.1 + lightningcss: 1.30.1 + magic-string: 0.30.17 + source-map-js: 1.2.1 + tailwindcss: 4.1.12 + '@tailwindcss/oxide-android-arm64@4.1.11': optional: true + '@tailwindcss/oxide-android-arm64@4.1.12': + optional: true + '@tailwindcss/oxide-darwin-arm64@4.1.11': optional: true + '@tailwindcss/oxide-darwin-arm64@4.1.12': + optional: true + '@tailwindcss/oxide-darwin-x64@4.1.11': optional: true + '@tailwindcss/oxide-darwin-x64@4.1.12': + optional: true + '@tailwindcss/oxide-freebsd-x64@4.1.11': optional: true + '@tailwindcss/oxide-freebsd-x64@4.1.12': + optional: true + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.11': optional: true + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.12': + optional: true + '@tailwindcss/oxide-linux-arm64-gnu@4.1.11': optional: true + '@tailwindcss/oxide-linux-arm64-gnu@4.1.12': + optional: true + '@tailwindcss/oxide-linux-arm64-musl@4.1.11': optional: true + '@tailwindcss/oxide-linux-arm64-musl@4.1.12': + optional: true + '@tailwindcss/oxide-linux-x64-gnu@4.1.11': optional: true + '@tailwindcss/oxide-linux-x64-gnu@4.1.12': + optional: true + '@tailwindcss/oxide-linux-x64-musl@4.1.11': optional: true + '@tailwindcss/oxide-linux-x64-musl@4.1.12': + optional: true + '@tailwindcss/oxide-wasm32-wasi@4.1.11': optional: true + '@tailwindcss/oxide-wasm32-wasi@4.1.12': + optional: true + '@tailwindcss/oxide-win32-arm64-msvc@4.1.11': optional: true + '@tailwindcss/oxide-win32-arm64-msvc@4.1.12': + optional: true + '@tailwindcss/oxide-win32-x64-msvc@4.1.11': optional: true + '@tailwindcss/oxide-win32-x64-msvc@4.1.12': + optional: true + '@tailwindcss/oxide@4.1.11': dependencies: detect-libc: 2.0.4 @@ -8789,6 +9198,24 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.11 '@tailwindcss/oxide-win32-x64-msvc': 4.1.11 + '@tailwindcss/oxide@4.1.12': + dependencies: + detect-libc: 2.0.4 + tar: 7.4.3 + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.1.12 + '@tailwindcss/oxide-darwin-arm64': 4.1.12 + '@tailwindcss/oxide-darwin-x64': 4.1.12 + '@tailwindcss/oxide-freebsd-x64': 4.1.12 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.12 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.12 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.12 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.12 + '@tailwindcss/oxide-linux-x64-musl': 4.1.12 + '@tailwindcss/oxide-wasm32-wasi': 4.1.12 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.12 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.12 + '@tailwindcss/postcss@4.1.11': dependencies: '@alloc/quick-lru': 5.2.0 @@ -8797,6 +9224,13 @@ snapshots: postcss: 8.5.6 tailwindcss: 4.1.11 + '@tailwindcss/vite@4.1.12(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0))': + dependencies: + '@tailwindcss/node': 4.1.12 + '@tailwindcss/oxide': 4.1.12 + tailwindcss: 4.1.12 + vite: 7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0) + '@teidesu/deno-types@2.1.10': {} '@tokenizer/inflate@0.2.7': @@ -9096,15 +9530,32 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2)': + '@typescript-eslint/eslint-plugin@8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2) + '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) '@typescript-eslint/scope-manager': 8.38.0 - '@typescript-eslint/type-utils': 8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2) - '@typescript-eslint/utils': 8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2) + '@typescript-eslint/type-utils': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/utils': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) '@typescript-eslint/visitor-keys': 8.38.0 - eslint: 9.32.0(jiti@2.4.2) + eslint: 9.32.0(jiti@2.5.1) + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/eslint-plugin@8.41.0(@typescript-eslint/parser@8.41.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.41.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/scope-manager': 8.41.0 + '@typescript-eslint/type-utils': 8.41.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/utils': 8.41.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.41.0 + eslint: 9.32.0(jiti@2.5.1) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -9126,14 +9577,26 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2)': + '@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2)': dependencies: '@typescript-eslint/scope-manager': 8.38.0 '@typescript-eslint/types': 8.38.0 '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.9.2) '@typescript-eslint/visitor-keys': 8.38.0 debug: 4.4.1 - eslint: 9.32.0(jiti@2.4.2) + eslint: 9.32.0(jiti@2.5.1) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.41.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.41.0 + '@typescript-eslint/types': 8.41.0 + '@typescript-eslint/typescript-estree': 8.41.0(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.41.0 + debug: 4.4.1 + eslint: 9.32.0(jiti@2.5.1) typescript: 5.9.2 transitivePeerDependencies: - supports-color @@ -9147,6 +9610,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.41.0(typescript@5.9.2)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.41.0(typescript@5.9.2) + '@typescript-eslint/types': 8.41.0 + debug: 4.4.1 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@7.18.0': dependencies: '@typescript-eslint/types': 7.18.0 @@ -9157,10 +9629,19 @@ snapshots: '@typescript-eslint/types': 8.38.0 '@typescript-eslint/visitor-keys': 8.38.0 + '@typescript-eslint/scope-manager@8.41.0': + dependencies: + '@typescript-eslint/types': 8.41.0 + '@typescript-eslint/visitor-keys': 8.41.0 + '@typescript-eslint/tsconfig-utils@8.38.0(typescript@5.9.2)': dependencies: typescript: 5.9.2 + '@typescript-eslint/tsconfig-utils@8.41.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.1)(typescript@5.9.2)': dependencies: '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.9.2) @@ -9173,13 +9654,25 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2)': + '@typescript-eslint/type-utils@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2)': dependencies: '@typescript-eslint/types': 8.38.0 '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.9.2) - '@typescript-eslint/utils': 8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2) + '@typescript-eslint/utils': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + debug: 4.4.1 + eslint: 9.32.0(jiti@2.5.1) + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/type-utils@8.41.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2)': + dependencies: + '@typescript-eslint/types': 8.41.0 + '@typescript-eslint/typescript-estree': 8.41.0(typescript@5.9.2) + '@typescript-eslint/utils': 8.41.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) debug: 4.4.1 - eslint: 9.32.0(jiti@2.4.2) + eslint: 9.32.0(jiti@2.5.1) ts-api-utils: 2.1.0(typescript@5.9.2) typescript: 5.9.2 transitivePeerDependencies: @@ -9189,6 +9682,8 @@ snapshots: '@typescript-eslint/types@8.38.0': {} + '@typescript-eslint/types@8.41.0': {} + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.9.2)': dependencies: '@typescript-eslint/types': 7.18.0 @@ -9220,6 +9715,22 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.41.0(typescript@5.9.2)': + dependencies: + '@typescript-eslint/project-service': 8.41.0(typescript@5.9.2) + '@typescript-eslint/tsconfig-utils': 8.41.0(typescript@5.9.2) + '@typescript-eslint/types': 8.41.0 + '@typescript-eslint/visitor-keys': 8.41.0 + debug: 4.4.1 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@7.18.0(eslint@8.57.1)(typescript@5.9.2)': dependencies: '@eslint-community/eslint-utils': 4.7.0(eslint@8.57.1) @@ -9231,13 +9742,24 @@ snapshots: - supports-color - typescript - '@typescript-eslint/utils@8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2)': + '@typescript-eslint/utils@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.32.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.32.0(jiti@2.5.1)) '@typescript-eslint/scope-manager': 8.38.0 '@typescript-eslint/types': 8.38.0 '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.9.2) - eslint: 9.32.0(jiti@2.4.2) + eslint: 9.32.0(jiti@2.5.1) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.41.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.32.0(jiti@2.5.1)) + '@typescript-eslint/scope-manager': 8.41.0 + '@typescript-eslint/types': 8.41.0 + '@typescript-eslint/typescript-estree': 8.41.0(typescript@5.9.2) + eslint: 9.32.0(jiti@2.5.1) typescript: 5.9.2 transitivePeerDependencies: - supports-color @@ -9252,6 +9774,11 @@ snapshots: '@typescript-eslint/types': 8.38.0 eslint-visitor-keys: 4.2.1 + '@typescript-eslint/visitor-keys@8.41.0': + dependencies: + '@typescript-eslint/types': 8.41.0 + eslint-visitor-keys: 4.2.1 + '@typescript/vfs@1.6.1(typescript@5.9.2)': dependencies: debug: 4.4.1 @@ -10181,6 +10708,11 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.2.2 + enhanced-resolve@5.18.3: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.2 + entities@4.5.0: {} es-abstract@1.24.0: @@ -10396,19 +10928,19 @@ snapshots: - eslint-plugin-import-x - supports-color - eslint-config-next@15.3.1(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2): + eslint-config-next@15.3.1(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2): dependencies: '@next/eslint-plugin-next': 15.3.1 '@rushstack/eslint-patch': 1.12.0 - '@typescript-eslint/eslint-plugin': 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2) - '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2) - eslint: 9.32.0(jiti@2.4.2) + '@typescript-eslint/eslint-plugin': 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.4.2)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.4.2)) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.32.0(jiti@2.4.2)) - eslint-plugin-react: 7.37.5(eslint@9.32.0(jiti@2.4.2)) - eslint-plugin-react-hooks: 5.2.0(eslint@9.32.0(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-react: 7.37.5(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-react-hooks: 5.2.0(eslint@9.32.0(jiti@2.5.1)) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: @@ -10416,19 +10948,19 @@ snapshots: - eslint-plugin-import-x - supports-color - eslint-config-next@15.5.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2): + eslint-config-next@15.5.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2): dependencies: '@next/eslint-plugin-next': 15.5.0 '@rushstack/eslint-patch': 1.12.0 - '@typescript-eslint/eslint-plugin': 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2) - '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2) - eslint: 9.32.0(jiti@2.4.2) + '@typescript-eslint/eslint-plugin': 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.4.2)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.4.2)) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.32.0(jiti@2.4.2)) - eslint-plugin-react: 7.37.5(eslint@9.32.0(jiti@2.4.2)) - eslint-plugin-react-hooks: 5.2.0(eslint@9.32.0(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-react: 7.37.5(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-react-hooks: 5.2.0(eslint@9.32.0(jiti@2.5.1)) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: @@ -10459,18 +10991,18 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.4.2)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1 - eslint: 9.32.0(jiti@2.4.2) + eslint: 9.32.0(jiti@2.5.1) get-tsconfig: 4.10.1 is-bun-module: 2.0.0 stable-hash: 0.0.5 tinyglobby: 0.2.14 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.4.2)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color @@ -10485,14 +11017,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.4.2)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2) - eslint: 9.32.0(jiti@2.4.2) + '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color @@ -10525,7 +11057,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.4.2)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -10534,9 +11066,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.32.0(jiti@2.4.2) + eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.4.2)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -10548,7 +11080,7 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.4.2))(typescript@5.9.2) + '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -10573,7 +11105,7 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-jsx-a11y@6.10.2(eslint@9.32.0(jiti@2.4.2)): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.32.0(jiti@2.5.1)): dependencies: aria-query: 5.3.2 array-includes: 3.1.9 @@ -10583,7 +11115,7 @@ snapshots: axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 9.32.0(jiti@2.4.2) + eslint: 9.32.0(jiti@2.5.1) hasown: 2.0.2 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -10596,9 +11128,9 @@ snapshots: dependencies: eslint: 8.57.1 - eslint-plugin-react-hooks@5.2.0(eslint@9.32.0(jiti@2.4.2)): + eslint-plugin-react-hooks@5.2.0(eslint@9.32.0(jiti@2.5.1)): dependencies: - eslint: 9.32.0(jiti@2.4.2) + eslint: 9.32.0(jiti@2.5.1) eslint-plugin-react@7.37.5(eslint@8.57.1): dependencies: @@ -10622,7 +11154,7 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-react@7.37.5(eslint@9.32.0(jiti@2.4.2)): + eslint-plugin-react@7.37.5(eslint@9.32.0(jiti@2.5.1)): dependencies: array-includes: 3.1.9 array.prototype.findlast: 1.2.5 @@ -10630,7 +11162,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 9.32.0(jiti@2.4.2) + eslint: 9.32.0(jiti@2.5.1) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -10644,6 +11176,24 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 + eslint-plugin-svelte@3.11.0(eslint@9.32.0(jiti@2.5.1))(svelte@5.38.3): + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.32.0(jiti@2.5.1)) + '@jridgewell/sourcemap-codec': 1.5.3 + eslint: 9.32.0(jiti@2.5.1) + esutils: 2.0.3 + globals: 16.3.0 + known-css-properties: 0.37.0 + postcss: 8.5.6 + postcss-load-config: 3.1.4(postcss@8.5.6) + postcss-safe-parser: 7.0.1(postcss@8.5.6) + semver: 7.7.2 + svelte-eslint-parser: 1.3.1(svelte@5.38.3) + optionalDependencies: + svelte: 5.38.3 + transitivePeerDependencies: + - ts-node + eslint-scope@7.2.2: dependencies: esrecurse: 4.3.0 @@ -10701,9 +11251,9 @@ snapshots: transitivePeerDependencies: - supports-color - eslint@9.32.0(jiti@2.4.2): + eslint@9.32.0(jiti@2.5.1): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.32.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.32.0(jiti@2.5.1)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.21.0 '@eslint/config-helpers': 0.3.0 @@ -10739,7 +11289,7 @@ snapshots: natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: - jiti: 2.4.2 + jiti: 2.5.1 transitivePeerDependencies: - supports-color @@ -10867,9 +11417,13 @@ snapshots: dependencies: format: 0.2.2 - fdir@6.4.6(picomatch@4.0.2): + fdir@6.4.6(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + fdir@6.5.0(picomatch@4.0.3): optionalDependencies: - picomatch: 4.0.2 + picomatch: 4.0.3 fetch-blob@3.2.0: dependencies: @@ -11056,6 +11610,8 @@ snapshots: globals@15.15.0: {} + globals@16.3.0: {} + globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -11374,6 +11930,8 @@ snapshots: jiti@2.4.2: {} + jiti@2.5.1: {} + js-tokens@4.0.0: {} js-yaml@3.14.1: @@ -11431,6 +11989,8 @@ snapshots: kleur@4.1.5: {} + known-css-properties@0.37.0: {} + kolorist@1.8.0: {} ky-universal@0.11.0(ky@0.33.3)(web-streams-polyfill@3.3.3): @@ -11511,6 +12071,8 @@ snapshots: lightningcss-win32-arm64-msvc: 1.30.1 lightningcss-win32-x64-msvc: 1.30.1 + lilconfig@2.1.0: {} + lilconfig@3.1.3: {} lines-and-columns@1.2.4: {} @@ -12234,7 +12796,7 @@ snapshots: picomatch@2.3.1: {} - picomatch@4.0.2: {} + picomatch@4.0.3: {} pify@2.3.0: {} @@ -12282,6 +12844,13 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.5.6 + postcss-load-config@3.1.4(postcss@8.5.6): + dependencies: + lilconfig: 2.1.0 + yaml: 1.10.2 + optionalDependencies: + postcss: 8.5.6 + postcss-load-config@4.0.2(postcss@8.5.6): dependencies: lilconfig: 3.1.3 @@ -12294,11 +12863,24 @@ snapshots: postcss: 8.5.6 postcss-selector-parser: 6.1.2 + postcss-safe-parser@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-scss@4.0.9(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser@6.1.2: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 + postcss-selector-parser@7.1.0: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + postcss-value-parser@4.2.0: {} postcss@8.4.31: @@ -12996,6 +13578,29 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + svelte-check@4.3.1(picomatch@4.0.3)(svelte@5.38.3)(typescript@5.9.2): + dependencies: + '@jridgewell/trace-mapping': 0.3.28 + chokidar: 4.0.3 + fdir: 6.4.6(picomatch@4.0.3) + picocolors: 1.1.1 + sade: 1.8.1 + svelte: 5.38.3 + typescript: 5.9.2 + transitivePeerDependencies: + - picomatch + + svelte-eslint-parser@1.3.1(svelte@5.38.3): + dependencies: + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + postcss: 8.5.6 + postcss-scss: 4.0.9(postcss@8.5.6) + postcss-selector-parser: 7.1.0 + optionalDependencies: + svelte: 5.38.3 + svelte@5.38.3: dependencies: '@jridgewell/remapping': 2.3.5 @@ -13044,6 +13649,8 @@ snapshots: tailwindcss@4.1.11: {} + tailwindcss@4.1.12: {} + tapable@2.2.2: {} tar@7.4.3: @@ -13069,8 +13676,8 @@ snapshots: tinyglobby@0.2.14: dependencies: - fdir: 6.4.6(picomatch@4.0.2) - picomatch: 4.0.2 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 to-regex-range@5.0.1: dependencies: @@ -13215,6 +13822,17 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 + typescript-eslint@8.41.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2): + dependencies: + '@typescript-eslint/eslint-plugin': 8.41.0(@typescript-eslint/parser@8.41.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/parser': 8.41.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/typescript-estree': 8.41.0(typescript@5.9.2) + '@typescript-eslint/utils': 8.41.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) + eslint: 9.32.0(jiti@2.5.1) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + typescript@5.8.3: {} typescript@5.9.2: {} @@ -13375,19 +13993,25 @@ snapshots: fsevents: 2.3.3 lightningcss: 1.30.1 - vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1): + vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0): dependencies: - esbuild: 0.21.5 + esbuild: 0.25.5 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 postcss: 8.5.6 rollup: 4.44.1 + tinyglobby: 0.2.14 optionalDependencies: '@types/node': 24.3.0 fsevents: 2.3.3 + jiti: 2.5.1 lightningcss: 1.30.1 + tsx: 4.20.3 + yaml: 2.8.0 - vitefu@1.1.1(vite@5.4.19(@types/node@24.3.0)(lightningcss@1.30.1)): + vitefu@1.1.1(vite@7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0)): optionalDependencies: - vite: 5.4.19(@types/node@24.3.0)(lightningcss@1.30.1) + vite: 7.1.3(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@2.8.0) vitepress-plugin-group-icons@1.6.1(markdown-it@14.1.0)(vite@5.4.19(@types/node@22.16.0)(lightningcss@1.30.1)): dependencies: @@ -13609,6 +14233,8 @@ snapshots: yallist@5.0.0: {} + yaml@1.10.2: {} + yaml@2.8.0: {} yargs-parser@21.1.1: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index e404911d9..70b847808 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -21,6 +21,7 @@ packages: - examples/next-integration - examples/next14-app-router - examples/next15-app-router +- examples/sveltekit catalog: "@cloudflare/workers-types": ^4.20250529.0 From c40b3b0ded17168bdcd1993fcb42d775ac369b2e Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Thu, 28 Aug 2025 13:41:36 +0900 Subject: [PATCH 02/23] Added federation --- examples/sveltekit/src/data/store.ts | 14 +++ examples/sveltekit/src/federation/index.ts | 100 +++++++++++++++++++++ examples/sveltekit/tsconfig.json | 37 ++++---- 3 files changed, 134 insertions(+), 17 deletions(-) create mode 100644 examples/sveltekit/src/data/store.ts create mode 100644 examples/sveltekit/src/federation/index.ts diff --git a/examples/sveltekit/src/data/store.ts b/examples/sveltekit/src/data/store.ts new file mode 100644 index 000000000..ba45c4625 --- /dev/null +++ b/examples/sveltekit/src/data/store.ts @@ -0,0 +1,14 @@ +declare global { + var keyPairsStore: Map>; + var relationStore: Map; +} + +export const keyPairsStore: Map> = + globalThis.keyPairsStore ?? new Map(); +export const relationStore: Map = globalThis.relationStore ?? + new Map(); + +// this is just a hack to demo nextjs +// never do this in production, use safe and secure storage +globalThis.keyPairsStore = keyPairsStore; +globalThis.relationStore = relationStore; diff --git a/examples/sveltekit/src/federation/index.ts b/examples/sveltekit/src/federation/index.ts new file mode 100644 index 000000000..a22024f96 --- /dev/null +++ b/examples/sveltekit/src/federation/index.ts @@ -0,0 +1,100 @@ +import { + Accept, + createFederation, + Endpoints, + Follow, + generateCryptoKeyPair, + MemoryKvStore, + Person, + Undo, +} from "@fedify/fedify"; +import { keyPairsStore, relationStore } from "@/data/store"; + +const federation = createFederation({ + kv: new MemoryKvStore(), +}); + +federation + .setActorDispatcher( + "/users/{identifier}", + async (context, identifier) => { + if (identifier != "demo") { + return null; + } + const keyPairs = await context.getActorKeyPairs(identifier); + return new Person({ + id: context.getActorUri(identifier), + name: "Fedify Demo", + summary: "This is a Fedify Demo account.", + preferredUsername: identifier, + url: new URL("/", context.url), + inbox: context.getInboxUri(identifier), + endpoints: new Endpoints({ + sharedInbox: context.getInboxUri(), + }), + publicKey: keyPairs[0].cryptographicKey, + assertionMethods: keyPairs.map((keyPair) => keyPair.multikey), + }); + }, + ) + .setKeyPairsDispatcher(async (_, identifier) => { + if (identifier != "demo") { + return []; + } + const keyPairs = keyPairsStore.get(identifier); + if (keyPairs) { + return keyPairs; + } + const { privateKey, publicKey } = await generateCryptoKeyPair(); + keyPairsStore.set(identifier, [{ privateKey, publicKey }]); + return [{ privateKey, publicKey }]; + }) /* .mapAlias() */; + +federation + .setInboxListeners("/users/{identifier}/inbox", "/inbox") + .on(Follow, async (context, follow) => { + if ( + follow.id == null || + follow.actorId == null || + follow.objectId == null + ) { + return; + } + const result = context.parseUri(follow.objectId); + if (result?.type !== "actor" || result.identifier !== "demo") { + return; + } + const follower = await follow.getActor(context); + if (follower?.id == null) { + throw new Error("follower is null"); + } + await context.sendActivity( + { identifier: result.identifier }, + follower, + new Accept({ + id: new URL( + `#accepts/${follower.id.href}`, + context.getActorUri("demo"), + ), + actor: follow.objectId, + object: follow, + }), + ); + relationStore.set(follower.id.href, follow.objectId.href); + }) + .on(Undo, async (context, undo) => { + const activity = await undo.getObject(context); + if (activity instanceof Follow) { + if (activity.id == null) { + return; + } + if (undo.actorId == null) { + return; + } + relationStore.delete(undo.actorId.href); + } else { + console.debug(undo); + } + }); + +export default federation; diff --git a/examples/sveltekit/tsconfig.json b/examples/sveltekit/tsconfig.json index a5567ee6b..e0891e0fd 100644 --- a/examples/sveltekit/tsconfig.json +++ b/examples/sveltekit/tsconfig.json @@ -1,19 +1,22 @@ { - "extends": "./.svelte-kit/tsconfig.json", - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "moduleResolution": "bundler" - } - // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias - // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files - // - // To make changes to top-level options such as include and exclude, we recommend extending - // the generated config; see https://svelte.dev/docs/kit/configuration#typescript + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler", + "paths": { + "@/*": ["./src/*"] + } + } + // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias + // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files + // + // To make changes to top-level options such as include and exclude, we recommend extending + // the generated config; see https://svelte.dev/docs/kit/configuration#typescript } From 8d2fe4200753d15cffc576f149bae363bce39bc8 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Thu, 28 Aug 2025 17:30:29 +0900 Subject: [PATCH 03/23] Able to lookup --- examples/sveltekit/package.json | 5 +++-- examples/sveltekit/src/federation/index.ts | 2 +- examples/sveltekit/src/hooks.server.ts | 10 ++++++++++ examples/sveltekit/src/lib/handles.ts | 14 ++++++++++++++ examples/sveltekit/tsconfig.json | 10 +--------- pnpm-lock.yaml | 9 ++++++--- 6 files changed, 35 insertions(+), 15 deletions(-) create mode 100644 examples/sveltekit/src/hooks.server.ts create mode 100644 examples/sveltekit/src/lib/handles.ts diff --git a/examples/sveltekit/package.json b/examples/sveltekit/package.json index abfef71e1..7fb0bf759 100644 --- a/examples/sveltekit/package.json +++ b/examples/sveltekit/package.json @@ -19,8 +19,9 @@ "lint": "eslint ." }, "dependencies": { - "@fedify/fedify": "workspace:^", - "@fedify/sveltekit": "workspace:^" + "@fedify/fedify": "workspace:", + "@fedify/sveltekit": "workspace:", + "x-forwarded-fetch": "^0.2.0" }, "devDependencies": { "@eslint/compat": "^1.2.5", diff --git a/examples/sveltekit/src/federation/index.ts b/examples/sveltekit/src/federation/index.ts index a22024f96..c9a57c490 100644 --- a/examples/sveltekit/src/federation/index.ts +++ b/examples/sveltekit/src/federation/index.ts @@ -8,7 +8,7 @@ import { Person, Undo, } from "@fedify/fedify"; -import { keyPairsStore, relationStore } from "@/data/store"; +import { keyPairsStore, relationStore } from "../data/store"; const federation = createFederation({ kv: new MemoryKvStore(), diff --git a/examples/sveltekit/src/hooks.server.ts b/examples/sveltekit/src/hooks.server.ts new file mode 100644 index 000000000..0e7ea7cf4 --- /dev/null +++ b/examples/sveltekit/src/hooks.server.ts @@ -0,0 +1,10 @@ +import { fedifyHook } from "@fedify/sveltekit"; +import federation from "./federation"; +import { sequence } from "@sveltejs/kit/hooks"; +import { replaceHost } from "./lib/handles"; +import type { Handle } from "@sveltejs/kit"; + +export const handle = sequence( + replaceHost, + fedifyHook(federation, () => {}) as unknown as Handle, +); diff --git a/examples/sveltekit/src/lib/handles.ts b/examples/sveltekit/src/lib/handles.ts new file mode 100644 index 000000000..9d2117a82 --- /dev/null +++ b/examples/sveltekit/src/lib/handles.ts @@ -0,0 +1,14 @@ +import type { Handle } from "@sveltejs/kit"; +import { getXForwardedRequest } from "x-forwarded-fetch"; + +/** + * Replaces the host of the request with the value of the + * x-forwarded-host header, if present. + * If don't use proxy or tunnel, this handle is unnecessary. + * @param input + * @return A new request handler with the host replaced. + */ +export const replaceHost: Handle = async ({ event, resolve }) => { + event.request = await getXForwardedRequest(event.request); + return resolve(event); +}; diff --git a/examples/sveltekit/tsconfig.json b/examples/sveltekit/tsconfig.json index e0891e0fd..43447105a 100644 --- a/examples/sveltekit/tsconfig.json +++ b/examples/sveltekit/tsconfig.json @@ -9,14 +9,6 @@ "skipLibCheck": true, "sourceMap": true, "strict": true, - "moduleResolution": "bundler", - "paths": { - "@/*": ["./src/*"] - } + "moduleResolution": "bundler" } - // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias - // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files - // - // To make changes to top-level options such as include and exclude, we recommend extending - // the generated config; see https://svelte.dev/docs/kit/configuration#typescript } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f08f96587..c16bb6381 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -439,11 +439,14 @@ importers: examples/sveltekit: dependencies: '@fedify/fedify': - specifier: workspace:^ + specifier: 'workspace:' version: link:../../packages/fedify '@fedify/sveltekit': - specifier: workspace:^ + specifier: 'workspace:' version: link:../../packages/sveltekit + x-forwarded-fetch: + specifier: ^0.2.0 + version: 0.2.0 devDependencies: '@eslint/compat': specifier: ^1.2.5 @@ -13862,7 +13865,7 @@ snapshots: dependencies: '@quansync/fs': 0.1.3 defu: 6.1.4 - jiti: 2.4.2 + jiti: 2.5.1 quansync: 0.2.10 uncrypto@0.1.3: {} From ca0f896ad78296c95272b7d1c5530ad524ef0df1 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Thu, 28 Aug 2025 19:06:49 +0900 Subject: [PATCH 04/23] Set prettier --- examples/sveltekit/.prettierignore | 9 ++ examples/sveltekit/.prettierrc | 13 +++ examples/sveltekit/eslint.config.js | 71 ++++++------ examples/sveltekit/package.json | 7 +- examples/sveltekit/src/app.css | 2 +- examples/sveltekit/src/app.d.ts | 14 +-- examples/sveltekit/src/data/store.ts | 10 +- examples/sveltekit/src/federation/index.ts | 41 ++++--- examples/sveltekit/src/routes/+layout.svelte | 10 +- examples/sveltekit/svelte.config.js | 22 ++-- examples/sveltekit/vite.config.ts | 8 +- pnpm-lock.yaml | 107 +++++++++++++++++++ 12 files changed, 224 insertions(+), 90 deletions(-) create mode 100644 examples/sveltekit/.prettierignore create mode 100644 examples/sveltekit/.prettierrc diff --git a/examples/sveltekit/.prettierignore b/examples/sveltekit/.prettierignore new file mode 100644 index 000000000..7d74fe246 --- /dev/null +++ b/examples/sveltekit/.prettierignore @@ -0,0 +1,9 @@ +# Package Managers +package-lock.json +pnpm-lock.yaml +yarn.lock +bun.lock +bun.lockb + +# Miscellaneous +/static/ diff --git a/examples/sveltekit/.prettierrc b/examples/sveltekit/.prettierrc new file mode 100644 index 000000000..b247df413 --- /dev/null +++ b/examples/sveltekit/.prettierrc @@ -0,0 +1,13 @@ +{ + "printWidth": 80, + "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], + "overrides": [ + { + "files": "*.svelte", + "options": { + "parser": "svelte" + } + } + ], + "tailwindStylesheet": "./src/app.css" +} diff --git a/examples/sveltekit/eslint.config.js b/examples/sveltekit/eslint.config.js index 2616f386b..67a4fdd7e 100644 --- a/examples/sveltekit/eslint.config.js +++ b/examples/sveltekit/eslint.config.js @@ -1,39 +1,40 @@ -import { includeIgnoreFile } from '@eslint/compat'; -import js from '@eslint/js'; -import svelte from 'eslint-plugin-svelte'; -import globals from 'globals'; -import { fileURLToPath } from 'node:url'; -import ts from 'typescript-eslint'; -import svelteConfig from './svelte.config.js'; +import prettier from "eslint-config-prettier"; +import { includeIgnoreFile } from "@eslint/compat"; +import js from "@eslint/js"; +import svelte from "eslint-plugin-svelte"; +import globals from "globals"; +import { fileURLToPath } from "node:url"; +import ts from "typescript-eslint"; +import svelteConfig from "./svelte.config.js"; -const gitignorePath = fileURLToPath(new URL('./.gitignore', import.meta.url)); +const gitignorePath = fileURLToPath(new URL("./.gitignore", import.meta.url)); export default ts.config( - includeIgnoreFile(gitignorePath), - js.configs.recommended, - ...ts.configs.recommended, - ...svelte.configs.recommended, - { - languageOptions: { - globals: { ...globals.browser, ...globals.node } - }, - rules: { // typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects. - // see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors - "no-undef": 'off' } - }, - { - files: [ - '**/*.svelte', - '**/*.svelte.ts', - '**/*.svelte.js' - ], - languageOptions: { - parserOptions: { - projectService: true, - extraFileExtensions: ['.svelte'], - parser: ts.parser, - svelteConfig - } - } - } + includeIgnoreFile(gitignorePath), + js.configs.recommended, + ...ts.configs.recommended, + ...svelte.configs.recommended, + prettier, + ...svelte.configs.prettier, + { + languageOptions: { + globals: { ...globals.browser, ...globals.node }, + }, + rules: { + // typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects. + // see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors + "no-undef": "off", + }, + }, + { + files: ["**/*.svelte", "**/*.svelte.ts", "**/*.svelte.js"], + languageOptions: { + parserOptions: { + projectService: true, + extraFileExtensions: [".svelte"], + parser: ts.parser, + svelteConfig, + }, + }, + }, ); diff --git a/examples/sveltekit/package.json b/examples/sveltekit/package.json index 7fb0bf759..f95c67f8f 100644 --- a/examples/sveltekit/package.json +++ b/examples/sveltekit/package.json @@ -16,11 +16,16 @@ "prepare": "svelte-kit sync || echo ''", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "lint": "eslint ." + "format": "prettier --write .", + "lint": "prettier --check . && eslint ." }, "dependencies": { "@fedify/fedify": "workspace:", "@fedify/sveltekit": "workspace:", + "eslint-config-prettier": "^10.1.8", + "prettier": "^3.6.2", + "prettier-plugin-svelte": "^3.4.0", + "prettier-plugin-tailwindcss": "^0.6.14", "x-forwarded-fetch": "^0.2.0" }, "devDependencies": { diff --git a/examples/sveltekit/src/app.css b/examples/sveltekit/src/app.css index d4b507858..f1d8c73cd 100644 --- a/examples/sveltekit/src/app.css +++ b/examples/sveltekit/src/app.css @@ -1 +1 @@ -@import 'tailwindcss'; +@import "tailwindcss"; diff --git a/examples/sveltekit/src/app.d.ts b/examples/sveltekit/src/app.d.ts index da08e6da5..520c4217a 100644 --- a/examples/sveltekit/src/app.d.ts +++ b/examples/sveltekit/src/app.d.ts @@ -1,13 +1,13 @@ // See https://svelte.dev/docs/kit/types#app.d.ts // for information about these interfaces declare global { - namespace App { - // interface Error {} - // interface Locals {} - // interface PageData {} - // interface PageState {} - // interface Platform {} - } + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface PageState {} + // interface Platform {} + } } export {}; diff --git a/examples/sveltekit/src/data/store.ts b/examples/sveltekit/src/data/store.ts index ba45c4625..c674bb93c 100644 --- a/examples/sveltekit/src/data/store.ts +++ b/examples/sveltekit/src/data/store.ts @@ -3,10 +3,12 @@ declare global { var relationStore: Map; } -export const keyPairsStore: Map> = - globalThis.keyPairsStore ?? new Map(); -export const relationStore: Map = globalThis.relationStore ?? - new Map(); +export const keyPairsStore: Map< + string, + Array +> = globalThis.keyPairsStore ?? new Map(); +export const relationStore: Map = + globalThis.relationStore ?? new Map(); // this is just a hack to demo nextjs // never do this in production, use safe and secure storage diff --git a/examples/sveltekit/src/federation/index.ts b/examples/sveltekit/src/federation/index.ts index c9a57c490..880a2686a 100644 --- a/examples/sveltekit/src/federation/index.ts +++ b/examples/sveltekit/src/federation/index.ts @@ -15,28 +15,25 @@ const federation = createFederation({ }); federation - .setActorDispatcher( - "/users/{identifier}", - async (context, identifier) => { - if (identifier != "demo") { - return null; - } - const keyPairs = await context.getActorKeyPairs(identifier); - return new Person({ - id: context.getActorUri(identifier), - name: "Fedify Demo", - summary: "This is a Fedify Demo account.", - preferredUsername: identifier, - url: new URL("/", context.url), - inbox: context.getInboxUri(identifier), - endpoints: new Endpoints({ - sharedInbox: context.getInboxUri(), - }), - publicKey: keyPairs[0].cryptographicKey, - assertionMethods: keyPairs.map((keyPair) => keyPair.multikey), - }); - }, - ) + .setActorDispatcher("/users/{identifier}", async (context, identifier) => { + if (identifier != "demo") { + return null; + } + const keyPairs = await context.getActorKeyPairs(identifier); + return new Person({ + id: context.getActorUri(identifier), + name: "Fedify Demo", + summary: "This is a Fedify Demo account.", + preferredUsername: identifier, + url: new URL("/", context.url), + inbox: context.getInboxUri(identifier), + endpoints: new Endpoints({ + sharedInbox: context.getInboxUri(), + }), + publicKey: keyPairs[0].cryptographicKey, + assertionMethods: keyPairs.map((keyPair) => keyPair.multikey), + }); + }) .setKeyPairsDispatcher(async (_, identifier) => { if (identifier != "demo") { return []; diff --git a/examples/sveltekit/src/routes/+layout.svelte b/examples/sveltekit/src/routes/+layout.svelte index 9cba825ad..ed4add1cb 100644 --- a/examples/sveltekit/src/routes/+layout.svelte +++ b/examples/sveltekit/src/routes/+layout.svelte @@ -1,12 +1,12 @@ - + {@render children?.()} diff --git a/examples/sveltekit/svelte.config.js b/examples/sveltekit/svelte.config.js index 1295460d1..a8bb58ace 100644 --- a/examples/sveltekit/svelte.config.js +++ b/examples/sveltekit/svelte.config.js @@ -1,18 +1,18 @@ -import adapter from '@sveltejs/adapter-auto'; -import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; +import adapter from "@sveltejs/adapter-auto"; +import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; /** @type {import('@sveltejs/kit').Config} */ const config = { - // Consult https://svelte.dev/docs/kit/integrations - // for more information about preprocessors - preprocess: vitePreprocess(), + // Consult https://svelte.dev/docs/kit/integrations + // for more information about preprocessors + preprocess: vitePreprocess(), - kit: { - // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list. - // If your environment is not supported, or you settled on a specific environment, switch out the adapter. - // See https://svelte.dev/docs/kit/adapters for more information about adapters. - adapter: adapter() - } + kit: { + // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list. + // If your environment is not supported, or you settled on a specific environment, switch out the adapter. + // See https://svelte.dev/docs/kit/adapters for more information about adapters. + adapter: adapter(), + }, }; export default config; diff --git a/examples/sveltekit/vite.config.ts b/examples/sveltekit/vite.config.ts index 2d35c4f5a..86683174d 100644 --- a/examples/sveltekit/vite.config.ts +++ b/examples/sveltekit/vite.config.ts @@ -1,7 +1,7 @@ -import tailwindcss from '@tailwindcss/vite'; -import { sveltekit } from '@sveltejs/kit/vite'; -import { defineConfig } from 'vite'; +import tailwindcss from "@tailwindcss/vite"; +import { sveltekit } from "@sveltejs/kit/vite"; +import { defineConfig } from "vite"; export default defineConfig({ - plugins: [tailwindcss(), sveltekit()] + plugins: [tailwindcss(), sveltekit()], }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c16bb6381..edbc95f83 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -444,6 +444,18 @@ importers: '@fedify/sveltekit': specifier: 'workspace:' version: link:../../packages/sveltekit + eslint-config-prettier: + specifier: ^10.1.8 + version: 10.1.8(eslint@9.32.0(jiti@2.5.1)) + prettier: + specifier: ^3.6.2 + version: 3.6.2 + prettier-plugin-svelte: + specifier: ^3.4.0 + version: 3.4.0(prettier@3.6.2)(svelte@5.38.3) + prettier-plugin-tailwindcss: + specifier: ^0.6.14 + version: 0.6.14(prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.38.3))(prettier@3.6.2) x-forwarded-fetch: specifier: ^0.2.0 version: 0.2.0 @@ -4557,6 +4569,12 @@ packages: typescript: optional: true + eslint-config-prettier@10.1.8: + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} @@ -6121,6 +6139,78 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + prettier-plugin-svelte@3.4.0: + resolution: {integrity: sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==} + peerDependencies: + prettier: ^3.0.0 + svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 + + prettier-plugin-tailwindcss@0.6.14: + resolution: {integrity: sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg==} + engines: {node: '>=14.21.3'} + peerDependencies: + '@ianvs/prettier-plugin-sort-imports': '*' + '@prettier/plugin-hermes': '*' + '@prettier/plugin-oxc': '*' + '@prettier/plugin-pug': '*' + '@shopify/prettier-plugin-liquid': '*' + '@trivago/prettier-plugin-sort-imports': '*' + '@zackad/prettier-plugin-twig': '*' + prettier: ^3.0 + prettier-plugin-astro: '*' + prettier-plugin-css-order: '*' + prettier-plugin-import-sort: '*' + prettier-plugin-jsdoc: '*' + prettier-plugin-marko: '*' + prettier-plugin-multiline-arrays: '*' + prettier-plugin-organize-attributes: '*' + prettier-plugin-organize-imports: '*' + prettier-plugin-sort-imports: '*' + prettier-plugin-style-order: '*' + prettier-plugin-svelte: '*' + peerDependenciesMeta: + '@ianvs/prettier-plugin-sort-imports': + optional: true + '@prettier/plugin-hermes': + optional: true + '@prettier/plugin-oxc': + optional: true + '@prettier/plugin-pug': + optional: true + '@shopify/prettier-plugin-liquid': + optional: true + '@trivago/prettier-plugin-sort-imports': + optional: true + '@zackad/prettier-plugin-twig': + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-css-order: + optional: true + prettier-plugin-import-sort: + optional: true + prettier-plugin-jsdoc: + optional: true + prettier-plugin-marko: + optional: true + prettier-plugin-multiline-arrays: + optional: true + prettier-plugin-organize-attributes: + optional: true + prettier-plugin-organize-imports: + optional: true + prettier-plugin-sort-imports: + optional: true + prettier-plugin-style-order: + optional: true + prettier-plugin-svelte: + optional: true + + prettier@3.6.2: + resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} + engines: {node: '>=14'} + hasBin: true + printable-characters@1.0.42: resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} @@ -10971,6 +11061,10 @@ snapshots: - eslint-plugin-import-x - supports-color + eslint-config-prettier@10.1.8(eslint@9.32.0(jiti@2.5.1)): + dependencies: + eslint: 9.32.0(jiti@2.5.1) + eslint-import-resolver-node@0.3.9: dependencies: debug: 3.2.7 @@ -12914,6 +13008,19 @@ snapshots: prelude-ls@1.2.1: {} + prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.38.3): + dependencies: + prettier: 3.6.2 + svelte: 5.38.3 + + prettier-plugin-tailwindcss@0.6.14(prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.38.3))(prettier@3.6.2): + dependencies: + prettier: 3.6.2 + optionalDependencies: + prettier-plugin-svelte: 3.4.0(prettier@3.6.2)(svelte@5.38.3) + + prettier@3.6.2: {} + printable-characters@1.0.42: {} prop-types@15.8.1: From 5d5d90b50a97e2aec24fcf99849e264e73aaeacf Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Thu, 28 Aug 2025 20:14:11 +0900 Subject: [PATCH 05/23] Completed root page --- examples/sveltekit/src/app.css | 23 ++ examples/sveltekit/src/app.html | 33 ++- examples/sveltekit/src/lib/assets/favicon.svg | 174 ++++++++++++++- examples/sveltekit/src/routes/+page.server.ts | 14 ++ examples/sveltekit/src/routes/+page.svelte | 77 ++++++- examples/sveltekit/static/fedify-logo.svg | 206 ++++++++++++++++++ .../sveltekit/static/fedify-svelte-logo.svg | 173 +++++++++++++++ .../sveltekit/static/svelte-horizontal.svg | 1 + packages/sveltekit/package.json | 1 + 9 files changed, 691 insertions(+), 11 deletions(-) create mode 100644 examples/sveltekit/src/routes/+page.server.ts create mode 100644 examples/sveltekit/static/fedify-logo.svg create mode 100644 examples/sveltekit/static/fedify-svelte-logo.svg create mode 100644 examples/sveltekit/static/svelte-horizontal.svg diff --git a/examples/sveltekit/src/app.css b/examples/sveltekit/src/app.css index f1d8c73cd..a8e6f63e8 100644 --- a/examples/sveltekit/src/app.css +++ b/examples/sveltekit/src/app.css @@ -1 +1,24 @@ @import "tailwindcss"; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +body { + background: var(--background); + color: var(--foreground); + font-family: Arial, Helvetica, sans-serif; +} diff --git a/examples/sveltekit/src/app.html b/examples/sveltekit/src/app.html index f273cc58f..8eb44cef7 100644 --- a/examples/sveltekit/src/app.html +++ b/examples/sveltekit/src/app.html @@ -1,11 +1,28 @@ - - - - %sveltekit.head% - - -
%sveltekit.body%
- + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + + diff --git a/examples/sveltekit/src/lib/assets/favicon.svg b/examples/sveltekit/src/lib/assets/favicon.svg index cc5dc66a3..73186fe23 100644 --- a/examples/sveltekit/src/lib/assets/favicon.svg +++ b/examples/sveltekit/src/lib/assets/favicon.svg @@ -1 +1,173 @@ -svelte-logo \ No newline at end of file + +FedifyFedify diff --git a/examples/sveltekit/src/routes/+page.server.ts b/examples/sveltekit/src/routes/+page.server.ts new file mode 100644 index 000000000..f03e03273 --- /dev/null +++ b/examples/sveltekit/src/routes/+page.server.ts @@ -0,0 +1,14 @@ +import type { PageServerLoad } from "./$types"; +import { relationStore } from "../data/store"; + +export const load: PageServerLoad = async ({ request, url }) => { + const forwardedHost = request.headers.get("x-forwarded-host"); + const host = forwardedHost || request.headers.get("host") || url.host; + + const addresses = Array.from(relationStore.keys()); + + return { + host, + addresses, + }; +}; diff --git a/examples/sveltekit/src/routes/+page.svelte b/examples/sveltekit/src/routes/+page.svelte index cc88df0ea..778e77e10 100644 --- a/examples/sveltekit/src/routes/+page.svelte +++ b/examples/sveltekit/src/routes/+page.svelte @@ -1,2 +1,75 @@ -

Welcome to SvelteKit

-

Visit svelte.dev/docs/kit to read the documentation

+ + +
+ @fedify/svelte Logo +
+ {bannerText} + + with + + Next.js + +
+

+ This small federated server app is a demo of + + Fedify logoFedify. The only one thing it does is to accept follow requests. +

+

+ You can follow this demo app via the below handle:{" "} + + @demo@{host} + +

+ + {#if addresses.length === 0} +

+ No followers yet. Try to add a follower using{" "} + + ActivityPub.Academy + . +

+ {:else} +

This account has the below {addresses.length} followers:

+
    + {#each addresses as address} +
  • + {address} +
  • + {/each} +
+ {/if} +
diff --git a/examples/sveltekit/static/fedify-logo.svg b/examples/sveltekit/static/fedify-logo.svg new file mode 100644 index 000000000..5bd9e2755 --- /dev/null +++ b/examples/sveltekit/static/fedify-logo.svg @@ -0,0 +1,206 @@ + + + + + + + + Fedify + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fedify + + + + \ No newline at end of file diff --git a/examples/sveltekit/static/fedify-svelte-logo.svg b/examples/sveltekit/static/fedify-svelte-logo.svg new file mode 100644 index 000000000..73186fe23 --- /dev/null +++ b/examples/sveltekit/static/fedify-svelte-logo.svg @@ -0,0 +1,173 @@ + +FedifyFedify diff --git a/examples/sveltekit/static/svelte-horizontal.svg b/examples/sveltekit/static/svelte-horizontal.svg new file mode 100644 index 000000000..3a9742c5b --- /dev/null +++ b/examples/sveltekit/static/svelte-horizontal.svg @@ -0,0 +1 @@ +svelte-horizontal \ No newline at end of file diff --git a/packages/sveltekit/package.json b/packages/sveltekit/package.json index a3ea1e6c0..38503f135 100644 --- a/packages/sveltekit/package.json +++ b/packages/sveltekit/package.json @@ -63,6 +63,7 @@ "build": "tsdown", "prepack": "tsdown", "prepublish": "tsdown", + "dev": "tsdown --watch", "test": "deno task codegen && tsdown && cd dist/ && node --test" } } From c49ab4ad53b37c3f24a18a7819077561fa20a4c4 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Thu, 28 Aug 2025 11:18:53 +0000 Subject: [PATCH 06/23] Renamed example --- .../.gitignore | 0 .../{sveltekit => sveltekit-sample}/.npmrc | 0 .../.prettierignore | 0 .../.prettierrc | 0 .../{sveltekit => sveltekit-sample}/README.md | 0 .../eslint.config.js | 0 .../package.json | 0 .../src/app.css | 0 .../src/app.d.ts | 0 .../src/app.html | 0 .../src/data/store.ts | 0 .../src/federation/index.ts | 0 .../src/hooks.server.ts | 0 .../src/lib/assets/favicon.svg | 0 .../src/lib/handles.ts | 0 .../src/lib/index.ts | 0 .../src/routes/+layout.svelte | 0 .../src/routes/+page.server.ts | 0 .../src/routes/+page.svelte | 0 .../static/fedify-logo.svg | 0 .../static/fedify-svelte-logo.svg | 0 .../static/robots.txt | 0 .../static/svelte-horizontal.svg | 0 .../svelte.config.js | 0 .../tsconfig.json | 0 .../vite.config.ts | 0 pnpm-lock.yaml | 22 +++++-------------- pnpm-workspace.yaml | 2 +- 28 files changed, 6 insertions(+), 18 deletions(-) rename examples/{sveltekit => sveltekit-sample}/.gitignore (100%) rename examples/{sveltekit => sveltekit-sample}/.npmrc (100%) rename examples/{sveltekit => sveltekit-sample}/.prettierignore (100%) rename examples/{sveltekit => sveltekit-sample}/.prettierrc (100%) rename examples/{sveltekit => sveltekit-sample}/README.md (100%) rename examples/{sveltekit => sveltekit-sample}/eslint.config.js (100%) rename examples/{sveltekit => sveltekit-sample}/package.json (100%) rename examples/{sveltekit => sveltekit-sample}/src/app.css (100%) rename examples/{sveltekit => sveltekit-sample}/src/app.d.ts (100%) rename examples/{sveltekit => sveltekit-sample}/src/app.html (100%) rename examples/{sveltekit => sveltekit-sample}/src/data/store.ts (100%) rename examples/{sveltekit => sveltekit-sample}/src/federation/index.ts (100%) rename examples/{sveltekit => sveltekit-sample}/src/hooks.server.ts (100%) rename examples/{sveltekit => sveltekit-sample}/src/lib/assets/favicon.svg (100%) rename examples/{sveltekit => sveltekit-sample}/src/lib/handles.ts (100%) rename examples/{sveltekit => sveltekit-sample}/src/lib/index.ts (100%) rename examples/{sveltekit => sveltekit-sample}/src/routes/+layout.svelte (100%) rename examples/{sveltekit => sveltekit-sample}/src/routes/+page.server.ts (100%) rename examples/{sveltekit => sveltekit-sample}/src/routes/+page.svelte (100%) rename examples/{sveltekit => sveltekit-sample}/static/fedify-logo.svg (100%) rename examples/{sveltekit => sveltekit-sample}/static/fedify-svelte-logo.svg (100%) rename examples/{sveltekit => sveltekit-sample}/static/robots.txt (100%) rename examples/{sveltekit => sveltekit-sample}/static/svelte-horizontal.svg (100%) rename examples/{sveltekit => sveltekit-sample}/svelte.config.js (100%) rename examples/{sveltekit => sveltekit-sample}/tsconfig.json (100%) rename examples/{sveltekit => sveltekit-sample}/vite.config.ts (100%) diff --git a/examples/sveltekit/.gitignore b/examples/sveltekit-sample/.gitignore similarity index 100% rename from examples/sveltekit/.gitignore rename to examples/sveltekit-sample/.gitignore diff --git a/examples/sveltekit/.npmrc b/examples/sveltekit-sample/.npmrc similarity index 100% rename from examples/sveltekit/.npmrc rename to examples/sveltekit-sample/.npmrc diff --git a/examples/sveltekit/.prettierignore b/examples/sveltekit-sample/.prettierignore similarity index 100% rename from examples/sveltekit/.prettierignore rename to examples/sveltekit-sample/.prettierignore diff --git a/examples/sveltekit/.prettierrc b/examples/sveltekit-sample/.prettierrc similarity index 100% rename from examples/sveltekit/.prettierrc rename to examples/sveltekit-sample/.prettierrc diff --git a/examples/sveltekit/README.md b/examples/sveltekit-sample/README.md similarity index 100% rename from examples/sveltekit/README.md rename to examples/sveltekit-sample/README.md diff --git a/examples/sveltekit/eslint.config.js b/examples/sveltekit-sample/eslint.config.js similarity index 100% rename from examples/sveltekit/eslint.config.js rename to examples/sveltekit-sample/eslint.config.js diff --git a/examples/sveltekit/package.json b/examples/sveltekit-sample/package.json similarity index 100% rename from examples/sveltekit/package.json rename to examples/sveltekit-sample/package.json diff --git a/examples/sveltekit/src/app.css b/examples/sveltekit-sample/src/app.css similarity index 100% rename from examples/sveltekit/src/app.css rename to examples/sveltekit-sample/src/app.css diff --git a/examples/sveltekit/src/app.d.ts b/examples/sveltekit-sample/src/app.d.ts similarity index 100% rename from examples/sveltekit/src/app.d.ts rename to examples/sveltekit-sample/src/app.d.ts diff --git a/examples/sveltekit/src/app.html b/examples/sveltekit-sample/src/app.html similarity index 100% rename from examples/sveltekit/src/app.html rename to examples/sveltekit-sample/src/app.html diff --git a/examples/sveltekit/src/data/store.ts b/examples/sveltekit-sample/src/data/store.ts similarity index 100% rename from examples/sveltekit/src/data/store.ts rename to examples/sveltekit-sample/src/data/store.ts diff --git a/examples/sveltekit/src/federation/index.ts b/examples/sveltekit-sample/src/federation/index.ts similarity index 100% rename from examples/sveltekit/src/federation/index.ts rename to examples/sveltekit-sample/src/federation/index.ts diff --git a/examples/sveltekit/src/hooks.server.ts b/examples/sveltekit-sample/src/hooks.server.ts similarity index 100% rename from examples/sveltekit/src/hooks.server.ts rename to examples/sveltekit-sample/src/hooks.server.ts diff --git a/examples/sveltekit/src/lib/assets/favicon.svg b/examples/sveltekit-sample/src/lib/assets/favicon.svg similarity index 100% rename from examples/sveltekit/src/lib/assets/favicon.svg rename to examples/sveltekit-sample/src/lib/assets/favicon.svg diff --git a/examples/sveltekit/src/lib/handles.ts b/examples/sveltekit-sample/src/lib/handles.ts similarity index 100% rename from examples/sveltekit/src/lib/handles.ts rename to examples/sveltekit-sample/src/lib/handles.ts diff --git a/examples/sveltekit/src/lib/index.ts b/examples/sveltekit-sample/src/lib/index.ts similarity index 100% rename from examples/sveltekit/src/lib/index.ts rename to examples/sveltekit-sample/src/lib/index.ts diff --git a/examples/sveltekit/src/routes/+layout.svelte b/examples/sveltekit-sample/src/routes/+layout.svelte similarity index 100% rename from examples/sveltekit/src/routes/+layout.svelte rename to examples/sveltekit-sample/src/routes/+layout.svelte diff --git a/examples/sveltekit/src/routes/+page.server.ts b/examples/sveltekit-sample/src/routes/+page.server.ts similarity index 100% rename from examples/sveltekit/src/routes/+page.server.ts rename to examples/sveltekit-sample/src/routes/+page.server.ts diff --git a/examples/sveltekit/src/routes/+page.svelte b/examples/sveltekit-sample/src/routes/+page.svelte similarity index 100% rename from examples/sveltekit/src/routes/+page.svelte rename to examples/sveltekit-sample/src/routes/+page.svelte diff --git a/examples/sveltekit/static/fedify-logo.svg b/examples/sveltekit-sample/static/fedify-logo.svg similarity index 100% rename from examples/sveltekit/static/fedify-logo.svg rename to examples/sveltekit-sample/static/fedify-logo.svg diff --git a/examples/sveltekit/static/fedify-svelte-logo.svg b/examples/sveltekit-sample/static/fedify-svelte-logo.svg similarity index 100% rename from examples/sveltekit/static/fedify-svelte-logo.svg rename to examples/sveltekit-sample/static/fedify-svelte-logo.svg diff --git a/examples/sveltekit/static/robots.txt b/examples/sveltekit-sample/static/robots.txt similarity index 100% rename from examples/sveltekit/static/robots.txt rename to examples/sveltekit-sample/static/robots.txt diff --git a/examples/sveltekit/static/svelte-horizontal.svg b/examples/sveltekit-sample/static/svelte-horizontal.svg similarity index 100% rename from examples/sveltekit/static/svelte-horizontal.svg rename to examples/sveltekit-sample/static/svelte-horizontal.svg diff --git a/examples/sveltekit/svelte.config.js b/examples/sveltekit-sample/svelte.config.js similarity index 100% rename from examples/sveltekit/svelte.config.js rename to examples/sveltekit-sample/svelte.config.js diff --git a/examples/sveltekit/tsconfig.json b/examples/sveltekit-sample/tsconfig.json similarity index 100% rename from examples/sveltekit/tsconfig.json rename to examples/sveltekit-sample/tsconfig.json diff --git a/examples/sveltekit/vite.config.ts b/examples/sveltekit-sample/vite.config.ts similarity index 100% rename from examples/sveltekit/vite.config.ts rename to examples/sveltekit-sample/vite.config.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index edbc95f83..b96971241 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -436,7 +436,7 @@ importers: specifier: 'catalog:' version: 5.9.2 - examples/sveltekit: + examples/sveltekit-sample: dependencies: '@fedify/fedify': specifier: 'workspace:' @@ -495,7 +495,7 @@ importers: version: 4.3.1(picomatch@4.0.3)(svelte@5.38.3)(typescript@5.9.2) tailwindcss: specifier: ^4.0.0 - version: 4.1.11 + version: 4.1.12 typescript: specifier: ^5.0.0 version: 5.9.2 @@ -4790,14 +4790,6 @@ packages: fault@2.0.1: resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} - fdir@6.4.6: - resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -9696,8 +9688,8 @@ snapshots: '@typescript-eslint/project-service@8.38.0(typescript@5.9.2)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.38.0(typescript@5.9.2) - '@typescript-eslint/types': 8.38.0 + '@typescript-eslint/tsconfig-utils': 8.41.0(typescript@5.9.2) + '@typescript-eslint/types': 8.41.0 debug: 4.4.1 typescript: 5.9.2 transitivePeerDependencies: @@ -11514,10 +11506,6 @@ snapshots: dependencies: format: 0.2.2 - fdir@6.4.6(picomatch@4.0.3): - optionalDependencies: - picomatch: 4.0.3 - fdir@6.5.0(picomatch@4.0.3): optionalDependencies: picomatch: 4.0.3 @@ -13692,7 +13680,7 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.28 chokidar: 4.0.3 - fdir: 6.4.6(picomatch@4.0.3) + fdir: 6.5.0(picomatch@4.0.3) picocolors: 1.1.1 sade: 1.8.1 svelte: 5.38.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 70b847808..cd4eeecaa 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -21,7 +21,7 @@ packages: - examples/next-integration - examples/next14-app-router - examples/next15-app-router -- examples/sveltekit +- examples/sveltekit-sample catalog: "@cloudflare/workers-types": ^4.20250529.0 From e8659dc058235b094858c18f9b6946201f4fbce6 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Fri, 29 Aug 2025 14:15:09 +0900 Subject: [PATCH 07/23] Added demo profile image --- .../sveltekit-sample/src/federation/index.ts | 16 +++++++++------- .../sveltekit-sample/static/demo-profile.png | Bin 0 -> 53098 bytes 2 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 examples/sveltekit-sample/static/demo-profile.png diff --git a/examples/sveltekit-sample/src/federation/index.ts b/examples/sveltekit-sample/src/federation/index.ts index 880a2686a..e5703de9b 100644 --- a/examples/sveltekit-sample/src/federation/index.ts +++ b/examples/sveltekit-sample/src/federation/index.ts @@ -4,6 +4,7 @@ import { Endpoints, Follow, generateCryptoKeyPair, + Image, MemoryKvStore, Person, Undo, @@ -14,9 +15,11 @@ const federation = createFederation({ kv: new MemoryKvStore(), }); +const IDENTIFIER = "demo"; + federation .setActorDispatcher("/users/{identifier}", async (context, identifier) => { - if (identifier != "demo") { + if (identifier != IDENTIFIER) { return null; } const keyPairs = await context.getActorKeyPairs(identifier); @@ -25,17 +28,16 @@ federation name: "Fedify Demo", summary: "This is a Fedify Demo account.", preferredUsername: identifier, + icon: new Image({ url: new URL("/demo-profile.png", context.url) }), url: new URL("/", context.url), inbox: context.getInboxUri(identifier), - endpoints: new Endpoints({ - sharedInbox: context.getInboxUri(), - }), + endpoints: new Endpoints({ sharedInbox: context.getInboxUri() }), publicKey: keyPairs[0].cryptographicKey, assertionMethods: keyPairs.map((keyPair) => keyPair.multikey), }); }) .setKeyPairsDispatcher(async (_, identifier) => { - if (identifier != "demo") { + if (identifier != IDENTIFIER) { return []; } const keyPairs = keyPairsStore.get(identifier); @@ -58,7 +60,7 @@ federation return; } const result = context.parseUri(follow.objectId); - if (result?.type !== "actor" || result.identifier !== "demo") { + if (result?.type !== "actor" || result.identifier !== IDENTIFIER) { return; } const follower = await follow.getActor(context); @@ -71,7 +73,7 @@ federation new Accept({ id: new URL( `#accepts/${follower.id.href}`, - context.getActorUri("demo"), + context.getActorUri(IDENTIFIER), ), actor: follow.objectId, object: follow, diff --git a/examples/sveltekit-sample/static/demo-profile.png b/examples/sveltekit-sample/static/demo-profile.png new file mode 100644 index 0000000000000000000000000000000000000000..131837df387665ebe6edc8fbc5c83c8741c8ed29 GIT binary patch literal 53098 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 literal 0 HcmV?d00001 From a621ef7147902058452cde59699cba51c7e9d882 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Fri, 29 Aug 2025 14:16:51 +0900 Subject: [PATCH 08/23] Added demo profile page --- examples/sveltekit-sample/src/app.css | 110 +++++++++++++++++- .../sveltekit-sample/src/routes/+page.svelte | 11 +- .../routes/users/[identifier]/+page.svelte | 92 +++++++++++++++ examples/sveltekit-sample/svelte.config.js | 1 - 4 files changed, 204 insertions(+), 10 deletions(-) create mode 100644 examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte diff --git a/examples/sveltekit-sample/src/app.css b/examples/sveltekit-sample/src/app.css index a8e6f63e8..8d4a9ef48 100644 --- a/examples/sveltekit-sample/src/app.css +++ b/examples/sveltekit-sample/src/app.css @@ -20,5 +20,113 @@ body { background: var(--background); color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; + font-size: 16px; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, + Cantarell, sans-serif; +} + +@layer components { + .profile-container { + @apply mx-auto flex h-svh max-w-4xl flex-col content-center justify-center p-8; + } + + .profile-header { + @apply mb-8 flex gap-8 rounded-2xl p-8 text-white; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + } + + .avatar-section { + @apply flex-shrink-0; + } + + .avatar { + @apply mx-auto h-30 w-30 rounded-full object-cover; + border: 4px solid rgba(255, 255, 255, 0.2); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2); + } + + .user-info { + @apply flex flex-1 flex-col justify-center; + } + + .user-name { + @apply mb-2 text-4xl font-bold; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + margin: 0 0 0.5rem 0; + } + + .user-handle { + @apply mb-4 text-xl font-medium; + opacity: 0.9; + } + + .user-bio { + @apply text-lg leading-relaxed; + opacity: 0.95; + margin: 0; + } + + .profile-content { + @apply grid gap-8; + } + + .info-card { + @apply rounded-xl border bg-background p-8 text-foreground; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); + border-color: rgba(0, 0, 0, 0.05); + } + + .info-card h3 { + @apply mb-6 text-2xl font-semibold; + margin: 0 0 1.5rem 0; + } + + .info-grid { + @apply grid gap-4; + } + + .info-item { + @apply flex flex-col justify-between border-b py-3; + border-color: rgba(0, 0, 0, 0.05); + } + + .info-item:last-child { + @apply border-b-0; + } + + .info-label { + @apply text-sm font-semibold; + color: color-mix(in srgb, var(--foreground) 60%, transparent); + } + + .fedify-anchor { + @apply h-6 rounded-md bg-sky-300 px-1 py-0.5 font-medium text-white; + &:before { + @apply mr-1 mb-1 inline-block size-4 align-middle; + content: ""; + background-image: url("/fedify-logo.svg"); + background-size: 16px 16px; + } + } + + /* 반응형 스타일 */ + @media (max-width: 768px) { + .profile-container { + @apply p-4; + } + + .profile-header { + @apply flex-col content-center gap-4 text-center; + } + + .user-name { + @apply text-3xl; + } + + .info-item { + @apply flex-col items-start gap-1; + } + } } diff --git a/examples/sveltekit-sample/src/routes/+page.svelte b/examples/sveltekit-sample/src/routes/+page.svelte index 778e77e10..91ced1c87 100644 --- a/examples/sveltekit-sample/src/routes/+page.svelte +++ b/examples/sveltekit-sample/src/routes/+page.svelte @@ -31,17 +31,12 @@ alt="Next.js" class="inline-block w-24" /> - + +

This small federated server app is a demo of - - Fedify logoFedifyFedify. The only one thing it does is to accept follow requests.

diff --git a/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte b/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte new file mode 100644 index 000000000..34465cfa2 --- /dev/null +++ b/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte @@ -0,0 +1,92 @@ + + +{#await data} + +

+ +
+{:then user} + {#if user} +
+
+
+ {user.name}'s profile +
+ +
+ +
+
+

Profile Information

+
+
+ Information + This profile is demo for + + Fedify + + Next.js + integration. + +
+
+
+
+
+ {/if} +{:catch} +

404 Not found

+{/await} diff --git a/examples/sveltekit-sample/svelte.config.js b/examples/sveltekit-sample/svelte.config.js index a8bb58ace..0c41bab48 100644 --- a/examples/sveltekit-sample/svelte.config.js +++ b/examples/sveltekit-sample/svelte.config.js @@ -6,7 +6,6 @@ const config = { // Consult https://svelte.dev/docs/kit/integrations // for more information about preprocessors preprocess: vitePreprocess(), - kit: { // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list. // If your environment is not supported, or you settled on a specific environment, switch out the adapter. From 38cce9918046f1329ee944cb4772d18975902e17 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Fri, 29 Aug 2025 14:20:11 +0900 Subject: [PATCH 09/23] Moved federation file --- examples/sveltekit-sample/src/hooks.server.ts | 2 +- .../src/{federation/index.ts => lib/federation.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename examples/sveltekit-sample/src/{federation/index.ts => lib/federation.ts} (100%) diff --git a/examples/sveltekit-sample/src/hooks.server.ts b/examples/sveltekit-sample/src/hooks.server.ts index 0e7ea7cf4..f978d75ba 100644 --- a/examples/sveltekit-sample/src/hooks.server.ts +++ b/examples/sveltekit-sample/src/hooks.server.ts @@ -1,5 +1,5 @@ import { fedifyHook } from "@fedify/sveltekit"; -import federation from "./federation"; +import federation from "./lib/federation"; import { sequence } from "@sveltejs/kit/hooks"; import { replaceHost } from "./lib/handles"; import type { Handle } from "@sveltejs/kit"; diff --git a/examples/sveltekit-sample/src/federation/index.ts b/examples/sveltekit-sample/src/lib/federation.ts similarity index 100% rename from examples/sveltekit-sample/src/federation/index.ts rename to examples/sveltekit-sample/src/lib/federation.ts From 7528ca2276278325c8732c7134e602cef06b76dc Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Fri, 29 Aug 2025 16:56:27 +0900 Subject: [PATCH 10/23] Wrote README.md --- examples/sveltekit-sample/README.md | 269 +++++++++++++++++-- examples/sveltekit-sample/src/lib/handles.ts | 2 +- 2 files changed, 249 insertions(+), 22 deletions(-) diff --git a/examples/sveltekit-sample/README.md b/examples/sveltekit-sample/README.md index 75842c404..5e109b7e9 100644 --- a/examples/sveltekit-sample/README.md +++ b/examples/sveltekit-sample/README.md @@ -1,38 +1,265 @@ -# sv +SvelteKit Sample +================ -Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli). +A comprehensive example of building a federated server application using [Fedify](https://fedify.dev) with [SvelteKit](https://kit.svelte.dev/). This sample demonstrates how to create an ActivityPub-compatible federated social media server that can interact with other federated platforms like Mastodon, Pleroma, and other ActivityPub implementations. -## Creating a project +🚀 Features +----------- -If you're seeing this, you've probably already done this step. Congrats! +- **ActivityPub Protocol Support**: Full implementation of ActivityPub for federated social networking +- **Actor System**: User profile management with cryptographic key pairs +- **Follow/Unfollow**: Complete follow relationship handling with Accept/Undo activities +- **Inbox Processing**: Real-time activity processing from federated instances +- **Modern UI**: Built with SvelteKit and Tailwind CSS +- **TypeScript**: Full type safety throughout the application -```sh -# create a new project in the current directory -npx sv create +📋 Prerequisites +---------------- -# create a new project in my-app -npx sv create my-app +Before you begin, ensure you have the following installed: + +- **Node.js** (version 18 or higher) +- **npm** or **yarn** package manager +- **Git** for version control + +🛠️ Setup and Installation +------------------------- + +### 1. Clone the Repository + +```bash +git clone https://github.com/fedify-dev/fedify.git +cd fedify/examples/sveltekit-sample +``` + +### 2. Install Dependencies + +```bash +pnpm install +``` + +### 3. Environment Setup + +The application uses in-memory storage by default, so no additional database setup is required for development. However, for production deployment, you may want to configure external storage. + +🏃 Development Server +--------------------- + +### Start the Development Server + +```bash +pnpm dev +``` + +The development server will start on `http://localhost:5173` by default. + +⚙️ Configuration Options +------------------------ + +### Federation Configuration + +The federation setup is configured in `src/lib/federation.ts`: + +```typescript +const federation = createFederation({ + kv: new MemoryKvStore(), // In-memory storage for development +}); +``` + +#### Key Configuration Options: + +1. **Storage Backend**: + - Development: `MemoryKvStore()` (data lost on restart) + - Production: Consider using persistent storage solutions + +2. **Actor Identifier**: + - Default: `"demo"` + - Modify the `IDENTIFIER` constant to change the demo user + +3. **Demo Actor Profile**: + - Name: "Fedify Demo" + - Summary: "This is a Fedify Demo account." + - Icon: `/demo-profile.png` + +### Server Configuration + +#### Proxy/Tunnel Support + +The application includes support for proxy headers via `x-forwarded-fetch`. This is configured in `src/lib/handles.ts`: + +```typescript +export const replaceHost: Handle = async ({ event, resolve }) => { + event.request = await getXForwardedRequest(event.request); + return resolve(event); +}; +``` + +This is useful when deploying behind reverse proxies or using tunneling services like ngrok. + +But if you don't use proxy or tunnel, the handle is unnecessary. + +📚 Example Usage Scenarios +------------------------- + +### 1. Basic Federation Testing + +1. Start the development server: + + ```bash + npm run dev + ``` + +2. Access the demo user profile: + + ``` + curl http://localhost:5173/users/demo + ``` + +3. The ActivityPub actor endpoint is available at: + ``` + curl -H "Accept: application/activity+json" http://localhost:5173/users/demo + ``` + +### 2. Following from `activitypub.academy` + +[`activitypub.academy`](https://activitypub.academy) is a platform for learning about the ActivityPub protocol and its implementation. + +To test federation with `activitypub.academy`: + +1. Deploy the application to a public server or use a tunneling service: + + ```bash + # Using Fedify CLI to tunnel + fedify tunnel 5173 + ``` + +2. From your `activitypub.academy` account, search for and follow: + + ``` + @demo@6c10b40c63d9e1ce7da55667ef0ef8b4.serveo.net + ``` + +3. The application will automatically: + - Receive the follow request + - Send an Accept activity back + - Store the relationship + +### 3. Custom Actor Creation + +To create additional actors, modify `src/lib/federation.ts`: + +```typescript +// Add more identifiers +const IDENTIFIERS = ["demo", "alice", "bob"]; + +federation.setActorDispatcher( + "/users/{identifier}", + async (context, identifier) => { + if (!IDENTIFIERS.includes(identifier)) { + return null; + } + // ... actor creation logic + }, +); +``` + +### 4. Activity Monitoring + +The application logs activities to the console. Monitor the development console to see: + +- Incoming follow requests +- Outgoing accept activities +- Undo operations + +### 5. Custom Activities + +Extend the inbox listeners to handle additional ActivityPub activities: + +```typescript +federation + .setInboxListeners("/users/{identifier}/inbox", "/inbox") + .on(Follow, async (context, follow) => { + // Handle follow requests + }) + .on(Undo, async (context, undo) => { + // Handle undo operations + }) + .on(Like, async (context, like) => { + // Add custom like handling + }); ``` -## Developing +🏗️ Project Structure +-------------------- + +``` +src/ +├── app.css # Global styles +├── app.html # HTML template +├── hooks.server.ts # Server-side hooks +├── data/ +│ └── store.ts # In-memory data storage +├── federation/ # Federation-related modules +├── lib/ +│ ├── federation.ts # Main federation configuration +│ ├── handles.ts # Request handlers +│ └── index.ts # Library exports +└── routes/ + ├── +layout.svelte # Layout component + ├── +page.svelte # Home page + └── users/ + └── [identifier]/ + └── +page.svelte # User profile page +``` -Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: +🚀 Deployment +------------- -```sh -npm run dev +### Production Build -# or start the server and open the app in a new browser tab -npm run dev -- --open +```bash +pnpm build ``` -## Building +### Deployment Considerations -To create a production version of your app: +1. **HTTPS Required**: ActivityPub requires HTTPS in production +2. **Domain Configuration**: Ensure proper domain setup for federation +3. **Storage**: Replace `MemoryKvStore` with persistent storage +4. **Environment Variables**: Configure production-specific settings -```sh -npm run build +### Example Deployment Commands + +```bash +# Build for production +pnpm build + +# Preview the build +pnpm dev + +# Or deploy to your preferred platform +# (Vercel, Netlify, Docker, etc.) ``` -You can preview the production build with `npm run preview`. +🤝 Contributing +--------------- + +This is a sample application demonstrating Fedify capabilities. Feel free to: + +- Experiment with the code +- Add new features +- Submit issues or suggestions +- Use as a starting point for your own federated applications + +📄 License +---------- + +This sample application follows the same license as the main Fedify project. + +🔗 Links +-------- -> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment. +- [Fedify Documentation](https://fedify.dev) +- [SvelteKit Documentation](https://kit.svelte.dev/) +- [ActivityPub Specification](https://www.w3.org/TR/activitypub/) +- [Fedify GitHub Repository](https://github.com/dahlia/fedify) diff --git a/examples/sveltekit-sample/src/lib/handles.ts b/examples/sveltekit-sample/src/lib/handles.ts index 9d2117a82..54dd65e17 100644 --- a/examples/sveltekit-sample/src/lib/handles.ts +++ b/examples/sveltekit-sample/src/lib/handles.ts @@ -4,7 +4,7 @@ import { getXForwardedRequest } from "x-forwarded-fetch"; /** * Replaces the host of the request with the value of the * x-forwarded-host header, if present. - * If don't use proxy or tunnel, this handle is unnecessary. + * If you don't use proxy or tunnel, this handle is unnecessary. * @param input * @return A new request handler with the host replaced. */ From cc89eba5defe2e042ea2089f27bfe135e89838c3 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Fri, 29 Aug 2025 16:58:25 +0900 Subject: [PATCH 11/23] Moved store.ts --- examples/sveltekit-sample/src/lib/federation.ts | 2 +- examples/sveltekit-sample/src/{data => lib}/store.ts | 0 examples/sveltekit-sample/src/routes/+page.server.ts | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename examples/sveltekit-sample/src/{data => lib}/store.ts (100%) diff --git a/examples/sveltekit-sample/src/lib/federation.ts b/examples/sveltekit-sample/src/lib/federation.ts index e5703de9b..38258768d 100644 --- a/examples/sveltekit-sample/src/lib/federation.ts +++ b/examples/sveltekit-sample/src/lib/federation.ts @@ -9,7 +9,7 @@ import { Person, Undo, } from "@fedify/fedify"; -import { keyPairsStore, relationStore } from "../data/store"; +import { keyPairsStore, relationStore } from "./store"; const federation = createFederation({ kv: new MemoryKvStore(), diff --git a/examples/sveltekit-sample/src/data/store.ts b/examples/sveltekit-sample/src/lib/store.ts similarity index 100% rename from examples/sveltekit-sample/src/data/store.ts rename to examples/sveltekit-sample/src/lib/store.ts diff --git a/examples/sveltekit-sample/src/routes/+page.server.ts b/examples/sveltekit-sample/src/routes/+page.server.ts index f03e03273..89f592d80 100644 --- a/examples/sveltekit-sample/src/routes/+page.server.ts +++ b/examples/sveltekit-sample/src/routes/+page.server.ts @@ -1,5 +1,5 @@ import type { PageServerLoad } from "./$types"; -import { relationStore } from "../data/store"; +import { relationStore } from "../lib/store"; export const load: PageServerLoad = async ({ request, url }) => { const forwardedHost = request.headers.get("x-forwarded-host"); From 6b4cc9e88a41402506a4e9b3ca9ce1e37381fecf Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Fri, 29 Aug 2025 20:48:59 +0900 Subject: [PATCH 12/23] Implement posting --- .../sveltekit-sample/src/lib/federation.ts | 43 +++++++++++++-- examples/sveltekit-sample/src/lib/store.ts | 52 ++++++++++++++++--- .../routes/users/[identifier]/+page.svelte | 3 -- .../users/[identifier]/posts/+page.server.ts | 46 ++++++++++++++++ .../users/[identifier]/posts/+page.svelte | 29 +++++++++++ .../users/[identifier]/posts/data.remote.ts | 4 ++ examples/sveltekit-sample/svelte.config.js | 5 +- 7 files changed, 165 insertions(+), 17 deletions(-) create mode 100644 examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.server.ts create mode 100644 examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.svelte create mode 100644 examples/sveltekit-sample/src/routes/users/[identifier]/posts/data.remote.ts diff --git a/examples/sveltekit-sample/src/lib/federation.ts b/examples/sveltekit-sample/src/lib/federation.ts index 38258768d..c0437eba3 100644 --- a/examples/sveltekit-sample/src/lib/federation.ts +++ b/examples/sveltekit-sample/src/lib/federation.ts @@ -6,7 +6,10 @@ import { generateCryptoKeyPair, Image, MemoryKvStore, + Note, Person, + PUBLIC_COLLECTION, + type Recipient, Undo, } from "@fedify/fedify"; import { keyPairsStore, relationStore } from "./store"; @@ -63,8 +66,8 @@ federation if (result?.type !== "actor" || result.identifier !== IDENTIFIER) { return; } - const follower = await follow.getActor(context); - if (follower?.id == null) { + const follower = await follow.getActor(context) as Person; + if (!follower?.id || follower.id === null) { throw new Error("follower is null"); } await context.sendActivity( @@ -79,7 +82,7 @@ federation object: follow, }), ); - relationStore.set(follower.id.href, follow.objectId.href); + relationStore.set(follower.id.href, follower); }) .on(Undo, async (context, undo) => { const activity = await undo.getObject(context); @@ -96,4 +99,38 @@ federation } }); +federation.setObjectDispatcher( + Note, + "/users/{identifier}/posts/{id}", + (ctx, values) => { + const id = ctx.getObjectUri(Note, values); + const post = postStore.get(id); + if (post == null) return null; + return new Note({ + id, + attribution: ctx.getActorUri(values.identifier), + to: PUBLIC_COLLECTION, + cc: ctx.getFollowersUri(values.identifier), + content: post.content, + mediaType: "text/html", + published: post.published, + url: id, + }); + }, +); + +federation + .setFollowersDispatcher( + "/users/{identifier}/followers", + () => { + const followers = Array.from(relationStore.values()); + const items: Recipient[] = followers.map((f) => ({ + id: f.id, + inboxId: f.inboxId, + endpoints: f.endpoints, + })); + return { items }; + }, + ); + export default federation; diff --git a/examples/sveltekit-sample/src/lib/store.ts b/examples/sveltekit-sample/src/lib/store.ts index c674bb93c..b12562d30 100644 --- a/examples/sveltekit-sample/src/lib/store.ts +++ b/examples/sveltekit-sample/src/lib/store.ts @@ -1,16 +1,52 @@ +import type { Note, Person } from "@fedify/fedify"; + declare global { var keyPairsStore: Map>; - var relationStore: Map; + var relationStore: Map; + var postStore: PostStore; +} + +class PostStore { + #map: Map = new Map(); + #timeline: URL[] = []; + constructor() {} + #append(posts: Note[]) { + posts.filter((p) => p.id && !this.#map.has(p.id.toString())) + .forEach((p) => { + this.#map.set(p.id!.toString(), p); + this.#timeline.push(p.id!); + }); + } + append = this.#append.bind(this); + #get(id: URL) { + return this.#map.get(id.toString()); + } + get = this.#get.bind(this); + async #getAll() { + return await Array.fromAsync( + this.#timeline.reverse() + .map((id) => id.toString()) + .map((id) => this.#map.get(id)!) + .filter((p) => p) + .map((p) => p.toJsonLd()), + ); + } + getAll = this.#getAll.bind(this); + #delete(id: URL) { + const existed = this.#map.delete(id.toString()); + if (existed) { + this.#timeline = this.#timeline.filter((i) => i !== id); + } + } + delete = this.#delete.bind(this); } -export const keyPairsStore: Map< - string, - Array -> = globalThis.keyPairsStore ?? new Map(); -export const relationStore: Map = - globalThis.relationStore ?? new Map(); +export const keyPairsStore = globalThis.keyPairsStore ?? new Map(); +export const relationStore = globalThis.relationStore ?? new Map(); +export const postStore = globalThis.postStore ?? new PostStore(); -// this is just a hack to demo nextjs +// this is just a hack to demo svelte // never do this in production, use safe and secure storage globalThis.keyPairsStore = keyPairsStore; globalThis.relationStore = relationStore; +globalThis.postStore = postStore; diff --git a/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte b/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte index 34465cfa2..9794ae2cc 100644 --- a/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte +++ b/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte @@ -5,9 +5,6 @@ let { params }: PageProps = $props(); const { identifier } = params; - $effect(() => { - console.log(identifier); - }); const data = browser ? fetch(`/users/${identifier}`, { headers: { Accept: "application/activity+json" }, diff --git a/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.server.ts b/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.server.ts new file mode 100644 index 000000000..bc7ac4fe6 --- /dev/null +++ b/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.server.ts @@ -0,0 +1,46 @@ +import type { Action, Actions } from "./$types"; +import { error, redirect } from "@sveltejs/kit"; +import { postStore } from "$lib/store"; +import { Create, Note } from "@fedify/fedify"; +import federation from "$lib/federation"; + +const post: Action = async (event) => { + const data = await event.request.formData(); + const content = data.get("content") as string; + const identifier = data.get("identifier") as string; + + if (typeof content !== "string" && typeof identifier !== "string") { + error(400, "Title and content are required"); + } + const ctx = federation.createContext(event.request, undefined); + const id = crypto.randomUUID(); + const attribution = ctx.getActorUri(identifier); + const url = new URL(`/users/${identifier}/posts/${id}`, attribution); + const post = new Note({ + id: url, + attribution, + content, + url, + }); + try { + postStore.append([post!]); + const note = await ctx.getObject(Note, { identifier, id }); + await ctx.sendActivity( + { identifier }, + "followers", + new Create({ + id: new URL("#activity", attribution), + object: note, + actors: note?.attributionIds, + tos: note?.toIds, + ccs: note?.ccIds, + }), + ); + // await getPosts().refresh(); + } catch { + postStore.delete(url); + } + redirect(303, `/users/${identifier}/posts`); +}; + +export const actions = { post } satisfies Actions; diff --git a/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.svelte b/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.svelte new file mode 100644 index 000000000..ae6049a13 --- /dev/null +++ b/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.svelte @@ -0,0 +1,29 @@ + + +
+ + + +
+ +{#if query.error} +

oops!

+{:else if query.loading} +

loading...

+{:else if query.current} +
    + {#each query.current as note} +
    {JSON.stringify(note, null, 2)}
    + {/each} +
+{/if} diff --git a/examples/sveltekit-sample/src/routes/users/[identifier]/posts/data.remote.ts b/examples/sveltekit-sample/src/routes/users/[identifier]/posts/data.remote.ts new file mode 100644 index 000000000..43eb93a9a --- /dev/null +++ b/examples/sveltekit-sample/src/routes/users/[identifier]/posts/data.remote.ts @@ -0,0 +1,4 @@ +import { query } from "$app/server"; +import { postStore } from "$lib/store"; + +export const getPosts = query(async () => postStore.getAll()); diff --git a/examples/sveltekit-sample/svelte.config.js b/examples/sveltekit-sample/svelte.config.js index 0c41bab48..6b2d8b686 100644 --- a/examples/sveltekit-sample/svelte.config.js +++ b/examples/sveltekit-sample/svelte.config.js @@ -7,11 +7,10 @@ const config = { // for more information about preprocessors preprocess: vitePreprocess(), kit: { - // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list. - // If your environment is not supported, or you settled on a specific environment, switch out the adapter. - // See https://svelte.dev/docs/kit/adapters for more information about adapters. + experimental: { remoteFunctions: true }, adapter: adapter(), }, + compilerOptions: { experimental: { async: true } }, }; export default config; From 3ede79e9b0d3371defe8a7e959078aa86c5dfed5 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Fri, 29 Aug 2025 21:15:10 +0900 Subject: [PATCH 13/23] Decorated /users/[identifier]/posts page --- examples/sveltekit-sample/src/app.css | 146 ++++++++++++++++++ .../src/lib/components/Spinner.svelte | 21 +++ examples/sveltekit-sample/src/lib/store.ts | 13 +- .../routes/users/[identifier]/+page.svelte | 20 +-- .../users/[identifier]/posts/+page.svelte | 80 ++++++++-- 5 files changed, 241 insertions(+), 39 deletions(-) create mode 100644 examples/sveltekit-sample/src/lib/components/Spinner.svelte diff --git a/examples/sveltekit-sample/src/app.css b/examples/sveltekit-sample/src/app.css index 8d4a9ef48..39464d5cf 100644 --- a/examples/sveltekit-sample/src/app.css +++ b/examples/sveltekit-sample/src/app.css @@ -129,4 +129,150 @@ body { @apply flex-col items-start gap-1; } } + + /* Posts Page Styles */ + .post-form { + @apply mx-auto my-8 max-w-4xl rounded-xl border p-6; + background: var(--background); + border-color: rgba(0, 0, 0, 0.1); + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); + } + + .form-group { + @apply mb-4; + } + + .form-label { + @apply mb-2 block text-lg font-semibold; + color: var(--foreground); + } + + .form-textarea { + @apply w-full resize-none rounded-lg border p-3 text-base focus:ring-2 focus:ring-blue-500 focus:outline-none; + background: var(--background); + color: var(--foreground); + border-color: rgba(0, 0, 0, 0.2); + transition: + border-color 0.2s, + box-shadow 0.2s; + } + + .form-textarea:focus { + border-color: #3b82f6; + } + + .post-button { + @apply rounded-lg px-6 py-2 font-semibold text-white transition-all duration-200; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + } + + .post-button:hover { + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + } + + .error-state, + .loading-state { + @apply py-12 text-center; + } + + .error-state p { + @apply text-lg text-red-600; + } + + .loading-state p { + @apply mt-4 text-gray-600; + } + + .posts-container { + @apply mx-auto max-w-4xl; + } + + .posts-title { + @apply mb-6 text-2xl font-bold; + color: var(--foreground); + } + + .posts-grid { + @apply grid gap-6; + } + + .post-card { + @apply rounded-xl border transition-all duration-200 hover:shadow-lg; + background: var(--background); + border-color: rgba(0, 0, 0, 0.1); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); + } + + .post-card:hover { + transform: translateY(-2px); + } + + .post-link { + @apply block p-6 no-underline; + color: inherit; + } + + .post-header { + @apply mb-4 flex items-center gap-3; + } + + .post-avatar { + @apply h-12 w-12 rounded-full border-2 border-gray-200 object-cover; + } + + .post-user-info { + @apply flex-1; + } + + .post-user-name { + @apply mb-1 text-lg font-semibold; + color: var(--foreground); + } + + .post-user-handle { + @apply text-sm opacity-70; + color: var(--foreground); + } + + .post-content { + @apply text-base leading-relaxed; + color: var(--foreground); + } + + .post-content p { + @apply m-0; + } + + /* Skeleton Styles */ + .skeleton-avatar { + @apply h-12 w-12 animate-pulse rounded-full bg-gray-300; + } + + .skeleton-info { + @apply flex-1 space-y-2; + } + + .skeleton-line { + @apply h-4 animate-pulse rounded bg-gray-300; + } + + .skeleton-name { + @apply w-24; + } + + .skeleton-handle { + @apply w-32; + } + + @media (max-width: 768px) { + .posts-container { + @apply px-4; + } + + .post-form { + @apply p-4; + } + } } diff --git a/examples/sveltekit-sample/src/lib/components/Spinner.svelte b/examples/sveltekit-sample/src/lib/components/Spinner.svelte new file mode 100644 index 000000000..d31852c36 --- /dev/null +++ b/examples/sveltekit-sample/src/lib/components/Spinner.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/examples/sveltekit-sample/src/lib/store.ts b/examples/sveltekit-sample/src/lib/store.ts index b12562d30..7befa6f34 100644 --- a/examples/sveltekit-sample/src/lib/store.ts +++ b/examples/sveltekit-sample/src/lib/store.ts @@ -22,14 +22,11 @@ class PostStore { return this.#map.get(id.toString()); } get = this.#get.bind(this); - async #getAll() { - return await Array.fromAsync( - this.#timeline.reverse() - .map((id) => id.toString()) - .map((id) => this.#map.get(id)!) - .filter((p) => p) - .map((p) => p.toJsonLd()), - ); + #getAll() { + return this.#timeline.reverse() + .map((id) => id.toString()) + .map((id) => this.#map.get(id)!) + .filter((p) => p); } getAll = this.#getAll.bind(this); #delete(id: URL) { diff --git a/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte b/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte index 9794ae2cc..c2289d308 100644 --- a/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte +++ b/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte @@ -2,6 +2,7 @@ import type { PageProps } from "./$types"; import { browser } from "$app/environment"; import type { Person } from "@fedify/fedify"; + import Spinner from "$lib/components/Spinner.svelte"; let { params }: PageProps = $props(); const { identifier } = params; @@ -17,24 +18,7 @@ {#await data}
- +
{:then user} {#if user} diff --git a/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.svelte b/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.svelte index ae6049a13..bbcb3443d 100644 --- a/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.svelte +++ b/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.svelte @@ -1,29 +1,83 @@ -
+ - - +
+ +
+
{#if query.error} -

oops!

+
+

포스트를 불러오는 중 오류가 발생했습니다.

+
{:else if query.loading} -

loading...

+
+ +

포스트를 불러오는 중...

+
{:else if query.current} -
    - {#each query.current as note} -
    {JSON.stringify(note, null, 2)}
    - {/each} -
+ {/if} From 45b3a53736e6aa9b92fe09641b001d0a518f45b4 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Fri, 29 Aug 2025 22:31:25 +0900 Subject: [PATCH 14/23] Refactored by modularizing --- .../src/lib/components/Profile.svelte | 24 +++++ examples/sveltekit-sample/src/lib/fetch.ts | 22 +++++ examples/sveltekit-sample/src/lib/types.ts | 11 +++ .../routes/users/[identifier]/+page.server.ts | 17 ++++ .../routes/users/[identifier]/+page.svelte | 89 ++++++------------- .../users/[identifier]/posts/+page.server.ts | 17 ++++ .../users/[identifier]/posts/+page.svelte | 88 ++++++------------ .../users/[identifier]/posts/data.remote.ts | 4 - 8 files changed, 145 insertions(+), 127 deletions(-) create mode 100644 examples/sveltekit-sample/src/lib/components/Profile.svelte create mode 100644 examples/sveltekit-sample/src/lib/fetch.ts create mode 100644 examples/sveltekit-sample/src/lib/types.ts create mode 100644 examples/sveltekit-sample/src/routes/users/[identifier]/+page.server.ts delete mode 100644 examples/sveltekit-sample/src/routes/users/[identifier]/posts/data.remote.ts diff --git a/examples/sveltekit-sample/src/lib/components/Profile.svelte b/examples/sveltekit-sample/src/lib/components/Profile.svelte new file mode 100644 index 000000000..3e51eaaa1 --- /dev/null +++ b/examples/sveltekit-sample/src/lib/components/Profile.svelte @@ -0,0 +1,24 @@ + + +
+
+ {user.name}'s profile +
+ +
diff --git a/examples/sveltekit-sample/src/lib/fetch.ts b/examples/sveltekit-sample/src/lib/fetch.ts new file mode 100644 index 000000000..140a6a1f2 --- /dev/null +++ b/examples/sveltekit-sample/src/lib/fetch.ts @@ -0,0 +1,22 @@ +import { Note, type RequestContext } from "@fedify/fedify"; +import type { Post, User } from "./types"; + +export const getUser = async ( + ctx: RequestContext, + identifier: string, +): Promise => await (await ctx.getActor(identifier))?.toJsonLd() as User; + +export const getPost = async ( + ctx: RequestContext, + identifier: string, + id: string, +): Promise => + await (await ctx.getObject(Note, { id, identifier }))?.toJsonLd() as Post; + +export const getPosts = async ( + author: User, +) => + (await Array.fromAsync( + postStore.getAll(), + (p) => p.toJsonLd() as Promise, + )).map((p) => ({ ...p, author } as Post & { author: User })); diff --git a/examples/sveltekit-sample/src/lib/types.ts b/examples/sveltekit-sample/src/lib/types.ts new file mode 100644 index 000000000..fabaf4923 --- /dev/null +++ b/examples/sveltekit-sample/src/lib/types.ts @@ -0,0 +1,11 @@ +export interface User { + icon: { url: string }; + name: string; + preferredUsername: string; + url: string; + summary: string; +} +export interface Post { + published?: string; + content: string; +} diff --git a/examples/sveltekit-sample/src/routes/users/[identifier]/+page.server.ts b/examples/sveltekit-sample/src/routes/users/[identifier]/+page.server.ts new file mode 100644 index 000000000..7143d3220 --- /dev/null +++ b/examples/sveltekit-sample/src/routes/users/[identifier]/+page.server.ts @@ -0,0 +1,17 @@ +import type { PageServerLoad } from "./$types"; +import fedi from "$lib/federation"; +import { error } from "@sveltejs/kit"; +import { getUser } from "$lib/fetch"; + +export const load: PageServerLoad = async ({ request, params }) => { + try { + const ctx = fedi.createContext(request, undefined); + const { identifier } = params; + + const user = await getUser(ctx, identifier); + + return { user }; + } catch { + error(404, { message: "Not Found" }); + } +}; diff --git a/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte b/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte index c2289d308..6f7a302d7 100644 --- a/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte +++ b/examples/sveltekit-sample/src/routes/users/[identifier]/+page.svelte @@ -1,73 +1,34 @@ -{#await data} - -
- -
-{:then user} - {#if user} -
-
-
- {user.name}'s profile -
- -
+
+ -
-
-

Profile Information

-
-
- Information - This profile is demo for - - Fedify - - Next.js - integration. - -
-
+
+
+

Profile Information

+
+
+ Information + This profile is demo for + + Fedify + + Next.js + integration. +
- {/if} -{:catch} -

404 Not found

-{/await} +
+
diff --git a/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.server.ts b/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.server.ts index bc7ac4fe6..5f49d9959 100644 --- a/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.server.ts +++ b/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.server.ts @@ -3,6 +3,9 @@ import { error, redirect } from "@sveltejs/kit"; import { postStore } from "$lib/store"; import { Create, Note } from "@fedify/fedify"; import federation from "$lib/federation"; +import type { PageServerLoad } from "./$types"; +import fedi from "$lib/federation"; +import { getPosts, getUser } from "$lib/fetch"; const post: Action = async (event) => { const data = await event.request.formData(); @@ -44,3 +47,17 @@ const post: Action = async (event) => { }; export const actions = { post } satisfies Actions; + +export const load: PageServerLoad = async ({ request, params }) => { + try { + const ctx = fedi.createContext(request, undefined); + const { identifier } = params; + + const user = await getUser(ctx, identifier); + const posts = await getPosts(user); + + return { user, posts }; + } catch { + error(404, { message: "Not Found" }); + } +}; diff --git a/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.svelte b/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.svelte index bbcb3443d..855d21d20 100644 --- a/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.svelte +++ b/examples/sveltekit-sample/src/routes/users/[identifier]/posts/+page.svelte @@ -1,23 +1,14 @@
+