From f4be03cebac56f27ff6e0e3e9ef2e40cb9475583 Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Sat, 21 Mar 2026 22:41:23 +0100 Subject: [PATCH] first --- .gitignore | 1 + Makefile | 71 + backend/.env | 8 + backend/.env.example | 19 + backend/cmd/server/embed/_app/env.js | 1 + .../_app/immutable/assets/0.DkgBtk4_.css | 1 + .../_app/immutable/assets/10.Qar-kS8x.css | 1 + .../_app/immutable/assets/11.D38O3Xxc.css | 1 + .../_app/immutable/assets/12.DQdHIvb_.css | 1 + .../_app/immutable/assets/13.DnP_H9DZ.css | 1 + .../_app/immutable/assets/2.By2d6Bxb.css | 1 + .../_app/immutable/assets/4.CG2X--Z8.css | 1 + .../_app/immutable/assets/5.YbbfqdJp.css | 1 + .../_app/immutable/assets/6.w_qTFDpy.css | 1 + .../_app/immutable/assets/7.Bq7myTre.css | 1 + .../_app/immutable/assets/8.neQUdyXe.css | 1 + .../_app/immutable/assets/9.Ci0QlAaW.css | 1 + .../embed/_app/immutable/chunks/-EcHSJia.js | 1 + .../embed/_app/immutable/chunks/B3ZK_jYJ.js | 1 + .../embed/_app/immutable/chunks/B7kAneMc.js | 1 + .../embed/_app/immutable/chunks/BX-b5t2l.js | 1 + .../embed/_app/immutable/chunks/BYrNiJ2z.js | 2 + .../embed/_app/immutable/chunks/CJv7FbHz.js | 1 + .../embed/_app/immutable/chunks/CfgL3m1f.js | 1 + .../embed/_app/immutable/chunks/DFRBE_Uq.js | 1 + .../embed/_app/immutable/chunks/DR7h53-u.js | 1 + .../embed/_app/immutable/chunks/DtGl34IE.js | 1 + .../embed/_app/immutable/chunks/RKc8iKz_.js | 1 + .../embed/_app/immutable/chunks/ayyTDfEa.js | 1 + .../embed/_app/immutable/chunks/e1WBZ7UL.js | 1 + .../embed/_app/immutable/chunks/ecAlPOj8.js | 1 + .../embed/_app/immutable/chunks/n1byU5WW.js | 2 + .../_app/immutable/entry/app.BI_Sozkn.js | 2 + .../_app/immutable/entry/start.tprRzko2.js | 1 + .../embed/_app/immutable/nodes/0.D3wXY_0K.js | 1 + .../embed/_app/immutable/nodes/1.Dgii_8lh.js | 1 + .../embed/_app/immutable/nodes/10.BvOkMiuT.js | 1 + .../embed/_app/immutable/nodes/11.DnvWFHPj.js | 1 + .../embed/_app/immutable/nodes/12.CRx3MqWn.js | 1 + .../embed/_app/immutable/nodes/13.CB7FlS8h.js | 1 + .../embed/_app/immutable/nodes/14.CFDiiGpK.js | 1 + .../embed/_app/immutable/nodes/2.BMCUuUxB.js | 1 + .../embed/_app/immutable/nodes/3.CFDiiGpK.js | 1 + .../embed/_app/immutable/nodes/4.YDL696B2.js | 1 + .../embed/_app/immutable/nodes/5.DHfYhdex.js | 1 + .../embed/_app/immutable/nodes/6.BiQ3_GJa.js | 1 + .../embed/_app/immutable/nodes/7.BEIquz8f.js | 1 + .../embed/_app/immutable/nodes/8.D4QctIPu.js | 1 + .../embed/_app/immutable/nodes/9.DflEy3LG.js | 1 + backend/cmd/server/embed/_app/version.json | 1 + backend/cmd/server/embed/favicon.png | 4 + backend/cmd/server/embed/index.html | 40 + backend/cmd/server/frontend.go | 19 + backend/cmd/server/main.go | 180 + backend/go.mod | 19 + backend/go.sum | 20 + backend/internal/api/handlers/aliases.go | 160 + backend/internal/api/handlers/auth.go | 269 + backend/internal/api/handlers/domains.go | 316 + backend/internal/api/handlers/logs.go | 38 + backend/internal/api/handlers/middleware.go | 72 + backend/internal/api/handlers/queue.go | 58 + backend/internal/api/handlers/response.go | 41 + backend/internal/api/handlers/stats.go | 53 + backend/internal/api/handlers/users.go | 351 + backend/internal/api/router.go | 247 + backend/internal/auth/jwt.go | 85 + backend/internal/auth/rbac.go | 18 + backend/internal/config/config.go | 56 + backend/internal/db/aliases.go | 70 + backend/internal/db/db.go | 164 + backend/internal/db/domains.go | 68 + backend/internal/db/imc_users.go | 122 + backend/internal/db/users.go | 76 + backend/internal/mail/logs.go | 88 + backend/internal/mail/queue.go | 123 + frontend/.svelte-kit/ambient.d.ts | 336 + .../generated/client-optimized/app.js | 53 + .../generated/client-optimized/matchers.js | 1 + .../generated/client-optimized/nodes/0.js | 1 + .../generated/client-optimized/nodes/1.js | 1 + .../generated/client-optimized/nodes/10.js | 1 + .../generated/client-optimized/nodes/11.js | 1 + .../generated/client-optimized/nodes/12.js | 1 + .../generated/client-optimized/nodes/13.js | 1 + .../generated/client-optimized/nodes/14.js | 1 + .../generated/client-optimized/nodes/2.js | 1 + .../generated/client-optimized/nodes/3.js | 1 + .../generated/client-optimized/nodes/4.js | 1 + .../generated/client-optimized/nodes/5.js | 1 + .../generated/client-optimized/nodes/6.js | 1 + .../generated/client-optimized/nodes/7.js | 1 + .../generated/client-optimized/nodes/8.js | 1 + .../generated/client-optimized/nodes/9.js | 1 + frontend/.svelte-kit/generated/client/app.js | 53 + .../.svelte-kit/generated/client/matchers.js | 1 + .../.svelte-kit/generated/client/nodes/0.js | 1 + .../.svelte-kit/generated/client/nodes/1.js | 1 + .../.svelte-kit/generated/client/nodes/10.js | 1 + .../.svelte-kit/generated/client/nodes/11.js | 1 + .../.svelte-kit/generated/client/nodes/12.js | 1 + .../.svelte-kit/generated/client/nodes/13.js | 1 + .../.svelte-kit/generated/client/nodes/14.js | 1 + .../.svelte-kit/generated/client/nodes/2.js | 1 + .../.svelte-kit/generated/client/nodes/3.js | 1 + .../.svelte-kit/generated/client/nodes/4.js | 1 + .../.svelte-kit/generated/client/nodes/5.js | 1 + .../.svelte-kit/generated/client/nodes/6.js | 1 + .../.svelte-kit/generated/client/nodes/7.js | 1 + .../.svelte-kit/generated/client/nodes/8.js | 1 + .../.svelte-kit/generated/client/nodes/9.js | 1 + frontend/.svelte-kit/generated/root.js | 3 + frontend/.svelte-kit/generated/root.svelte | 68 + .../.svelte-kit/generated/server/internal.js | 54 + frontend/.svelte-kit/non-ambient.d.ts | 58 + .../output/client/.vite/manifest.json | 424 + .../_app/immutable/assets/0.DkgBtk4_.css | 1 + .../_app/immutable/assets/10.Qar-kS8x.css | 1 + .../_app/immutable/assets/11.D38O3Xxc.css | 1 + .../_app/immutable/assets/12.DQdHIvb_.css | 1 + .../_app/immutable/assets/13.DnP_H9DZ.css | 1 + .../_app/immutable/assets/2.By2d6Bxb.css | 1 + .../_app/immutable/assets/4.CG2X--Z8.css | 1 + .../_app/immutable/assets/5.YbbfqdJp.css | 1 + .../_app/immutable/assets/6.w_qTFDpy.css | 1 + .../_app/immutable/assets/7.Bq7myTre.css | 1 + .../_app/immutable/assets/8.neQUdyXe.css | 1 + .../_app/immutable/assets/9.Ci0QlAaW.css | 1 + .../client/_app/immutable/chunks/-EcHSJia.js | 1 + .../client/_app/immutable/chunks/B3ZK_jYJ.js | 1 + .../client/_app/immutable/chunks/B7kAneMc.js | 1 + .../client/_app/immutable/chunks/BX-b5t2l.js | 1 + .../client/_app/immutable/chunks/BYrNiJ2z.js | 2 + .../client/_app/immutable/chunks/CJv7FbHz.js | 1 + .../client/_app/immutable/chunks/CfgL3m1f.js | 1 + .../client/_app/immutable/chunks/DFRBE_Uq.js | 1 + .../client/_app/immutable/chunks/DR7h53-u.js | 1 + .../client/_app/immutable/chunks/DtGl34IE.js | 1 + .../client/_app/immutable/chunks/RKc8iKz_.js | 1 + .../client/_app/immutable/chunks/ayyTDfEa.js | 1 + .../client/_app/immutable/chunks/e1WBZ7UL.js | 1 + .../client/_app/immutable/chunks/ecAlPOj8.js | 1 + .../client/_app/immutable/chunks/n1byU5WW.js | 2 + .../_app/immutable/entry/app.BI_Sozkn.js | 2 + .../_app/immutable/entry/start.tprRzko2.js | 1 + .../client/_app/immutable/nodes/0.D3wXY_0K.js | 1 + .../client/_app/immutable/nodes/1.Dgii_8lh.js | 1 + .../_app/immutable/nodes/10.BvOkMiuT.js | 1 + .../_app/immutable/nodes/11.DnvWFHPj.js | 1 + .../_app/immutable/nodes/12.CRx3MqWn.js | 1 + .../_app/immutable/nodes/13.CB7FlS8h.js | 1 + .../_app/immutable/nodes/14.CFDiiGpK.js | 1 + .../client/_app/immutable/nodes/2.BMCUuUxB.js | 1 + .../client/_app/immutable/nodes/3.CFDiiGpK.js | 1 + .../client/_app/immutable/nodes/4.YDL696B2.js | 1 + .../client/_app/immutable/nodes/5.DHfYhdex.js | 1 + .../client/_app/immutable/nodes/6.BiQ3_GJa.js | 1 + .../client/_app/immutable/nodes/7.BEIquz8f.js | 1 + .../client/_app/immutable/nodes/8.D4QctIPu.js | 1 + .../client/_app/immutable/nodes/9.DflEy3LG.js | 1 + .../output/client/_app/version.json | 1 + .../.svelte-kit/output/client/favicon.png | 4 + .../prerendered/dependencies/_app/env.js | 1 + .../output/server/.vite/manifest.json | 301 + .../immutable/assets/_layout.DkgBtk4_.css | 1 + .../_app/immutable/assets/_page.Bmr1F0Zh.css | 1 + .../_app/immutable/assets/_page.Bq7myTre.css | 1 + .../_app/immutable/assets/_page.By2d6Bxb.css | 1 + .../_app/immutable/assets/_page.CG2X--Z8.css | 1 + .../_app/immutable/assets/_page.Ci0QlAaW.css | 1 + .../_app/immutable/assets/_page.CvxoqpCi.css | 1 + .../_app/immutable/assets/_page.DQdHIvb_.css | 1 + .../_app/immutable/assets/_page.DnP_H9DZ.css | 1 + .../_app/immutable/assets/_page.Sd9PQMHc.css | 1 + .../_app/immutable/assets/_page.YbbfqdJp.css | 1 + .../_app/immutable/assets/_page.w_qTFDpy.css | 1 + .../output/server/chunks/environment.js | 34 + .../output/server/chunks/exports.js | 174 + .../.svelte-kit/output/server/chunks/false.js | 4 + .../.svelte-kit/output/server/chunks/index.js | 59 + .../output/server/chunks/index2.js | 1250 + .../output/server/chunks/internal.js | 134 + .../.svelte-kit/output/server/chunks/root.js | 2732 + .../output/server/chunks/shared.js | 789 + .../output/server/chunks/state.svelte.js | 19 + .../.svelte-kit/output/server/chunks/utils.js | 43 + .../server/entries/fallbacks/error.svelte.js | 45 + .../server/entries/pages/_layout.svelte.js | 20 + .../server/entries/pages/_page.svelte.js | 14 + .../entries/pages/aliases/_page.svelte.js | 15 + .../auth/change-password/_page.svelte.js | 31 + .../pages/auth/dashboard/_page.svelte.js | 24 + .../entries/pages/auth/forgot/_page.svelte.js | 24 + .../entries/pages/auth/login/_page.svelte.js | 22 + .../pages/domains/_name_/_page.svelte.js | 19 + .../domains/_name_/aliases/_page.svelte.js | 25 + .../domains/_name_/users/_page.svelte.js | 25 + .../entries/pages/domains/_page.svelte.js | 18 + .../server/entries/pages/logs/_page.svelte.js | 78 + .../entries/pages/queue/_page.svelte.js | 14 + .../entries/pages/users/_page.svelte.js | 15 + frontend/.svelte-kit/output/server/index.js | 3821 + .../.svelte-kit/output/server/internal.js | 14 + .../output/server/manifest-full.js | 135 + .../.svelte-kit/output/server/manifest.js | 135 + frontend/.svelte-kit/output/server/nodes/0.js | 8 + frontend/.svelte-kit/output/server/nodes/1.js | 8 + .../.svelte-kit/output/server/nodes/10.js | 8 + .../.svelte-kit/output/server/nodes/11.js | 8 + .../.svelte-kit/output/server/nodes/12.js | 8 + .../.svelte-kit/output/server/nodes/13.js | 8 + .../.svelte-kit/output/server/nodes/14.js | 8 + frontend/.svelte-kit/output/server/nodes/2.js | 8 + frontend/.svelte-kit/output/server/nodes/3.js | 8 + frontend/.svelte-kit/output/server/nodes/4.js | 8 + frontend/.svelte-kit/output/server/nodes/5.js | 8 + frontend/.svelte-kit/output/server/nodes/6.js | 8 + frontend/.svelte-kit/output/server/nodes/7.js | 8 + frontend/.svelte-kit/output/server/nodes/8.js | 8 + frontend/.svelte-kit/output/server/nodes/9.js | 8 + .../.svelte-kit/output/server/remote-entry.js | 557 + frontend/.svelte-kit/tsconfig.json | 55 + .../.svelte-kit/types/route_meta_data.json | 15 + .../.svelte-kit/types/src/routes/$types.d.ts | 23 + .../types/src/routes/aliases/$types.d.ts | 17 + .../routes/auth/change-password/$types.d.ts | 17 + .../src/routes/auth/dashboard/$types.d.ts | 17 + .../types/src/routes/auth/forgot/$types.d.ts | 17 + .../types/src/routes/auth/login/$types.d.ts | 17 + .../types/src/routes/domains/$types.d.ts | 17 + .../src/routes/domains/[name]/$types.d.ts | 18 + .../routes/domains/[name]/aliases/$types.d.ts | 18 + .../routes/domains/[name]/users/$types.d.ts | 18 + .../types/src/routes/logs/$types.d.ts | 17 + .../types/src/routes/queue/$types.d.ts | 17 + .../types/src/routes/users/$types.d.ts | 17 + frontend/bun.lock | 208 + frontend/node_modules/.bin/acorn | 1 + frontend/node_modules/.bin/esbuild | 1 + frontend/node_modules/.bin/nanoid | 1 + frontend/node_modules/.bin/rollup | 1 + frontend/node_modules/.bin/svelte-kit | 1 + frontend/node_modules/.bin/tsc | 1 + frontend/node_modules/.bin/tsserver | 1 + frontend/node_modules/.bin/vite | 1 + .../svelte-native-jsx.d.ts | 32 + .../svelte-shims-v4.d.ts | 290 + .../node_modules/@esbuild/linux-x64/README.md | 3 + .../@esbuild/linux-x64/bin/esbuild | Bin 0 -> 9707520 bytes .../@esbuild/linux-x64/package.json | 20 + .../@jridgewell/gen-mapping/LICENSE | 19 + .../@jridgewell/gen-mapping/README.md | 227 + .../gen-mapping/dist/gen-mapping.mjs | 292 + .../gen-mapping/dist/gen-mapping.mjs.map | 6 + .../gen-mapping/dist/gen-mapping.umd.js | 358 + .../gen-mapping/dist/gen-mapping.umd.js.map | 6 + .../gen-mapping/dist/types/gen-mapping.d.ts | 88 + .../gen-mapping/dist/types/set-array.d.ts | 32 + .../dist/types/sourcemap-segment.d.ts | 12 + .../gen-mapping/dist/types/types.d.ts | 43 + .../@jridgewell/gen-mapping/package.json | 67 + .../gen-mapping/src/gen-mapping.ts | 614 + .../@jridgewell/gen-mapping/src/set-array.ts | 82 + .../gen-mapping/src/sourcemap-segment.ts | 16 + .../@jridgewell/gen-mapping/src/types.ts | 61 + .../gen-mapping/types/gen-mapping.d.cts | 89 + .../gen-mapping/types/gen-mapping.d.cts.map | 1 + .../gen-mapping/types/gen-mapping.d.mts | 89 + .../gen-mapping/types/gen-mapping.d.mts.map | 1 + .../gen-mapping/types/set-array.d.cts | 33 + .../gen-mapping/types/set-array.d.cts.map | 1 + .../gen-mapping/types/set-array.d.mts | 33 + .../gen-mapping/types/set-array.d.mts.map | 1 + .../gen-mapping/types/sourcemap-segment.d.cts | 13 + .../types/sourcemap-segment.d.cts.map | 1 + .../gen-mapping/types/sourcemap-segment.d.mts | 13 + .../types/sourcemap-segment.d.mts.map | 1 + .../@jridgewell/gen-mapping/types/types.d.cts | 44 + .../gen-mapping/types/types.d.cts.map | 1 + .../@jridgewell/gen-mapping/types/types.d.mts | 44 + .../gen-mapping/types/types.d.mts.map | 1 + .../@jridgewell/remapping/LICENSE | 19 + .../@jridgewell/remapping/README.md | 218 + .../@jridgewell/remapping/dist/remapping.mjs | 144 + .../remapping/dist/remapping.mjs.map | 6 + .../remapping/dist/remapping.umd.js | 212 + .../remapping/dist/remapping.umd.js.map | 6 + .../@jridgewell/remapping/package.json | 71 + .../remapping/src/build-source-map-tree.ts | 89 + .../@jridgewell/remapping/src/remapping.ts | 42 + .../remapping/src/source-map-tree.ts | 172 + .../@jridgewell/remapping/src/source-map.ts | 38 + .../@jridgewell/remapping/src/types.ts | 27 + .../types/build-source-map-tree.d.cts | 15 + .../types/build-source-map-tree.d.cts.map | 1 + .../types/build-source-map-tree.d.mts | 15 + .../types/build-source-map-tree.d.mts.map | 1 + .../remapping/types/remapping.d.cts | 21 + .../remapping/types/remapping.d.cts.map | 1 + .../remapping/types/remapping.d.mts | 21 + .../remapping/types/remapping.d.mts.map | 1 + .../remapping/types/source-map-tree.d.cts | 46 + .../remapping/types/source-map-tree.d.cts.map | 1 + .../remapping/types/source-map-tree.d.mts | 46 + .../remapping/types/source-map-tree.d.mts.map | 1 + .../remapping/types/source-map.d.cts | 19 + .../remapping/types/source-map.d.cts.map | 1 + .../remapping/types/source-map.d.mts | 19 + .../remapping/types/source-map.d.mts.map | 1 + .../@jridgewell/remapping/types/types.d.cts | 16 + .../remapping/types/types.d.cts.map | 1 + .../@jridgewell/remapping/types/types.d.mts | 16 + .../remapping/types/types.d.mts.map | 1 + .../@jridgewell/resolve-uri/LICENSE | 19 + .../@jridgewell/resolve-uri/README.md | 40 + .../resolve-uri/dist/resolve-uri.mjs | 232 + .../resolve-uri/dist/resolve-uri.mjs.map | 1 + .../resolve-uri/dist/resolve-uri.umd.js | 240 + .../resolve-uri/dist/resolve-uri.umd.js.map | 1 + .../resolve-uri/dist/types/resolve-uri.d.ts | 4 + .../@jridgewell/resolve-uri/package.json | 69 + .../@jridgewell/sourcemap-codec/LICENSE | 19 + .../@jridgewell/sourcemap-codec/README.md | 264 + .../sourcemap-codec/dist/sourcemap-codec.mjs | 423 + .../dist/sourcemap-codec.mjs.map | 6 + .../dist/sourcemap-codec.umd.js | 464 + .../dist/sourcemap-codec.umd.js.map | 6 + .../@jridgewell/sourcemap-codec/package.json | 63 + .../@jridgewell/sourcemap-codec/src/scopes.ts | 345 + .../sourcemap-codec/src/sourcemap-codec.ts | 111 + .../sourcemap-codec/src/strings.ts | 65 + .../@jridgewell/sourcemap-codec/src/vlq.ts | 55 + .../sourcemap-codec/types/scopes.d.cts | 50 + .../sourcemap-codec/types/scopes.d.cts.map | 1 + .../sourcemap-codec/types/scopes.d.mts | 50 + .../sourcemap-codec/types/scopes.d.mts.map | 1 + .../types/sourcemap-codec.d.cts | 9 + .../types/sourcemap-codec.d.cts.map | 1 + .../types/sourcemap-codec.d.mts | 9 + .../types/sourcemap-codec.d.mts.map | 1 + .../sourcemap-codec/types/strings.d.cts | 16 + .../sourcemap-codec/types/strings.d.cts.map | 1 + .../sourcemap-codec/types/strings.d.mts | 16 + .../sourcemap-codec/types/strings.d.mts.map | 1 + .../sourcemap-codec/types/vlq.d.cts | 7 + .../sourcemap-codec/types/vlq.d.cts.map | 1 + .../sourcemap-codec/types/vlq.d.mts | 7 + .../sourcemap-codec/types/vlq.d.mts.map | 1 + .../@jridgewell/trace-mapping/LICENSE | 19 + .../@jridgewell/trace-mapping/README.md | 348 + .../trace-mapping/dist/trace-mapping.mjs | 493 + .../trace-mapping/dist/trace-mapping.mjs.map | 6 + .../trace-mapping/dist/trace-mapping.umd.js | 559 + .../dist/trace-mapping.umd.js.map | 6 + .../@jridgewell/trace-mapping/package.json | 67 + .../trace-mapping/src/binary-search.ts | 115 + .../trace-mapping/src/by-source.ts | 41 + .../trace-mapping/src/flatten-map.ts | 192 + .../@jridgewell/trace-mapping/src/resolve.ts | 16 + .../@jridgewell/trace-mapping/src/sort.ts | 45 + .../trace-mapping/src/sourcemap-segment.ts | 23 + .../trace-mapping/src/strip-filename.ts | 8 + .../trace-mapping/src/trace-mapping.ts | 502 + .../@jridgewell/trace-mapping/src/types.ts | 114 + .../trace-mapping/types/binary-search.d.cts | 33 + .../types/binary-search.d.cts.map | 1 + .../trace-mapping/types/binary-search.d.mts | 33 + .../types/binary-search.d.mts.map | 1 + .../trace-mapping/types/by-source.d.cts | 4 + .../trace-mapping/types/by-source.d.cts.map | 1 + .../trace-mapping/types/by-source.d.mts | 4 + .../trace-mapping/types/by-source.d.mts.map | 1 + .../trace-mapping/types/flatten-map.d.cts | 9 + .../trace-mapping/types/flatten-map.d.cts.map | 1 + .../trace-mapping/types/flatten-map.d.mts | 9 + .../trace-mapping/types/flatten-map.d.mts.map | 1 + .../trace-mapping/types/resolve.d.cts | 4 + .../trace-mapping/types/resolve.d.cts.map | 1 + .../trace-mapping/types/resolve.d.mts | 4 + .../trace-mapping/types/resolve.d.mts.map | 1 + .../trace-mapping/types/sort.d.cts | 4 + .../trace-mapping/types/sort.d.cts.map | 1 + .../trace-mapping/types/sort.d.mts | 4 + .../trace-mapping/types/sort.d.mts.map | 1 + .../types/sourcemap-segment.d.cts | 17 + .../types/sourcemap-segment.d.cts.map | 1 + .../types/sourcemap-segment.d.mts | 17 + .../types/sourcemap-segment.d.mts.map | 1 + .../trace-mapping/types/strip-filename.d.cts | 5 + .../types/strip-filename.d.cts.map | 1 + .../trace-mapping/types/strip-filename.d.mts | 5 + .../types/strip-filename.d.mts.map | 1 + .../trace-mapping/types/trace-mapping.d.cts | 80 + .../types/trace-mapping.d.cts.map | 1 + .../trace-mapping/types/trace-mapping.d.mts | 80 + .../types/trace-mapping.d.mts.map | 1 + .../trace-mapping/types/types.d.cts | 107 + .../trace-mapping/types/types.d.cts.map | 1 + .../trace-mapping/types/types.d.mts | 107 + .../trace-mapping/types/types.d.mts.map | 1 + frontend/node_modules/@polka/url/build.js | 49 + frontend/node_modules/@polka/url/build.mjs | 47 + frontend/node_modules/@polka/url/index.d.ts | 11 + frontend/node_modules/@polka/url/package.json | 30 + frontend/node_modules/@polka/url/readme.md | 68 + .../@rollup/rollup-linux-x64-gnu/README.md | 3 + .../@rollup/rollup-linux-x64-gnu/package.json | 25 + .../rollup.linux-x64-gnu.node | Bin 0 -> 2030680 bytes .../@rollup/rollup-linux-x64-musl/README.md | 3 + .../rollup-linux-x64-musl/package.json | 25 + .../rollup.linux-x64-musl.node | Bin 0 -> 2061104 bytes .../@standard-schema/spec/LICENSE | 21 + .../@standard-schema/spec/README.md | 198 + .../@standard-schema/spec/dist/index.cjs | 18 + .../@standard-schema/spec/dist/index.d.cts | 119 + .../@standard-schema/spec/dist/index.d.ts | 119 + .../@standard-schema/spec/dist/index.js | 0 .../@standard-schema/spec/package.json | 52 + .../@sveltejs/acorn-typescript/LICENSE.md | 22 + .../@sveltejs/acorn-typescript/README.md | 70 + .../@sveltejs/acorn-typescript/index.d.ts | 12 + .../@sveltejs/acorn-typescript/index.js | 5016 + .../@sveltejs/acorn-typescript/package.json | 55 + .../@sveltejs/adapter-static/LICENSE | 7 + .../@sveltejs/adapter-static/README.md | 15 + .../@sveltejs/adapter-static/index.d.ts | 11 + .../@sveltejs/adapter-static/index.js | 91 + .../@sveltejs/adapter-static/package.json | 54 + .../@sveltejs/adapter-static/platforms.js | 76 + frontend/node_modules/@sveltejs/kit/LICENSE | 7 + frontend/node_modules/@sveltejs/kit/README.md | 18 + .../node_modules/@sveltejs/kit/package.json | 135 + .../node_modules/@sveltejs/kit/src/cli.js | 95 + .../@sveltejs/kit/src/constants.js | 13 + .../@sveltejs/kit/src/core/adapt/builder.js | 369 + .../@sveltejs/kit/src/core/adapt/index.js | 44 + .../kit/src/core/config/default-error.html | 80 + .../@sveltejs/kit/src/core/config/index.js | 155 + .../@sveltejs/kit/src/core/config/options.js | 489 + .../@sveltejs/kit/src/core/config/types.d.ts | 1 + .../@sveltejs/kit/src/core/env.js | 152 + .../generate_manifest/find_server_assets.js | 56 + .../kit/src/core/generate_manifest/index.js | 152 + .../kit/src/core/postbuild/analyse.js | 285 + .../@sveltejs/kit/src/core/postbuild/crawl.js | 243 + .../kit/src/core/postbuild/entities.js | 2252 + .../kit/src/core/postbuild/fallback.js | 55 + .../kit/src/core/postbuild/prerender.js | 593 + .../@sveltejs/kit/src/core/postbuild/queue.js | 72 + .../sync/create_manifest_data/conflict.js | 0 .../core/sync/create_manifest_data/index.js | 613 + .../core/sync/create_manifest_data/sort.js | 162 + .../core/sync/create_manifest_data/types.d.ts | 37 + .../@sveltejs/kit/src/core/sync/sync.js | 96 + .../@sveltejs/kit/src/core/sync/ts.js | 6 + .../@sveltejs/kit/src/core/sync/utils.js | 78 + .../kit/src/core/sync/write_ambient.js | 63 + .../src/core/sync/write_client_manifest.js | 203 + .../kit/src/core/sync/write_non_ambient.js | 266 + .../@sveltejs/kit/src/core/sync/write_root.js | 196 + .../kit/src/core/sync/write_server.js | 143 + .../kit/src/core/sync/write_tsconfig.js | 243 + .../kit/src/core/sync/write_types/index.js | 869 + .../@sveltejs/kit/src/core/utils.js | 87 + .../@sveltejs/kit/src/exports/hooks/index.js | 1 + .../kit/src/exports/hooks/sequence.js | 145 + .../@sveltejs/kit/src/exports/index.js | 308 + .../kit/src/exports/internal/event.js | 85 + .../kit/src/exports/internal/index.js | 81 + .../src/exports/internal/remote-functions.js | 28 + .../kit/src/exports/internal/server.js | 22 + .../@sveltejs/kit/src/exports/node/index.js | 238 + .../kit/src/exports/node/polyfills.js | 30 + .../@sveltejs/kit/src/exports/public.d.ts | 2186 + .../kit/src/exports/vite/dev/index.js | 669 + .../@sveltejs/kit/src/exports/vite/index.js | 1464 + .../kit/src/exports/vite/module_ids.js | 16 + .../kit/src/exports/vite/preview/index.js | 261 + .../src/exports/vite/static_analysis/index.js | 301 + .../src/exports/vite/static_analysis/utils.js | 118 + .../@sveltejs/kit/src/exports/vite/types.d.ts | 3 + .../@sveltejs/kit/src/exports/vite/utils.js | 216 + .../kit/src/runtime/app/environment/index.js | 2 + .../src/runtime/app/environment/types.d.ts | 19 + .../@sveltejs/kit/src/runtime/app/forms.js | 231 + .../kit/src/runtime/app/navigation.js | 14 + .../kit/src/runtime/app/paths/client.js | 99 + .../kit/src/runtime/app/paths/index.js | 1 + .../src/runtime/app/paths/internal/client.js | 4 + .../src/runtime/app/paths/internal/server.js | 30 + .../kit/src/runtime/app/paths/public.d.ts | 29 + .../kit/src/runtime/app/paths/server.js | 71 + .../kit/src/runtime/app/paths/types.d.ts | 23 + .../kit/src/runtime/app/server/index.js | 78 + .../src/runtime/app/server/remote/command.js | 97 + .../kit/src/runtime/app/server/remote/form.js | 373 + .../src/runtime/app/server/remote/index.js | 4 + .../runtime/app/server/remote/prerender.js | 163 + .../src/runtime/app/server/remote/query.js | 314 + .../src/runtime/app/server/remote/shared.js | 161 + .../kit/src/runtime/app/state/client.js | 68 + .../kit/src/runtime/app/state/index.js | 64 + .../kit/src/runtime/app/state/server.js | 63 + .../@sveltejs/kit/src/runtime/app/stores.js | 101 + .../kit/src/runtime/client/bundle.js | 17 + .../kit/src/runtime/client/client.js | 3309 + .../kit/src/runtime/client/constants.js | 16 + .../@sveltejs/kit/src/runtime/client/entry.js | 3 + .../kit/src/runtime/client/fetcher.js | 178 + .../@sveltejs/kit/src/runtime/client/parse.js | 77 + .../client/remote-functions/command.svelte.js | 96 + .../client/remote-functions/form.svelte.js | 650 + .../runtime/client/remote-functions/index.js | 4 + .../remote-functions/prerender.svelte.js | 184 + .../client/remote-functions/query.svelte.js | 341 + .../client/remote-functions/shared.svelte.js | 154 + .../kit/src/runtime/client/session-storage.js | 28 + .../kit/src/runtime/client/state.svelte.js | 59 + .../kit/src/runtime/client/types.d.ts | 133 + .../@sveltejs/kit/src/runtime/client/utils.js | 365 + .../runtime/components/svelte-4/error.svelte | 6 + .../runtime/components/svelte-4/layout.svelte | 1 + .../runtime/components/svelte-5/error.svelte | 6 + .../runtime/components/svelte-5/layout.svelte | 5 + .../kit/src/runtime/env/dynamic/private.js | 1 + .../kit/src/runtime/env/dynamic/public.js | 1 + .../@sveltejs/kit/src/runtime/form-utils.js | 879 + .../@sveltejs/kit/src/runtime/pathname.js | 49 + .../kit/src/runtime/server/ambient.d.ts | 4 + .../@sveltejs/kit/src/runtime/server/app.js | 9 + .../kit/src/runtime/server/constants.js | 4 + .../kit/src/runtime/server/cookie.js | 334 + .../kit/src/runtime/server/data/index.js | 188 + .../kit/src/runtime/server/endpoint.js | 110 + .../kit/src/runtime/server/env_module.js | 29 + .../@sveltejs/kit/src/runtime/server/fetch.js | 238 + .../@sveltejs/kit/src/runtime/server/index.js | 178 + .../kit/src/runtime/server/page/actions.js | 358 + .../kit/src/runtime/server/page/crypto.js | 184 + .../kit/src/runtime/server/page/csp.js | 405 + .../runtime/server/page/data_serializer.js | 222 + .../kit/src/runtime/server/page/index.js | 427 + .../kit/src/runtime/server/page/load_data.js | 501 + .../kit/src/runtime/server/page/render.js | 777 + .../runtime/server/page/respond_with_error.js | 124 + .../src/runtime/server/page/serialize_data.js | 107 + .../src/runtime/server/page/server_routing.js | 127 + .../kit/src/runtime/server/page/types.d.ts | 57 + .../kit/src/runtime/server/remote.js | 334 + .../kit/src/runtime/server/respond.js | 752 + .../@sveltejs/kit/src/runtime/server/utils.js | 265 + .../src/runtime/server/validate-headers.js | 64 + .../kit/src/runtime/shared-server.js | 29 + .../@sveltejs/kit/src/runtime/shared.js | 93 + .../kit/src/runtime/telemetry/noop.js | 81 + .../kit/src/runtime/telemetry/otel.js | 21 + .../kit/src/runtime/telemetry/record_span.js | 65 + .../@sveltejs/kit/src/runtime/utils.js | 65 + .../kit/src/types/ambient-private.d.ts | 29 + .../@sveltejs/kit/src/types/ambient.d.ts | 148 + .../kit/src/types/global-private.d.ts | 65 + .../@sveltejs/kit/src/types/internal.d.ts | 643 + .../@sveltejs/kit/src/types/private.d.ts | 254 + .../types/synthetic/$env+dynamic+private.md | 43 + .../types/synthetic/$env+dynamic+public.md | 46 + .../types/synthetic/$env+static+private.md | 31 + .../src/types/synthetic/$env+static+public.md | 31 + .../@sveltejs/kit/src/types/synthetic/$lib.md | 5 + .../@sveltejs/kit/src/utils/array.js | 9 + .../@sveltejs/kit/src/utils/css.js | 213 + .../@sveltejs/kit/src/utils/env.js | 13 + .../@sveltejs/kit/src/utils/error.js | 38 + .../@sveltejs/kit/src/utils/escape.js | 71 + .../@sveltejs/kit/src/utils/exports.js | 93 + .../@sveltejs/kit/src/utils/features.js | 24 + .../@sveltejs/kit/src/utils/filesystem.js | 202 + .../@sveltejs/kit/src/utils/fork.js | 70 + .../@sveltejs/kit/src/utils/functions.js | 16 + .../@sveltejs/kit/src/utils/hash.js | 22 + .../@sveltejs/kit/src/utils/http.js | 82 + .../@sveltejs/kit/src/utils/import.js | 52 + .../@sveltejs/kit/src/utils/misc.js | 1 + .../@sveltejs/kit/src/utils/page_nodes.js | 95 + .../@sveltejs/kit/src/utils/promise.js | 29 + .../@sveltejs/kit/src/utils/routing.js | 307 + .../@sveltejs/kit/src/utils/streaming.js | 41 + .../@sveltejs/kit/src/utils/url.js | 201 + .../node_modules/@sveltejs/kit/src/version.js | 4 + .../node_modules/@sveltejs/kit/svelte-kit.js | 2 + .../@sveltejs/kit/types/index.d.ts | 3625 + .../@sveltejs/kit/types/index.d.ts.map | 232 + .../vite-plugin-svelte-inspector/LICENSE | 21 + .../vite-plugin-svelte-inspector/README.md | 26 + .../vite-plugin-svelte-inspector/package.json | 56 + .../vite-plugin-svelte-inspector/src/debug.js | 3 + .../vite-plugin-svelte-inspector/src/index.js | 112 + .../src/options.js | 63 + .../src/public.d.ts | 78 + .../src/runtime/Inspector.svelte | 411 + .../src/runtime/load-inspector.js | 14 + .../vite-plugin-svelte-inspector/src/utils.js | 8 + .../types/index.d.ts | 82 + .../types/index.d.ts.map | 17 + .../@sveltejs/vite-plugin-svelte/LICENSE | 21 + .../@sveltejs/vite-plugin-svelte/README.md | 28 + .../@sveltejs/vite-plugin-svelte/package.json | 62 + .../src/handle-hot-update.js | 145 + .../@sveltejs/vite-plugin-svelte/src/index.js | 220 + .../vite-plugin-svelte/src/preprocess.js | 124 + .../vite-plugin-svelte/src/public.d.ts | 210 + .../vite-plugin-svelte/src/types/compile.d.ts | 25 + .../vite-plugin-svelte/src/types/id.d.ts | 45 + .../vite-plugin-svelte/src/types/log.d.ts | 24 + .../vite-plugin-svelte/src/types/options.d.ts | 21 + .../src/types/plugin-api.d.ts | 11 + .../src/types/vite-plugin-svelte-stats.d.ts | 30 + .../vite-plugin-svelte/src/utils/compile.js | 191 + .../vite-plugin-svelte/src/utils/constants.js | 30 + .../src/utils/dependencies.js | 89 + .../vite-plugin-svelte/src/utils/error.js | 162 + .../vite-plugin-svelte/src/utils/esbuild.js | 177 + .../vite-plugin-svelte/src/utils/hash.js | 43 + .../vite-plugin-svelte/src/utils/id.js | 252 + .../vite-plugin-svelte/src/utils/load-raw.js | 125 + .../src/utils/load-svelte-config.js | 122 + .../vite-plugin-svelte/src/utils/log.js | 277 + .../vite-plugin-svelte/src/utils/optimizer.js | 53 + .../vite-plugin-svelte/src/utils/options.js | 620 + .../src/utils/preprocess.js | 173 + .../src/utils/sourcemaps.js | 82 + .../src/utils/svelte-version.js | 12 + .../src/utils/vite-plugin-svelte-cache.js | 212 + .../src/utils/vite-plugin-svelte-stats.js | 200 + .../vite-plugin-svelte/src/utils/watch.js | 120 + .../vite-plugin-svelte/types/index.d.ts | 216 + .../vite-plugin-svelte/types/index.d.ts.map | 26 + frontend/node_modules/@types/cookie/LICENSE | 21 + frontend/node_modules/@types/cookie/README.md | 15 + .../node_modules/@types/cookie/index.d.ts | 154 + .../node_modules/@types/cookie/package.json | 30 + frontend/node_modules/@types/estree/LICENSE | 21 + frontend/node_modules/@types/estree/README.md | 15 + frontend/node_modules/@types/estree/flow.d.ts | 167 + .../node_modules/@types/estree/index.d.ts | 694 + .../node_modules/@types/estree/package.json | 27 + .../node_modules/@types/trusted-types/LICENSE | 21 + .../@types/trusted-types/README.md | 15 + .../@types/trusted-types/index.d.ts | 53 + .../@types/trusted-types/lib/index.d.ts | 64 + .../@types/trusted-types/package.json | 45 + .../@typescript-eslint/types/LICENSE | 21 + .../@typescript-eslint/types/README.md | 12 + .../types/dist/generated/ast-spec.d.ts | 2163 + .../types/dist/generated/ast-spec.js | 200 + .../@typescript-eslint/types/dist/index.d.ts | 4 + .../@typescript-eslint/types/dist/index.js | 23 + .../@typescript-eslint/types/dist/lib.d.ts | 1 + .../@typescript-eslint/types/dist/lib.js | 6 + .../types/dist/parser-options.d.ts | 68 + .../types/dist/parser-options.js | 2 + .../types/dist/ts-estree.d.ts | 188 + .../types/dist/ts-estree.js | 37 + .../types/dist/tsconfig.build.tsbuildinfo | 1 + .../@typescript-eslint/types/package.json | 100 + frontend/node_modules/acorn/CHANGELOG.md | 972 + frontend/node_modules/acorn/LICENSE | 21 + frontend/node_modules/acorn/README.md | 301 + frontend/node_modules/acorn/bin/acorn | 4 + frontend/node_modules/acorn/dist/acorn.d.mts | 883 + frontend/node_modules/acorn/dist/acorn.d.ts | 883 + frontend/node_modules/acorn/dist/acorn.js | 6295 + frontend/node_modules/acorn/dist/acorn.mjs | 6266 + frontend/node_modules/acorn/dist/bin.js | 90 + frontend/node_modules/acorn/package.json | 50 + frontend/node_modules/aria-query/LICENSE | 201 + frontend/node_modules/aria-query/README.md | 195 + .../aria-query/lib/ariaPropsMap.js | 168 + .../node_modules/aria-query/lib/domMap.js | 311 + .../aria-query/lib/elementRoleMap.js | 151 + .../lib/etc/roles/abstract/commandRole.js | 22 + .../lib/etc/roles/abstract/compositeRole.js | 25 + .../lib/etc/roles/abstract/inputRole.js | 29 + .../lib/etc/roles/abstract/landmarkRole.js | 22 + .../lib/etc/roles/abstract/rangeRole.js | 26 + .../lib/etc/roles/abstract/roletypeRole.js | 50 + .../lib/etc/roles/abstract/sectionRole.js | 37 + .../lib/etc/roles/abstract/sectionheadRole.js | 22 + .../lib/etc/roles/abstract/selectRole.js | 24 + .../lib/etc/roles/abstract/structureRole.js | 22 + .../lib/etc/roles/abstract/widgetRole.js | 22 + .../lib/etc/roles/abstract/windowRole.js | 24 + .../lib/etc/roles/ariaAbstractRoles.js | 21 + .../aria-query/lib/etc/roles/ariaDpubRoles.js | 50 + .../lib/etc/roles/ariaGraphicsRoles.js | 12 + .../lib/etc/roles/ariaLiteralRoles.js | 92 + .../lib/etc/roles/dpub/docAbstractRole.js | 33 + .../etc/roles/dpub/docAcknowledgmentsRole.js | 33 + .../lib/etc/roles/dpub/docAfterwordRole.js | 33 + .../lib/etc/roles/dpub/docAppendixRole.js | 33 + .../lib/etc/roles/dpub/docBacklinkRole.js | 30 + .../lib/etc/roles/dpub/docBiblioentryRole.js | 33 + .../lib/etc/roles/dpub/docBibliographyRole.js | 33 + .../lib/etc/roles/dpub/docBibliorefRole.js | 30 + .../lib/etc/roles/dpub/docChapterRole.js | 33 + .../lib/etc/roles/dpub/docColophonRole.js | 33 + .../lib/etc/roles/dpub/docConclusionRole.js | 33 + .../lib/etc/roles/dpub/docCoverRole.js | 33 + .../lib/etc/roles/dpub/docCreditRole.js | 33 + .../lib/etc/roles/dpub/docCreditsRole.js | 33 + .../lib/etc/roles/dpub/docDedicationRole.js | 33 + .../lib/etc/roles/dpub/docEndnoteRole.js | 33 + .../lib/etc/roles/dpub/docEndnotesRole.js | 33 + .../lib/etc/roles/dpub/docEpigraphRole.js | 33 + .../lib/etc/roles/dpub/docEpilogueRole.js | 33 + .../lib/etc/roles/dpub/docErrataRole.js | 33 + .../lib/etc/roles/dpub/docExampleRole.js | 28 + .../lib/etc/roles/dpub/docFootnoteRole.js | 33 + .../lib/etc/roles/dpub/docForewordRole.js | 33 + .../lib/etc/roles/dpub/docGlossaryRole.js | 33 + .../lib/etc/roles/dpub/docGlossrefRole.js | 30 + .../lib/etc/roles/dpub/docIndexRole.js | 33 + .../lib/etc/roles/dpub/docIntroductionRole.js | 33 + .../lib/etc/roles/dpub/docNoterefRole.js | 30 + .../lib/etc/roles/dpub/docNoticeRole.js | 33 + .../lib/etc/roles/dpub/docPagebreakRole.js | 32 + .../lib/etc/roles/dpub/docPagefooterRole.js | 30 + .../lib/etc/roles/dpub/docPageheaderRole.js | 30 + .../lib/etc/roles/dpub/docPagelistRole.js | 33 + .../lib/etc/roles/dpub/docPartRole.js | 33 + .../lib/etc/roles/dpub/docPrefaceRole.js | 33 + .../lib/etc/roles/dpub/docPrologueRole.js | 33 + .../lib/etc/roles/dpub/docPullquoteRole.js | 27 + .../lib/etc/roles/dpub/docQnaRole.js | 33 + .../lib/etc/roles/dpub/docSubtitleRole.js | 33 + .../lib/etc/roles/dpub/docTipRole.js | 33 + .../lib/etc/roles/dpub/docTocRole.js | 33 + .../roles/graphics/graphicsDocumentRole.js | 43 + .../etc/roles/graphics/graphicsObjectRole.js | 47 + .../etc/roles/graphics/graphicsSymbolRole.js | 28 + .../lib/etc/roles/literal/alertRole.js | 30 + .../lib/etc/roles/literal/alertdialogRole.js | 27 + .../lib/etc/roles/literal/applicationRole.js | 33 + .../lib/etc/roles/literal/articleRole.js | 30 + .../lib/etc/roles/literal/bannerRole.js | 28 + .../lib/etc/roles/literal/blockquoteRole.js | 27 + .../lib/etc/roles/literal/buttonRole.js | 73 + .../lib/etc/roles/literal/captionRole.js | 27 + .../lib/etc/roles/literal/cellRole.js | 33 + .../lib/etc/roles/literal/checkboxRole.js | 45 + .../lib/etc/roles/literal/codeRole.js | 27 + .../lib/etc/roles/literal/columnheaderRole.js | 47 + .../lib/etc/roles/literal/comboboxRole.js | 124 + .../etc/roles/literal/complementaryRole.js | 48 + .../lib/etc/roles/literal/contentinfoRole.js | 28 + .../lib/etc/roles/literal/definitionRole.js | 27 + .../lib/etc/roles/literal/deletionRole.js | 27 + .../lib/etc/roles/literal/dialogRole.js | 27 + .../lib/etc/roles/literal/directoryRole.js | 24 + .../lib/etc/roles/literal/documentRole.js | 31 + .../lib/etc/roles/literal/emphasisRole.js | 27 + .../lib/etc/roles/literal/feedRole.js | 22 + .../lib/etc/roles/literal/figureRole.js | 27 + .../lib/etc/roles/literal/formRole.js | 49 + .../lib/etc/roles/literal/genericRole.js | 119 + .../etc/roles/literal/graphicsDocumentRole.js | 43 + .../etc/roles/literal/graphicsObjectRole.js | 47 + .../etc/roles/literal/graphicsSymbolRole.js | 28 + .../lib/etc/roles/literal/gridRole.js | 25 + .../lib/etc/roles/literal/gridcellRole.js | 37 + .../lib/etc/roles/literal/groupRole.js | 45 + .../lib/etc/roles/literal/headingRole.js | 56 + .../lib/etc/roles/literal/imgRole.js | 45 + .../lib/etc/roles/literal/insertionRole.js | 27 + .../lib/etc/roles/literal/linkRole.js | 44 + .../lib/etc/roles/literal/listRole.js | 37 + .../lib/etc/roles/literal/listboxRole.js | 63 + .../lib/etc/roles/literal/listitemRole.js | 37 + .../lib/etc/roles/literal/logRole.js | 24 + .../lib/etc/roles/literal/mainRole.js | 27 + .../lib/etc/roles/literal/markRole.js | 31 + .../lib/etc/roles/literal/marqueeRole.js | 22 + .../lib/etc/roles/literal/mathRole.js | 27 + .../lib/etc/roles/literal/menuRole.js | 44 + .../lib/etc/roles/literal/menubarRole.js | 29 + .../lib/etc/roles/literal/menuitemRole.js | 43 + .../etc/roles/literal/menuitemcheckboxRole.js | 29 + .../etc/roles/literal/menuitemradioRole.js | 29 + .../lib/etc/roles/literal/meterRole.js | 33 + .../lib/etc/roles/literal/navigationRole.js | 27 + .../lib/etc/roles/literal/noneRole.js | 22 + .../lib/etc/roles/literal/noteRole.js | 22 + .../lib/etc/roles/literal/optionRole.js | 44 + .../lib/etc/roles/literal/paragraphRole.js | 27 + .../lib/etc/roles/literal/presentationRole.js | 31 + .../lib/etc/roles/literal/progressbarRole.js | 34 + .../lib/etc/roles/literal/radioRole.js | 37 + .../lib/etc/roles/literal/radiogroupRole.js | 32 + .../lib/etc/roles/literal/regionRole.js | 44 + .../lib/etc/roles/literal/rowRole.js | 35 + .../lib/etc/roles/literal/rowgroupRole.js | 37 + .../lib/etc/roles/literal/rowheaderRole.js | 42 + .../lib/etc/roles/literal/scrollbarRole.js | 31 + .../lib/etc/roles/literal/searchRole.js | 22 + .../lib/etc/roles/literal/searchboxRole.js | 35 + .../lib/etc/roles/literal/separatorRole.js | 34 + .../lib/etc/roles/literal/sliderRole.js | 42 + .../lib/etc/roles/literal/spinbuttonRole.js | 38 + .../lib/etc/roles/literal/statusRole.js | 30 + .../lib/etc/roles/literal/strongRole.js | 27 + .../lib/etc/roles/literal/subscriptRole.js | 27 + .../lib/etc/roles/literal/superscriptRole.js | 27 + .../lib/etc/roles/literal/switchRole.js | 29 + .../lib/etc/roles/literal/tabRole.js | 29 + .../lib/etc/roles/literal/tableRole.js | 30 + .../lib/etc/roles/literal/tablistRole.js | 31 + .../lib/etc/roles/literal/tabpanelRole.js | 22 + .../lib/etc/roles/literal/termRole.js | 32 + .../lib/etc/roles/literal/textboxRole.js | 107 + .../lib/etc/roles/literal/timeRole.js | 27 + .../lib/etc/roles/literal/timerRole.js | 22 + .../lib/etc/roles/literal/toolbarRole.js | 29 + .../lib/etc/roles/literal/tooltipRole.js | 22 + .../lib/etc/roles/literal/treeRole.js | 28 + .../lib/etc/roles/literal/treegridRole.js | 22 + .../lib/etc/roles/literal/treeitemRole.js | 27 + frontend/node_modules/aria-query/lib/index.js | 17 + .../aria-query/lib/roleElementMap.js | 75 + .../node_modules/aria-query/lib/rolesMap.js | 116 + .../aria-query/lib/util/iterationDecorator.js | 17 + .../aria-query/lib/util/iteratorProxy.js | 32 + frontend/node_modules/aria-query/package.json | 70 + frontend/node_modules/axobject-query/LICENSE | 201 + .../node_modules/axobject-query/README.md | 404 + .../axobject-query/lib/AXObjectElementMap.js | 92 + .../axobject-query/lib/AXObjectRoleMap.js | 92 + .../axobject-query/lib/AXObjectsMap.js | 178 + .../axobject-query/lib/elementAXObjectMap.js | 128 + .../lib/etc/objects/AbbrRole.js | 17 + .../lib/etc/objects/AlertDialogRole.js | 17 + .../lib/etc/objects/AlertRole.js | 17 + .../lib/etc/objects/AnnotationRole.js | 12 + .../lib/etc/objects/ApplicationRole.js | 17 + .../lib/etc/objects/ArticleRole.js | 22 + .../lib/etc/objects/AudioRole.js | 17 + .../lib/etc/objects/BannerRole.js | 17 + .../lib/etc/objects/BlockquoteRole.js | 17 + .../lib/etc/objects/BusyIndicatorRole.js | 20 + .../lib/etc/objects/ButtonRole.js | 22 + .../lib/etc/objects/CanvasRole.js | 17 + .../lib/etc/objects/CaptionRole.js | 17 + .../lib/etc/objects/CellRole.js | 27 + .../lib/etc/objects/CheckBoxRole.js | 26 + .../lib/etc/objects/ColorWellRole.js | 21 + .../lib/etc/objects/ColumnHeaderRole.js | 22 + .../lib/etc/objects/ColumnRole.js | 12 + .../lib/etc/objects/ComboBoxRole.js | 22 + .../lib/etc/objects/ComplementaryRole.js | 17 + .../lib/etc/objects/ContentInfoRole.js | 17 + .../lib/etc/objects/DateRole.js | 21 + .../lib/etc/objects/DateTimeRole.js | 21 + .../lib/etc/objects/DefinitionRole.js | 17 + .../etc/objects/DescriptionListDetailRole.js | 17 + .../lib/etc/objects/DescriptionListRole.js | 17 + .../etc/objects/DescriptionListTermRole.js | 17 + .../lib/etc/objects/DetailsRole.js | 17 + .../lib/etc/objects/DialogRole.js | 22 + .../lib/etc/objects/DirectoryRole.js | 22 + .../lib/etc/objects/DisclosureTriangleRole.js | 18 + .../axobject-query/lib/etc/objects/DivRole.js | 17 + .../lib/etc/objects/DocumentRole.js | 17 + .../lib/etc/objects/EmbeddedObjectRole.js | 17 + .../lib/etc/objects/FeedRole.js | 17 + .../lib/etc/objects/FigcaptionRole.js | 17 + .../lib/etc/objects/FigureRole.js | 22 + .../lib/etc/objects/FooterRole.js | 17 + .../lib/etc/objects/FormRole.js | 22 + .../lib/etc/objects/GridRole.js | 17 + .../lib/etc/objects/GroupRole.js | 17 + .../lib/etc/objects/HeadingRole.js | 47 + .../etc/objects/IframePresentationalRole.js | 12 + .../lib/etc/objects/IframeRole.js | 17 + .../lib/etc/objects/IgnoredRole.js | 12 + .../lib/etc/objects/ImageMapLinkRole.js | 12 + .../lib/etc/objects/ImageMapRole.js | 20 + .../lib/etc/objects/ImageRole.js | 22 + .../lib/etc/objects/InlineTextBoxRole.js | 17 + .../lib/etc/objects/InputTimeRole.js | 21 + .../lib/etc/objects/LabelRole.js | 17 + .../lib/etc/objects/LegendRole.js | 17 + .../lib/etc/objects/LineBreakRole.js | 17 + .../lib/etc/objects/LinkRole.js | 25 + .../lib/etc/objects/ListBoxOptionRole.js | 22 + .../lib/etc/objects/ListBoxRole.js | 27 + .../lib/etc/objects/ListItemRole.js | 22 + .../lib/etc/objects/ListMarkerRole.js | 12 + .../lib/etc/objects/ListRole.js | 27 + .../axobject-query/lib/etc/objects/LogRole.js | 17 + .../lib/etc/objects/MainRole.js | 22 + .../lib/etc/objects/MarkRole.js | 17 + .../lib/etc/objects/MarqueeRole.js | 22 + .../lib/etc/objects/MathRole.js | 17 + .../lib/etc/objects/MenuBarRole.js | 17 + .../lib/etc/objects/MenuButtonRole.js | 12 + .../lib/etc/objects/MenuItemCheckBoxRole.js | 17 + .../lib/etc/objects/MenuItemRadioRole.js | 17 + .../lib/etc/objects/MenuItemRole.js | 22 + .../lib/etc/objects/MenuListOptionRole.js | 12 + .../lib/etc/objects/MenuListPopupRole.js | 12 + .../lib/etc/objects/MenuRole.js | 22 + .../lib/etc/objects/MeterRole.js | 17 + .../lib/etc/objects/NavigationRole.js | 22 + .../lib/etc/objects/NoneRole.js | 17 + .../lib/etc/objects/NoteRole.js | 17 + .../lib/etc/objects/OutlineRole.js | 12 + .../lib/etc/objects/ParagraphRole.js | 17 + .../lib/etc/objects/PopUpButtonRole.js | 12 + .../axobject-query/lib/etc/objects/PreRole.js | 17 + .../lib/etc/objects/PresentationalRole.js | 17 + .../lib/etc/objects/ProgressIndicatorRole.js | 22 + .../lib/etc/objects/RadioButtonRole.js | 26 + .../lib/etc/objects/RadioGroupRole.js | 17 + .../lib/etc/objects/RegionRole.js | 17 + .../lib/etc/objects/RootWebAreaRole.js | 12 + .../lib/etc/objects/RowHeaderRole.js | 26 + .../axobject-query/lib/etc/objects/RowRole.js | 22 + .../lib/etc/objects/RubyRole.js | 17 + .../lib/etc/objects/RulerRole.js | 12 + .../lib/etc/objects/SVGRootRole.js | 12 + .../lib/etc/objects/ScrollAreaRole.js | 12 + .../lib/etc/objects/ScrollBarRole.js | 17 + .../lib/etc/objects/SeamlessWebAreaRole.js | 12 + .../lib/etc/objects/SearchBoxRole.js | 26 + .../lib/etc/objects/SearchRole.js | 17 + .../lib/etc/objects/SliderRole.js | 26 + .../lib/etc/objects/SliderThumbRole.js | 12 + .../lib/etc/objects/SpinButtonPartRole.js | 12 + .../lib/etc/objects/SpinButtonRole.js | 26 + .../lib/etc/objects/SplitterRole.js | 17 + .../lib/etc/objects/StaticTextRole.js | 12 + .../lib/etc/objects/StatusRole.js | 17 + .../lib/etc/objects/SwitchRole.js | 26 + .../lib/etc/objects/TabGroupRole.js | 17 + .../lib/etc/objects/TabListRole.js | 17 + .../lib/etc/objects/TabPanelRole.js | 17 + .../axobject-query/lib/etc/objects/TabRole.js | 17 + .../etc/objects/TableHeaderContainerRole.js | 12 + .../lib/etc/objects/TableRole.js | 22 + .../lib/etc/objects/TermRole.js | 17 + .../lib/etc/objects/TextAreaRole.js | 26 + .../lib/etc/objects/TextFieldRole.js | 31 + .../lib/etc/objects/TimeRole.js | 17 + .../lib/etc/objects/TimerRole.js | 17 + .../lib/etc/objects/ToggleButtonRole.js | 19 + .../lib/etc/objects/ToolbarRole.js | 17 + .../lib/etc/objects/TreeGridRole.js | 17 + .../lib/etc/objects/TreeItemRole.js | 17 + .../lib/etc/objects/TreeRole.js | 17 + .../etc/objects/UserInterfaceTooltipRole.js | 17 + .../lib/etc/objects/VideoRole.js | 17 + .../lib/etc/objects/WebAreaRole.js | 12 + .../lib/etc/objects/WindowRole.js | 12 + .../node_modules/axobject-query/lib/index.js | 19 + .../lib/util/iterationDecorator.js | 17 + .../axobject-query/lib/util/iteratorProxy.js | 33 + .../node_modules/axobject-query/package.json | 69 + frontend/node_modules/clsx/clsx.d.mts | 6 + frontend/node_modules/clsx/clsx.d.ts | 10 + frontend/node_modules/clsx/dist/clsx.js | 1 + frontend/node_modules/clsx/dist/clsx.min.js | 1 + frontend/node_modules/clsx/dist/clsx.mjs | 1 + frontend/node_modules/clsx/dist/lite.js | 1 + frontend/node_modules/clsx/dist/lite.mjs | 1 + frontend/node_modules/clsx/license | 9 + frontend/node_modules/clsx/package.json | 60 + frontend/node_modules/clsx/readme.md | 154 + frontend/node_modules/cookie/HISTORY.md | 147 + frontend/node_modules/cookie/LICENSE | 24 + frontend/node_modules/cookie/README.md | 317 + frontend/node_modules/cookie/SECURITY.md | 25 + frontend/node_modules/cookie/index.js | 274 + frontend/node_modules/cookie/package.json | 44 + frontend/node_modules/debug/LICENSE | 20 + frontend/node_modules/debug/README.md | 481 + frontend/node_modules/debug/package.json | 64 + frontend/node_modules/debug/src/browser.js | 272 + frontend/node_modules/debug/src/common.js | 292 + frontend/node_modules/debug/src/index.js | 10 + frontend/node_modules/debug/src/node.js | 263 + frontend/node_modules/deepmerge/.editorconfig | 7 + frontend/node_modules/deepmerge/.eslintcache | 1 + frontend/node_modules/deepmerge/changelog.md | 167 + frontend/node_modules/deepmerge/dist/cjs.js | 133 + frontend/node_modules/deepmerge/dist/umd.js | 139 + frontend/node_modules/deepmerge/index.d.ts | 20 + frontend/node_modules/deepmerge/index.js | 106 + frontend/node_modules/deepmerge/license.txt | 21 + frontend/node_modules/deepmerge/package.json | 42 + frontend/node_modules/deepmerge/readme.md | 264 + .../node_modules/deepmerge/rollup.config.js | 22 + frontend/node_modules/devalue/LICENSE | 7 + frontend/node_modules/devalue/README.md | 228 + frontend/node_modules/devalue/index.js | 4 + frontend/node_modules/devalue/package.json | 37 + frontend/node_modules/devalue/src/base64.js | 110 + .../node_modules/devalue/src/constants.js | 7 + frontend/node_modules/devalue/src/parse.js | 265 + .../node_modules/devalue/src/stringify.js | 350 + frontend/node_modules/devalue/src/types.d.ts | 1 + frontend/node_modules/devalue/src/uneval.js | 490 + frontend/node_modules/devalue/src/utils.js | 148 + .../node_modules/devalue/src/utils.test.js | 63 + .../node_modules/devalue/types/index.d.ts | 36 + .../node_modules/devalue/types/index.d.ts.map | 25 + frontend/node_modules/esbuild/LICENSE.md | 21 + frontend/node_modules/esbuild/README.md | 3 + frontend/node_modules/esbuild/bin/esbuild | 220 + frontend/node_modules/esbuild/install.js | 285 + frontend/node_modules/esbuild/lib/main.d.ts | 705 + frontend/node_modules/esbuild/lib/main.js | 2239 + frontend/node_modules/esbuild/package.json | 46 + frontend/node_modules/esm-env/CHANGELOG.md | 19 + frontend/node_modules/esm-env/LICENSE | 7 + frontend/node_modules/esm-env/README.md | 27 + .../node_modules/esm-env/browser-fallback.js | 1 + frontend/node_modules/esm-env/dev-fallback.js | 2 + frontend/node_modules/esm-env/false.js | 1 + frontend/node_modules/esm-env/index.d.ts | 3 + frontend/node_modules/esm-env/index.js | 3 + frontend/node_modules/esm-env/package.json | 33 + frontend/node_modules/esm-env/true.js | 1 + frontend/node_modules/esrap/LICENSE | 7 + frontend/node_modules/esrap/README.md | 161 + frontend/node_modules/esrap/package.json | 59 + frontend/node_modules/esrap/src/context.js | 163 + frontend/node_modules/esrap/src/index.js | 165 + .../esrap/src/languages/ts/index.js | 2255 + .../esrap/src/languages/ts/public.d.ts | 2 + .../esrap/src/languages/tsx/index.js | 137 + .../esrap/src/languages/tsx/public.d.ts | 2 + .../esrap/src/languages/types.d.ts | 29 + frontend/node_modules/esrap/src/public.d.ts | 2 + frontend/node_modules/esrap/src/types.d.ts | 48 + frontend/node_modules/esrap/types/index.d.ts | 181 + .../node_modules/esrap/types/index.d.ts.map | 38 + frontend/node_modules/is-reference/README.md | 61 + .../node_modules/is-reference/package.json | 48 + .../node_modules/is-reference/src/index.js | 51 + .../is-reference/types/index.d.ts | 8 + .../is-reference/types/index.d.ts.map | 9 + frontend/node_modules/kleur/colors.d.ts | 38 + frontend/node_modules/kleur/colors.js | 53 + frontend/node_modules/kleur/colors.mjs | 53 + frontend/node_modules/kleur/index.d.ts | 45 + frontend/node_modules/kleur/index.js | 110 + frontend/node_modules/kleur/index.mjs | 110 + frontend/node_modules/kleur/license | 21 + frontend/node_modules/kleur/package.json | 51 + frontend/node_modules/kleur/readme.md | 232 + .../node_modules/locate-character/README.md | 66 + .../locate-character/package.json | 44 + .../locate-character/src/index.js | 72 + .../locate-character/src/types.d.ts | 17 + .../locate-character/types/index.d.ts | 19 + .../locate-character/types/index.d.ts.map | 19 + frontend/node_modules/magic-string/LICENSE | 7 + frontend/node_modules/magic-string/README.md | 325 + .../magic-string/dist/magic-string.cjs.d.ts | 289 + .../magic-string/dist/magic-string.cjs.js | 1594 + .../magic-string/dist/magic-string.cjs.js.map | 1 + .../magic-string/dist/magic-string.es.d.mts | 289 + .../magic-string/dist/magic-string.es.mjs | 1588 + .../magic-string/dist/magic-string.es.mjs.map | 1 + .../magic-string/dist/magic-string.umd.js | 1682 + .../magic-string/dist/magic-string.umd.js.map | 1 + .../node_modules/magic-string/package.json | 67 + frontend/node_modules/mrmime/index.d.ts | 2 + frontend/node_modules/mrmime/index.js | 449 + frontend/node_modules/mrmime/index.mjs | 448 + frontend/node_modules/mrmime/license | 21 + frontend/node_modules/mrmime/package.json | 44 + frontend/node_modules/mrmime/readme.md | 130 + frontend/node_modules/ms/index.js | 162 + frontend/node_modules/ms/license.md | 21 + frontend/node_modules/ms/package.json | 38 + frontend/node_modules/ms/readme.md | 59 + frontend/node_modules/nanoid/LICENSE | 20 + frontend/node_modules/nanoid/README.md | 39 + .../nanoid/async/index.browser.cjs | 69 + .../nanoid/async/index.browser.js | 34 + frontend/node_modules/nanoid/async/index.cjs | 71 + frontend/node_modules/nanoid/async/index.d.ts | 56 + frontend/node_modules/nanoid/async/index.js | 35 + .../node_modules/nanoid/async/index.native.js | 26 + .../node_modules/nanoid/async/package.json | 12 + frontend/node_modules/nanoid/bin/nanoid.cjs | 55 + .../node_modules/nanoid/index.browser.cjs | 72 + frontend/node_modules/nanoid/index.browser.js | 34 + frontend/node_modules/nanoid/index.cjs | 85 + frontend/node_modules/nanoid/index.d.cts | 91 + frontend/node_modules/nanoid/index.d.ts | 91 + frontend/node_modules/nanoid/index.js | 45 + frontend/node_modules/nanoid/nanoid.js | 1 + .../node_modules/nanoid/non-secure/index.cjs | 34 + .../node_modules/nanoid/non-secure/index.d.ts | 33 + .../node_modules/nanoid/non-secure/index.js | 21 + .../nanoid/non-secure/package.json | 6 + frontend/node_modules/nanoid/package.json | 89 + .../nanoid/url-alphabet/index.cjs | 7 + .../node_modules/nanoid/url-alphabet/index.js | 3 + .../nanoid/url-alphabet/package.json | 6 + frontend/node_modules/picocolors/LICENSE | 15 + frontend/node_modules/picocolors/README.md | 21 + frontend/node_modules/picocolors/package.json | 25 + .../picocolors/picocolors.browser.js | 4 + .../node_modules/picocolors/picocolors.d.ts | 5 + .../node_modules/picocolors/picocolors.js | 75 + frontend/node_modules/picocolors/types.d.ts | 51 + frontend/node_modules/postcss/LICENSE | 20 + frontend/node_modules/postcss/README.md | 29 + .../node_modules/postcss/lib/at-rule.d.ts | 140 + frontend/node_modules/postcss/lib/at-rule.js | 25 + .../node_modules/postcss/lib/comment.d.ts | 68 + frontend/node_modules/postcss/lib/comment.js | 13 + .../node_modules/postcss/lib/container.d.ts | 483 + .../node_modules/postcss/lib/container.js | 447 + .../postcss/lib/css-syntax-error.d.ts | 248 + .../postcss/lib/css-syntax-error.js | 133 + .../node_modules/postcss/lib/declaration.d.ts | 151 + .../node_modules/postcss/lib/declaration.js | 24 + .../node_modules/postcss/lib/document.d.ts | 69 + frontend/node_modules/postcss/lib/document.js | 33 + .../node_modules/postcss/lib/fromJSON.d.ts | 9 + frontend/node_modules/postcss/lib/fromJSON.js | 54 + frontend/node_modules/postcss/lib/input.d.ts | 227 + frontend/node_modules/postcss/lib/input.js | 265 + .../node_modules/postcss/lib/lazy-result.d.ts | 190 + .../node_modules/postcss/lib/lazy-result.js | 550 + frontend/node_modules/postcss/lib/list.d.ts | 60 + frontend/node_modules/postcss/lib/list.js | 58 + .../node_modules/postcss/lib/map-generator.js | 376 + .../postcss/lib/no-work-result.d.ts | 46 + .../postcss/lib/no-work-result.js | 137 + frontend/node_modules/postcss/lib/node.d.ts | 556 + frontend/node_modules/postcss/lib/node.js | 449 + frontend/node_modules/postcss/lib/parse.d.ts | 9 + frontend/node_modules/postcss/lib/parse.js | 42 + frontend/node_modules/postcss/lib/parser.js | 611 + .../node_modules/postcss/lib/postcss.d.mts | 69 + .../node_modules/postcss/lib/postcss.d.ts | 458 + frontend/node_modules/postcss/lib/postcss.js | 101 + frontend/node_modules/postcss/lib/postcss.mjs | 30 + .../postcss/lib/previous-map.d.ts | 81 + .../node_modules/postcss/lib/previous-map.js | 144 + .../node_modules/postcss/lib/processor.d.ts | 115 + .../node_modules/postcss/lib/processor.js | 67 + frontend/node_modules/postcss/lib/result.d.ts | 205 + frontend/node_modules/postcss/lib/result.js | 42 + frontend/node_modules/postcss/lib/root.d.ts | 87 + frontend/node_modules/postcss/lib/root.js | 61 + frontend/node_modules/postcss/lib/rule.d.ts | 126 + frontend/node_modules/postcss/lib/rule.js | 27 + .../node_modules/postcss/lib/stringifier.d.ts | 46 + .../node_modules/postcss/lib/stringifier.js | 353 + .../node_modules/postcss/lib/stringify.d.ts | 9 + .../node_modules/postcss/lib/stringify.js | 11 + frontend/node_modules/postcss/lib/symbols.js | 5 + .../postcss/lib/terminal-highlight.js | 70 + frontend/node_modules/postcss/lib/tokenize.js | 266 + .../node_modules/postcss/lib/warn-once.js | 13 + .../node_modules/postcss/lib/warning.d.ts | 147 + frontend/node_modules/postcss/lib/warning.js | 37 + frontend/node_modules/postcss/package.json | 88 + frontend/node_modules/rollup/LICENSE.md | 679 + frontend/node_modules/rollup/README.md | 134 + frontend/node_modules/rollup/dist/bin/rollup | 1912 + .../rollup/dist/es/getLogFilter.js | 64 + .../node_modules/rollup/dist/es/package.json | 1 + .../node_modules/rollup/dist/es/parseAst.js | 12 + .../node_modules/rollup/dist/es/rollup.js | 17 + .../rollup/dist/es/shared/node-entry.js | 24071 ++ .../rollup/dist/es/shared/parseAst.js | 2102 + .../rollup/dist/es/shared/watch.js | 9297 + .../rollup/dist/getLogFilter.d.ts | 5 + .../node_modules/rollup/dist/getLogFilter.js | 69 + .../rollup/dist/loadConfigFile.d.ts | 20 + .../rollup/dist/loadConfigFile.js | 29 + frontend/node_modules/rollup/dist/native.js | 161 + .../node_modules/rollup/dist/parseAst.d.ts | 4 + frontend/node_modules/rollup/dist/parseAst.js | 22 + frontend/node_modules/rollup/dist/rollup.d.ts | 1225 + frontend/node_modules/rollup/dist/rollup.js | 127 + .../rollup/dist/shared/fsevents-importer.js | 37 + .../node_modules/rollup/dist/shared/index.js | 9003 + .../rollup/dist/shared/loadConfigFile.js | 572 + .../rollup/dist/shared/parseAst.js | 2337 + .../node_modules/rollup/dist/shared/rollup.js | 23993 ++ .../rollup/dist/shared/watch-cli.js | 542 + .../node_modules/rollup/dist/shared/watch.js | 324 + frontend/node_modules/rollup/package.json | 288 + .../node_modules/set-cookie-parser/LICENSE | 21 + .../node_modules/set-cookie-parser/README.md | 169 + .../set-cookie-parser/dist/.eslintrc.cjs | 16 + .../set-cookie-parser/dist/set-cookie.cjs | 260 + .../set-cookie-parser/lib/set-cookie.d.ts | 119 + .../set-cookie-parser/lib/set-cookie.js | 265 + .../set-cookie-parser/package.json | 61 + frontend/node_modules/sirv/build.js | 197 + frontend/node_modules/sirv/build.mjs | 197 + frontend/node_modules/sirv/index.d.mts | 29 + frontend/node_modules/sirv/index.d.ts | 33 + frontend/node_modules/sirv/package.json | 40 + frontend/node_modules/sirv/readme.md | 238 + frontend/node_modules/source-map-js/LICENSE | 28 + frontend/node_modules/source-map-js/README.md | 765 + .../source-map-js/lib/array-set.js | 121 + .../source-map-js/lib/base64-vlq.js | 140 + .../node_modules/source-map-js/lib/base64.js | 67 + .../source-map-js/lib/binary-search.js | 111 + .../source-map-js/lib/mapping-list.js | 79 + .../source-map-js/lib/quick-sort.js | 132 + .../lib/source-map-consumer.d.ts | 1 + .../source-map-js/lib/source-map-consumer.js | 1188 + .../lib/source-map-generator.d.ts | 1 + .../source-map-js/lib/source-map-generator.js | 444 + .../source-map-js/lib/source-node.d.ts | 1 + .../source-map-js/lib/source-node.js | 413 + .../node_modules/source-map-js/lib/util.js | 594 + .../node_modules/source-map-js/package.json | 71 + .../source-map-js/source-map.d.ts | 104 + .../node_modules/source-map-js/source-map.js | 8 + frontend/node_modules/svelte/LICENSE.md | 7 + frontend/node_modules/svelte/README.md | 41 + frontend/node_modules/svelte/action.d.ts | 1 + frontend/node_modules/svelte/animate.d.ts | 1 + frontend/node_modules/svelte/compiler.d.ts | 1 + .../node_modules/svelte/compiler/index.js | 1 + .../node_modules/svelte/compiler/package.json | 3 + frontend/node_modules/svelte/easing.d.ts | 1 + frontend/node_modules/svelte/elements.d.ts | 2078 + frontend/node_modules/svelte/index.d.ts | 1 + frontend/node_modules/svelte/legacy.d.ts | 1 + frontend/node_modules/svelte/motion.d.ts | 1 + frontend/node_modules/svelte/package.json | 186 + .../node_modules/svelte/src/animate/index.js | 78 + .../svelte/src/attachments/index.js | 113 + .../svelte/src/compiler/errors.js | 1719 + .../node_modules/svelte/src/compiler/index.js | 201 + .../svelte/src/compiler/legacy.js | 637 + .../svelte/src/compiler/migrate/index.js | 1998 + .../src/compiler/phases/1-parse/acorn.js | 198 + .../src/compiler/phases/1-parse/index.js | 348 + .../compiler/phases/1-parse/read/context.js | 116 + .../phases/1-parse/read/expression.js | 93 + .../compiler/phases/1-parse/read/options.js | 263 + .../compiler/phases/1-parse/read/script.js | 97 + .../src/compiler/phases/1-parse/read/style.js | 637 + .../phases/1-parse/remove_typescript_nodes.js | 180 + .../compiler/phases/1-parse/state/element.js | 950 + .../compiler/phases/1-parse/state/fragment.js | 17 + .../src/compiler/phases/1-parse/state/tag.js | 751 + .../src/compiler/phases/1-parse/state/text.js | 23 + .../compiler/phases/1-parse/utils/bracket.js | 215 + .../compiler/phases/1-parse/utils/create.js | 16 + .../compiler/phases/1-parse/utils/entities.js | 2234 + .../phases/1-parse/utils/fuzzymatch.js | 281 + .../src/compiler/phases/1-parse/utils/html.js | 127 + .../phases/2-analyze/css/css-analyze.js | 331 + .../phases/2-analyze/css/css-prune.js | 1247 + .../compiler/phases/2-analyze/css/css-warn.js | 47 + .../compiler/phases/2-analyze/css/utils.js | 177 + .../src/compiler/phases/2-analyze/index.js | 1303 + .../2-analyze/utils/check_graph_for_cycles.js | 47 + .../2-analyze/visitors/AnimateDirective.js | 15 + .../visitors/ArrowFunctionExpression.js | 11 + .../visitors/AssignmentExpression.js | 31 + .../phases/2-analyze/visitors/AttachTag.js | 17 + .../phases/2-analyze/visitors/Attribute.js | 66 + .../phases/2-analyze/visitors/AwaitBlock.js | 48 + .../2-analyze/visitors/AwaitExpression.js | 150 + .../2-analyze/visitors/BindDirective.js | 280 + .../2-analyze/visitors/CallExpression.js | 339 + .../phases/2-analyze/visitors/ClassBody.js | 156 + .../2-analyze/visitors/ClassDeclaration.js | 25 + .../2-analyze/visitors/ClassDirective.js | 13 + .../phases/2-analyze/visitors/Component.js | 26 + .../phases/2-analyze/visitors/ConstTag.js | 45 + .../phases/2-analyze/visitors/DebugTag.js | 15 + .../phases/2-analyze/visitors/EachBlock.js | 97 + .../visitors/ExportDefaultDeclaration.js | 20 + .../visitors/ExportNamedDeclaration.js | 70 + .../2-analyze/visitors/ExportSpecifier.js | 30 + .../2-analyze/visitors/ExpressionStatement.js | 38 + .../2-analyze/visitors/ExpressionTag.js | 26 + .../phases/2-analyze/visitors/Fragment.js | 10 + .../2-analyze/visitors/FunctionDeclaration.js | 16 + .../2-analyze/visitors/FunctionExpression.js | 11 + .../phases/2-analyze/visitors/HtmlTag.js | 19 + .../phases/2-analyze/visitors/Identifier.js | 194 + .../phases/2-analyze/visitors/IfBlock.js | 46 + .../2-analyze/visitors/ImportDeclaration.js | 31 + .../phases/2-analyze/visitors/KeyBlock.js | 21 + .../2-analyze/visitors/LabeledStatement.js | 95 + .../phases/2-analyze/visitors/LetDirective.js | 24 + .../phases/2-analyze/visitors/Literal.js | 14 + .../2-analyze/visitors/MemberExpression.js | 28 + .../2-analyze/visitors/NewExpression.js | 17 + .../phases/2-analyze/visitors/OnDirective.js | 28 + .../2-analyze/visitors/PropertyDefinition.js | 21 + .../2-analyze/visitors/RegularElement.js | 240 + .../phases/2-analyze/visitors/RenderTag.js | 68 + .../phases/2-analyze/visitors/SlotElement.js | 42 + .../phases/2-analyze/visitors/SnippetBlock.js | 113 + .../2-analyze/visitors/SpreadAttribute.js | 13 + .../2-analyze/visitors/SpreadElement.js | 16 + .../2-analyze/visitors/StyleDirective.js | 39 + .../phases/2-analyze/visitors/SvelteBody.js | 22 + .../2-analyze/visitors/SvelteBoundary.js | 30 + .../2-analyze/visitors/SvelteComponent.js | 18 + .../2-analyze/visitors/SvelteDocument.js | 24 + .../2-analyze/visitors/SvelteElement.js | 78 + .../2-analyze/visitors/SvelteFragment.js | 27 + .../phases/2-analyze/visitors/SvelteHead.js | 18 + .../phases/2-analyze/visitors/SvelteSelf.js | 36 + .../phases/2-analyze/visitors/SvelteWindow.js | 24 + .../visitors/TaggedTemplateExpression.js | 16 + .../2-analyze/visitors/TemplateElement.js | 12 + .../phases/2-analyze/visitors/Text.js | 52 + .../phases/2-analyze/visitors/TitleElement.js | 21 + .../2-analyze/visitors/TransitionDirective.js | 19 + .../2-analyze/visitors/UpdateExpression.js | 29 + .../phases/2-analyze/visitors/UseDirective.js | 18 + .../2-analyze/visitors/VariableDeclarator.js | 160 + .../visitors/shared/a11y/constants.js | 334 + .../2-analyze/visitors/shared/a11y/index.js | 954 + .../2-analyze/visitors/shared/attribute.js | 125 + .../2-analyze/visitors/shared/component.js | 177 + .../2-analyze/visitors/shared/element.js | 160 + .../2-analyze/visitors/shared/fragment.js | 15 + .../2-analyze/visitors/shared/function.js | 24 + .../2-analyze/visitors/shared/snippets.js | 17 + .../visitors/shared/special-element.js | 16 + .../phases/2-analyze/visitors/shared/utils.js | 301 + .../3-transform/client/transform-client.js | 719 + .../fix-attribute-casing.js | 18 + .../client/transform-template/index.js | 67 + .../client/transform-template/template.js | 164 + .../phases/3-transform/client/utils.js | 181 + .../client/visitors/AnimateDirective.js | 38 + .../visitors/ArrowFunctionExpression.js | 11 + .../client/visitors/AssignmentExpression.js | 241 + .../3-transform/client/visitors/AttachTag.js | 26 + .../3-transform/client/visitors/Attribute.js | 14 + .../3-transform/client/visitors/AwaitBlock.js | 124 + .../client/visitors/AwaitExpression.js | 25 + .../client/visitors/BinaryExpression.js | 34 + .../client/visitors/BindDirective.js | 290 + .../client/visitors/BlockStatement.js | 32 + .../client/visitors/BreakStatement.js | 20 + .../client/visitors/CallExpression.js | 136 + .../3-transform/client/visitors/ClassBody.js | 111 + .../3-transform/client/visitors/Comment.js | 11 + .../3-transform/client/visitors/Component.js | 12 + .../3-transform/client/visitors/ConstTag.js | 134 + .../3-transform/client/visitors/DebugTag.js | 28 + .../3-transform/client/visitors/EachBlock.js | 362 + .../client/visitors/ExportNamedDeclaration.js | 19 + .../client/visitors/ExpressionStatement.js | 20 + .../client/visitors/ForOfStatement.js | 25 + .../3-transform/client/visitors/Fragment.js | 187 + .../client/visitors/FunctionDeclaration.js | 12 + .../client/visitors/FunctionExpression.js | 11 + .../3-transform/client/visitors/HtmlTag.js | 60 + .../3-transform/client/visitors/Identifier.js | 45 + .../3-transform/client/visitors/IfBlock.js | 131 + .../3-transform/client/visitors/KeyBlock.js | 45 + .../client/visitors/LabeledStatement.js | 64 + .../client/visitors/LetDirective.js | 55 + .../client/visitors/MemberExpression.js | 23 + .../client/visitors/OnDirective.js | 38 + .../3-transform/client/visitors/Program.js | 153 + .../client/visitors/RegularElement.js | 725 + .../3-transform/client/visitors/RenderTag.js | 95 + .../client/visitors/SlotElement.js | 94 + .../client/visitors/SnippetBlock.js | 94 + .../client/visitors/SpreadAttribute.js | 10 + .../3-transform/client/visitors/SvelteBody.js | 11 + .../client/visitors/SvelteBoundary.js | 126 + .../client/visitors/SvelteComponent.js | 13 + .../client/visitors/SvelteDocument.js | 11 + .../client/visitors/SvelteElement.js | 161 + .../client/visitors/SvelteFragment.js | 17 + .../3-transform/client/visitors/SvelteHead.js | 23 + .../3-transform/client/visitors/SvelteSelf.js | 13 + .../client/visitors/SvelteWindow.js | 11 + .../client/visitors/TitleElement.js | 48 + .../client/visitors/TransitionDirective.js | 41 + .../client/visitors/UpdateExpression.js | 55 + .../client/visitors/UseDirective.js | 49 + .../client/visitors/VariableDeclaration.js | 422 + .../client/visitors/shared/component.js | 536 + .../client/visitors/shared/declarations.js | 53 + .../client/visitors/shared/element.js | 263 + .../client/visitors/shared/events.js | 180 + .../client/visitors/shared/fragment.js | 187 + .../client/visitors/shared/function.js | 17 + .../client/visitors/shared/special_element.js | 22 + .../client/visitors/shared/utils.js | 517 + .../compiler/phases/3-transform/css/index.js | 479 + .../src/compiler/phases/3-transform/index.js | 118 + .../3-transform/server/transform-server.js | 428 + .../server/visitors/AssignmentExpression.js | 124 + .../3-transform/server/visitors/AwaitBlock.js | 36 + .../server/visitors/AwaitExpression.js | 40 + .../server/visitors/CallExpression.js | 71 + .../3-transform/server/visitors/ClassBody.js | 81 + .../3-transform/server/visitors/Component.js | 13 + .../3-transform/server/visitors/ConstTag.js | 49 + .../3-transform/server/visitors/DebugTag.js | 24 + .../3-transform/server/visitors/EachBlock.js | 76 + .../server/visitors/ExpressionStatement.js | 23 + .../3-transform/server/visitors/Fragment.js | 53 + .../3-transform/server/visitors/HtmlTag.js | 25 + .../3-transform/server/visitors/Identifier.js | 24 + .../3-transform/server/visitors/IfBlock.js | 48 + .../3-transform/server/visitors/KeyBlock.js | 22 + .../server/visitors/LabeledStatement.js | 24 + .../server/visitors/MemberExpression.js | 19 + .../3-transform/server/visitors/Program.js | 25 + .../server/visitors/PropertyDefinition.js | 37 + .../server/visitors/RegularElement.js | 216 + .../3-transform/server/visitors/RenderTag.js | 45 + .../server/visitors/SlotElement.js | 68 + .../server/visitors/SnippetBlock.js | 29 + .../server/visitors/SpreadAttribute.js | 10 + .../server/visitors/SvelteBoundary.js | 139 + .../server/visitors/SvelteComponent.js | 12 + .../server/visitors/SvelteElement.js | 89 + .../server/visitors/SvelteFragment.js | 11 + .../3-transform/server/visitors/SvelteHead.js | 25 + .../3-transform/server/visitors/SvelteSelf.js | 12 + .../server/visitors/TitleElement.js | 21 + .../server/visitors/UpdateExpression.js | 35 + .../server/visitors/VariableDeclaration.js | 247 + .../server/visitors/shared/component.js | 359 + .../server/visitors/shared/element.js | 561 + .../server/visitors/shared/utils.js | 408 + .../phases/3-transform/shared/assignments.js | 92 + .../3-transform/shared/transform-async.js | 115 + .../src/compiler/phases/3-transform/utils.js | 451 + .../svelte/src/compiler/phases/bindings.js | 227 + .../svelte/src/compiler/phases/css.js | 14 + .../svelte/src/compiler/phases/nodes.js | 258 + .../svelte/src/compiler/phases/patterns.js | 27 + .../svelte/src/compiler/phases/scope.js | 1471 + .../compiler/preprocess/decode_sourcemap.js | 96 + .../svelte/src/compiler/preprocess/index.js | 368 + .../compiler/preprocess/replace_in_code.js | 72 + .../svelte/src/compiler/print/index.js | 911 + .../node_modules/svelte/src/compiler/state.js | 175 + .../svelte/src/compiler/utils/assert.js | 9 + .../svelte/src/compiler/utils/ast.js | 639 + .../svelte/src/compiler/utils/builders.js | 698 + .../src/compiler/utils/compile_diagnostic.js | 106 + .../compiler/utils/extract_svelte_ignore.js | 104 + .../svelte/src/compiler/utils/mapped_code.js | 454 + .../svelte/src/compiler/utils/push_array.js | 13 + .../utils/sanitize_template_string.js | 7 + .../svelte/src/compiler/utils/slot.js | 20 + .../svelte/src/compiler/utils/string.js | 9 + .../svelte/src/compiler/validate-options.js | 361 + .../svelte/src/compiler/warnings.js | 845 + frontend/node_modules/svelte/src/constants.js | 66 + .../node_modules/svelte/src/easing/index.js | 286 + frontend/node_modules/svelte/src/escaping.js | 26 + .../node_modules/svelte/src/events/index.js | 1 + .../svelte/src/html-tree-validation.js | 238 + .../node_modules/svelte/src/index-client.js | 255 + .../node_modules/svelte/src/index-server.js | 56 + .../svelte/src/internal/client/constants.js | 79 + .../svelte/src/internal/client/context.js | 259 + .../svelte/src/internal/client/dev/assign.js | 67 + .../src/internal/client/dev/console-log.js | 37 + .../svelte/src/internal/client/dev/css.js | 31 + .../svelte/src/internal/client/dev/debug.js | 518 + .../src/internal/client/dev/elements.js | 63 + .../src/internal/client/dev/equality.js | 101 + .../svelte/src/internal/client/dev/hmr.js | 102 + .../svelte/src/internal/client/dev/inspect.js | 72 + .../svelte/src/internal/client/dev/legacy.js | 25 + .../src/internal/client/dev/ownership.js | 81 + .../svelte/src/internal/client/dev/tracing.js | 162 + .../src/internal/client/dev/validation.js | 16 + .../src/internal/client/dom/blocks/async.js | 71 + .../src/internal/client/dom/blocks/await.js | 149 + .../internal/client/dom/blocks/boundary.js | 522 + .../internal/client/dom/blocks/branches.js | 228 + .../internal/client/dom/blocks/css-props.js | 28 + .../src/internal/client/dom/blocks/each.js | 765 + .../src/internal/client/dom/blocks/html.js | 160 + .../src/internal/client/dom/blocks/if.js | 72 + .../src/internal/client/dom/blocks/key.js | 40 + .../src/internal/client/dom/blocks/slot.js | 44 + .../src/internal/client/dom/blocks/snippet.js | 103 + .../client/dom/blocks/svelte-component.js | 61 + .../client/dom/blocks/svelte-element.js | 152 + .../internal/client/dom/blocks/svelte-head.js | 61 + .../svelte/src/internal/client/dom/css.js | 33 + .../internal/client/dom/elements/actions.js | 43 + .../client/dom/elements/attachments.js | 33 + .../client/dom/elements/attributes.js | 657 + .../client/dom/elements/bindings/document.js | 17 + .../client/dom/elements/bindings/input.js | 314 + .../client/dom/elements/bindings/media.js | 233 + .../client/dom/elements/bindings/navigator.js | 11 + .../client/dom/elements/bindings/props.js | 22 + .../client/dom/elements/bindings/select.js | 164 + .../client/dom/elements/bindings/shared.js | 76 + .../client/dom/elements/bindings/size.js | 107 + .../client/dom/elements/bindings/this.js | 78 + .../client/dom/elements/bindings/universal.js | 75 + .../client/dom/elements/bindings/window.js | 66 + .../src/internal/client/dom/elements/class.js | 51 + .../client/dom/elements/custom-element.js | 344 + .../dom/elements/customizable-select.js | 99 + .../internal/client/dom/elements/events.js | 355 + .../src/internal/client/dom/elements/misc.js | 58 + .../src/internal/client/dom/elements/style.js | 57 + .../client/dom/elements/transitions.js | 471 + .../src/internal/client/dom/hydration.js | 125 + .../client/dom/legacy/event-modifiers.js | 127 + .../internal/client/dom/legacy/lifecycle.js | 82 + .../src/internal/client/dom/legacy/misc.js | 68 + .../src/internal/client/dom/operations.js | 293 + .../src/internal/client/dom/reconciler.js | 25 + .../svelte/src/internal/client/dom/task.js | 42 + .../src/internal/client/dom/template.js | 401 + .../src/internal/client/error-handling.js | 118 + .../svelte/src/internal/client/errors.js | 510 + .../svelte/src/internal/client/hydratable.js | 33 + .../svelte/src/internal/client/index.js | 183 + .../svelte/src/internal/client/legacy.js | 46 + .../svelte/src/internal/client/loop.js | 48 + .../svelte/src/internal/client/proxy.js | 432 + .../src/internal/client/reactivity/async.js | 321 + .../src/internal/client/reactivity/batch.js | 1113 + .../internal/client/reactivity/deriveds.js | 466 + .../src/internal/client/reactivity/effects.js | 739 + .../internal/client/reactivity/equality.js | 31 + .../src/internal/client/reactivity/props.js | 430 + .../src/internal/client/reactivity/sources.js | 388 + .../src/internal/client/reactivity/status.js | 25 + .../src/internal/client/reactivity/store.js | 224 + .../src/internal/client/reactivity/utils.js | 40 + .../svelte/src/internal/client/render.js | 335 + .../svelte/src/internal/client/runtime.js | 829 + .../svelte/src/internal/client/timing.js | 16 + .../svelte/src/internal/client/validate.js | 54 + .../svelte/src/internal/client/warnings.js | 271 + .../svelte/src/internal/disclose-version.js | 6 + .../svelte/src/internal/flags/async.js | 3 + .../svelte/src/internal/flags/index.js | 23 + .../svelte/src/internal/flags/legacy.js | 3 + .../svelte/src/internal/flags/tracing.js | 3 + .../node_modules/svelte/src/internal/index.js | 5 + .../src/internal/server/abort-signal.js | 13 + .../svelte/src/internal/server/blocks/html.js | 11 + .../src/internal/server/blocks/snippet.js | 24 + .../svelte/src/internal/server/context.js | 132 + .../svelte/src/internal/server/crypto.js | 45 + .../svelte/src/internal/server/dev.js | 115 + .../svelte/src/internal/server/errors.js | 131 + .../svelte/src/internal/server/hydratable.js | 142 + .../svelte/src/internal/server/hydration.js | 6 + .../svelte/src/internal/server/index.js | 543 + .../src/internal/server/render-context.js | 86 + .../svelte/src/internal/server/renderer.js | 937 + .../svelte/src/internal/server/warnings.js | 29 + .../svelte/src/internal/shared/attributes.js | 225 + .../svelte/src/internal/shared/clone.js | 137 + .../svelte/src/internal/shared/dev.js | 79 + .../svelte/src/internal/shared/errors.js | 151 + .../svelte/src/internal/shared/utils.js | 144 + .../svelte/src/internal/shared/validate.js | 47 + .../svelte/src/internal/shared/warnings.js | 40 + .../svelte/src/legacy/legacy-client.js | 281 + .../svelte/src/legacy/legacy-server.js | 112 + .../node_modules/svelte/src/motion/index.js | 32 + .../node_modules/svelte/src/motion/spring.js | 369 + .../node_modules/svelte/src/motion/tweened.js | 306 + .../node_modules/svelte/src/motion/utils.js | 7 + .../src/reactivity/create-subscriber.js | 95 + .../svelte/src/reactivity/date.js | 118 + .../svelte/src/reactivity/index-client.js | 7 + .../svelte/src/reactivity/index-server.js | 23 + .../node_modules/svelte/src/reactivity/map.js | 274 + .../svelte/src/reactivity/media-query.js | 55 + .../svelte/src/reactivity/reactive-value.js | 24 + .../node_modules/svelte/src/reactivity/set.js | 213 + .../src/reactivity/url-search-params.js | 174 + .../node_modules/svelte/src/reactivity/url.js | 205 + .../svelte/src/reactivity/window/index.js | 161 + .../node_modules/svelte/src/server/index.js | 1 + .../svelte/src/store/index-client.js | 169 + .../svelte/src/store/index-server.js | 101 + .../svelte/src/store/shared/index.js | 209 + .../node_modules/svelte/src/store/utils.js | 36 + .../svelte/src/transition/index.js | 300 + frontend/node_modules/svelte/src/utils.js | 504 + frontend/node_modules/svelte/src/version.js | 8 + frontend/node_modules/svelte/store.d.ts | 1 + frontend/node_modules/svelte/svelte-html.d.ts | 245 + frontend/node_modules/svelte/transition.d.ts | 1 + .../svelte/types/compiler/interfaces.d.ts | 1 + .../svelte/types/compiler/preprocess.d.ts | 1 + frontend/node_modules/svelte/types/index.d.ts | 3752 + .../node_modules/svelte/types/index.d.ts.map | 280 + frontend/node_modules/totalist/dist/index.js | 24 + frontend/node_modules/totalist/dist/index.mjs | 22 + frontend/node_modules/totalist/index.d.ts | 3 + frontend/node_modules/totalist/license | 21 + frontend/node_modules/totalist/package.json | 55 + frontend/node_modules/totalist/readme.md | 109 + .../node_modules/totalist/sync/index.d.ts | 3 + frontend/node_modules/totalist/sync/index.js | 17 + frontend/node_modules/totalist/sync/index.mjs | 15 + frontend/node_modules/typescript/LICENSE.txt | 55 + frontend/node_modules/typescript/README.md | 50 + frontend/node_modules/typescript/SECURITY.md | 41 + .../typescript/ThirdPartyNoticeText.txt | 193 + frontend/node_modules/typescript/bin/tsc | 2 + frontend/node_modules/typescript/bin/tsserver | 2 + frontend/node_modules/typescript/lib/_tsc.js | 133818 ++++++++++ .../node_modules/typescript/lib/_tsserver.js | 659 + .../typescript/lib/_typingsInstaller.js | 222 + .../lib/cs/diagnosticMessages.generated.json | 2122 + .../lib/de/diagnosticMessages.generated.json | 2122 + .../lib/es/diagnosticMessages.generated.json | 2122 + .../lib/fr/diagnosticMessages.generated.json | 2122 + .../lib/it/diagnosticMessages.generated.json | 2122 + .../lib/ja/diagnosticMessages.generated.json | 2122 + .../lib/ko/diagnosticMessages.generated.json | 2122 + frontend/node_modules/typescript/lib/lib.d.ts | 22 + .../typescript/lib/lib.decorators.d.ts | 384 + .../typescript/lib/lib.decorators.legacy.d.ts | 22 + .../typescript/lib/lib.dom.asynciterable.d.ts | 41 + .../node_modules/typescript/lib/lib.dom.d.ts | 39429 +++ .../typescript/lib/lib.dom.iterable.d.ts | 571 + .../typescript/lib/lib.es2015.collection.d.ts | 147 + .../typescript/lib/lib.es2015.core.d.ts | 597 + .../typescript/lib/lib.es2015.d.ts | 28 + .../typescript/lib/lib.es2015.generator.d.ts | 77 + .../typescript/lib/lib.es2015.iterable.d.ts | 605 + .../typescript/lib/lib.es2015.promise.d.ts | 81 + .../typescript/lib/lib.es2015.proxy.d.ts | 128 + .../typescript/lib/lib.es2015.reflect.d.ts | 144 + .../typescript/lib/lib.es2015.symbol.d.ts | 46 + .../lib/lib.es2015.symbol.wellknown.d.ts | 326 + .../lib/lib.es2016.array.include.d.ts | 116 + .../typescript/lib/lib.es2016.d.ts | 21 + .../typescript/lib/lib.es2016.full.d.ts | 23 + .../typescript/lib/lib.es2016.intl.d.ts | 31 + .../lib/lib.es2017.arraybuffer.d.ts | 21 + .../typescript/lib/lib.es2017.d.ts | 26 + .../typescript/lib/lib.es2017.date.d.ts | 31 + .../typescript/lib/lib.es2017.full.d.ts | 23 + .../typescript/lib/lib.es2017.intl.d.ts | 44 + .../typescript/lib/lib.es2017.object.d.ts | 49 + .../lib/lib.es2017.sharedmemory.d.ts | 135 + .../typescript/lib/lib.es2017.string.d.ts | 45 + .../lib/lib.es2017.typedarrays.d.ts | 53 + .../lib/lib.es2018.asyncgenerator.d.ts | 77 + .../lib/lib.es2018.asynciterable.d.ts | 53 + .../typescript/lib/lib.es2018.d.ts | 24 + .../typescript/lib/lib.es2018.full.d.ts | 24 + .../typescript/lib/lib.es2018.intl.d.ts | 83 + .../typescript/lib/lib.es2018.promise.d.ts | 30 + .../typescript/lib/lib.es2018.regexp.d.ts | 37 + .../typescript/lib/lib.es2019.array.d.ts | 79 + .../typescript/lib/lib.es2019.d.ts | 24 + .../typescript/lib/lib.es2019.full.d.ts | 24 + .../typescript/lib/lib.es2019.intl.d.ts | 23 + .../typescript/lib/lib.es2019.object.d.ts | 33 + .../typescript/lib/lib.es2019.string.d.ts | 37 + .../typescript/lib/lib.es2019.symbol.d.ts | 24 + .../typescript/lib/lib.es2020.bigint.d.ts | 765 + .../typescript/lib/lib.es2020.d.ts | 27 + .../typescript/lib/lib.es2020.date.d.ts | 42 + .../typescript/lib/lib.es2020.full.d.ts | 24 + .../typescript/lib/lib.es2020.intl.d.ts | 474 + .../typescript/lib/lib.es2020.number.d.ts | 28 + .../typescript/lib/lib.es2020.promise.d.ts | 47 + .../lib/lib.es2020.sharedmemory.d.ts | 99 + .../typescript/lib/lib.es2020.string.d.ts | 44 + .../lib/lib.es2020.symbol.wellknown.d.ts | 41 + .../typescript/lib/lib.es2021.d.ts | 23 + .../typescript/lib/lib.es2021.full.d.ts | 24 + .../typescript/lib/lib.es2021.intl.d.ts | 166 + .../typescript/lib/lib.es2021.promise.d.ts | 48 + .../typescript/lib/lib.es2021.string.d.ts | 33 + .../typescript/lib/lib.es2021.weakref.d.ts | 78 + .../typescript/lib/lib.es2022.array.d.ts | 121 + .../typescript/lib/lib.es2022.d.ts | 25 + .../typescript/lib/lib.es2022.error.d.ts | 75 + .../typescript/lib/lib.es2022.full.d.ts | 24 + .../typescript/lib/lib.es2022.intl.d.ts | 145 + .../typescript/lib/lib.es2022.object.d.ts | 26 + .../typescript/lib/lib.es2022.regexp.d.ts | 39 + .../typescript/lib/lib.es2022.string.d.ts | 25 + .../typescript/lib/lib.es2023.array.d.ts | 924 + .../typescript/lib/lib.es2023.collection.d.ts | 21 + .../typescript/lib/lib.es2023.d.ts | 22 + .../typescript/lib/lib.es2023.full.d.ts | 24 + .../typescript/lib/lib.es2023.intl.d.ts | 56 + .../lib/lib.es2024.arraybuffer.d.ts | 65 + .../typescript/lib/lib.es2024.collection.d.ts | 29 + .../typescript/lib/lib.es2024.d.ts | 26 + .../typescript/lib/lib.es2024.full.d.ts | 24 + .../typescript/lib/lib.es2024.object.d.ts | 29 + .../typescript/lib/lib.es2024.promise.d.ts | 35 + .../typescript/lib/lib.es2024.regexp.d.ts | 25 + .../lib/lib.es2024.sharedmemory.d.ts | 68 + .../typescript/lib/lib.es2024.string.d.ts | 29 + .../node_modules/typescript/lib/lib.es5.d.ts | 4601 + .../node_modules/typescript/lib/lib.es6.d.ts | 23 + .../typescript/lib/lib.esnext.array.d.ts | 35 + .../typescript/lib/lib.esnext.collection.d.ts | 96 + .../typescript/lib/lib.esnext.d.ts | 29 + .../typescript/lib/lib.esnext.decorators.d.ts | 28 + .../typescript/lib/lib.esnext.disposable.d.ts | 193 + .../typescript/lib/lib.esnext.error.d.ts | 24 + .../typescript/lib/lib.esnext.float16.d.ts | 445 + .../typescript/lib/lib.esnext.full.d.ts | 24 + .../typescript/lib/lib.esnext.intl.d.ts | 21 + .../typescript/lib/lib.esnext.iterator.d.ts | 148 + .../typescript/lib/lib.esnext.promise.d.ts | 34 + .../lib/lib.esnext.sharedmemory.d.ts | 25 + .../typescript/lib/lib.scripthost.d.ts | 322 + .../lib/lib.webworker.asynciterable.d.ts | 41 + .../typescript/lib/lib.webworker.d.ts | 13150 + .../lib/lib.webworker.importscripts.d.ts | 23 + .../lib/lib.webworker.iterable.d.ts | 340 + .../lib/pl/diagnosticMessages.generated.json | 2122 + .../pt-br/diagnosticMessages.generated.json | 2122 + .../lib/ru/diagnosticMessages.generated.json | 2122 + .../lib/tr/diagnosticMessages.generated.json | 2122 + frontend/node_modules/typescript/lib/tsc.js | 8 + .../node_modules/typescript/lib/tsserver.js | 8 + .../typescript/lib/tsserverlibrary.d.ts | 17 + .../typescript/lib/tsserverlibrary.js | 21 + .../node_modules/typescript/lib/typesMap.json | 497 + .../typescript/lib/typescript.d.ts | 11437 + .../node_modules/typescript/lib/typescript.js | 200276 +++++++++++++++ .../typescript/lib/typingsInstaller.js | 8 + .../node_modules/typescript/lib/watchGuard.js | 53 + .../zh-cn/diagnosticMessages.generated.json | 2122 + .../zh-tw/diagnosticMessages.generated.json | 2122 + frontend/node_modules/typescript/package.json | 120 + frontend/node_modules/vite/LICENSE.md | 3423 + frontend/node_modules/vite/README.md | 20 + .../vite/bin/openChrome.applescript | 95 + frontend/node_modules/vite/bin/vite.js | 61 + frontend/node_modules/vite/client.d.ts | 256 + .../node_modules/vite/dist/client/client.mjs | 829 + .../node_modules/vite/dist/client/env.mjs | 24 + .../vite/dist/node-cjs/publicUtils.cjs | 6172 + .../vite/dist/node/chunks/dep-BB45zftN.js | 993 + .../vite/dist/node/chunks/dep-BK3b2jBa.js | 67048 +++++ .../vite/dist/node/chunks/dep-D-7KCb9p.js | 7960 + .../vite/dist/node/chunks/dep-Dnp7gl8U.js | 7004 + .../vite/dist/node/chunks/dep-IQS-Za7F.js | 561 + frontend/node_modules/vite/dist/node/cli.js | 917 + .../node_modules/vite/dist/node/constants.js | 113 + .../node_modules/vite/dist/node/index.d.ts | 3627 + frontend/node_modules/vite/dist/node/index.js | 261 + .../node_modules/vite/dist/node/runtime.d.ts | 63 + .../node_modules/vite/dist/node/runtime.js | 1066 + .../vite/dist/node/types.d-aGj9QkWt.d.ts | 281 + frontend/node_modules/vite/index.cjs | 60 + frontend/node_modules/vite/index.d.cts | 6 + frontend/node_modules/vite/package.json | 191 + .../node_modules/vite/types/customEvent.d.ts | 39 + .../node_modules/vite/types/hmrPayload.d.ts | 65 + frontend/node_modules/vite/types/hot.d.ts | 36 + .../node_modules/vite/types/import-meta.d.ts | 5 + .../node_modules/vite/types/importGlob.d.ts | 75 + .../node_modules/vite/types/importMeta.d.ts | 22 + .../node_modules/vite/types/metadata.d.ts | 10 + frontend/node_modules/vite/types/package.json | 4 + frontend/node_modules/vitefu/LICENSE | 21 + frontend/node_modules/vitefu/README.md | 11 + frontend/node_modules/vitefu/package.json | 51 + frontend/node_modules/vitefu/src/index.cjs | 18 + frontend/node_modules/vitefu/src/index.d.cts | 59 + frontend/node_modules/vitefu/src/index.d.ts | 187 + frontend/node_modules/vitefu/src/index.js | 315 + frontend/node_modules/vitefu/src/sync.cjs | 66 + frontend/node_modules/zimmerframe/LICENSE | 21 + frontend/node_modules/zimmerframe/README.md | 180 + .../node_modules/zimmerframe/package.json | 35 + .../node_modules/zimmerframe/src/index.d.ts | 2 + .../node_modules/zimmerframe/src/types.d.ts | 21 + frontend/node_modules/zimmerframe/src/walk.js | 168 + .../node_modules/zimmerframe/types/index.d.ts | 30 + .../zimmerframe/types/index.d.ts.map | 23 + frontend/package.json | 19 + frontend/src/app.html | 12 + frontend/src/lib/api/client.ts | 190 + frontend/src/lib/stores/auth.ts | 38 + frontend/src/routes/+layout.svelte | 184 + frontend/src/routes/+page.svelte | 97 + frontend/src/routes/aliases/+page.svelte | 10 + .../routes/auth/change-password/+page.svelte | 283 + .../src/routes/auth/dashboard/+page.svelte | 187 + frontend/src/routes/auth/forgot/+page.svelte | 198 + frontend/src/routes/auth/login/+page.svelte | 189 + frontend/src/routes/domains/+page.svelte | 190 + .../src/routes/domains/[name]/+page.svelte | 114 + .../domains/[name]/aliases/+page.svelte | 227 + .../routes/domains/[name]/users/+page.svelte | 243 + frontend/src/routes/logs/+page.svelte | 165 + frontend/src/routes/queue/+page.svelte | 160 + frontend/src/routes/users/+page.svelte | 10 + frontend/static/favicon.png | 4 + frontend/svelte.config.js | 22 + frontend/tsconfig.json | 14 + frontend/vite.config.ts | 6 + 1826 files changed, 830924 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 backend/.env create mode 100644 backend/.env.example create mode 100644 backend/cmd/server/embed/_app/env.js create mode 100644 backend/cmd/server/embed/_app/immutable/assets/0.DkgBtk4_.css create mode 100644 backend/cmd/server/embed/_app/immutable/assets/10.Qar-kS8x.css create mode 100644 backend/cmd/server/embed/_app/immutable/assets/11.D38O3Xxc.css create mode 100644 backend/cmd/server/embed/_app/immutable/assets/12.DQdHIvb_.css create mode 100644 backend/cmd/server/embed/_app/immutable/assets/13.DnP_H9DZ.css create mode 100644 backend/cmd/server/embed/_app/immutable/assets/2.By2d6Bxb.css create mode 100644 backend/cmd/server/embed/_app/immutable/assets/4.CG2X--Z8.css create mode 100644 backend/cmd/server/embed/_app/immutable/assets/5.YbbfqdJp.css create mode 100644 backend/cmd/server/embed/_app/immutable/assets/6.w_qTFDpy.css create mode 100644 backend/cmd/server/embed/_app/immutable/assets/7.Bq7myTre.css create mode 100644 backend/cmd/server/embed/_app/immutable/assets/8.neQUdyXe.css create mode 100644 backend/cmd/server/embed/_app/immutable/assets/9.Ci0QlAaW.css create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/-EcHSJia.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/B3ZK_jYJ.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/B7kAneMc.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/BX-b5t2l.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/BYrNiJ2z.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/CJv7FbHz.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/CfgL3m1f.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/DFRBE_Uq.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/DR7h53-u.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/DtGl34IE.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/RKc8iKz_.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/ayyTDfEa.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/e1WBZ7UL.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/ecAlPOj8.js create mode 100644 backend/cmd/server/embed/_app/immutable/chunks/n1byU5WW.js create mode 100644 backend/cmd/server/embed/_app/immutable/entry/app.BI_Sozkn.js create mode 100644 backend/cmd/server/embed/_app/immutable/entry/start.tprRzko2.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/0.D3wXY_0K.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/1.Dgii_8lh.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/10.BvOkMiuT.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/11.DnvWFHPj.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/12.CRx3MqWn.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/13.CB7FlS8h.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/14.CFDiiGpK.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/2.BMCUuUxB.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/3.CFDiiGpK.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/4.YDL696B2.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/5.DHfYhdex.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/6.BiQ3_GJa.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/7.BEIquz8f.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/8.D4QctIPu.js create mode 100644 backend/cmd/server/embed/_app/immutable/nodes/9.DflEy3LG.js create mode 100644 backend/cmd/server/embed/_app/version.json create mode 100644 backend/cmd/server/embed/favicon.png create mode 100644 backend/cmd/server/embed/index.html create mode 100644 backend/cmd/server/frontend.go create mode 100644 backend/cmd/server/main.go create mode 100644 backend/go.mod create mode 100644 backend/go.sum create mode 100644 backend/internal/api/handlers/aliases.go create mode 100644 backend/internal/api/handlers/auth.go create mode 100644 backend/internal/api/handlers/domains.go create mode 100644 backend/internal/api/handlers/logs.go create mode 100644 backend/internal/api/handlers/middleware.go create mode 100644 backend/internal/api/handlers/queue.go create mode 100644 backend/internal/api/handlers/response.go create mode 100644 backend/internal/api/handlers/stats.go create mode 100644 backend/internal/api/handlers/users.go create mode 100644 backend/internal/api/router.go create mode 100644 backend/internal/auth/jwt.go create mode 100644 backend/internal/auth/rbac.go create mode 100644 backend/internal/config/config.go create mode 100644 backend/internal/db/aliases.go create mode 100644 backend/internal/db/db.go create mode 100644 backend/internal/db/domains.go create mode 100644 backend/internal/db/imc_users.go create mode 100644 backend/internal/db/users.go create mode 100644 backend/internal/mail/logs.go create mode 100644 backend/internal/mail/queue.go create mode 100644 frontend/.svelte-kit/ambient.d.ts create mode 100644 frontend/.svelte-kit/generated/client-optimized/app.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/matchers.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/0.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/1.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/10.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/11.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/12.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/13.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/14.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/2.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/3.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/4.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/5.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/6.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/7.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/8.js create mode 100644 frontend/.svelte-kit/generated/client-optimized/nodes/9.js create mode 100644 frontend/.svelte-kit/generated/client/app.js create mode 100644 frontend/.svelte-kit/generated/client/matchers.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/0.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/1.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/10.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/11.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/12.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/13.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/14.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/2.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/3.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/4.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/5.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/6.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/7.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/8.js create mode 100644 frontend/.svelte-kit/generated/client/nodes/9.js create mode 100644 frontend/.svelte-kit/generated/root.js create mode 100644 frontend/.svelte-kit/generated/root.svelte create mode 100644 frontend/.svelte-kit/generated/server/internal.js create mode 100644 frontend/.svelte-kit/non-ambient.d.ts create mode 100644 frontend/.svelte-kit/output/client/.vite/manifest.json create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/assets/0.DkgBtk4_.css create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/assets/10.Qar-kS8x.css create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/assets/11.D38O3Xxc.css create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/assets/12.DQdHIvb_.css create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/assets/13.DnP_H9DZ.css create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/assets/2.By2d6Bxb.css create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/assets/4.CG2X--Z8.css create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/assets/5.YbbfqdJp.css create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/assets/6.w_qTFDpy.css create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/assets/7.Bq7myTre.css create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/assets/8.neQUdyXe.css create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/assets/9.Ci0QlAaW.css create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/-EcHSJia.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/B3ZK_jYJ.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/B7kAneMc.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/BX-b5t2l.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/BYrNiJ2z.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/CJv7FbHz.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/CfgL3m1f.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/DFRBE_Uq.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/DR7h53-u.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/DtGl34IE.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/RKc8iKz_.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/ayyTDfEa.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/e1WBZ7UL.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/ecAlPOj8.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/chunks/n1byU5WW.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/entry/app.BI_Sozkn.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/entry/start.tprRzko2.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/0.D3wXY_0K.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/1.Dgii_8lh.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/10.BvOkMiuT.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/11.DnvWFHPj.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/12.CRx3MqWn.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/13.CB7FlS8h.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/14.CFDiiGpK.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/2.BMCUuUxB.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/3.CFDiiGpK.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/4.YDL696B2.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/5.DHfYhdex.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/6.BiQ3_GJa.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/7.BEIquz8f.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/8.D4QctIPu.js create mode 100644 frontend/.svelte-kit/output/client/_app/immutable/nodes/9.DflEy3LG.js create mode 100644 frontend/.svelte-kit/output/client/_app/version.json create mode 100644 frontend/.svelte-kit/output/client/favicon.png create mode 100644 frontend/.svelte-kit/output/prerendered/dependencies/_app/env.js create mode 100644 frontend/.svelte-kit/output/server/.vite/manifest.json create mode 100644 frontend/.svelte-kit/output/server/_app/immutable/assets/_layout.DkgBtk4_.css create mode 100644 frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Bmr1F0Zh.css create mode 100644 frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Bq7myTre.css create mode 100644 frontend/.svelte-kit/output/server/_app/immutable/assets/_page.By2d6Bxb.css create mode 100644 frontend/.svelte-kit/output/server/_app/immutable/assets/_page.CG2X--Z8.css create mode 100644 frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Ci0QlAaW.css create mode 100644 frontend/.svelte-kit/output/server/_app/immutable/assets/_page.CvxoqpCi.css create mode 100644 frontend/.svelte-kit/output/server/_app/immutable/assets/_page.DQdHIvb_.css create mode 100644 frontend/.svelte-kit/output/server/_app/immutable/assets/_page.DnP_H9DZ.css create mode 100644 frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Sd9PQMHc.css create mode 100644 frontend/.svelte-kit/output/server/_app/immutable/assets/_page.YbbfqdJp.css create mode 100644 frontend/.svelte-kit/output/server/_app/immutable/assets/_page.w_qTFDpy.css create mode 100644 frontend/.svelte-kit/output/server/chunks/environment.js create mode 100644 frontend/.svelte-kit/output/server/chunks/exports.js create mode 100644 frontend/.svelte-kit/output/server/chunks/false.js create mode 100644 frontend/.svelte-kit/output/server/chunks/index.js create mode 100644 frontend/.svelte-kit/output/server/chunks/index2.js create mode 100644 frontend/.svelte-kit/output/server/chunks/internal.js create mode 100644 frontend/.svelte-kit/output/server/chunks/root.js create mode 100644 frontend/.svelte-kit/output/server/chunks/shared.js create mode 100644 frontend/.svelte-kit/output/server/chunks/state.svelte.js create mode 100644 frontend/.svelte-kit/output/server/chunks/utils.js create mode 100644 frontend/.svelte-kit/output/server/entries/fallbacks/error.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/_layout.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/_page.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/aliases/_page.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/auth/change-password/_page.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/auth/dashboard/_page.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/auth/forgot/_page.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/auth/login/_page.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/domains/_name_/_page.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/domains/_name_/aliases/_page.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/domains/_name_/users/_page.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/domains/_page.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/logs/_page.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/queue/_page.svelte.js create mode 100644 frontend/.svelte-kit/output/server/entries/pages/users/_page.svelte.js create mode 100644 frontend/.svelte-kit/output/server/index.js create mode 100644 frontend/.svelte-kit/output/server/internal.js create mode 100644 frontend/.svelte-kit/output/server/manifest-full.js create mode 100644 frontend/.svelte-kit/output/server/manifest.js create mode 100644 frontend/.svelte-kit/output/server/nodes/0.js create mode 100644 frontend/.svelte-kit/output/server/nodes/1.js create mode 100644 frontend/.svelte-kit/output/server/nodes/10.js create mode 100644 frontend/.svelte-kit/output/server/nodes/11.js create mode 100644 frontend/.svelte-kit/output/server/nodes/12.js create mode 100644 frontend/.svelte-kit/output/server/nodes/13.js create mode 100644 frontend/.svelte-kit/output/server/nodes/14.js create mode 100644 frontend/.svelte-kit/output/server/nodes/2.js create mode 100644 frontend/.svelte-kit/output/server/nodes/3.js create mode 100644 frontend/.svelte-kit/output/server/nodes/4.js create mode 100644 frontend/.svelte-kit/output/server/nodes/5.js create mode 100644 frontend/.svelte-kit/output/server/nodes/6.js create mode 100644 frontend/.svelte-kit/output/server/nodes/7.js create mode 100644 frontend/.svelte-kit/output/server/nodes/8.js create mode 100644 frontend/.svelte-kit/output/server/nodes/9.js create mode 100644 frontend/.svelte-kit/output/server/remote-entry.js create mode 100644 frontend/.svelte-kit/tsconfig.json create mode 100644 frontend/.svelte-kit/types/route_meta_data.json create mode 100644 frontend/.svelte-kit/types/src/routes/$types.d.ts create mode 100644 frontend/.svelte-kit/types/src/routes/aliases/$types.d.ts create mode 100644 frontend/.svelte-kit/types/src/routes/auth/change-password/$types.d.ts create mode 100644 frontend/.svelte-kit/types/src/routes/auth/dashboard/$types.d.ts create mode 100644 frontend/.svelte-kit/types/src/routes/auth/forgot/$types.d.ts create mode 100644 frontend/.svelte-kit/types/src/routes/auth/login/$types.d.ts create mode 100644 frontend/.svelte-kit/types/src/routes/domains/$types.d.ts create mode 100644 frontend/.svelte-kit/types/src/routes/domains/[name]/$types.d.ts create mode 100644 frontend/.svelte-kit/types/src/routes/domains/[name]/aliases/$types.d.ts create mode 100644 frontend/.svelte-kit/types/src/routes/domains/[name]/users/$types.d.ts create mode 100644 frontend/.svelte-kit/types/src/routes/logs/$types.d.ts create mode 100644 frontend/.svelte-kit/types/src/routes/queue/$types.d.ts create mode 100644 frontend/.svelte-kit/types/src/routes/users/$types.d.ts create mode 100644 frontend/bun.lock create mode 120000 frontend/node_modules/.bin/acorn create mode 120000 frontend/node_modules/.bin/esbuild create mode 120000 frontend/node_modules/.bin/nanoid create mode 120000 frontend/node_modules/.bin/rollup create mode 120000 frontend/node_modules/.bin/svelte-kit create mode 120000 frontend/node_modules/.bin/tsc create mode 120000 frontend/node_modules/.bin/tsserver create mode 120000 frontend/node_modules/.bin/vite create mode 100644 frontend/node_modules/.svelte2tsx-language-server-files/svelte-native-jsx.d.ts create mode 100644 frontend/node_modules/.svelte2tsx-language-server-files/svelte-shims-v4.d.ts create mode 100644 frontend/node_modules/@esbuild/linux-x64/README.md create mode 100755 frontend/node_modules/@esbuild/linux-x64/bin/esbuild create mode 100644 frontend/node_modules/@esbuild/linux-x64/package.json create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/LICENSE create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/README.md create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/dist/gen-mapping.mjs create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/dist/gen-mapping.mjs.map create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/dist/gen-mapping.umd.js create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/dist/gen-mapping.umd.js.map create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/dist/types/gen-mapping.d.ts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/dist/types/set-array.d.ts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/dist/types/sourcemap-segment.d.ts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/dist/types/types.d.ts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/package.json create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/src/gen-mapping.ts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/src/set-array.ts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/src/sourcemap-segment.ts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/src/types.ts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/gen-mapping.d.cts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/gen-mapping.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/gen-mapping.d.mts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/gen-mapping.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/set-array.d.cts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/set-array.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/set-array.d.mts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/set-array.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/sourcemap-segment.d.cts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/sourcemap-segment.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/sourcemap-segment.d.mts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/sourcemap-segment.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/types.d.cts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/types.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/types.d.mts create mode 100644 frontend/node_modules/@jridgewell/gen-mapping/types/types.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/remapping/LICENSE create mode 100644 frontend/node_modules/@jridgewell/remapping/README.md create mode 100644 frontend/node_modules/@jridgewell/remapping/dist/remapping.mjs create mode 100644 frontend/node_modules/@jridgewell/remapping/dist/remapping.mjs.map create mode 100644 frontend/node_modules/@jridgewell/remapping/dist/remapping.umd.js create mode 100644 frontend/node_modules/@jridgewell/remapping/dist/remapping.umd.js.map create mode 100644 frontend/node_modules/@jridgewell/remapping/package.json create mode 100644 frontend/node_modules/@jridgewell/remapping/src/build-source-map-tree.ts create mode 100644 frontend/node_modules/@jridgewell/remapping/src/remapping.ts create mode 100644 frontend/node_modules/@jridgewell/remapping/src/source-map-tree.ts create mode 100644 frontend/node_modules/@jridgewell/remapping/src/source-map.ts create mode 100644 frontend/node_modules/@jridgewell/remapping/src/types.ts create mode 100644 frontend/node_modules/@jridgewell/remapping/types/build-source-map-tree.d.cts create mode 100644 frontend/node_modules/@jridgewell/remapping/types/build-source-map-tree.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/remapping/types/build-source-map-tree.d.mts create mode 100644 frontend/node_modules/@jridgewell/remapping/types/build-source-map-tree.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/remapping/types/remapping.d.cts create mode 100644 frontend/node_modules/@jridgewell/remapping/types/remapping.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/remapping/types/remapping.d.mts create mode 100644 frontend/node_modules/@jridgewell/remapping/types/remapping.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/remapping/types/source-map-tree.d.cts create mode 100644 frontend/node_modules/@jridgewell/remapping/types/source-map-tree.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/remapping/types/source-map-tree.d.mts create mode 100644 frontend/node_modules/@jridgewell/remapping/types/source-map-tree.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/remapping/types/source-map.d.cts create mode 100644 frontend/node_modules/@jridgewell/remapping/types/source-map.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/remapping/types/source-map.d.mts create mode 100644 frontend/node_modules/@jridgewell/remapping/types/source-map.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/remapping/types/types.d.cts create mode 100644 frontend/node_modules/@jridgewell/remapping/types/types.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/remapping/types/types.d.mts create mode 100644 frontend/node_modules/@jridgewell/remapping/types/types.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/resolve-uri/LICENSE create mode 100644 frontend/node_modules/@jridgewell/resolve-uri/README.md create mode 100644 frontend/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.mjs create mode 100644 frontend/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.mjs.map create mode 100644 frontend/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.umd.js create mode 100644 frontend/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.umd.js.map create mode 100644 frontend/node_modules/@jridgewell/resolve-uri/dist/types/resolve-uri.d.ts create mode 100644 frontend/node_modules/@jridgewell/resolve-uri/package.json create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/LICENSE create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/README.md create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs.map create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.umd.js create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.umd.js.map create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/package.json create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/src/scopes.ts create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/src/sourcemap-codec.ts create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/src/strings.ts create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/src/vlq.ts create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/scopes.d.cts create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/scopes.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/scopes.d.mts create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/scopes.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/sourcemap-codec.d.cts create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/sourcemap-codec.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/sourcemap-codec.d.mts create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/sourcemap-codec.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/strings.d.cts create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/strings.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/strings.d.mts create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/strings.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/vlq.d.cts create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/vlq.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/vlq.d.mts create mode 100644 frontend/node_modules/@jridgewell/sourcemap-codec/types/vlq.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/LICENSE create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/README.md create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.mjs create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.mjs.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.umd.js create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.umd.js.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/package.json create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/src/binary-search.ts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/src/by-source.ts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/src/flatten-map.ts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/src/resolve.ts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/src/sort.ts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/src/sourcemap-segment.ts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/src/strip-filename.ts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/src/trace-mapping.ts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/src/types.ts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/binary-search.d.cts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/binary-search.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/binary-search.d.mts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/binary-search.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/by-source.d.cts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/by-source.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/by-source.d.mts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/by-source.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/flatten-map.d.cts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/flatten-map.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/flatten-map.d.mts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/flatten-map.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/resolve.d.cts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/resolve.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/resolve.d.mts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/resolve.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/sort.d.cts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/sort.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/sort.d.mts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/sort.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/sourcemap-segment.d.cts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/sourcemap-segment.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/sourcemap-segment.d.mts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/sourcemap-segment.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/strip-filename.d.cts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/strip-filename.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/strip-filename.d.mts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/strip-filename.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/trace-mapping.d.cts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/trace-mapping.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/trace-mapping.d.mts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/trace-mapping.d.mts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/types.d.cts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/types.d.cts.map create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/types.d.mts create mode 100644 frontend/node_modules/@jridgewell/trace-mapping/types/types.d.mts.map create mode 100644 frontend/node_modules/@polka/url/build.js create mode 100644 frontend/node_modules/@polka/url/build.mjs create mode 100644 frontend/node_modules/@polka/url/index.d.ts create mode 100644 frontend/node_modules/@polka/url/package.json create mode 100644 frontend/node_modules/@polka/url/readme.md create mode 100644 frontend/node_modules/@rollup/rollup-linux-x64-gnu/README.md create mode 100644 frontend/node_modules/@rollup/rollup-linux-x64-gnu/package.json create mode 100644 frontend/node_modules/@rollup/rollup-linux-x64-gnu/rollup.linux-x64-gnu.node create mode 100644 frontend/node_modules/@rollup/rollup-linux-x64-musl/README.md create mode 100644 frontend/node_modules/@rollup/rollup-linux-x64-musl/package.json create mode 100644 frontend/node_modules/@rollup/rollup-linux-x64-musl/rollup.linux-x64-musl.node create mode 100644 frontend/node_modules/@standard-schema/spec/LICENSE create mode 100644 frontend/node_modules/@standard-schema/spec/README.md create mode 100644 frontend/node_modules/@standard-schema/spec/dist/index.cjs create mode 100644 frontend/node_modules/@standard-schema/spec/dist/index.d.cts create mode 100644 frontend/node_modules/@standard-schema/spec/dist/index.d.ts create mode 100644 frontend/node_modules/@standard-schema/spec/dist/index.js create mode 100644 frontend/node_modules/@standard-schema/spec/package.json create mode 100644 frontend/node_modules/@sveltejs/acorn-typescript/LICENSE.md create mode 100644 frontend/node_modules/@sveltejs/acorn-typescript/README.md create mode 100644 frontend/node_modules/@sveltejs/acorn-typescript/index.d.ts create mode 100644 frontend/node_modules/@sveltejs/acorn-typescript/index.js create mode 100644 frontend/node_modules/@sveltejs/acorn-typescript/package.json create mode 100644 frontend/node_modules/@sveltejs/adapter-static/LICENSE create mode 100644 frontend/node_modules/@sveltejs/adapter-static/README.md create mode 100644 frontend/node_modules/@sveltejs/adapter-static/index.d.ts create mode 100644 frontend/node_modules/@sveltejs/adapter-static/index.js create mode 100644 frontend/node_modules/@sveltejs/adapter-static/package.json create mode 100644 frontend/node_modules/@sveltejs/adapter-static/platforms.js create mode 100644 frontend/node_modules/@sveltejs/kit/LICENSE create mode 100644 frontend/node_modules/@sveltejs/kit/README.md create mode 100644 frontend/node_modules/@sveltejs/kit/package.json create mode 100644 frontend/node_modules/@sveltejs/kit/src/cli.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/constants.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/adapt/builder.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/adapt/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/config/default-error.html create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/config/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/config/options.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/config/types.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/env.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/generate_manifest/find_server_assets.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/generate_manifest/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/postbuild/analyse.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/postbuild/crawl.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/postbuild/entities.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/postbuild/fallback.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/postbuild/prerender.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/postbuild/queue.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/conflict.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/sort.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/types.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/sync.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/ts.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/utils.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/write_ambient.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/write_client_manifest.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/write_non_ambient.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/write_root.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/write_server.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/write_tsconfig.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/sync/write_types/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/core/utils.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/hooks/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/hooks/sequence.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/internal/event.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/internal/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/internal/remote-functions.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/internal/server.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/node/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/node/polyfills.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/public.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/vite/dev/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/vite/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/vite/module_ids.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/vite/preview/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/vite/static_analysis/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/vite/static_analysis/utils.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/vite/types.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/exports/vite/utils.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/environment/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/environment/types.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/forms.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/navigation.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/paths/client.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/paths/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/paths/internal/client.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/paths/internal/server.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/paths/public.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/paths/server.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/paths/types.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/server/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/server/remote/command.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/server/remote/form.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/server/remote/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/server/remote/prerender.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/server/remote/query.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/server/remote/shared.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/state/client.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/state/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/state/server.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/app/stores.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/bundle.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/client.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/constants.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/entry.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/fetcher.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/parse.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/remote-functions/command.svelte.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/remote-functions/form.svelte.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/remote-functions/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/remote-functions/prerender.svelte.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/remote-functions/query.svelte.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/remote-functions/shared.svelte.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/session-storage.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/state.svelte.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/types.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/client/utils.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/components/svelte-4/error.svelte create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/components/svelte-4/layout.svelte create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/components/svelte-5/error.svelte create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/components/svelte-5/layout.svelte create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/env/dynamic/private.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/env/dynamic/public.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/form-utils.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/pathname.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/ambient.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/app.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/constants.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/cookie.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/data/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/endpoint.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/env_module.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/fetch.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/page/actions.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/page/crypto.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/page/csp.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/page/data_serializer.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/page/index.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/page/load_data.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/page/render.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/page/respond_with_error.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/page/serialize_data.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/page/server_routing.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/page/types.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/remote.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/respond.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/utils.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/server/validate-headers.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/shared-server.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/shared.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/telemetry/noop.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/telemetry/otel.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/telemetry/record_span.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/runtime/utils.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/types/ambient-private.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/types/ambient.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/types/global-private.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/types/internal.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/types/private.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/src/types/synthetic/$env+dynamic+private.md create mode 100644 frontend/node_modules/@sveltejs/kit/src/types/synthetic/$env+dynamic+public.md create mode 100644 frontend/node_modules/@sveltejs/kit/src/types/synthetic/$env+static+private.md create mode 100644 frontend/node_modules/@sveltejs/kit/src/types/synthetic/$env+static+public.md create mode 100644 frontend/node_modules/@sveltejs/kit/src/types/synthetic/$lib.md create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/array.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/css.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/env.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/error.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/escape.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/exports.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/features.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/filesystem.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/fork.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/functions.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/hash.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/http.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/import.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/misc.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/page_nodes.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/promise.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/routing.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/streaming.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/utils/url.js create mode 100644 frontend/node_modules/@sveltejs/kit/src/version.js create mode 100755 frontend/node_modules/@sveltejs/kit/svelte-kit.js create mode 100644 frontend/node_modules/@sveltejs/kit/types/index.d.ts create mode 100644 frontend/node_modules/@sveltejs/kit/types/index.d.ts.map create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/LICENSE create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/README.md create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/package.json create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/debug.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/index.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/options.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/public.d.ts create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/runtime/Inspector.svelte create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/runtime/load-inspector.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/utils.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/types/index.d.ts create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/types/index.d.ts.map create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/LICENSE create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/README.md create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/package.json create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/handle-hot-update.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/index.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/preprocess.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/public.d.ts create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/compile.d.ts create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/id.d.ts create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/log.d.ts create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/options.d.ts create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/plugin-api.d.ts create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/vite-plugin-svelte-stats.d.ts create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/compile.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/constants.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/dependencies.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/error.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/esbuild.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/hash.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/id.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/load-raw.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/load-svelte-config.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/log.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/optimizer.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/options.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/preprocess.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/sourcemaps.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/svelte-version.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/vite-plugin-svelte-cache.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/vite-plugin-svelte-stats.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/watch.js create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/types/index.d.ts create mode 100644 frontend/node_modules/@sveltejs/vite-plugin-svelte/types/index.d.ts.map create mode 100644 frontend/node_modules/@types/cookie/LICENSE create mode 100644 frontend/node_modules/@types/cookie/README.md create mode 100644 frontend/node_modules/@types/cookie/index.d.ts create mode 100644 frontend/node_modules/@types/cookie/package.json create mode 100644 frontend/node_modules/@types/estree/LICENSE create mode 100644 frontend/node_modules/@types/estree/README.md create mode 100644 frontend/node_modules/@types/estree/flow.d.ts create mode 100644 frontend/node_modules/@types/estree/index.d.ts create mode 100644 frontend/node_modules/@types/estree/package.json create mode 100644 frontend/node_modules/@types/trusted-types/LICENSE create mode 100644 frontend/node_modules/@types/trusted-types/README.md create mode 100644 frontend/node_modules/@types/trusted-types/index.d.ts create mode 100644 frontend/node_modules/@types/trusted-types/lib/index.d.ts create mode 100644 frontend/node_modules/@types/trusted-types/package.json create mode 100644 frontend/node_modules/@typescript-eslint/types/LICENSE create mode 100644 frontend/node_modules/@typescript-eslint/types/README.md create mode 100644 frontend/node_modules/@typescript-eslint/types/dist/generated/ast-spec.d.ts create mode 100644 frontend/node_modules/@typescript-eslint/types/dist/generated/ast-spec.js create mode 100644 frontend/node_modules/@typescript-eslint/types/dist/index.d.ts create mode 100644 frontend/node_modules/@typescript-eslint/types/dist/index.js create mode 100644 frontend/node_modules/@typescript-eslint/types/dist/lib.d.ts create mode 100644 frontend/node_modules/@typescript-eslint/types/dist/lib.js create mode 100644 frontend/node_modules/@typescript-eslint/types/dist/parser-options.d.ts create mode 100644 frontend/node_modules/@typescript-eslint/types/dist/parser-options.js create mode 100644 frontend/node_modules/@typescript-eslint/types/dist/ts-estree.d.ts create mode 100644 frontend/node_modules/@typescript-eslint/types/dist/ts-estree.js create mode 100644 frontend/node_modules/@typescript-eslint/types/dist/tsconfig.build.tsbuildinfo create mode 100644 frontend/node_modules/@typescript-eslint/types/package.json create mode 100644 frontend/node_modules/acorn/CHANGELOG.md create mode 100644 frontend/node_modules/acorn/LICENSE create mode 100644 frontend/node_modules/acorn/README.md create mode 100755 frontend/node_modules/acorn/bin/acorn create mode 100644 frontend/node_modules/acorn/dist/acorn.d.mts create mode 100644 frontend/node_modules/acorn/dist/acorn.d.ts create mode 100644 frontend/node_modules/acorn/dist/acorn.js create mode 100644 frontend/node_modules/acorn/dist/acorn.mjs create mode 100644 frontend/node_modules/acorn/dist/bin.js create mode 100644 frontend/node_modules/acorn/package.json create mode 100644 frontend/node_modules/aria-query/LICENSE create mode 100644 frontend/node_modules/aria-query/README.md create mode 100644 frontend/node_modules/aria-query/lib/ariaPropsMap.js create mode 100644 frontend/node_modules/aria-query/lib/domMap.js create mode 100644 frontend/node_modules/aria-query/lib/elementRoleMap.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/abstract/commandRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/abstract/compositeRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/abstract/inputRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/abstract/landmarkRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/abstract/rangeRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/abstract/roletypeRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/abstract/sectionRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/abstract/sectionheadRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/abstract/selectRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/abstract/structureRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/abstract/widgetRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/abstract/windowRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/ariaAbstractRoles.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/ariaDpubRoles.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/ariaGraphicsRoles.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/ariaLiteralRoles.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docAbstractRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docAcknowledgmentsRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docAfterwordRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docAppendixRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docBacklinkRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docBiblioentryRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docBibliographyRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docBibliorefRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docChapterRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docColophonRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docConclusionRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docCoverRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docCreditRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docCreditsRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docDedicationRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docEndnoteRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docEndnotesRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docEpigraphRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docEpilogueRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docErrataRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docExampleRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docFootnoteRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docForewordRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docGlossaryRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docGlossrefRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docIndexRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docIntroductionRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docNoterefRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docNoticeRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docPagebreakRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docPagefooterRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docPageheaderRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docPagelistRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docPartRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docPrefaceRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docPrologueRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docPullquoteRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docQnaRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docSubtitleRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docTipRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/dpub/docTocRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/graphics/graphicsDocumentRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/graphics/graphicsObjectRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/graphics/graphicsSymbolRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/alertRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/alertdialogRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/applicationRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/articleRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/bannerRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/blockquoteRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/buttonRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/captionRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/cellRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/checkboxRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/codeRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/columnheaderRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/comboboxRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/complementaryRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/contentinfoRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/definitionRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/deletionRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/dialogRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/directoryRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/documentRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/emphasisRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/feedRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/figureRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/formRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/genericRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/graphicsDocumentRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/graphicsObjectRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/graphicsSymbolRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/gridRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/gridcellRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/groupRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/headingRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/imgRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/insertionRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/linkRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/listRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/listboxRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/listitemRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/logRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/mainRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/markRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/marqueeRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/mathRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/menuRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/menubarRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/menuitemRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/menuitemcheckboxRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/menuitemradioRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/meterRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/navigationRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/noneRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/noteRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/optionRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/paragraphRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/presentationRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/progressbarRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/radioRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/radiogroupRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/regionRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/rowRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/rowgroupRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/rowheaderRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/scrollbarRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/searchRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/searchboxRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/separatorRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/sliderRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/spinbuttonRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/statusRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/strongRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/subscriptRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/superscriptRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/switchRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/tabRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/tableRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/tablistRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/tabpanelRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/termRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/textboxRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/timeRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/timerRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/toolbarRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/tooltipRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/treeRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/treegridRole.js create mode 100644 frontend/node_modules/aria-query/lib/etc/roles/literal/treeitemRole.js create mode 100644 frontend/node_modules/aria-query/lib/index.js create mode 100644 frontend/node_modules/aria-query/lib/roleElementMap.js create mode 100644 frontend/node_modules/aria-query/lib/rolesMap.js create mode 100644 frontend/node_modules/aria-query/lib/util/iterationDecorator.js create mode 100644 frontend/node_modules/aria-query/lib/util/iteratorProxy.js create mode 100644 frontend/node_modules/aria-query/package.json create mode 100755 frontend/node_modules/axobject-query/LICENSE create mode 100644 frontend/node_modules/axobject-query/README.md create mode 100644 frontend/node_modules/axobject-query/lib/AXObjectElementMap.js create mode 100644 frontend/node_modules/axobject-query/lib/AXObjectRoleMap.js create mode 100644 frontend/node_modules/axobject-query/lib/AXObjectsMap.js create mode 100644 frontend/node_modules/axobject-query/lib/elementAXObjectMap.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/AbbrRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/AlertDialogRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/AlertRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/AnnotationRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ApplicationRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ArticleRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/AudioRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/BannerRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/BlockquoteRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/BusyIndicatorRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ButtonRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/CanvasRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/CaptionRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/CellRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/CheckBoxRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ColorWellRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ColumnHeaderRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ColumnRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ComboBoxRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ComplementaryRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ContentInfoRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/DateRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/DateTimeRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/DefinitionRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/DescriptionListDetailRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/DescriptionListRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/DescriptionListTermRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/DetailsRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/DialogRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/DirectoryRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/DisclosureTriangleRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/DivRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/DocumentRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/EmbeddedObjectRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/FeedRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/FigcaptionRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/FigureRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/FooterRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/FormRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/GridRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/GroupRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/HeadingRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/IframePresentationalRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/IframeRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/IgnoredRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ImageMapLinkRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ImageMapRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ImageRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/InlineTextBoxRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/InputTimeRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/LabelRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/LegendRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/LineBreakRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/LinkRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ListBoxOptionRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ListBoxRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ListItemRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ListMarkerRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ListRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/LogRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/MainRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/MarkRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/MarqueeRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/MathRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/MenuBarRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/MenuButtonRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/MenuItemCheckBoxRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/MenuItemRadioRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/MenuItemRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/MenuListOptionRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/MenuListPopupRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/MenuRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/MeterRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/NavigationRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/NoneRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/NoteRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/OutlineRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ParagraphRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/PopUpButtonRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/PreRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/PresentationalRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ProgressIndicatorRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/RadioButtonRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/RadioGroupRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/RegionRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/RootWebAreaRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/RowHeaderRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/RowRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/RubyRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/RulerRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/SVGRootRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ScrollAreaRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ScrollBarRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/SeamlessWebAreaRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/SearchBoxRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/SearchRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/SliderRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/SliderThumbRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/SpinButtonPartRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/SpinButtonRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/SplitterRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/StaticTextRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/StatusRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/SwitchRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TabGroupRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TabListRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TabPanelRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TabRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TableHeaderContainerRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TableRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TermRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TextAreaRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TextFieldRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TimeRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TimerRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ToggleButtonRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/ToolbarRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TreeGridRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TreeItemRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/TreeRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/UserInterfaceTooltipRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/VideoRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/WebAreaRole.js create mode 100644 frontend/node_modules/axobject-query/lib/etc/objects/WindowRole.js create mode 100644 frontend/node_modules/axobject-query/lib/index.js create mode 100644 frontend/node_modules/axobject-query/lib/util/iterationDecorator.js create mode 100644 frontend/node_modules/axobject-query/lib/util/iteratorProxy.js create mode 100644 frontend/node_modules/axobject-query/package.json create mode 100644 frontend/node_modules/clsx/clsx.d.mts create mode 100644 frontend/node_modules/clsx/clsx.d.ts create mode 100644 frontend/node_modules/clsx/dist/clsx.js create mode 100644 frontend/node_modules/clsx/dist/clsx.min.js create mode 100644 frontend/node_modules/clsx/dist/clsx.mjs create mode 100644 frontend/node_modules/clsx/dist/lite.js create mode 100644 frontend/node_modules/clsx/dist/lite.mjs create mode 100644 frontend/node_modules/clsx/license create mode 100644 frontend/node_modules/clsx/package.json create mode 100644 frontend/node_modules/clsx/readme.md create mode 100644 frontend/node_modules/cookie/HISTORY.md create mode 100644 frontend/node_modules/cookie/LICENSE create mode 100644 frontend/node_modules/cookie/README.md create mode 100644 frontend/node_modules/cookie/SECURITY.md create mode 100644 frontend/node_modules/cookie/index.js create mode 100644 frontend/node_modules/cookie/package.json create mode 100644 frontend/node_modules/debug/LICENSE create mode 100644 frontend/node_modules/debug/README.md create mode 100644 frontend/node_modules/debug/package.json create mode 100644 frontend/node_modules/debug/src/browser.js create mode 100644 frontend/node_modules/debug/src/common.js create mode 100644 frontend/node_modules/debug/src/index.js create mode 100644 frontend/node_modules/debug/src/node.js create mode 100644 frontend/node_modules/deepmerge/.editorconfig create mode 100644 frontend/node_modules/deepmerge/.eslintcache create mode 100644 frontend/node_modules/deepmerge/changelog.md create mode 100644 frontend/node_modules/deepmerge/dist/cjs.js create mode 100644 frontend/node_modules/deepmerge/dist/umd.js create mode 100644 frontend/node_modules/deepmerge/index.d.ts create mode 100644 frontend/node_modules/deepmerge/index.js create mode 100644 frontend/node_modules/deepmerge/license.txt create mode 100644 frontend/node_modules/deepmerge/package.json create mode 100644 frontend/node_modules/deepmerge/readme.md create mode 100644 frontend/node_modules/deepmerge/rollup.config.js create mode 100644 frontend/node_modules/devalue/LICENSE create mode 100644 frontend/node_modules/devalue/README.md create mode 100644 frontend/node_modules/devalue/index.js create mode 100644 frontend/node_modules/devalue/package.json create mode 100644 frontend/node_modules/devalue/src/base64.js create mode 100644 frontend/node_modules/devalue/src/constants.js create mode 100644 frontend/node_modules/devalue/src/parse.js create mode 100644 frontend/node_modules/devalue/src/stringify.js create mode 100644 frontend/node_modules/devalue/src/types.d.ts create mode 100644 frontend/node_modules/devalue/src/uneval.js create mode 100644 frontend/node_modules/devalue/src/utils.js create mode 100644 frontend/node_modules/devalue/src/utils.test.js create mode 100644 frontend/node_modules/devalue/types/index.d.ts create mode 100644 frontend/node_modules/devalue/types/index.d.ts.map create mode 100644 frontend/node_modules/esbuild/LICENSE.md create mode 100644 frontend/node_modules/esbuild/README.md create mode 100755 frontend/node_modules/esbuild/bin/esbuild create mode 100644 frontend/node_modules/esbuild/install.js create mode 100644 frontend/node_modules/esbuild/lib/main.d.ts create mode 100644 frontend/node_modules/esbuild/lib/main.js create mode 100644 frontend/node_modules/esbuild/package.json create mode 100644 frontend/node_modules/esm-env/CHANGELOG.md create mode 100644 frontend/node_modules/esm-env/LICENSE create mode 100644 frontend/node_modules/esm-env/README.md create mode 100644 frontend/node_modules/esm-env/browser-fallback.js create mode 100644 frontend/node_modules/esm-env/dev-fallback.js create mode 100644 frontend/node_modules/esm-env/false.js create mode 100644 frontend/node_modules/esm-env/index.d.ts create mode 100644 frontend/node_modules/esm-env/index.js create mode 100644 frontend/node_modules/esm-env/package.json create mode 100644 frontend/node_modules/esm-env/true.js create mode 100644 frontend/node_modules/esrap/LICENSE create mode 100644 frontend/node_modules/esrap/README.md create mode 100644 frontend/node_modules/esrap/package.json create mode 100644 frontend/node_modules/esrap/src/context.js create mode 100644 frontend/node_modules/esrap/src/index.js create mode 100644 frontend/node_modules/esrap/src/languages/ts/index.js create mode 100644 frontend/node_modules/esrap/src/languages/ts/public.d.ts create mode 100644 frontend/node_modules/esrap/src/languages/tsx/index.js create mode 100644 frontend/node_modules/esrap/src/languages/tsx/public.d.ts create mode 100644 frontend/node_modules/esrap/src/languages/types.d.ts create mode 100644 frontend/node_modules/esrap/src/public.d.ts create mode 100644 frontend/node_modules/esrap/src/types.d.ts create mode 100644 frontend/node_modules/esrap/types/index.d.ts create mode 100644 frontend/node_modules/esrap/types/index.d.ts.map create mode 100644 frontend/node_modules/is-reference/README.md create mode 100644 frontend/node_modules/is-reference/package.json create mode 100644 frontend/node_modules/is-reference/src/index.js create mode 100644 frontend/node_modules/is-reference/types/index.d.ts create mode 100644 frontend/node_modules/is-reference/types/index.d.ts.map create mode 100644 frontend/node_modules/kleur/colors.d.ts create mode 100644 frontend/node_modules/kleur/colors.js create mode 100644 frontend/node_modules/kleur/colors.mjs create mode 100644 frontend/node_modules/kleur/index.d.ts create mode 100644 frontend/node_modules/kleur/index.js create mode 100644 frontend/node_modules/kleur/index.mjs create mode 100644 frontend/node_modules/kleur/license create mode 100644 frontend/node_modules/kleur/package.json create mode 100644 frontend/node_modules/kleur/readme.md create mode 100644 frontend/node_modules/locate-character/README.md create mode 100644 frontend/node_modules/locate-character/package.json create mode 100644 frontend/node_modules/locate-character/src/index.js create mode 100644 frontend/node_modules/locate-character/src/types.d.ts create mode 100644 frontend/node_modules/locate-character/types/index.d.ts create mode 100644 frontend/node_modules/locate-character/types/index.d.ts.map create mode 100644 frontend/node_modules/magic-string/LICENSE create mode 100644 frontend/node_modules/magic-string/README.md create mode 100644 frontend/node_modules/magic-string/dist/magic-string.cjs.d.ts create mode 100644 frontend/node_modules/magic-string/dist/magic-string.cjs.js create mode 100644 frontend/node_modules/magic-string/dist/magic-string.cjs.js.map create mode 100644 frontend/node_modules/magic-string/dist/magic-string.es.d.mts create mode 100644 frontend/node_modules/magic-string/dist/magic-string.es.mjs create mode 100644 frontend/node_modules/magic-string/dist/magic-string.es.mjs.map create mode 100644 frontend/node_modules/magic-string/dist/magic-string.umd.js create mode 100644 frontend/node_modules/magic-string/dist/magic-string.umd.js.map create mode 100644 frontend/node_modules/magic-string/package.json create mode 100644 frontend/node_modules/mrmime/index.d.ts create mode 100644 frontend/node_modules/mrmime/index.js create mode 100644 frontend/node_modules/mrmime/index.mjs create mode 100644 frontend/node_modules/mrmime/license create mode 100644 frontend/node_modules/mrmime/package.json create mode 100644 frontend/node_modules/mrmime/readme.md create mode 100644 frontend/node_modules/ms/index.js create mode 100644 frontend/node_modules/ms/license.md create mode 100644 frontend/node_modules/ms/package.json create mode 100644 frontend/node_modules/ms/readme.md create mode 100644 frontend/node_modules/nanoid/LICENSE create mode 100644 frontend/node_modules/nanoid/README.md create mode 100644 frontend/node_modules/nanoid/async/index.browser.cjs create mode 100644 frontend/node_modules/nanoid/async/index.browser.js create mode 100644 frontend/node_modules/nanoid/async/index.cjs create mode 100644 frontend/node_modules/nanoid/async/index.d.ts create mode 100644 frontend/node_modules/nanoid/async/index.js create mode 100644 frontend/node_modules/nanoid/async/index.native.js create mode 100644 frontend/node_modules/nanoid/async/package.json create mode 100755 frontend/node_modules/nanoid/bin/nanoid.cjs create mode 100644 frontend/node_modules/nanoid/index.browser.cjs create mode 100644 frontend/node_modules/nanoid/index.browser.js create mode 100644 frontend/node_modules/nanoid/index.cjs create mode 100644 frontend/node_modules/nanoid/index.d.cts create mode 100644 frontend/node_modules/nanoid/index.d.ts create mode 100644 frontend/node_modules/nanoid/index.js create mode 100644 frontend/node_modules/nanoid/nanoid.js create mode 100644 frontend/node_modules/nanoid/non-secure/index.cjs create mode 100644 frontend/node_modules/nanoid/non-secure/index.d.ts create mode 100644 frontend/node_modules/nanoid/non-secure/index.js create mode 100644 frontend/node_modules/nanoid/non-secure/package.json create mode 100644 frontend/node_modules/nanoid/package.json create mode 100644 frontend/node_modules/nanoid/url-alphabet/index.cjs create mode 100644 frontend/node_modules/nanoid/url-alphabet/index.js create mode 100644 frontend/node_modules/nanoid/url-alphabet/package.json create mode 100644 frontend/node_modules/picocolors/LICENSE create mode 100644 frontend/node_modules/picocolors/README.md create mode 100644 frontend/node_modules/picocolors/package.json create mode 100644 frontend/node_modules/picocolors/picocolors.browser.js create mode 100644 frontend/node_modules/picocolors/picocolors.d.ts create mode 100644 frontend/node_modules/picocolors/picocolors.js create mode 100644 frontend/node_modules/picocolors/types.d.ts create mode 100644 frontend/node_modules/postcss/LICENSE create mode 100644 frontend/node_modules/postcss/README.md create mode 100644 frontend/node_modules/postcss/lib/at-rule.d.ts create mode 100644 frontend/node_modules/postcss/lib/at-rule.js create mode 100644 frontend/node_modules/postcss/lib/comment.d.ts create mode 100644 frontend/node_modules/postcss/lib/comment.js create mode 100644 frontend/node_modules/postcss/lib/container.d.ts create mode 100644 frontend/node_modules/postcss/lib/container.js create mode 100644 frontend/node_modules/postcss/lib/css-syntax-error.d.ts create mode 100644 frontend/node_modules/postcss/lib/css-syntax-error.js create mode 100644 frontend/node_modules/postcss/lib/declaration.d.ts create mode 100644 frontend/node_modules/postcss/lib/declaration.js create mode 100644 frontend/node_modules/postcss/lib/document.d.ts create mode 100644 frontend/node_modules/postcss/lib/document.js create mode 100644 frontend/node_modules/postcss/lib/fromJSON.d.ts create mode 100644 frontend/node_modules/postcss/lib/fromJSON.js create mode 100644 frontend/node_modules/postcss/lib/input.d.ts create mode 100644 frontend/node_modules/postcss/lib/input.js create mode 100644 frontend/node_modules/postcss/lib/lazy-result.d.ts create mode 100644 frontend/node_modules/postcss/lib/lazy-result.js create mode 100644 frontend/node_modules/postcss/lib/list.d.ts create mode 100644 frontend/node_modules/postcss/lib/list.js create mode 100644 frontend/node_modules/postcss/lib/map-generator.js create mode 100644 frontend/node_modules/postcss/lib/no-work-result.d.ts create mode 100644 frontend/node_modules/postcss/lib/no-work-result.js create mode 100644 frontend/node_modules/postcss/lib/node.d.ts create mode 100644 frontend/node_modules/postcss/lib/node.js create mode 100644 frontend/node_modules/postcss/lib/parse.d.ts create mode 100644 frontend/node_modules/postcss/lib/parse.js create mode 100644 frontend/node_modules/postcss/lib/parser.js create mode 100644 frontend/node_modules/postcss/lib/postcss.d.mts create mode 100644 frontend/node_modules/postcss/lib/postcss.d.ts create mode 100644 frontend/node_modules/postcss/lib/postcss.js create mode 100644 frontend/node_modules/postcss/lib/postcss.mjs create mode 100644 frontend/node_modules/postcss/lib/previous-map.d.ts create mode 100644 frontend/node_modules/postcss/lib/previous-map.js create mode 100644 frontend/node_modules/postcss/lib/processor.d.ts create mode 100644 frontend/node_modules/postcss/lib/processor.js create mode 100644 frontend/node_modules/postcss/lib/result.d.ts create mode 100644 frontend/node_modules/postcss/lib/result.js create mode 100644 frontend/node_modules/postcss/lib/root.d.ts create mode 100644 frontend/node_modules/postcss/lib/root.js create mode 100644 frontend/node_modules/postcss/lib/rule.d.ts create mode 100644 frontend/node_modules/postcss/lib/rule.js create mode 100644 frontend/node_modules/postcss/lib/stringifier.d.ts create mode 100644 frontend/node_modules/postcss/lib/stringifier.js create mode 100644 frontend/node_modules/postcss/lib/stringify.d.ts create mode 100644 frontend/node_modules/postcss/lib/stringify.js create mode 100644 frontend/node_modules/postcss/lib/symbols.js create mode 100644 frontend/node_modules/postcss/lib/terminal-highlight.js create mode 100644 frontend/node_modules/postcss/lib/tokenize.js create mode 100644 frontend/node_modules/postcss/lib/warn-once.js create mode 100644 frontend/node_modules/postcss/lib/warning.d.ts create mode 100644 frontend/node_modules/postcss/lib/warning.js create mode 100644 frontend/node_modules/postcss/package.json create mode 100644 frontend/node_modules/rollup/LICENSE.md create mode 100644 frontend/node_modules/rollup/README.md create mode 100755 frontend/node_modules/rollup/dist/bin/rollup create mode 100644 frontend/node_modules/rollup/dist/es/getLogFilter.js create mode 100644 frontend/node_modules/rollup/dist/es/package.json create mode 100644 frontend/node_modules/rollup/dist/es/parseAst.js create mode 100644 frontend/node_modules/rollup/dist/es/rollup.js create mode 100644 frontend/node_modules/rollup/dist/es/shared/node-entry.js create mode 100644 frontend/node_modules/rollup/dist/es/shared/parseAst.js create mode 100644 frontend/node_modules/rollup/dist/es/shared/watch.js create mode 100644 frontend/node_modules/rollup/dist/getLogFilter.d.ts create mode 100644 frontend/node_modules/rollup/dist/getLogFilter.js create mode 100644 frontend/node_modules/rollup/dist/loadConfigFile.d.ts create mode 100644 frontend/node_modules/rollup/dist/loadConfigFile.js create mode 100644 frontend/node_modules/rollup/dist/native.js create mode 100644 frontend/node_modules/rollup/dist/parseAst.d.ts create mode 100644 frontend/node_modules/rollup/dist/parseAst.js create mode 100644 frontend/node_modules/rollup/dist/rollup.d.ts create mode 100644 frontend/node_modules/rollup/dist/rollup.js create mode 100644 frontend/node_modules/rollup/dist/shared/fsevents-importer.js create mode 100644 frontend/node_modules/rollup/dist/shared/index.js create mode 100644 frontend/node_modules/rollup/dist/shared/loadConfigFile.js create mode 100644 frontend/node_modules/rollup/dist/shared/parseAst.js create mode 100644 frontend/node_modules/rollup/dist/shared/rollup.js create mode 100644 frontend/node_modules/rollup/dist/shared/watch-cli.js create mode 100644 frontend/node_modules/rollup/dist/shared/watch.js create mode 100644 frontend/node_modules/rollup/package.json create mode 100644 frontend/node_modules/set-cookie-parser/LICENSE create mode 100644 frontend/node_modules/set-cookie-parser/README.md create mode 100644 frontend/node_modules/set-cookie-parser/dist/.eslintrc.cjs create mode 100644 frontend/node_modules/set-cookie-parser/dist/set-cookie.cjs create mode 100644 frontend/node_modules/set-cookie-parser/lib/set-cookie.d.ts create mode 100644 frontend/node_modules/set-cookie-parser/lib/set-cookie.js create mode 100644 frontend/node_modules/set-cookie-parser/package.json create mode 100644 frontend/node_modules/sirv/build.js create mode 100644 frontend/node_modules/sirv/build.mjs create mode 100644 frontend/node_modules/sirv/index.d.mts create mode 100644 frontend/node_modules/sirv/index.d.ts create mode 100644 frontend/node_modules/sirv/package.json create mode 100644 frontend/node_modules/sirv/readme.md create mode 100644 frontend/node_modules/source-map-js/LICENSE create mode 100644 frontend/node_modules/source-map-js/README.md create mode 100644 frontend/node_modules/source-map-js/lib/array-set.js create mode 100644 frontend/node_modules/source-map-js/lib/base64-vlq.js create mode 100644 frontend/node_modules/source-map-js/lib/base64.js create mode 100644 frontend/node_modules/source-map-js/lib/binary-search.js create mode 100644 frontend/node_modules/source-map-js/lib/mapping-list.js create mode 100644 frontend/node_modules/source-map-js/lib/quick-sort.js create mode 100644 frontend/node_modules/source-map-js/lib/source-map-consumer.d.ts create mode 100644 frontend/node_modules/source-map-js/lib/source-map-consumer.js create mode 100644 frontend/node_modules/source-map-js/lib/source-map-generator.d.ts create mode 100644 frontend/node_modules/source-map-js/lib/source-map-generator.js create mode 100644 frontend/node_modules/source-map-js/lib/source-node.d.ts create mode 100644 frontend/node_modules/source-map-js/lib/source-node.js create mode 100644 frontend/node_modules/source-map-js/lib/util.js create mode 100644 frontend/node_modules/source-map-js/package.json create mode 100644 frontend/node_modules/source-map-js/source-map.d.ts create mode 100644 frontend/node_modules/source-map-js/source-map.js create mode 100644 frontend/node_modules/svelte/LICENSE.md create mode 100644 frontend/node_modules/svelte/README.md create mode 100644 frontend/node_modules/svelte/action.d.ts create mode 100644 frontend/node_modules/svelte/animate.d.ts create mode 100644 frontend/node_modules/svelte/compiler.d.ts create mode 100644 frontend/node_modules/svelte/compiler/index.js create mode 100644 frontend/node_modules/svelte/compiler/package.json create mode 100644 frontend/node_modules/svelte/easing.d.ts create mode 100644 frontend/node_modules/svelte/elements.d.ts create mode 100644 frontend/node_modules/svelte/index.d.ts create mode 100644 frontend/node_modules/svelte/legacy.d.ts create mode 100644 frontend/node_modules/svelte/motion.d.ts create mode 100644 frontend/node_modules/svelte/package.json create mode 100644 frontend/node_modules/svelte/src/animate/index.js create mode 100644 frontend/node_modules/svelte/src/attachments/index.js create mode 100644 frontend/node_modules/svelte/src/compiler/errors.js create mode 100644 frontend/node_modules/svelte/src/compiler/index.js create mode 100644 frontend/node_modules/svelte/src/compiler/legacy.js create mode 100644 frontend/node_modules/svelte/src/compiler/migrate/index.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/acorn.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/index.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/read/context.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/read/expression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/read/options.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/read/script.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/read/style.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/remove_typescript_nodes.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/state/element.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/state/fragment.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/state/tag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/state/text.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/utils/bracket.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/utils/create.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/utils/entities.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/utils/fuzzymatch.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/1-parse/utils/html.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/css/css-analyze.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/css/css-prune.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/css/css-warn.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/css/utils.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/index.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/utils/check_graph_for_cycles.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/AnimateDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/ArrowFunctionExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/AssignmentExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/AttachTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/AwaitBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/AwaitExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/BindDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/CallExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/ClassDeclaration.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/ClassDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/Component.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/ConstTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/DebugTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/EachBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/ExportDefaultDeclaration.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/ExportNamedDeclaration.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/ExportSpecifier.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/ExpressionStatement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/ExpressionTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/Fragment.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/FunctionDeclaration.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/FunctionExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/HtmlTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/IfBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/ImportDeclaration.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/KeyBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/LabeledStatement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/LetDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/Literal.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/MemberExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/NewExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/OnDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/PropertyDefinition.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/RenderTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/SlotElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/SnippetBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/SpreadAttribute.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/SpreadElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/StyleDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/SvelteBody.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/SvelteBoundary.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/SvelteComponent.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/SvelteDocument.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/SvelteElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/SvelteFragment.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/SvelteHead.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/SvelteSelf.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/SvelteWindow.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/TaggedTemplateExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/TemplateElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/Text.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/TitleElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/TransitionDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/UpdateExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/UseDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/VariableDeclarator.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/shared/a11y/constants.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/shared/a11y/index.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/shared/attribute.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/shared/component.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/shared/element.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/shared/fragment.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/shared/function.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/shared/snippets.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/shared/special-element.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/2-analyze/visitors/shared/utils.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/transform-client.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/transform-template/fix-attribute-casing.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/transform-template/index.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/transform-template/template.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/utils.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/AnimateDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/ArrowFunctionExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/AttachTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/Attribute.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/AwaitBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/AwaitExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/BinaryExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/BindDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/BlockStatement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/BreakStatement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/ClassBody.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/Comment.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/Component.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/ConstTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/DebugTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/EachBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/ExportNamedDeclaration.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/ExpressionStatement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/ForOfStatement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/Fragment.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/FunctionDeclaration.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/FunctionExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/HtmlTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/Identifier.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/IfBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/KeyBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/LabeledStatement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/LetDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/MemberExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/OnDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/Program.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/RenderTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/SnippetBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/SpreadAttribute.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/SvelteBody.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/SvelteBoundary.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/SvelteComponent.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/SvelteDocument.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/SvelteElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/SvelteFragment.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/SvelteHead.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/SvelteSelf.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/SvelteWindow.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/TitleElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/TransitionDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/UpdateExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/UseDirective.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/shared/declarations.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/shared/element.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/shared/events.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/shared/fragment.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/shared/function.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/shared/special_element.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/css/index.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/index.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/transform-server.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/AwaitBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/AwaitExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/ClassBody.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/Component.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/ConstTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/DebugTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/EachBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/ExpressionStatement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/Fragment.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/HtmlTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/Identifier.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/IfBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/KeyBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/LabeledStatement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/MemberExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/Program.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/PropertyDefinition.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/RegularElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/RenderTag.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/SlotElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/SnippetBlock.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/SpreadAttribute.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/SvelteComponent.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/SvelteElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/SvelteFragment.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/SvelteHead.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/SvelteSelf.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/TitleElement.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/UpdateExpression.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/shared/component.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/shared/element.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/shared/assignments.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/shared/transform-async.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/3-transform/utils.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/bindings.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/css.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/nodes.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/patterns.js create mode 100644 frontend/node_modules/svelte/src/compiler/phases/scope.js create mode 100644 frontend/node_modules/svelte/src/compiler/preprocess/decode_sourcemap.js create mode 100644 frontend/node_modules/svelte/src/compiler/preprocess/index.js create mode 100644 frontend/node_modules/svelte/src/compiler/preprocess/replace_in_code.js create mode 100644 frontend/node_modules/svelte/src/compiler/print/index.js create mode 100644 frontend/node_modules/svelte/src/compiler/state.js create mode 100644 frontend/node_modules/svelte/src/compiler/utils/assert.js create mode 100644 frontend/node_modules/svelte/src/compiler/utils/ast.js create mode 100644 frontend/node_modules/svelte/src/compiler/utils/builders.js create mode 100644 frontend/node_modules/svelte/src/compiler/utils/compile_diagnostic.js create mode 100644 frontend/node_modules/svelte/src/compiler/utils/extract_svelte_ignore.js create mode 100644 frontend/node_modules/svelte/src/compiler/utils/mapped_code.js create mode 100644 frontend/node_modules/svelte/src/compiler/utils/push_array.js create mode 100644 frontend/node_modules/svelte/src/compiler/utils/sanitize_template_string.js create mode 100644 frontend/node_modules/svelte/src/compiler/utils/slot.js create mode 100644 frontend/node_modules/svelte/src/compiler/utils/string.js create mode 100644 frontend/node_modules/svelte/src/compiler/validate-options.js create mode 100644 frontend/node_modules/svelte/src/compiler/warnings.js create mode 100644 frontend/node_modules/svelte/src/constants.js create mode 100644 frontend/node_modules/svelte/src/easing/index.js create mode 100644 frontend/node_modules/svelte/src/escaping.js create mode 100644 frontend/node_modules/svelte/src/events/index.js create mode 100644 frontend/node_modules/svelte/src/html-tree-validation.js create mode 100644 frontend/node_modules/svelte/src/index-client.js create mode 100644 frontend/node_modules/svelte/src/index-server.js create mode 100644 frontend/node_modules/svelte/src/internal/client/constants.js create mode 100644 frontend/node_modules/svelte/src/internal/client/context.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dev/assign.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dev/console-log.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dev/css.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dev/debug.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dev/elements.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dev/equality.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dev/hmr.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dev/inspect.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dev/legacy.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dev/ownership.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dev/tracing.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dev/validation.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/async.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/await.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/boundary.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/branches.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/css-props.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/each.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/html.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/if.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/key.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/slot.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/snippet.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/svelte-component.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/svelte-element.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/blocks/svelte-head.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/css.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/actions.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/attachments.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/attributes.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/bindings/document.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/bindings/input.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/bindings/media.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/bindings/navigator.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/bindings/props.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/bindings/select.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/bindings/shared.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/bindings/size.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/bindings/this.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/bindings/universal.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/bindings/window.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/class.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/custom-element.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/customizable-select.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/events.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/misc.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/style.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/elements/transitions.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/hydration.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/legacy/event-modifiers.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/legacy/lifecycle.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/legacy/misc.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/operations.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/reconciler.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/task.js create mode 100644 frontend/node_modules/svelte/src/internal/client/dom/template.js create mode 100644 frontend/node_modules/svelte/src/internal/client/error-handling.js create mode 100644 frontend/node_modules/svelte/src/internal/client/errors.js create mode 100644 frontend/node_modules/svelte/src/internal/client/hydratable.js create mode 100644 frontend/node_modules/svelte/src/internal/client/index.js create mode 100644 frontend/node_modules/svelte/src/internal/client/legacy.js create mode 100644 frontend/node_modules/svelte/src/internal/client/loop.js create mode 100644 frontend/node_modules/svelte/src/internal/client/proxy.js create mode 100644 frontend/node_modules/svelte/src/internal/client/reactivity/async.js create mode 100644 frontend/node_modules/svelte/src/internal/client/reactivity/batch.js create mode 100644 frontend/node_modules/svelte/src/internal/client/reactivity/deriveds.js create mode 100644 frontend/node_modules/svelte/src/internal/client/reactivity/effects.js create mode 100644 frontend/node_modules/svelte/src/internal/client/reactivity/equality.js create mode 100644 frontend/node_modules/svelte/src/internal/client/reactivity/props.js create mode 100644 frontend/node_modules/svelte/src/internal/client/reactivity/sources.js create mode 100644 frontend/node_modules/svelte/src/internal/client/reactivity/status.js create mode 100644 frontend/node_modules/svelte/src/internal/client/reactivity/store.js create mode 100644 frontend/node_modules/svelte/src/internal/client/reactivity/utils.js create mode 100644 frontend/node_modules/svelte/src/internal/client/render.js create mode 100644 frontend/node_modules/svelte/src/internal/client/runtime.js create mode 100644 frontend/node_modules/svelte/src/internal/client/timing.js create mode 100644 frontend/node_modules/svelte/src/internal/client/validate.js create mode 100644 frontend/node_modules/svelte/src/internal/client/warnings.js create mode 100644 frontend/node_modules/svelte/src/internal/disclose-version.js create mode 100644 frontend/node_modules/svelte/src/internal/flags/async.js create mode 100644 frontend/node_modules/svelte/src/internal/flags/index.js create mode 100644 frontend/node_modules/svelte/src/internal/flags/legacy.js create mode 100644 frontend/node_modules/svelte/src/internal/flags/tracing.js create mode 100644 frontend/node_modules/svelte/src/internal/index.js create mode 100644 frontend/node_modules/svelte/src/internal/server/abort-signal.js create mode 100644 frontend/node_modules/svelte/src/internal/server/blocks/html.js create mode 100644 frontend/node_modules/svelte/src/internal/server/blocks/snippet.js create mode 100644 frontend/node_modules/svelte/src/internal/server/context.js create mode 100644 frontend/node_modules/svelte/src/internal/server/crypto.js create mode 100644 frontend/node_modules/svelte/src/internal/server/dev.js create mode 100644 frontend/node_modules/svelte/src/internal/server/errors.js create mode 100644 frontend/node_modules/svelte/src/internal/server/hydratable.js create mode 100644 frontend/node_modules/svelte/src/internal/server/hydration.js create mode 100644 frontend/node_modules/svelte/src/internal/server/index.js create mode 100644 frontend/node_modules/svelte/src/internal/server/render-context.js create mode 100644 frontend/node_modules/svelte/src/internal/server/renderer.js create mode 100644 frontend/node_modules/svelte/src/internal/server/warnings.js create mode 100644 frontend/node_modules/svelte/src/internal/shared/attributes.js create mode 100644 frontend/node_modules/svelte/src/internal/shared/clone.js create mode 100644 frontend/node_modules/svelte/src/internal/shared/dev.js create mode 100644 frontend/node_modules/svelte/src/internal/shared/errors.js create mode 100644 frontend/node_modules/svelte/src/internal/shared/utils.js create mode 100644 frontend/node_modules/svelte/src/internal/shared/validate.js create mode 100644 frontend/node_modules/svelte/src/internal/shared/warnings.js create mode 100644 frontend/node_modules/svelte/src/legacy/legacy-client.js create mode 100644 frontend/node_modules/svelte/src/legacy/legacy-server.js create mode 100644 frontend/node_modules/svelte/src/motion/index.js create mode 100644 frontend/node_modules/svelte/src/motion/spring.js create mode 100644 frontend/node_modules/svelte/src/motion/tweened.js create mode 100644 frontend/node_modules/svelte/src/motion/utils.js create mode 100644 frontend/node_modules/svelte/src/reactivity/create-subscriber.js create mode 100644 frontend/node_modules/svelte/src/reactivity/date.js create mode 100644 frontend/node_modules/svelte/src/reactivity/index-client.js create mode 100644 frontend/node_modules/svelte/src/reactivity/index-server.js create mode 100644 frontend/node_modules/svelte/src/reactivity/map.js create mode 100644 frontend/node_modules/svelte/src/reactivity/media-query.js create mode 100644 frontend/node_modules/svelte/src/reactivity/reactive-value.js create mode 100644 frontend/node_modules/svelte/src/reactivity/set.js create mode 100644 frontend/node_modules/svelte/src/reactivity/url-search-params.js create mode 100644 frontend/node_modules/svelte/src/reactivity/url.js create mode 100644 frontend/node_modules/svelte/src/reactivity/window/index.js create mode 100644 frontend/node_modules/svelte/src/server/index.js create mode 100644 frontend/node_modules/svelte/src/store/index-client.js create mode 100644 frontend/node_modules/svelte/src/store/index-server.js create mode 100644 frontend/node_modules/svelte/src/store/shared/index.js create mode 100644 frontend/node_modules/svelte/src/store/utils.js create mode 100644 frontend/node_modules/svelte/src/transition/index.js create mode 100644 frontend/node_modules/svelte/src/utils.js create mode 100644 frontend/node_modules/svelte/src/version.js create mode 100644 frontend/node_modules/svelte/store.d.ts create mode 100644 frontend/node_modules/svelte/svelte-html.d.ts create mode 100644 frontend/node_modules/svelte/transition.d.ts create mode 100644 frontend/node_modules/svelte/types/compiler/interfaces.d.ts create mode 100644 frontend/node_modules/svelte/types/compiler/preprocess.d.ts create mode 100644 frontend/node_modules/svelte/types/index.d.ts create mode 100644 frontend/node_modules/svelte/types/index.d.ts.map create mode 100644 frontend/node_modules/totalist/dist/index.js create mode 100644 frontend/node_modules/totalist/dist/index.mjs create mode 100644 frontend/node_modules/totalist/index.d.ts create mode 100644 frontend/node_modules/totalist/license create mode 100644 frontend/node_modules/totalist/package.json create mode 100644 frontend/node_modules/totalist/readme.md create mode 100644 frontend/node_modules/totalist/sync/index.d.ts create mode 100644 frontend/node_modules/totalist/sync/index.js create mode 100644 frontend/node_modules/totalist/sync/index.mjs create mode 100644 frontend/node_modules/typescript/LICENSE.txt create mode 100644 frontend/node_modules/typescript/README.md create mode 100644 frontend/node_modules/typescript/SECURITY.md create mode 100644 frontend/node_modules/typescript/ThirdPartyNoticeText.txt create mode 100755 frontend/node_modules/typescript/bin/tsc create mode 100755 frontend/node_modules/typescript/bin/tsserver create mode 100644 frontend/node_modules/typescript/lib/_tsc.js create mode 100644 frontend/node_modules/typescript/lib/_tsserver.js create mode 100644 frontend/node_modules/typescript/lib/_typingsInstaller.js create mode 100644 frontend/node_modules/typescript/lib/cs/diagnosticMessages.generated.json create mode 100644 frontend/node_modules/typescript/lib/de/diagnosticMessages.generated.json create mode 100644 frontend/node_modules/typescript/lib/es/diagnosticMessages.generated.json create mode 100644 frontend/node_modules/typescript/lib/fr/diagnosticMessages.generated.json create mode 100644 frontend/node_modules/typescript/lib/it/diagnosticMessages.generated.json create mode 100644 frontend/node_modules/typescript/lib/ja/diagnosticMessages.generated.json create mode 100644 frontend/node_modules/typescript/lib/ko/diagnosticMessages.generated.json create mode 100644 frontend/node_modules/typescript/lib/lib.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.decorators.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.decorators.legacy.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.dom.asynciterable.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.dom.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.dom.iterable.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2015.collection.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2015.core.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2015.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2015.generator.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2015.iterable.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2015.promise.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2015.proxy.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2015.reflect.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2015.symbol.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2016.array.include.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2016.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2016.full.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2016.intl.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2017.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2017.date.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2017.full.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2017.intl.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2017.object.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2017.string.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2018.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2018.full.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2018.intl.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2018.promise.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2018.regexp.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2019.array.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2019.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2019.full.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2019.intl.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2019.object.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2019.string.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2019.symbol.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2020.bigint.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2020.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2020.date.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2020.full.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2020.intl.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2020.number.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2020.promise.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2020.string.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2021.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2021.full.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2021.intl.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2021.promise.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2021.string.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2021.weakref.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2022.array.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2022.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2022.error.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2022.full.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2022.intl.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2022.object.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2022.regexp.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2022.string.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2023.array.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2023.collection.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2023.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2023.full.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2023.intl.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2024.collection.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2024.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2024.full.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2024.object.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2024.promise.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2024.regexp.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es2024.string.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es5.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.es6.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.esnext.array.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.esnext.collection.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.esnext.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.esnext.decorators.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.esnext.disposable.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.esnext.error.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.esnext.float16.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.esnext.full.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.esnext.intl.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.esnext.iterator.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.esnext.promise.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.scripthost.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.webworker.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.webworker.importscripts.d.ts create mode 100644 frontend/node_modules/typescript/lib/lib.webworker.iterable.d.ts create mode 100644 frontend/node_modules/typescript/lib/pl/diagnosticMessages.generated.json create mode 100644 frontend/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json create mode 100644 frontend/node_modules/typescript/lib/ru/diagnosticMessages.generated.json create mode 100644 frontend/node_modules/typescript/lib/tr/diagnosticMessages.generated.json create mode 100644 frontend/node_modules/typescript/lib/tsc.js create mode 100644 frontend/node_modules/typescript/lib/tsserver.js create mode 100644 frontend/node_modules/typescript/lib/tsserverlibrary.d.ts create mode 100644 frontend/node_modules/typescript/lib/tsserverlibrary.js create mode 100644 frontend/node_modules/typescript/lib/typesMap.json create mode 100644 frontend/node_modules/typescript/lib/typescript.d.ts create mode 100644 frontend/node_modules/typescript/lib/typescript.js create mode 100644 frontend/node_modules/typescript/lib/typingsInstaller.js create mode 100644 frontend/node_modules/typescript/lib/watchGuard.js create mode 100644 frontend/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json create mode 100644 frontend/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json create mode 100644 frontend/node_modules/typescript/package.json create mode 100644 frontend/node_modules/vite/LICENSE.md create mode 100644 frontend/node_modules/vite/README.md create mode 100644 frontend/node_modules/vite/bin/openChrome.applescript create mode 100755 frontend/node_modules/vite/bin/vite.js create mode 100644 frontend/node_modules/vite/client.d.ts create mode 100644 frontend/node_modules/vite/dist/client/client.mjs create mode 100644 frontend/node_modules/vite/dist/client/env.mjs create mode 100644 frontend/node_modules/vite/dist/node-cjs/publicUtils.cjs create mode 100644 frontend/node_modules/vite/dist/node/chunks/dep-BB45zftN.js create mode 100644 frontend/node_modules/vite/dist/node/chunks/dep-BK3b2jBa.js create mode 100644 frontend/node_modules/vite/dist/node/chunks/dep-D-7KCb9p.js create mode 100644 frontend/node_modules/vite/dist/node/chunks/dep-Dnp7gl8U.js create mode 100644 frontend/node_modules/vite/dist/node/chunks/dep-IQS-Za7F.js create mode 100644 frontend/node_modules/vite/dist/node/cli.js create mode 100644 frontend/node_modules/vite/dist/node/constants.js create mode 100644 frontend/node_modules/vite/dist/node/index.d.ts create mode 100644 frontend/node_modules/vite/dist/node/index.js create mode 100644 frontend/node_modules/vite/dist/node/runtime.d.ts create mode 100644 frontend/node_modules/vite/dist/node/runtime.js create mode 100644 frontend/node_modules/vite/dist/node/types.d-aGj9QkWt.d.ts create mode 100644 frontend/node_modules/vite/index.cjs create mode 100644 frontend/node_modules/vite/index.d.cts create mode 100644 frontend/node_modules/vite/package.json create mode 100644 frontend/node_modules/vite/types/customEvent.d.ts create mode 100644 frontend/node_modules/vite/types/hmrPayload.d.ts create mode 100644 frontend/node_modules/vite/types/hot.d.ts create mode 100644 frontend/node_modules/vite/types/import-meta.d.ts create mode 100644 frontend/node_modules/vite/types/importGlob.d.ts create mode 100644 frontend/node_modules/vite/types/importMeta.d.ts create mode 100644 frontend/node_modules/vite/types/metadata.d.ts create mode 100644 frontend/node_modules/vite/types/package.json create mode 100644 frontend/node_modules/vitefu/LICENSE create mode 100644 frontend/node_modules/vitefu/README.md create mode 100644 frontend/node_modules/vitefu/package.json create mode 100644 frontend/node_modules/vitefu/src/index.cjs create mode 100644 frontend/node_modules/vitefu/src/index.d.cts create mode 100644 frontend/node_modules/vitefu/src/index.d.ts create mode 100644 frontend/node_modules/vitefu/src/index.js create mode 100644 frontend/node_modules/vitefu/src/sync.cjs create mode 100644 frontend/node_modules/zimmerframe/LICENSE create mode 100644 frontend/node_modules/zimmerframe/README.md create mode 100644 frontend/node_modules/zimmerframe/package.json create mode 100644 frontend/node_modules/zimmerframe/src/index.d.ts create mode 100644 frontend/node_modules/zimmerframe/src/types.d.ts create mode 100644 frontend/node_modules/zimmerframe/src/walk.js create mode 100644 frontend/node_modules/zimmerframe/types/index.d.ts create mode 100644 frontend/node_modules/zimmerframe/types/index.d.ts.map create mode 100644 frontend/package.json create mode 100644 frontend/src/app.html create mode 100644 frontend/src/lib/api/client.ts create mode 100644 frontend/src/lib/stores/auth.ts create mode 100644 frontend/src/routes/+layout.svelte create mode 100644 frontend/src/routes/+page.svelte create mode 100644 frontend/src/routes/aliases/+page.svelte create mode 100644 frontend/src/routes/auth/change-password/+page.svelte create mode 100644 frontend/src/routes/auth/dashboard/+page.svelte create mode 100644 frontend/src/routes/auth/forgot/+page.svelte create mode 100644 frontend/src/routes/auth/login/+page.svelte create mode 100644 frontend/src/routes/domains/+page.svelte create mode 100644 frontend/src/routes/domains/[name]/+page.svelte create mode 100644 frontend/src/routes/domains/[name]/aliases/+page.svelte create mode 100644 frontend/src/routes/domains/[name]/users/+page.svelte create mode 100644 frontend/src/routes/logs/+page.svelte create mode 100644 frontend/src/routes/queue/+page.svelte create mode 100644 frontend/src/routes/users/+page.svelte create mode 100644 frontend/static/favicon.png create mode 100644 frontend/svelte.config.js create mode 100644 frontend/tsconfig.json create mode 100644 frontend/vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b3b6ba2 --- /dev/null +++ b/Makefile @@ -0,0 +1,71 @@ +.PHONY: all dev-frontend dev-backend build build-frontend build-backend clean test lint + +# Variables +APP_NAME := imc-vibe +FRONTEND_DIR := frontend +BACKEND_DIR := backend +BUILD_DIR := build + +# Default target +all: build + +# Build everything (frontend + backend + embed) +build: build-frontend build-backend + +# Build frontend only +build-frontend: + @echo "Building frontend..." + cd $(FRONTEND_DIR) && bun install --frozen-lockfile + cd $(FRONTEND_DIR) && bun run build + @echo "Frontend built successfully" + +# Build backend only (copies frontend build into embed directory) +build-backend: build-frontend + @echo "Copying frontend to embed directory..." + rm -rf $(BACKEND_DIR)/cmd/server/embed + cp -r $(FRONTEND_DIR)/build $(BACKEND_DIR)/cmd/server/embed + @echo "Building backend..." + cd $(BACKEND_DIR) && go mod tidy + cd $(BACKEND_DIR) && go build -ldflags "-s -w" -o ../$(BUILD_DIR)/$(APP_NAME) ./cmd/server + @echo "Backend built successfully" + +# Development targets +dev-frontend: + @echo "Starting frontend dev server..." + cd $(FRONTEND_DIR) && bun run dev + +dev-backend: + @echo "Starting backend dev server..." + cd $(BACKEND_DIR) && USE_EMBEDDED=false go run ./cmd/server + +# Clean build artifacts +clean: + @echo "Cleaning..." + rm -rf $(BUILD_DIR) + rm -rf $(FRONTEND_DIR)/build + rm -rf $(FRONTEND_DIR)/.svelte-kit + rm -rf $(BACKEND_DIR)/cmd/server/embed + cd $(BACKEND_DIR) && go clean + @echo "Cleaned successfully" + +# Test +test: + cd $(BACKEND_DIR) && go test ./... + +# Lint +lint: + cd $(BACKEND_DIR) && go vet ./... + +# Help +help: + @echo "Available targets:" + @echo " all - Build frontend and backend (default)" + @echo " build - Build frontend and backend" + @echo " build-frontend - Build frontend only" + @echo " build-backend - Build backend only" + @echo " dev-frontend - Start frontend dev server" + @echo " dev-backend - Start backend dev server" + @echo " clean - Remove build artifacts" + @echo " test - Run backend tests" + @echo " lint - Run Go vet" + @echo " help - Show this help" diff --git a/backend/.env b/backend/.env new file mode 100644 index 0000000..c47d326 --- /dev/null +++ b/backend/.env @@ -0,0 +1,8 @@ +DB_HOST=localhost +DB_PORT=3306 +DB_USER=mailadmin +DB_PASSWORD=MAILADMIN-PASSWORD-HERE +DB_NAME=mailserver +JWT_SECRET=change-this-secret-in-production +ADMIN_USER=admin +ADMIN_PASSWORD=admin123 diff --git a/backend/.env.example b/backend/.env.example new file mode 100644 index 0000000..6d1fda1 --- /dev/null +++ b/backend/.env.example @@ -0,0 +1,19 @@ +# Database +DB_HOST=localhost +DB_PORT=3306 +DB_USER=mailadmin +DB_PASSWORD=your-password +DB_NAME=mailserver + +# App +PORT=8080 +USE_EMBEDDED=true +JWT_SECRET=change-this-to-a-random-secret + +# Mail server paths +MAIL_DATA_DIR=/var/vmail +POSTQUEUE_PATH=/usr/sbin/postqueue +POSTSUPER_PATH=/usr/sbin/postsuper +DOVECOT_QUOTA_CMD=/usr/bin/doveadm +JOURNALCTL_PATH=/usr/bin/journalctl +RSPMAD_API=http://127.0.0.1:11334 diff --git a/backend/cmd/server/embed/_app/env.js b/backend/cmd/server/embed/_app/env.js new file mode 100644 index 0000000..f5427da --- /dev/null +++ b/backend/cmd/server/embed/_app/env.js @@ -0,0 +1 @@ +export const env={} \ No newline at end of file diff --git a/backend/cmd/server/embed/_app/immutable/assets/0.DkgBtk4_.css b/backend/cmd/server/embed/_app/immutable/assets/0.DkgBtk4_.css new file mode 100644 index 0000000..792fc3f --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/assets/0.DkgBtk4_.css @@ -0,0 +1 @@ +.loading.svelte-12qhfyh{min-height:100vh;display:flex;align-items:center;justify-content:center;font-size:1.2rem;color:#666}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,sans-serif;background:#f5f5f5}.app.svelte-12qhfyh{min-height:100vh}header.svelte-12qhfyh{background:#2c3e50;color:#fff;padding:.75rem 2rem;display:flex;align-items:center;gap:2rem;flex-wrap:wrap}h1.svelte-12qhfyh{margin:0;font-size:1.25rem}nav.svelte-12qhfyh{display:flex;gap:.5rem;flex:1}nav.svelte-12qhfyh a:where(.svelte-12qhfyh){color:#ecf0f1;text-decoration:none;padding:.5rem 1rem;border-radius:4px;font-size:.9rem;transition:background .2s}nav.svelte-12qhfyh a:where(.svelte-12qhfyh):hover{background:#34495e}main.svelte-12qhfyh{padding:2rem;max-width:1400px;margin:0 auto}.user-menu.svelte-12qhfyh{display:flex;align-items:center;gap:1rem;font-size:.9rem}.user-menu.svelte-12qhfyh span:where(.svelte-12qhfyh){color:#ecf0f1}.user-menu.svelte-12qhfyh a:where(.svelte-12qhfyh){color:#ecf0f1;text-decoration:none;padding:.375rem .75rem;border:1px solid #7f8c8d;border-radius:4px;font-size:.85rem}.user-menu.svelte-12qhfyh a:where(.svelte-12qhfyh):hover{background:#34495e}.user-menu.svelte-12qhfyh button:where(.svelte-12qhfyh){background:transparent;border:1px solid #7f8c8d;color:#ecf0f1;padding:.375rem .75rem;border-radius:4px;cursor:pointer;font-size:.85rem}.user-menu.svelte-12qhfyh button:where(.svelte-12qhfyh):hover{background:#34495e} diff --git a/backend/cmd/server/embed/_app/immutable/assets/10.Qar-kS8x.css b/backend/cmd/server/embed/_app/immutable/assets/10.Qar-kS8x.css new file mode 100644 index 0000000..bbde314 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/assets/10.Qar-kS8x.css @@ -0,0 +1 @@ +.header.svelte-15uyvzd{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem;gap:1rem}.back.svelte-15uyvzd{color:#3498db;text-decoration:none;font-size:.9rem}.back.svelte-15uyvzd:hover{text-decoration:underline}.header.svelte-15uyvzd h2:where(.svelte-15uyvzd){flex:1;margin:0}table.svelte-15uyvzd{width:100%;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}th.svelte-15uyvzd,td.svelte-15uyvzd{padding:1rem;text-align:left;border-bottom:1px solid #eee}th.svelte-15uyvzd{background:#f8f9fa;font-weight:600}button.svelte-15uyvzd{padding:.5rem 1rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff}button.danger.svelte-15uyvzd{background:#e74c3c}.modal-backdrop.svelte-15uyvzd{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;border:none;cursor:pointer;z-index:100}.modal.svelte-15uyvzd{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;padding:2rem;border-radius:8px;min-width:400px;z-index:101}.modal.svelte-15uyvzd h3:where(.svelte-15uyvzd){margin-top:0}.modal.svelte-15uyvzd form:where(.svelte-15uyvzd){display:flex;flex-direction:column;gap:1rem}.modal.svelte-15uyvzd label:where(.svelte-15uyvzd){display:flex;flex-direction:column;gap:.5rem}.modal.svelte-15uyvzd input:where(.svelte-15uyvzd){padding:.5rem;border:1px solid #ddd;border-radius:4px}.actions.svelte-15uyvzd{display:flex;gap:1rem;justify-content:flex-end} diff --git a/backend/cmd/server/embed/_app/immutable/assets/11.D38O3Xxc.css b/backend/cmd/server/embed/_app/immutable/assets/11.D38O3Xxc.css new file mode 100644 index 0000000..14eb981 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/assets/11.D38O3Xxc.css @@ -0,0 +1 @@ +.header.svelte-oa5z6t{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem;gap:1rem}.back.svelte-oa5z6t{color:#3498db;text-decoration:none;font-size:.9rem}.back.svelte-oa5z6t:hover{text-decoration:underline}.header.svelte-oa5z6t h2:where(.svelte-oa5z6t){flex:1;margin:0}table.svelte-oa5z6t{width:100%;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}th.svelte-oa5z6t,td.svelte-oa5z6t{padding:1rem;text-align:left;border-bottom:1px solid #eee}th.svelte-oa5z6t{background:#f8f9fa;font-weight:600}button.svelte-oa5z6t{padding:.5rem 1rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff}button.danger.svelte-oa5z6t{background:#e74c3c}.modal-backdrop.svelte-oa5z6t{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;border:none;cursor:pointer;z-index:100}.modal.svelte-oa5z6t{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;padding:2rem;border-radius:8px;min-width:400px;z-index:101}.modal.svelte-oa5z6t h3:where(.svelte-oa5z6t){margin-top:0}.modal.svelte-oa5z6t form:where(.svelte-oa5z6t){display:flex;flex-direction:column;gap:1rem}.modal.svelte-oa5z6t label:where(.svelte-oa5z6t){display:flex;flex-direction:column;gap:.5rem}.modal.svelte-oa5z6t input:where(.svelte-oa5z6t){padding:.5rem;border:1px solid #ddd;border-radius:4px}.actions.svelte-oa5z6t{display:flex;gap:1rem;justify-content:flex-end} diff --git a/backend/cmd/server/embed/_app/immutable/assets/12.DQdHIvb_.css b/backend/cmd/server/embed/_app/immutable/assets/12.DQdHIvb_.css new file mode 100644 index 0000000..3f6263d --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/assets/12.DQdHIvb_.css @@ -0,0 +1 @@ +.header.svelte-1lsf4ps{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem;flex-wrap:wrap;gap:1rem}.controls.svelte-1lsf4ps{display:flex;gap:1rem;align-items:center}.controls.svelte-1lsf4ps label:where(.svelte-1lsf4ps){display:flex;align-items:center;gap:.5rem}.controls.svelte-1lsf4ps select:where(.svelte-1lsf4ps),.controls.svelte-1lsf4ps input:where(.svelte-1lsf4ps){padding:.5rem;border:1px solid #ddd;border-radius:4px}button.svelte-1lsf4ps{padding:.5rem 1rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff}.log-container.svelte-1lsf4ps{background:#1a1a2e;color:#eee;padding:1rem;border-radius:8px;max-height:600px;overflow-y:auto;font-family:monospace;font-size:.85rem}.log-entry.svelte-1lsf4ps{padding:.25rem 0;border-bottom:1px solid #333}.log-entry.svelte-1lsf4ps:last-child{border-bottom:none}.timestamp.svelte-1lsf4ps{color:#888;margin-right:.5rem}.priority.svelte-1lsf4ps{margin-right:.5rem;font-weight:700}.log-entry.error.svelte-1lsf4ps .priority:where(.svelte-1lsf4ps){color:#e74c3c}.log-entry.warning.svelte-1lsf4ps .priority:where(.svelte-1lsf4ps){color:#f39c12}.log-entry.info.svelte-1lsf4ps .priority:where(.svelte-1lsf4ps){color:#3498db}.error.svelte-1lsf4ps{color:#e74c3c} diff --git a/backend/cmd/server/embed/_app/immutable/assets/13.DnP_H9DZ.css b/backend/cmd/server/embed/_app/immutable/assets/13.DnP_H9DZ.css new file mode 100644 index 0000000..5caa7e3 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/assets/13.DnP_H9DZ.css @@ -0,0 +1 @@ +.header.svelte-qegr5c{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem}table.svelte-qegr5c{width:100%;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}th.svelte-qegr5c,td.svelte-qegr5c{padding:.75rem;text-align:left;border-bottom:1px solid #eee;font-size:.9rem}th.svelte-qegr5c{background:#f8f9fa;font-weight:600}.id.svelte-qegr5c{font-family:monospace;font-size:.8rem}.reason.svelte-qegr5c{color:#e74c3c}button.svelte-qegr5c{padding:.25rem .5rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff;font-size:.8rem;margin-right:.25rem}button.danger.svelte-qegr5c{background:#e74c3c}.error.svelte-qegr5c{color:#e74c3c} diff --git a/backend/cmd/server/embed/_app/immutable/assets/2.By2d6Bxb.css b/backend/cmd/server/embed/_app/immutable/assets/2.By2d6Bxb.css new file mode 100644 index 0000000..f2098ff --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/assets/2.By2d6Bxb.css @@ -0,0 +1 @@ +.stats-grid.svelte-1uha8ag{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:1.5rem;margin-top:2rem}.stat-card.svelte-1uha8ag{background:#fff;padding:1.5rem;border-radius:8px;box-shadow:0 2px 4px #0000001a;text-align:center}.stat-card.warning.svelte-1uha8ag{border:2px solid #e74c3c}.stat-card.svelte-1uha8ag h3:where(.svelte-1uha8ag){font-size:2.5rem;margin:0;color:#2c3e50}.stat-card.svelte-1uha8ag p:where(.svelte-1uha8ag){margin:.5rem 0 0;color:#7f8c8d}.warning.svelte-1uha8ag h3:where(.svelte-1uha8ag){color:#e74c3c} diff --git a/backend/cmd/server/embed/_app/immutable/assets/4.CG2X--Z8.css b/backend/cmd/server/embed/_app/immutable/assets/4.CG2X--Z8.css new file mode 100644 index 0000000..ea80681 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/assets/4.CG2X--Z8.css @@ -0,0 +1 @@ +.page-container.svelte-imhhoo{min-height:100vh;background:#f5f7fa}.header.svelte-imhhoo{background:#fff;padding:1rem 2rem;box-shadow:0 2px 4px #0000001a}.header-content.svelte-imhhoo{max-width:800px;margin:0 auto;display:flex;justify-content:space-between;align-items:center}.header.svelte-imhhoo h1:where(.svelte-imhhoo){margin:0;font-size:1.5rem;color:#2c3e50}.user-info.svelte-imhhoo{display:flex;align-items:center;gap:1rem}.logout.svelte-imhhoo{padding:.5rem 1rem;background:#e74c3c;color:#fff;border:none;border-radius:4px;cursor:pointer}.content.svelte-imhhoo{max-width:500px;margin:2rem auto;padding:2rem;background:#fff;border-radius:12px;box-shadow:0 2px 8px #0000001a}.error.svelte-imhhoo{background:#fee;color:#c00;padding:.75rem;border-radius:4px;margin-bottom:1rem}.success.svelte-imhhoo{background:#efe;color:#060;padding:.75rem;border-radius:4px;margin-bottom:1rem}form.svelte-imhhoo{display:flex;flex-direction:column;gap:1rem}label.svelte-imhhoo{display:flex;flex-direction:column;gap:.5rem;font-weight:500;color:#555}input.svelte-imhhoo{padding:.75rem;border:1px solid #ddd;border-radius:6px;font-size:1rem}input.svelte-imhhoo:focus{outline:none;border-color:#667eea;box-shadow:0 0 0 3px #667eea1a}button.svelte-imhhoo{padding:.75rem;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;border-radius:6px;font-size:1rem;font-weight:500;cursor:pointer;margin-top:.5rem}button.svelte-imhhoo:hover:not(:disabled){opacity:.9}button.svelte-imhhoo:disabled{opacity:.6;cursor:not-allowed}.links.svelte-imhhoo{margin-top:1.5rem;text-align:center}.links.svelte-imhhoo a:where(.svelte-imhhoo){color:#667eea;text-decoration:none}.links.svelte-imhhoo a:where(.svelte-imhhoo):hover{text-decoration:underline} diff --git a/backend/cmd/server/embed/_app/immutable/assets/5.YbbfqdJp.css b/backend/cmd/server/embed/_app/immutable/assets/5.YbbfqdJp.css new file mode 100644 index 0000000..47f5e83 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/assets/5.YbbfqdJp.css @@ -0,0 +1 @@ +.page-container.svelte-1s1ktxm{min-height:100vh;background:#f5f7fa}.header.svelte-1s1ktxm{background:#fff;padding:1rem 2rem;box-shadow:0 2px 4px #0000001a;display:flex;justify-content:space-between;align-items:center}.header.svelte-1s1ktxm h1:where(.svelte-1s1ktxm){margin:0;font-size:1.5rem;color:#2c3e50}.user-info.svelte-1s1ktxm{display:flex;align-items:center;gap:1rem}.logout.svelte-1s1ktxm{padding:.5rem 1rem;background:#e74c3c;color:#fff;border:none;border-radius:4px;cursor:pointer}.content.svelte-1s1ktxm{max-width:800px;margin:2rem auto;padding:0 1rem}.card.svelte-1s1ktxm{background:#fff;padding:1.5rem;border-radius:12px;box-shadow:0 2px 8px #0000001a;margin-bottom:1.5rem}.card.svelte-1s1ktxm h2:where(.svelte-1s1ktxm){margin:0 0 1rem;color:#2c3e50;font-size:1.2rem}.info-row.svelte-1s1ktxm{display:flex;padding:.75rem 0;border-bottom:1px solid #eee}.info-row.svelte-1s1ktxm:last-child{border-bottom:none}.label.svelte-1s1ktxm{font-weight:500;color:#666;width:120px}.value.svelte-1s1ktxm{color:#2c3e50}.actions.svelte-1s1ktxm{display:flex;gap:1rem;flex-wrap:wrap}.action-btn.svelte-1s1ktxm{padding:.75rem 1.5rem;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;text-decoration:none;border-radius:6px;font-weight:500;transition:opacity .2s}.action-btn.svelte-1s1ktxm:hover{opacity:.9} diff --git a/backend/cmd/server/embed/_app/immutable/assets/6.w_qTFDpy.css b/backend/cmd/server/embed/_app/immutable/assets/6.w_qTFDpy.css new file mode 100644 index 0000000..4f2c471 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/assets/6.w_qTFDpy.css @@ -0,0 +1 @@ +.login-container.svelte-15sczaz{min-height:100vh;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#667eea,#764ba2);padding:1rem}.login-card.svelte-15sczaz{background:#fff;padding:2rem;border-radius:12px;box-shadow:0 10px 40px #0003;width:100%;max-width:400px}h1.svelte-15sczaz{text-align:center;margin:0 0 1rem;color:#2c3e50}.info.svelte-15sczaz{color:#666;text-align:center;margin-bottom:1.5rem;font-size:.9rem}.error.svelte-15sczaz{background:#fee;color:#c00;padding:.75rem;border-radius:4px;margin-bottom:1rem;font-size:.9rem}.success.svelte-15sczaz{background:#efe;color:#060;padding:1rem;border-radius:4px;margin-bottom:1rem;text-align:center}.success.svelte-15sczaz p:where(.svelte-15sczaz){margin:.5rem 0}form.svelte-15sczaz{display:flex;flex-direction:column;gap:1rem}label.svelte-15sczaz{display:flex;flex-direction:column;gap:.5rem;font-weight:500;color:#555}input.svelte-15sczaz{padding:.75rem;border:1px solid #ddd;border-radius:6px;font-size:1rem}input.svelte-15sczaz:focus{outline:none;border-color:#667eea;box-shadow:0 0 0 3px #667eea1a}button.svelte-15sczaz{padding:.75rem;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;border-radius:6px;font-size:1rem;font-weight:500;cursor:pointer;transition:opacity .2s}button.svelte-15sczaz:hover:not(:disabled){opacity:.9}button.svelte-15sczaz:disabled{opacity:.6;cursor:not-allowed}.links.svelte-15sczaz{margin-top:1.5rem;text-align:center;padding-top:1rem;border-top:1px solid #eee}.links.svelte-15sczaz a:where(.svelte-15sczaz){color:#667eea;text-decoration:none;font-size:.9rem}.links.svelte-15sczaz a:where(.svelte-15sczaz):hover{text-decoration:underline} diff --git a/backend/cmd/server/embed/_app/immutable/assets/7.Bq7myTre.css b/backend/cmd/server/embed/_app/immutable/assets/7.Bq7myTre.css new file mode 100644 index 0000000..5e0a5f3 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/assets/7.Bq7myTre.css @@ -0,0 +1 @@ +.login-container.svelte-1i2smtp{min-height:100vh;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#2c3e50,#34495e)}.login-card.svelte-1i2smtp{background:#fff;padding:3rem;border-radius:12px;box-shadow:0 10px 40px #0003;width:100%;max-width:400px}h1.svelte-1i2smtp{margin:0;text-align:center;color:#2c3e50;font-size:2rem}.subtitle.svelte-1i2smtp{text-align:center;color:#7f8c8d;margin:.5rem 0 2rem}.error.svelte-1i2smtp{background:#fee;border:1px solid #fcc;color:#c00;padding:.75rem;border-radius:4px;margin-bottom:1rem;font-size:.9rem}form.svelte-1i2smtp{display:flex;flex-direction:column;gap:1.25rem}label.svelte-1i2smtp{display:flex;flex-direction:column;gap:.5rem;font-weight:500;color:#2c3e50}input.svelte-1i2smtp{padding:.75rem;border:1px solid #ddd;border-radius:6px;font-size:1rem;transition:border-color .2s}input.svelte-1i2smtp:focus{outline:none;border-color:#3498db}.forgot.svelte-1i2smtp{text-align:right;margin-top:-.5rem}.forgot.svelte-1i2smtp a:where(.svelte-1i2smtp){color:#3498db;text-decoration:none;font-size:.9rem}.forgot.svelte-1i2smtp a:where(.svelte-1i2smtp):hover{text-decoration:underline}button.svelte-1i2smtp{padding:.875rem;background:#3498db;color:#fff;border:none;border-radius:6px;font-size:1rem;font-weight:600;cursor:pointer;transition:background .2s;margin-top:.5rem}button.svelte-1i2smtp:hover:not(:disabled){background:#2980b9}button.svelte-1i2smtp:disabled{opacity:.7;cursor:not-allowed} diff --git a/backend/cmd/server/embed/_app/immutable/assets/8.neQUdyXe.css b/backend/cmd/server/embed/_app/immutable/assets/8.neQUdyXe.css new file mode 100644 index 0000000..b665553 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/assets/8.neQUdyXe.css @@ -0,0 +1 @@ +.header.svelte-83awcy{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem}table.svelte-83awcy{width:100%;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}th.svelte-83awcy,td.svelte-83awcy{padding:1rem;text-align:left;border-bottom:1px solid #eee}th.svelte-83awcy{background:#f8f9fa;font-weight:600}button.svelte-83awcy{padding:.5rem 1rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff}button.danger.svelte-83awcy{background:#e74c3c}.modal-backdrop.svelte-83awcy{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:100}.modal.svelte-83awcy{background:#fff;padding:2rem;border-radius:8px;min-width:400px}.modal.svelte-83awcy form:where(.svelte-83awcy){display:flex;flex-direction:column;gap:1rem}.modal.svelte-83awcy label:where(.svelte-83awcy){display:flex;flex-direction:column;gap:.5rem}.modal.svelte-83awcy input:where(.svelte-83awcy){padding:.5rem;border:1px solid #ddd;border-radius:4px}.actions.svelte-83awcy{display:flex;gap:1rem;justify-content:flex-end} diff --git a/backend/cmd/server/embed/_app/immutable/assets/9.Ci0QlAaW.css b/backend/cmd/server/embed/_app/immutable/assets/9.Ci0QlAaW.css new file mode 100644 index 0000000..6ef841b --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/assets/9.Ci0QlAaW.css @@ -0,0 +1 @@ +.header.svelte-lb8x40{margin-bottom:2rem}.back.svelte-lb8x40{display:inline-block;margin-bottom:1rem;color:#3498db;text-decoration:none}.back.svelte-lb8x40:hover{text-decoration:underline}.error.svelte-lb8x40{color:#e74c3c}.cards-grid.svelte-lb8x40{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:1.5rem}.card.svelte-lb8x40{background:#fff;padding:2rem;border-radius:8px;box-shadow:0 2px 4px #0000001a;text-align:center;text-decoration:none;color:inherit;transition:transform .2s,box-shadow .2s}.card.svelte-lb8x40:hover{transform:translateY(-2px);box-shadow:0 4px 8px #00000026}.card.svelte-lb8x40 h3:where(.svelte-lb8x40){font-size:3rem;margin:0;color:#3498db}.card.svelte-lb8x40 p:where(.svelte-lb8x40){margin:.5rem 0 0;color:#7f8c8d;font-size:1.1rem} diff --git a/backend/cmd/server/embed/_app/immutable/chunks/-EcHSJia.js b/backend/cmd/server/embed/_app/immutable/chunks/-EcHSJia.js new file mode 100644 index 0000000..ece78c0 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/-EcHSJia.js @@ -0,0 +1 @@ +var C=Object.defineProperty;var w=a=>{throw TypeError(a)};var D=(a,e,s)=>e in a?C(a,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):a[e]=s;var A=(a,e,s)=>D(a,typeof e!="symbol"?e+"":e,s),x=(a,e,s)=>e.has(a)||w("Cannot "+s);var t=(a,e,s)=>(x(a,e,"read from private field"),s?s.call(a):e.get(a)),u=(a,e,s)=>e.has(a)?w("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(a):e.set(a,s),E=(a,e,s,i)=>(x(a,e,"write to private field"),i?i.call(a,s):e.set(a,s),s);import{U as N,_ as g,V as R,o as F,E as M,c as S,h as k,A as B,Z as j,G as z,w as G,v as I,a9 as P,x as U,y as V,j as Z,z as T}from"./DtGl34IE.js";var d,l,c,p,v,m,b;class q{constructor(e,s=!0){A(this,"anchor");u(this,d,new Map);u(this,l,new Map);u(this,c,new Map);u(this,p,new Set);u(this,v,!0);u(this,m,e=>{if(t(this,d).has(e)){var s=t(this,d).get(e),i=t(this,l).get(s);if(i)N(i),t(this,p).delete(s);else{var n=t(this,c).get(s);n&&(t(this,l).set(s,n.effect),t(this,c).delete(s),n.fragment.lastChild.remove(),this.anchor.before(n.fragment),i=n.effect)}for(const[f,h]of t(this,d)){if(t(this,d).delete(f),f===e)break;const r=t(this,c).get(h);r&&(g(r.effect),t(this,c).delete(h))}for(const[f,h]of t(this,l)){if(f===s||t(this,p).has(f))continue;const r=()=>{if(Array.from(t(this,d).values()).includes(f)){var _=document.createDocumentFragment();j(h,_),_.append(F()),t(this,c).set(f,{effect:h,fragment:_})}else g(h);t(this,p).delete(f),t(this,l).delete(f)};t(this,v)||!i?(t(this,p).add(f),R(h,r,!1)):r()}}});u(this,b,e=>{t(this,d).delete(e);const s=Array.from(t(this,d).values());for(const[i,n]of t(this,c))s.includes(i)||(g(n.effect),t(this,c).delete(i))});this.anchor=e,E(this,v,s)}ensure(e,s){var i=S,n=z();if(s&&!t(this,l).has(e)&&!t(this,c).has(e))if(n){var f=document.createDocumentFragment(),h=F();f.append(h),t(this,c).set(e,{effect:M(()=>s(h)),fragment:f})}else t(this,l).set(e,M(()=>s(this.anchor)));if(t(this,d).set(i,e),n){for(const[r,o]of t(this,l))r===e?i.unskip_effect(o):i.skip_effect(o);for(const[r,o]of t(this,c))r===e?i.unskip_effect(o.effect):i.skip_effect(o.effect);i.oncommit(t(this,m)),i.ondiscard(t(this,b))}else k&&(this.anchor=B),t(this,m).call(this,i)}}d=new WeakMap,l=new WeakMap,c=new WeakMap,p=new WeakMap,v=new WeakMap,m=new WeakMap,b=new WeakMap;function K(a,e,s=!1){var i;k&&(i=B,I());var n=new q(a),f=s?P:0;function h(r,o){if(k){var _=U(i);if(r!==parseInt(_.substring(1))){var y=V();Z(y),n.anchor=y,T(!1),n.ensure(r,o),T(!0);return}}n.ensure(r,o)}G(()=>{var r=!1;e((o,_=0)=>{r=!0,h(_,o)}),r||h(-1,null)},f)}export{q as B,K as i}; diff --git a/backend/cmd/server/embed/_app/immutable/chunks/B3ZK_jYJ.js b/backend/cmd/server/embed/_app/immutable/chunks/B3ZK_jYJ.js new file mode 100644 index 0000000..e067bd4 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/B3ZK_jYJ.js @@ -0,0 +1 @@ +import{s as c,g as l}from"./BX-b5t2l.js";import{n as a,m as o,g as b,t as d,d as p,s as g}from"./DtGl34IE.js";let s=!1,i=Symbol();function m(e,u,r){const n=r[u]??(r[u]={store:null,source:o(void 0),unsubscribe:a});if(n.store!==e&&!(i in r))if(n.unsubscribe(),n.store=e??null,e==null)n.source.v=void 0,n.unsubscribe=a;else{var t=!0;n.unsubscribe=c(e,f=>{t?n.source.v=f:g(n.source,f)}),t=!1}return e&&i in r?l(e):b(n.source)}function y(){const e={};function u(){d(()=>{for(var r in e)e[r].unsubscribe();p(e,i,{enumerable:!1,value:!0})})}return[e,u]}function N(e){var u=s;try{return s=!1,[e(),s]}finally{s=u}}export{y as a,N as c,m as s}; diff --git a/backend/cmd/server/embed/_app/immutable/chunks/B7kAneMc.js b/backend/cmd/server/embed/_app/immutable/chunks/B7kAneMc.js new file mode 100644 index 0000000..6e13c31 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/B7kAneMc.js @@ -0,0 +1 @@ +import{s as e}from"./RKc8iKz_.js";const r=()=>{const s=e;return{page:{subscribe:s.page.subscribe},navigating:{subscribe:s.navigating.subscribe},updated:s.updated}},b={subscribe(s){return r().page.subscribe(s)}};export{b as p}; diff --git a/backend/cmd/server/embed/_app/immutable/chunks/BX-b5t2l.js b/backend/cmd/server/embed/_app/immutable/chunks/BX-b5t2l.js new file mode 100644 index 0000000..e3d342c --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/BX-b5t2l.js @@ -0,0 +1 @@ +import{n as o,u as a,ah as d}from"./DtGl34IE.js";function p(s,u,e){if(s==null)return u(void 0),o;const t=a(()=>s.subscribe(u,e));return t.unsubscribe?()=>t.unsubscribe():t}const i=[];function h(s,u=o){let e=null;const t=new Set;function c(r){if(d(s,r)&&(s=r,e)){const b=!i.length;for(const n of t)n[1](),i.push(n,s);if(b){for(let n=0;n{t.delete(n),t.size===0&&e&&(e(),e=null)}}return{set:c,update:f,subscribe:l}}function _(s){let u;return p(s,e=>u=e)(),u}export{_ as g,p as s,h as w}; diff --git a/backend/cmd/server/embed/_app/immutable/chunks/BYrNiJ2z.js b/backend/cmd/server/embed/_app/immutable/chunks/BYrNiJ2z.js new file mode 100644 index 0000000..7221eb2 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/BYrNiJ2z.js @@ -0,0 +1,2 @@ +import{h as c}from"./DtGl34IE.js";const a=[...` +\r\f \v\uFEFF`];function e(r,g,u){var f=r==null?"":""+r;if(g&&(f=f?f+" "+g:g),u){for(var t of Object.keys(u))if(u[t])f=f?f+" "+t:t;else if(f.length)for(var l=t.length,i=0;(i=f.indexOf(t,i))>=0;){var n=i+l;(i===0||a.includes(f[i-1]))&&(n===f.length||a.includes(f[n]))?f=(i===0?"":f.substring(0,i))+f.substring(n+1):i=n}}return f===""?null:f}function v(r,g,u,f,t,l){var i=r.__className;if(c||i!==u||i===void 0){var n=e(u,f,l);(!c||n!==r.getAttribute("class"))&&(n==null?r.removeAttribute("class"):r.className=n),r.__className=u}else if(l&&t!==l)for(var o in l){var s=!!l[o];(t==null||s!==!!t[o])&&r.classList.toggle(o,s)}return l}export{v as s}; diff --git a/backend/cmd/server/embed/_app/immutable/chunks/CJv7FbHz.js b/backend/cmd/server/embed/_app/immutable/chunks/CJv7FbHz.js new file mode 100644 index 0000000..a809740 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/CJv7FbHz.js @@ -0,0 +1 @@ +import{am as p,o as u,an as c,k as l,ao as E,ap as g,aq as w,h as d,A as s,ar as y,v as N,as as A,j as M,at as x}from"./DtGl34IE.js";var f;const i=((f=globalThis==null?void 0:globalThis.window)==null?void 0:f.trustedTypes)&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:t=>t});function L(t){return(i==null?void 0:i.createHTML(t))??t}function b(t){var r=p("template");return r.innerHTML=L(t.replaceAll("","")),r.content}function n(t,r){var e=c;e.nodes===null&&(e.nodes={start:t,end:r,a:null,t:null})}function R(t,r){var e=(r&g)!==0,m=(r&w)!==0,a,v=!t.startsWith("");return()=>{if(d)return n(s,null),s;a===void 0&&(a=b(v?t:""+t),e||(a=l(a)));var o=m||E?document.importNode(a,!0):a.cloneNode(!0);if(e){var T=l(o),h=o.lastChild;n(T,h)}else n(o,o);return o}}function C(t=""){if(!d){var r=u(t+"");return n(r,r),r}var e=s;return e.nodeType!==A?(e.before(e=u()),M(e)):x(e),n(e,e),e}function I(){if(d)return n(s,null),s;var t=document.createDocumentFragment(),r=document.createComment(""),e=u();return t.append(r,e),n(r,e),t}function D(t,r){if(d){var e=c;(!(e.f&y)||e.nodes.end===null)&&(e.nodes.end=s),N();return}t!==null&&t.before(r)}const O="5";var _;typeof window<"u"&&((_=window.__svelte??(window.__svelte={})).v??(_.v=new Set)).add(O);export{D as a,n as b,I as c,R as f,C as t}; diff --git a/backend/cmd/server/embed/_app/immutable/chunks/CfgL3m1f.js b/backend/cmd/server/embed/_app/immutable/chunks/CfgL3m1f.js new file mode 100644 index 0000000..ab5a7e3 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/CfgL3m1f.js @@ -0,0 +1 @@ +var I=t=>{throw TypeError(t)};var B=(t,e,n)=>e.has(t)||I("Cannot "+n);var a=(t,e,n)=>(B(t,e,"read from private field"),n?n.call(t):e.get(t)),c=(t,e,n)=>e.has(t)?I("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,n);import{o as N}from"./DR7h53-u.js";import{a0 as u,g as f,s as d}from"./DtGl34IE.js";import{w as Y}from"./BX-b5t2l.js";new URL("sveltekit-internal://");function oe(t,e){return t==="/"||e==="ignore"?t:e==="never"?t.endsWith("/")?t.slice(0,-1):t:e==="always"&&!t.endsWith("/")?t+"/":t}function ie(t){return t.split("%25").map(decodeURI).join("%25")}function le(t){for(const e in t)t[e]=decodeURIComponent(t[e]);return t}function ce({href:t}){return t.split("#")[0]}function W(...t){let e=5381;for(const n of t)if(typeof n=="string"){let r=n.length;for(;r;)e=e*33^n.charCodeAt(--r)}else if(ArrayBuffer.isView(n)){const r=new Uint8Array(n.buffer,n.byteOffset,n.byteLength);let s=r.length;for(;s;)e=e*33^r[--s]}else throw new TypeError("value must be a string or TypedArray");return(e>>>0).toString(36)}new TextEncoder;new TextDecoder;function X(t){const e=atob(t),n=new Uint8Array(e.length);for(let r=0;r((t instanceof Request?t.method:(e==null?void 0:e.method)||"GET")!=="GET"&&_.delete(U(t)),J(t,e));const _=new Map;function ue(t,e){const n=U(t,e),r=document.querySelector(n);if(r!=null&&r.textContent){r.remove();let{body:s,...l}=JSON.parse(r.textContent);const o=r.getAttribute("data-ttl");return o&&_.set(n,{body:s,init:l,ttl:1e3*Number(o)}),r.getAttribute("data-b64")!==null&&(s=X(s)),Promise.resolve(new Response(s,l))}return window.fetch(t,e)}function fe(t,e,n){if(_.size>0){const r=U(t,n),s=_.get(r);if(s){if(performance.now()o)}function s(o){n=!1,e.set(o)}function l(o){let i;return e.subscribe(h=>{(i===void 0||n&&h!==i)&&o(i=h)})}return{notify:r,set:s,subscribe:l}}const D={v:()=>{}};function Se(){const{set:t,subscribe:e}=Y(!1);let n;async function r(){clearTimeout(n);try{const s=await fetch(`${F}/_app/version.json`,{headers:{pragma:"no-cache","cache-control":"no-cache"}});if(!s.ok)return!1;const o=(await s.json()).version!==Q;return o&&(t(!0),D.v(),clearTimeout(n)),o}catch{return!1}}return{subscribe:e,check:r}}function Z(t,e,n){return t.origin!==q||!t.pathname.startsWith(e)?!0:n?t.pathname!==location.pathname:!1}function ke(t){}const H=new Set(["load","prerender","csr","ssr","trailingSlash","config"]);[...H];const ee=new Set([...H]);[...ee];let E,x,T;const te=N.toString().includes("$$")||/function \w+\(\) \{\}/.test(N.toString()),$="a:";var b,w,m,v,p,y,A,R,V,S,j,k,G;te?(E={data:{},form:null,error:null,params:{},route:{id:null},state:{},status:-1,url:new URL($)},x={current:null},T={current:!1}):(E=new(V=class{constructor(){c(this,b,u({}));c(this,w,u(null));c(this,m,u(null));c(this,v,u({}));c(this,p,u({id:null}));c(this,y,u({}));c(this,A,u(-1));c(this,R,u(new URL($)))}get data(){return f(a(this,b))}set data(e){d(a(this,b),e)}get form(){return f(a(this,w))}set form(e){d(a(this,w),e)}get error(){return f(a(this,m))}set error(e){d(a(this,m),e)}get params(){return f(a(this,v))}set params(e){d(a(this,v),e)}get route(){return f(a(this,p))}set route(e){d(a(this,p),e)}get state(){return f(a(this,y))}set state(e){d(a(this,y),e)}get status(){return f(a(this,A))}set status(e){d(a(this,A),e)}get url(){return f(a(this,R))}set url(e){d(a(this,R),e)}},b=new WeakMap,w=new WeakMap,m=new WeakMap,v=new WeakMap,p=new WeakMap,y=new WeakMap,A=new WeakMap,R=new WeakMap,V),x=new(j=class{constructor(){c(this,S,u(null))}get current(){return f(a(this,S))}set current(e){d(a(this,S),e)}},S=new WeakMap,j),T=new(G=class{constructor(){c(this,k,u(!1))}get current(){return f(a(this,k))}set current(e){d(a(this,k),e)}},k=new WeakMap,G),D.v=()=>T.current=!0);function Ie(t){Object.assign(E,t)}export{be as H,we as N,_e as P,ge as S,Ae as a,M as b,Se as c,ce as d,le as e,pe as f,ye as g,oe as h,Z as i,L as j,ie as k,de as l,fe as m,x as n,q as o,E as p,ue as q,me as r,ve as s,he as t,Re as u,Ie as v,ke as w}; diff --git a/backend/cmd/server/embed/_app/immutable/chunks/DFRBE_Uq.js b/backend/cmd/server/embed/_app/immutable/chunks/DFRBE_Uq.js new file mode 100644 index 0000000..aa5446f --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/DFRBE_Uq.js @@ -0,0 +1 @@ +import{aa as g,ab as d,a8 as l,u as b,ac as i,ad as m,g as p,ae as v,af as h,ag as k}from"./DtGl34IE.js";function x(t=!1){const a=g,e=a.l.u;if(!e)return;let o=()=>v(a.s);if(t){let n=0,s={};const _=h(()=>{let c=!1;const r=a.s;for(const f in r)r[f]!==s[f]&&(s[f]=r[f],c=!0);return c&&n++,n});o=()=>p(_)}e.b.length&&d(()=>{u(a,o),i(e.b)}),l(()=>{const n=b(()=>e.m.map(m));return()=>{for(const s of n)typeof s=="function"&&s()}}),e.a.length&&l(()=>{u(a,o),i(e.a)})}function u(t,a){if(t.l.s)for(const e of t.l.s)p(e);a()}k();export{x as i}; diff --git a/backend/cmd/server/embed/_app/immutable/chunks/DR7h53-u.js b/backend/cmd/server/embed/_app/immutable/chunks/DR7h53-u.js new file mode 100644 index 0000000..7c177f8 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/DR7h53-u.js @@ -0,0 +1 @@ +import{a8 as o,aa as t,ai as a,u as c}from"./DtGl34IE.js";function u(n){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function r(n){t===null&&u(),a&&t.l!==null?l(t).m.push(n):o(()=>{const e=c(n);if(typeof e=="function")return e})}function l(n){var e=n.l;return e.u??(e.u={a:[],b:[],m:[]})}export{r as o}; diff --git a/backend/cmd/server/embed/_app/immutable/chunks/DtGl34IE.js b/backend/cmd/server/embed/_app/immutable/chunks/DtGl34IE.js new file mode 100644 index 0000000..ac6b025 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/DtGl34IE.js @@ -0,0 +1 @@ +var ht=Object.defineProperty;var mn=e=>{throw TypeError(e)};var pt=(e,n,t)=>n in e?ht(e,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[n]=t;var ne=(e,n,t)=>pt(e,typeof n!="symbol"?n+"":n,t),$e=(e,n,t)=>n.has(e)||mn("Cannot "+t);var v=(e,n,t)=>($e(e,n,"read from private field"),t?t.call(e):n.get(e)),I=(e,n,t)=>n.has(e)?mn("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(e):n.set(e,t),Y=(e,n,t,r)=>($e(e,n,"write to private field"),r?r.call(e,t):n.set(e,t),t),q=(e,n,t)=>($e(e,n,"access private method"),t);var wt=Array.isArray,yt=Array.prototype.indexOf,Te=Array.prototype.includes,cr=Array.from,_r=Object.defineProperty,De=Object.getOwnPropertyDescriptor,Et=Object.getOwnPropertyDescriptors,gt=Object.prototype,mt=Array.prototype,Cn=Object.getPrototypeOf,Tn=Object.isExtensible;const Tt=()=>{};function vr(e){return e()}function bt(e){for(var n=0;n{e=r,n=s});return{promise:t,resolve:e,reject:n}}const T=2,be=4,Fe=8,Mn=1<<24,Q=16,V=32,ue=64,At=128,C=512,E=1024,O=2048,B=4096,H=8192,U=16384,he=32768,bn=1<<25,He=65536,An=1<<17,Rt=1<<18,Me=1<<19,jn=1<<20,dr=1<<25,oe=65536,Je=1<<21,un=1<<22,Z=1<<23,ie=Symbol("$state"),hr=Symbol("legacy props"),pr=Symbol(""),K=new class extends Error{constructor(){super(...arguments);ne(this,"name","StaleReactionError");ne(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}};var Pn;const yr=!!((Pn=globalThis.document)!=null&&Pn.contentType)&&globalThis.document.contentType.includes("xml"),ze=3,Ln=8;function St(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function Er(e,n,t){throw new Error("https://svelte.dev/e/each_key_duplicate")}function Ot(e){throw new Error("https://svelte.dev/e/effect_in_teardown")}function xt(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function Nt(e){throw new Error("https://svelte.dev/e/effect_orphan")}function kt(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function gr(){throw new Error("https://svelte.dev/e/hydration_failed")}function mr(e){throw new Error("https://svelte.dev/e/props_invalid_value")}function Dt(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function It(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function Pt(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function Tr(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}const br=1,Ar=2,Rr=16,Sr=1,Or=2,xr=4,Nr=8,kr=16,Dr=1,Ir=2,Ct="[",Ft="[!",Pr="[?",Mt="]",on={},b=Symbol(),jt="http://www.w3.org/1999/xhtml";function cn(e){console.warn("https://svelte.dev/e/hydration_mismatch")}function Cr(){console.warn("https://svelte.dev/e/select_multiple_invalid_value")}function Fr(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}let ce=!1;function Mr(e){ce=e}let m;function Ae(e){if(e===null)throw cn(),on;return m=e}function jr(){return Ae(ee(m))}function Lr(e){if(ce){if(ee(m)!==null)throw cn(),on;m=e}}function Yr(e=1){if(ce){for(var n=e,t=m;n--;)t=ee(t);m=t}}function qr(e=!0){for(var n=0,t=m;;){if(t.nodeType===Ln){var r=t.data;if(r===Mt){if(n===0)return t;n-=1}else(r===Ct||r===Ft||r[0]==="["&&!isNaN(Number(r.slice(1))))&&(n+=1)}var s=ee(t);e&&t.remove(),t=s}}function Hr(e){if(!e||e.nodeType!==Ln)throw cn(),on;return e.data}function Yn(e){return e===this.v}function Lt(e,n){return e!=e?n==n:e!==n||e!==null&&typeof e=="object"||typeof e=="function"}function qn(e){return!Lt(e,this.v)}let Xe=!1;function Ur(){Xe=!0}let S=null;function Ue(e){S=e}function Vr(e,n=!1,t){S={p:S,i:!1,c:null,e:null,s:e,x:null,r:w,l:Xe&&!n?{s:null,u:null,$:[]}:null}}function Br(e){var n=S,t=n.e;if(t!==null){n.e=null;for(var r of t)rt(r)}return n.i=!0,S=n.p,{}}function je(){return!Xe||S!==null&&S.l===null}let se=[];function Hn(){var e=se;se=[],bt(e)}function Rn(e){if(se.length===0&&!Ie){var n=se;queueMicrotask(()=>{n===se&&Hn()})}se.push(e)}function Yt(){for(;se.length>0;)Hn()}function qt(e){var n=w;if(n===null)return d.f|=Z,e;if(!(n.f&he)&&!(n.f&be))throw e;Ve(e,n)}function Ve(e,n){for(;n!==null;){if(n.f&At){if(!(n.f&he))throw e;try{n.b.error(e);return}catch(t){e=t}}n=n.parent}throw e}const Ht=-7169;function y(e,n){e.f=e.f&Ht|n}function _n(e){e.f&C||e.deps===null?y(e,E):y(e,B)}function Un(e){if(e!==null)for(const n of e)!(n.f&T)||!(n.f&oe)||(n.f^=oe,Un(n.deps))}function Ut(e,n,t){e.f&O?n.add(e):e.f&B&&t.add(e),Un(e.deps),y(e,E)}const te=new Set;let h=null,A=null,Qe=null,Ie=!1,Ze=!1,pe=null,Ye=null;var Sn=0;let Vt=1;var we,ye,Ee,ge,Ce,D,fe,z,X,me,R,en,nn,tn,rn,Vn;const Ke=class Ke{constructor(){I(this,R);ne(this,"id",Vt++);ne(this,"current",new Map);ne(this,"previous",new Map);I(this,we,new Set);I(this,ye,new Set);I(this,Ee,0);I(this,ge,0);I(this,Ce,null);I(this,D,[]);I(this,fe,new Set);I(this,z,new Set);I(this,X,new Map);ne(this,"is_fork",!1);I(this,me,!1)}skip_effect(n){v(this,X).has(n)||v(this,X).set(n,{d:[],m:[]})}unskip_effect(n){var t=v(this,X).get(n);if(t){v(this,X).delete(n);for(var r of t.d)y(r,O),this.schedule(r);for(r of t.m)y(r,B),this.schedule(r)}}capture(n,t){t!==b&&!this.previous.has(n)&&this.previous.set(n,t),n.f&Z||(this.current.set(n,n.v),A==null||A.set(n,n.v))}activate(){h=this}deactivate(){h=null,A=null}flush(){try{Ze=!0,h=this,q(this,R,nn).call(this)}finally{Sn=0,Qe=null,pe=null,Ye=null,Ze=!1,h=null,A=null,W.clear()}}discard(){for(const n of v(this,ye))n(this);v(this,ye).clear(),te.delete(this)}increment(n){Y(this,Ee,v(this,Ee)+1),n&&Y(this,ge,v(this,ge)+1)}decrement(n,t){Y(this,Ee,v(this,Ee)-1),n&&Y(this,ge,v(this,ge)-1),!(v(this,me)||t)&&(Y(this,me,!0),Rn(()=>{Y(this,me,!1),this.flush()}))}transfer_effects(n,t){for(const r of n)v(this,fe).add(r);for(const r of t)v(this,z).add(r);n.clear(),t.clear()}oncommit(n){v(this,we).add(n)}ondiscard(n){v(this,ye).add(n)}settled(){return(v(this,Ce)??Y(this,Ce,Fn())).promise}static ensure(){if(h===null){const n=h=new Ke;Ze||(te.add(h),Ie||Rn(()=>{h===n&&n.flush()}))}return h}apply(){{A=null;return}}schedule(n){var s;if(Qe=n,(s=n.b)!=null&&s.is_pending&&n.f&(be|Fe|Mn)&&!(n.f&he)){n.b.defer_effect(n);return}for(var t=n;t.parent!==null;){t=t.parent;var r=t.f;if(pe!==null&&t===w&&(d===null||!(d.f&T)))return;if(r&(ue|V)){if(!(r&E))return;t.f^=E}}v(this,D).push(t)}};we=new WeakMap,ye=new WeakMap,Ee=new WeakMap,ge=new WeakMap,Ce=new WeakMap,D=new WeakMap,fe=new WeakMap,z=new WeakMap,X=new WeakMap,me=new WeakMap,R=new WeakSet,en=function(){return this.is_fork||v(this,ge)>0},nn=function(){var a,i;if(Sn++>1e3&&(te.delete(this),Gt()),!q(this,R,en).call(this)){for(const l of v(this,fe))v(this,z).delete(l),y(l,O),this.schedule(l);for(const l of v(this,z))y(l,B),this.schedule(l)}const n=v(this,D);Y(this,D,[]),this.apply();var t=pe=[],r=[],s=Ye=[];for(const l of n)try{q(this,R,tn).call(this,l,t,r)}catch(o){throw zn(l),o}if(h=null,s.length>0){var f=Ke.ensure();for(const l of s)f.schedule(l)}if(pe=null,Ye=null,q(this,R,en).call(this)){q(this,R,rn).call(this,r),q(this,R,rn).call(this,t);for(const[l,o]of v(this,X))Kn(l,o)}else{v(this,Ee)===0&&te.delete(this),v(this,fe).clear(),v(this,z).clear();for(const l of v(this,we))l(this);v(this,we).clear(),On(r),On(t),(a=v(this,Ce))==null||a.resolve()}var u=h;if(v(this,D).length>0){const l=u??(u=this);v(l,D).push(...v(this,D).filter(o=>!v(l,D).includes(o)))}u!==null&&(te.add(u),q(i=u,R,nn).call(i)),te.has(this)||q(this,R,Vn).call(this)},tn=function(n,t,r){n.f^=E;for(var s=n.first;s!==null;){var f=s.f,u=(f&(V|ue))!==0,a=u&&(f&E)!==0,i=a||(f&H)!==0||v(this,X).has(s);if(!i&&s.fn!==null){u?s.f^=E:f&be?t.push(s):Le(s)&&(f&Q&&v(this,z).add(s),Se(s));var l=s.first;if(l!==null){s=l;continue}}for(;s!==null;){var o=s.next;if(o!==null){s=o;break}s=s.parent}}},rn=function(n){for(var t=0;t!this.current.has(o));if(r.length===0)n&&l.discard();else if(t.length>0){l.activate();var s=new Set,f=new Map;for(var u of t)Bn(u,r,s,f);if(v(l,D).length>0){l.apply();for(var a of v(l,D))q(i=l,R,tn).call(i,a,[],[]);Y(l,D,[])}l.deactivate()}}};let _e=Ke;function Bt(e){var n=Ie;Ie=!0;try{for(var t;;){if(Yt(),h===null)return t;h.flush()}}finally{Ie=n}}function Gt(){try{kt()}catch(e){Ve(e,Qe)}}let j=null;function On(e){var n=e.length;if(n!==0){for(var t=0;t0)){W.clear();for(const s of j){if(s.f&(U|H))continue;const f=[s];let u=s.parent;for(;u!==null;)j.has(u)&&(j.delete(u),f.push(u)),u=u.parent;for(let a=f.length-1;a>=0;a--){const i=f[a];i.f&(U|H)||Se(i)}}j.clear()}}j=null}}function Bn(e,n,t,r){if(!t.has(e)&&(t.add(e),e.reactions!==null))for(const s of e.reactions){const f=s.f;f&T?Bn(s,n,t,r):f&(un|Q)&&!(f&O)&&Gn(s,n,r)&&(y(s,O),vn(s))}}function Gn(e,n,t){const r=t.get(e);if(r!==void 0)return r;if(e.deps!==null)for(const s of e.deps){if(Te.call(n,s))return!0;if(s.f&T&&Gn(s,n,t))return t.set(s,!0),!0}return t.set(e,!1),!1}function vn(e){h.schedule(e)}function Kn(e,n){if(!(e.f&V&&e.f&E)){e.f&O?n.d.push(e):e.f&B&&n.m.push(e),y(e,E);for(var t=e.first;t!==null;)Kn(t,n),t=t.next}}function zn(e){y(e,E);for(var n=e.first;n!==null;)zn(n),n=n.next}function Kt(e,n,t,r){const s=je()?dn:$t;var f=e.filter(c=>!c.settled);if(t.length===0&&f.length===0){r(n.map(s));return}var u=w,a=zt(),i=f.length===1?f[0].promise:f.length>1?Promise.all(f.map(c=>c.promise)):null;function l(c){a();try{r(c)}catch(g){u.f&U||Ve(g,u)}Be()}if(t.length===0){i.then(()=>l(n.map(s)));return}var o=Xn();function _(){Promise.all(t.map(c=>Xt(c))).then(c=>l([...n.map(s),...c])).catch(c=>Ve(c,u)).finally(()=>o())}i?i.then(()=>{a(),_(),Be()}):_()}function zt(){var e=w,n=d,t=S,r=h;return function(f=!0){Re(e),J(n),Ue(t),f&&!(e.f&U)&&(r==null||r.activate(),r==null||r.apply())}}function Be(e=!0){Re(null),J(null),Ue(null),e&&(h==null||h.deactivate())}function Xn(){var e=w.b,n=h,t=e.is_rendered();return e.update_pending_count(1,n),n.increment(t),(r=!1)=>{e.update_pending_count(-1,n),n.decrement(t,r)}}function dn(e){var n=T|O,t=d!==null&&d.f&T?d:null;return w!==null&&(w.f|=Me),{ctx:S,deps:null,effects:null,equals:Yn,f:n,fn:e,reactions:null,rv:0,v:b,wv:0,parent:t??w,ac:null}}function Xt(e,n,t){let r=w;r===null&&St();var s=void 0,f=pn(b),u=!d,a=new Map;return sr(()=>{var g;var i=w,l=Fn();s=l.promise;try{Promise.resolve(e()).then(l.resolve,l.reject).finally(Be)}catch(p){l.reject(p),Be()}var o=h;if(u){if(i.f&he)var _=Xn();if(r.b.is_rendered())(g=a.get(o))==null||g.reject(K),a.delete(o);else{for(const p of a.values())p.reject(K);a.clear()}a.set(o,l)}const c=(p,M=void 0)=>{if(_){var x=M===K;_(x)}if(!(M===K||i.f&U)){if(o.activate(),M)f.f|=Z,ln(f,M);else{f.f&Z&&(f.f^=Z),ln(f,p);for(const[Oe,xe]of a){if(a.delete(Oe),Oe===o)break;xe.reject(K)}}o.deactivate()}};l.promise.then(c,p=>c(null,p||"unknown"))}),rr(()=>{for(const i of a.values())i.reject(K)}),new Promise(i=>{function l(o){function _(){o===s?i(f):l(s)}o.then(_,_)}l(s)})}function Gr(e){const n=dn(e);return at(n),n}function $t(e){const n=dn(e);return n.equals=qn,n}function Zt(e){var n=e.effects;if(n!==null){e.effects=null;for(var t=0;t0&&!Wn&&Qt()}return n}function Qt(){Wn=!1;for(const e of sn)e.f&E&&y(e,B),Le(e)&&Se(e);sn.clear()}function We(e){re(e,e.v+1)}function Jn(e,n,t){var r=e.reactions;if(r!==null)for(var s=je(),f=r.length,u=0;u{if(ae===f)return a();var i=d,l=ae;J(null),In(f);var o=a();return J(i),In(l),o};return r&&t.set("length",$(e.length)),new Proxy(e,{defineProperty(a,i,l){(!("value"in l)||l.configurable===!1||l.enumerable===!1||l.writable===!1)&&Dt();var o=t.get(i);return o===void 0?u(()=>{var _=$(l.value);return t.set(i,_),_}):re(o,l.value,!0),!0},deleteProperty(a,i){var l=t.get(i);if(l===void 0){if(i in a){const o=u(()=>$(b));t.set(i,o),We(s)}}else re(l,b),We(s);return!0},get(a,i,l){var g;if(i===ie)return e;var o=t.get(i),_=i in a;if(o===void 0&&(!_||(g=De(a,i))!=null&&g.writable)&&(o=u(()=>{var p=Ne(_?a[i]:b),M=$(p);return M}),t.set(i,o)),o!==void 0){var c=ke(o);return c===b?void 0:c}return Reflect.get(a,i,l)},getOwnPropertyDescriptor(a,i){var l=Reflect.getOwnPropertyDescriptor(a,i);if(l&&"value"in l){var o=t.get(i);o&&(l.value=ke(o))}else if(l===void 0){var _=t.get(i),c=_==null?void 0:_.v;if(_!==void 0&&c!==b)return{enumerable:!0,configurable:!0,value:c,writable:!0}}return l},has(a,i){var c;if(i===ie)return!0;var l=t.get(i),o=l!==void 0&&l.v!==b||Reflect.has(a,i);if(l!==void 0||w!==null&&(!o||(c=De(a,i))!=null&&c.writable)){l===void 0&&(l=u(()=>{var g=o?Ne(a[i]):b,p=$(g);return p}),t.set(i,l));var _=ke(l);if(_===b)return!1}return o},set(a,i,l,o){var gn;var _=t.get(i),c=i in a;if(r&&i==="length")for(var g=l;g<_.v;g+=1){var p=t.get(g+"");p!==void 0?re(p,b):g in a&&(p=u(()=>$(b)),t.set(g+"",p))}if(_===void 0)(!c||(gn=De(a,i))!=null&&gn.writable)&&(_=u(()=>$(void 0)),re(_,Ne(l)),t.set(i,_));else{c=_.v!==b;var M=u(()=>Ne(l));re(_,M)}var x=Reflect.getOwnPropertyDescriptor(a,i);if(x!=null&&x.set&&x.set.call(o,l),!c){if(r&&typeof i=="string"){var Oe=t.get("length"),xe=Number(i);Number.isInteger(xe)&&xe>=Oe.v&&re(Oe,xe+1)}We(s)}return!0},ownKeys(a){ke(s);var i=Reflect.ownKeys(a).filter(_=>{var c=t.get(_);return c===void 0||c.v!==b});for(var[l,o]of t)o.v!==b&&!(l in a)&&i.push(l);return i},setPrototypeOf(){It()}})}function xn(e){try{if(e!==null&&typeof e=="object"&&ie in e)return e[ie]}catch{}return e}function zr(e,n){return Object.is(xn(e),xn(n))}var Nn,er,Qn,et;function Xr(){if(Nn===void 0){Nn=window,er=/Firefox/.test(navigator.userAgent);var e=Element.prototype,n=Node.prototype,t=Text.prototype;Qn=De(n,"firstChild").get,et=De(n,"nextSibling").get,Tn(e)&&(e.__click=void 0,e.__className=void 0,e.__attributes=null,e.__style=void 0,e.__e=void 0),Tn(t)&&(t.__t=void 0)}}function Ge(e=""){return document.createTextNode(e)}function fn(e){return Qn.call(e)}function ee(e){return et.call(e)}function $r(e,n){if(!ce)return fn(e);var t=fn(m);if(t===null)t=m.appendChild(Ge());else if(n&&t.nodeType!==ze){var r=Ge();return t==null||t.before(r),Ae(r),r}return n&&wn(t),Ae(t),t}function Zr(e,n=!1){if(!ce){var t=fn(e);return t instanceof Comment&&t.data===""?ee(t):t}if(n){if((m==null?void 0:m.nodeType)!==ze){var r=Ge();return m==null||m.before(r),Ae(r),r}wn(m)}return m}function Wr(e,n=1,t=!1){let r=ce?m:e;for(var s;n--;)s=r,r=ee(r);if(!ce)return r;if(t){if((r==null?void 0:r.nodeType)!==ze){var f=Ge();return r===null?s==null||s.after(f):r.before(f),Ae(f),f}wn(r)}return Ae(r),r}function Jr(e){e.textContent=""}function Qr(){return!1}function es(e,n,t){return document.createElementNS(jt,e,void 0)}function wn(e){if(e.nodeValue.length<65536)return;let n=e.nextSibling;for(;n!==null&&n.nodeType===ze;)n.remove(),e.nodeValue+=n.nodeValue,n=e.nextSibling}let kn=!1;function nr(){kn||(kn=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{var n;if(!e.defaultPrevented)for(const t of e.target.elements)(n=t.__on_r)==null||n.call(t)})},{capture:!0}))}function yn(e){var n=d,t=w;J(null),Re(null);try{return e()}finally{J(n),Re(t)}}function ns(e,n,t,r=t){e.addEventListener(n,()=>yn(t));const s=e.__on_r;s?e.__on_r=()=>{s(),r(!0)}:e.__on_r=()=>r(!0),nr()}function nt(e){w===null&&(d===null&&Nt(),xt()),de&&Ot()}function tr(e,n){var t=n.last;t===null?n.last=n.first=e:(t.next=e,e.prev=t,n.last=e)}function G(e,n){var t=w;t!==null&&t.f&H&&(e|=H);var r={ctx:S,deps:null,nodes:null,f:e|O|C,first:null,fn:n,last:null,next:null,parent:t,b:t&&t.b,prev:null,teardown:null,wv:0,ac:null},s=r;if(e&be)pe!==null?pe.push(r):_e.ensure().schedule(r);else if(n!==null){try{Se(r)}catch(u){throw ve(r),u}s.deps===null&&s.teardown===null&&s.nodes===null&&s.first===s.last&&!(s.f&Me)&&(s=s.first,e&Q&&e&He&&s!==null&&(s.f|=He))}if(s!==null&&(s.parent=t,t!==null&&tr(s,t),d!==null&&d.f&T&&!(e&ue))){var f=d;(f.effects??(f.effects=[])).push(s)}return r}function tt(){return d!==null&&!L}function rr(e){const n=G(Fe,null);return y(n,E),n.teardown=e,n}function ts(e){nt();var n=w.f,t=!d&&(n&V)!==0&&(n&he)===0;if(t){var r=S;(r.e??(r.e=[])).push(e)}else return rt(e)}function rt(e){return G(be|jn,e)}function rs(e){return nt(),G(Fe|jn,e)}function ss(e){_e.ensure();const n=G(ue|Me,e);return(t={})=>new Promise(r=>{t.outro?ir(n,()=>{ve(n),r(void 0)}):(ve(n),r(void 0))})}function ls(e){return G(be,e)}function sr(e){return G(un|Me,e)}function fs(e,n=0){return G(Fe|n,e)}function is(e,n=[],t=[],r=[]){Kt(r,n,t,s=>{G(Fe,()=>e(...s.map(ke)))})}function as(e,n=0){var t=G(Q|n,e);return t}function us(e){return G(V|Me,e)}function st(e){var n=e.teardown;if(n!==null){const t=de,r=d;Dn(!0),J(null);try{n.call(null)}finally{Dn(t),J(r)}}}function En(e,n=!1){var t=e.first;for(e.first=e.last=null;t!==null;){const s=t.ac;s!==null&&yn(()=>{s.abort(K)});var r=t.next;t.f&ue?t.parent=null:ve(t,n),t=r}}function lr(e){for(var n=e.first;n!==null;){var t=n.next;n.f&V||ve(n),n=t}}function ve(e,n=!0){var t=!1;(n||e.f&Rt)&&e.nodes!==null&&e.nodes.end!==null&&(fr(e.nodes.start,e.nodes.end),t=!0),y(e,bn),En(e,n&&!t),Pe(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(const f of r)f.stop();st(e),e.f^=bn,e.f|=U;var s=e.parent;s!==null&&s.first!==null&<(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=null}function fr(e,n){for(;e!==null;){var t=e===n?null:ee(e);e.remove(),e=t}}function lt(e){var n=e.parent,t=e.prev,r=e.next;t!==null&&(t.next=r),r!==null&&(r.prev=t),n!==null&&(n.first===e&&(n.first=r),n.last===e&&(n.last=t))}function ir(e,n,t=!0){var r=[];ft(e,r,!0);var s=()=>{t&&ve(e),n&&n()},f=r.length;if(f>0){var u=()=>--f||s();for(var a of r)a.out(u)}else s()}function ft(e,n,t){if(!(e.f&H)){e.f^=H;var r=e.nodes&&e.nodes.t;if(r!==null)for(const a of r)(a.is_global||t)&&n.push(a);for(var s=e.first;s!==null;){var f=s.next,u=(s.f&He)!==0||(s.f&V)!==0&&(e.f&Q)!==0;ft(s,n,u?t:!1),s=f}}}function os(e){it(e,!0)}function it(e,n){if(e.f&H){e.f^=H,e.f&E||(y(e,O),_e.ensure().schedule(e));for(var t=e.first;t!==null;){var r=t.next,s=(t.f&He)!==0||(t.f&V)!==0;it(t,s?n:!1),t=r}var f=e.nodes&&e.nodes.t;if(f!==null)for(const u of f)(u.is_global||n)&&u.in()}}function cs(e,n){if(e.nodes)for(var t=e.nodes.start,r=e.nodes.end;t!==null;){var s=t===r?null:ee(t);n.append(t),t=s}}let qe=!1,de=!1;function Dn(e){de=e}let d=null,L=!1;function J(e){d=e}let w=null;function Re(e){w=e}let F=null;function at(e){d!==null&&(F===null?F=[e]:F.push(e))}let N=null,k=0,P=null;function ar(e){P=e}let ut=1,le=0,ae=le;function In(e){ae=e}function ot(){return++ut}function Le(e){var n=e.f;if(n&O)return!0;if(n&T&&(e.f&=~oe),n&B){for(var t=e.deps,r=t.length,s=0;se.wv)return!0}n&C&&A===null&&y(e,E)}return!1}function ct(e,n,t=!0){var r=e.reactions;if(r!==null&&!(F!==null&&Te.call(F,e)))for(var s=0;s{e.ac.abort(K)}),e.ac=null);try{e.f|=Je;var o=e.fn,_=o();e.f|=he;var c=e.deps,g=h==null?void 0:h.is_fork;if(N!==null){var p;if(g||Pe(e,k),c!==null&&k>0)for(c.length=k+N.length,p=0;p{const n=/^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(r);if(n)return a.push({name:n[1],matcher:n[2],optional:!1,rest:!0,chained:!0}),"(?:/([^]*))?";const o=/^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(r);if(o)return a.push({name:o[1],matcher:o[2],optional:!0,rest:!1,chained:!0}),"(?:/([^/]+))?";if(!r)return;const i=r.split(/\[(.+?)\](?!\])/);return"/"+i.map((l,c)=>{if(c%2){if(l.startsWith("x+"))return ft(String.fromCharCode(parseInt(l.slice(2),16)));if(l.startsWith("u+"))return ft(String.fromCharCode(...l.slice(2).split("-").map(m=>parseInt(m,16))));const h=de.exec(l),[,u,w,p,f]=h;return a.push({name:p,matcher:f,optional:!!u,rest:!!w,chained:w?c===1&&i[0]==="":!1}),w?"([^]*?)":u?"([^/]*)?":"([^/]+?)"}return ft(l)}).join("")}).join("")}/?$`),params:a}}function ge(t){return t!==""&&!/^\([^)]+\)$/.test(t)}function me(t){return t.slice(1).split("/").filter(ge)}function _e(t,a,e){const r={},n=t.slice(1),o=n.filter(s=>s!==void 0);let i=0;for(let s=0;sh).join("/"),i=0),c===void 0)if(l.rest)c="";else continue;if(!l.matcher||e[l.matcher](c)){r[l.name]=c;const h=a[s+1],u=n[s+1];h&&!h.rest&&h.optional&&u&&l.chained&&(i=0),!h&&!u&&Object.keys(r).length===o.length&&(i=0);continue}if(l.optional&&l.chained){i++;continue}return}if(!i)return r}function ft(t){return t.normalize().replace(/[[\]]/g,"\\$&").replace(/%/g,"%25").replace(/\//g,"%2[Ff]").replace(/\?/g,"%3[Ff]").replace(/#/g,"%23").replace(/[.*+?^${}()|\\]/g,"\\$&")}function we({nodes:t,server_loads:a,dictionary:e,matchers:r}){const n=new Set(a);return Object.entries(e).map(([s,[l,c,h]])=>{const{pattern:u,params:w}=pe(s),p={id:s,exec:f=>{const m=u.exec(f);if(m)return _e(m,w,r)},errors:[1,...h||[]].map(f=>t[f]),layouts:[0,...c||[]].map(i),leaf:o(l)};return p.errors.length=p.layouts.length=Math.max(p.errors.length,p.layouts.length),p});function o(s){const l=s<0;return l&&(s=~s),[l,t[s]]}function i(s){return s===void 0?s:[n.has(s),t[s]]}}function Bt(t,a=JSON.parse){try{return a(sessionStorage[t])}catch{}}function Ot(t,a,e=JSON.stringify){const r=e(a);try{sessionStorage[t]=r}catch{}}function ve(t){return t.filter(a=>a!=null)}function kt(t){return t instanceof yt||t instanceof Et?t.status:500}function ye(t){return t instanceof Et?t.text:"Internal Error"}const be=new Set(["icon","shortcut icon","apple-touch-icon"]);let F=null;const I=Bt(zt)??{},V=Bt(Ft)??{},A={url:Tt({}),page:Tt({}),navigating:re(null),updated:oe()};function St(t){I[t]=j()}function Ee(t,a){let e=t+1;for(;I[e];)delete I[e],e+=1;for(e=a+1;V[e];)delete V[e],e+=1}function H(t,a=!1){return a?location.replace(t.href):location.href=t.href,new Promise(()=>{})}async function Mt(){if("serviceWorker"in navigator){const t=await navigator.serviceWorker.getRegistration(L||"/");t&&await t.update()}}function jt(){}let Rt,pt,Z,U,gt,E;const tt=[],et=[];let v=null;function mt(){var t;(t=v==null?void 0:v.fork)==null||t.then(a=>a==null?void 0:a.discard()),v=null}const J=new Map,Vt=new Set,ke=new Set,B=new Set;let _={branch:[],error:null,url:null},Ht=!1,at=!1,Ct=!0,Y=!1,z=!1,Yt=!1,xt=!1,Wt,b,R,O;const nt=new Set,$t=new Map;async function Be(t,a,e){var o,i,s,l,c;(o=globalThis.__sveltekit_63i6zh)!=null&&o.data&&globalThis.__sveltekit_63i6zh.data,document.URL!==location.href&&(location.href=location.href),E=t,await((s=(i=t.hooks).init)==null?void 0:s.call(i)),Rt=we(t),U=document.documentElement,gt=a,pt=t.nodes[0],Z=t.nodes[1],pt(),Z(),b=(l=history.state)==null?void 0:l[$],R=(c=history.state)==null?void 0:c[M],b||(b=R=Date.now(),history.replaceState({...history.state,[$]:b,[M]:R},""));const r=I[b];function n(){r&&(history.scrollRestoration="manual",scrollTo(r.x,r.y))}e?(n(),await $e(gt,e)):(await N({type:"enter",url:wt(E.hash?qe(new URL(location.href)):location.href),replace_state:!0}),n()),Ce()}function Se(){tt.length=0,xt=!1}function Gt(t){et.some(a=>a==null?void 0:a.snapshot)&&(V[t]=et.map(a=>{var e;return(e=a==null?void 0:a.snapshot)==null?void 0:e.capture()}))}function Jt(t){var a;(a=V[t])==null||a.forEach((e,r)=>{var n,o;(o=(n=et[r])==null?void 0:n.snapshot)==null||o.restore(e)})}function Nt(){St(b),Ot(zt,I),Gt(R),Ot(Ft,V)}async function Xt(t,a,e,r){let n;a.invalidateAll&&mt(),await N({type:"goto",url:wt(t),keepfocus:a.keepFocus,noscroll:a.noScroll,replace_state:a.replaceState,state:a.state,redirect_count:e,nav_token:r,accept:()=>{a.invalidateAll&&(xt=!0,n=[...$t.keys()]),a.invalidate&&a.invalidate.forEach(je)}}),a.invalidateAll&&X().then(X).then(()=>{$t.forEach(({resource:o},i)=>{var s;n!=null&&n.includes(i)&&((s=o.refresh)==null||s.call(o))})})}async function Re(t){if(t.id!==(v==null?void 0:v.id)){mt();const a={};nt.add(a),v={id:t.id,token:a,promise:Zt({...t,preload:a}).then(e=>(nt.delete(a),e.type==="loaded"&&e.state.error&&mt(),e)),fork:null}}return v.promise}async function ut(t){var e;const a=(e=await it(t,!1))==null?void 0:e.route;a&&await Promise.all([...a.layouts,a.leaf].filter(Boolean).map(r=>r[1]()))}async function Qt(t,a,e){var o;const r={params:_.params,route:{id:((o=_.route)==null?void 0:o.id)??null},url:new URL(location.href)};_={...t.state,nav:r};const n=document.querySelector("style[data-sveltekit]");if(n&&n.remove(),Object.assign(x,t.props.page),Wt=new E.root({target:a,props:{...t.props,stores:A,components:et},hydrate:e,sync:!1,transformError:void 0}),await Promise.resolve(),Jt(R),e){const i={from:null,to:{...r,scroll:I[b]??j()},willUnload:!1,type:"enter",complete:Promise.resolve()};B.forEach(s=>s(i))}at=!0}async function rt({url:t,params:a,branch:e,errors:r,status:n,error:o,route:i,form:s}){let l="never";if(L&&(t.pathname===L||t.pathname===L+"/"))l="always";else for(const f of e)(f==null?void 0:f.slash)!==void 0&&(l=f.slash);t.pathname=le(t.pathname,l),t.search=t.search;const c={type:"loaded",state:{url:t,params:a,branch:e,error:o,route:i},props:{constructors:ve(e).map(f=>f.node.component),page:It(x)}};s!==void 0&&(c.props.form=s);let h={},u=!x,w=0;for(let f=0;fs(new URL(i))))return!0;return!1}function Ut(t,a){return(t==null?void 0:t.type)==="data"?t:(t==null?void 0:t.type)==="skip"?a??null:null}function Ue(t,a){if(!t)return new Set(a.searchParams.keys());const e=new Set([...t.searchParams.keys(),...a.searchParams.keys()]);for(const r of e){const n=t.searchParams.getAll(r),o=a.searchParams.getAll(r);n.every(i=>o.includes(i))&&o.every(i=>n.includes(i))&&e.delete(r)}return e}function Pe({error:t,url:a,route:e,params:r}){return{type:"loaded",state:{error:t,url:a,route:e,params:r,branch:[]},props:{page:It(x),constructors:[]}}}async function Zt({id:t,invalidating:a,url:e,params:r,route:n,preload:o}){if((v==null?void 0:v.id)===t)return nt.delete(v.token),v.promise;const{errors:i,layouts:s,leaf:l}=n,c=[...s,l];i.forEach(d=>d==null?void 0:d().catch(()=>{})),c.forEach(d=>d==null?void 0:d[1]().catch(()=>{}));const h=_.url?t!==ot(_.url):!1,u=_.route?n.id!==_.route.id:!1,w=Ue(_.url,e);let p=!1;const f=c.map(async(d,g)=>{var P;if(!d)return;const y=_.branch[g];return d[1]===(y==null?void 0:y.loader)&&!Le(p,u,h,w,(P=y.universal)==null?void 0:P.uses,r)?y:(p=!0,Lt({loader:d[1],url:e,params:r,route:n,parent:async()=>{var G;const T={};for(let C=0;C{});const m=[];for(let d=0;dPromise.resolve({}),server_data_node:Ut(o)}),s={node:await Z(),loader:Z,universal:null,server:null,data:null};return rt({url:e,params:n,branch:[i,s],status:t,error:a,errors:[],route:null})}catch(i){if(i instanceof bt)return Xt(new URL(i.location,location.href),{},0);throw i}}async function Ie(t){const a=t.href;if(J.has(a))return J.get(a);let e;try{const r=(async()=>{let n=await E.hooks.reroute({url:new URL(t),fetch:async(o,i)=>xe(o,i,t).promise})??t;if(typeof n=="string"){const o=new URL(t);E.hash?o.hash=n:o.pathname=n,n=o}return n})();J.set(a,r),e=await r}catch{J.delete(a);return}return e}async function it(t,a){if(t&&!vt(t,L,E.hash)){const e=await Ie(t);if(!e)return;const r=Te(e);for(const n of Rt){const o=n.exec(r);if(o)return{id:ot(t),invalidating:a,route:n,params:se(o),url:t}}}}function Te(t){return ce(E.hash?t.hash.replace(/^#/,"").replace(/[?#].+/,""):t.pathname.slice(L.length))||"/"}function ot(t){return(E.hash?t.hash.replace(/^#/,""):t.pathname)+t.search}function te({url:t,type:a,intent:e,delta:r,event:n,scroll:o}){let i=!1;const s=At(_,e,t,a,o??null);r!==void 0&&(s.navigation.delta=r),n!==void 0&&(s.navigation.event=n);const l={...s.navigation,cancel:()=>{i=!0,s.reject(new Error("navigation cancelled"))}};return Y||Vt.forEach(c=>c(l)),i?null:s}async function N({type:t,url:a,popped:e,keepfocus:r,noscroll:n,replace_state:o,state:i={},redirect_count:s=0,nav_token:l={},accept:c=jt,block:h=jt,event:u}){var C;const w=O;O=l;const p=await it(a,!1),f=t==="enter"?At(_,p,a,t):te({url:a,type:t,delta:e==null?void 0:e.delta,intent:p,scroll:e==null?void 0:e.scroll,event:u});if(!f){h(),O===l&&(O=w);return}const m=b,d=R;c(),Y=!0,at&&f.navigation.type!=="enter"&&A.navigating.set(ht.current=f.navigation);let g=p&&await Zt(p);if(!g){if(vt(a,L,E.hash))return await H(a,o);g=await ee(a,{id:null},await W(new Et(404,"Not Found",`Not found: ${a.pathname}`),{url:a,params:{},route:{id:null}}),404,o)}if(a=(p==null?void 0:p.url)||a,O!==l)return f.reject(new Error("navigation aborted")),!1;if(g.type==="redirect"){if(s<20){await N({type:t,url:new URL(g.location,a),popped:e,keepfocus:r,noscroll:n,replace_state:o,state:i,redirect_count:s+1,nav_token:l}),f.fulfil(void 0);return}g=await Pt({status:500,error:await W(new Error("Redirect loop"),{url:a,params:{},route:{id:null}}),url:a,route:{id:null}})}else g.props.page.status>=400&&await A.updated.check()&&(await Mt(),await H(a,o));if(Se(),St(m),Gt(d),g.props.page.url.pathname!==a.pathname&&(a.pathname=g.props.page.url.pathname),i=e?e.state:i,!e){const k=o?0:1,D={[$]:b+=k,[M]:R+=k,[Kt]:i};(o?history.replaceState:history.pushState).call(history,D,"",a),o||Ee(b,R)}const y=p&&(v==null?void 0:v.id)===p.id?v.fork:null;v=null,g.props.page.state=i;let S;if(at){const k=(await Promise.all(Array.from(ke,q=>q(f.navigation)))).filter(q=>typeof q=="function");if(k.length>0){let q=function(){k.forEach(lt=>{B.delete(lt)})};k.push(q),k.forEach(lt=>{B.add(lt)})}const D=f.navigation.to;_={...g.state,nav:{params:D.params,route:D.route,url:D.url}},g.props.page&&(g.props.page.url=a);const st=y&&await y;st?S=st.commit():(F=null,Wt.$set(g.props),F&&Object.assign(g.props.page,F),he(g.props.page),S=(C=ne)==null?void 0:C()),Yt=!0}else await Qt(g,gt,!1);const{activeElement:P}=document;await S,await X(),await X();let T=null;if(Ct){const k=e?e.scroll:n?j():null;k?scrollTo(k.x,k.y):(T=a.hash&&document.getElementById(ae(a)))?T.scrollIntoView():scrollTo(0,0)}const G=document.activeElement!==P&&document.activeElement!==document.body;!r&&!G&&De(a,!T),Ct=!0,g.props.page&&(F&&Object.assign(g.props.page,F),Object.assign(x,g.props.page)),Y=!1,t==="popstate"&&Jt(R),f.fulfil(void 0),f.navigation.to&&(f.navigation.to.scroll=j()),B.forEach(k=>k(f.navigation)),A.navigating.set(ht.current=null)}async function ee(t,a,e,r,n){return t.origin===Dt&&t.pathname===location.pathname&&!Ht?await Pt({status:r,error:e,url:t,route:a}):await H(t,n)}function Oe(){let t,a={element:void 0,href:void 0},e;U.addEventListener("mousemove",s=>{const l=s.target;clearTimeout(t),t=setTimeout(()=>{o(l,K.hover)},20)});function r(s){s.defaultPrevented||o(s.composedPath()[0],K.tap)}U.addEventListener("mousedown",r),U.addEventListener("touchstart",r,{passive:!0});const n=new IntersectionObserver(s=>{for(const l of s)l.isIntersecting&&(ut(new URL(l.target.href)),n.unobserve(l.target))},{threshold:0});async function o(s,l){const c=qt(s,U),h=c===a.element&&(c==null?void 0:c.href)===a.href&&l>=e;if(!c||h)return;const{url:u,external:w,download:p}=dt(c,L,E.hash);if(w||p)return;const f=Q(c),m=u&&ot(_.url)===ot(u);if(!(f.reload||m))if(l<=f.preload_data){a={element:c,href:c.href},e=K.tap;const d=await it(u,!1);if(!d)return;Re(d)}else l<=f.preload_code&&(a={element:c,href:c.href},e=l,ut(u))}function i(){n.disconnect();for(const s of U.querySelectorAll("a")){const{url:l,external:c,download:h}=dt(s,L,E.hash);if(c||h)continue;const u=Q(s);u.reload||(u.preload_code===K.viewport&&n.observe(s),u.preload_code===K.eager&&ut(l))}}B.add(i),i()}function W(t,a){if(t instanceof yt)return t.body;const e=kt(t),r=ye(t);return E.hooks.handleError({error:t,event:a,status:e,message:r})??{message:r}}function Me(t,a={}){return t=new URL(wt(t)),t.origin!==Dt?Promise.reject(new Error("goto: invalid URL")):Xt(t,a,0)}function je(t){if(typeof t=="function")tt.push(t);else{const{href:a}=new URL(t,location.href);tt.push(e=>e.href===a)}}function Ce(){var a;history.scrollRestoration="manual",addEventListener("beforeunload",e=>{let r=!1;if(Nt(),!Y){const n=At(_,void 0,null,"leave"),o={...n.navigation,cancel:()=>{r=!0,n.reject(new Error("navigation cancelled"))}};Vt.forEach(i=>i(o))}r?(e.preventDefault(),e.returnValue=""):history.scrollRestoration="auto"}),addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&Nt()}),(a=navigator.connection)!=null&&a.saveData||Oe(),U.addEventListener("click",async e=>{if(e.button||e.which!==1||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||e.defaultPrevented)return;const r=qt(e.composedPath()[0],U);if(!r)return;const{url:n,external:o,target:i,download:s}=dt(r,L,E.hash);if(!n)return;if(i==="_parent"||i==="_top"){if(window.parent!==window)return}else if(i&&i!=="_self")return;const l=Q(r);if(!(r instanceof SVGAElement)&&n.protocol!==location.protocol&&!(n.protocol==="https:"||n.protocol==="http:")||s)return;const[h,u]=(E.hash?n.hash.replace(/^#/,""):n.href).split("#"),w=h===ct(location);if(o||l.reload&&(!w||!u)){te({url:n,type:"link",event:e})?Y=!0:e.preventDefault();return}if(u!==void 0&&w){const[,p]=_.url.href.split("#");if(p===u){if(e.preventDefault(),u===""||u==="top"&&r.ownerDocument.getElementById("top")===null)scrollTo({top:0});else{const f=r.ownerDocument.getElementById(decodeURIComponent(u));f&&(f.scrollIntoView(),f.focus())}return}if(z=!0,St(b),t(n),!l.replace_state)return;z=!1}e.preventDefault(),await new Promise(p=>{requestAnimationFrame(()=>{setTimeout(p,0)}),setTimeout(p,100)}),await N({type:"link",url:n,keepfocus:l.keepfocus,noscroll:l.noscroll,replace_state:l.replace_state??n.href===location.href,event:e})}),U.addEventListener("submit",e=>{if(e.defaultPrevented)return;const r=HTMLFormElement.prototype.cloneNode.call(e.target),n=e.submitter;if(((n==null?void 0:n.formTarget)||r.target)==="_blank"||((n==null?void 0:n.formMethod)||r.method)!=="get")return;const s=new URL((n==null?void 0:n.hasAttribute("formaction"))&&(n==null?void 0:n.formAction)||r.action);if(vt(s,L,!1))return;const l=e.target,c=Q(l);if(c.reload)return;e.preventDefault(),e.stopPropagation();const h=new FormData(l,n);s.search=new URLSearchParams(h).toString(),N({type:"form",url:s,keepfocus:c.keepfocus,noscroll:c.noscroll,replace_state:c.replace_state??s.href===location.href,event:e})}),addEventListener("popstate",async e=>{var r;if(!_t){if((r=e.state)!=null&&r[$]){const n=e.state[$];if(O={},n===b)return;const o=I[n],i=e.state[Kt]??{},s=new URL(e.state[ie]??location.href),l=e.state[M],c=_.url?ct(location)===ct(_.url):!1;if(l===R&&(Yt||c)){i!==x.state&&(x.state=i),t(s),I[b]=j(),o&&scrollTo(o.x,o.y),b=n;return}const u=n-b;await N({type:"popstate",url:s,popped:{state:i,scroll:o,delta:u},accept:()=>{b=n,R=l},block:()=>{history.go(-u)},nav_token:O,event:e})}else if(!z){const n=new URL(location.href);t(n),E.hash&&location.reload()}}}),addEventListener("hashchange",()=>{z&&(z=!1,history.replaceState({...history.state,[$]:++b,[M]:R},"",location.href))});for(const e of document.querySelectorAll("link"))be.has(e.rel)&&(e.href=e.href);addEventListener("pageshow",e=>{e.persisted&&A.navigating.set(ht.current=null)});function t(e){_.url=x.url=e,A.page.set(It(x)),A.page.notify()}}async function $e(t,{status:a=200,error:e,node_ids:r,params:n,route:o,server_route:i,data:s,form:l}){Ht=!0;const c=new URL(location.href);let h;({params:n={},route:o={id:null}}=await it(c,!1)||{}),h=Rt.find(({id:p})=>p===o.id);let u,w=!0;try{const p=r.map(async(m,d)=>{const g=s[d];return g!=null&&g.uses&&(g.uses=Ne(g.uses)),Lt({loader:E.nodes[m],url:c,params:n,route:o,parent:async()=>{const y={};for(let S=0;S{const s=history.state;_t=!0,location.replace(new URL(`#${r}`,location.href)),history.replaceState(s,"",t),a&&scrollTo(o,i),_t=!1})}else{const o=document.body,i=o.getAttribute("tabindex");o.tabIndex=-1,o.focus({preventScroll:!0,focusVisible:!1}),i!==null?o.setAttribute("tabindex",i):o.removeAttribute("tabindex")}const n=getSelection();if(n&&n.type!=="None"){const o=[];for(let i=0;i{if(n.rangeCount===o.length){for(let i=0;i{o=u,i=w});return s.catch(()=>{}),{navigation:{from:{params:t.params,route:{id:((c=t.route)==null?void 0:c.id)??null},url:t.url,scroll:j()},to:e&&{params:(a==null?void 0:a.params)??null,route:{id:((h=a==null?void 0:a.route)==null?void 0:h.id)??null},url:e,scroll:n},willUnload:!a,type:r,complete:s},fulfil:o,reject:i}}function It(t){return{data:t.data,error:t.error,form:t.form,params:t.params,route:t.route,state:t.state,status:t.status,url:t.url}}function qe(t){const a=new URL(t);return a.hash=decodeURIComponent(t.hash),a}function ae(t){let a;if(E.hash){const[,,e]=t.hash.split("#",3);a=e??""}else a=t.hash.slice(1);return decodeURIComponent(a)}export{Be as a,Me as g,A as s}; diff --git a/backend/cmd/server/embed/_app/immutable/chunks/ayyTDfEa.js b/backend/cmd/server/embed/_app/immutable/chunks/ayyTDfEa.js new file mode 100644 index 0000000..ce8adf6 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/ayyTDfEa.js @@ -0,0 +1 @@ +import{l as b,c as v,b as m,u as _,r as i,h as y}from"./DtGl34IE.js";function k(e,l,u=l){var s=new WeakSet;b(e,"input",async r=>{var a=r?e.defaultValue:e.value;if(a=t(e)?o(a):a,u(a),v!==null&&s.add(v),await m(),a!==(a=l())){var d=e.selectionStart,c=e.selectionEnd,n=e.value.length;if(e.value=a??"",c!==null){var f=e.value.length;d===c&&c===n&&f>n?(e.selectionStart=f,e.selectionEnd=f):(e.selectionStart=d,e.selectionEnd=Math.min(c,f))}}}),(y&&e.defaultValue!==e.value||_(l)==null&&e.value)&&(u(t(e)?o(e.value):e.value),v!==null&&s.add(v)),i(()=>{var r=l();if(e===document.activeElement){var a=v;if(s.has(a))return}t(e)&&r===o(e.value)||e.type==="date"&&!r&&!e.value||r!==e.value&&(e.value=r??"")})}function t(e){var l=e.type;return l==="number"||l==="range"}function o(e){return e===""?null:+e}export{k as b}; diff --git a/backend/cmd/server/embed/_app/immutable/chunks/e1WBZ7UL.js b/backend/cmd/server/embed/_app/immutable/chunks/e1WBZ7UL.js new file mode 100644 index 0000000..ef637a0 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/e1WBZ7UL.js @@ -0,0 +1 @@ +import{h as i,q as d,e as n,L as v,N as h,I as u,f as g,i as A}from"./DtGl34IE.js";const L=Symbol("is custom element"),N=Symbol("is html"),l=u?"link":"LINK";function S(r){if(i){var s=!1,e=()=>{if(!s){if(s=!0,r.hasAttribute("value")){var a=r.value;t(r,"value",null),r.value=a}if(r.hasAttribute("checked")){var o=r.checked;t(r,"checked",null),r.checked=o}}};r.__on_r=e,d(e),n()}}function t(r,s,e,a){var o=p(r);i&&(o[s]=r.getAttribute(s),s==="src"||s==="srcset"||s==="href"&&r.nodeName===l)||o[s]!==(o[s]=e)&&(s==="loading"&&(r[v]=e),e==null?r.removeAttribute(s):typeof e!="string"&&I(r).includes(s)?r[s]=e:r.setAttribute(s,e))}function p(r){return r.__attributes??(r.__attributes={[L]:r.nodeName.includes("-"),[N]:r.namespaceURI===h})}var c=new Map;function I(r){var s=r.getAttribute("is")||r.nodeName,e=c.get(s);if(e)return e;c.set(s,e=[]);for(var a,o=r,f=Element.prototype;f!==o;){a=A(o);for(var _ in a)a[_].set&&e.push(_);o=g(o)}return e}export{S as r,t as s}; diff --git a/backend/cmd/server/embed/_app/immutable/chunks/ecAlPOj8.js b/backend/cmd/server/embed/_app/immutable/chunks/ecAlPOj8.js new file mode 100644 index 0000000..c322045 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/ecAlPOj8.js @@ -0,0 +1 @@ +import{h as N,j as z,k as W,o as H,v as Z,w as $,g as L,x as j,H as ee,y as U,z as O,A as b,C as ne,B as re,D as X,c as fe,E as Y,F as ae,G as ie,J as le,K as ue,M as V,O as se,P as q,Q as oe,R as ve,m as te,S as T,T as de,U as J,V as K,W as y,X as ce,Y as pe,Z as ge,_ as he,$ as _e}from"./DtGl34IE.js";function Ce(e,a){return a}function Ee(e,a,l){for(var o=[],c=a.length,u,i=a.length,r=0;r{if(u){if(u.pending.delete(v),u.done.add(v),u.pending.size===0){var w=e.outrogroups;B(e,V(u.done)),w.delete(u),w.size===0&&(e.outrogroups=null)}}else i-=1},!1)}if(i===0){var t=o.length===0&&l!==null;if(t){var f=l,d=f.parentNode;pe(d),d.append(f),e.items.clear()}B(e,a,!t)}else u={pending:new Set(a),done:new Set},(e.outrogroups??(e.outrogroups=new Set)).add(u)}function B(e,a,l=!0){var o;if(e.pending.size>0){o=new Set;for(const i of e.pending.values())for(const r of i)o.add(e.items.get(r).e)}for(var c=0;c{var s=l();return ue(s)?s:s==null?[]:V(s)}),v,w=new Map,h=!0;function n(s){p.effect.f&de||(p.pending.delete(s),p.fallback=f,me(p,v,i,a,o),f!==null&&(v.length===0?f.f&T?(f.f^=T,D(f,null,i)):J(f):K(f,()=>{f=null})))}function C(s){p.pending.delete(s)}var I=$(()=>{v=L(d);var s=v.length;let k=!1;if(N){var R=j(i)===ee;R!==(s===0)&&(i=U(),z(i),O(!1),k=!0)}for(var _=new Set,A=fe,M=ie(),E=0;Eu(i)):(f=Y(()=>u(G??(G=H()))),f.f|=T)),s>_.size&&ae(),N&&s>0&&z(U()),!h)if(w.set(A,_),M){for(const[P,Q]of r)_.has(P)||A.skip_effect(Q.e);A.oncommit(n),A.ondiscard(C)}else n(A);k&&O(!0),L(d)}),p={effect:I,items:r,pending:w,outrogroups:null,fallback:f};h=!1,N&&(i=b)}function x(e){for(;e!==null&&!(e.f&ce);)e=e.next;return e}function me(e,a,l,o,c){var E;var u=a.length,i=e.items,r=x(e.effect.first),t,f=null,d=[],v=[],w,h,n,C;for(C=0;C0){var M=u===0?l:null;Ee(e,_,M)}}}function Te(e,a,l,o,c,u,i,r){var t=i&oe?i&ve?q(l):te(l,!1,!1):null,f=i&se?q(c):null;return{v:t,i:f,e:Y(()=>(u(a,t??l,f??c,r),()=>{e.delete(o)}))}}function D(e,a,l){if(e.nodes)for(var o=e.nodes.start,c=e.nodes.end,u=a&&!(a.f&T)?a.nodes.start:l;o!==null;){var i=_e(o);if(u.before(o),o===c)return;o=i}}function S(e,a,l){a===null?e.effect.first=l:a.next=l,l===null?e.effect.last=a:l.prev=a}export{Ae as e,Ce as i}; diff --git a/backend/cmd/server/embed/_app/immutable/chunks/n1byU5WW.js b/backend/cmd/server/embed/_app/immutable/chunks/n1byU5WW.js new file mode 100644 index 0000000..4424acc --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/chunks/n1byU5WW.js @@ -0,0 +1,2 @@ +var Ft=Object.defineProperty;var dt=e=>{throw TypeError(e)};var kt=(e,t,r)=>t in e?Ft(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r;var z=(e,t,r)=>kt(e,typeof t!="symbol"?t+"":t,r),rt=(e,t,r)=>t.has(e)||dt("Cannot "+r);var s=(e,t,r)=>(rt(e,t,"read from private field"),r?r.call(e):t.get(e)),c=(e,t,r)=>t.has(e)?dt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,r),n=(e,t,r,a)=>(rt(e,t,"write to private field"),a?a.call(e,r):t.set(e,r),r),p=(e,t,r)=>(rt(e,t,"access private method"),r);import{au as Mt,g as bt,r as Lt,u as Ct,av as ut,q as V,P as Et,A as M,h as L,an as P,aw as _t,w as Ht,v as It,H as Bt,ax as pt,E as k,o as wt,V as st,c as gt,Z as Pt,ay as Yt,az as Z,aA as Q,aB as vt,aC as xt,aD as Vt,aE as mt,aa as Tt,D as Wt,_ as it,j as X,a6 as $t,y as qt,aF as j,a9 as zt,aG as jt,aH as Jt,aI as Gt,t as Kt,aJ as Ut,d as Zt,aK as at,k as Qt,C as St,aL as Xt,$ as te,aM as nt,z as J,aN as ee,Y as re,aO as se,M as ie,p as ae,B as ne,aP as fe,a as he}from"./DtGl34IE.js";import{b as oe}from"./CJv7FbHz.js";function le(e){let t=0,r=Et(0),a;return()=>{Mt()&&(bt(r),Lt(()=>(t===0&&(a=Ct(()=>e(()=>ut(r)))),t+=1,()=>{V(()=>{t-=1,t===0&&(a==null||a(),a=void 0,ut(r))})})))}}var ce=zt|jt;function de(e,t,r,a){new ue(e,t,r,a)}var E,W,T,H,g,S,w,m,N,I,D,Y,$,q,R,tt,o,Nt,Rt,At,ft,K,U,ht;class ue{constructor(t,r,a,h){c(this,o);z(this,"parent");z(this,"is_pending",!1);z(this,"transform_error");c(this,E);c(this,W,L?M:null);c(this,T);c(this,H);c(this,g);c(this,S,null);c(this,w,null);c(this,m,null);c(this,N,null);c(this,I,0);c(this,D,0);c(this,Y,!1);c(this,$,new Set);c(this,q,new Set);c(this,R,null);c(this,tt,le(()=>(n(this,R,Et(s(this,I))),()=>{n(this,R,null)})));var i;n(this,E,t),n(this,T,r),n(this,H,f=>{var u=P;u.b=this,u.f|=_t,a(f)}),this.parent=P.b,this.transform_error=h??((i=this.parent)==null?void 0:i.transform_error)??(f=>f),n(this,g,Ht(()=>{if(L){const f=s(this,W);It();const u=f.data===Bt;if(f.data.startsWith(pt)){const d=JSON.parse(f.data.slice(pt.length));p(this,o,Rt).call(this,d)}else u?p(this,o,At).call(this):p(this,o,Nt).call(this)}else p(this,o,ft).call(this)},ce)),L&&n(this,E,M)}defer_effect(t){Yt(t,s(this,$),s(this,q))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!s(this,T).pending}update_pending_count(t,r){p(this,o,ht).call(this,t,r),n(this,I,s(this,I)+t),!(!s(this,R)||s(this,Y))&&(n(this,Y,!0),V(()=>{n(this,Y,!1),s(this,R)&&Wt(s(this,R),s(this,I))}))}get_effect_pending(){return s(this,tt).call(this),bt(s(this,R))}error(t){var r=s(this,T).onerror;let a=s(this,T).failed;if(!r&&!a)throw t;s(this,S)&&(it(s(this,S)),n(this,S,null)),s(this,w)&&(it(s(this,w)),n(this,w,null)),s(this,m)&&(it(s(this,m)),n(this,m,null)),L&&(X(s(this,W)),$t(),X(qt()));var h=!1,i=!1;const f=()=>{if(h){Gt();return}h=!0,i&&Jt(),s(this,m)!==null&&st(s(this,m),()=>{n(this,m,null)}),p(this,o,U).call(this,()=>{p(this,o,ft).call(this)})},u=l=>{try{i=!0,r==null||r(l,f),i=!1}catch(d){j(d,s(this,g)&&s(this,g).parent)}a&&n(this,m,p(this,o,U).call(this,()=>{try{return k(()=>{var d=P;d.b=this,d.f|=_t,a(s(this,E),()=>l,()=>f)})}catch(d){return j(d,s(this,g).parent),null}}))};V(()=>{var l;try{l=this.transform_error(t)}catch(d){j(d,s(this,g)&&s(this,g).parent);return}l!==null&&typeof l=="object"&&typeof l.then=="function"?l.then(u,d=>j(d,s(this,g)&&s(this,g).parent)):u(l)})}}E=new WeakMap,W=new WeakMap,T=new WeakMap,H=new WeakMap,g=new WeakMap,S=new WeakMap,w=new WeakMap,m=new WeakMap,N=new WeakMap,I=new WeakMap,D=new WeakMap,Y=new WeakMap,$=new WeakMap,q=new WeakMap,R=new WeakMap,tt=new WeakMap,o=new WeakSet,Nt=function(){try{n(this,S,k(()=>s(this,H).call(this,s(this,E))))}catch(t){this.error(t)}},Rt=function(t){const r=s(this,T).failed;r&&n(this,m,k(()=>{r(s(this,E),()=>t,()=>()=>{})}))},At=function(){const t=s(this,T).pending;t&&(this.is_pending=!0,n(this,w,k(()=>t(s(this,E)))),V(()=>{var r=n(this,N,document.createDocumentFragment()),a=wt();r.append(a),n(this,S,p(this,o,U).call(this,()=>k(()=>s(this,H).call(this,a)))),s(this,D)===0&&(s(this,E).before(r),n(this,N,null),st(s(this,w),()=>{n(this,w,null)}),p(this,o,K).call(this,gt))}))},ft=function(){try{if(this.is_pending=this.has_pending_snippet(),n(this,D,0),n(this,I,0),n(this,S,k(()=>{s(this,H).call(this,s(this,E))})),s(this,D)>0){var t=n(this,N,document.createDocumentFragment());Pt(s(this,S),t);const r=s(this,T).pending;n(this,w,k(()=>r(s(this,E))))}else p(this,o,K).call(this,gt)}catch(r){this.error(r)}},K=function(t){this.is_pending=!1,t.transfer_effects(s(this,$),s(this,q))},U=function(t){var r=P,a=mt,h=Tt;Z(s(this,g)),Q(s(this,g)),vt(s(this,g).ctx);try{return xt.ensure(),t()}catch(i){return Vt(i),null}finally{Z(r),Q(a),vt(h)}},ht=function(t,r){var a;if(!this.has_pending_snippet()){this.parent&&p(a=this.parent,o,ht).call(a,t,r);return}n(this,D,s(this,D)+t),s(this,D)===0&&(p(this,o,K).call(this,r),s(this,w)&&st(s(this,w),()=>{n(this,w,null)}),s(this,N)&&(s(this,E).before(s(this,N)),n(this,N,null)))};const _e=["touchstart","touchmove"];function pe(e){return _e.includes(e)}const C=Symbol("events"),Dt=new Set,ot=new Set;function ge(e,t,r,a={}){function h(i){if(a.capture||lt.call(t,i),!i.cancelBubble)return Ut(()=>r==null?void 0:r.call(this,i))}return e.startsWith("pointer")||e.startsWith("touch")||e==="wheel"?V(()=>{t.addEventListener(e,h,a)}):t.addEventListener(e,h,a),h}function we(e,t,r,a,h){var i={capture:a,passive:h},f=ge(e,t,r,i);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&Kt(()=>{t.removeEventListener(e,f,i)})}function me(e,t,r){(t[C]??(t[C]={}))[e]=r}function Te(e){for(var t=0;t{throw F});throw A}}finally{e[C]=t,delete e.currentTarget,Q(B),Z(x)}}}function Se(e,t){var r=t==null?"":typeof t=="object"?`${t}`:t;r!==(e.__t??(e.__t=e.nodeValue))&&(e.__t=r,e.nodeValue=`${r}`)}function ve(e,t){return Ot(e,t)}function Ne(e,t){at(),t.intro=t.intro??!1;const r=t.target,a=L,h=M;try{for(var i=Qt(r);i&&(i.nodeType!==St||i.data!==Xt);)i=te(i);if(!i)throw nt;J(!0),X(i);const f=Ot(e,{...t,anchor:i});return J(!1),f}catch(f){if(f instanceof Error&&f.message.split(` +`).some(u=>u.startsWith("https://svelte.dev/e/")))throw f;return f!==nt&&console.warn("Failed to hydrate: ",f),t.recover===!1&&ee(),at(),re(r),J(!1),ve(e,t)}finally{J(a),X(h)}}const G=new Map;function Ot(e,{target:t,anchor:r,props:a={},events:h,context:i,intro:f=!0,transformError:u}){at();var l=void 0,d=se(()=>{var B=r??t.appendChild(wt());de(B,{pending:()=>{}},v=>{ae({});var _=Tt;if(i&&(_.c=i),h&&(a.$$events=h),L&&oe(v,null),l=e(v,a)||{},L&&(P.nodes.end=M,M===null||M.nodeType!==St||M.data!==ne))throw fe(),nt;he()},u);var x=new Set,A=v=>{for(var _=0;_{var O;for(var v of x)for(const b of[t,document]){var _=G.get(b),y=_.get(v);--y==0?(b.removeEventListener(v,lt),_.delete(v),_.size===0&&G.delete(b)):_.set(v,y)}ot.delete(A),B!==r&&((O=B.parentNode)==null||O.removeChild(B))}});return ct.set(l,d),l}let ct=new WeakMap;function Re(e,t){const r=ct.get(e);return r?(ct.delete(e),r(t)):Promise.resolve()}export{me as a,Te as d,we as e,Ne as h,ve as m,Se as s,Re as u}; diff --git a/backend/cmd/server/embed/_app/immutable/entry/app.BI_Sozkn.js b/backend/cmd/server/embed/_app/immutable/entry/app.BI_Sozkn.js new file mode 100644 index 0000000..113305c --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/entry/app.BI_Sozkn.js @@ -0,0 +1,2 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["../nodes/0.D3wXY_0K.js","../chunks/CJv7FbHz.js","../chunks/DtGl34IE.js","../chunks/B3ZK_jYJ.js","../chunks/BX-b5t2l.js","../chunks/n1byU5WW.js","../chunks/-EcHSJia.js","../chunks/B7kAneMc.js","../chunks/RKc8iKz_.js","../chunks/CfgL3m1f.js","../chunks/DR7h53-u.js","../assets/0.DkgBtk4_.css","../nodes/1.Dgii_8lh.js","../chunks/DFRBE_Uq.js","../nodes/2.BMCUuUxB.js","../chunks/BYrNiJ2z.js","../assets/2.By2d6Bxb.css","../nodes/3.CFDiiGpK.js","../nodes/4.YDL696B2.js","../chunks/e1WBZ7UL.js","../chunks/ayyTDfEa.js","../assets/4.CG2X--Z8.css","../nodes/5.DHfYhdex.js","../assets/5.YbbfqdJp.css","../nodes/6.BiQ3_GJa.js","../assets/6.w_qTFDpy.css","../nodes/7.BEIquz8f.js","../assets/7.Bq7myTre.css","../nodes/8.D4QctIPu.js","../chunks/ecAlPOj8.js","../assets/8.neQUdyXe.css","../nodes/9.DflEy3LG.js","../assets/9.Ci0QlAaW.css","../nodes/10.BvOkMiuT.js","../assets/10.Qar-kS8x.css","../nodes/11.DnvWFHPj.js","../assets/11.D38O3Xxc.css","../nodes/12.CRx3MqWn.js","../assets/12.DQdHIvb_.css","../nodes/13.CB7FlS8h.js","../assets/13.DnP_H9DZ.css","../nodes/14.CFDiiGpK.js"])))=>i.map(i=>d[i]); +var M=t=>{throw TypeError(t)};var z=(t,e,a)=>e.has(t)||M("Cannot "+a);var h=(t,e,a)=>(z(t,e,"read from private field"),a?a.call(t):e.get(t)),V=(t,e,a)=>e.has(t)?M("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,a),x=(t,e,a,n)=>(z(t,e,"write to private field"),n?n.call(t,a):e.set(t,a),a);import{h as F,v as ae,w as se,a9 as ne,x as ie,y as oe,j as ue,z as G,aL as ce,A as _e,aa as de,aj as fe,r as le,u as H,an as J,aQ as me,aR as Q,aS as ve,aT as he,aU as Ee,g as R,a1 as ge,s as L,aV as Pe,T as Re,aW as ye,ai as Oe,aX as Te,aY as Ae,af as be,J as Ie,aZ as Se,a_ as X,a$ as Le,d as De,m as we,p as pe,ab as Ve,a8 as xe,b as je,a3 as w,a2 as Be,a as ke,a0 as j,a4 as Ce,a5 as Ye,a7 as Ne,b0 as B}from"../chunks/DtGl34IE.js";import{h as Ue,m as qe,u as Me,s as ze}from"../chunks/n1byU5WW.js";import{a as I,c as k,f as K,t as Fe}from"../chunks/CJv7FbHz.js";import{o as Ge}from"../chunks/DR7h53-u.js";import{B as We,i as C}from"../chunks/-EcHSJia.js";import{c as Ze}from"../chunks/B3ZK_jYJ.js";function Y(t,e,a){var n;F&&(n=_e,ae());var i=new We(t);se(()=>{var u=e()??null;if(F){var s=ie(n),r=s===ce,o=u!==null;if(r!==o){var d=oe();ue(d),i.anchor=d,G(!1),i.ensure(u,u&&(c=>a(c,u))),G(!0);return}}i.ensure(u,u&&(c=>a(c,u)))},ne)}function W(t,e){return t===e||(t==null?void 0:t[Q])===e}function N(t={},e,a,n){var i=de.r,u=J;return fe(()=>{var s,r;return le(()=>{s=r,r=[],H(()=>{t!==a(...r)&&(e(t,...r),s&&W(a(...s),t)&&e(null,...s))})}),()=>{let o=u;for(;o!==i&&o.parent!==null&&o.parent.f&me;)o=o.parent;const d=()=>{r&&W(a(...r),t)&&e(null,...r)},c=o.teardown;o.teardown=()=>{d(),c==null||c()}}}),t}function U(t,e,a,n){var O;var i=!Oe||(a&Te)!==0,u=(a&ye)!==0,s=(a&Se)!==0,r=n,o=!0,d=()=>(o&&(o=!1,r=s?H(n):n),r);let c;if(u){var S=Q in t||X in t;c=((O=ve(t,e))==null?void 0:O.set)??(S&&e in t?_=>t[e]=_:void 0)}var A,E=!1;u?[A,E]=Ze(()=>t[e]):A=t[e],A===void 0&&n!==void 0&&(A=d(),c&&(i&&he(),c(A)));var v;if(i?v=()=>{var _=t[e];return _===void 0?d():(o=!0,_)}:v=()=>{var _=t[e];return _!==void 0&&(r=void 0),_===void 0?r:_},i&&!(a&Ee))return v;if(c){var f=t.$$legacy;return function(_,l){return arguments.length>0?((!i||!l||f||E)&&c(l?v():_),_):v()}}var y=!1,g=(a&Ae?be:Ie)(()=>(y=!1,v()));u&&R(g);var b=J;return function(_,l){if(arguments.length>0){const p=l?R(g):i&&u?ge(_):_;return L(g,p),y=!0,r!==void 0&&(r=p),_}return Pe&&y||b.f&Re?g.v:R(g)}}function He(t){return class extends Je{constructor(e){super({component:t,...e})}}}var T,P;class Je{constructor(e){V(this,T);V(this,P);var u;var a=new Map,n=(s,r)=>{var o=we(r,!1,!1);return a.set(s,o),o};const i=new Proxy({...e.props||{},$$events:{}},{get(s,r){return R(a.get(r)??n(r,Reflect.get(s,r)))},has(s,r){return r===X?!0:(R(a.get(r)??n(r,Reflect.get(s,r))),Reflect.has(s,r))},set(s,r,o){return L(a.get(r)??n(r,o),o),Reflect.set(s,r,o)}});x(this,P,(e.hydrate?Ue:qe)(e.component,{target:e.target,anchor:e.anchor,props:i,context:e.context,intro:e.intro??!1,recover:e.recover,transformError:e.transformError})),(!((u=e==null?void 0:e.props)!=null&&u.$$host)||e.sync===!1)&&Le(),x(this,T,i.$$events);for(const s of Object.keys(h(this,P)))s==="$set"||s==="$destroy"||s==="$on"||De(this,s,{get(){return h(this,P)[s]},set(r){h(this,P)[s]=r},enumerable:!0});h(this,P).$set=s=>{Object.assign(i,s)},h(this,P).$destroy=()=>{Me(h(this,P))}}$set(e){h(this,P).$set(e)}$on(e,a){h(this,T)[e]=h(this,T)[e]||[];const n=(...i)=>a.call(this,...i);return h(this,T)[e].push(n),()=>{h(this,T)[e]=h(this,T)[e].filter(i=>i!==n)}}$destroy(){h(this,P).$destroy()}}T=new WeakMap,P=new WeakMap;const Qe="modulepreload",Xe=function(t,e){return new URL(t,e).href},Z={},m=function(e,a,n){let i=Promise.resolve();if(a&&a.length>0){const s=document.getElementsByTagName("link"),r=document.querySelector("meta[property=csp-nonce]"),o=(r==null?void 0:r.nonce)||(r==null?void 0:r.getAttribute("nonce"));i=Promise.allSettled(a.map(d=>{if(d=Xe(d,n),d in Z)return;Z[d]=!0;const c=d.endsWith(".css"),S=c?'[rel="stylesheet"]':"";if(!!n)for(let v=s.length-1;v>=0;v--){const f=s[v];if(f.href===d&&(!c||f.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${d}"]${S}`))return;const E=document.createElement("link");if(E.rel=c?"stylesheet":Qe,c||(E.as="script"),E.crossOrigin="",E.href=d,o&&E.setAttribute("nonce",o),document.head.appendChild(E),c)return new Promise((v,f)=>{E.addEventListener("load",v),E.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${d}`)))})}))}function u(s){const r=new Event("vite:preloadError",{cancelable:!0});if(r.payload=s,window.dispatchEvent(r),!r.defaultPrevented)throw s}return i.then(s=>{for(const r of s||[])r.status==="rejected"&&u(r.reason);return e().catch(u)})},ct={};var Ke=K('
'),$e=K(" ",1);function et(t,e){pe(e,!0);let a=U(e,"components",23,()=>[]),n=U(e,"data_0",3,null),i=U(e,"data_1",3,null);Ve(()=>e.stores.page.set(e.page)),xe(()=>{e.stores,e.page,e.constructors,a(),e.form,n(),i(),e.stores.page.notify()});let u=j(!1),s=j(!1),r=j(null);Ge(()=>{const f=e.stores.page.subscribe(()=>{R(u)&&(L(s,!0),je().then(()=>{L(r,document.title||"untitled page",!0)}))});return L(u,!0),f});const o=B(()=>e.constructors[1]);var d=$e(),c=w(d);{var S=f=>{const y=B(()=>e.constructors[0]);var g=k(),b=w(g);Y(b,()=>R(y),(O,_)=>{N(_(O,{get data(){return n()},get form(){return e.form},get params(){return e.page.params},children:(l,p)=>{var q=k(),ee=w(q);Y(ee,()=>R(o),(te,re)=>{N(re(te,{get data(){return i()},get form(){return e.form},get params(){return e.page.params}}),D=>a()[1]=D,()=>{var D;return(D=a())==null?void 0:D[1]})}),I(l,q)},$$slots:{default:!0}}),l=>a()[0]=l,()=>{var l;return(l=a())==null?void 0:l[0]})}),I(f,g)},A=f=>{const y=B(()=>e.constructors[0]);var g=k(),b=w(g);Y(b,()=>R(y),(O,_)=>{N(_(O,{get data(){return n()},get form(){return e.form},get params(){return e.page.params}}),l=>a()[0]=l,()=>{var l;return(l=a())==null?void 0:l[0]})}),I(f,g)};C(c,f=>{e.constructors[1]?f(S):f(A,-1)})}var E=Be(c,2);{var v=f=>{var y=Ke(),g=Ce(y);{var b=O=>{var _=Fe();Ne(()=>ze(_,R(r))),I(O,_)};C(g,O=>{R(s)&&O(b)})}Ye(y),I(f,y)};C(E,f=>{R(u)&&f(v)})}I(t,d),ke()}const _t=He(et),dt=[()=>m(()=>import("../nodes/0.D3wXY_0K.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11]),import.meta.url),()=>m(()=>import("../nodes/1.Dgii_8lh.js"),__vite__mapDeps([12,1,2,13,5,9,10,4,8]),import.meta.url),()=>m(()=>import("../nodes/2.BMCUuUxB.js"),__vite__mapDeps([14,1,2,10,5,6,15,16]),import.meta.url),()=>m(()=>import("../nodes/3.CFDiiGpK.js"),__vite__mapDeps([17,1,2,13,10,8,4,9]),import.meta.url),()=>m(()=>import("../nodes/4.YDL696B2.js"),__vite__mapDeps([18,1,2,10,5,6,19,20,8,4,9,21]),import.meta.url),()=>m(()=>import("../nodes/5.DHfYhdex.js"),__vite__mapDeps([22,1,2,10,5,6,8,4,9,23]),import.meta.url),()=>m(()=>import("../nodes/6.BiQ3_GJa.js"),__vite__mapDeps([24,1,2,5,6,19,20,9,10,4,25]),import.meta.url),()=>m(()=>import("../nodes/7.BEIquz8f.js"),__vite__mapDeps([26,1,2,5,6,19,20,8,4,9,10,27]),import.meta.url),()=>m(()=>import("../nodes/8.D4QctIPu.js"),__vite__mapDeps([28,1,2,5,6,29,19,20,30]),import.meta.url),()=>m(()=>import("../nodes/9.DflEy3LG.js"),__vite__mapDeps([31,1,2,3,4,5,6,19,7,8,9,10,32]),import.meta.url),()=>m(()=>import("../nodes/10.BvOkMiuT.js"),__vite__mapDeps([33,1,2,3,4,5,6,29,19,20,7,8,9,10,34]),import.meta.url),()=>m(()=>import("../nodes/11.DnvWFHPj.js"),__vite__mapDeps([35,1,2,3,4,5,6,29,19,20,7,8,9,10,36]),import.meta.url),()=>m(()=>import("../nodes/12.CRx3MqWn.js"),__vite__mapDeps([37,1,2,5,6,29,19,15,20,38]),import.meta.url),()=>m(()=>import("../nodes/13.CB7FlS8h.js"),__vite__mapDeps([39,1,2,5,6,29,40]),import.meta.url),()=>m(()=>import("../nodes/14.CFDiiGpK.js"),__vite__mapDeps([41,1,2,13,10,8,4,9]),import.meta.url)],ft=[],lt={"/":[2],"/aliases":[3],"/auth/change-password":[4],"/auth/dashboard":[5],"/auth/forgot":[6],"/auth/login":[7],"/domains":[8],"/domains/[name]":[9],"/domains/[name]/aliases":[10],"/domains/[name]/users":[11],"/logs":[12],"/queue":[13],"/users":[14]},$={handleError:({error:t})=>{console.error(t)},reroute:()=>{},transport:{}},tt=Object.fromEntries(Object.entries($.transport).map(([t,e])=>[t,e.decode])),mt=Object.fromEntries(Object.entries($.transport).map(([t,e])=>[t,e.encode])),vt=!1,ht=(t,e)=>tt[t](e);export{ht as decode,tt as decoders,lt as dictionary,mt as encoders,vt as hash,$ as hooks,ct as matchers,dt as nodes,_t as root,ft as server_loads}; diff --git a/backend/cmd/server/embed/_app/immutable/entry/start.tprRzko2.js b/backend/cmd/server/embed/_app/immutable/entry/start.tprRzko2.js new file mode 100644 index 0000000..5305aa3 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/entry/start.tprRzko2.js @@ -0,0 +1 @@ +import{a as r}from"../chunks/RKc8iKz_.js";import{w as t}from"../chunks/CfgL3m1f.js";export{t as load_css,r as start}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/0.D3wXY_0K.js b/backend/cmd/server/embed/_app/immutable/nodes/0.D3wXY_0K.js new file mode 100644 index 0000000..8472483 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/0.D3wXY_0K.js @@ -0,0 +1 @@ +import{c as A,a as h,f as q}from"../chunks/CJv7FbHz.js";import{w as j,a9 as z,p as Q,a8 as U,s as v,g as r,a3 as x,a as V,a0 as B,a4 as n,a2 as _,a5 as i,a7 as W}from"../chunks/DtGl34IE.js";import{s as G,a as H}from"../chunks/B3ZK_jYJ.js";import{d as J,a as K,s as O}from"../chunks/n1byU5WW.js";import{B as X,i as C}from"../chunks/-EcHSJia.js";import{p as Y}from"../chunks/B7kAneMc.js";import{g as f}from"../chunks/RKc8iKz_.js";function E(u,o,...d){var m=new X(u);j(()=>{const l=o()??null;m.ensure(l,l&&(s=>l(s,...d)))},z)}var Z=q('
Loading...
'),$=q(' '),aa=q('');function na(u,o){Q(o,!0);const d=()=>G(Y,"$page",m),[m,l]=H();let s=B(null),p=B(!0);U(()=>{d().url.pathname.startsWith("/auth/")?v(p,!1):I()});async function I(){var a;const e=localStorage.getItem("token");if(!e){f("/auth/login");return}try{const t=await fetch("/api/auth/me",{headers:{Authorization:`Bearer ${e}`}});if(!t.ok){f("/auth/login");return}const c=await t.json();if(v(s,c.data,!0),((a=r(s))==null?void 0:a.role)!=="admin"){f("/auth/dashboard");return}}catch{f("/auth/login")}finally{v(p,!1)}}function L(){localStorage.removeItem("token"),v(s,null),f("/auth/login")}var b=A(),S=x(b);{var T=e=>{var a=Z();h(e,a)},D=e=>{var a=aa(),t=n(a),c=_(n(t),4),k=n(c);{var M=g=>{var y=$(),R=n(y,!0);i(y),W(()=>O(R,r(s).username||r(s).email)),h(g,y)};C(k,g=>{r(s)&&g(M)})}var N=_(k,4);i(c),i(t);var w=_(t,2),P=n(w);E(P,()=>o.children),i(w),i(a),K("click",N,L),h(e,a)},F=e=>{var a=A(),t=x(a);E(t,()=>o.children),h(e,a)};C(S,e=>{var a;r(p)?e(T):((a=r(s))==null?void 0:a.role)==="admin"?e(D,1):e(F,-1)})}h(u,b),V(),l()}J(["click"]);export{na as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/1.Dgii_8lh.js b/backend/cmd/server/embed/_app/immutable/nodes/1.Dgii_8lh.js new file mode 100644 index 0000000..a5bb0fa --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/1.Dgii_8lh.js @@ -0,0 +1 @@ +import{a as h,f as g}from"../chunks/CJv7FbHz.js";import{i as l}from"../chunks/DFRBE_Uq.js";import{p as v,a3 as d,a7 as _,a as x,a4 as e,a5 as o,a2 as $}from"../chunks/DtGl34IE.js";import{s as p}from"../chunks/n1byU5WW.js";import{p as m}from"../chunks/CfgL3m1f.js";import{s as k}from"../chunks/RKc8iKz_.js";const b={get error(){return m.error},get status(){return m.status}};k.updated.check;const i=b;var E=g("

",1);function B(f,n){v(n,!1),l();var t=E(),r=d(t),c=e(r,!0);o(r);var a=$(r,2),u=e(a,!0);o(a),_(()=>{var s;p(c,i.status),p(u,(s=i.error)==null?void 0:s.message)}),h(f,t),x()}export{B as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/10.BvOkMiuT.js b/backend/cmd/server/embed/_app/immutable/nodes/10.BvOkMiuT.js new file mode 100644 index 0000000..b154daf --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/10.BvOkMiuT.js @@ -0,0 +1 @@ +import{a as m,f as y}from"../chunks/CJv7FbHz.js";import{p as Z,a0 as _,a1 as I,a8 as aa,s as i,a3 as N,a7 as D,a as ea,a2 as o,a4 as r,a5 as s,g as t,a6 as ta}from"../chunks/DtGl34IE.js";import{s as sa,a as oa}from"../chunks/B3ZK_jYJ.js";import{d as ra,a as w,s as F,e as la}from"../chunks/n1byU5WW.js";import{i as R}from"../chunks/-EcHSJia.js";import{e as ia,i as da}from"../chunks/ecAlPOj8.js";import{s as T,r as U}from"../chunks/e1WBZ7UL.js";import{b as q}from"../chunks/ayyTDfEa.js";import{p as na}from"../chunks/B7kAneMc.js";var va=y("

Loading...

"),ca=y("

No aliases configured yet.

"),ua=y(' '),pa=y('
SourceDestinationActions
'),fa=y(' ',1),ma=y('

Aliases

',1);function Aa(L,O){Z(O,!0);const B=()=>sa(na,"$page",J),[J,M]=oa();let A=_(I([])),S=_(!0),b=_(!1),p=_(I({source:"",destination:""})),l=_("");async function $(a){try{const e=await fetch(`/api/domains/${encodeURIComponent(a)}/aliases`);if(e.ok){const d=await e.json();i(A,d.data||[],!0)}}catch(e){console.error("Failed to load aliases:",e)}finally{i(S,!1)}}async function P(){try{const a=await fetch(`/api/domains/${encodeURIComponent(t(l))}/aliases`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t(p))});if(a.ok)i(b,!1),i(p,{source:"",destination:""},!0),await $(t(l));else{const e=await a.json();alert(e.error||"Failed to create alias")}}catch(a){console.error("Failed to create alias:",a)}}async function G(a){if(confirm("Delete this alias?"))try{await fetch(`/api/domains/${encodeURIComponent(t(l))}/aliases/${a}`,{method:"DELETE"}),await $(t(l))}catch(e){console.error("Failed to delete alias:",e)}}aa(()=>{const a=B().params.name;a&&(i(l,a,!0),$(a))});var j=ma(),C=N(j),z=r(C),H=r(z);s(z);var K=o(z,4);s(C);var E=o(C,2);{var Q=a=>{var e=va();m(a,e)},V=a=>{var e=ca();m(a,e)},W=a=>{var e=pa(),d=o(r(e));ia(d,21,()=>t(A),da,(g,n)=>{var v=ua(),c=r(v),h=r(c,!0);s(c);var f=o(c),k=r(f,!0);s(f);var x=o(f),u=r(x);s(x),s(v),D(()=>{F(h,t(n).source),F(k,t(n).destination)}),w("click",u,()=>G(t(n).id)),m(g,v)}),s(d),s(e),m(a,e)};R(E,a=>{t(S)?a(Q):t(A).length===0?a(V,1):a(W,-1)})}var X=o(E,2);{var Y=a=>{var e=fa(),d=N(e),g=o(d,2),n=o(r(g),2),v=r(n),c=o(r(v));U(c),s(v);var h=o(v,2),f=o(r(h));U(f),s(h);var k=o(h,2),x=r(k);ta(2),s(k),s(n),s(g),D(()=>T(c,"placeholder",`info@${t(l)??""}`)),w("click",d,()=>i(b,!1)),la("submit",n,u=>{u.preventDefault(),P()}),q(c,()=>t(p).source,u=>t(p).source=u),q(f,()=>t(p).destination,u=>t(p).destination=u),w("click",x,()=>i(b,!1)),m(a,e)};R(X,a=>{t(b)&&a(Y)})}D(()=>{T(z,"href",`/domains/${t(l)??""}`),F(H,`← Back to ${t(l)??""}`)}),w("click",K,()=>i(b,!0)),m(L,j),ea(),M()}ra(["click"]);export{Aa as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/11.DnvWFHPj.js b/backend/cmd/server/embed/_app/immutable/nodes/11.DnvWFHPj.js new file mode 100644 index 0000000..7662206 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/11.DnvWFHPj.js @@ -0,0 +1 @@ +import{a as b,f as _}from"../chunks/CJv7FbHz.js";import{p as ot,a0 as w,a1 as M,a8 as rt,s as c,a3 as O,a7 as D,a as lt,a2 as s,a4 as r,a5 as o,g as a,a6 as it}from"../chunks/DtGl34IE.js";import{s as nt,a as dt}from"../chunks/B3ZK_jYJ.js";import{d as ct,a as $,s as q,e as vt}from"../chunks/n1byU5WW.js";import{i as Q}from"../chunks/-EcHSJia.js";import{e as ut,i as pt}from"../chunks/ecAlPOj8.js";import{s as R,r as E}from"../chunks/e1WBZ7UL.js";import{b as N}from"../chunks/ayyTDfEa.js";import{p as mt}from"../chunks/B7kAneMc.js";var ft=_("

Loading...

"),bt=_("

No users configured yet.

"),_t=_(' '),ht=_('
EmailQuotaUsedActions
'),zt=_(' ',1),gt=_('

Users

',1);function Bt(L,P){ot(P,!0);const S=()=>nt(mt,"$page",G),[G,J]=dt();let C=w(M([])),T=w(!0),h=w(!1),i=w(M({email:"",password:"",quota:0})),n=w("");async function F(t){try{const e=await fetch(`/api/domains/${encodeURIComponent(t)}/users`);if(e.ok){const v=await e.json();c(C,v.data||[],!0)}}catch(e){console.error("Failed to load users:",e)}finally{c(T,!1)}}async function K(){try{const t=await fetch(`/api/domains/${encodeURIComponent(a(n))}/users`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a(i))});if(t.ok)c(h,!1),c(i,{email:"",password:"",quota:0},!0),await F(a(n));else{const e=await t.json();alert(e.error||"Failed to create user")}}catch(t){console.error("Failed to create user:",t)}}async function H(t){if(confirm("Delete this user? Mailbox will NOT be deleted."))try{await fetch(`/api/domains/${encodeURIComponent(a(n))}/users/${t}`,{method:"DELETE"}),await F(a(n))}catch(e){console.error("Failed to delete user:",e)}}function j(t){return t===0?"Default":t<1024?t+" B":t<1024*1024?(t/1024).toFixed(1)+" KB":t<1024*1024*1024?(t/1024/1024).toFixed(1)+" MB":(t/1024/1024/1024).toFixed(2)+" GB"}rt(()=>{const t=S().params.name;t&&(c(n,t,!0),F(t))});var A=gt(),B=O(A),y=r(B),V=r(y);o(y);var W=s(y,4);o(B);var I=s(B,2);{var X=t=>{var e=ft();b(t,e)},Y=t=>{var e=bt();b(t,e)},Z=t=>{var e=ht(),v=s(r(e));ut(v,21,()=>a(C),pt,(x,d)=>{var u=_t(),p=r(u),z=r(p,!0);o(p);var m=s(p),g=r(m,!0);o(m);var f=s(m),k=r(f,!0);o(f);var U=s(f),l=r(U);o(U),o(u),D((et,st)=>{q(z,a(d).email),q(g,et),q(k,st)},[()=>j(a(d).quota),()=>j(a(d).used_quota)]),$("click",l,()=>H(a(d).id)),b(x,u)}),o(v),o(e),b(t,e)};Q(I,t=>{a(T)?t(X):a(C).length===0?t(Y,1):t(Z,-1)})}var tt=s(I,2);{var at=t=>{var e=zt(),v=O(e),x=s(v,2),d=s(r(x),2),u=r(d),p=s(r(u));E(p),o(u);var z=s(u,2),m=s(r(z));E(m),o(z);var g=s(z,2),f=s(r(g));E(f),o(g);var k=s(g,2),U=r(k);it(2),o(k),o(d),o(x),D(()=>R(p,"placeholder",`user@${a(n)??""}`)),$("click",v,()=>c(h,!1)),vt("submit",d,l=>{l.preventDefault(),K()}),N(p,()=>a(i).email,l=>a(i).email=l),N(m,()=>a(i).password,l=>a(i).password=l),N(f,()=>a(i).quota,l=>a(i).quota=l),$("click",U,()=>c(h,!1)),b(t,e)};Q(tt,t=>{a(h)&&t(at)})}D(()=>{R(y,"href",`/domains/${a(n)??""}`),q(V,`← Back to ${a(n)??""}`)}),$("click",W,()=>c(h,!0)),b(L,A),lt(),J()}ct(["click"]);export{Bt as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/12.CRx3MqWn.js b/backend/cmd/server/embed/_app/immutable/nodes/12.CRx3MqWn.js new file mode 100644 index 0000000..2164ff6 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/12.CRx3MqWn.js @@ -0,0 +1 @@ +import{a as d,f as m}from"../chunks/CJv7FbHz.js";import{l as Z,c as A,aj as $,t as ee,K as ae,ak as re,al as te,p as se,a0 as g,a1 as oe,a8 as le,a3 as ie,g as s,a as ne,s as c,a2 as v,a4 as f,a5 as u,a7 as U}from"../chunks/DtGl34IE.js";import{d as ve,a as H,s as x}from"../chunks/n1byU5WW.js";import{i as ue}from"../chunks/-EcHSJia.js";import{e as fe,i as pe}from"../chunks/ecAlPOj8.js";import{r as _e}from"../chunks/e1WBZ7UL.js";import{s as ce}from"../chunks/BYrNiJ2z.js";import{b as de}from"../chunks/ayyTDfEa.js";function W(e,t,p=!1){if(e.multiple){if(t==null)return;if(!ae(t))return re();for(var o of e.options)o.selected=t.includes(h(o));return}for(o of e.options){var i=h(o);if(te(i,t)){o.selected=!0;return}}(!p||t!==void 0)&&(e.selectedIndex=-1)}function me(e){var t=new MutationObserver(()=>{W(e,e.__value)});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),ee(()=>{t.disconnect()})}function ge(e,t,p=t){var o=new WeakSet,i=!0;Z(e,"change",n=>{var _=n?"[selected]":":checked",l;if(e.multiple)l=[].map.call(e.querySelectorAll(_),h);else{var b=e.querySelector(_)??e.querySelector("option:not([disabled])");l=b&&h(b)}p(l),e.__value=l,A!==null&&o.add(A)}),$(()=>{var n=t();if(e===document.activeElement){var _=A;if(o.has(_))return}if(W(e,n,i),i&&n===void 0){var l=e.querySelector(":checked");l!==null&&(n=h(l),p(n))}e.__value=n,i=!1}),me(e)}function h(e){return"__value"in e?e.__value:e.value}var he=m("

Loading...

"),be=m('

'),ye=m("

No log entries found.

"),ke=m('
'),we=m('
'),xe=m('

Mail Logs

',1);function Me(e,t){se(t,!0);let p=g(oe([])),o=g(!0),i=g(""),n=g(""),_=g(1);async function l(){c(o,!0),c(i,"");try{const a=await fetch(`/api/logs?hours=${s(_)}&filter=${encodeURIComponent(s(n))}`);if(a.ok){const r=await a.json();c(p,r.data||[],!0)}else c(i,"Failed to load logs")}catch(a){c(i,"Connection error"),console.error("Failed to load logs:",a)}finally{c(o,!1)}}function b(a){const r=a.toLowerCase();return r==="err"||r==="error"?"error":r==="warning"||r==="warn"?"warning":r==="info"?"info":""}le(()=>{l()});var K=xe(),L=ie(K),N=v(f(L),2),q=f(N),y=v(f(q)),F=f(y);F.value=F.__value=1;var S=v(F);S.value=S.__value=6;var C=v(S);C.value=C.__value=24;var O=v(C);O.value=O.__value=48,u(y),u(q);var j=v(q,2),E=v(f(j));_e(E),u(j);var z=v(j,2);u(N),u(L);var B=v(L,2);{var D=a=>{var r=he();d(a,r)},G=a=>{var r=be(),I=f(r,!0);u(r),U(()=>x(I,s(i))),d(a,r)},J=a=>{var r=ye();d(a,r)},Q=a=>{var r=we();fe(r,21,()=>s(p),pe,(I,k)=>{var w=ke(),M=f(w),T=f(M,!0);u(M);var R=v(M,2),V=f(R);u(R);var P=v(R,2),X=f(P,!0);u(P),u(w),U(Y=>{ce(w,1,`log-entry ${Y??""}`,"svelte-1lsf4ps"),x(T,s(k).timestamp),x(V,`[${s(k).priority??""}]`),x(X,s(k).message)},[()=>b(s(k).priority)]),d(I,w)}),u(r),d(a,r)};ue(B,a=>{s(o)?a(D):s(i)?a(G,1):s(p).length===0?a(J,2):a(Q,-1)})}H("change",y,l),ge(y,()=>s(_),a=>c(_,a)),H("keydown",E,a=>a.key==="Enter"&&l()),de(E,()=>s(n),a=>c(n,a)),H("click",z,l),d(e,K),ne()}ve(["change","keydown","click"]);export{Me as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/13.CB7FlS8h.js b/backend/cmd/server/embed/_app/immutable/nodes/13.CB7FlS8h.js new file mode 100644 index 0000000..1c15ab4 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/13.CB7FlS8h.js @@ -0,0 +1 @@ +import{a as i,f as d}from"../chunks/CJv7FbHz.js";import{p as Y,a0 as w,a1 as Z,a8 as $,a3 as ee,a as te,s as u,a2 as o,a4 as s,a5 as r,g as a,a7 as z}from"../chunks/DtGl34IE.js";import{d as ae,a as D,s as l}from"../chunks/n1byU5WW.js";import{i as re}from"../chunks/-EcHSJia.js";import{e as se,i as oe}from"../chunks/ecAlPOj8.js";var ce=d("

Loading...

"),le=d('

'),ie=d("

Queue is empty.

"),ue=d(' '),de=d('
IDSenderRecipientsSizeTimeReasonActions
'),ve=d('

Mail Queue

',1);function pe(B,E){Y(E,!0);let h=w(Z([])),g=w(!0),v=w("");async function n(){u(g,!0),u(v,"");try{const e=await fetch("/api/queue");if(e.ok){const t=await e.json();u(h,t.data||[],!0)}else u(v,"Failed to load queue")}catch(e){u(v,"Connection error"),console.error("Failed to load queue:",e)}finally{u(g,!1)}}async function T(e){try{await fetch(`/api/queue/${e}/requeue`,{method:"POST"}),await n()}catch(t){console.error("Failed to requeue:",t)}}async function j(e){if(confirm("Delete this message from queue?"))try{await fetch(`/api/queue/${e}`,{method:"DELETE"}),await n()}catch(t){console.error("Failed to delete from queue:",t)}}function L(e){return e<1024?e+" B":e<1024*1024?(e/1024).toFixed(1)+" KB":(e/1024/1024).toFixed(1)+" MB"}$(()=>{n()});var Q=ve(),q=ee(Q),M=o(s(q),2);r(q);var y=o(q,2);{var A=e=>{var t=ce();i(e,t)},C=e=>{var t=le(),f=s(t,!0);r(t),z(()=>l(f,a(v))),i(e,t)},I=e=>{var t=ie();i(e,t)},K=e=>{var t=de(),f=o(s(t));se(f,21,()=>a(h),oe,(O,c)=>{var p=ue(),_=s(p),P=s(_,!0);r(_);var m=o(_),G=s(m,!0);r(m);var b=o(m),H=s(b,!0);r(b);var x=o(b),J=s(x,!0);r(x);var F=o(x),N=s(F,!0);r(F);var k=o(F),U=s(k,!0);r(k);var R=o(k),S=s(R),V=o(S,2);r(R),r(p),z((W,X)=>{l(P,a(c).id),l(G,a(c).sender),l(H,W),l(J,X),l(N,a(c).time),l(U,a(c).reason)},[()=>a(c).recipients.join(", "),()=>L(a(c).size)]),D("click",S,()=>T(a(c).id)),D("click",V,()=>j(a(c).id)),i(O,p)}),r(f),r(t),i(e,t)};re(y,e=>{a(g)?e(A):a(v)?e(C,1):a(h).length===0?e(I,2):e(K,-1)})}D("click",M,n),i(B,Q),te()}ae(["click"]);export{pe as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/14.CFDiiGpK.js b/backend/cmd/server/embed/_app/immutable/nodes/14.CFDiiGpK.js new file mode 100644 index 0000000..0b5a50b --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/14.CFDiiGpK.js @@ -0,0 +1 @@ +import{a as r,f as m}from"../chunks/CJv7FbHz.js";import{i as t}from"../chunks/DFRBE_Uq.js";import{o as i}from"../chunks/DR7h53-u.js";import{p as s,a as n}from"../chunks/DtGl34IE.js";import{g as f}from"../chunks/RKc8iKz_.js";var e=m("

Redirecting to domains...

");function l(o,a){s(a,!1),i(()=>{f("/domains")}),t();var p=e();r(o,p),n()}export{l as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/2.BMCUuUxB.js b/backend/cmd/server/embed/_app/immutable/nodes/2.BMCUuUxB.js new file mode 100644 index 0000000..e8be904 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/2.BMCUuUxB.js @@ -0,0 +1 @@ +import{a as p,f as n}from"../chunks/CJv7FbHz.js";import{o as L}from"../chunks/DR7h53-u.js";import{p as M,a0 as b,a1 as Q,a2 as o,a3 as B,a as C,s as q,g as l,a4 as s,a5 as t,a6 as i,a7 as G}from"../chunks/DtGl34IE.js";import{s as v}from"../chunks/n1byU5WW.js";import{i as H}from"../chunks/-EcHSJia.js";import{s as I}from"../chunks/BYrNiJ2z.js";var J=n("

Loading...

"),K=n('

Domains

Users

Aliases

Queued Emails

'),N=n("

Dashboard

",1);function X(w,z){M(z,!0);let r=b(Q({totalDomains:0,totalUsers:0,totalAliases:0,queueSize:0})),g=b(!0);L(async()=>{try{const a=await fetch("/api/stats");if(a.ok){const e=await a.json();q(r,e.data,!0)}}catch(a){console.error("Failed to fetch stats:",a)}finally{q(g,!1)}});var m=N(),A=o(B(m),2);{var S=a=>{var e=J();p(a,e)},U=a=>{var e=K(),h=s(e),f=s(h),j=s(f,!0);t(f),i(2),t(h);var c=o(h,2),_=s(c),k=s(_,!0);t(_),i(2),t(c);var u=o(c,2),x=s(u),E=s(x,!0);t(x),i(2),t(u);var d=o(u,2);let y;var D=s(d),F=s(D,!0);t(D),i(2),t(d),t(e),G(()=>{v(j,l(r).totalDomains),v(k,l(r).totalUsers),v(E,l(r).totalAliases),y=I(d,1,"stat-card svelte-1uha8ag",null,y,{warning:l(r).queueSize>10}),v(F,l(r).queueSize)}),p(a,e)};H(A,a=>{l(g)?a(S):a(U,-1)})}p(w,m),C()}export{X as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/3.CFDiiGpK.js b/backend/cmd/server/embed/_app/immutable/nodes/3.CFDiiGpK.js new file mode 100644 index 0000000..0b5a50b --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/3.CFDiiGpK.js @@ -0,0 +1 @@ +import{a as r,f as m}from"../chunks/CJv7FbHz.js";import{i as t}from"../chunks/DFRBE_Uq.js";import{o as i}from"../chunks/DR7h53-u.js";import{p as s,a as n}from"../chunks/DtGl34IE.js";import{g as f}from"../chunks/RKc8iKz_.js";var e=m("

Redirecting to domains...

");function l(o,a){s(a,!1),i(()=>{f("/domains")}),t();var p=e();r(o,p),n()}export{l as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/4.YDL696B2.js b/backend/cmd/server/embed/_app/immutable/nodes/4.YDL696B2.js new file mode 100644 index 0000000..16b5869 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/4.YDL696B2.js @@ -0,0 +1 @@ +import{a as p,f as g}from"../chunks/CJv7FbHz.js";import{o as W}from"../chunks/DR7h53-u.js";import{p as X,a7 as q,g as t,a as Y,a2 as i,a4 as o,a0 as v,a5 as r,a6 as Z,s}from"../chunks/DtGl34IE.js";import{d as aa,a as ea,e as ta,s as B}from"../chunks/n1byU5WW.js";import{i as I}from"../chunks/-EcHSJia.js";import{r as L}from"../chunks/e1WBZ7UL.js";import{b as N}from"../chunks/ayyTDfEa.js";import{g as f}from"../chunks/RKc8iKz_.js";var sa=g("Logged in as "),oa=g('
'),ra=g('
Password changed successfully!
'),ia=g('

Change Password

');function pa(F,J){X(J,!0);let c=null,u=v(""),h=v(""),m=v(""),l=v(""),z=v(!1),n=v(!1);W(async()=>{const a=localStorage.getItem("token");if(!a){await f("/auth/login");return}try{const e=await fetch("/api/auth/me",{headers:{Authorization:`Bearer ${a}`}});if(!e.ok){await f("/auth/login");return}c=(await e.json()).data}catch{await f("/auth/login")}});async function M(a){if(a.preventDefault(),s(l,""),t(h)!==t(m)){s(l,"Passwords do not match");return}if(t(h).length<8){s(l,"Password must be at least 8 characters");return}s(n,!0);try{const e=await fetch("/api/auth/change-password",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${localStorage.getItem("token")}`},body:JSON.stringify({oldPassword:t(u),newPassword:t(h)})}),d=await e.json();if(!e.ok){s(l,d.error||"Failed to change password",!0);return}s(z,!0),s(u,""),s(h,""),s(m,"")}catch{s(l,"Connection error")}finally{s(n,!1)}}function G(){localStorage.removeItem("token"),f("/auth/login")}var w=ia(),b=o(w),A=o(b),D=i(o(A),2),E=o(D);{var H=a=>{var e=sa(),d=i(o(e)),V=o(d,!0);r(d),r(e),q(()=>B(V,c.email||c.username)),p(a,e)};I(E,a=>{c&&a(H)})}var K=i(E,2);r(D),r(A),r(b);var O=i(b,2),T=o(O);{var Q=a=>{var e=oa(),d=o(e,!0);r(e),q(()=>B(d,t(l))),p(a,e)};I(T,a=>{t(l)&&a(Q)})}var $=i(T,2);{var R=a=>{var e=ra();p(a,e)};I($,a=>{t(z)&&a(R)})}var _=i($,2),P=o(_),y=i(o(P));L(y),r(P);var k=i(P,2),C=i(o(k));L(C),r(k);var x=i(k,2),S=i(o(x));L(S),r(x);var j=i(x,2),U=o(j,!0);r(j),r(_),Z(2),r(O),r(w),q(()=>{y.disabled=t(n),C.disabled=t(n),S.disabled=t(n),j.disabled=t(n),B(U,t(n)?"Changing...":"Change Password")}),ea("click",K,G),ta("submit",_,M),N(y,()=>t(u),a=>s(u,a)),N(C,()=>t(h),a=>s(h,a)),N(S,()=>t(m),a=>s(m,a)),p(F,w),Y()}aa(["click"]);export{pa as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/5.DHfYhdex.js b/backend/cmd/server/embed/_app/immutable/nodes/5.DHfYhdex.js new file mode 100644 index 0000000..84e60ea --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/5.DHfYhdex.js @@ -0,0 +1 @@ +import{a as n,f as c}from"../chunks/CJv7FbHz.js";import{o as H}from"../chunks/DR7h53-u.js";import{p as J,a as K,a2 as r,a4 as a,s as O,a5 as s,g as T,a0 as V,a7 as g,a3 as W,a6 as X}from"../chunks/DtGl34IE.js";import{d as Y,a as Z,s as i}from"../chunks/n1byU5WW.js";import{i as h}from"../chunks/-EcHSJia.js";import{g as d}from"../chunks/RKc8iKz_.js";var $=c("Logged in as "),aa=c("

Loading...

"),sa=c('
Quota:
'),ta=c('

Account Information

Email:
Username:
Role:

Quick Actions

',1),ea=c('

User Dashboard

');function da(U,B){J(B,!0);let t=null,_=V(!0);H(async()=>{const e=localStorage.getItem("token");if(!e){await d("/auth/login");return}try{const o=await fetch("/api/auth/me",{headers:{Authorization:`Bearer ${e}`}});if(!o.ok){await d("/auth/login");return}if(t=(await o.json()).data,(t==null?void 0:t.role)==="admin"){await d("/");return}}catch{await d("/auth/login")}finally{O(_,!1)}});function M(){localStorage.removeItem("token"),d("/auth/login")}var m=ea(),p=a(m),w=r(a(p),2),b=a(w);{var N=e=>{var o=$(),l=r(a(o)),v=a(l,!0);s(l),s(o),g(()=>i(v,t.email||t.username)),n(e,o)};h(b,e=>{t&&e(N)})}var Q=r(b,2);s(w),s(p);var A=r(p,2),S=a(A);{var j=e=>{var o=aa();n(e,o)},z=e=>{var o=ta(),l=W(o),v=r(a(l),2),L=r(a(v),2),C=a(L,!0);s(L),s(v);var u=r(v,2),q=r(a(u),2),D=a(q,!0);s(q),s(u);var f=r(u,2),y=r(a(f),2),E=a(y,!0);s(y),s(f);var F=r(f,2);{var P=x=>{var k=sa(),I=r(a(k),2),R=a(I,!0);s(I),s(k),g(G=>i(R,G),[()=>t.quota>0?(t.quota/1024/1024).toFixed(0)+" MB":"Unlimited"]),n(x,k)};h(F,x=>{t.quota!==void 0&&x(P)})}s(l),X(2),g(()=>{i(C,t.email||"N/A"),i(D,t.username||"N/A"),i(E,t.role)}),n(e,o)};h(S,e=>{T(_)?e(j):t&&e(z,1)})}s(A),s(m),Z("click",Q,M),n(U,m),K()}Y(["click"]);export{da as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/6.BiQ3_GJa.js b/backend/cmd/server/embed/_app/immutable/nodes/6.BiQ3_GJa.js new file mode 100644 index 0000000..b512f8a --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/6.BiQ3_GJa.js @@ -0,0 +1 @@ +import{a as v,f}from"../chunks/CJv7FbHz.js";import{a2 as c,a4 as i,g as s,a5 as o,a0 as d,a7 as y,a6 as k,a3 as E,s as r}from"../chunks/DtGl34IE.js";import{s as x,e as O}from"../chunks/n1byU5WW.js";import{i as w}from"../chunks/-EcHSJia.js";import{r as T}from"../chunks/e1WBZ7UL.js";import{b as D}from"../chunks/ayyTDfEa.js";import"../chunks/CfgL3m1f.js";var I=f('
'),J=f('

If an account exists with that email or username, a password reset link has been sent.

Please check your inbox.

',1),N=f(`

Enter your email address or username and we'll send you a link to reset your password.

`,1),U=f('');function V(S){let u=d(""),l=d(""),b=d(!1),n=d(!1);async function L(e){e.preventDefault(),r(l,""),r(n,!0);try{const a=await fetch("/api/auth/forgot",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({identifier:s(u)})}),t=await a.json();if(!a.ok){r(l,t.error||"Request failed",!0);return}r(b,!0)}catch{r(l,"Connection error")}finally{r(n,!1)}}var m=U(),g=i(m),_=c(i(g),2);{var P=e=>{var a=I(),t=i(a,!0);o(a),y(()=>x(t,s(l))),v(e,a)};w(_,e=>{s(l)&&e(P)})}var R=c(_,2);{var j=e=>{var a=J();k(2),v(e,a)},q=e=>{var a=N(),t=c(E(a),2),p=i(t),z=c(i(p));T(z),o(p);var h=c(p,2),B=i(h,!0);o(h),o(t),k(2),y(()=>{z.disabled=s(n),h.disabled=s(n),x(B,s(n)?"Sending...":"Send Reset Link")}),O("submit",t,L),D(z,()=>s(u),C=>r(u,C)),v(e,a)};w(R,e=>{s(b)?e(j):e(q,-1)})}o(g),o(m),v(S,m)}export{V as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/7.BEIquz8f.js b/backend/cmd/server/embed/_app/immutable/nodes/7.BEIquz8f.js new file mode 100644 index 0000000..8e5713c --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/7.BEIquz8f.js @@ -0,0 +1 @@ +import{a as y,f as j}from"../chunks/CJv7FbHz.js";import{p as A,a7 as S,g as t,a as D,a2 as i,a4 as s,s as r,a0 as p,a5 as o}from"../chunks/DtGl34IE.js";import{e as F,s as x}from"../chunks/n1byU5WW.js";import{i as J}from"../chunks/-EcHSJia.js";import{r as k}from"../chunks/e1WBZ7UL.js";import{b as C}from"../chunks/ayyTDfEa.js";import{g as I}from"../chunks/RKc8iKz_.js";var L=j('
'),N=j('');function Q(q,E){A(E,!0);let m=p(""),d=p(""),l=p(""),n=p(!1);async function M(){r(n,!0),r(l,"");try{const e=await fetch("/api/auth/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:t(m),password:t(d)})}),a=await e.json();if(!e.ok){r(l,a.error||"Login failed",!0);return}localStorage.setItem("token",a.data.token),a.data.user.role==="admin"?I("/"):I("/auth/dashboard")}catch{r(l,"Connection error")}finally{r(n,!1)}}var v=N(),g=s(v),h=i(s(g),4);{var O=e=>{var a=L(),T=s(a,!0);o(a),S(()=>x(T,t(l))),y(e,a)};J(h,e=>{t(l)&&e(O)})}var u=i(h,2),c=s(u),_=i(s(c));k(_),o(c);var f=i(c,2),w=i(s(f));k(w),o(f);var b=i(f,4),P=s(b,!0);o(b),o(u),o(g),o(v),S(()=>{b.disabled=t(n),x(P,t(n)?"Signing in...":"Sign In")}),F("submit",u,e=>{e.preventDefault(),M()}),C(_,()=>t(m),e=>r(m,e)),C(w,()=>t(d),e=>r(d,e)),y(q,v),D()}export{Q as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/8.D4QctIPu.js b/backend/cmd/server/embed/_app/immutable/nodes/8.D4QctIPu.js new file mode 100644 index 0000000..19836cd --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/8.D4QctIPu.js @@ -0,0 +1 @@ +import{a as m,f}from"../chunks/CJv7FbHz.js";import{p as K,a0 as w,a1 as j,a8 as Q,a3 as R,a as V,s as c,a2 as r,a4 as s,a5 as e,g as o,a6 as W,a7 as X}from"../chunks/DtGl34IE.js";import{d as Y,a as h,e as Z,s as C}from"../chunks/n1byU5WW.js";import{i as L}from"../chunks/-EcHSJia.js";import{e as $,i as aa}from"../chunks/ecAlPOj8.js";import{r as ta,s as ea}from"../chunks/e1WBZ7UL.js";import{b as sa}from"../chunks/ayyTDfEa.js";var oa=f("

Loading...

"),ra=f("

No domains configured yet.

"),la=f(' '),ia=f('
DomainUsersAliasesActions
'),ca=f(''),na=f('

Domains

',1);function ha(N,O){K(O,!0);let _=w(j([])),A=w(!0),p=w(!1),b=w(j({name:""}));async function g(){try{const a=await fetch("/api/domains");if(a.ok){const t=await a.json();c(_,t.data||[],!0)}}catch(a){console.error("Failed to load domains:",a)}finally{c(A,!1)}}async function P(){try{(await fetch("/api/domains",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o(b))})).ok&&(c(p,!1),c(b,{name:""},!0),await g())}catch(a){console.error("Failed to create domain:",a)}}async function S(a){if(confirm("Delete this domain? Users and aliases will be deleted."))try{await fetch(`/api/domains/${a}`,{method:"DELETE"}),await g()}catch(t){console.error("Failed to delete domain:",t)}}Q(()=>{g()});var E=na(),D=R(E),U=r(s(D),2);e(D);var F=r(D,2);{var q=a=>{var t=oa();m(a,t)},J=a=>{var t=ra();m(a,t)},M=a=>{var t=ia(),n=r(s(t));$(n,21,()=>o(_),aa,(u,l)=>{var d=la(),v=s(d),y=s(v),i=s(y,!0);e(y),e(v);var k=r(v),G=s(k,!0);e(k);var x=r(k),H=s(x,!0);e(x);var T=r(x),I=s(T);e(T),e(d),X(()=>{ea(y,"href",`/domains/${o(l).name??""}/users`),C(i,o(l).name),C(G,o(l).userCount),C(H,o(l).aliasCount)}),h("click",I,()=>S(o(l).id)),m(u,d)}),e(n),e(t),m(a,t)};L(F,a=>{o(A)?a(q):o(_).length===0?a(J,1):a(M,-1)})}var z=r(F,2);{var B=a=>{var t=ca(),n=s(t),u=r(s(n),2),l=s(u),d=r(s(l));ta(d),e(l);var v=r(l,2),y=s(v);W(2),e(v),e(u),e(n),e(t),h("click",t,()=>c(p,!1)),h("click",n,i=>i.stopPropagation()),Z("submit",u,i=>{i.preventDefault(),P()}),sa(d,()=>o(b).name,i=>o(b).name=i),h("click",y,()=>c(p,!1)),m(a,t)};L(z,a=>{o(p)&&a(B)})}h("click",U,()=>c(p,!0)),m(N,E),V()}Y(["click"]);export{ha as component}; diff --git a/backend/cmd/server/embed/_app/immutable/nodes/9.DflEy3LG.js b/backend/cmd/server/embed/_app/immutable/nodes/9.DflEy3LG.js new file mode 100644 index 0000000..2ac9188 --- /dev/null +++ b/backend/cmd/server/embed/_app/immutable/nodes/9.DflEy3LG.js @@ -0,0 +1 @@ +import{c as J,a as i,f as c}from"../chunks/CJv7FbHz.js";import{p as K,a8 as M,a3 as D,a as N,s as m,a0 as d,g as e,a4 as t,a5 as r,a7 as y,a2 as _,a6 as C}from"../chunks/DtGl34IE.js";import{s as O,a as P}from"../chunks/B3ZK_jYJ.js";import{s as p}from"../chunks/n1byU5WW.js";import{i as Q}from"../chunks/-EcHSJia.js";import{s as $}from"../chunks/e1WBZ7UL.js";import{p as S}from"../chunks/B7kAneMc.js";var T=c("

Loading...

"),V=c('

'),W=c(' ',1),X=c("

Domain not found

");function oa(w,U){K(U,!0);const j=()=>O(S,"$page",A),[A,B]=P();let o=d(null),u=d(!0),n=d("");async function F(a){try{const s=await fetch(`/api/domains/${encodeURIComponent(a)}`);if(s.ok){const l=await s.json();m(o,l.data,!0)}else m(n,"Domain not found")}catch{m(n,"Failed to load domain")}finally{m(u,!1)}}M(()=>{const a=j().params.name;a&&F(a)});var h=J(),I=D(h);{var L=a=>{var s=T();i(a,s)},R=a=>{var s=V(),l=t(s,!0);r(s),y(()=>p(l,e(n))),i(a,s)},q=a=>{var s=W(),l=D(s),x=_(t(l),2),E=t(x,!0);r(x),r(l);var b=_(l,2),v=t(b),g=t(v),G=t(g,!0);r(g),C(2),r(v);var f=_(v,2),k=t(f),H=t(k,!0);r(k),C(2),r(f),r(b),y(()=>{p(E,e(o).name),$(v,"href",`/domains/${e(o).name??""}/users`),p(G,e(o).userCount),$(f,"href",`/domains/${e(o).name??""}/aliases`),p(H,e(o).aliasCount)}),i(a,s)},z=a=>{var s=X();i(a,s)};Q(I,a=>{e(u)?a(L):e(n)?a(R,1):e(o)?a(q,2):a(z,-1)})}i(w,h),N(),B()}export{oa as component}; diff --git a/backend/cmd/server/embed/_app/version.json b/backend/cmd/server/embed/_app/version.json new file mode 100644 index 0000000..1afd2af --- /dev/null +++ b/backend/cmd/server/embed/_app/version.json @@ -0,0 +1 @@ +{"version":"1774129207705"} \ No newline at end of file diff --git a/backend/cmd/server/embed/favicon.png b/backend/cmd/server/embed/favicon.png new file mode 100644 index 0000000..47ce666 --- /dev/null +++ b/backend/cmd/server/embed/favicon.png @@ -0,0 +1,4 @@ + + + V + diff --git a/backend/cmd/server/embed/index.html b/backend/cmd/server/embed/index.html new file mode 100644 index 0000000..be50b17 --- /dev/null +++ b/backend/cmd/server/embed/index.html @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + +
+ +
+ + diff --git a/backend/cmd/server/frontend.go b/backend/cmd/server/frontend.go new file mode 100644 index 0000000..75f5c52 --- /dev/null +++ b/backend/cmd/server/frontend.go @@ -0,0 +1,19 @@ +package main + +import ( + "embed" + "io/fs" + "net/http" +) + +//go:embed all:embed +//go:embed all:embed/_app +var Files embed.FS + +func FrontendFileSystem() http.FileSystem { + return http.FS(Files) +} + +func FrontendFS() fs.FS { + return Files +} diff --git a/backend/cmd/server/main.go b/backend/cmd/server/main.go new file mode 100644 index 0000000..51602da --- /dev/null +++ b/backend/cmd/server/main.go @@ -0,0 +1,180 @@ +package main + +import ( + "log" + "net/http" + "os" + "strings" + + "github.com/imc-vibe/backend/internal/api" + "github.com/imc-vibe/backend/internal/auth" + "github.com/imc-vibe/backend/internal/config" + "github.com/imc-vibe/backend/internal/db" +) + +func main() { + cfg := config.Load() + + database, err := db.Connect(cfg) + if err != nil { + log.Fatalf("Failed to connect to database: %v", err) + } + + if err := database.InitSchema(); err != nil { + log.Printf("Warning: Could not initialize schema: %v", err) + } + + if cfg.AdminUser != "" && cfg.AdminPassword != "" { + hash, err := auth.HashPassword(cfg.AdminPassword) + if err != nil { + log.Printf("Warning: Failed to hash admin password: %v", err) + } else { + if err := database.EnsureAdminUser(cfg.AdminUser, hash); err != nil { + log.Printf("Warning: Failed to create admin user: %v", err) + } else { + log.Printf("Admin user '%s' created or already exists", cfg.AdminUser) + } + } + } + + useEmbedded := os.Getenv("USE_EMBEDDED") != "false" + port := cfg.Port + + frontendFS := FrontendFileSystem() + + router := http.NewServeMux() + + router.HandleFunc("/api/health", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.Write([]byte(`{"status":"ok"}`)) + }) + + apiRouter := api.New(database, cfg) + router.Handle("/api/", apiRouter.Handler()) + + if useEmbedded { + router.HandleFunc("/favicon.png", serveStaticFile(frontendFS, "embed/favicon.png")) + router.Handle("/_app/", http.StripPrefix("/_app/", serveStaticPrefixed(frontendFS, "embed/_app/"))) + router.HandleFunc("/", serveSPA(frontendFS)) + log.Println("Using embedded frontend") + } else { + router.Handle("/", http.FileServer(http.Dir("../frontend/build"))) + log.Println("Using filesystem frontend") + } + + log.Printf("Server starting on http://localhost:%s", port) + log.Fatal(http.ListenAndServe(":"+port, router)) +} + +func serveStaticPrefixed(fsys http.FileSystem, prefix string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + path := prefix + r.URL.Path + log.Printf("Static file requested: /_app/%s -> %s", r.URL.Path, path) + + file, err := fsys.Open(path) + if err != nil { + log.Printf("Error opening file %s: %v", path, err) + http.NotFound(w, r) + return + } + defer file.Close() + + fi, err := file.Stat() + if err != nil { + http.NotFound(w, r) + return + } + + if fi.IsDir() { + http.NotFound(w, r) + return + } + + contentType := mimeType(path) + w.Header().Set("Content-Type", contentType) + http.ServeContent(w, r, fi.Name(), fi.ModTime(), file) + } +} + +func serveStaticFile(fsys http.FileSystem, filename string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + log.Printf("Static file requested: /%s", filename) + + file, err := fsys.Open(filename) + if err != nil { + log.Printf("Error opening file %s: %v", filename, err) + http.NotFound(w, r) + return + } + defer file.Close() + + fi, err := file.Stat() + if err != nil { + http.NotFound(w, r) + return + } + + contentType := mimeType(filename) + w.Header().Set("Content-Type", contentType) + http.ServeContent(w, r, fi.Name(), fi.ModTime(), file) + } +} + +func serveSPA(fsys http.FileSystem) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + path := r.URL.Path + + if strings.HasPrefix(path, "/api/") { + http.NotFound(w, r) + return + } + + if path == "/" || path == "" { + path = "embed/index.html" + } else { + path = "embed/index.html" + } + + file, err := fsys.Open(path) + if err != nil { + log.Printf("Error opening %s: %v", path, err) + http.Error(w, "Not found", http.StatusNotFound) + return + } + defer file.Close() + fi, _ := file.Stat() + w.Header().Set("Content-Type", "text/html; charset=utf-8") + http.ServeContent(w, r, fi.Name(), fi.ModTime(), file) + } +} + +func mimeType(path string) string { + switch { + case strings.HasSuffix(path, ".html"): + return "text/html; charset=utf-8" + case strings.HasSuffix(path, ".css"): + return "text/css" + case strings.HasSuffix(path, ".js"): + return "application/javascript" + case strings.HasSuffix(path, ".json"): + return "application/json" + case strings.HasSuffix(path, ".png"): + return "image/png" + case strings.HasSuffix(path, ".jpg") || strings.HasSuffix(path, ".jpeg"): + return "image/jpeg" + case strings.HasSuffix(path, ".svg"): + return "image/svg+xml" + case strings.HasSuffix(path, ".ico"): + return "image/x-icon" + case strings.HasSuffix(path, ".woff"): + return "font/woff" + case strings.HasSuffix(path, ".woff2"): + return "font/woff2" + case strings.HasSuffix(path, ".ttf"): + return "font/ttf" + case strings.HasSuffix(path, ".eot"): + return "application/vnd.ms-fontobject" + default: + return "text/plain" + } +} diff --git a/backend/go.mod b/backend/go.mod new file mode 100644 index 0000000..2be6bef --- /dev/null +++ b/backend/go.mod @@ -0,0 +1,19 @@ +module github.com/imc-vibe/backend + +go 1.25.0 + +require ( + github.com/golang-jwt/jwt/v5 v5.3.1 + github.com/joho/godotenv v1.5.1 + golang.org/x/crypto v0.49.0 + gorm.io/driver/mysql v1.6.0 + gorm.io/gorm v1.31.1 +) + +require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/go-sql-driver/mysql v1.9.3 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + golang.org/x/text v0.35.0 // indirect +) diff --git a/backend/go.sum b/backend/go.sum new file mode 100644 index 0000000..87f32ff --- /dev/null +++ b/backend/go.sum @@ -0,0 +1,20 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= +github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= +github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= +github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= +gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg= +gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo= +gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg= +gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= diff --git a/backend/internal/api/handlers/aliases.go b/backend/internal/api/handlers/aliases.go new file mode 100644 index 0000000..bb60f3e --- /dev/null +++ b/backend/internal/api/handlers/aliases.go @@ -0,0 +1,160 @@ +package handlers + +import ( + "encoding/json" + "net/http" + "strconv" + "strings" + + "github.com/imc-vibe/backend/internal/db" +) + +type AliasHandler struct { + db *db.DB +} + +func NewAliasHandler(database *db.DB) *AliasHandler { + return &AliasHandler{db: database} +} + +type CreateAliasRequest struct { + Source string `json:"source"` + Destination string `json:"destination"` +} + +func (h *AliasHandler) List(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + domainName := extractDomainNameFromPath(r.URL.Path) + if domainName == "" { + Error(w, http.StatusBadRequest, "domain name required") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil { + Error(w, http.StatusUnauthorized, "authentication required") + return + } + + canAccess, _ := h.db.CanAccessDomain(authCtx.UserID, domainName, authCtx.IsAdmin()) + if !canAccess { + Error(w, http.StatusForbidden, "access denied") + return + } + + domain, err := h.db.GetDomainByName(domainName) + if err != nil { + Error(w, http.StatusNotFound, "domain not found") + return + } + + aliases, err := h.db.GetAliasesByDomain(domain.ID) + if err != nil { + Error(w, http.StatusInternalServerError, "database error") + return + } + + Success(w, aliases) +} + +func (h *AliasHandler) Create(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + domainName := extractDomainNameFromPath(r.URL.Path) + if domainName == "" { + Error(w, http.StatusBadRequest, "domain name required") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil { + Error(w, http.StatusUnauthorized, "authentication required") + return + } + + canAccess, _ := h.db.CanAccessDomain(authCtx.UserID, domainName, authCtx.IsAdmin()) + if !canAccess { + Error(w, http.StatusForbidden, "access denied") + return + } + + domain, err := h.db.GetDomainByName(domainName) + if err != nil { + Error(w, http.StatusNotFound, "domain not found") + return + } + + var req CreateAliasRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + Error(w, http.StatusBadRequest, "invalid request body") + return + } + + if req.Source == "" || req.Destination == "" { + Error(w, http.StatusBadRequest, "source and destination required") + return + } + + alias, err := h.db.CreateAliasInDomain(req.Source, req.Destination, domain.ID) + if err != nil { + Error(w, http.StatusInternalServerError, "failed to create alias") + return + } + + Created(w, alias) +} + +func (h *AliasHandler) Delete(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodDelete { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + pathParts := strings.Split(r.URL.Path, "/") + var domainName, idStr string + for i, part := range pathParts { + if part == "domains" && i+1 < len(pathParts) { + domainName = pathParts[i+1] + } + if part == "aliases" && i+1 < len(pathParts) { + idStr = pathParts[i+1] + } + } + + if domainName == "" || idStr == "" { + Error(w, http.StatusBadRequest, "invalid path") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil { + Error(w, http.StatusUnauthorized, "authentication required") + return + } + + canAccess, _ := h.db.CanAccessDomain(authCtx.UserID, domainName, authCtx.IsAdmin()) + if !canAccess { + Error(w, http.StatusForbidden, "access denied") + return + } + + id, err := strconv.ParseUint(idStr, 10, 64) + if err != nil { + Error(w, http.StatusBadRequest, "invalid alias id") + return + } + + if err := h.db.DeleteAlias(uint(id)); err != nil { + Error(w, http.StatusInternalServerError, "failed to delete alias") + return + } + + NoContent(w) +} diff --git a/backend/internal/api/handlers/auth.go b/backend/internal/api/handlers/auth.go new file mode 100644 index 0000000..a4881dd --- /dev/null +++ b/backend/internal/api/handlers/auth.go @@ -0,0 +1,269 @@ +package handlers + +import ( + "encoding/json" + "net/http" + "strings" + "time" + + "github.com/imc-vibe/backend/internal/auth" + "github.com/imc-vibe/backend/internal/db" +) + +const MaxLoginAttempts = 5 + +type AuthHandler struct { + db *db.DB + jwtManager *auth.JWTManager +} + +func NewAuthHandler(database *db.DB, jwtManager *auth.JWTManager) *AuthHandler { + return &AuthHandler{ + db: database, + jwtManager: jwtManager, + } +} + +type LoginRequest struct { + Username string `json:"username"` + Password string `json:"password"` +} + +type ChangePasswordRequest struct { + OldPassword string `json:"oldPassword"` + NewPassword string `json:"newPassword"` +} + +type ForgotPasswordRequest struct { + Identifier string `json:"identifier"` +} + +type UserResponse struct { + ID uint `json:"id"` + Username string `json:"username"` + Role string `json:"role"` + Domains []string `json:"domains"` +} + +func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + var req LoginRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + Error(w, http.StatusBadRequest, "invalid request body") + return + } + + if req.Username == "" || req.Password == "" { + Error(w, http.StatusBadRequest, "username and password required") + return + } + + ip := getClientIP(r) + + if isLockedOut(ip, req.Username, h.db) { + Error(w, http.StatusTooManyRequests, "too many failed attempts, try again later") + return + } + + user, err := h.db.GetImcUserByUsername(req.Username) + if err != nil || user == nil || !auth.CheckPassword(req.Password, user.PasswordHash) { + recordFailedAttempt(req.Username, ip, h.db) + Error(w, http.StatusUnauthorized, "invalid credentials") + return + } + + clearFailedAttempts(req.Username, ip, h.db) + + domains, _ := h.db.GetUserAccessibleDomains(user.ID, user.Role == "admin") + + domainNames := make([]string, len(domains)) + for i, d := range domains { + domainNames[i] = d.Name + } + + token, err := h.jwtManager.GenerateToken(user.ID, user.Username, user.Role, 24*time.Hour) + if err != nil { + Error(w, http.StatusInternalServerError, "failed to generate token") + return + } + + Success(w, map[string]interface{}{ + "token": token, + "user": UserResponse{ + ID: user.ID, + Username: user.Username, + Role: user.Role, + Domains: domainNames, + }, + }) +} + +func (h *AuthHandler) Me(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil { + Error(w, http.StatusUnauthorized, "not authenticated") + return + } + + user, err := h.db.GetImcUserByID(authCtx.UserID) + if err != nil || user == nil { + Error(w, http.StatusNotFound, "user not found") + return + } + + domains, _ := h.db.GetUserAccessibleDomains(user.ID, user.Role == "admin") + + domainNames := make([]string, len(domains)) + for i, d := range domains { + domainNames[i] = d.Name + } + + Success(w, UserResponse{ + ID: user.ID, + Username: user.Username, + Role: user.Role, + Domains: domainNames, + }) +} + +func (h *AuthHandler) ForgotPassword(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + var req ForgotPasswordRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + Error(w, http.StatusBadRequest, "invalid request") + return + } + + req.Identifier = strings.TrimSpace(strings.ToLower(req.Identifier)) + if req.Identifier == "" { + Error(w, http.StatusBadRequest, "identifier required") + return + } + + _, err := h.db.GetImcUserByUsername(req.Identifier) + if err == nil { + Success(w, map[string]string{ + "message": "If the account exists, a password reset link will be sent", + }) + return + } + + Success(w, map[string]string{ + "message": "If the account exists, a password reset link will be sent", + }) +} + +func (h *AuthHandler) ChangePassword(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil { + Error(w, http.StatusUnauthorized, "authentication required") + return + } + + var req ChangePasswordRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + Error(w, http.StatusBadRequest, "invalid request") + return + } + + if req.OldPassword == "" || req.NewPassword == "" { + Error(w, http.StatusBadRequest, "old and new password required") + return + } + + if len(req.NewPassword) < 8 { + Error(w, http.StatusBadRequest, "password must be at least 8 characters") + return + } + + user, err := h.db.GetImcUserByID(authCtx.UserID) + if err != nil || user == nil { + Error(w, http.StatusNotFound, "user not found") + return + } + + if !auth.CheckPassword(req.OldPassword, user.PasswordHash) { + Error(w, http.StatusUnauthorized, "current password is incorrect") + return + } + + newHash, err := auth.HashPassword(req.NewPassword) + if err != nil { + Error(w, http.StatusInternalServerError, "failed to hash password") + return + } + + err = h.db.UpdateImcUserPassword(user.ID, newHash) + if err != nil { + Error(w, http.StatusInternalServerError, "failed to update password") + return + } + + Success(w, map[string]string{"message": "password updated successfully"}) +} + +func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { + Success(w, map[string]string{"message": "logged out"}) +} + +func isLockedOut(ip, identifier string, database *db.DB) bool { + var count int64 + cutoff := time.Now().Add(-15 * time.Minute) + + database.Model(&db.ImcLoginAttempt{}). + Where("ip_address = ? AND attempted_at > ? AND successful = false", ip, cutoff). + Count(&count) + + if count >= MaxLoginAttempts { + return true + } + + database.Model(&db.ImcLoginAttempt{}). + Where("email = ? AND attempted_at > ? AND successful = false", identifier, cutoff). + Count(&count) + + return count >= MaxLoginAttempts +} + +func recordFailedAttempt(identifier, ip string, database *db.DB) { + database.Create(&db.ImcLoginAttempt{ + Email: identifier, + IPAddress: ip, + Successful: false, + }) +} + +func clearFailedAttempts(identifier, ip string, database *db.DB) { + database.Model(&db.ImcLoginAttempt{}). + Where("email = ? OR ip_address = ?", identifier, ip). + Update("successful", true) +} + +func getClientIP(r *http.Request) string { + forwarded := r.Header.Get("X-Forwarded-For") + if forwarded != "" { + return strings.Split(forwarded, ",")[0] + } + if idx := strings.LastIndex(r.RemoteAddr, ":"); idx != -1 { + return r.RemoteAddr[:idx] + } + return r.RemoteAddr +} diff --git a/backend/internal/api/handlers/domains.go b/backend/internal/api/handlers/domains.go new file mode 100644 index 0000000..804982f --- /dev/null +++ b/backend/internal/api/handlers/domains.go @@ -0,0 +1,316 @@ +package handlers + +import ( + "encoding/json" + "net/http" + "strings" + + "github.com/imc-vibe/backend/internal/db" +) + +type DomainHandler struct { + db *db.DB +} + +func NewDomainHandler(database *db.DB) *DomainHandler { + return &DomainHandler{db: database} +} + +type CreateDomainRequest struct { + Name string `json:"name"` +} + +type DomainPermissions struct { + DomainID uint `json:"domainId"` + DomainName string `json:"domainName"` + UserID uint `json:"userId"` + CanManage bool `json:"canManage"` +} + +func (h *DomainHandler) List(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil { + Error(w, http.StatusUnauthorized, "authentication required") + return + } + + isAdmin := authCtx.IsAdmin() + domains, err := h.db.GetUserAccessibleDomains(authCtx.UserID, isAdmin) + if err != nil { + Error(w, http.StatusInternalServerError, "database error") + return + } + + domainStats := make([]db.DomainStats, len(domains)) + for i, d := range domains { + var userCount, aliasCount int64 + h.db.Model(&db.User{}).Where("domain_id = ?", d.ID).Count(&userCount) + h.db.Model(&db.Alias{}).Where("domain_id = ?", d.ID).Count(&aliasCount) + domainStats[i] = db.DomainStats{ + ID: d.ID, + Name: d.Name, + UserCount: userCount, + AliasCount: aliasCount, + } + } + + Success(w, domainStats) +} + +func (h *DomainHandler) Get(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + domainName := extractDomainName(r.URL.Path) + if domainName == "" { + Error(w, http.StatusBadRequest, "domain name required") + return + } + + domain, err := h.db.GetDomainByName(domainName) + if err != nil { + Error(w, http.StatusNotFound, "domain not found") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil { + Error(w, http.StatusUnauthorized, "authentication required") + return + } + + canAccess, _ := h.db.CanAccessDomain(authCtx.UserID, domainName, authCtx.IsAdmin()) + if !canAccess { + Error(w, http.StatusForbidden, "access denied") + return + } + + Success(w, domain) +} + +func (h *DomainHandler) Create(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil || !authCtx.IsAdmin() { + Error(w, http.StatusForbidden, "admin access required") + return + } + + var req CreateDomainRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + Error(w, http.StatusBadRequest, "invalid request body") + return + } + + if req.Name == "" { + Error(w, http.StatusBadRequest, "domain name required") + return + } + + existing, err := h.db.GetDomainByName(req.Name) + if err == nil && existing != nil { + Error(w, http.StatusConflict, "domain already exists") + return + } + + domain, err := h.db.CreateDomain(req.Name) + if err != nil { + Error(w, http.StatusInternalServerError, "failed to create domain") + return + } + + Created(w, domain) +} + +func (h *DomainHandler) Delete(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodDelete { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil || !authCtx.IsAdmin() { + Error(w, http.StatusForbidden, "admin access required") + return + } + + domainName := extractDomainName(r.URL.Path) + if domainName == "" { + Error(w, http.StatusBadRequest, "domain name required") + return + } + + domain, err := h.db.GetDomainByName(domainName) + if err != nil { + Error(w, http.StatusNotFound, "domain not found") + return + } + + if err := h.db.DeleteDomain(domain.ID); err != nil { + Error(w, http.StatusInternalServerError, "failed to delete domain") + return + } + + NoContent(w) +} + +func (h *DomainHandler) GetPermissions(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil { + Error(w, http.StatusUnauthorized, "authentication required") + return + } + + if !authCtx.IsAdmin() { + Error(w, http.StatusForbidden, "admin access required") + return + } + + domainName := extractDomainName(r.URL.Path) + if domainName == "" { + Error(w, http.StatusBadRequest, "domain name required") + return + } + + domain, err := h.db.GetDomainByName(domainName) + if err != nil { + Error(w, http.StatusNotFound, "domain not found") + return + } + + users, err := h.db.GetUsersForDomain(domain.ID) + if err != nil { + Error(w, http.StatusInternalServerError, "database error") + return + } + + permissions := make([]DomainPermissions, len(users)) + for i, u := range users { + permissions[i] = DomainPermissions{ + DomainID: domain.ID, + DomainName: domain.Name, + UserID: u.ID, + CanManage: true, + } + } + + Success(w, permissions) +} + +func (h *DomainHandler) AddPermission(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil || !authCtx.IsAdmin() { + Error(w, http.StatusForbidden, "admin access required") + return + } + + domainName := extractDomainName(r.URL.Path) + if domainName == "" { + Error(w, http.StatusBadRequest, "domain name required") + return + } + + domain, err := h.db.GetDomainByName(domainName) + if err != nil { + Error(w, http.StatusNotFound, "domain not found") + return + } + + var req struct { + UserID uint `json:"userId"` + } + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + Error(w, http.StatusBadRequest, "invalid request") + return + } + + if err := h.db.AddUserToDomain(req.UserID, domain.ID); err != nil { + Error(w, http.StatusInternalServerError, "failed to add user to domain") + return + } + + Success(w, map[string]string{"message": "user added to domain"}) +} + +func (h *DomainHandler) RemovePermission(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodDelete { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil || !authCtx.IsAdmin() { + Error(w, http.StatusForbidden, "admin access required") + return + } + + domainName := extractDomainName(r.URL.Path) + if domainName == "" { + Error(w, http.StatusBadRequest, "domain name required") + return + } + + domain, err := h.db.GetDomainByName(domainName) + if err != nil { + Error(w, http.StatusNotFound, "domain not found") + return + } + + userID := extractIDFromPath(r.URL.Path) + + if err := h.db.RemoveUserFromDomain(userID, domain.ID); err != nil { + Error(w, http.StatusInternalServerError, "failed to remove user from domain") + return + } + + NoContent(w) +} + +func extractDomainName(path string) string { + parts := strings.Split(strings.TrimPrefix(path, "/api/"), "/") + if len(parts) >= 2 && parts[1] != "" { + return parts[1] + } + return "" +} + +func extractIDFromPath(path string) uint { + parts := strings.Split(path, "/") + for i := len(parts) - 1; i >= 0; i-- { + if idStr := parts[i]; idStr != "" { + var id uint + for _, c := range idStr { + if c >= '0' && c <= '9' { + id = id*10 + uint(c-'0') + } else { + break + } + } + if id > 0 { + return id + } + } + } + return 0 +} diff --git a/backend/internal/api/handlers/logs.go b/backend/internal/api/handlers/logs.go new file mode 100644 index 0000000..7f716d1 --- /dev/null +++ b/backend/internal/api/handlers/logs.go @@ -0,0 +1,38 @@ +package handlers + +import ( + "net/http" + "strconv" + + "github.com/imc-vibe/backend/internal/mail" +) + +type LogsHandler struct{} + +func NewLogsHandler() *LogsHandler { + return &LogsHandler{} +} + +func (h *LogsHandler) List(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + hours := 1 + if h := r.URL.Query().Get("hours"); h != "" { + if n, err := strconv.Atoi(h); err == nil && n > 0 { + hours = n + } + } + + filter := r.URL.Query().Get("filter") + + entries, err := mail.GetLogs(hours, filter) + if err != nil { + Error(w, http.StatusInternalServerError, "failed to get logs") + return + } + + Success(w, entries) +} diff --git a/backend/internal/api/handlers/middleware.go b/backend/internal/api/handlers/middleware.go new file mode 100644 index 0000000..e539357 --- /dev/null +++ b/backend/internal/api/handlers/middleware.go @@ -0,0 +1,72 @@ +package handlers + +import ( + "context" + "net/http" + "strings" + + "github.com/imc-vibe/backend/internal/auth" +) + +type contextKey string + +const AuthContextKey contextKey = "auth" + +func AuthMiddleware(jwtManager *auth.JWTManager, next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + authHeader := r.Header.Get("Authorization") + if authHeader == "" { + http.Error(w, `{"error":"authorization header required"}`, http.StatusUnauthorized) + return + } + + parts := strings.SplitN(authHeader, " ", 2) + if len(parts) != 2 || strings.ToLower(parts[0]) != "bearer" { + http.Error(w, `{"error":"invalid authorization header format"}`, http.StatusUnauthorized) + return + } + + claims, err := jwtManager.ValidateToken(parts[1]) + if err != nil { + http.Error(w, `{"error":"invalid token"}`, http.StatusUnauthorized) + return + } + + authCtx := &auth.Context{ + UserID: claims.UserID, + Username: claims.Username, + Role: auth.Role(claims.Role), + } + + ctx := context.WithValue(r.Context(), AuthContextKey, authCtx) + next.ServeHTTP(w, r.WithContext(ctx)) + }) +} + +func GetAuthContext(r *http.Request) *auth.Context { + if ctx := r.Context().Value(AuthContextKey); ctx != nil { + if authCtx, ok := ctx.(*auth.Context); ok { + return authCtx + } + } + return nil +} + +func RequireAdmin(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + authCtx := GetAuthContext(r) + if authCtx == nil || !authCtx.IsAdmin() { + http.Error(w, `{"error":"admin access required"}`, http.StatusForbidden) + return + } + next.ServeHTTP(w, r) + }) +} + +func extractID(path string) string { + parts := strings.Split(path, "/") + if len(parts) > 0 { + return parts[len(parts)-1] + } + return "" +} diff --git a/backend/internal/api/handlers/queue.go b/backend/internal/api/handlers/queue.go new file mode 100644 index 0000000..34bb712 --- /dev/null +++ b/backend/internal/api/handlers/queue.go @@ -0,0 +1,58 @@ +package handlers + +import ( + "net/http" + + "github.com/imc-vibe/backend/internal/mail" +) + +type QueueHandler struct{} + +func NewQueueHandler() *QueueHandler { + return &QueueHandler{} +} + +func (h *QueueHandler) List(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + entries, err := mail.GetQueue() + if err != nil { + Error(w, http.StatusInternalServerError, "failed to get queue") + return + } + + Success(w, entries) +} + +func (h *QueueHandler) Requeue(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + id := extractID(r.URL.Path) + if err := mail.RequeueMail(id); err != nil { + Error(w, http.StatusInternalServerError, "failed to requeue mail") + return + } + + Success(w, map[string]string{"message": "mail requeued"}) +} + +func (h *QueueHandler) Delete(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodDelete { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + id := extractID(r.URL.Path) + if err := mail.DeleteFromQueue(id); err != nil { + Error(w, http.StatusInternalServerError, "failed to delete from queue") + return + } + + NoContent(w) +} diff --git a/backend/internal/api/handlers/response.go b/backend/internal/api/handlers/response.go new file mode 100644 index 0000000..025a474 --- /dev/null +++ b/backend/internal/api/handlers/response.go @@ -0,0 +1,41 @@ +package handlers + +import ( + "encoding/json" + "net/http" +) + +type Response struct { + Data interface{} `json:"data"` + Error string `json:"error,omitempty"` + Meta *Meta `json:"meta,omitempty"` +} + +type Meta struct { + Total int `json:"total,omitempty"` + Page int `json:"page,omitempty"` +} + +func JSON(w http.ResponseWriter, status int, data interface{}) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(status) + json.NewEncoder(w).Encode(Response{Data: data}) +} + +func Error(w http.ResponseWriter, status int, message string) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(status) + json.NewEncoder(w).Encode(Response{Error: message}) +} + +func Success(w http.ResponseWriter, data interface{}) { + JSON(w, http.StatusOK, data) +} + +func Created(w http.ResponseWriter, data interface{}) { + JSON(w, http.StatusCreated, data) +} + +func NoContent(w http.ResponseWriter) { + w.WriteHeader(http.StatusNoContent) +} diff --git a/backend/internal/api/handlers/stats.go b/backend/internal/api/handlers/stats.go new file mode 100644 index 0000000..7bb6a5c --- /dev/null +++ b/backend/internal/api/handlers/stats.go @@ -0,0 +1,53 @@ +package handlers + +import ( + "net/http" + + "github.com/imc-vibe/backend/internal/db" +) + +type StatsHandler struct { + db *db.DB +} + +func NewStatsHandler(database *db.DB) *StatsHandler { + return &StatsHandler{db: database} +} + +type Stats struct { + TotalDomains int `json:"totalDomains"` + TotalUsers int `json:"totalUsers"` + TotalAliases int `json:"totalAliases"` + QueueSize int `json:"queueSize"` +} + +func (h *StatsHandler) Get(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + domains, err := h.db.GetAllDomains() + if err != nil { + domains = []db.DomainStats{} + } + + users, err := h.db.GetAllUsers() + if err != nil { + users = []db.User{} + } + + aliases, err := h.db.GetAllAliases() + if err != nil { + aliases = []db.AliasWithDomain{} + } + + stats := Stats{ + TotalDomains: len(domains), + TotalUsers: len(users), + TotalAliases: len(aliases), + QueueSize: 0, + } + + Success(w, stats) +} diff --git a/backend/internal/api/handlers/users.go b/backend/internal/api/handlers/users.go new file mode 100644 index 0000000..4b260c9 --- /dev/null +++ b/backend/internal/api/handlers/users.go @@ -0,0 +1,351 @@ +package handlers + +import ( + "encoding/json" + "net/http" + "strconv" + "strings" + + "github.com/imc-vibe/backend/internal/auth" + "github.com/imc-vibe/backend/internal/db" +) + +type UserHandler struct { + db *db.DB +} + +func NewUserHandler(database *db.DB) *UserHandler { + return &UserHandler{db: database} +} + +type CreateUserRequest struct { + Email string `json:"email"` + Password string `json:"password"` + Quota int64 `json:"quota"` +} + +type UpdateUserRequest struct { + Password string `json:"password,omitempty"` + Quota int64 `json:"quota,omitempty"` +} + +func (h *UserHandler) List(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + domainName := extractDomainNameFromPath(r.URL.Path) + if domainName == "" { + Error(w, http.StatusBadRequest, "domain name required") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil { + Error(w, http.StatusUnauthorized, "authentication required") + return + } + + canAccess, _ := h.db.CanAccessDomain(authCtx.UserID, domainName, authCtx.IsAdmin()) + if !canAccess { + Error(w, http.StatusForbidden, "access denied") + return + } + + domain, err := h.db.GetDomainByName(domainName) + if err != nil { + Error(w, http.StatusNotFound, "domain not found") + return + } + + users, err := h.db.GetUsersByDomain(domain.ID) + if err != nil { + Error(w, http.StatusInternalServerError, "database error") + return + } + + Success(w, users) +} + +func (h *UserHandler) Get(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + parts := strings.Split(strings.TrimPrefix(r.URL.Path, "/api/domains/"), "/") + if len(parts) < 4 { + Error(w, http.StatusBadRequest, "invalid path") + return + } + domainName := parts[0] + + authCtx := GetAuthContext(r) + if authCtx == nil { + Error(w, http.StatusUnauthorized, "authentication required") + return + } + + canAccess, _ := h.db.CanAccessDomain(authCtx.UserID, domainName, authCtx.IsAdmin()) + if !canAccess { + Error(w, http.StatusForbidden, "access denied") + return + } + + idStr := parts[3] + id, err := strconv.ParseUint(idStr, 10, 64) + if err != nil { + Error(w, http.StatusBadRequest, "invalid user id") + return + } + + user, err := h.db.GetUserByID(uint(id)) + if err != nil { + Error(w, http.StatusNotFound, "user not found") + return + } + + Success(w, user) +} + +func (h *UserHandler) Create(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + domainName := extractDomainNameFromPath(r.URL.Path) + if domainName == "" { + Error(w, http.StatusBadRequest, "domain name required") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil { + Error(w, http.StatusUnauthorized, "authentication required") + return + } + + canAccess, _ := h.db.CanAccessDomain(authCtx.UserID, domainName, authCtx.IsAdmin()) + if !canAccess { + Error(w, http.StatusForbidden, "access denied") + return + } + + domain, err := h.db.GetDomainByName(domainName) + if err != nil { + Error(w, http.StatusNotFound, "domain not found") + return + } + + var req CreateUserRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + Error(w, http.StatusBadRequest, "invalid request body") + return + } + + if req.Email == "" || req.Password == "" { + Error(w, http.StatusBadRequest, "email and password required") + return + } + + existing, _ := h.db.GetUserByEmail(req.Email) + if existing != nil { + Error(w, http.StatusConflict, "user already exists") + return + } + + passwordHash := "{BLF-CRYPT}" + req.Password + + user, err := h.db.CreateUserInDomain(req.Email, passwordHash, req.Quota, domain.ID) + if err != nil { + Error(w, http.StatusInternalServerError, "failed to create user") + return + } + + Created(w, user) +} + +func (h *UserHandler) Update(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPut { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + parts := strings.Split(strings.TrimPrefix(r.URL.Path, "/api/domains/"), "/") + if len(parts) < 4 { + Error(w, http.StatusBadRequest, "invalid path") + return + } + domainName := parts[0] + + authCtx := GetAuthContext(r) + if authCtx == nil { + Error(w, http.StatusUnauthorized, "authentication required") + return + } + + canAccess, _ := h.db.CanAccessDomain(authCtx.UserID, domainName, authCtx.IsAdmin()) + if !canAccess { + Error(w, http.StatusForbidden, "access denied") + return + } + + idStr := parts[3] + id, err := strconv.ParseUint(idStr, 10, 64) + if err != nil { + Error(w, http.StatusBadRequest, "invalid user id") + return + } + + user, err := h.db.GetUserByID(uint(id)) + if err != nil { + Error(w, http.StatusNotFound, "user not found") + return + } + + var req UpdateUserRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + Error(w, http.StatusBadRequest, "invalid request body") + return + } + + if req.Password != "" { + passwordHash := "{BLF-CRYPT}" + req.Password + if err := h.db.UpdateUserPassword(user.ID, passwordHash); err != nil { + Error(w, http.StatusInternalServerError, "failed to update password") + return + } + } + + if req.Quota >= 0 { + if err := h.db.UpdateUserQuota(user.ID, req.Quota); err != nil { + Error(w, http.StatusInternalServerError, "failed to update quota") + return + } + } + + Success(w, map[string]string{"message": "user updated"}) +} + +func (h *UserHandler) Delete(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodDelete { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + parts := strings.Split(strings.TrimPrefix(r.URL.Path, "/api/domains/"), "/") + if len(parts) < 4 { + Error(w, http.StatusBadRequest, "invalid path") + return + } + domainName := parts[0] + + authCtx := GetAuthContext(r) + if authCtx == nil { + Error(w, http.StatusUnauthorized, "authentication required") + return + } + + canAccess, _ := h.db.CanAccessDomain(authCtx.UserID, domainName, authCtx.IsAdmin()) + if !canAccess { + Error(w, http.StatusForbidden, "access denied") + return + } + + idStr := parts[3] + id, err := strconv.ParseUint(idStr, 10, 64) + if err != nil { + Error(w, http.StatusBadRequest, "invalid user id") + return + } + + if err := h.db.DeleteUser(uint(id)); err != nil { + Error(w, http.StatusInternalServerError, "failed to delete user") + return + } + + NoContent(w) +} + +func (h *UserHandler) ListAll(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + Error(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + + authCtx := GetAuthContext(r) + if authCtx == nil || !authCtx.IsAdmin() { + Error(w, http.StatusForbidden, "admin access required") + return + } + + users, err := h.db.GetAllUsers() + if err != nil { + Error(w, http.StatusInternalServerError, "database error") + return + } + + Success(w, users) +} + +func extractDomainNameFromPath(path string) string { + parts := strings.Split(strings.TrimPrefix(path, "/api/"), "/") + if len(parts) >= 2 && parts[0] == "domains" && parts[1] != "" { + if idx := strings.Index(parts[1], "/"); idx > 0 { + return parts[1][:idx] + } + return parts[1] + } + return "" +} + +func requireAuth(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if GetAuthContext(r) == nil { + http.Error(w, `{"error":"authentication required"}`, http.StatusUnauthorized) + return + } + next.ServeHTTP(w, r) + }) +} + +func requireAdmin(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + authCtx := GetAuthContext(r) + if authCtx == nil || !authCtx.IsAdmin() { + http.Error(w, `{"error":"admin access required"}`, http.StatusForbidden) + return + } + next.ServeHTTP(w, r) + }) +} + +func checkDomainAccess(database *db.DB) func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + authCtx := GetAuthContext(r) + if authCtx == nil { + http.Error(w, `{"error":"authentication required"}`, http.StatusUnauthorized) + return + } + + domainName := extractDomainNameFromPath(r.URL.Path) + if domainName == "" { + next.ServeHTTP(w, r) + return + } + + canAccess, _ := database.CanAccessDomain(authCtx.UserID, domainName, authCtx.IsAdmin()) + if !canAccess { + http.Error(w, `{"error":"access denied"}`, http.StatusForbidden) + return + } + + next.ServeHTTP(w, r) + }) + } +} + +var _ = auth.RoleAdmin diff --git a/backend/internal/api/router.go b/backend/internal/api/router.go new file mode 100644 index 0000000..3f8396b --- /dev/null +++ b/backend/internal/api/router.go @@ -0,0 +1,247 @@ +package api + +import ( + "context" + "net/http" + "strings" + + "github.com/imc-vibe/backend/internal/api/handlers" + "github.com/imc-vibe/backend/internal/auth" + "github.com/imc-vibe/backend/internal/config" + "github.com/imc-vibe/backend/internal/db" +) + +type Router struct { + authHandler *handlers.AuthHandler + domainHandler *handlers.DomainHandler + userHandler *handlers.UserHandler + aliasHandler *handlers.AliasHandler + statsHandler *handlers.StatsHandler + queueHandler *handlers.QueueHandler + logsHandler *handlers.LogsHandler + jwtManager *auth.JWTManager + db *db.DB +} + +func New(database *db.DB, cfg *config.Config) *Router { + jwtManager := auth.NewJWTManager(cfg.JWTSecret, "imc-vibe") + + return &Router{ + authHandler: handlers.NewAuthHandler(database, jwtManager), + domainHandler: handlers.NewDomainHandler(database), + userHandler: handlers.NewUserHandler(database), + aliasHandler: handlers.NewAliasHandler(database), + statsHandler: handlers.NewStatsHandler(database), + queueHandler: handlers.NewQueueHandler(), + logsHandler: handlers.NewLogsHandler(), + jwtManager: jwtManager, + db: database, + } +} + +func (r *Router) Handler() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + path := req.URL.Path + + // Only handle /api/* routes + if !strings.HasPrefix(path, "/api/") { + http.NotFound(w, req) + return + } + + // Public routes - no auth required + switch path { + case "/api/auth/login": + r.authHandler.Login(w, req) + return + case "/api/auth/forgot": + r.authHandler.ForgotPassword(w, req) + return + case "/api/auth/logout": + r.authHandler.Logout(w, req) + return + } + + // Protected routes - auth required + req = r.validateAuth(req) + if req == nil { + http.Error(w, `{"error":"not authenticated"}`, http.StatusUnauthorized) + return + } + + switch { + case path == "/api/auth/me": + r.authHandler.Me(w, req) + case path == "/api/auth/change-password": + r.authHandler.ChangePassword(w, req) + case path == "/api/stats": + r.statsHandler.Get(w, req) + case strings.HasPrefix(path, "/api/domains/"): + if strings.Contains(strings.TrimPrefix(path, "/api/domains/"), "/users") { + r.handleDomainUsers(w, req) + } else if strings.Contains(strings.TrimPrefix(path, "/api/domains/"), "/aliases") { + r.handleDomainAliases(w, req) + } else { + r.handleDomains(w, req) + } + case strings.HasPrefix(path, "/api/domains"): + r.handleDomains(w, req) + case strings.HasPrefix(path, "/api/queue"): + r.handleQueue(w, req) + case path == "/api/logs": + r.logsHandler.List(w, req) + default: + http.NotFound(w, req) + } + }) +} + +func (r *Router) validateAuth(req *http.Request) *http.Request { + authHeader := req.Header.Get("Authorization") + if authHeader == "" { + return nil + } + + parts := strings.SplitN(authHeader, " ", 2) + if len(parts) != 2 || strings.ToLower(parts[0]) != "bearer" { + return nil + } + + claims, err := r.jwtManager.ValidateToken(parts[1]) + if err != nil { + return nil + } + + authCtx := &auth.Context{ + UserID: claims.UserID, + Username: claims.Username, + Role: auth.Role(claims.Role), + } + + ctx := context.WithValue(req.Context(), handlers.AuthContextKey, authCtx) + return req.WithContext(ctx) +} + +func (r *Router) handleDomains(w http.ResponseWriter, req *http.Request) { + switch req.Method { + case http.MethodGet: + if len(req.URL.Path) > len("/api/domains/") { + r.domainHandler.Get(w, req) + } else { + r.domainHandler.List(w, req) + } + case http.MethodPost: + r.domainHandler.Create(w, req) + case http.MethodDelete: + r.domainHandler.Delete(w, req) + default: + http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed) + } +} + +func (r *Router) handleDomainUsers(w http.ResponseWriter, req *http.Request) { + path := req.URL.Path + parts := strings.Split(strings.TrimPrefix(path, "/api/domains/"), "/") + if len(parts) < 2 || parts[1] != "users" { + http.NotFound(w, req) + return + } + + domainName := parts[0] + var idStr string + if len(parts) >= 3 { + idStr = parts[2] + } + + switch req.Method { + case http.MethodGet: + if idStr != "" { + req.URL.Path = "/api/domains/" + domainName + "/users/" + idStr + r.userHandler.Get(w, req) + } else { + req.URL.Path = "/api/domains/" + domainName + "/users" + r.userHandler.List(w, req) + } + case http.MethodPost: + req.URL.Path = "/api/domains/" + domainName + "/users" + r.userHandler.Create(w, req) + case http.MethodPut: + if idStr != "" { + req.URL.Path = "/api/domains/" + domainName + "/users/" + idStr + r.userHandler.Update(w, req) + } else { + http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed) + } + case http.MethodDelete: + if idStr != "" { + req.URL.Path = "/api/domains/" + domainName + "/users/" + idStr + r.userHandler.Delete(w, req) + } else { + http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed) + } + default: + http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed) + } +} + +func (r *Router) handleDomainAliases(w http.ResponseWriter, req *http.Request) { + path := req.URL.Path + parts := strings.Split(strings.TrimPrefix(path, "/api/domains/"), "/") + if len(parts) < 2 || parts[1] != "aliases" { + http.NotFound(w, req) + return + } + + domainName := parts[0] + var idStr string + if len(parts) >= 3 { + idStr = parts[2] + } + + switch req.Method { + case http.MethodGet: + req.URL.Path = "/api/domains/" + domainName + "/aliases" + r.aliasHandler.List(w, req) + case http.MethodPost: + req.URL.Path = "/api/domains/" + domainName + "/aliases" + r.aliasHandler.Create(w, req) + case http.MethodDelete: + if idStr != "" { + req.URL.Path = "/api/domains/" + domainName + "/aliases/" + idStr + r.aliasHandler.Delete(w, req) + } else { + http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed) + } + default: + http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed) + } +} + +func (r *Router) handleQueue(w http.ResponseWriter, req *http.Request) { + path := req.URL.Path + id := "" + if len(path) > len("/api/queue/") { + id = path[len("/api/queue/"):] + } + + switch req.Method { + case http.MethodGet: + r.queueHandler.List(w, req) + case http.MethodPost: + if id != "" { + req.URL.Path = "/api/queue/" + id + r.queueHandler.Requeue(w, req) + } else { + http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed) + } + case http.MethodDelete: + if id != "" { + req.URL.Path = "/api/queue/" + id + r.queueHandler.Delete(w, req) + } else { + http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed) + } + default: + http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed) + } +} diff --git a/backend/internal/auth/jwt.go b/backend/internal/auth/jwt.go new file mode 100644 index 0000000..d23a360 --- /dev/null +++ b/backend/internal/auth/jwt.go @@ -0,0 +1,85 @@ +package auth + +import ( + "errors" + "time" + + "github.com/golang-jwt/jwt/v5" + "golang.org/x/crypto/bcrypt" +) + +var ( + ErrInvalidToken = errors.New("invalid token") + ErrExpiredToken = errors.New("token has expired") +) + +type Claims struct { + UserID uint `json:"userId"` + Username string `json:"username"` + Role string `json:"role"` + jwt.RegisteredClaims +} + +type JWTManager struct { + secretKey []byte + issuer string +} + +func NewJWTManager(secretKey, issuer string) *JWTManager { + return &JWTManager{ + secretKey: []byte(secretKey), + issuer: issuer, + } +} + +func (j *JWTManager) GenerateToken(userID uint, username, role string, duration time.Duration) (string, error) { + claims := &Claims{ + UserID: userID, + Username: username, + Role: role, + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(time.Now().Add(duration)), + IssuedAt: jwt.NewNumericDate(time.Now()), + Issuer: j.issuer, + }, + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString(j.secretKey) +} + +func (j *JWTManager) ValidateToken(tokenString string) (*Claims, error) { + token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) { + if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { + return nil, ErrInvalidToken + } + return j.secretKey, nil + }) + + if err != nil { + if errors.Is(err, jwt.ErrTokenExpired) { + return nil, ErrExpiredToken + } + return nil, ErrInvalidToken + } + + claims, ok := token.Claims.(*Claims) + if !ok || !token.Valid { + return nil, ErrInvalidToken + } + + return claims, nil +} + +func HashPassword(password string) (string, error) { + hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + if err != nil { + return "", err + } + return string(hash), nil +} + +func CheckPassword(password, hash string) bool { + err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) + return err == nil +} diff --git a/backend/internal/auth/rbac.go b/backend/internal/auth/rbac.go new file mode 100644 index 0000000..4884cb0 --- /dev/null +++ b/backend/internal/auth/rbac.go @@ -0,0 +1,18 @@ +package auth + +type Role string + +const ( + RoleAdmin Role = "admin" + RoleUser Role = "user" +) + +type Context struct { + UserID uint + Username string + Role Role +} + +func (c *Context) IsAdmin() bool { + return c.Role == RoleAdmin +} diff --git a/backend/internal/config/config.go b/backend/internal/config/config.go new file mode 100644 index 0000000..35efe1c --- /dev/null +++ b/backend/internal/config/config.go @@ -0,0 +1,56 @@ +package config + +import ( + "os" + + "github.com/joho/godotenv" +) + +type Config struct { + DBHost string + DBPort string + DBUser string + DBPassword string + DBName string + Port string + UseEmbedded bool + JWTSecret string + AdminUser string + AdminPassword string + MailDataDir string + PostqueuePath string + PostsuperPath string + DovecotQuotaCmd string + JournalctlPath string + RspamdAPI string +} + +func Load() *Config { + godotenv.Load("backend/.env") + + return &Config{ + DBHost: getEnv("DB_HOST", "localhost"), + DBPort: getEnv("DB_PORT", "3306"), + DBUser: getEnv("DB_USER", "mailadmin"), + DBPassword: getEnv("DB_PASSWORD", ""), + DBName: getEnv("DB_NAME", "mailserver"), + Port: getEnv("PORT", "8080"), + UseEmbedded: getEnv("USE_EMBEDDED", "true") == "true", + JWTSecret: getEnv("JWT_SECRET", "change-this-secret"), + AdminUser: getEnv("ADMIN_USER", ""), + AdminPassword: getEnv("ADMIN_PASSWORD", ""), + MailDataDir: getEnv("MAIL_DATA_DIR", "/var/vmail"), + PostqueuePath: getEnv("POSTQUEUE_PATH", "/usr/sbin/postqueue"), + PostsuperPath: getEnv("POSTSUPER_PATH", "/usr/sbin/postsuper"), + DovecotQuotaCmd: getEnv("DOVECOT_QUOTA_CMD", "/usr/bin/doveadm"), + JournalctlPath: getEnv("JOURNALCTL_PATH", "/usr/bin/journalctl"), + RspamdAPI: getEnv("RSPAMD_API", "http://127.0.0.1:11334"), + } +} + +func getEnv(key, defaultValue string) string { + if value := os.Getenv(key); value != "" { + return value + } + return defaultValue +} diff --git a/backend/internal/db/aliases.go b/backend/internal/db/aliases.go new file mode 100644 index 0000000..e531103 --- /dev/null +++ b/backend/internal/db/aliases.go @@ -0,0 +1,70 @@ +package db + +func (d *DB) GetAllAliases() ([]AliasWithDomain, error) { + var aliases []Alias + if err := d.Preload("Domain").Find(&aliases).Error; err != nil { + return nil, err + } + + result := make([]AliasWithDomain, len(aliases)) + for i, a := range aliases { + result[i] = AliasWithDomain{ + Alias: a, + DomainName: "", + } + if a.Domain != nil { + result[i].DomainName = a.Domain.Name + } + } + + if result == nil { + result = []AliasWithDomain{} + } + return result, nil +} + +func (d *DB) GetAliasesByDomain(domainID uint) ([]Alias, error) { + var aliases []Alias + if err := d.Where("domain_id = ?", domainID).Find(&aliases).Error; err != nil { + return nil, err + } + if aliases == nil { + aliases = []Alias{} + } + return aliases, nil +} + +func (d *DB) GetAliasByID(id uint) (*Alias, error) { + var alias Alias + if err := d.Preload("Domain").First(&alias, id).Error; err != nil { + return nil, err + } + return &alias, nil +} + +func (d *DB) CreateAlias(source, destination string) (*Alias, error) { + alias := Alias{ + Source: source, + Destination: destination, + } + if err := d.Create(&alias).Error; err != nil { + return nil, err + } + return &alias, nil +} + +func (d *DB) CreateAliasInDomain(source, destination string, domainID uint) (*Alias, error) { + alias := Alias{ + DomainID: domainID, + Source: source, + Destination: destination, + } + if err := d.Create(&alias).Error; err != nil { + return nil, err + } + return &alias, nil +} + +func (d *DB) DeleteAlias(id uint) error { + return d.Delete(&Alias{}, id).Error +} diff --git a/backend/internal/db/db.go b/backend/internal/db/db.go new file mode 100644 index 0000000..4d339a1 --- /dev/null +++ b/backend/internal/db/db.go @@ -0,0 +1,164 @@ +package db + +import ( + "fmt" + "time" + + "gorm.io/driver/mysql" + "gorm.io/gorm" + "gorm.io/gorm/logger" + + "github.com/imc-vibe/backend/internal/config" +) + +type DB struct { + *gorm.DB +} + +type Domain struct { + ID uint `gorm:"primaryKey" json:"id"` + Name string `gorm:"uniqueIndex;size:50;not null" json:"name"` + CreatedAt time.Time `json:"createdAt"` + Users []User `gorm:"foreignKey:DomainID" json:"users,omitempty"` + Aliases []Alias `gorm:"foreignKey:DomainID" json:"aliases,omitempty"` +} + +func (Domain) TableName() string { return "virtual_domains" } + +type User struct { + ID uint `gorm:"primaryKey" json:"id"` + DomainID uint `gorm:"not null" json:"domainId"` + Email string `gorm:"uniqueIndex;size:100;not null" json:"email"` + Password string `gorm:"size:150;not null" json:"-"` + Quota int64 `gorm:"default:0" json:"quota"` + Domain *Domain `gorm:"foreignKey:DomainID" json:"domain,omitempty"` + CreatedAt time.Time `json:"createdAt,omitempty"` +} + +func (User) TableName() string { return "virtual_users" } + +type Alias struct { + ID uint `gorm:"primaryKey" json:"id"` + DomainID uint `gorm:"not null" json:"domainId"` + Source string `gorm:"size:100;not null" json:"source"` + Destination string `gorm:"size:100;not null" json:"destination"` + Domain *Domain `gorm:"foreignKey:DomainID" json:"domain,omitempty"` +} + +func (Alias) TableName() string { return "virtual_aliases" } + +type ImcUser struct { + ID uint `gorm:"primaryKey" json:"id"` + Username string `gorm:"uniqueIndex;size:100;not null" json:"username"` + PasswordHash string `gorm:"size:255;not null" json:"-"` + Role string `gorm:"type:enum('admin','user');default:'user'" json:"role"` + CreatedAt time.Time `json:"createdAt"` + Domains []ImcUserDomain `gorm:"foreignKey:UserID" json:"domains,omitempty"` +} + +func (ImcUser) TableName() string { return "imc_users" } + +type ImcUserDomain struct { + ID uint `gorm:"primaryKey" json:"id"` + UserID uint `gorm:"not null" json:"userId"` + DomainID uint `gorm:"not null" json:"domainId"` + CreatedAt time.Time `json:"createdAt"` + Domain *Domain `gorm:"foreignKey:DomainID" json:"domain,omitempty"` +} + +func (ImcUserDomain) TableName() string { return "imc_users2domains" } + +type ImcLoginAttempt struct { + ID uint `gorm:"primaryKey" json:"id"` + Email string `gorm:"size:100;not null" json:"email"` + IPAddress string `gorm:"size:45;not null" json:"ipAddress"` + AttemptedAt time.Time `json:"attemptedAt"` + Successful bool `gorm:"default:false" json:"successful"` +} + +func (ImcLoginAttempt) TableName() string { return "imc_login_attempts" } + +type DomainStats struct { + ID uint `json:"id"` + Name string `json:"name"` + UserCount int64 `json:"userCount"` + AliasCount int64 `json:"aliasCount"` +} + +type AliasWithDomain struct { + Alias + DomainName string `json:"domainName"` +} + +type UserWithDomain struct { + User + DomainName string `json:"domainName"` +} + +func Connect(cfg *config.Config) (*DB, error) { + dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true&charset=utf8mb4", + cfg.DBUser, cfg.DBPassword, cfg.DBHost, cfg.DBPort, cfg.DBName) + + db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ + Logger: logger.Default.LogMode(logger.Silent), + }) + if err != nil { + return nil, fmt.Errorf("failed to connect to database: %w", err) + } + + sqlDB, err := db.DB() + if err != nil { + return nil, err + } + + sqlDB.SetMaxOpenConns(25) + sqlDB.SetMaxIdleConns(5) + sqlDB.SetConnMaxLifetime(5 * time.Minute) + + return &DB{db}, nil +} + +func (d *DB) InitSchema() error { + imcUsersSQL := ` + CREATE TABLE IF NOT EXISTS imc_users ( + id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(100) NOT NULL UNIQUE, + password_hash VARCHAR(255) NOT NULL, + role ENUM('admin','user') DEFAULT 'user', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + INDEX idx_username (username), + INDEX idx_role (role) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 + ` + if err := d.Exec(imcUsersSQL).Error; err != nil { + return err + } + + loginAttemptsSQL := ` + CREATE TABLE IF NOT EXISTS imc_login_attempts ( + id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + email VARCHAR(100) NOT NULL, + ip_address VARCHAR(45) NOT NULL, + attempted_at DATETIME DEFAULT CURRENT_TIMESTAMP, + successful BOOLEAN DEFAULT FALSE, + INDEX idx_email_time (email, attempted_at), + INDEX idx_ip_time (ip_address, attempted_at) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 + ` + if err := d.Exec(loginAttemptsSQL).Error; err != nil { + return err + } + + users2DomainsSQL := ` + CREATE TABLE IF NOT EXISTS imc_users2domains ( + id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + user_id INT UNSIGNED NOT NULL, + domain_id INT UNSIGNED NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + UNIQUE KEY unique_user_domain (user_id, domain_id), + INDEX idx_user_id (user_id), + INDEX idx_domain_id (domain_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 + ` + return d.Exec(users2DomainsSQL).Error +} diff --git a/backend/internal/db/domains.go b/backend/internal/db/domains.go new file mode 100644 index 0000000..f3b797b --- /dev/null +++ b/backend/internal/db/domains.go @@ -0,0 +1,68 @@ +package db + +func (d *DB) GetAllDomains() ([]DomainStats, error) { + var domains []Domain + if err := d.Find(&domains).Error; err != nil { + return nil, err + } + + stats := make([]DomainStats, len(domains)) + for i, dom := range domains { + var userCount, aliasCount int64 + d.Model(&User{}).Where("domain_id = ?", dom.ID).Count(&userCount) + d.Model(&Alias{}).Where("domain_id = ?", dom.ID).Count(&aliasCount) + + stats[i] = DomainStats{ + ID: dom.ID, + Name: dom.Name, + UserCount: userCount, + AliasCount: aliasCount, + } + } + + if stats == nil { + stats = []DomainStats{} + } + return stats, nil +} + +func (d *DB) GetDomainByID(id uint) (*Domain, error) { + var domain Domain + if err := d.Where("id = ?", id).First(&domain).Error; err != nil { + return nil, err + } + return &domain, nil +} + +func (d *DB) GetDomainByName(name string) (*Domain, error) { + var domain Domain + if err := d.Where("name = ?", name).First(&domain).Error; err != nil { + return nil, err + } + return &domain, nil +} + +func (d *DB) CreateDomain(name string) (*Domain, error) { + domain := Domain{Name: name} + if err := d.Create(&domain).Error; err != nil { + return nil, err + } + return &domain, nil +} + +func (d *DB) DeleteDomain(id uint) error { + tx := d.Begin() + defer func() { tx.Rollback() }() + + if err := tx.Where("domain_id = ?", id).Delete(&User{}).Error; err != nil { + return err + } + if err := tx.Where("domain_id = ?", id).Delete(&Alias{}).Error; err != nil { + return err + } + if err := tx.Delete(&Domain{}, id).Error; err != nil { + return err + } + + return tx.Commit().Error +} diff --git a/backend/internal/db/imc_users.go b/backend/internal/db/imc_users.go new file mode 100644 index 0000000..d3baeb2 --- /dev/null +++ b/backend/internal/db/imc_users.go @@ -0,0 +1,122 @@ +package db + +func (d *DB) GetImcUserByUsername(username string) (*ImcUser, error) { + var user ImcUser + if err := d.Preload("Domains.Domain").Where("username = ?", username).First(&user).Error; err != nil { + return nil, err + } + return &user, nil +} + +func (d *DB) GetImcUserByID(id uint) (*ImcUser, error) { + var user ImcUser + if err := d.Preload("Domains.Domain").First(&user, id).Error; err != nil { + return nil, err + } + return &user, nil +} + +func (d *DB) CreateImcUser(username, passwordHash, role string) (*ImcUser, error) { + user := ImcUser{ + Username: username, + PasswordHash: passwordHash, + Role: role, + } + if err := d.Create(&user).Error; err != nil { + return nil, err + } + return &user, nil +} + +func (d *DB) UpdateImcUserPassword(id uint, passwordHash string) error { + return d.Model(&ImcUser{}).Where("id = ?", id).Update("password_hash", passwordHash).Error +} + +func (d *DB) DeleteImcUser(id uint) error { + return d.Delete(&ImcUser{}, id).Error +} + +func (d *DB) EnsureAdminUser(username, passwordHash string) error { + var user ImcUser + err := d.Where("username = ? AND role = ?", username, "admin").First(&user).Error + if err == nil { + return d.Model(&ImcUser{}).Where("id = ?", user.ID).Update("password_hash", passwordHash).Error + } + _, err = d.CreateImcUser(username, passwordHash, "admin") + return err +} + +func (d *DB) GetUserAccessibleDomains(userID uint, isAdmin bool) ([]Domain, error) { + if isAdmin { + var domains []Domain + if err := d.Find(&domains).Error; err != nil { + return nil, err + } + return domains, nil + } + + var domains []Domain + err := d.Table("imc_users2domains"). + Select("virtual_domains.*"). + Joins("JOIN virtual_domains ON virtual_domains.id = imc_users2domains.domain_id"). + Where("imc_users2domains.user_id = ?", userID). + Find(&domains).Error + if err != nil { + return nil, err + } + if domains == nil { + domains = []Domain{} + } + return domains, nil +} + +func (d *DB) CanAccessDomain(userID uint, domainName string, isAdmin bool) (bool, error) { + if isAdmin { + return true, nil + } + + var count int64 + err := d.Table("imc_users2domains"). + Select("COUNT(*)"). + Joins("JOIN virtual_domains ON virtual_domains.id = imc_users2domains.domain_id"). + Where("imc_users2domains.user_id = ? AND virtual_domains.name = ?", userID, domainName). + Count(&count).Error + if err != nil { + return false, err + } + return count > 0, nil +} + +func (d *DB) AddUserToDomain(userID, domainID uint) error { + ud := ImcUserDomain{ + UserID: userID, + DomainID: domainID, + } + return d.Create(&ud).Error +} + +func (d *DB) RemoveUserFromDomain(userID, domainID uint) error { + return d.Where("user_id = ? AND domain_id = ?", userID, domainID).Delete(&ImcUserDomain{}).Error +} + +func (d *DB) GetUsersForDomain(domainID uint) ([]ImcUser, error) { + var users []ImcUser + err := d.Table("imc_users2domains"). + Select("imc_users.*"). + Joins("JOIN imc_users ON imc_users.id = imc_users2domains.user_id"). + Where("imc_users2domains.domain_id = ?", domainID). + Find(&users).Error + if err != nil { + return nil, err + } + if users == nil { + users = []ImcUser{} + } + return users, nil +} + +func (d *DB) IsUserInDomain(userID, domainID uint) (bool, error) { + var count int64 + err := d.Model(&ImcUserDomain{}).Where("user_id = ? AND domain_id = ?", userID, domainID).Count(&count).Error + return count > 0, err +} diff --git a/backend/internal/db/users.go b/backend/internal/db/users.go new file mode 100644 index 0000000..6dcd2fc --- /dev/null +++ b/backend/internal/db/users.go @@ -0,0 +1,76 @@ +package db + +func (d *DB) GetAllUsers() ([]User, error) { + var users []User + if err := d.Preload("Domain").Find(&users).Error; err != nil { + return nil, err + } + if users == nil { + users = []User{} + } + return users, nil +} + +func (d *DB) GetUsersByDomain(domainID uint) ([]User, error) { + var users []User + if err := d.Where("domain_id = ?", domainID).Find(&users).Error; err != nil { + return nil, err + } + if users == nil { + users = []User{} + } + return users, nil +} + +func (d *DB) GetUserByID(id uint) (*User, error) { + var user User + if err := d.Preload("Domain").First(&user, id).Error; err != nil { + return nil, err + } + return &user, nil +} + +func (d *DB) GetUserByEmail(email string) (*User, error) { + var user User + if err := d.Where("email = ?", email).First(&user).Error; err != nil { + return nil, err + } + return &user, nil +} + +func (d *DB) CreateUser(email, passwordHash string, quota int64) (*User, error) { + user := User{ + Email: email, + Password: passwordHash, + Quota: quota, + } + if err := d.Create(&user).Error; err != nil { + return nil, err + } + return &user, nil +} + +func (d *DB) CreateUserInDomain(email, passwordHash string, quota int64, domainID uint) (*User, error) { + user := User{ + DomainID: domainID, + Email: email, + Password: passwordHash, + Quota: quota, + } + if err := d.Create(&user).Error; err != nil { + return nil, err + } + return &user, nil +} + +func (d *DB) UpdateUserPassword(id uint, passwordHash string) error { + return d.Model(&User{}).Where("id = ?", id).Update("password", passwordHash).Error +} + +func (d *DB) UpdateUserQuota(id uint, quota int64) error { + return d.Model(&User{}).Where("id = ?", id).Update("quota", quota).Error +} + +func (d *DB) DeleteUser(id uint) error { + return d.Delete(&User{}, id).Error +} diff --git a/backend/internal/mail/logs.go b/backend/internal/mail/logs.go new file mode 100644 index 0000000..29c20e4 --- /dev/null +++ b/backend/internal/mail/logs.go @@ -0,0 +1,88 @@ +package mail + +import ( + "bufio" + "bytes" + "context" + "os/exec" + "regexp" + "strings" + "time" +) + +type LogEntry struct { + Timestamp string `json:"timestamp"` + Priority string `json:"priority"` + Message string `json:"message"` +} + +func GetLogs(hours int, filter string) ([]LogEntry, error) { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + args := []string{ + "-u", "postfix", + "--since", formatDuration(hours), + "--no-pager", + "-o", "short=false", + } + + cmd := exec.CommandContext(ctx, "journalctl", args...) + var out bytes.Buffer + cmd.Stdout = &out + + if err := cmd.Run(); err != nil { + return nil, err + } + + var entries []LogEntry + scanner := bufio.NewScanner(&out) + priorityRegex := regexp.MustCompile(`\[([^\]]+)\]`) + + for scanner.Scan() { + line := scanner.Text() + + if filter != "" && !strings.Contains(strings.ToLower(line), strings.ToLower(filter)) { + continue + } + + parts := strings.SplitN(line, " ", 4) + if len(parts) < 4 { + continue + } + + timestamp := parts[0] + " " + parts[1] + + matches := priorityRegex.FindStringSubmatch(parts[2]) + priority := "info" + if len(matches) > 1 { + priority = matches[1] + } else if strings.Contains(parts[2], "err") { + priority = "err" + } else if strings.Contains(parts[2], "warning") || strings.Contains(parts[2], "warn") { + priority = "warning" + } + + message := parts[3] + + if filter != "" && !strings.Contains(strings.ToLower(message), strings.ToLower(filter)) { + continue + } + + entries = append(entries, LogEntry{ + Timestamp: timestamp, + Priority: priority, + Message: message, + }) + } + + if entries == nil { + entries = []LogEntry{} + } + + return entries, nil +} + +func formatDuration(hours int) string { + return time.Now().Add(-time.Duration(hours) * time.Hour).Format("15:04:05 2006-01-02") +} diff --git a/backend/internal/mail/queue.go b/backend/internal/mail/queue.go new file mode 100644 index 0000000..744e061 --- /dev/null +++ b/backend/internal/mail/queue.go @@ -0,0 +1,123 @@ +package mail + +import ( + "bufio" + "bytes" + "encoding/json" + "os/exec" + "regexp" + "strconv" + "strings" +) + +type QueueEntry struct { + ID string `json:"id"` + Sender string `json:"sender"` + Recipients []string `json:"recipients"` + Size int `json:"size"` + Time string `json:"time"` + Reason string `json:"reason"` +} + +var queueLineRegex = regexp.MustCompile(`^([A-Fa-f0-9]+)\s+(\d+)\s+(\w+)\s+([A-Za-z]+\s+\d+\s+[\d:]+)\s+([^\s]+)\s+(.+)$`) + +func GetQueue() ([]QueueEntry, error) { + cmd := exec.Command("postqueue", "-p", "-j") + var out bytes.Buffer + cmd.Stdout = &out + + if err := cmd.Run(); err != nil { + return nil, err + } + + var entries []QueueEntry + scanner := bufio.NewScanner(&out) + + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if line == "" || !strings.HasPrefix(line, "{") { + continue + } + + var entry struct { + QueueID string `json:"queueid"` + Sender string `json:"sender"` + Recipients []struct { + Address string `json:"address"` + } `json:"recipients"` + Size int64 `json:"size"` + Arrival string `json:"arrival_timestamp"` + Delay string `json:"delay_reason"` + } + + if err := json.Unmarshal([]byte(line), &entry); err != nil { + continue + } + + recipients := make([]string, len(entry.Recipients)) + for i, r := range entry.Recipients { + recipients[i] = r.Address + } + + entries = append(entries, QueueEntry{ + ID: entry.QueueID, + Sender: entry.Sender, + Recipients: recipients, + Size: int(entry.Size), + Time: entry.Arrival, + Reason: entry.Delay, + }) + } + + if entries == nil { + entries = []QueueEntry{} + } + + return entries, nil +} + +func RequeueMail(id string) error { + cmd := exec.Command("postqueue", "-f", "-v") + var out bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &out + + if err := cmd.Run(); err != nil { + return err + } + return nil +} + +func DeleteFromQueue(id string) error { + cmd := exec.Command("postsuper", "-d", id) + return cmd.Run() +} + +func GetQueueCount() (int, error) { + cmd := exec.Command("postqueue", "-p") + var out bytes.Buffer + cmd.Stdout = &out + + if err := cmd.Run(); err != nil { + return 0, err + } + + count := 0 + scanner := bufio.NewScanner(&out) + for scanner.Scan() { + line := scanner.Text() + if strings.Contains(line, " mail queue") { + parts := strings.Fields(line) + for i, p := range parts { + if n, err := strconv.Atoi(p); err == nil && n > 0 { + count = n + if i > 0 && parts[i-1] == "in" { + return n, nil + } + } + } + } + } + + return count, nil +} diff --git a/frontend/.svelte-kit/ambient.d.ts b/frontend/.svelte-kit/ambient.d.ts new file mode 100644 index 0000000..dff2444 --- /dev/null +++ b/frontend/.svelte-kit/ambient.d.ts @@ -0,0 +1,336 @@ + +// this file is generated — do not edit it + + +/// + +/** + * This module provides access to environment variables that are injected _statically_ into your bundle at build time and are limited to _private_ access. + * + * | | Runtime | Build time | + * | ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ | + * | Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) | + * | Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) | + * + * Static environment variables are [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env` at build time and then statically injected into your bundle at build time, enabling optimisations like dead code elimination. + * + * **_Private_ access:** + * + * - This module cannot be imported into client-side code + * - This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured) + * + * For example, given the following build time environment: + * + * ```env + * ENVIRONMENT=production + * PUBLIC_BASE_URL=http://site.com + * ``` + * + * With the default `publicPrefix` and `privatePrefix`: + * + * ```ts + * import { ENVIRONMENT, PUBLIC_BASE_URL } from '$env/static/private'; + * + * console.log(ENVIRONMENT); // => "production" + * console.log(PUBLIC_BASE_URL); // => throws error during build + * ``` + * + * The above values will be the same _even if_ different values for `ENVIRONMENT` or `PUBLIC_BASE_URL` are set at runtime, as they are statically replaced in your code with their build time values. + */ +declare module '$env/static/private' { + export const SHELL: string; + export const npm_command: string; + export const LSCOLORS: string; + export const SESSION_MANAGER: string; + export const QT_ACCESSIBILITY: string; + export const COLORTERM: string; + export const XDG_CONFIG_DIRS: string; + export const LESS: string; + export const XDG_SESSION_PATH: string; + export const GNOME_DESKTOP_SESSION_ID: string; + export const GTK_IM_MODULE: string; + export const QT_IM_MODULES: string; + export const GNOME_KEYRING_CONTROL: string; + export const LANGUAGE: string; + export const NODE: string; + export const SSH_AUTH_SOCK: string; + export const AGENT: string; + export const npm_config_local_prefix: string; + export const XMODIFIERS: string; + export const DESKTOP_SESSION: string; + export const GTK_MODULES: string; + export const XDG_SEAT: string; + export const PWD: string; + export const XDG_SESSION_DESKTOP: string; + export const LOGNAME: string; + export const XDG_SESSION_TYPE: string; + export const GPG_AGENT_INFO: string; + export const _: string; + export const XAUTHORITY: string; + export const XDG_GREETER_DATA_DIR: string; + export const GDM_LANG: string; + export const HOME: string; + export const OPENCODE: string; + export const LANG: string; + export const LS_COLORS: string; + export const XDG_CURRENT_DESKTOP: string; + export const npm_package_version: string; + export const VTE_VERSION: string; + export const DEBEMAIL: string; + export const XDG_SEAT_PATH: string; + export const GNOME_TERMINAL_SCREEN: string; + export const CLUTTER_IM_MODULE: string; + export const MFLAGS: string; + export const npm_lifecycle_script: string; + export const XDG_SESSION_CLASS: string; + export const MAKEFLAGS: string; + export const TERM: string; + export const npm_package_name: string; + export const ZSH: string; + export const GTK_OVERLAY_SCROLLING: string; + export const LIBVIRT_DEFAULT_URI: string; + export const USER: string; + export const GNOME_TERMINAL_SERVICE: string; + export const DISPLAY: string; + export const npm_lifecycle_event: string; + export const SHLVL: string; + export const PAGER: string; + export const MAKELEVEL: string; + export const QT_IM_MODULE: string; + export const XDG_VTNR: string; + export const XDG_SESSION_ID: string; + export const npm_config_user_agent: string; + export const npm_execpath: string; + export const XDG_RUNTIME_DIR: string; + export const npm_package_json: string; + export const BUN_INSTALL: string; + export const EMAIL: string; + export const GTK3_MODULES: string; + export const XDG_DATA_DIRS: string; + export const PATH: string; + export const GDMSESSION: string; + export const DBUS_SESSION_BUS_ADDRESS: string; + export const THOR_MERGE: string; + export const npm_node_execpath: string; + export const OLDPWD: string; + export const NODE_ENV: string; +} + +/** + * This module provides access to environment variables that are injected _statically_ into your bundle at build time and are _publicly_ accessible. + * + * | | Runtime | Build time | + * | ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ | + * | Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) | + * | Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) | + * + * Static environment variables are [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env` at build time and then statically injected into your bundle at build time, enabling optimisations like dead code elimination. + * + * **_Public_ access:** + * + * - This module _can_ be imported into client-side code + * - **Only** variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`) are included + * + * For example, given the following build time environment: + * + * ```env + * ENVIRONMENT=production + * PUBLIC_BASE_URL=http://site.com + * ``` + * + * With the default `publicPrefix` and `privatePrefix`: + * + * ```ts + * import { ENVIRONMENT, PUBLIC_BASE_URL } from '$env/static/public'; + * + * console.log(ENVIRONMENT); // => throws error during build + * console.log(PUBLIC_BASE_URL); // => "http://site.com" + * ``` + * + * The above values will be the same _even if_ different values for `ENVIRONMENT` or `PUBLIC_BASE_URL` are set at runtime, as they are statically replaced in your code with their build time values. + */ +declare module '$env/static/public' { + +} + +/** + * This module provides access to environment variables set _dynamically_ at runtime and that are limited to _private_ access. + * + * | | Runtime | Build time | + * | ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ | + * | Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) | + * | Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) | + * + * Dynamic environment variables are defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/main/packages/adapter-node) (or running [`vite preview`](https://svelte.dev/docs/kit/cli)), this is equivalent to `process.env`. + * + * **_Private_ access:** + * + * - This module cannot be imported into client-side code + * - This module includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured) + * + * > [!NOTE] In `dev`, `$env/dynamic` includes environment variables from `.env`. In `prod`, this behavior will depend on your adapter. + * + * > [!NOTE] To get correct types, environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed: + * > + * > ```env + * > MY_FEATURE_FLAG= + * > ``` + * > + * > You can override `.env` values from the command line like so: + * > + * > ```sh + * > MY_FEATURE_FLAG="enabled" npm run dev + * > ``` + * + * For example, given the following runtime environment: + * + * ```env + * ENVIRONMENT=production + * PUBLIC_BASE_URL=http://site.com + * ``` + * + * With the default `publicPrefix` and `privatePrefix`: + * + * ```ts + * import { env } from '$env/dynamic/private'; + * + * console.log(env.ENVIRONMENT); // => "production" + * console.log(env.PUBLIC_BASE_URL); // => undefined + * ``` + */ +declare module '$env/dynamic/private' { + export const env: { + SHELL: string; + npm_command: string; + LSCOLORS: string; + SESSION_MANAGER: string; + QT_ACCESSIBILITY: string; + COLORTERM: string; + XDG_CONFIG_DIRS: string; + LESS: string; + XDG_SESSION_PATH: string; + GNOME_DESKTOP_SESSION_ID: string; + GTK_IM_MODULE: string; + QT_IM_MODULES: string; + GNOME_KEYRING_CONTROL: string; + LANGUAGE: string; + NODE: string; + SSH_AUTH_SOCK: string; + AGENT: string; + npm_config_local_prefix: string; + XMODIFIERS: string; + DESKTOP_SESSION: string; + GTK_MODULES: string; + XDG_SEAT: string; + PWD: string; + XDG_SESSION_DESKTOP: string; + LOGNAME: string; + XDG_SESSION_TYPE: string; + GPG_AGENT_INFO: string; + _: string; + XAUTHORITY: string; + XDG_GREETER_DATA_DIR: string; + GDM_LANG: string; + HOME: string; + OPENCODE: string; + LANG: string; + LS_COLORS: string; + XDG_CURRENT_DESKTOP: string; + npm_package_version: string; + VTE_VERSION: string; + DEBEMAIL: string; + XDG_SEAT_PATH: string; + GNOME_TERMINAL_SCREEN: string; + CLUTTER_IM_MODULE: string; + MFLAGS: string; + npm_lifecycle_script: string; + XDG_SESSION_CLASS: string; + MAKEFLAGS: string; + TERM: string; + npm_package_name: string; + ZSH: string; + GTK_OVERLAY_SCROLLING: string; + LIBVIRT_DEFAULT_URI: string; + USER: string; + GNOME_TERMINAL_SERVICE: string; + DISPLAY: string; + npm_lifecycle_event: string; + SHLVL: string; + PAGER: string; + MAKELEVEL: string; + QT_IM_MODULE: string; + XDG_VTNR: string; + XDG_SESSION_ID: string; + npm_config_user_agent: string; + npm_execpath: string; + XDG_RUNTIME_DIR: string; + npm_package_json: string; + BUN_INSTALL: string; + EMAIL: string; + GTK3_MODULES: string; + XDG_DATA_DIRS: string; + PATH: string; + GDMSESSION: string; + DBUS_SESSION_BUS_ADDRESS: string; + THOR_MERGE: string; + npm_node_execpath: string; + OLDPWD: string; + NODE_ENV: string; + [key: `PUBLIC_${string}`]: undefined; + [key: `${string}`]: string | undefined; + } +} + +/** + * This module provides access to environment variables set _dynamically_ at runtime and that are _publicly_ accessible. + * + * | | Runtime | Build time | + * | ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ | + * | Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) | + * | Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) | + * + * Dynamic environment variables are defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/main/packages/adapter-node) (or running [`vite preview`](https://svelte.dev/docs/kit/cli)), this is equivalent to `process.env`. + * + * **_Public_ access:** + * + * - This module _can_ be imported into client-side code + * - **Only** variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`) are included + * + * > [!NOTE] In `dev`, `$env/dynamic` includes environment variables from `.env`. In `prod`, this behavior will depend on your adapter. + * + * > [!NOTE] To get correct types, environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed: + * > + * > ```env + * > MY_FEATURE_FLAG= + * > ``` + * > + * > You can override `.env` values from the command line like so: + * > + * > ```sh + * > MY_FEATURE_FLAG="enabled" npm run dev + * > ``` + * + * For example, given the following runtime environment: + * + * ```env + * ENVIRONMENT=production + * PUBLIC_BASE_URL=http://example.com + * ``` + * + * With the default `publicPrefix` and `privatePrefix`: + * + * ```ts + * import { env } from '$env/dynamic/public'; + * console.log(env.ENVIRONMENT); // => undefined, not public + * console.log(env.PUBLIC_BASE_URL); // => "http://example.com" + * ``` + * + * ``` + * + * ``` + */ +declare module '$env/dynamic/public' { + export const env: { + [key: `PUBLIC_${string}`]: string | undefined; + } +} diff --git a/frontend/.svelte-kit/generated/client-optimized/app.js b/frontend/.svelte-kit/generated/client-optimized/app.js new file mode 100644 index 0000000..77fc2a6 --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/app.js @@ -0,0 +1,53 @@ +export { matchers } from './matchers.js'; + +export const nodes = [ + () => import('./nodes/0'), + () => import('./nodes/1'), + () => import('./nodes/2'), + () => import('./nodes/3'), + () => import('./nodes/4'), + () => import('./nodes/5'), + () => import('./nodes/6'), + () => import('./nodes/7'), + () => import('./nodes/8'), + () => import('./nodes/9'), + () => import('./nodes/10'), + () => import('./nodes/11'), + () => import('./nodes/12'), + () => import('./nodes/13'), + () => import('./nodes/14') +]; + +export const server_loads = []; + +export const dictionary = { + "/": [2], + "/aliases": [3], + "/auth/change-password": [4], + "/auth/dashboard": [5], + "/auth/forgot": [6], + "/auth/login": [7], + "/domains": [8], + "/domains/[name]": [9], + "/domains/[name]/aliases": [10], + "/domains/[name]/users": [11], + "/logs": [12], + "/queue": [13], + "/users": [14] + }; + +export const hooks = { + handleError: (({ error }) => { console.error(error) }), + + reroute: (() => {}), + transport: {} +}; + +export const decoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.decode])); +export const encoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.encode])); + +export const hash = false; + +export const decode = (type, value) => decoders[type](value); + +export { default as root } from '../root.js'; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/matchers.js b/frontend/.svelte-kit/generated/client-optimized/matchers.js new file mode 100644 index 0000000..f6bd30a --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/matchers.js @@ -0,0 +1 @@ +export const matchers = {}; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/0.js b/frontend/.svelte-kit/generated/client-optimized/nodes/0.js new file mode 100644 index 0000000..fed1375 --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/0.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/+layout.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/1.js b/frontend/.svelte-kit/generated/client-optimized/nodes/1.js new file mode 100644 index 0000000..bf58bad --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/1.js @@ -0,0 +1 @@ +export { default as component } from "../../../../node_modules/@sveltejs/kit/src/runtime/components/svelte-5/error.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/10.js b/frontend/.svelte-kit/generated/client-optimized/nodes/10.js new file mode 100644 index 0000000..6e3e843 --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/10.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/domains/[name]/aliases/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/11.js b/frontend/.svelte-kit/generated/client-optimized/nodes/11.js new file mode 100644 index 0000000..5d78636 --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/11.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/domains/[name]/users/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/12.js b/frontend/.svelte-kit/generated/client-optimized/nodes/12.js new file mode 100644 index 0000000..74546b8 --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/12.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/logs/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/13.js b/frontend/.svelte-kit/generated/client-optimized/nodes/13.js new file mode 100644 index 0000000..2c7481c --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/13.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/queue/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/14.js b/frontend/.svelte-kit/generated/client-optimized/nodes/14.js new file mode 100644 index 0000000..81499df --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/14.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/users/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/2.js b/frontend/.svelte-kit/generated/client-optimized/nodes/2.js new file mode 100644 index 0000000..1cb4f85 --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/2.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/3.js b/frontend/.svelte-kit/generated/client-optimized/nodes/3.js new file mode 100644 index 0000000..282cdf9 --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/3.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/aliases/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/4.js b/frontend/.svelte-kit/generated/client-optimized/nodes/4.js new file mode 100644 index 0000000..38113d5 --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/4.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/auth/change-password/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/5.js b/frontend/.svelte-kit/generated/client-optimized/nodes/5.js new file mode 100644 index 0000000..8fbcc40 --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/5.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/auth/dashboard/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/6.js b/frontend/.svelte-kit/generated/client-optimized/nodes/6.js new file mode 100644 index 0000000..c3e6677 --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/6.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/auth/forgot/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/7.js b/frontend/.svelte-kit/generated/client-optimized/nodes/7.js new file mode 100644 index 0000000..3e6b791 --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/7.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/auth/login/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/8.js b/frontend/.svelte-kit/generated/client-optimized/nodes/8.js new file mode 100644 index 0000000..7ddef3d --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/8.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/domains/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client-optimized/nodes/9.js b/frontend/.svelte-kit/generated/client-optimized/nodes/9.js new file mode 100644 index 0000000..8c3dbb9 --- /dev/null +++ b/frontend/.svelte-kit/generated/client-optimized/nodes/9.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/domains/[name]/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/app.js b/frontend/.svelte-kit/generated/client/app.js new file mode 100644 index 0000000..77fc2a6 --- /dev/null +++ b/frontend/.svelte-kit/generated/client/app.js @@ -0,0 +1,53 @@ +export { matchers } from './matchers.js'; + +export const nodes = [ + () => import('./nodes/0'), + () => import('./nodes/1'), + () => import('./nodes/2'), + () => import('./nodes/3'), + () => import('./nodes/4'), + () => import('./nodes/5'), + () => import('./nodes/6'), + () => import('./nodes/7'), + () => import('./nodes/8'), + () => import('./nodes/9'), + () => import('./nodes/10'), + () => import('./nodes/11'), + () => import('./nodes/12'), + () => import('./nodes/13'), + () => import('./nodes/14') +]; + +export const server_loads = []; + +export const dictionary = { + "/": [2], + "/aliases": [3], + "/auth/change-password": [4], + "/auth/dashboard": [5], + "/auth/forgot": [6], + "/auth/login": [7], + "/domains": [8], + "/domains/[name]": [9], + "/domains/[name]/aliases": [10], + "/domains/[name]/users": [11], + "/logs": [12], + "/queue": [13], + "/users": [14] + }; + +export const hooks = { + handleError: (({ error }) => { console.error(error) }), + + reroute: (() => {}), + transport: {} +}; + +export const decoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.decode])); +export const encoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.encode])); + +export const hash = false; + +export const decode = (type, value) => decoders[type](value); + +export { default as root } from '../root.js'; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/matchers.js b/frontend/.svelte-kit/generated/client/matchers.js new file mode 100644 index 0000000..f6bd30a --- /dev/null +++ b/frontend/.svelte-kit/generated/client/matchers.js @@ -0,0 +1 @@ +export const matchers = {}; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/0.js b/frontend/.svelte-kit/generated/client/nodes/0.js new file mode 100644 index 0000000..fed1375 --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/0.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/+layout.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/1.js b/frontend/.svelte-kit/generated/client/nodes/1.js new file mode 100644 index 0000000..bf58bad --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/1.js @@ -0,0 +1 @@ +export { default as component } from "../../../../node_modules/@sveltejs/kit/src/runtime/components/svelte-5/error.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/10.js b/frontend/.svelte-kit/generated/client/nodes/10.js new file mode 100644 index 0000000..6e3e843 --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/10.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/domains/[name]/aliases/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/11.js b/frontend/.svelte-kit/generated/client/nodes/11.js new file mode 100644 index 0000000..5d78636 --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/11.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/domains/[name]/users/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/12.js b/frontend/.svelte-kit/generated/client/nodes/12.js new file mode 100644 index 0000000..74546b8 --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/12.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/logs/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/13.js b/frontend/.svelte-kit/generated/client/nodes/13.js new file mode 100644 index 0000000..2c7481c --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/13.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/queue/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/14.js b/frontend/.svelte-kit/generated/client/nodes/14.js new file mode 100644 index 0000000..81499df --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/14.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/users/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/2.js b/frontend/.svelte-kit/generated/client/nodes/2.js new file mode 100644 index 0000000..1cb4f85 --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/2.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/3.js b/frontend/.svelte-kit/generated/client/nodes/3.js new file mode 100644 index 0000000..282cdf9 --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/3.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/aliases/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/4.js b/frontend/.svelte-kit/generated/client/nodes/4.js new file mode 100644 index 0000000..38113d5 --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/4.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/auth/change-password/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/5.js b/frontend/.svelte-kit/generated/client/nodes/5.js new file mode 100644 index 0000000..8fbcc40 --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/5.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/auth/dashboard/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/6.js b/frontend/.svelte-kit/generated/client/nodes/6.js new file mode 100644 index 0000000..c3e6677 --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/6.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/auth/forgot/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/7.js b/frontend/.svelte-kit/generated/client/nodes/7.js new file mode 100644 index 0000000..3e6b791 --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/7.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/auth/login/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/8.js b/frontend/.svelte-kit/generated/client/nodes/8.js new file mode 100644 index 0000000..7ddef3d --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/8.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/domains/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/client/nodes/9.js b/frontend/.svelte-kit/generated/client/nodes/9.js new file mode 100644 index 0000000..8c3dbb9 --- /dev/null +++ b/frontend/.svelte-kit/generated/client/nodes/9.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/domains/[name]/+page.svelte"; \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/root.js b/frontend/.svelte-kit/generated/root.js new file mode 100644 index 0000000..4d1e892 --- /dev/null +++ b/frontend/.svelte-kit/generated/root.js @@ -0,0 +1,3 @@ +import { asClassComponent } from 'svelte/legacy'; +import Root from './root.svelte'; +export default asClassComponent(Root); \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/root.svelte b/frontend/.svelte-kit/generated/root.svelte new file mode 100644 index 0000000..0795183 --- /dev/null +++ b/frontend/.svelte-kit/generated/root.svelte @@ -0,0 +1,68 @@ + + + + +{#if constructors[1]} + {@const Pyramid_0 = constructors[0]} + + + + + + +{:else} + {@const Pyramid_0 = constructors[0]} + + + +{/if} + +{#if mounted} +
+ {#if navigated} + {title} + {/if} +
+{/if} \ No newline at end of file diff --git a/frontend/.svelte-kit/generated/server/internal.js b/frontend/.svelte-kit/generated/server/internal.js new file mode 100644 index 0000000..1c18a42 --- /dev/null +++ b/frontend/.svelte-kit/generated/server/internal.js @@ -0,0 +1,54 @@ + +import root from '../root.js'; +import { set_building, set_prerendering } from '__sveltekit/environment'; +import { set_assets } from '$app/paths/internal/server'; +import { set_manifest, set_read_implementation } from '__sveltekit/server'; +import { set_private_env, set_public_env } from '../../../node_modules/@sveltejs/kit/src/runtime/shared-server.js'; + +export const options = { + app_template_contains_nonce: false, + async: false, + csp: {"mode":"auto","directives":{"upgrade-insecure-requests":false,"block-all-mixed-content":false},"reportOnly":{"upgrade-insecure-requests":false,"block-all-mixed-content":false}}, + csrf_check_origin: true, + csrf_trusted_origins: [], + embedded: false, + env_public_prefix: 'PUBLIC_', + env_private_prefix: '', + hash_routing: false, + hooks: null, // added lazily, via `get_hooks` + preload_strategy: "modulepreload", + root, + service_worker: false, + service_worker_options: undefined, + server_error_boundaries: false, + templates: { + app: ({ head, body, assets, nonce, env }) => "\n\n \n \n \n \n " + head + "\n \n \n
" + body + "
\n \n\n", + error: ({ status, message }) => "\n\n\t\n\t\t\n\t\t" + message + "\n\n\t\t\n\t\n\t\n\t\t
\n\t\t\t" + status + "\n\t\t\t
\n\t\t\t\t

" + message + "

\n\t\t\t
\n\t\t
\n\t\n\n" + }, + version_hash: "63i6zh" +}; + +export async function get_hooks() { + let handle; + let handleFetch; + let handleError; + let handleValidationError; + let init; + + + let reroute; + let transport; + + + return { + handle, + handleFetch, + handleError, + handleValidationError, + init, + reroute, + transport + }; +} + +export { set_assets, set_building, set_manifest, set_prerendering, set_private_env, set_public_env, set_read_implementation }; diff --git a/frontend/.svelte-kit/non-ambient.d.ts b/frontend/.svelte-kit/non-ambient.d.ts new file mode 100644 index 0000000..7a0a5ab --- /dev/null +++ b/frontend/.svelte-kit/non-ambient.d.ts @@ -0,0 +1,58 @@ + +// this file is generated — do not edit it + + +declare module "svelte/elements" { + export interface HTMLAttributes { + 'data-sveltekit-keepfocus'?: true | '' | 'off' | undefined | null; + 'data-sveltekit-noscroll'?: true | '' | 'off' | undefined | null; + 'data-sveltekit-preload-code'?: + | true + | '' + | 'eager' + | 'viewport' + | 'hover' + | 'tap' + | 'off' + | undefined + | null; + 'data-sveltekit-preload-data'?: true | '' | 'hover' | 'tap' | 'off' | undefined | null; + 'data-sveltekit-reload'?: true | '' | 'off' | undefined | null; + 'data-sveltekit-replacestate'?: true | '' | 'off' | undefined | null; + } +} + +export {}; + + +declare module "$app/types" { + type MatcherParam = M extends (param : string) => param is (infer U extends string) ? U : string; + + export interface AppTypes { + RouteId(): "/" | "/aliases" | "/auth" | "/auth/change-password" | "/auth/dashboard" | "/auth/forgot" | "/auth/login" | "/domains" | "/domains/[name]" | "/domains/[name]/aliases" | "/domains/[name]/users" | "/logs" | "/queue" | "/users"; + RouteParams(): { + "/domains/[name]": { name: string }; + "/domains/[name]/aliases": { name: string }; + "/domains/[name]/users": { name: string } + }; + LayoutParams(): { + "/": { name?: string }; + "/aliases": Record; + "/auth": Record; + "/auth/change-password": Record; + "/auth/dashboard": Record; + "/auth/forgot": Record; + "/auth/login": Record; + "/domains": { name?: string }; + "/domains/[name]": { name: string }; + "/domains/[name]/aliases": { name: string }; + "/domains/[name]/users": { name: string }; + "/logs": Record; + "/queue": Record; + "/users": Record + }; + Pathname(): "/" | "/aliases" | "/auth/change-password" | "/auth/dashboard" | "/auth/forgot" | "/auth/login" | "/domains" | `/domains/${string}` & {} | `/domains/${string}/aliases` & {} | `/domains/${string}/users` & {} | "/logs" | "/queue" | "/users"; + ResolvedPathname(): `${"" | `/${string}`}${ReturnType}`; + Asset(): "/favicon.png" | string & {}; + } +} \ No newline at end of file diff --git a/frontend/.svelte-kit/output/client/.vite/manifest.json b/frontend/.svelte-kit/output/client/.vite/manifest.json new file mode 100644 index 0000000..29c6da2 --- /dev/null +++ b/frontend/.svelte-kit/output/client/.vite/manifest.json @@ -0,0 +1,424 @@ +{ + ".svelte-kit/generated/client-optimized/app.js": { + "file": "_app/immutable/entry/app.BI_Sozkn.js", + "name": "entry/app", + "src": ".svelte-kit/generated/client-optimized/app.js", + "isEntry": true, + "imports": [ + "_DtGl34IE.js", + "_n1byU5WW.js", + "_CJv7FbHz.js", + "_DR7h53-u.js", + "_-EcHSJia.js", + "_B3ZK_jYJ.js" + ], + "dynamicImports": [ + ".svelte-kit/generated/client-optimized/nodes/0.js", + ".svelte-kit/generated/client-optimized/nodes/1.js", + ".svelte-kit/generated/client-optimized/nodes/2.js", + ".svelte-kit/generated/client-optimized/nodes/3.js", + ".svelte-kit/generated/client-optimized/nodes/4.js", + ".svelte-kit/generated/client-optimized/nodes/5.js", + ".svelte-kit/generated/client-optimized/nodes/6.js", + ".svelte-kit/generated/client-optimized/nodes/7.js", + ".svelte-kit/generated/client-optimized/nodes/8.js", + ".svelte-kit/generated/client-optimized/nodes/9.js", + ".svelte-kit/generated/client-optimized/nodes/10.js", + ".svelte-kit/generated/client-optimized/nodes/11.js", + ".svelte-kit/generated/client-optimized/nodes/12.js", + ".svelte-kit/generated/client-optimized/nodes/13.js", + ".svelte-kit/generated/client-optimized/nodes/14.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/0.js": { + "file": "_app/immutable/nodes/0.D3wXY_0K.js", + "name": "nodes/0", + "src": ".svelte-kit/generated/client-optimized/nodes/0.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DtGl34IE.js", + "_B3ZK_jYJ.js", + "_n1byU5WW.js", + "_-EcHSJia.js", + "_B7kAneMc.js", + "_RKc8iKz_.js" + ], + "css": [ + "_app/immutable/assets/0.DkgBtk4_.css" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/1.js": { + "file": "_app/immutable/nodes/1.Dgii_8lh.js", + "name": "nodes/1", + "src": ".svelte-kit/generated/client-optimized/nodes/1.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DFRBE_Uq.js", + "_DtGl34IE.js", + "_n1byU5WW.js", + "_CfgL3m1f.js", + "_RKc8iKz_.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/10.js": { + "file": "_app/immutable/nodes/10.BvOkMiuT.js", + "name": "nodes/10", + "src": ".svelte-kit/generated/client-optimized/nodes/10.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DtGl34IE.js", + "_B3ZK_jYJ.js", + "_n1byU5WW.js", + "_-EcHSJia.js", + "_ecAlPOj8.js", + "_e1WBZ7UL.js", + "_ayyTDfEa.js", + "_B7kAneMc.js" + ], + "css": [ + "_app/immutable/assets/10.Qar-kS8x.css" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/11.js": { + "file": "_app/immutable/nodes/11.DnvWFHPj.js", + "name": "nodes/11", + "src": ".svelte-kit/generated/client-optimized/nodes/11.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DtGl34IE.js", + "_B3ZK_jYJ.js", + "_n1byU5WW.js", + "_-EcHSJia.js", + "_ecAlPOj8.js", + "_e1WBZ7UL.js", + "_ayyTDfEa.js", + "_B7kAneMc.js" + ], + "css": [ + "_app/immutable/assets/11.D38O3Xxc.css" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/12.js": { + "file": "_app/immutable/nodes/12.CRx3MqWn.js", + "name": "nodes/12", + "src": ".svelte-kit/generated/client-optimized/nodes/12.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DtGl34IE.js", + "_n1byU5WW.js", + "_-EcHSJia.js", + "_ecAlPOj8.js", + "_e1WBZ7UL.js", + "_BYrNiJ2z.js", + "_ayyTDfEa.js" + ], + "css": [ + "_app/immutable/assets/12.DQdHIvb_.css" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/13.js": { + "file": "_app/immutable/nodes/13.CB7FlS8h.js", + "name": "nodes/13", + "src": ".svelte-kit/generated/client-optimized/nodes/13.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DtGl34IE.js", + "_n1byU5WW.js", + "_-EcHSJia.js", + "_ecAlPOj8.js" + ], + "css": [ + "_app/immutable/assets/13.DnP_H9DZ.css" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/14.js": { + "file": "_app/immutable/nodes/14.CFDiiGpK.js", + "name": "nodes/14", + "src": ".svelte-kit/generated/client-optimized/nodes/14.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DFRBE_Uq.js", + "_DR7h53-u.js", + "_DtGl34IE.js", + "_RKc8iKz_.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/2.js": { + "file": "_app/immutable/nodes/2.BMCUuUxB.js", + "name": "nodes/2", + "src": ".svelte-kit/generated/client-optimized/nodes/2.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DR7h53-u.js", + "_DtGl34IE.js", + "_n1byU5WW.js", + "_-EcHSJia.js", + "_BYrNiJ2z.js" + ], + "css": [ + "_app/immutable/assets/2.By2d6Bxb.css" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/3.js": { + "file": "_app/immutable/nodes/3.CFDiiGpK.js", + "name": "nodes/3", + "src": ".svelte-kit/generated/client-optimized/nodes/3.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DFRBE_Uq.js", + "_DR7h53-u.js", + "_DtGl34IE.js", + "_RKc8iKz_.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/4.js": { + "file": "_app/immutable/nodes/4.YDL696B2.js", + "name": "nodes/4", + "src": ".svelte-kit/generated/client-optimized/nodes/4.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DR7h53-u.js", + "_DtGl34IE.js", + "_n1byU5WW.js", + "_-EcHSJia.js", + "_e1WBZ7UL.js", + "_ayyTDfEa.js", + "_RKc8iKz_.js" + ], + "css": [ + "_app/immutable/assets/4.CG2X--Z8.css" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/5.js": { + "file": "_app/immutable/nodes/5.DHfYhdex.js", + "name": "nodes/5", + "src": ".svelte-kit/generated/client-optimized/nodes/5.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DR7h53-u.js", + "_DtGl34IE.js", + "_n1byU5WW.js", + "_-EcHSJia.js", + "_RKc8iKz_.js" + ], + "css": [ + "_app/immutable/assets/5.YbbfqdJp.css" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/6.js": { + "file": "_app/immutable/nodes/6.BiQ3_GJa.js", + "name": "nodes/6", + "src": ".svelte-kit/generated/client-optimized/nodes/6.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DtGl34IE.js", + "_n1byU5WW.js", + "_-EcHSJia.js", + "_e1WBZ7UL.js", + "_ayyTDfEa.js", + "_CfgL3m1f.js" + ], + "css": [ + "_app/immutable/assets/6.w_qTFDpy.css" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/7.js": { + "file": "_app/immutable/nodes/7.BEIquz8f.js", + "name": "nodes/7", + "src": ".svelte-kit/generated/client-optimized/nodes/7.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DtGl34IE.js", + "_n1byU5WW.js", + "_-EcHSJia.js", + "_e1WBZ7UL.js", + "_ayyTDfEa.js", + "_RKc8iKz_.js" + ], + "css": [ + "_app/immutable/assets/7.Bq7myTre.css" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/8.js": { + "file": "_app/immutable/nodes/8.D4QctIPu.js", + "name": "nodes/8", + "src": ".svelte-kit/generated/client-optimized/nodes/8.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DtGl34IE.js", + "_n1byU5WW.js", + "_-EcHSJia.js", + "_ecAlPOj8.js", + "_e1WBZ7UL.js", + "_ayyTDfEa.js" + ], + "css": [ + "_app/immutable/assets/8.neQUdyXe.css" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/9.js": { + "file": "_app/immutable/nodes/9.DflEy3LG.js", + "name": "nodes/9", + "src": ".svelte-kit/generated/client-optimized/nodes/9.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_CJv7FbHz.js", + "_DtGl34IE.js", + "_B3ZK_jYJ.js", + "_n1byU5WW.js", + "_-EcHSJia.js", + "_e1WBZ7UL.js", + "_B7kAneMc.js" + ], + "css": [ + "_app/immutable/assets/9.Ci0QlAaW.css" + ] + }, + "_-EcHSJia.js": { + "file": "_app/immutable/chunks/-EcHSJia.js", + "name": "if", + "imports": [ + "_DtGl34IE.js" + ] + }, + "_B3ZK_jYJ.js": { + "file": "_app/immutable/chunks/B3ZK_jYJ.js", + "name": "store", + "imports": [ + "_BX-b5t2l.js", + "_DtGl34IE.js" + ] + }, + "_B7kAneMc.js": { + "file": "_app/immutable/chunks/B7kAneMc.js", + "name": "stores", + "imports": [ + "_RKc8iKz_.js" + ] + }, + "_BX-b5t2l.js": { + "file": "_app/immutable/chunks/BX-b5t2l.js", + "name": "index", + "imports": [ + "_DtGl34IE.js" + ] + }, + "_BYrNiJ2z.js": { + "file": "_app/immutable/chunks/BYrNiJ2z.js", + "name": "class", + "imports": [ + "_DtGl34IE.js" + ] + }, + "_CJv7FbHz.js": { + "file": "_app/immutable/chunks/CJv7FbHz.js", + "name": "disclose-version", + "imports": [ + "_DtGl34IE.js" + ] + }, + "_CfgL3m1f.js": { + "file": "_app/immutable/chunks/CfgL3m1f.js", + "name": "state.svelte", + "imports": [ + "_DR7h53-u.js", + "_DtGl34IE.js", + "_BX-b5t2l.js" + ] + }, + "_DFRBE_Uq.js": { + "file": "_app/immutable/chunks/DFRBE_Uq.js", + "name": "legacy", + "imports": [ + "_DtGl34IE.js" + ] + }, + "_DR7h53-u.js": { + "file": "_app/immutable/chunks/DR7h53-u.js", + "name": "index-client", + "imports": [ + "_DtGl34IE.js" + ] + }, + "_DtGl34IE.js": { + "file": "_app/immutable/chunks/DtGl34IE.js", + "name": "runtime" + }, + "_RKc8iKz_.js": { + "file": "_app/immutable/chunks/RKc8iKz_.js", + "name": "entry", + "imports": [ + "_DtGl34IE.js", + "_BX-b5t2l.js", + "_CfgL3m1f.js" + ] + }, + "_ayyTDfEa.js": { + "file": "_app/immutable/chunks/ayyTDfEa.js", + "name": "input", + "imports": [ + "_DtGl34IE.js" + ] + }, + "_e1WBZ7UL.js": { + "file": "_app/immutable/chunks/e1WBZ7UL.js", + "name": "attributes", + "imports": [ + "_DtGl34IE.js" + ] + }, + "_ecAlPOj8.js": { + "file": "_app/immutable/chunks/ecAlPOj8.js", + "name": "each", + "imports": [ + "_DtGl34IE.js" + ] + }, + "_n1byU5WW.js": { + "file": "_app/immutable/chunks/n1byU5WW.js", + "name": "render", + "imports": [ + "_DtGl34IE.js", + "_CJv7FbHz.js" + ] + }, + "node_modules/@sveltejs/kit/src/runtime/client/entry.js": { + "file": "_app/immutable/entry/start.tprRzko2.js", + "name": "entry/start", + "src": "node_modules/@sveltejs/kit/src/runtime/client/entry.js", + "isEntry": true, + "imports": [ + "_RKc8iKz_.js", + "_CfgL3m1f.js" + ] + } +} \ No newline at end of file diff --git a/frontend/.svelte-kit/output/client/_app/immutable/assets/0.DkgBtk4_.css b/frontend/.svelte-kit/output/client/_app/immutable/assets/0.DkgBtk4_.css new file mode 100644 index 0000000..792fc3f --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/assets/0.DkgBtk4_.css @@ -0,0 +1 @@ +.loading.svelte-12qhfyh{min-height:100vh;display:flex;align-items:center;justify-content:center;font-size:1.2rem;color:#666}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,sans-serif;background:#f5f5f5}.app.svelte-12qhfyh{min-height:100vh}header.svelte-12qhfyh{background:#2c3e50;color:#fff;padding:.75rem 2rem;display:flex;align-items:center;gap:2rem;flex-wrap:wrap}h1.svelte-12qhfyh{margin:0;font-size:1.25rem}nav.svelte-12qhfyh{display:flex;gap:.5rem;flex:1}nav.svelte-12qhfyh a:where(.svelte-12qhfyh){color:#ecf0f1;text-decoration:none;padding:.5rem 1rem;border-radius:4px;font-size:.9rem;transition:background .2s}nav.svelte-12qhfyh a:where(.svelte-12qhfyh):hover{background:#34495e}main.svelte-12qhfyh{padding:2rem;max-width:1400px;margin:0 auto}.user-menu.svelte-12qhfyh{display:flex;align-items:center;gap:1rem;font-size:.9rem}.user-menu.svelte-12qhfyh span:where(.svelte-12qhfyh){color:#ecf0f1}.user-menu.svelte-12qhfyh a:where(.svelte-12qhfyh){color:#ecf0f1;text-decoration:none;padding:.375rem .75rem;border:1px solid #7f8c8d;border-radius:4px;font-size:.85rem}.user-menu.svelte-12qhfyh a:where(.svelte-12qhfyh):hover{background:#34495e}.user-menu.svelte-12qhfyh button:where(.svelte-12qhfyh){background:transparent;border:1px solid #7f8c8d;color:#ecf0f1;padding:.375rem .75rem;border-radius:4px;cursor:pointer;font-size:.85rem}.user-menu.svelte-12qhfyh button:where(.svelte-12qhfyh):hover{background:#34495e} diff --git a/frontend/.svelte-kit/output/client/_app/immutable/assets/10.Qar-kS8x.css b/frontend/.svelte-kit/output/client/_app/immutable/assets/10.Qar-kS8x.css new file mode 100644 index 0000000..bbde314 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/assets/10.Qar-kS8x.css @@ -0,0 +1 @@ +.header.svelte-15uyvzd{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem;gap:1rem}.back.svelte-15uyvzd{color:#3498db;text-decoration:none;font-size:.9rem}.back.svelte-15uyvzd:hover{text-decoration:underline}.header.svelte-15uyvzd h2:where(.svelte-15uyvzd){flex:1;margin:0}table.svelte-15uyvzd{width:100%;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}th.svelte-15uyvzd,td.svelte-15uyvzd{padding:1rem;text-align:left;border-bottom:1px solid #eee}th.svelte-15uyvzd{background:#f8f9fa;font-weight:600}button.svelte-15uyvzd{padding:.5rem 1rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff}button.danger.svelte-15uyvzd{background:#e74c3c}.modal-backdrop.svelte-15uyvzd{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;border:none;cursor:pointer;z-index:100}.modal.svelte-15uyvzd{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;padding:2rem;border-radius:8px;min-width:400px;z-index:101}.modal.svelte-15uyvzd h3:where(.svelte-15uyvzd){margin-top:0}.modal.svelte-15uyvzd form:where(.svelte-15uyvzd){display:flex;flex-direction:column;gap:1rem}.modal.svelte-15uyvzd label:where(.svelte-15uyvzd){display:flex;flex-direction:column;gap:.5rem}.modal.svelte-15uyvzd input:where(.svelte-15uyvzd){padding:.5rem;border:1px solid #ddd;border-radius:4px}.actions.svelte-15uyvzd{display:flex;gap:1rem;justify-content:flex-end} diff --git a/frontend/.svelte-kit/output/client/_app/immutable/assets/11.D38O3Xxc.css b/frontend/.svelte-kit/output/client/_app/immutable/assets/11.D38O3Xxc.css new file mode 100644 index 0000000..14eb981 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/assets/11.D38O3Xxc.css @@ -0,0 +1 @@ +.header.svelte-oa5z6t{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem;gap:1rem}.back.svelte-oa5z6t{color:#3498db;text-decoration:none;font-size:.9rem}.back.svelte-oa5z6t:hover{text-decoration:underline}.header.svelte-oa5z6t h2:where(.svelte-oa5z6t){flex:1;margin:0}table.svelte-oa5z6t{width:100%;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}th.svelte-oa5z6t,td.svelte-oa5z6t{padding:1rem;text-align:left;border-bottom:1px solid #eee}th.svelte-oa5z6t{background:#f8f9fa;font-weight:600}button.svelte-oa5z6t{padding:.5rem 1rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff}button.danger.svelte-oa5z6t{background:#e74c3c}.modal-backdrop.svelte-oa5z6t{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;border:none;cursor:pointer;z-index:100}.modal.svelte-oa5z6t{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;padding:2rem;border-radius:8px;min-width:400px;z-index:101}.modal.svelte-oa5z6t h3:where(.svelte-oa5z6t){margin-top:0}.modal.svelte-oa5z6t form:where(.svelte-oa5z6t){display:flex;flex-direction:column;gap:1rem}.modal.svelte-oa5z6t label:where(.svelte-oa5z6t){display:flex;flex-direction:column;gap:.5rem}.modal.svelte-oa5z6t input:where(.svelte-oa5z6t){padding:.5rem;border:1px solid #ddd;border-radius:4px}.actions.svelte-oa5z6t{display:flex;gap:1rem;justify-content:flex-end} diff --git a/frontend/.svelte-kit/output/client/_app/immutable/assets/12.DQdHIvb_.css b/frontend/.svelte-kit/output/client/_app/immutable/assets/12.DQdHIvb_.css new file mode 100644 index 0000000..3f6263d --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/assets/12.DQdHIvb_.css @@ -0,0 +1 @@ +.header.svelte-1lsf4ps{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem;flex-wrap:wrap;gap:1rem}.controls.svelte-1lsf4ps{display:flex;gap:1rem;align-items:center}.controls.svelte-1lsf4ps label:where(.svelte-1lsf4ps){display:flex;align-items:center;gap:.5rem}.controls.svelte-1lsf4ps select:where(.svelte-1lsf4ps),.controls.svelte-1lsf4ps input:where(.svelte-1lsf4ps){padding:.5rem;border:1px solid #ddd;border-radius:4px}button.svelte-1lsf4ps{padding:.5rem 1rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff}.log-container.svelte-1lsf4ps{background:#1a1a2e;color:#eee;padding:1rem;border-radius:8px;max-height:600px;overflow-y:auto;font-family:monospace;font-size:.85rem}.log-entry.svelte-1lsf4ps{padding:.25rem 0;border-bottom:1px solid #333}.log-entry.svelte-1lsf4ps:last-child{border-bottom:none}.timestamp.svelte-1lsf4ps{color:#888;margin-right:.5rem}.priority.svelte-1lsf4ps{margin-right:.5rem;font-weight:700}.log-entry.error.svelte-1lsf4ps .priority:where(.svelte-1lsf4ps){color:#e74c3c}.log-entry.warning.svelte-1lsf4ps .priority:where(.svelte-1lsf4ps){color:#f39c12}.log-entry.info.svelte-1lsf4ps .priority:where(.svelte-1lsf4ps){color:#3498db}.error.svelte-1lsf4ps{color:#e74c3c} diff --git a/frontend/.svelte-kit/output/client/_app/immutable/assets/13.DnP_H9DZ.css b/frontend/.svelte-kit/output/client/_app/immutable/assets/13.DnP_H9DZ.css new file mode 100644 index 0000000..5caa7e3 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/assets/13.DnP_H9DZ.css @@ -0,0 +1 @@ +.header.svelte-qegr5c{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem}table.svelte-qegr5c{width:100%;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}th.svelte-qegr5c,td.svelte-qegr5c{padding:.75rem;text-align:left;border-bottom:1px solid #eee;font-size:.9rem}th.svelte-qegr5c{background:#f8f9fa;font-weight:600}.id.svelte-qegr5c{font-family:monospace;font-size:.8rem}.reason.svelte-qegr5c{color:#e74c3c}button.svelte-qegr5c{padding:.25rem .5rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff;font-size:.8rem;margin-right:.25rem}button.danger.svelte-qegr5c{background:#e74c3c}.error.svelte-qegr5c{color:#e74c3c} diff --git a/frontend/.svelte-kit/output/client/_app/immutable/assets/2.By2d6Bxb.css b/frontend/.svelte-kit/output/client/_app/immutable/assets/2.By2d6Bxb.css new file mode 100644 index 0000000..f2098ff --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/assets/2.By2d6Bxb.css @@ -0,0 +1 @@ +.stats-grid.svelte-1uha8ag{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:1.5rem;margin-top:2rem}.stat-card.svelte-1uha8ag{background:#fff;padding:1.5rem;border-radius:8px;box-shadow:0 2px 4px #0000001a;text-align:center}.stat-card.warning.svelte-1uha8ag{border:2px solid #e74c3c}.stat-card.svelte-1uha8ag h3:where(.svelte-1uha8ag){font-size:2.5rem;margin:0;color:#2c3e50}.stat-card.svelte-1uha8ag p:where(.svelte-1uha8ag){margin:.5rem 0 0;color:#7f8c8d}.warning.svelte-1uha8ag h3:where(.svelte-1uha8ag){color:#e74c3c} diff --git a/frontend/.svelte-kit/output/client/_app/immutable/assets/4.CG2X--Z8.css b/frontend/.svelte-kit/output/client/_app/immutable/assets/4.CG2X--Z8.css new file mode 100644 index 0000000..ea80681 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/assets/4.CG2X--Z8.css @@ -0,0 +1 @@ +.page-container.svelte-imhhoo{min-height:100vh;background:#f5f7fa}.header.svelte-imhhoo{background:#fff;padding:1rem 2rem;box-shadow:0 2px 4px #0000001a}.header-content.svelte-imhhoo{max-width:800px;margin:0 auto;display:flex;justify-content:space-between;align-items:center}.header.svelte-imhhoo h1:where(.svelte-imhhoo){margin:0;font-size:1.5rem;color:#2c3e50}.user-info.svelte-imhhoo{display:flex;align-items:center;gap:1rem}.logout.svelte-imhhoo{padding:.5rem 1rem;background:#e74c3c;color:#fff;border:none;border-radius:4px;cursor:pointer}.content.svelte-imhhoo{max-width:500px;margin:2rem auto;padding:2rem;background:#fff;border-radius:12px;box-shadow:0 2px 8px #0000001a}.error.svelte-imhhoo{background:#fee;color:#c00;padding:.75rem;border-radius:4px;margin-bottom:1rem}.success.svelte-imhhoo{background:#efe;color:#060;padding:.75rem;border-radius:4px;margin-bottom:1rem}form.svelte-imhhoo{display:flex;flex-direction:column;gap:1rem}label.svelte-imhhoo{display:flex;flex-direction:column;gap:.5rem;font-weight:500;color:#555}input.svelte-imhhoo{padding:.75rem;border:1px solid #ddd;border-radius:6px;font-size:1rem}input.svelte-imhhoo:focus{outline:none;border-color:#667eea;box-shadow:0 0 0 3px #667eea1a}button.svelte-imhhoo{padding:.75rem;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;border-radius:6px;font-size:1rem;font-weight:500;cursor:pointer;margin-top:.5rem}button.svelte-imhhoo:hover:not(:disabled){opacity:.9}button.svelte-imhhoo:disabled{opacity:.6;cursor:not-allowed}.links.svelte-imhhoo{margin-top:1.5rem;text-align:center}.links.svelte-imhhoo a:where(.svelte-imhhoo){color:#667eea;text-decoration:none}.links.svelte-imhhoo a:where(.svelte-imhhoo):hover{text-decoration:underline} diff --git a/frontend/.svelte-kit/output/client/_app/immutable/assets/5.YbbfqdJp.css b/frontend/.svelte-kit/output/client/_app/immutable/assets/5.YbbfqdJp.css new file mode 100644 index 0000000..47f5e83 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/assets/5.YbbfqdJp.css @@ -0,0 +1 @@ +.page-container.svelte-1s1ktxm{min-height:100vh;background:#f5f7fa}.header.svelte-1s1ktxm{background:#fff;padding:1rem 2rem;box-shadow:0 2px 4px #0000001a;display:flex;justify-content:space-between;align-items:center}.header.svelte-1s1ktxm h1:where(.svelte-1s1ktxm){margin:0;font-size:1.5rem;color:#2c3e50}.user-info.svelte-1s1ktxm{display:flex;align-items:center;gap:1rem}.logout.svelte-1s1ktxm{padding:.5rem 1rem;background:#e74c3c;color:#fff;border:none;border-radius:4px;cursor:pointer}.content.svelte-1s1ktxm{max-width:800px;margin:2rem auto;padding:0 1rem}.card.svelte-1s1ktxm{background:#fff;padding:1.5rem;border-radius:12px;box-shadow:0 2px 8px #0000001a;margin-bottom:1.5rem}.card.svelte-1s1ktxm h2:where(.svelte-1s1ktxm){margin:0 0 1rem;color:#2c3e50;font-size:1.2rem}.info-row.svelte-1s1ktxm{display:flex;padding:.75rem 0;border-bottom:1px solid #eee}.info-row.svelte-1s1ktxm:last-child{border-bottom:none}.label.svelte-1s1ktxm{font-weight:500;color:#666;width:120px}.value.svelte-1s1ktxm{color:#2c3e50}.actions.svelte-1s1ktxm{display:flex;gap:1rem;flex-wrap:wrap}.action-btn.svelte-1s1ktxm{padding:.75rem 1.5rem;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;text-decoration:none;border-radius:6px;font-weight:500;transition:opacity .2s}.action-btn.svelte-1s1ktxm:hover{opacity:.9} diff --git a/frontend/.svelte-kit/output/client/_app/immutable/assets/6.w_qTFDpy.css b/frontend/.svelte-kit/output/client/_app/immutable/assets/6.w_qTFDpy.css new file mode 100644 index 0000000..4f2c471 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/assets/6.w_qTFDpy.css @@ -0,0 +1 @@ +.login-container.svelte-15sczaz{min-height:100vh;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#667eea,#764ba2);padding:1rem}.login-card.svelte-15sczaz{background:#fff;padding:2rem;border-radius:12px;box-shadow:0 10px 40px #0003;width:100%;max-width:400px}h1.svelte-15sczaz{text-align:center;margin:0 0 1rem;color:#2c3e50}.info.svelte-15sczaz{color:#666;text-align:center;margin-bottom:1.5rem;font-size:.9rem}.error.svelte-15sczaz{background:#fee;color:#c00;padding:.75rem;border-radius:4px;margin-bottom:1rem;font-size:.9rem}.success.svelte-15sczaz{background:#efe;color:#060;padding:1rem;border-radius:4px;margin-bottom:1rem;text-align:center}.success.svelte-15sczaz p:where(.svelte-15sczaz){margin:.5rem 0}form.svelte-15sczaz{display:flex;flex-direction:column;gap:1rem}label.svelte-15sczaz{display:flex;flex-direction:column;gap:.5rem;font-weight:500;color:#555}input.svelte-15sczaz{padding:.75rem;border:1px solid #ddd;border-radius:6px;font-size:1rem}input.svelte-15sczaz:focus{outline:none;border-color:#667eea;box-shadow:0 0 0 3px #667eea1a}button.svelte-15sczaz{padding:.75rem;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;border-radius:6px;font-size:1rem;font-weight:500;cursor:pointer;transition:opacity .2s}button.svelte-15sczaz:hover:not(:disabled){opacity:.9}button.svelte-15sczaz:disabled{opacity:.6;cursor:not-allowed}.links.svelte-15sczaz{margin-top:1.5rem;text-align:center;padding-top:1rem;border-top:1px solid #eee}.links.svelte-15sczaz a:where(.svelte-15sczaz){color:#667eea;text-decoration:none;font-size:.9rem}.links.svelte-15sczaz a:where(.svelte-15sczaz):hover{text-decoration:underline} diff --git a/frontend/.svelte-kit/output/client/_app/immutable/assets/7.Bq7myTre.css b/frontend/.svelte-kit/output/client/_app/immutable/assets/7.Bq7myTre.css new file mode 100644 index 0000000..5e0a5f3 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/assets/7.Bq7myTre.css @@ -0,0 +1 @@ +.login-container.svelte-1i2smtp{min-height:100vh;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#2c3e50,#34495e)}.login-card.svelte-1i2smtp{background:#fff;padding:3rem;border-radius:12px;box-shadow:0 10px 40px #0003;width:100%;max-width:400px}h1.svelte-1i2smtp{margin:0;text-align:center;color:#2c3e50;font-size:2rem}.subtitle.svelte-1i2smtp{text-align:center;color:#7f8c8d;margin:.5rem 0 2rem}.error.svelte-1i2smtp{background:#fee;border:1px solid #fcc;color:#c00;padding:.75rem;border-radius:4px;margin-bottom:1rem;font-size:.9rem}form.svelte-1i2smtp{display:flex;flex-direction:column;gap:1.25rem}label.svelte-1i2smtp{display:flex;flex-direction:column;gap:.5rem;font-weight:500;color:#2c3e50}input.svelte-1i2smtp{padding:.75rem;border:1px solid #ddd;border-radius:6px;font-size:1rem;transition:border-color .2s}input.svelte-1i2smtp:focus{outline:none;border-color:#3498db}.forgot.svelte-1i2smtp{text-align:right;margin-top:-.5rem}.forgot.svelte-1i2smtp a:where(.svelte-1i2smtp){color:#3498db;text-decoration:none;font-size:.9rem}.forgot.svelte-1i2smtp a:where(.svelte-1i2smtp):hover{text-decoration:underline}button.svelte-1i2smtp{padding:.875rem;background:#3498db;color:#fff;border:none;border-radius:6px;font-size:1rem;font-weight:600;cursor:pointer;transition:background .2s;margin-top:.5rem}button.svelte-1i2smtp:hover:not(:disabled){background:#2980b9}button.svelte-1i2smtp:disabled{opacity:.7;cursor:not-allowed} diff --git a/frontend/.svelte-kit/output/client/_app/immutable/assets/8.neQUdyXe.css b/frontend/.svelte-kit/output/client/_app/immutable/assets/8.neQUdyXe.css new file mode 100644 index 0000000..b665553 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/assets/8.neQUdyXe.css @@ -0,0 +1 @@ +.header.svelte-83awcy{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem}table.svelte-83awcy{width:100%;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}th.svelte-83awcy,td.svelte-83awcy{padding:1rem;text-align:left;border-bottom:1px solid #eee}th.svelte-83awcy{background:#f8f9fa;font-weight:600}button.svelte-83awcy{padding:.5rem 1rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff}button.danger.svelte-83awcy{background:#e74c3c}.modal-backdrop.svelte-83awcy{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:100}.modal.svelte-83awcy{background:#fff;padding:2rem;border-radius:8px;min-width:400px}.modal.svelte-83awcy form:where(.svelte-83awcy){display:flex;flex-direction:column;gap:1rem}.modal.svelte-83awcy label:where(.svelte-83awcy){display:flex;flex-direction:column;gap:.5rem}.modal.svelte-83awcy input:where(.svelte-83awcy){padding:.5rem;border:1px solid #ddd;border-radius:4px}.actions.svelte-83awcy{display:flex;gap:1rem;justify-content:flex-end} diff --git a/frontend/.svelte-kit/output/client/_app/immutable/assets/9.Ci0QlAaW.css b/frontend/.svelte-kit/output/client/_app/immutable/assets/9.Ci0QlAaW.css new file mode 100644 index 0000000..6ef841b --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/assets/9.Ci0QlAaW.css @@ -0,0 +1 @@ +.header.svelte-lb8x40{margin-bottom:2rem}.back.svelte-lb8x40{display:inline-block;margin-bottom:1rem;color:#3498db;text-decoration:none}.back.svelte-lb8x40:hover{text-decoration:underline}.error.svelte-lb8x40{color:#e74c3c}.cards-grid.svelte-lb8x40{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:1.5rem}.card.svelte-lb8x40{background:#fff;padding:2rem;border-radius:8px;box-shadow:0 2px 4px #0000001a;text-align:center;text-decoration:none;color:inherit;transition:transform .2s,box-shadow .2s}.card.svelte-lb8x40:hover{transform:translateY(-2px);box-shadow:0 4px 8px #00000026}.card.svelte-lb8x40 h3:where(.svelte-lb8x40){font-size:3rem;margin:0;color:#3498db}.card.svelte-lb8x40 p:where(.svelte-lb8x40){margin:.5rem 0 0;color:#7f8c8d;font-size:1.1rem} diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/-EcHSJia.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/-EcHSJia.js new file mode 100644 index 0000000..ece78c0 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/-EcHSJia.js @@ -0,0 +1 @@ +var C=Object.defineProperty;var w=a=>{throw TypeError(a)};var D=(a,e,s)=>e in a?C(a,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):a[e]=s;var A=(a,e,s)=>D(a,typeof e!="symbol"?e+"":e,s),x=(a,e,s)=>e.has(a)||w("Cannot "+s);var t=(a,e,s)=>(x(a,e,"read from private field"),s?s.call(a):e.get(a)),u=(a,e,s)=>e.has(a)?w("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(a):e.set(a,s),E=(a,e,s,i)=>(x(a,e,"write to private field"),i?i.call(a,s):e.set(a,s),s);import{U as N,_ as g,V as R,o as F,E as M,c as S,h as k,A as B,Z as j,G as z,w as G,v as I,a9 as P,x as U,y as V,j as Z,z as T}from"./DtGl34IE.js";var d,l,c,p,v,m,b;class q{constructor(e,s=!0){A(this,"anchor");u(this,d,new Map);u(this,l,new Map);u(this,c,new Map);u(this,p,new Set);u(this,v,!0);u(this,m,e=>{if(t(this,d).has(e)){var s=t(this,d).get(e),i=t(this,l).get(s);if(i)N(i),t(this,p).delete(s);else{var n=t(this,c).get(s);n&&(t(this,l).set(s,n.effect),t(this,c).delete(s),n.fragment.lastChild.remove(),this.anchor.before(n.fragment),i=n.effect)}for(const[f,h]of t(this,d)){if(t(this,d).delete(f),f===e)break;const r=t(this,c).get(h);r&&(g(r.effect),t(this,c).delete(h))}for(const[f,h]of t(this,l)){if(f===s||t(this,p).has(f))continue;const r=()=>{if(Array.from(t(this,d).values()).includes(f)){var _=document.createDocumentFragment();j(h,_),_.append(F()),t(this,c).set(f,{effect:h,fragment:_})}else g(h);t(this,p).delete(f),t(this,l).delete(f)};t(this,v)||!i?(t(this,p).add(f),R(h,r,!1)):r()}}});u(this,b,e=>{t(this,d).delete(e);const s=Array.from(t(this,d).values());for(const[i,n]of t(this,c))s.includes(i)||(g(n.effect),t(this,c).delete(i))});this.anchor=e,E(this,v,s)}ensure(e,s){var i=S,n=z();if(s&&!t(this,l).has(e)&&!t(this,c).has(e))if(n){var f=document.createDocumentFragment(),h=F();f.append(h),t(this,c).set(e,{effect:M(()=>s(h)),fragment:f})}else t(this,l).set(e,M(()=>s(this.anchor)));if(t(this,d).set(i,e),n){for(const[r,o]of t(this,l))r===e?i.unskip_effect(o):i.skip_effect(o);for(const[r,o]of t(this,c))r===e?i.unskip_effect(o.effect):i.skip_effect(o.effect);i.oncommit(t(this,m)),i.ondiscard(t(this,b))}else k&&(this.anchor=B),t(this,m).call(this,i)}}d=new WeakMap,l=new WeakMap,c=new WeakMap,p=new WeakMap,v=new WeakMap,m=new WeakMap,b=new WeakMap;function K(a,e,s=!1){var i;k&&(i=B,I());var n=new q(a),f=s?P:0;function h(r,o){if(k){var _=U(i);if(r!==parseInt(_.substring(1))){var y=V();Z(y),n.anchor=y,T(!1),n.ensure(r,o),T(!0);return}}n.ensure(r,o)}G(()=>{var r=!1;e((o,_=0)=>{r=!0,h(_,o)}),r||h(-1,null)},f)}export{q as B,K as i}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/B3ZK_jYJ.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/B3ZK_jYJ.js new file mode 100644 index 0000000..e067bd4 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/B3ZK_jYJ.js @@ -0,0 +1 @@ +import{s as c,g as l}from"./BX-b5t2l.js";import{n as a,m as o,g as b,t as d,d as p,s as g}from"./DtGl34IE.js";let s=!1,i=Symbol();function m(e,u,r){const n=r[u]??(r[u]={store:null,source:o(void 0),unsubscribe:a});if(n.store!==e&&!(i in r))if(n.unsubscribe(),n.store=e??null,e==null)n.source.v=void 0,n.unsubscribe=a;else{var t=!0;n.unsubscribe=c(e,f=>{t?n.source.v=f:g(n.source,f)}),t=!1}return e&&i in r?l(e):b(n.source)}function y(){const e={};function u(){d(()=>{for(var r in e)e[r].unsubscribe();p(e,i,{enumerable:!1,value:!0})})}return[e,u]}function N(e){var u=s;try{return s=!1,[e(),s]}finally{s=u}}export{y as a,N as c,m as s}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/B7kAneMc.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/B7kAneMc.js new file mode 100644 index 0000000..6e13c31 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/B7kAneMc.js @@ -0,0 +1 @@ +import{s as e}from"./RKc8iKz_.js";const r=()=>{const s=e;return{page:{subscribe:s.page.subscribe},navigating:{subscribe:s.navigating.subscribe},updated:s.updated}},b={subscribe(s){return r().page.subscribe(s)}};export{b as p}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/BX-b5t2l.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/BX-b5t2l.js new file mode 100644 index 0000000..e3d342c --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/BX-b5t2l.js @@ -0,0 +1 @@ +import{n as o,u as a,ah as d}from"./DtGl34IE.js";function p(s,u,e){if(s==null)return u(void 0),o;const t=a(()=>s.subscribe(u,e));return t.unsubscribe?()=>t.unsubscribe():t}const i=[];function h(s,u=o){let e=null;const t=new Set;function c(r){if(d(s,r)&&(s=r,e)){const b=!i.length;for(const n of t)n[1](),i.push(n,s);if(b){for(let n=0;n{t.delete(n),t.size===0&&e&&(e(),e=null)}}return{set:c,update:f,subscribe:l}}function _(s){let u;return p(s,e=>u=e)(),u}export{_ as g,p as s,h as w}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/BYrNiJ2z.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/BYrNiJ2z.js new file mode 100644 index 0000000..7221eb2 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/BYrNiJ2z.js @@ -0,0 +1,2 @@ +import{h as c}from"./DtGl34IE.js";const a=[...` +\r\f \v\uFEFF`];function e(r,g,u){var f=r==null?"":""+r;if(g&&(f=f?f+" "+g:g),u){for(var t of Object.keys(u))if(u[t])f=f?f+" "+t:t;else if(f.length)for(var l=t.length,i=0;(i=f.indexOf(t,i))>=0;){var n=i+l;(i===0||a.includes(f[i-1]))&&(n===f.length||a.includes(f[n]))?f=(i===0?"":f.substring(0,i))+f.substring(n+1):i=n}}return f===""?null:f}function v(r,g,u,f,t,l){var i=r.__className;if(c||i!==u||i===void 0){var n=e(u,f,l);(!c||n!==r.getAttribute("class"))&&(n==null?r.removeAttribute("class"):r.className=n),r.__className=u}else if(l&&t!==l)for(var o in l){var s=!!l[o];(t==null||s!==!!t[o])&&r.classList.toggle(o,s)}return l}export{v as s}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CJv7FbHz.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/CJv7FbHz.js new file mode 100644 index 0000000..a809740 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/CJv7FbHz.js @@ -0,0 +1 @@ +import{am as p,o as u,an as c,k as l,ao as E,ap as g,aq as w,h as d,A as s,ar as y,v as N,as as A,j as M,at as x}from"./DtGl34IE.js";var f;const i=((f=globalThis==null?void 0:globalThis.window)==null?void 0:f.trustedTypes)&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:t=>t});function L(t){return(i==null?void 0:i.createHTML(t))??t}function b(t){var r=p("template");return r.innerHTML=L(t.replaceAll("","")),r.content}function n(t,r){var e=c;e.nodes===null&&(e.nodes={start:t,end:r,a:null,t:null})}function R(t,r){var e=(r&g)!==0,m=(r&w)!==0,a,v=!t.startsWith("");return()=>{if(d)return n(s,null),s;a===void 0&&(a=b(v?t:""+t),e||(a=l(a)));var o=m||E?document.importNode(a,!0):a.cloneNode(!0);if(e){var T=l(o),h=o.lastChild;n(T,h)}else n(o,o);return o}}function C(t=""){if(!d){var r=u(t+"");return n(r,r),r}var e=s;return e.nodeType!==A?(e.before(e=u()),M(e)):x(e),n(e,e),e}function I(){if(d)return n(s,null),s;var t=document.createDocumentFragment(),r=document.createComment(""),e=u();return t.append(r,e),n(r,e),t}function D(t,r){if(d){var e=c;(!(e.f&y)||e.nodes.end===null)&&(e.nodes.end=s),N();return}t!==null&&t.before(r)}const O="5";var _;typeof window<"u"&&((_=window.__svelte??(window.__svelte={})).v??(_.v=new Set)).add(O);export{D as a,n as b,I as c,R as f,C as t}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CfgL3m1f.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/CfgL3m1f.js new file mode 100644 index 0000000..ab5a7e3 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/CfgL3m1f.js @@ -0,0 +1 @@ +var I=t=>{throw TypeError(t)};var B=(t,e,n)=>e.has(t)||I("Cannot "+n);var a=(t,e,n)=>(B(t,e,"read from private field"),n?n.call(t):e.get(t)),c=(t,e,n)=>e.has(t)?I("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,n);import{o as N}from"./DR7h53-u.js";import{a0 as u,g as f,s as d}from"./DtGl34IE.js";import{w as Y}from"./BX-b5t2l.js";new URL("sveltekit-internal://");function oe(t,e){return t==="/"||e==="ignore"?t:e==="never"?t.endsWith("/")?t.slice(0,-1):t:e==="always"&&!t.endsWith("/")?t+"/":t}function ie(t){return t.split("%25").map(decodeURI).join("%25")}function le(t){for(const e in t)t[e]=decodeURIComponent(t[e]);return t}function ce({href:t}){return t.split("#")[0]}function W(...t){let e=5381;for(const n of t)if(typeof n=="string"){let r=n.length;for(;r;)e=e*33^n.charCodeAt(--r)}else if(ArrayBuffer.isView(n)){const r=new Uint8Array(n.buffer,n.byteOffset,n.byteLength);let s=r.length;for(;s;)e=e*33^r[--s]}else throw new TypeError("value must be a string or TypedArray");return(e>>>0).toString(36)}new TextEncoder;new TextDecoder;function X(t){const e=atob(t),n=new Uint8Array(e.length);for(let r=0;r((t instanceof Request?t.method:(e==null?void 0:e.method)||"GET")!=="GET"&&_.delete(U(t)),J(t,e));const _=new Map;function ue(t,e){const n=U(t,e),r=document.querySelector(n);if(r!=null&&r.textContent){r.remove();let{body:s,...l}=JSON.parse(r.textContent);const o=r.getAttribute("data-ttl");return o&&_.set(n,{body:s,init:l,ttl:1e3*Number(o)}),r.getAttribute("data-b64")!==null&&(s=X(s)),Promise.resolve(new Response(s,l))}return window.fetch(t,e)}function fe(t,e,n){if(_.size>0){const r=U(t,n),s=_.get(r);if(s){if(performance.now()o)}function s(o){n=!1,e.set(o)}function l(o){let i;return e.subscribe(h=>{(i===void 0||n&&h!==i)&&o(i=h)})}return{notify:r,set:s,subscribe:l}}const D={v:()=>{}};function Se(){const{set:t,subscribe:e}=Y(!1);let n;async function r(){clearTimeout(n);try{const s=await fetch(`${F}/_app/version.json`,{headers:{pragma:"no-cache","cache-control":"no-cache"}});if(!s.ok)return!1;const o=(await s.json()).version!==Q;return o&&(t(!0),D.v(),clearTimeout(n)),o}catch{return!1}}return{subscribe:e,check:r}}function Z(t,e,n){return t.origin!==q||!t.pathname.startsWith(e)?!0:n?t.pathname!==location.pathname:!1}function ke(t){}const H=new Set(["load","prerender","csr","ssr","trailingSlash","config"]);[...H];const ee=new Set([...H]);[...ee];let E,x,T;const te=N.toString().includes("$$")||/function \w+\(\) \{\}/.test(N.toString()),$="a:";var b,w,m,v,p,y,A,R,V,S,j,k,G;te?(E={data:{},form:null,error:null,params:{},route:{id:null},state:{},status:-1,url:new URL($)},x={current:null},T={current:!1}):(E=new(V=class{constructor(){c(this,b,u({}));c(this,w,u(null));c(this,m,u(null));c(this,v,u({}));c(this,p,u({id:null}));c(this,y,u({}));c(this,A,u(-1));c(this,R,u(new URL($)))}get data(){return f(a(this,b))}set data(e){d(a(this,b),e)}get form(){return f(a(this,w))}set form(e){d(a(this,w),e)}get error(){return f(a(this,m))}set error(e){d(a(this,m),e)}get params(){return f(a(this,v))}set params(e){d(a(this,v),e)}get route(){return f(a(this,p))}set route(e){d(a(this,p),e)}get state(){return f(a(this,y))}set state(e){d(a(this,y),e)}get status(){return f(a(this,A))}set status(e){d(a(this,A),e)}get url(){return f(a(this,R))}set url(e){d(a(this,R),e)}},b=new WeakMap,w=new WeakMap,m=new WeakMap,v=new WeakMap,p=new WeakMap,y=new WeakMap,A=new WeakMap,R=new WeakMap,V),x=new(j=class{constructor(){c(this,S,u(null))}get current(){return f(a(this,S))}set current(e){d(a(this,S),e)}},S=new WeakMap,j),T=new(G=class{constructor(){c(this,k,u(!1))}get current(){return f(a(this,k))}set current(e){d(a(this,k),e)}},k=new WeakMap,G),D.v=()=>T.current=!0);function Ie(t){Object.assign(E,t)}export{be as H,we as N,_e as P,ge as S,Ae as a,M as b,Se as c,ce as d,le as e,pe as f,ye as g,oe as h,Z as i,L as j,ie as k,de as l,fe as m,x as n,q as o,E as p,ue as q,me as r,ve as s,he as t,Re as u,Ie as v,ke as w}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/DFRBE_Uq.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/DFRBE_Uq.js new file mode 100644 index 0000000..aa5446f --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/DFRBE_Uq.js @@ -0,0 +1 @@ +import{aa as g,ab as d,a8 as l,u as b,ac as i,ad as m,g as p,ae as v,af as h,ag as k}from"./DtGl34IE.js";function x(t=!1){const a=g,e=a.l.u;if(!e)return;let o=()=>v(a.s);if(t){let n=0,s={};const _=h(()=>{let c=!1;const r=a.s;for(const f in r)r[f]!==s[f]&&(s[f]=r[f],c=!0);return c&&n++,n});o=()=>p(_)}e.b.length&&d(()=>{u(a,o),i(e.b)}),l(()=>{const n=b(()=>e.m.map(m));return()=>{for(const s of n)typeof s=="function"&&s()}}),e.a.length&&l(()=>{u(a,o),i(e.a)})}function u(t,a){if(t.l.s)for(const e of t.l.s)p(e);a()}k();export{x as i}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/DR7h53-u.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/DR7h53-u.js new file mode 100644 index 0000000..7c177f8 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/DR7h53-u.js @@ -0,0 +1 @@ +import{a8 as o,aa as t,ai as a,u as c}from"./DtGl34IE.js";function u(n){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function r(n){t===null&&u(),a&&t.l!==null?l(t).m.push(n):o(()=>{const e=c(n);if(typeof e=="function")return e})}function l(n){var e=n.l;return e.u??(e.u={a:[],b:[],m:[]})}export{r as o}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/DtGl34IE.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/DtGl34IE.js new file mode 100644 index 0000000..ac6b025 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/DtGl34IE.js @@ -0,0 +1 @@ +var ht=Object.defineProperty;var mn=e=>{throw TypeError(e)};var pt=(e,n,t)=>n in e?ht(e,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[n]=t;var ne=(e,n,t)=>pt(e,typeof n!="symbol"?n+"":n,t),$e=(e,n,t)=>n.has(e)||mn("Cannot "+t);var v=(e,n,t)=>($e(e,n,"read from private field"),t?t.call(e):n.get(e)),I=(e,n,t)=>n.has(e)?mn("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(e):n.set(e,t),Y=(e,n,t,r)=>($e(e,n,"write to private field"),r?r.call(e,t):n.set(e,t),t),q=(e,n,t)=>($e(e,n,"access private method"),t);var wt=Array.isArray,yt=Array.prototype.indexOf,Te=Array.prototype.includes,cr=Array.from,_r=Object.defineProperty,De=Object.getOwnPropertyDescriptor,Et=Object.getOwnPropertyDescriptors,gt=Object.prototype,mt=Array.prototype,Cn=Object.getPrototypeOf,Tn=Object.isExtensible;const Tt=()=>{};function vr(e){return e()}function bt(e){for(var n=0;n{e=r,n=s});return{promise:t,resolve:e,reject:n}}const T=2,be=4,Fe=8,Mn=1<<24,Q=16,V=32,ue=64,At=128,C=512,E=1024,O=2048,B=4096,H=8192,U=16384,he=32768,bn=1<<25,He=65536,An=1<<17,Rt=1<<18,Me=1<<19,jn=1<<20,dr=1<<25,oe=65536,Je=1<<21,un=1<<22,Z=1<<23,ie=Symbol("$state"),hr=Symbol("legacy props"),pr=Symbol(""),K=new class extends Error{constructor(){super(...arguments);ne(this,"name","StaleReactionError");ne(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}};var Pn;const yr=!!((Pn=globalThis.document)!=null&&Pn.contentType)&&globalThis.document.contentType.includes("xml"),ze=3,Ln=8;function St(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function Er(e,n,t){throw new Error("https://svelte.dev/e/each_key_duplicate")}function Ot(e){throw new Error("https://svelte.dev/e/effect_in_teardown")}function xt(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function Nt(e){throw new Error("https://svelte.dev/e/effect_orphan")}function kt(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function gr(){throw new Error("https://svelte.dev/e/hydration_failed")}function mr(e){throw new Error("https://svelte.dev/e/props_invalid_value")}function Dt(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function It(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function Pt(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function Tr(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}const br=1,Ar=2,Rr=16,Sr=1,Or=2,xr=4,Nr=8,kr=16,Dr=1,Ir=2,Ct="[",Ft="[!",Pr="[?",Mt="]",on={},b=Symbol(),jt="http://www.w3.org/1999/xhtml";function cn(e){console.warn("https://svelte.dev/e/hydration_mismatch")}function Cr(){console.warn("https://svelte.dev/e/select_multiple_invalid_value")}function Fr(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}let ce=!1;function Mr(e){ce=e}let m;function Ae(e){if(e===null)throw cn(),on;return m=e}function jr(){return Ae(ee(m))}function Lr(e){if(ce){if(ee(m)!==null)throw cn(),on;m=e}}function Yr(e=1){if(ce){for(var n=e,t=m;n--;)t=ee(t);m=t}}function qr(e=!0){for(var n=0,t=m;;){if(t.nodeType===Ln){var r=t.data;if(r===Mt){if(n===0)return t;n-=1}else(r===Ct||r===Ft||r[0]==="["&&!isNaN(Number(r.slice(1))))&&(n+=1)}var s=ee(t);e&&t.remove(),t=s}}function Hr(e){if(!e||e.nodeType!==Ln)throw cn(),on;return e.data}function Yn(e){return e===this.v}function Lt(e,n){return e!=e?n==n:e!==n||e!==null&&typeof e=="object"||typeof e=="function"}function qn(e){return!Lt(e,this.v)}let Xe=!1;function Ur(){Xe=!0}let S=null;function Ue(e){S=e}function Vr(e,n=!1,t){S={p:S,i:!1,c:null,e:null,s:e,x:null,r:w,l:Xe&&!n?{s:null,u:null,$:[]}:null}}function Br(e){var n=S,t=n.e;if(t!==null){n.e=null;for(var r of t)rt(r)}return n.i=!0,S=n.p,{}}function je(){return!Xe||S!==null&&S.l===null}let se=[];function Hn(){var e=se;se=[],bt(e)}function Rn(e){if(se.length===0&&!Ie){var n=se;queueMicrotask(()=>{n===se&&Hn()})}se.push(e)}function Yt(){for(;se.length>0;)Hn()}function qt(e){var n=w;if(n===null)return d.f|=Z,e;if(!(n.f&he)&&!(n.f&be))throw e;Ve(e,n)}function Ve(e,n){for(;n!==null;){if(n.f&At){if(!(n.f&he))throw e;try{n.b.error(e);return}catch(t){e=t}}n=n.parent}throw e}const Ht=-7169;function y(e,n){e.f=e.f&Ht|n}function _n(e){e.f&C||e.deps===null?y(e,E):y(e,B)}function Un(e){if(e!==null)for(const n of e)!(n.f&T)||!(n.f&oe)||(n.f^=oe,Un(n.deps))}function Ut(e,n,t){e.f&O?n.add(e):e.f&B&&t.add(e),Un(e.deps),y(e,E)}const te=new Set;let h=null,A=null,Qe=null,Ie=!1,Ze=!1,pe=null,Ye=null;var Sn=0;let Vt=1;var we,ye,Ee,ge,Ce,D,fe,z,X,me,R,en,nn,tn,rn,Vn;const Ke=class Ke{constructor(){I(this,R);ne(this,"id",Vt++);ne(this,"current",new Map);ne(this,"previous",new Map);I(this,we,new Set);I(this,ye,new Set);I(this,Ee,0);I(this,ge,0);I(this,Ce,null);I(this,D,[]);I(this,fe,new Set);I(this,z,new Set);I(this,X,new Map);ne(this,"is_fork",!1);I(this,me,!1)}skip_effect(n){v(this,X).has(n)||v(this,X).set(n,{d:[],m:[]})}unskip_effect(n){var t=v(this,X).get(n);if(t){v(this,X).delete(n);for(var r of t.d)y(r,O),this.schedule(r);for(r of t.m)y(r,B),this.schedule(r)}}capture(n,t){t!==b&&!this.previous.has(n)&&this.previous.set(n,t),n.f&Z||(this.current.set(n,n.v),A==null||A.set(n,n.v))}activate(){h=this}deactivate(){h=null,A=null}flush(){try{Ze=!0,h=this,q(this,R,nn).call(this)}finally{Sn=0,Qe=null,pe=null,Ye=null,Ze=!1,h=null,A=null,W.clear()}}discard(){for(const n of v(this,ye))n(this);v(this,ye).clear(),te.delete(this)}increment(n){Y(this,Ee,v(this,Ee)+1),n&&Y(this,ge,v(this,ge)+1)}decrement(n,t){Y(this,Ee,v(this,Ee)-1),n&&Y(this,ge,v(this,ge)-1),!(v(this,me)||t)&&(Y(this,me,!0),Rn(()=>{Y(this,me,!1),this.flush()}))}transfer_effects(n,t){for(const r of n)v(this,fe).add(r);for(const r of t)v(this,z).add(r);n.clear(),t.clear()}oncommit(n){v(this,we).add(n)}ondiscard(n){v(this,ye).add(n)}settled(){return(v(this,Ce)??Y(this,Ce,Fn())).promise}static ensure(){if(h===null){const n=h=new Ke;Ze||(te.add(h),Ie||Rn(()=>{h===n&&n.flush()}))}return h}apply(){{A=null;return}}schedule(n){var s;if(Qe=n,(s=n.b)!=null&&s.is_pending&&n.f&(be|Fe|Mn)&&!(n.f&he)){n.b.defer_effect(n);return}for(var t=n;t.parent!==null;){t=t.parent;var r=t.f;if(pe!==null&&t===w&&(d===null||!(d.f&T)))return;if(r&(ue|V)){if(!(r&E))return;t.f^=E}}v(this,D).push(t)}};we=new WeakMap,ye=new WeakMap,Ee=new WeakMap,ge=new WeakMap,Ce=new WeakMap,D=new WeakMap,fe=new WeakMap,z=new WeakMap,X=new WeakMap,me=new WeakMap,R=new WeakSet,en=function(){return this.is_fork||v(this,ge)>0},nn=function(){var a,i;if(Sn++>1e3&&(te.delete(this),Gt()),!q(this,R,en).call(this)){for(const l of v(this,fe))v(this,z).delete(l),y(l,O),this.schedule(l);for(const l of v(this,z))y(l,B),this.schedule(l)}const n=v(this,D);Y(this,D,[]),this.apply();var t=pe=[],r=[],s=Ye=[];for(const l of n)try{q(this,R,tn).call(this,l,t,r)}catch(o){throw zn(l),o}if(h=null,s.length>0){var f=Ke.ensure();for(const l of s)f.schedule(l)}if(pe=null,Ye=null,q(this,R,en).call(this)){q(this,R,rn).call(this,r),q(this,R,rn).call(this,t);for(const[l,o]of v(this,X))Kn(l,o)}else{v(this,Ee)===0&&te.delete(this),v(this,fe).clear(),v(this,z).clear();for(const l of v(this,we))l(this);v(this,we).clear(),On(r),On(t),(a=v(this,Ce))==null||a.resolve()}var u=h;if(v(this,D).length>0){const l=u??(u=this);v(l,D).push(...v(this,D).filter(o=>!v(l,D).includes(o)))}u!==null&&(te.add(u),q(i=u,R,nn).call(i)),te.has(this)||q(this,R,Vn).call(this)},tn=function(n,t,r){n.f^=E;for(var s=n.first;s!==null;){var f=s.f,u=(f&(V|ue))!==0,a=u&&(f&E)!==0,i=a||(f&H)!==0||v(this,X).has(s);if(!i&&s.fn!==null){u?s.f^=E:f&be?t.push(s):Le(s)&&(f&Q&&v(this,z).add(s),Se(s));var l=s.first;if(l!==null){s=l;continue}}for(;s!==null;){var o=s.next;if(o!==null){s=o;break}s=s.parent}}},rn=function(n){for(var t=0;t!this.current.has(o));if(r.length===0)n&&l.discard();else if(t.length>0){l.activate();var s=new Set,f=new Map;for(var u of t)Bn(u,r,s,f);if(v(l,D).length>0){l.apply();for(var a of v(l,D))q(i=l,R,tn).call(i,a,[],[]);Y(l,D,[])}l.deactivate()}}};let _e=Ke;function Bt(e){var n=Ie;Ie=!0;try{for(var t;;){if(Yt(),h===null)return t;h.flush()}}finally{Ie=n}}function Gt(){try{kt()}catch(e){Ve(e,Qe)}}let j=null;function On(e){var n=e.length;if(n!==0){for(var t=0;t0)){W.clear();for(const s of j){if(s.f&(U|H))continue;const f=[s];let u=s.parent;for(;u!==null;)j.has(u)&&(j.delete(u),f.push(u)),u=u.parent;for(let a=f.length-1;a>=0;a--){const i=f[a];i.f&(U|H)||Se(i)}}j.clear()}}j=null}}function Bn(e,n,t,r){if(!t.has(e)&&(t.add(e),e.reactions!==null))for(const s of e.reactions){const f=s.f;f&T?Bn(s,n,t,r):f&(un|Q)&&!(f&O)&&Gn(s,n,r)&&(y(s,O),vn(s))}}function Gn(e,n,t){const r=t.get(e);if(r!==void 0)return r;if(e.deps!==null)for(const s of e.deps){if(Te.call(n,s))return!0;if(s.f&T&&Gn(s,n,t))return t.set(s,!0),!0}return t.set(e,!1),!1}function vn(e){h.schedule(e)}function Kn(e,n){if(!(e.f&V&&e.f&E)){e.f&O?n.d.push(e):e.f&B&&n.m.push(e),y(e,E);for(var t=e.first;t!==null;)Kn(t,n),t=t.next}}function zn(e){y(e,E);for(var n=e.first;n!==null;)zn(n),n=n.next}function Kt(e,n,t,r){const s=je()?dn:$t;var f=e.filter(c=>!c.settled);if(t.length===0&&f.length===0){r(n.map(s));return}var u=w,a=zt(),i=f.length===1?f[0].promise:f.length>1?Promise.all(f.map(c=>c.promise)):null;function l(c){a();try{r(c)}catch(g){u.f&U||Ve(g,u)}Be()}if(t.length===0){i.then(()=>l(n.map(s)));return}var o=Xn();function _(){Promise.all(t.map(c=>Xt(c))).then(c=>l([...n.map(s),...c])).catch(c=>Ve(c,u)).finally(()=>o())}i?i.then(()=>{a(),_(),Be()}):_()}function zt(){var e=w,n=d,t=S,r=h;return function(f=!0){Re(e),J(n),Ue(t),f&&!(e.f&U)&&(r==null||r.activate(),r==null||r.apply())}}function Be(e=!0){Re(null),J(null),Ue(null),e&&(h==null||h.deactivate())}function Xn(){var e=w.b,n=h,t=e.is_rendered();return e.update_pending_count(1,n),n.increment(t),(r=!1)=>{e.update_pending_count(-1,n),n.decrement(t,r)}}function dn(e){var n=T|O,t=d!==null&&d.f&T?d:null;return w!==null&&(w.f|=Me),{ctx:S,deps:null,effects:null,equals:Yn,f:n,fn:e,reactions:null,rv:0,v:b,wv:0,parent:t??w,ac:null}}function Xt(e,n,t){let r=w;r===null&&St();var s=void 0,f=pn(b),u=!d,a=new Map;return sr(()=>{var g;var i=w,l=Fn();s=l.promise;try{Promise.resolve(e()).then(l.resolve,l.reject).finally(Be)}catch(p){l.reject(p),Be()}var o=h;if(u){if(i.f&he)var _=Xn();if(r.b.is_rendered())(g=a.get(o))==null||g.reject(K),a.delete(o);else{for(const p of a.values())p.reject(K);a.clear()}a.set(o,l)}const c=(p,M=void 0)=>{if(_){var x=M===K;_(x)}if(!(M===K||i.f&U)){if(o.activate(),M)f.f|=Z,ln(f,M);else{f.f&Z&&(f.f^=Z),ln(f,p);for(const[Oe,xe]of a){if(a.delete(Oe),Oe===o)break;xe.reject(K)}}o.deactivate()}};l.promise.then(c,p=>c(null,p||"unknown"))}),rr(()=>{for(const i of a.values())i.reject(K)}),new Promise(i=>{function l(o){function _(){o===s?i(f):l(s)}o.then(_,_)}l(s)})}function Gr(e){const n=dn(e);return at(n),n}function $t(e){const n=dn(e);return n.equals=qn,n}function Zt(e){var n=e.effects;if(n!==null){e.effects=null;for(var t=0;t0&&!Wn&&Qt()}return n}function Qt(){Wn=!1;for(const e of sn)e.f&E&&y(e,B),Le(e)&&Se(e);sn.clear()}function We(e){re(e,e.v+1)}function Jn(e,n,t){var r=e.reactions;if(r!==null)for(var s=je(),f=r.length,u=0;u{if(ae===f)return a();var i=d,l=ae;J(null),In(f);var o=a();return J(i),In(l),o};return r&&t.set("length",$(e.length)),new Proxy(e,{defineProperty(a,i,l){(!("value"in l)||l.configurable===!1||l.enumerable===!1||l.writable===!1)&&Dt();var o=t.get(i);return o===void 0?u(()=>{var _=$(l.value);return t.set(i,_),_}):re(o,l.value,!0),!0},deleteProperty(a,i){var l=t.get(i);if(l===void 0){if(i in a){const o=u(()=>$(b));t.set(i,o),We(s)}}else re(l,b),We(s);return!0},get(a,i,l){var g;if(i===ie)return e;var o=t.get(i),_=i in a;if(o===void 0&&(!_||(g=De(a,i))!=null&&g.writable)&&(o=u(()=>{var p=Ne(_?a[i]:b),M=$(p);return M}),t.set(i,o)),o!==void 0){var c=ke(o);return c===b?void 0:c}return Reflect.get(a,i,l)},getOwnPropertyDescriptor(a,i){var l=Reflect.getOwnPropertyDescriptor(a,i);if(l&&"value"in l){var o=t.get(i);o&&(l.value=ke(o))}else if(l===void 0){var _=t.get(i),c=_==null?void 0:_.v;if(_!==void 0&&c!==b)return{enumerable:!0,configurable:!0,value:c,writable:!0}}return l},has(a,i){var c;if(i===ie)return!0;var l=t.get(i),o=l!==void 0&&l.v!==b||Reflect.has(a,i);if(l!==void 0||w!==null&&(!o||(c=De(a,i))!=null&&c.writable)){l===void 0&&(l=u(()=>{var g=o?Ne(a[i]):b,p=$(g);return p}),t.set(i,l));var _=ke(l);if(_===b)return!1}return o},set(a,i,l,o){var gn;var _=t.get(i),c=i in a;if(r&&i==="length")for(var g=l;g<_.v;g+=1){var p=t.get(g+"");p!==void 0?re(p,b):g in a&&(p=u(()=>$(b)),t.set(g+"",p))}if(_===void 0)(!c||(gn=De(a,i))!=null&&gn.writable)&&(_=u(()=>$(void 0)),re(_,Ne(l)),t.set(i,_));else{c=_.v!==b;var M=u(()=>Ne(l));re(_,M)}var x=Reflect.getOwnPropertyDescriptor(a,i);if(x!=null&&x.set&&x.set.call(o,l),!c){if(r&&typeof i=="string"){var Oe=t.get("length"),xe=Number(i);Number.isInteger(xe)&&xe>=Oe.v&&re(Oe,xe+1)}We(s)}return!0},ownKeys(a){ke(s);var i=Reflect.ownKeys(a).filter(_=>{var c=t.get(_);return c===void 0||c.v!==b});for(var[l,o]of t)o.v!==b&&!(l in a)&&i.push(l);return i},setPrototypeOf(){It()}})}function xn(e){try{if(e!==null&&typeof e=="object"&&ie in e)return e[ie]}catch{}return e}function zr(e,n){return Object.is(xn(e),xn(n))}var Nn,er,Qn,et;function Xr(){if(Nn===void 0){Nn=window,er=/Firefox/.test(navigator.userAgent);var e=Element.prototype,n=Node.prototype,t=Text.prototype;Qn=De(n,"firstChild").get,et=De(n,"nextSibling").get,Tn(e)&&(e.__click=void 0,e.__className=void 0,e.__attributes=null,e.__style=void 0,e.__e=void 0),Tn(t)&&(t.__t=void 0)}}function Ge(e=""){return document.createTextNode(e)}function fn(e){return Qn.call(e)}function ee(e){return et.call(e)}function $r(e,n){if(!ce)return fn(e);var t=fn(m);if(t===null)t=m.appendChild(Ge());else if(n&&t.nodeType!==ze){var r=Ge();return t==null||t.before(r),Ae(r),r}return n&&wn(t),Ae(t),t}function Zr(e,n=!1){if(!ce){var t=fn(e);return t instanceof Comment&&t.data===""?ee(t):t}if(n){if((m==null?void 0:m.nodeType)!==ze){var r=Ge();return m==null||m.before(r),Ae(r),r}wn(m)}return m}function Wr(e,n=1,t=!1){let r=ce?m:e;for(var s;n--;)s=r,r=ee(r);if(!ce)return r;if(t){if((r==null?void 0:r.nodeType)!==ze){var f=Ge();return r===null?s==null||s.after(f):r.before(f),Ae(f),f}wn(r)}return Ae(r),r}function Jr(e){e.textContent=""}function Qr(){return!1}function es(e,n,t){return document.createElementNS(jt,e,void 0)}function wn(e){if(e.nodeValue.length<65536)return;let n=e.nextSibling;for(;n!==null&&n.nodeType===ze;)n.remove(),e.nodeValue+=n.nodeValue,n=e.nextSibling}let kn=!1;function nr(){kn||(kn=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{var n;if(!e.defaultPrevented)for(const t of e.target.elements)(n=t.__on_r)==null||n.call(t)})},{capture:!0}))}function yn(e){var n=d,t=w;J(null),Re(null);try{return e()}finally{J(n),Re(t)}}function ns(e,n,t,r=t){e.addEventListener(n,()=>yn(t));const s=e.__on_r;s?e.__on_r=()=>{s(),r(!0)}:e.__on_r=()=>r(!0),nr()}function nt(e){w===null&&(d===null&&Nt(),xt()),de&&Ot()}function tr(e,n){var t=n.last;t===null?n.last=n.first=e:(t.next=e,e.prev=t,n.last=e)}function G(e,n){var t=w;t!==null&&t.f&H&&(e|=H);var r={ctx:S,deps:null,nodes:null,f:e|O|C,first:null,fn:n,last:null,next:null,parent:t,b:t&&t.b,prev:null,teardown:null,wv:0,ac:null},s=r;if(e&be)pe!==null?pe.push(r):_e.ensure().schedule(r);else if(n!==null){try{Se(r)}catch(u){throw ve(r),u}s.deps===null&&s.teardown===null&&s.nodes===null&&s.first===s.last&&!(s.f&Me)&&(s=s.first,e&Q&&e&He&&s!==null&&(s.f|=He))}if(s!==null&&(s.parent=t,t!==null&&tr(s,t),d!==null&&d.f&T&&!(e&ue))){var f=d;(f.effects??(f.effects=[])).push(s)}return r}function tt(){return d!==null&&!L}function rr(e){const n=G(Fe,null);return y(n,E),n.teardown=e,n}function ts(e){nt();var n=w.f,t=!d&&(n&V)!==0&&(n&he)===0;if(t){var r=S;(r.e??(r.e=[])).push(e)}else return rt(e)}function rt(e){return G(be|jn,e)}function rs(e){return nt(),G(Fe|jn,e)}function ss(e){_e.ensure();const n=G(ue|Me,e);return(t={})=>new Promise(r=>{t.outro?ir(n,()=>{ve(n),r(void 0)}):(ve(n),r(void 0))})}function ls(e){return G(be,e)}function sr(e){return G(un|Me,e)}function fs(e,n=0){return G(Fe|n,e)}function is(e,n=[],t=[],r=[]){Kt(r,n,t,s=>{G(Fe,()=>e(...s.map(ke)))})}function as(e,n=0){var t=G(Q|n,e);return t}function us(e){return G(V|Me,e)}function st(e){var n=e.teardown;if(n!==null){const t=de,r=d;Dn(!0),J(null);try{n.call(null)}finally{Dn(t),J(r)}}}function En(e,n=!1){var t=e.first;for(e.first=e.last=null;t!==null;){const s=t.ac;s!==null&&yn(()=>{s.abort(K)});var r=t.next;t.f&ue?t.parent=null:ve(t,n),t=r}}function lr(e){for(var n=e.first;n!==null;){var t=n.next;n.f&V||ve(n),n=t}}function ve(e,n=!0){var t=!1;(n||e.f&Rt)&&e.nodes!==null&&e.nodes.end!==null&&(fr(e.nodes.start,e.nodes.end),t=!0),y(e,bn),En(e,n&&!t),Pe(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(const f of r)f.stop();st(e),e.f^=bn,e.f|=U;var s=e.parent;s!==null&&s.first!==null&<(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=null}function fr(e,n){for(;e!==null;){var t=e===n?null:ee(e);e.remove(),e=t}}function lt(e){var n=e.parent,t=e.prev,r=e.next;t!==null&&(t.next=r),r!==null&&(r.prev=t),n!==null&&(n.first===e&&(n.first=r),n.last===e&&(n.last=t))}function ir(e,n,t=!0){var r=[];ft(e,r,!0);var s=()=>{t&&ve(e),n&&n()},f=r.length;if(f>0){var u=()=>--f||s();for(var a of r)a.out(u)}else s()}function ft(e,n,t){if(!(e.f&H)){e.f^=H;var r=e.nodes&&e.nodes.t;if(r!==null)for(const a of r)(a.is_global||t)&&n.push(a);for(var s=e.first;s!==null;){var f=s.next,u=(s.f&He)!==0||(s.f&V)!==0&&(e.f&Q)!==0;ft(s,n,u?t:!1),s=f}}}function os(e){it(e,!0)}function it(e,n){if(e.f&H){e.f^=H,e.f&E||(y(e,O),_e.ensure().schedule(e));for(var t=e.first;t!==null;){var r=t.next,s=(t.f&He)!==0||(t.f&V)!==0;it(t,s?n:!1),t=r}var f=e.nodes&&e.nodes.t;if(f!==null)for(const u of f)(u.is_global||n)&&u.in()}}function cs(e,n){if(e.nodes)for(var t=e.nodes.start,r=e.nodes.end;t!==null;){var s=t===r?null:ee(t);n.append(t),t=s}}let qe=!1,de=!1;function Dn(e){de=e}let d=null,L=!1;function J(e){d=e}let w=null;function Re(e){w=e}let F=null;function at(e){d!==null&&(F===null?F=[e]:F.push(e))}let N=null,k=0,P=null;function ar(e){P=e}let ut=1,le=0,ae=le;function In(e){ae=e}function ot(){return++ut}function Le(e){var n=e.f;if(n&O)return!0;if(n&T&&(e.f&=~oe),n&B){for(var t=e.deps,r=t.length,s=0;se.wv)return!0}n&C&&A===null&&y(e,E)}return!1}function ct(e,n,t=!0){var r=e.reactions;if(r!==null&&!(F!==null&&Te.call(F,e)))for(var s=0;s{e.ac.abort(K)}),e.ac=null);try{e.f|=Je;var o=e.fn,_=o();e.f|=he;var c=e.deps,g=h==null?void 0:h.is_fork;if(N!==null){var p;if(g||Pe(e,k),c!==null&&k>0)for(c.length=k+N.length,p=0;p{const n=/^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(r);if(n)return a.push({name:n[1],matcher:n[2],optional:!1,rest:!0,chained:!0}),"(?:/([^]*))?";const o=/^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(r);if(o)return a.push({name:o[1],matcher:o[2],optional:!0,rest:!1,chained:!0}),"(?:/([^/]+))?";if(!r)return;const i=r.split(/\[(.+?)\](?!\])/);return"/"+i.map((l,c)=>{if(c%2){if(l.startsWith("x+"))return ft(String.fromCharCode(parseInt(l.slice(2),16)));if(l.startsWith("u+"))return ft(String.fromCharCode(...l.slice(2).split("-").map(m=>parseInt(m,16))));const h=de.exec(l),[,u,w,p,f]=h;return a.push({name:p,matcher:f,optional:!!u,rest:!!w,chained:w?c===1&&i[0]==="":!1}),w?"([^]*?)":u?"([^/]*)?":"([^/]+?)"}return ft(l)}).join("")}).join("")}/?$`),params:a}}function ge(t){return t!==""&&!/^\([^)]+\)$/.test(t)}function me(t){return t.slice(1).split("/").filter(ge)}function _e(t,a,e){const r={},n=t.slice(1),o=n.filter(s=>s!==void 0);let i=0;for(let s=0;sh).join("/"),i=0),c===void 0)if(l.rest)c="";else continue;if(!l.matcher||e[l.matcher](c)){r[l.name]=c;const h=a[s+1],u=n[s+1];h&&!h.rest&&h.optional&&u&&l.chained&&(i=0),!h&&!u&&Object.keys(r).length===o.length&&(i=0);continue}if(l.optional&&l.chained){i++;continue}return}if(!i)return r}function ft(t){return t.normalize().replace(/[[\]]/g,"\\$&").replace(/%/g,"%25").replace(/\//g,"%2[Ff]").replace(/\?/g,"%3[Ff]").replace(/#/g,"%23").replace(/[.*+?^${}()|\\]/g,"\\$&")}function we({nodes:t,server_loads:a,dictionary:e,matchers:r}){const n=new Set(a);return Object.entries(e).map(([s,[l,c,h]])=>{const{pattern:u,params:w}=pe(s),p={id:s,exec:f=>{const m=u.exec(f);if(m)return _e(m,w,r)},errors:[1,...h||[]].map(f=>t[f]),layouts:[0,...c||[]].map(i),leaf:o(l)};return p.errors.length=p.layouts.length=Math.max(p.errors.length,p.layouts.length),p});function o(s){const l=s<0;return l&&(s=~s),[l,t[s]]}function i(s){return s===void 0?s:[n.has(s),t[s]]}}function Bt(t,a=JSON.parse){try{return a(sessionStorage[t])}catch{}}function Ot(t,a,e=JSON.stringify){const r=e(a);try{sessionStorage[t]=r}catch{}}function ve(t){return t.filter(a=>a!=null)}function kt(t){return t instanceof yt||t instanceof Et?t.status:500}function ye(t){return t instanceof Et?t.text:"Internal Error"}const be=new Set(["icon","shortcut icon","apple-touch-icon"]);let F=null;const I=Bt(zt)??{},V=Bt(Ft)??{},A={url:Tt({}),page:Tt({}),navigating:re(null),updated:oe()};function St(t){I[t]=j()}function Ee(t,a){let e=t+1;for(;I[e];)delete I[e],e+=1;for(e=a+1;V[e];)delete V[e],e+=1}function H(t,a=!1){return a?location.replace(t.href):location.href=t.href,new Promise(()=>{})}async function Mt(){if("serviceWorker"in navigator){const t=await navigator.serviceWorker.getRegistration(L||"/");t&&await t.update()}}function jt(){}let Rt,pt,Z,U,gt,E;const tt=[],et=[];let v=null;function mt(){var t;(t=v==null?void 0:v.fork)==null||t.then(a=>a==null?void 0:a.discard()),v=null}const J=new Map,Vt=new Set,ke=new Set,B=new Set;let _={branch:[],error:null,url:null},Ht=!1,at=!1,Ct=!0,Y=!1,z=!1,Yt=!1,xt=!1,Wt,b,R,O;const nt=new Set,$t=new Map;async function Be(t,a,e){var o,i,s,l,c;(o=globalThis.__sveltekit_63i6zh)!=null&&o.data&&globalThis.__sveltekit_63i6zh.data,document.URL!==location.href&&(location.href=location.href),E=t,await((s=(i=t.hooks).init)==null?void 0:s.call(i)),Rt=we(t),U=document.documentElement,gt=a,pt=t.nodes[0],Z=t.nodes[1],pt(),Z(),b=(l=history.state)==null?void 0:l[$],R=(c=history.state)==null?void 0:c[M],b||(b=R=Date.now(),history.replaceState({...history.state,[$]:b,[M]:R},""));const r=I[b];function n(){r&&(history.scrollRestoration="manual",scrollTo(r.x,r.y))}e?(n(),await $e(gt,e)):(await N({type:"enter",url:wt(E.hash?qe(new URL(location.href)):location.href),replace_state:!0}),n()),Ce()}function Se(){tt.length=0,xt=!1}function Gt(t){et.some(a=>a==null?void 0:a.snapshot)&&(V[t]=et.map(a=>{var e;return(e=a==null?void 0:a.snapshot)==null?void 0:e.capture()}))}function Jt(t){var a;(a=V[t])==null||a.forEach((e,r)=>{var n,o;(o=(n=et[r])==null?void 0:n.snapshot)==null||o.restore(e)})}function Nt(){St(b),Ot(zt,I),Gt(R),Ot(Ft,V)}async function Xt(t,a,e,r){let n;a.invalidateAll&&mt(),await N({type:"goto",url:wt(t),keepfocus:a.keepFocus,noscroll:a.noScroll,replace_state:a.replaceState,state:a.state,redirect_count:e,nav_token:r,accept:()=>{a.invalidateAll&&(xt=!0,n=[...$t.keys()]),a.invalidate&&a.invalidate.forEach(je)}}),a.invalidateAll&&X().then(X).then(()=>{$t.forEach(({resource:o},i)=>{var s;n!=null&&n.includes(i)&&((s=o.refresh)==null||s.call(o))})})}async function Re(t){if(t.id!==(v==null?void 0:v.id)){mt();const a={};nt.add(a),v={id:t.id,token:a,promise:Zt({...t,preload:a}).then(e=>(nt.delete(a),e.type==="loaded"&&e.state.error&&mt(),e)),fork:null}}return v.promise}async function ut(t){var e;const a=(e=await it(t,!1))==null?void 0:e.route;a&&await Promise.all([...a.layouts,a.leaf].filter(Boolean).map(r=>r[1]()))}async function Qt(t,a,e){var o;const r={params:_.params,route:{id:((o=_.route)==null?void 0:o.id)??null},url:new URL(location.href)};_={...t.state,nav:r};const n=document.querySelector("style[data-sveltekit]");if(n&&n.remove(),Object.assign(x,t.props.page),Wt=new E.root({target:a,props:{...t.props,stores:A,components:et},hydrate:e,sync:!1,transformError:void 0}),await Promise.resolve(),Jt(R),e){const i={from:null,to:{...r,scroll:I[b]??j()},willUnload:!1,type:"enter",complete:Promise.resolve()};B.forEach(s=>s(i))}at=!0}async function rt({url:t,params:a,branch:e,errors:r,status:n,error:o,route:i,form:s}){let l="never";if(L&&(t.pathname===L||t.pathname===L+"/"))l="always";else for(const f of e)(f==null?void 0:f.slash)!==void 0&&(l=f.slash);t.pathname=le(t.pathname,l),t.search=t.search;const c={type:"loaded",state:{url:t,params:a,branch:e,error:o,route:i},props:{constructors:ve(e).map(f=>f.node.component),page:It(x)}};s!==void 0&&(c.props.form=s);let h={},u=!x,w=0;for(let f=0;fs(new URL(i))))return!0;return!1}function Ut(t,a){return(t==null?void 0:t.type)==="data"?t:(t==null?void 0:t.type)==="skip"?a??null:null}function Ue(t,a){if(!t)return new Set(a.searchParams.keys());const e=new Set([...t.searchParams.keys(),...a.searchParams.keys()]);for(const r of e){const n=t.searchParams.getAll(r),o=a.searchParams.getAll(r);n.every(i=>o.includes(i))&&o.every(i=>n.includes(i))&&e.delete(r)}return e}function Pe({error:t,url:a,route:e,params:r}){return{type:"loaded",state:{error:t,url:a,route:e,params:r,branch:[]},props:{page:It(x),constructors:[]}}}async function Zt({id:t,invalidating:a,url:e,params:r,route:n,preload:o}){if((v==null?void 0:v.id)===t)return nt.delete(v.token),v.promise;const{errors:i,layouts:s,leaf:l}=n,c=[...s,l];i.forEach(d=>d==null?void 0:d().catch(()=>{})),c.forEach(d=>d==null?void 0:d[1]().catch(()=>{}));const h=_.url?t!==ot(_.url):!1,u=_.route?n.id!==_.route.id:!1,w=Ue(_.url,e);let p=!1;const f=c.map(async(d,g)=>{var P;if(!d)return;const y=_.branch[g];return d[1]===(y==null?void 0:y.loader)&&!Le(p,u,h,w,(P=y.universal)==null?void 0:P.uses,r)?y:(p=!0,Lt({loader:d[1],url:e,params:r,route:n,parent:async()=>{var G;const T={};for(let C=0;C{});const m=[];for(let d=0;dPromise.resolve({}),server_data_node:Ut(o)}),s={node:await Z(),loader:Z,universal:null,server:null,data:null};return rt({url:e,params:n,branch:[i,s],status:t,error:a,errors:[],route:null})}catch(i){if(i instanceof bt)return Xt(new URL(i.location,location.href),{},0);throw i}}async function Ie(t){const a=t.href;if(J.has(a))return J.get(a);let e;try{const r=(async()=>{let n=await E.hooks.reroute({url:new URL(t),fetch:async(o,i)=>xe(o,i,t).promise})??t;if(typeof n=="string"){const o=new URL(t);E.hash?o.hash=n:o.pathname=n,n=o}return n})();J.set(a,r),e=await r}catch{J.delete(a);return}return e}async function it(t,a){if(t&&!vt(t,L,E.hash)){const e=await Ie(t);if(!e)return;const r=Te(e);for(const n of Rt){const o=n.exec(r);if(o)return{id:ot(t),invalidating:a,route:n,params:se(o),url:t}}}}function Te(t){return ce(E.hash?t.hash.replace(/^#/,"").replace(/[?#].+/,""):t.pathname.slice(L.length))||"/"}function ot(t){return(E.hash?t.hash.replace(/^#/,""):t.pathname)+t.search}function te({url:t,type:a,intent:e,delta:r,event:n,scroll:o}){let i=!1;const s=At(_,e,t,a,o??null);r!==void 0&&(s.navigation.delta=r),n!==void 0&&(s.navigation.event=n);const l={...s.navigation,cancel:()=>{i=!0,s.reject(new Error("navigation cancelled"))}};return Y||Vt.forEach(c=>c(l)),i?null:s}async function N({type:t,url:a,popped:e,keepfocus:r,noscroll:n,replace_state:o,state:i={},redirect_count:s=0,nav_token:l={},accept:c=jt,block:h=jt,event:u}){var C;const w=O;O=l;const p=await it(a,!1),f=t==="enter"?At(_,p,a,t):te({url:a,type:t,delta:e==null?void 0:e.delta,intent:p,scroll:e==null?void 0:e.scroll,event:u});if(!f){h(),O===l&&(O=w);return}const m=b,d=R;c(),Y=!0,at&&f.navigation.type!=="enter"&&A.navigating.set(ht.current=f.navigation);let g=p&&await Zt(p);if(!g){if(vt(a,L,E.hash))return await H(a,o);g=await ee(a,{id:null},await W(new Et(404,"Not Found",`Not found: ${a.pathname}`),{url:a,params:{},route:{id:null}}),404,o)}if(a=(p==null?void 0:p.url)||a,O!==l)return f.reject(new Error("navigation aborted")),!1;if(g.type==="redirect"){if(s<20){await N({type:t,url:new URL(g.location,a),popped:e,keepfocus:r,noscroll:n,replace_state:o,state:i,redirect_count:s+1,nav_token:l}),f.fulfil(void 0);return}g=await Pt({status:500,error:await W(new Error("Redirect loop"),{url:a,params:{},route:{id:null}}),url:a,route:{id:null}})}else g.props.page.status>=400&&await A.updated.check()&&(await Mt(),await H(a,o));if(Se(),St(m),Gt(d),g.props.page.url.pathname!==a.pathname&&(a.pathname=g.props.page.url.pathname),i=e?e.state:i,!e){const k=o?0:1,D={[$]:b+=k,[M]:R+=k,[Kt]:i};(o?history.replaceState:history.pushState).call(history,D,"",a),o||Ee(b,R)}const y=p&&(v==null?void 0:v.id)===p.id?v.fork:null;v=null,g.props.page.state=i;let S;if(at){const k=(await Promise.all(Array.from(ke,q=>q(f.navigation)))).filter(q=>typeof q=="function");if(k.length>0){let q=function(){k.forEach(lt=>{B.delete(lt)})};k.push(q),k.forEach(lt=>{B.add(lt)})}const D=f.navigation.to;_={...g.state,nav:{params:D.params,route:D.route,url:D.url}},g.props.page&&(g.props.page.url=a);const st=y&&await y;st?S=st.commit():(F=null,Wt.$set(g.props),F&&Object.assign(g.props.page,F),he(g.props.page),S=(C=ne)==null?void 0:C()),Yt=!0}else await Qt(g,gt,!1);const{activeElement:P}=document;await S,await X(),await X();let T=null;if(Ct){const k=e?e.scroll:n?j():null;k?scrollTo(k.x,k.y):(T=a.hash&&document.getElementById(ae(a)))?T.scrollIntoView():scrollTo(0,0)}const G=document.activeElement!==P&&document.activeElement!==document.body;!r&&!G&&De(a,!T),Ct=!0,g.props.page&&(F&&Object.assign(g.props.page,F),Object.assign(x,g.props.page)),Y=!1,t==="popstate"&&Jt(R),f.fulfil(void 0),f.navigation.to&&(f.navigation.to.scroll=j()),B.forEach(k=>k(f.navigation)),A.navigating.set(ht.current=null)}async function ee(t,a,e,r,n){return t.origin===Dt&&t.pathname===location.pathname&&!Ht?await Pt({status:r,error:e,url:t,route:a}):await H(t,n)}function Oe(){let t,a={element:void 0,href:void 0},e;U.addEventListener("mousemove",s=>{const l=s.target;clearTimeout(t),t=setTimeout(()=>{o(l,K.hover)},20)});function r(s){s.defaultPrevented||o(s.composedPath()[0],K.tap)}U.addEventListener("mousedown",r),U.addEventListener("touchstart",r,{passive:!0});const n=new IntersectionObserver(s=>{for(const l of s)l.isIntersecting&&(ut(new URL(l.target.href)),n.unobserve(l.target))},{threshold:0});async function o(s,l){const c=qt(s,U),h=c===a.element&&(c==null?void 0:c.href)===a.href&&l>=e;if(!c||h)return;const{url:u,external:w,download:p}=dt(c,L,E.hash);if(w||p)return;const f=Q(c),m=u&&ot(_.url)===ot(u);if(!(f.reload||m))if(l<=f.preload_data){a={element:c,href:c.href},e=K.tap;const d=await it(u,!1);if(!d)return;Re(d)}else l<=f.preload_code&&(a={element:c,href:c.href},e=l,ut(u))}function i(){n.disconnect();for(const s of U.querySelectorAll("a")){const{url:l,external:c,download:h}=dt(s,L,E.hash);if(c||h)continue;const u=Q(s);u.reload||(u.preload_code===K.viewport&&n.observe(s),u.preload_code===K.eager&&ut(l))}}B.add(i),i()}function W(t,a){if(t instanceof yt)return t.body;const e=kt(t),r=ye(t);return E.hooks.handleError({error:t,event:a,status:e,message:r})??{message:r}}function Me(t,a={}){return t=new URL(wt(t)),t.origin!==Dt?Promise.reject(new Error("goto: invalid URL")):Xt(t,a,0)}function je(t){if(typeof t=="function")tt.push(t);else{const{href:a}=new URL(t,location.href);tt.push(e=>e.href===a)}}function Ce(){var a;history.scrollRestoration="manual",addEventListener("beforeunload",e=>{let r=!1;if(Nt(),!Y){const n=At(_,void 0,null,"leave"),o={...n.navigation,cancel:()=>{r=!0,n.reject(new Error("navigation cancelled"))}};Vt.forEach(i=>i(o))}r?(e.preventDefault(),e.returnValue=""):history.scrollRestoration="auto"}),addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&Nt()}),(a=navigator.connection)!=null&&a.saveData||Oe(),U.addEventListener("click",async e=>{if(e.button||e.which!==1||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||e.defaultPrevented)return;const r=qt(e.composedPath()[0],U);if(!r)return;const{url:n,external:o,target:i,download:s}=dt(r,L,E.hash);if(!n)return;if(i==="_parent"||i==="_top"){if(window.parent!==window)return}else if(i&&i!=="_self")return;const l=Q(r);if(!(r instanceof SVGAElement)&&n.protocol!==location.protocol&&!(n.protocol==="https:"||n.protocol==="http:")||s)return;const[h,u]=(E.hash?n.hash.replace(/^#/,""):n.href).split("#"),w=h===ct(location);if(o||l.reload&&(!w||!u)){te({url:n,type:"link",event:e})?Y=!0:e.preventDefault();return}if(u!==void 0&&w){const[,p]=_.url.href.split("#");if(p===u){if(e.preventDefault(),u===""||u==="top"&&r.ownerDocument.getElementById("top")===null)scrollTo({top:0});else{const f=r.ownerDocument.getElementById(decodeURIComponent(u));f&&(f.scrollIntoView(),f.focus())}return}if(z=!0,St(b),t(n),!l.replace_state)return;z=!1}e.preventDefault(),await new Promise(p=>{requestAnimationFrame(()=>{setTimeout(p,0)}),setTimeout(p,100)}),await N({type:"link",url:n,keepfocus:l.keepfocus,noscroll:l.noscroll,replace_state:l.replace_state??n.href===location.href,event:e})}),U.addEventListener("submit",e=>{if(e.defaultPrevented)return;const r=HTMLFormElement.prototype.cloneNode.call(e.target),n=e.submitter;if(((n==null?void 0:n.formTarget)||r.target)==="_blank"||((n==null?void 0:n.formMethod)||r.method)!=="get")return;const s=new URL((n==null?void 0:n.hasAttribute("formaction"))&&(n==null?void 0:n.formAction)||r.action);if(vt(s,L,!1))return;const l=e.target,c=Q(l);if(c.reload)return;e.preventDefault(),e.stopPropagation();const h=new FormData(l,n);s.search=new URLSearchParams(h).toString(),N({type:"form",url:s,keepfocus:c.keepfocus,noscroll:c.noscroll,replace_state:c.replace_state??s.href===location.href,event:e})}),addEventListener("popstate",async e=>{var r;if(!_t){if((r=e.state)!=null&&r[$]){const n=e.state[$];if(O={},n===b)return;const o=I[n],i=e.state[Kt]??{},s=new URL(e.state[ie]??location.href),l=e.state[M],c=_.url?ct(location)===ct(_.url):!1;if(l===R&&(Yt||c)){i!==x.state&&(x.state=i),t(s),I[b]=j(),o&&scrollTo(o.x,o.y),b=n;return}const u=n-b;await N({type:"popstate",url:s,popped:{state:i,scroll:o,delta:u},accept:()=>{b=n,R=l},block:()=>{history.go(-u)},nav_token:O,event:e})}else if(!z){const n=new URL(location.href);t(n),E.hash&&location.reload()}}}),addEventListener("hashchange",()=>{z&&(z=!1,history.replaceState({...history.state,[$]:++b,[M]:R},"",location.href))});for(const e of document.querySelectorAll("link"))be.has(e.rel)&&(e.href=e.href);addEventListener("pageshow",e=>{e.persisted&&A.navigating.set(ht.current=null)});function t(e){_.url=x.url=e,A.page.set(It(x)),A.page.notify()}}async function $e(t,{status:a=200,error:e,node_ids:r,params:n,route:o,server_route:i,data:s,form:l}){Ht=!0;const c=new URL(location.href);let h;({params:n={},route:o={id:null}}=await it(c,!1)||{}),h=Rt.find(({id:p})=>p===o.id);let u,w=!0;try{const p=r.map(async(m,d)=>{const g=s[d];return g!=null&&g.uses&&(g.uses=Ne(g.uses)),Lt({loader:E.nodes[m],url:c,params:n,route:o,parent:async()=>{const y={};for(let S=0;S{const s=history.state;_t=!0,location.replace(new URL(`#${r}`,location.href)),history.replaceState(s,"",t),a&&scrollTo(o,i),_t=!1})}else{const o=document.body,i=o.getAttribute("tabindex");o.tabIndex=-1,o.focus({preventScroll:!0,focusVisible:!1}),i!==null?o.setAttribute("tabindex",i):o.removeAttribute("tabindex")}const n=getSelection();if(n&&n.type!=="None"){const o=[];for(let i=0;i{if(n.rangeCount===o.length){for(let i=0;i{o=u,i=w});return s.catch(()=>{}),{navigation:{from:{params:t.params,route:{id:((c=t.route)==null?void 0:c.id)??null},url:t.url,scroll:j()},to:e&&{params:(a==null?void 0:a.params)??null,route:{id:((h=a==null?void 0:a.route)==null?void 0:h.id)??null},url:e,scroll:n},willUnload:!a,type:r,complete:s},fulfil:o,reject:i}}function It(t){return{data:t.data,error:t.error,form:t.form,params:t.params,route:t.route,state:t.state,status:t.status,url:t.url}}function qe(t){const a=new URL(t);return a.hash=decodeURIComponent(t.hash),a}function ae(t){let a;if(E.hash){const[,,e]=t.hash.split("#",3);a=e??""}else a=t.hash.slice(1);return decodeURIComponent(a)}export{Be as a,Me as g,A as s}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/ayyTDfEa.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/ayyTDfEa.js new file mode 100644 index 0000000..ce8adf6 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/ayyTDfEa.js @@ -0,0 +1 @@ +import{l as b,c as v,b as m,u as _,r as i,h as y}from"./DtGl34IE.js";function k(e,l,u=l){var s=new WeakSet;b(e,"input",async r=>{var a=r?e.defaultValue:e.value;if(a=t(e)?o(a):a,u(a),v!==null&&s.add(v),await m(),a!==(a=l())){var d=e.selectionStart,c=e.selectionEnd,n=e.value.length;if(e.value=a??"",c!==null){var f=e.value.length;d===c&&c===n&&f>n?(e.selectionStart=f,e.selectionEnd=f):(e.selectionStart=d,e.selectionEnd=Math.min(c,f))}}}),(y&&e.defaultValue!==e.value||_(l)==null&&e.value)&&(u(t(e)?o(e.value):e.value),v!==null&&s.add(v)),i(()=>{var r=l();if(e===document.activeElement){var a=v;if(s.has(a))return}t(e)&&r===o(e.value)||e.type==="date"&&!r&&!e.value||r!==e.value&&(e.value=r??"")})}function t(e){var l=e.type;return l==="number"||l==="range"}function o(e){return e===""?null:+e}export{k as b}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/e1WBZ7UL.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/e1WBZ7UL.js new file mode 100644 index 0000000..ef637a0 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/e1WBZ7UL.js @@ -0,0 +1 @@ +import{h as i,q as d,e as n,L as v,N as h,I as u,f as g,i as A}from"./DtGl34IE.js";const L=Symbol("is custom element"),N=Symbol("is html"),l=u?"link":"LINK";function S(r){if(i){var s=!1,e=()=>{if(!s){if(s=!0,r.hasAttribute("value")){var a=r.value;t(r,"value",null),r.value=a}if(r.hasAttribute("checked")){var o=r.checked;t(r,"checked",null),r.checked=o}}};r.__on_r=e,d(e),n()}}function t(r,s,e,a){var o=p(r);i&&(o[s]=r.getAttribute(s),s==="src"||s==="srcset"||s==="href"&&r.nodeName===l)||o[s]!==(o[s]=e)&&(s==="loading"&&(r[v]=e),e==null?r.removeAttribute(s):typeof e!="string"&&I(r).includes(s)?r[s]=e:r.setAttribute(s,e))}function p(r){return r.__attributes??(r.__attributes={[L]:r.nodeName.includes("-"),[N]:r.namespaceURI===h})}var c=new Map;function I(r){var s=r.getAttribute("is")||r.nodeName,e=c.get(s);if(e)return e;c.set(s,e=[]);for(var a,o=r,f=Element.prototype;f!==o;){a=A(o);for(var _ in a)a[_].set&&e.push(_);o=g(o)}return e}export{S as r,t as s}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/ecAlPOj8.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/ecAlPOj8.js new file mode 100644 index 0000000..c322045 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/ecAlPOj8.js @@ -0,0 +1 @@ +import{h as N,j as z,k as W,o as H,v as Z,w as $,g as L,x as j,H as ee,y as U,z as O,A as b,C as ne,B as re,D as X,c as fe,E as Y,F as ae,G as ie,J as le,K as ue,M as V,O as se,P as q,Q as oe,R as ve,m as te,S as T,T as de,U as J,V as K,W as y,X as ce,Y as pe,Z as ge,_ as he,$ as _e}from"./DtGl34IE.js";function Ce(e,a){return a}function Ee(e,a,l){for(var o=[],c=a.length,u,i=a.length,r=0;r{if(u){if(u.pending.delete(v),u.done.add(v),u.pending.size===0){var w=e.outrogroups;B(e,V(u.done)),w.delete(u),w.size===0&&(e.outrogroups=null)}}else i-=1},!1)}if(i===0){var t=o.length===0&&l!==null;if(t){var f=l,d=f.parentNode;pe(d),d.append(f),e.items.clear()}B(e,a,!t)}else u={pending:new Set(a),done:new Set},(e.outrogroups??(e.outrogroups=new Set)).add(u)}function B(e,a,l=!0){var o;if(e.pending.size>0){o=new Set;for(const i of e.pending.values())for(const r of i)o.add(e.items.get(r).e)}for(var c=0;c{var s=l();return ue(s)?s:s==null?[]:V(s)}),v,w=new Map,h=!0;function n(s){p.effect.f&de||(p.pending.delete(s),p.fallback=f,me(p,v,i,a,o),f!==null&&(v.length===0?f.f&T?(f.f^=T,D(f,null,i)):J(f):K(f,()=>{f=null})))}function C(s){p.pending.delete(s)}var I=$(()=>{v=L(d);var s=v.length;let k=!1;if(N){var R=j(i)===ee;R!==(s===0)&&(i=U(),z(i),O(!1),k=!0)}for(var _=new Set,A=fe,M=ie(),E=0;Eu(i)):(f=Y(()=>u(G??(G=H()))),f.f|=T)),s>_.size&&ae(),N&&s>0&&z(U()),!h)if(w.set(A,_),M){for(const[P,Q]of r)_.has(P)||A.skip_effect(Q.e);A.oncommit(n),A.ondiscard(C)}else n(A);k&&O(!0),L(d)}),p={effect:I,items:r,pending:w,outrogroups:null,fallback:f};h=!1,N&&(i=b)}function x(e){for(;e!==null&&!(e.f&ce);)e=e.next;return e}function me(e,a,l,o,c){var E;var u=a.length,i=e.items,r=x(e.effect.first),t,f=null,d=[],v=[],w,h,n,C;for(C=0;C0){var M=u===0?l:null;Ee(e,_,M)}}}function Te(e,a,l,o,c,u,i,r){var t=i&oe?i&ve?q(l):te(l,!1,!1):null,f=i&se?q(c):null;return{v:t,i:f,e:Y(()=>(u(a,t??l,f??c,r),()=>{e.delete(o)}))}}function D(e,a,l){if(e.nodes)for(var o=e.nodes.start,c=e.nodes.end,u=a&&!(a.f&T)?a.nodes.start:l;o!==null;){var i=_e(o);if(u.before(o),o===c)return;o=i}}function S(e,a,l){a===null?e.effect.first=l:a.next=l,l===null?e.effect.last=a:l.prev=a}export{Ae as e,Ce as i}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/n1byU5WW.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/n1byU5WW.js new file mode 100644 index 0000000..4424acc --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/chunks/n1byU5WW.js @@ -0,0 +1,2 @@ +var Ft=Object.defineProperty;var dt=e=>{throw TypeError(e)};var kt=(e,t,r)=>t in e?Ft(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r;var z=(e,t,r)=>kt(e,typeof t!="symbol"?t+"":t,r),rt=(e,t,r)=>t.has(e)||dt("Cannot "+r);var s=(e,t,r)=>(rt(e,t,"read from private field"),r?r.call(e):t.get(e)),c=(e,t,r)=>t.has(e)?dt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,r),n=(e,t,r,a)=>(rt(e,t,"write to private field"),a?a.call(e,r):t.set(e,r),r),p=(e,t,r)=>(rt(e,t,"access private method"),r);import{au as Mt,g as bt,r as Lt,u as Ct,av as ut,q as V,P as Et,A as M,h as L,an as P,aw as _t,w as Ht,v as It,H as Bt,ax as pt,E as k,o as wt,V as st,c as gt,Z as Pt,ay as Yt,az as Z,aA as Q,aB as vt,aC as xt,aD as Vt,aE as mt,aa as Tt,D as Wt,_ as it,j as X,a6 as $t,y as qt,aF as j,a9 as zt,aG as jt,aH as Jt,aI as Gt,t as Kt,aJ as Ut,d as Zt,aK as at,k as Qt,C as St,aL as Xt,$ as te,aM as nt,z as J,aN as ee,Y as re,aO as se,M as ie,p as ae,B as ne,aP as fe,a as he}from"./DtGl34IE.js";import{b as oe}from"./CJv7FbHz.js";function le(e){let t=0,r=Et(0),a;return()=>{Mt()&&(bt(r),Lt(()=>(t===0&&(a=Ct(()=>e(()=>ut(r)))),t+=1,()=>{V(()=>{t-=1,t===0&&(a==null||a(),a=void 0,ut(r))})})))}}var ce=zt|jt;function de(e,t,r,a){new ue(e,t,r,a)}var E,W,T,H,g,S,w,m,N,I,D,Y,$,q,R,tt,o,Nt,Rt,At,ft,K,U,ht;class ue{constructor(t,r,a,h){c(this,o);z(this,"parent");z(this,"is_pending",!1);z(this,"transform_error");c(this,E);c(this,W,L?M:null);c(this,T);c(this,H);c(this,g);c(this,S,null);c(this,w,null);c(this,m,null);c(this,N,null);c(this,I,0);c(this,D,0);c(this,Y,!1);c(this,$,new Set);c(this,q,new Set);c(this,R,null);c(this,tt,le(()=>(n(this,R,Et(s(this,I))),()=>{n(this,R,null)})));var i;n(this,E,t),n(this,T,r),n(this,H,f=>{var u=P;u.b=this,u.f|=_t,a(f)}),this.parent=P.b,this.transform_error=h??((i=this.parent)==null?void 0:i.transform_error)??(f=>f),n(this,g,Ht(()=>{if(L){const f=s(this,W);It();const u=f.data===Bt;if(f.data.startsWith(pt)){const d=JSON.parse(f.data.slice(pt.length));p(this,o,Rt).call(this,d)}else u?p(this,o,At).call(this):p(this,o,Nt).call(this)}else p(this,o,ft).call(this)},ce)),L&&n(this,E,M)}defer_effect(t){Yt(t,s(this,$),s(this,q))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!s(this,T).pending}update_pending_count(t,r){p(this,o,ht).call(this,t,r),n(this,I,s(this,I)+t),!(!s(this,R)||s(this,Y))&&(n(this,Y,!0),V(()=>{n(this,Y,!1),s(this,R)&&Wt(s(this,R),s(this,I))}))}get_effect_pending(){return s(this,tt).call(this),bt(s(this,R))}error(t){var r=s(this,T).onerror;let a=s(this,T).failed;if(!r&&!a)throw t;s(this,S)&&(it(s(this,S)),n(this,S,null)),s(this,w)&&(it(s(this,w)),n(this,w,null)),s(this,m)&&(it(s(this,m)),n(this,m,null)),L&&(X(s(this,W)),$t(),X(qt()));var h=!1,i=!1;const f=()=>{if(h){Gt();return}h=!0,i&&Jt(),s(this,m)!==null&&st(s(this,m),()=>{n(this,m,null)}),p(this,o,U).call(this,()=>{p(this,o,ft).call(this)})},u=l=>{try{i=!0,r==null||r(l,f),i=!1}catch(d){j(d,s(this,g)&&s(this,g).parent)}a&&n(this,m,p(this,o,U).call(this,()=>{try{return k(()=>{var d=P;d.b=this,d.f|=_t,a(s(this,E),()=>l,()=>f)})}catch(d){return j(d,s(this,g).parent),null}}))};V(()=>{var l;try{l=this.transform_error(t)}catch(d){j(d,s(this,g)&&s(this,g).parent);return}l!==null&&typeof l=="object"&&typeof l.then=="function"?l.then(u,d=>j(d,s(this,g)&&s(this,g).parent)):u(l)})}}E=new WeakMap,W=new WeakMap,T=new WeakMap,H=new WeakMap,g=new WeakMap,S=new WeakMap,w=new WeakMap,m=new WeakMap,N=new WeakMap,I=new WeakMap,D=new WeakMap,Y=new WeakMap,$=new WeakMap,q=new WeakMap,R=new WeakMap,tt=new WeakMap,o=new WeakSet,Nt=function(){try{n(this,S,k(()=>s(this,H).call(this,s(this,E))))}catch(t){this.error(t)}},Rt=function(t){const r=s(this,T).failed;r&&n(this,m,k(()=>{r(s(this,E),()=>t,()=>()=>{})}))},At=function(){const t=s(this,T).pending;t&&(this.is_pending=!0,n(this,w,k(()=>t(s(this,E)))),V(()=>{var r=n(this,N,document.createDocumentFragment()),a=wt();r.append(a),n(this,S,p(this,o,U).call(this,()=>k(()=>s(this,H).call(this,a)))),s(this,D)===0&&(s(this,E).before(r),n(this,N,null),st(s(this,w),()=>{n(this,w,null)}),p(this,o,K).call(this,gt))}))},ft=function(){try{if(this.is_pending=this.has_pending_snippet(),n(this,D,0),n(this,I,0),n(this,S,k(()=>{s(this,H).call(this,s(this,E))})),s(this,D)>0){var t=n(this,N,document.createDocumentFragment());Pt(s(this,S),t);const r=s(this,T).pending;n(this,w,k(()=>r(s(this,E))))}else p(this,o,K).call(this,gt)}catch(r){this.error(r)}},K=function(t){this.is_pending=!1,t.transfer_effects(s(this,$),s(this,q))},U=function(t){var r=P,a=mt,h=Tt;Z(s(this,g)),Q(s(this,g)),vt(s(this,g).ctx);try{return xt.ensure(),t()}catch(i){return Vt(i),null}finally{Z(r),Q(a),vt(h)}},ht=function(t,r){var a;if(!this.has_pending_snippet()){this.parent&&p(a=this.parent,o,ht).call(a,t,r);return}n(this,D,s(this,D)+t),s(this,D)===0&&(p(this,o,K).call(this,r),s(this,w)&&st(s(this,w),()=>{n(this,w,null)}),s(this,N)&&(s(this,E).before(s(this,N)),n(this,N,null)))};const _e=["touchstart","touchmove"];function pe(e){return _e.includes(e)}const C=Symbol("events"),Dt=new Set,ot=new Set;function ge(e,t,r,a={}){function h(i){if(a.capture||lt.call(t,i),!i.cancelBubble)return Ut(()=>r==null?void 0:r.call(this,i))}return e.startsWith("pointer")||e.startsWith("touch")||e==="wheel"?V(()=>{t.addEventListener(e,h,a)}):t.addEventListener(e,h,a),h}function we(e,t,r,a,h){var i={capture:a,passive:h},f=ge(e,t,r,i);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&Kt(()=>{t.removeEventListener(e,f,i)})}function me(e,t,r){(t[C]??(t[C]={}))[e]=r}function Te(e){for(var t=0;t{throw F});throw A}}finally{e[C]=t,delete e.currentTarget,Q(B),Z(x)}}}function Se(e,t){var r=t==null?"":typeof t=="object"?`${t}`:t;r!==(e.__t??(e.__t=e.nodeValue))&&(e.__t=r,e.nodeValue=`${r}`)}function ve(e,t){return Ot(e,t)}function Ne(e,t){at(),t.intro=t.intro??!1;const r=t.target,a=L,h=M;try{for(var i=Qt(r);i&&(i.nodeType!==St||i.data!==Xt);)i=te(i);if(!i)throw nt;J(!0),X(i);const f=Ot(e,{...t,anchor:i});return J(!1),f}catch(f){if(f instanceof Error&&f.message.split(` +`).some(u=>u.startsWith("https://svelte.dev/e/")))throw f;return f!==nt&&console.warn("Failed to hydrate: ",f),t.recover===!1&&ee(),at(),re(r),J(!1),ve(e,t)}finally{J(a),X(h)}}const G=new Map;function Ot(e,{target:t,anchor:r,props:a={},events:h,context:i,intro:f=!0,transformError:u}){at();var l=void 0,d=se(()=>{var B=r??t.appendChild(wt());de(B,{pending:()=>{}},v=>{ae({});var _=Tt;if(i&&(_.c=i),h&&(a.$$events=h),L&&oe(v,null),l=e(v,a)||{},L&&(P.nodes.end=M,M===null||M.nodeType!==St||M.data!==ne))throw fe(),nt;he()},u);var x=new Set,A=v=>{for(var _=0;_{var O;for(var v of x)for(const b of[t,document]){var _=G.get(b),y=_.get(v);--y==0?(b.removeEventListener(v,lt),_.delete(v),_.size===0&&G.delete(b)):_.set(v,y)}ot.delete(A),B!==r&&((O=B.parentNode)==null||O.removeChild(B))}});return ct.set(l,d),l}let ct=new WeakMap;function Re(e,t){const r=ct.get(e);return r?(ct.delete(e),r(t)):Promise.resolve()}export{me as a,Te as d,we as e,Ne as h,ve as m,Se as s,Re as u}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/entry/app.BI_Sozkn.js b/frontend/.svelte-kit/output/client/_app/immutable/entry/app.BI_Sozkn.js new file mode 100644 index 0000000..113305c --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/entry/app.BI_Sozkn.js @@ -0,0 +1,2 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["../nodes/0.D3wXY_0K.js","../chunks/CJv7FbHz.js","../chunks/DtGl34IE.js","../chunks/B3ZK_jYJ.js","../chunks/BX-b5t2l.js","../chunks/n1byU5WW.js","../chunks/-EcHSJia.js","../chunks/B7kAneMc.js","../chunks/RKc8iKz_.js","../chunks/CfgL3m1f.js","../chunks/DR7h53-u.js","../assets/0.DkgBtk4_.css","../nodes/1.Dgii_8lh.js","../chunks/DFRBE_Uq.js","../nodes/2.BMCUuUxB.js","../chunks/BYrNiJ2z.js","../assets/2.By2d6Bxb.css","../nodes/3.CFDiiGpK.js","../nodes/4.YDL696B2.js","../chunks/e1WBZ7UL.js","../chunks/ayyTDfEa.js","../assets/4.CG2X--Z8.css","../nodes/5.DHfYhdex.js","../assets/5.YbbfqdJp.css","../nodes/6.BiQ3_GJa.js","../assets/6.w_qTFDpy.css","../nodes/7.BEIquz8f.js","../assets/7.Bq7myTre.css","../nodes/8.D4QctIPu.js","../chunks/ecAlPOj8.js","../assets/8.neQUdyXe.css","../nodes/9.DflEy3LG.js","../assets/9.Ci0QlAaW.css","../nodes/10.BvOkMiuT.js","../assets/10.Qar-kS8x.css","../nodes/11.DnvWFHPj.js","../assets/11.D38O3Xxc.css","../nodes/12.CRx3MqWn.js","../assets/12.DQdHIvb_.css","../nodes/13.CB7FlS8h.js","../assets/13.DnP_H9DZ.css","../nodes/14.CFDiiGpK.js"])))=>i.map(i=>d[i]); +var M=t=>{throw TypeError(t)};var z=(t,e,a)=>e.has(t)||M("Cannot "+a);var h=(t,e,a)=>(z(t,e,"read from private field"),a?a.call(t):e.get(t)),V=(t,e,a)=>e.has(t)?M("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,a),x=(t,e,a,n)=>(z(t,e,"write to private field"),n?n.call(t,a):e.set(t,a),a);import{h as F,v as ae,w as se,a9 as ne,x as ie,y as oe,j as ue,z as G,aL as ce,A as _e,aa as de,aj as fe,r as le,u as H,an as J,aQ as me,aR as Q,aS as ve,aT as he,aU as Ee,g as R,a1 as ge,s as L,aV as Pe,T as Re,aW as ye,ai as Oe,aX as Te,aY as Ae,af as be,J as Ie,aZ as Se,a_ as X,a$ as Le,d as De,m as we,p as pe,ab as Ve,a8 as xe,b as je,a3 as w,a2 as Be,a as ke,a0 as j,a4 as Ce,a5 as Ye,a7 as Ne,b0 as B}from"../chunks/DtGl34IE.js";import{h as Ue,m as qe,u as Me,s as ze}from"../chunks/n1byU5WW.js";import{a as I,c as k,f as K,t as Fe}from"../chunks/CJv7FbHz.js";import{o as Ge}from"../chunks/DR7h53-u.js";import{B as We,i as C}from"../chunks/-EcHSJia.js";import{c as Ze}from"../chunks/B3ZK_jYJ.js";function Y(t,e,a){var n;F&&(n=_e,ae());var i=new We(t);se(()=>{var u=e()??null;if(F){var s=ie(n),r=s===ce,o=u!==null;if(r!==o){var d=oe();ue(d),i.anchor=d,G(!1),i.ensure(u,u&&(c=>a(c,u))),G(!0);return}}i.ensure(u,u&&(c=>a(c,u)))},ne)}function W(t,e){return t===e||(t==null?void 0:t[Q])===e}function N(t={},e,a,n){var i=de.r,u=J;return fe(()=>{var s,r;return le(()=>{s=r,r=[],H(()=>{t!==a(...r)&&(e(t,...r),s&&W(a(...s),t)&&e(null,...s))})}),()=>{let o=u;for(;o!==i&&o.parent!==null&&o.parent.f&me;)o=o.parent;const d=()=>{r&&W(a(...r),t)&&e(null,...r)},c=o.teardown;o.teardown=()=>{d(),c==null||c()}}}),t}function U(t,e,a,n){var O;var i=!Oe||(a&Te)!==0,u=(a&ye)!==0,s=(a&Se)!==0,r=n,o=!0,d=()=>(o&&(o=!1,r=s?H(n):n),r);let c;if(u){var S=Q in t||X in t;c=((O=ve(t,e))==null?void 0:O.set)??(S&&e in t?_=>t[e]=_:void 0)}var A,E=!1;u?[A,E]=Ze(()=>t[e]):A=t[e],A===void 0&&n!==void 0&&(A=d(),c&&(i&&he(),c(A)));var v;if(i?v=()=>{var _=t[e];return _===void 0?d():(o=!0,_)}:v=()=>{var _=t[e];return _!==void 0&&(r=void 0),_===void 0?r:_},i&&!(a&Ee))return v;if(c){var f=t.$$legacy;return function(_,l){return arguments.length>0?((!i||!l||f||E)&&c(l?v():_),_):v()}}var y=!1,g=(a&Ae?be:Ie)(()=>(y=!1,v()));u&&R(g);var b=J;return function(_,l){if(arguments.length>0){const p=l?R(g):i&&u?ge(_):_;return L(g,p),y=!0,r!==void 0&&(r=p),_}return Pe&&y||b.f&Re?g.v:R(g)}}function He(t){return class extends Je{constructor(e){super({component:t,...e})}}}var T,P;class Je{constructor(e){V(this,T);V(this,P);var u;var a=new Map,n=(s,r)=>{var o=we(r,!1,!1);return a.set(s,o),o};const i=new Proxy({...e.props||{},$$events:{}},{get(s,r){return R(a.get(r)??n(r,Reflect.get(s,r)))},has(s,r){return r===X?!0:(R(a.get(r)??n(r,Reflect.get(s,r))),Reflect.has(s,r))},set(s,r,o){return L(a.get(r)??n(r,o),o),Reflect.set(s,r,o)}});x(this,P,(e.hydrate?Ue:qe)(e.component,{target:e.target,anchor:e.anchor,props:i,context:e.context,intro:e.intro??!1,recover:e.recover,transformError:e.transformError})),(!((u=e==null?void 0:e.props)!=null&&u.$$host)||e.sync===!1)&&Le(),x(this,T,i.$$events);for(const s of Object.keys(h(this,P)))s==="$set"||s==="$destroy"||s==="$on"||De(this,s,{get(){return h(this,P)[s]},set(r){h(this,P)[s]=r},enumerable:!0});h(this,P).$set=s=>{Object.assign(i,s)},h(this,P).$destroy=()=>{Me(h(this,P))}}$set(e){h(this,P).$set(e)}$on(e,a){h(this,T)[e]=h(this,T)[e]||[];const n=(...i)=>a.call(this,...i);return h(this,T)[e].push(n),()=>{h(this,T)[e]=h(this,T)[e].filter(i=>i!==n)}}$destroy(){h(this,P).$destroy()}}T=new WeakMap,P=new WeakMap;const Qe="modulepreload",Xe=function(t,e){return new URL(t,e).href},Z={},m=function(e,a,n){let i=Promise.resolve();if(a&&a.length>0){const s=document.getElementsByTagName("link"),r=document.querySelector("meta[property=csp-nonce]"),o=(r==null?void 0:r.nonce)||(r==null?void 0:r.getAttribute("nonce"));i=Promise.allSettled(a.map(d=>{if(d=Xe(d,n),d in Z)return;Z[d]=!0;const c=d.endsWith(".css"),S=c?'[rel="stylesheet"]':"";if(!!n)for(let v=s.length-1;v>=0;v--){const f=s[v];if(f.href===d&&(!c||f.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${d}"]${S}`))return;const E=document.createElement("link");if(E.rel=c?"stylesheet":Qe,c||(E.as="script"),E.crossOrigin="",E.href=d,o&&E.setAttribute("nonce",o),document.head.appendChild(E),c)return new Promise((v,f)=>{E.addEventListener("load",v),E.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${d}`)))})}))}function u(s){const r=new Event("vite:preloadError",{cancelable:!0});if(r.payload=s,window.dispatchEvent(r),!r.defaultPrevented)throw s}return i.then(s=>{for(const r of s||[])r.status==="rejected"&&u(r.reason);return e().catch(u)})},ct={};var Ke=K('
'),$e=K(" ",1);function et(t,e){pe(e,!0);let a=U(e,"components",23,()=>[]),n=U(e,"data_0",3,null),i=U(e,"data_1",3,null);Ve(()=>e.stores.page.set(e.page)),xe(()=>{e.stores,e.page,e.constructors,a(),e.form,n(),i(),e.stores.page.notify()});let u=j(!1),s=j(!1),r=j(null);Ge(()=>{const f=e.stores.page.subscribe(()=>{R(u)&&(L(s,!0),je().then(()=>{L(r,document.title||"untitled page",!0)}))});return L(u,!0),f});const o=B(()=>e.constructors[1]);var d=$e(),c=w(d);{var S=f=>{const y=B(()=>e.constructors[0]);var g=k(),b=w(g);Y(b,()=>R(y),(O,_)=>{N(_(O,{get data(){return n()},get form(){return e.form},get params(){return e.page.params},children:(l,p)=>{var q=k(),ee=w(q);Y(ee,()=>R(o),(te,re)=>{N(re(te,{get data(){return i()},get form(){return e.form},get params(){return e.page.params}}),D=>a()[1]=D,()=>{var D;return(D=a())==null?void 0:D[1]})}),I(l,q)},$$slots:{default:!0}}),l=>a()[0]=l,()=>{var l;return(l=a())==null?void 0:l[0]})}),I(f,g)},A=f=>{const y=B(()=>e.constructors[0]);var g=k(),b=w(g);Y(b,()=>R(y),(O,_)=>{N(_(O,{get data(){return n()},get form(){return e.form},get params(){return e.page.params}}),l=>a()[0]=l,()=>{var l;return(l=a())==null?void 0:l[0]})}),I(f,g)};C(c,f=>{e.constructors[1]?f(S):f(A,-1)})}var E=Be(c,2);{var v=f=>{var y=Ke(),g=Ce(y);{var b=O=>{var _=Fe();Ne(()=>ze(_,R(r))),I(O,_)};C(g,O=>{R(s)&&O(b)})}Ye(y),I(f,y)};C(E,f=>{R(u)&&f(v)})}I(t,d),ke()}const _t=He(et),dt=[()=>m(()=>import("../nodes/0.D3wXY_0K.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11]),import.meta.url),()=>m(()=>import("../nodes/1.Dgii_8lh.js"),__vite__mapDeps([12,1,2,13,5,9,10,4,8]),import.meta.url),()=>m(()=>import("../nodes/2.BMCUuUxB.js"),__vite__mapDeps([14,1,2,10,5,6,15,16]),import.meta.url),()=>m(()=>import("../nodes/3.CFDiiGpK.js"),__vite__mapDeps([17,1,2,13,10,8,4,9]),import.meta.url),()=>m(()=>import("../nodes/4.YDL696B2.js"),__vite__mapDeps([18,1,2,10,5,6,19,20,8,4,9,21]),import.meta.url),()=>m(()=>import("../nodes/5.DHfYhdex.js"),__vite__mapDeps([22,1,2,10,5,6,8,4,9,23]),import.meta.url),()=>m(()=>import("../nodes/6.BiQ3_GJa.js"),__vite__mapDeps([24,1,2,5,6,19,20,9,10,4,25]),import.meta.url),()=>m(()=>import("../nodes/7.BEIquz8f.js"),__vite__mapDeps([26,1,2,5,6,19,20,8,4,9,10,27]),import.meta.url),()=>m(()=>import("../nodes/8.D4QctIPu.js"),__vite__mapDeps([28,1,2,5,6,29,19,20,30]),import.meta.url),()=>m(()=>import("../nodes/9.DflEy3LG.js"),__vite__mapDeps([31,1,2,3,4,5,6,19,7,8,9,10,32]),import.meta.url),()=>m(()=>import("../nodes/10.BvOkMiuT.js"),__vite__mapDeps([33,1,2,3,4,5,6,29,19,20,7,8,9,10,34]),import.meta.url),()=>m(()=>import("../nodes/11.DnvWFHPj.js"),__vite__mapDeps([35,1,2,3,4,5,6,29,19,20,7,8,9,10,36]),import.meta.url),()=>m(()=>import("../nodes/12.CRx3MqWn.js"),__vite__mapDeps([37,1,2,5,6,29,19,15,20,38]),import.meta.url),()=>m(()=>import("../nodes/13.CB7FlS8h.js"),__vite__mapDeps([39,1,2,5,6,29,40]),import.meta.url),()=>m(()=>import("../nodes/14.CFDiiGpK.js"),__vite__mapDeps([41,1,2,13,10,8,4,9]),import.meta.url)],ft=[],lt={"/":[2],"/aliases":[3],"/auth/change-password":[4],"/auth/dashboard":[5],"/auth/forgot":[6],"/auth/login":[7],"/domains":[8],"/domains/[name]":[9],"/domains/[name]/aliases":[10],"/domains/[name]/users":[11],"/logs":[12],"/queue":[13],"/users":[14]},$={handleError:({error:t})=>{console.error(t)},reroute:()=>{},transport:{}},tt=Object.fromEntries(Object.entries($.transport).map(([t,e])=>[t,e.decode])),mt=Object.fromEntries(Object.entries($.transport).map(([t,e])=>[t,e.encode])),vt=!1,ht=(t,e)=>tt[t](e);export{ht as decode,tt as decoders,lt as dictionary,mt as encoders,vt as hash,$ as hooks,ct as matchers,dt as nodes,_t as root,ft as server_loads}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/entry/start.tprRzko2.js b/frontend/.svelte-kit/output/client/_app/immutable/entry/start.tprRzko2.js new file mode 100644 index 0000000..5305aa3 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/entry/start.tprRzko2.js @@ -0,0 +1 @@ +import{a as r}from"../chunks/RKc8iKz_.js";import{w as t}from"../chunks/CfgL3m1f.js";export{t as load_css,r as start}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/0.D3wXY_0K.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/0.D3wXY_0K.js new file mode 100644 index 0000000..8472483 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/0.D3wXY_0K.js @@ -0,0 +1 @@ +import{c as A,a as h,f as q}from"../chunks/CJv7FbHz.js";import{w as j,a9 as z,p as Q,a8 as U,s as v,g as r,a3 as x,a as V,a0 as B,a4 as n,a2 as _,a5 as i,a7 as W}from"../chunks/DtGl34IE.js";import{s as G,a as H}from"../chunks/B3ZK_jYJ.js";import{d as J,a as K,s as O}from"../chunks/n1byU5WW.js";import{B as X,i as C}from"../chunks/-EcHSJia.js";import{p as Y}from"../chunks/B7kAneMc.js";import{g as f}from"../chunks/RKc8iKz_.js";function E(u,o,...d){var m=new X(u);j(()=>{const l=o()??null;m.ensure(l,l&&(s=>l(s,...d)))},z)}var Z=q('
Loading...
'),$=q(' '),aa=q('');function na(u,o){Q(o,!0);const d=()=>G(Y,"$page",m),[m,l]=H();let s=B(null),p=B(!0);U(()=>{d().url.pathname.startsWith("/auth/")?v(p,!1):I()});async function I(){var a;const e=localStorage.getItem("token");if(!e){f("/auth/login");return}try{const t=await fetch("/api/auth/me",{headers:{Authorization:`Bearer ${e}`}});if(!t.ok){f("/auth/login");return}const c=await t.json();if(v(s,c.data,!0),((a=r(s))==null?void 0:a.role)!=="admin"){f("/auth/dashboard");return}}catch{f("/auth/login")}finally{v(p,!1)}}function L(){localStorage.removeItem("token"),v(s,null),f("/auth/login")}var b=A(),S=x(b);{var T=e=>{var a=Z();h(e,a)},D=e=>{var a=aa(),t=n(a),c=_(n(t),4),k=n(c);{var M=g=>{var y=$(),R=n(y,!0);i(y),W(()=>O(R,r(s).username||r(s).email)),h(g,y)};C(k,g=>{r(s)&&g(M)})}var N=_(k,4);i(c),i(t);var w=_(t,2),P=n(w);E(P,()=>o.children),i(w),i(a),K("click",N,L),h(e,a)},F=e=>{var a=A(),t=x(a);E(t,()=>o.children),h(e,a)};C(S,e=>{var a;r(p)?e(T):((a=r(s))==null?void 0:a.role)==="admin"?e(D,1):e(F,-1)})}h(u,b),V(),l()}J(["click"]);export{na as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/1.Dgii_8lh.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/1.Dgii_8lh.js new file mode 100644 index 0000000..a5bb0fa --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/1.Dgii_8lh.js @@ -0,0 +1 @@ +import{a as h,f as g}from"../chunks/CJv7FbHz.js";import{i as l}from"../chunks/DFRBE_Uq.js";import{p as v,a3 as d,a7 as _,a as x,a4 as e,a5 as o,a2 as $}from"../chunks/DtGl34IE.js";import{s as p}from"../chunks/n1byU5WW.js";import{p as m}from"../chunks/CfgL3m1f.js";import{s as k}from"../chunks/RKc8iKz_.js";const b={get error(){return m.error},get status(){return m.status}};k.updated.check;const i=b;var E=g("

",1);function B(f,n){v(n,!1),l();var t=E(),r=d(t),c=e(r,!0);o(r);var a=$(r,2),u=e(a,!0);o(a),_(()=>{var s;p(c,i.status),p(u,(s=i.error)==null?void 0:s.message)}),h(f,t),x()}export{B as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/10.BvOkMiuT.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/10.BvOkMiuT.js new file mode 100644 index 0000000..b154daf --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/10.BvOkMiuT.js @@ -0,0 +1 @@ +import{a as m,f as y}from"../chunks/CJv7FbHz.js";import{p as Z,a0 as _,a1 as I,a8 as aa,s as i,a3 as N,a7 as D,a as ea,a2 as o,a4 as r,a5 as s,g as t,a6 as ta}from"../chunks/DtGl34IE.js";import{s as sa,a as oa}from"../chunks/B3ZK_jYJ.js";import{d as ra,a as w,s as F,e as la}from"../chunks/n1byU5WW.js";import{i as R}from"../chunks/-EcHSJia.js";import{e as ia,i as da}from"../chunks/ecAlPOj8.js";import{s as T,r as U}from"../chunks/e1WBZ7UL.js";import{b as q}from"../chunks/ayyTDfEa.js";import{p as na}from"../chunks/B7kAneMc.js";var va=y("

Loading...

"),ca=y("

No aliases configured yet.

"),ua=y(' '),pa=y('
SourceDestinationActions
'),fa=y(' ',1),ma=y('

Aliases

',1);function Aa(L,O){Z(O,!0);const B=()=>sa(na,"$page",J),[J,M]=oa();let A=_(I([])),S=_(!0),b=_(!1),p=_(I({source:"",destination:""})),l=_("");async function $(a){try{const e=await fetch(`/api/domains/${encodeURIComponent(a)}/aliases`);if(e.ok){const d=await e.json();i(A,d.data||[],!0)}}catch(e){console.error("Failed to load aliases:",e)}finally{i(S,!1)}}async function P(){try{const a=await fetch(`/api/domains/${encodeURIComponent(t(l))}/aliases`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t(p))});if(a.ok)i(b,!1),i(p,{source:"",destination:""},!0),await $(t(l));else{const e=await a.json();alert(e.error||"Failed to create alias")}}catch(a){console.error("Failed to create alias:",a)}}async function G(a){if(confirm("Delete this alias?"))try{await fetch(`/api/domains/${encodeURIComponent(t(l))}/aliases/${a}`,{method:"DELETE"}),await $(t(l))}catch(e){console.error("Failed to delete alias:",e)}}aa(()=>{const a=B().params.name;a&&(i(l,a,!0),$(a))});var j=ma(),C=N(j),z=r(C),H=r(z);s(z);var K=o(z,4);s(C);var E=o(C,2);{var Q=a=>{var e=va();m(a,e)},V=a=>{var e=ca();m(a,e)},W=a=>{var e=pa(),d=o(r(e));ia(d,21,()=>t(A),da,(g,n)=>{var v=ua(),c=r(v),h=r(c,!0);s(c);var f=o(c),k=r(f,!0);s(f);var x=o(f),u=r(x);s(x),s(v),D(()=>{F(h,t(n).source),F(k,t(n).destination)}),w("click",u,()=>G(t(n).id)),m(g,v)}),s(d),s(e),m(a,e)};R(E,a=>{t(S)?a(Q):t(A).length===0?a(V,1):a(W,-1)})}var X=o(E,2);{var Y=a=>{var e=fa(),d=N(e),g=o(d,2),n=o(r(g),2),v=r(n),c=o(r(v));U(c),s(v);var h=o(v,2),f=o(r(h));U(f),s(h);var k=o(h,2),x=r(k);ta(2),s(k),s(n),s(g),D(()=>T(c,"placeholder",`info@${t(l)??""}`)),w("click",d,()=>i(b,!1)),la("submit",n,u=>{u.preventDefault(),P()}),q(c,()=>t(p).source,u=>t(p).source=u),q(f,()=>t(p).destination,u=>t(p).destination=u),w("click",x,()=>i(b,!1)),m(a,e)};R(X,a=>{t(b)&&a(Y)})}D(()=>{T(z,"href",`/domains/${t(l)??""}`),F(H,`← Back to ${t(l)??""}`)}),w("click",K,()=>i(b,!0)),m(L,j),ea(),M()}ra(["click"]);export{Aa as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/11.DnvWFHPj.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/11.DnvWFHPj.js new file mode 100644 index 0000000..7662206 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/11.DnvWFHPj.js @@ -0,0 +1 @@ +import{a as b,f as _}from"../chunks/CJv7FbHz.js";import{p as ot,a0 as w,a1 as M,a8 as rt,s as c,a3 as O,a7 as D,a as lt,a2 as s,a4 as r,a5 as o,g as a,a6 as it}from"../chunks/DtGl34IE.js";import{s as nt,a as dt}from"../chunks/B3ZK_jYJ.js";import{d as ct,a as $,s as q,e as vt}from"../chunks/n1byU5WW.js";import{i as Q}from"../chunks/-EcHSJia.js";import{e as ut,i as pt}from"../chunks/ecAlPOj8.js";import{s as R,r as E}from"../chunks/e1WBZ7UL.js";import{b as N}from"../chunks/ayyTDfEa.js";import{p as mt}from"../chunks/B7kAneMc.js";var ft=_("

Loading...

"),bt=_("

No users configured yet.

"),_t=_(' '),ht=_('
EmailQuotaUsedActions
'),zt=_(' ',1),gt=_('

Users

',1);function Bt(L,P){ot(P,!0);const S=()=>nt(mt,"$page",G),[G,J]=dt();let C=w(M([])),T=w(!0),h=w(!1),i=w(M({email:"",password:"",quota:0})),n=w("");async function F(t){try{const e=await fetch(`/api/domains/${encodeURIComponent(t)}/users`);if(e.ok){const v=await e.json();c(C,v.data||[],!0)}}catch(e){console.error("Failed to load users:",e)}finally{c(T,!1)}}async function K(){try{const t=await fetch(`/api/domains/${encodeURIComponent(a(n))}/users`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a(i))});if(t.ok)c(h,!1),c(i,{email:"",password:"",quota:0},!0),await F(a(n));else{const e=await t.json();alert(e.error||"Failed to create user")}}catch(t){console.error("Failed to create user:",t)}}async function H(t){if(confirm("Delete this user? Mailbox will NOT be deleted."))try{await fetch(`/api/domains/${encodeURIComponent(a(n))}/users/${t}`,{method:"DELETE"}),await F(a(n))}catch(e){console.error("Failed to delete user:",e)}}function j(t){return t===0?"Default":t<1024?t+" B":t<1024*1024?(t/1024).toFixed(1)+" KB":t<1024*1024*1024?(t/1024/1024).toFixed(1)+" MB":(t/1024/1024/1024).toFixed(2)+" GB"}rt(()=>{const t=S().params.name;t&&(c(n,t,!0),F(t))});var A=gt(),B=O(A),y=r(B),V=r(y);o(y);var W=s(y,4);o(B);var I=s(B,2);{var X=t=>{var e=ft();b(t,e)},Y=t=>{var e=bt();b(t,e)},Z=t=>{var e=ht(),v=s(r(e));ut(v,21,()=>a(C),pt,(x,d)=>{var u=_t(),p=r(u),z=r(p,!0);o(p);var m=s(p),g=r(m,!0);o(m);var f=s(m),k=r(f,!0);o(f);var U=s(f),l=r(U);o(U),o(u),D((et,st)=>{q(z,a(d).email),q(g,et),q(k,st)},[()=>j(a(d).quota),()=>j(a(d).used_quota)]),$("click",l,()=>H(a(d).id)),b(x,u)}),o(v),o(e),b(t,e)};Q(I,t=>{a(T)?t(X):a(C).length===0?t(Y,1):t(Z,-1)})}var tt=s(I,2);{var at=t=>{var e=zt(),v=O(e),x=s(v,2),d=s(r(x),2),u=r(d),p=s(r(u));E(p),o(u);var z=s(u,2),m=s(r(z));E(m),o(z);var g=s(z,2),f=s(r(g));E(f),o(g);var k=s(g,2),U=r(k);it(2),o(k),o(d),o(x),D(()=>R(p,"placeholder",`user@${a(n)??""}`)),$("click",v,()=>c(h,!1)),vt("submit",d,l=>{l.preventDefault(),K()}),N(p,()=>a(i).email,l=>a(i).email=l),N(m,()=>a(i).password,l=>a(i).password=l),N(f,()=>a(i).quota,l=>a(i).quota=l),$("click",U,()=>c(h,!1)),b(t,e)};Q(tt,t=>{a(h)&&t(at)})}D(()=>{R(y,"href",`/domains/${a(n)??""}`),q(V,`← Back to ${a(n)??""}`)}),$("click",W,()=>c(h,!0)),b(L,A),lt(),J()}ct(["click"]);export{Bt as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/12.CRx3MqWn.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/12.CRx3MqWn.js new file mode 100644 index 0000000..2164ff6 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/12.CRx3MqWn.js @@ -0,0 +1 @@ +import{a as d,f as m}from"../chunks/CJv7FbHz.js";import{l as Z,c as A,aj as $,t as ee,K as ae,ak as re,al as te,p as se,a0 as g,a1 as oe,a8 as le,a3 as ie,g as s,a as ne,s as c,a2 as v,a4 as f,a5 as u,a7 as U}from"../chunks/DtGl34IE.js";import{d as ve,a as H,s as x}from"../chunks/n1byU5WW.js";import{i as ue}from"../chunks/-EcHSJia.js";import{e as fe,i as pe}from"../chunks/ecAlPOj8.js";import{r as _e}from"../chunks/e1WBZ7UL.js";import{s as ce}from"../chunks/BYrNiJ2z.js";import{b as de}from"../chunks/ayyTDfEa.js";function W(e,t,p=!1){if(e.multiple){if(t==null)return;if(!ae(t))return re();for(var o of e.options)o.selected=t.includes(h(o));return}for(o of e.options){var i=h(o);if(te(i,t)){o.selected=!0;return}}(!p||t!==void 0)&&(e.selectedIndex=-1)}function me(e){var t=new MutationObserver(()=>{W(e,e.__value)});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),ee(()=>{t.disconnect()})}function ge(e,t,p=t){var o=new WeakSet,i=!0;Z(e,"change",n=>{var _=n?"[selected]":":checked",l;if(e.multiple)l=[].map.call(e.querySelectorAll(_),h);else{var b=e.querySelector(_)??e.querySelector("option:not([disabled])");l=b&&h(b)}p(l),e.__value=l,A!==null&&o.add(A)}),$(()=>{var n=t();if(e===document.activeElement){var _=A;if(o.has(_))return}if(W(e,n,i),i&&n===void 0){var l=e.querySelector(":checked");l!==null&&(n=h(l),p(n))}e.__value=n,i=!1}),me(e)}function h(e){return"__value"in e?e.__value:e.value}var he=m("

Loading...

"),be=m('

'),ye=m("

No log entries found.

"),ke=m('
'),we=m('
'),xe=m('

Mail Logs

',1);function Me(e,t){se(t,!0);let p=g(oe([])),o=g(!0),i=g(""),n=g(""),_=g(1);async function l(){c(o,!0),c(i,"");try{const a=await fetch(`/api/logs?hours=${s(_)}&filter=${encodeURIComponent(s(n))}`);if(a.ok){const r=await a.json();c(p,r.data||[],!0)}else c(i,"Failed to load logs")}catch(a){c(i,"Connection error"),console.error("Failed to load logs:",a)}finally{c(o,!1)}}function b(a){const r=a.toLowerCase();return r==="err"||r==="error"?"error":r==="warning"||r==="warn"?"warning":r==="info"?"info":""}le(()=>{l()});var K=xe(),L=ie(K),N=v(f(L),2),q=f(N),y=v(f(q)),F=f(y);F.value=F.__value=1;var S=v(F);S.value=S.__value=6;var C=v(S);C.value=C.__value=24;var O=v(C);O.value=O.__value=48,u(y),u(q);var j=v(q,2),E=v(f(j));_e(E),u(j);var z=v(j,2);u(N),u(L);var B=v(L,2);{var D=a=>{var r=he();d(a,r)},G=a=>{var r=be(),I=f(r,!0);u(r),U(()=>x(I,s(i))),d(a,r)},J=a=>{var r=ye();d(a,r)},Q=a=>{var r=we();fe(r,21,()=>s(p),pe,(I,k)=>{var w=ke(),M=f(w),T=f(M,!0);u(M);var R=v(M,2),V=f(R);u(R);var P=v(R,2),X=f(P,!0);u(P),u(w),U(Y=>{ce(w,1,`log-entry ${Y??""}`,"svelte-1lsf4ps"),x(T,s(k).timestamp),x(V,`[${s(k).priority??""}]`),x(X,s(k).message)},[()=>b(s(k).priority)]),d(I,w)}),u(r),d(a,r)};ue(B,a=>{s(o)?a(D):s(i)?a(G,1):s(p).length===0?a(J,2):a(Q,-1)})}H("change",y,l),ge(y,()=>s(_),a=>c(_,a)),H("keydown",E,a=>a.key==="Enter"&&l()),de(E,()=>s(n),a=>c(n,a)),H("click",z,l),d(e,K),ne()}ve(["change","keydown","click"]);export{Me as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/13.CB7FlS8h.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/13.CB7FlS8h.js new file mode 100644 index 0000000..1c15ab4 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/13.CB7FlS8h.js @@ -0,0 +1 @@ +import{a as i,f as d}from"../chunks/CJv7FbHz.js";import{p as Y,a0 as w,a1 as Z,a8 as $,a3 as ee,a as te,s as u,a2 as o,a4 as s,a5 as r,g as a,a7 as z}from"../chunks/DtGl34IE.js";import{d as ae,a as D,s as l}from"../chunks/n1byU5WW.js";import{i as re}from"../chunks/-EcHSJia.js";import{e as se,i as oe}from"../chunks/ecAlPOj8.js";var ce=d("

Loading...

"),le=d('

'),ie=d("

Queue is empty.

"),ue=d(' '),de=d('
IDSenderRecipientsSizeTimeReasonActions
'),ve=d('

Mail Queue

',1);function pe(B,E){Y(E,!0);let h=w(Z([])),g=w(!0),v=w("");async function n(){u(g,!0),u(v,"");try{const e=await fetch("/api/queue");if(e.ok){const t=await e.json();u(h,t.data||[],!0)}else u(v,"Failed to load queue")}catch(e){u(v,"Connection error"),console.error("Failed to load queue:",e)}finally{u(g,!1)}}async function T(e){try{await fetch(`/api/queue/${e}/requeue`,{method:"POST"}),await n()}catch(t){console.error("Failed to requeue:",t)}}async function j(e){if(confirm("Delete this message from queue?"))try{await fetch(`/api/queue/${e}`,{method:"DELETE"}),await n()}catch(t){console.error("Failed to delete from queue:",t)}}function L(e){return e<1024?e+" B":e<1024*1024?(e/1024).toFixed(1)+" KB":(e/1024/1024).toFixed(1)+" MB"}$(()=>{n()});var Q=ve(),q=ee(Q),M=o(s(q),2);r(q);var y=o(q,2);{var A=e=>{var t=ce();i(e,t)},C=e=>{var t=le(),f=s(t,!0);r(t),z(()=>l(f,a(v))),i(e,t)},I=e=>{var t=ie();i(e,t)},K=e=>{var t=de(),f=o(s(t));se(f,21,()=>a(h),oe,(O,c)=>{var p=ue(),_=s(p),P=s(_,!0);r(_);var m=o(_),G=s(m,!0);r(m);var b=o(m),H=s(b,!0);r(b);var x=o(b),J=s(x,!0);r(x);var F=o(x),N=s(F,!0);r(F);var k=o(F),U=s(k,!0);r(k);var R=o(k),S=s(R),V=o(S,2);r(R),r(p),z((W,X)=>{l(P,a(c).id),l(G,a(c).sender),l(H,W),l(J,X),l(N,a(c).time),l(U,a(c).reason)},[()=>a(c).recipients.join(", "),()=>L(a(c).size)]),D("click",S,()=>T(a(c).id)),D("click",V,()=>j(a(c).id)),i(O,p)}),r(f),r(t),i(e,t)};re(y,e=>{a(g)?e(A):a(v)?e(C,1):a(h).length===0?e(I,2):e(K,-1)})}D("click",M,n),i(B,Q),te()}ae(["click"]);export{pe as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/14.CFDiiGpK.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/14.CFDiiGpK.js new file mode 100644 index 0000000..0b5a50b --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/14.CFDiiGpK.js @@ -0,0 +1 @@ +import{a as r,f as m}from"../chunks/CJv7FbHz.js";import{i as t}from"../chunks/DFRBE_Uq.js";import{o as i}from"../chunks/DR7h53-u.js";import{p as s,a as n}from"../chunks/DtGl34IE.js";import{g as f}from"../chunks/RKc8iKz_.js";var e=m("

Redirecting to domains...

");function l(o,a){s(a,!1),i(()=>{f("/domains")}),t();var p=e();r(o,p),n()}export{l as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/2.BMCUuUxB.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/2.BMCUuUxB.js new file mode 100644 index 0000000..e8be904 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/2.BMCUuUxB.js @@ -0,0 +1 @@ +import{a as p,f as n}from"../chunks/CJv7FbHz.js";import{o as L}from"../chunks/DR7h53-u.js";import{p as M,a0 as b,a1 as Q,a2 as o,a3 as B,a as C,s as q,g as l,a4 as s,a5 as t,a6 as i,a7 as G}from"../chunks/DtGl34IE.js";import{s as v}from"../chunks/n1byU5WW.js";import{i as H}from"../chunks/-EcHSJia.js";import{s as I}from"../chunks/BYrNiJ2z.js";var J=n("

Loading...

"),K=n('

Domains

Users

Aliases

Queued Emails

'),N=n("

Dashboard

",1);function X(w,z){M(z,!0);let r=b(Q({totalDomains:0,totalUsers:0,totalAliases:0,queueSize:0})),g=b(!0);L(async()=>{try{const a=await fetch("/api/stats");if(a.ok){const e=await a.json();q(r,e.data,!0)}}catch(a){console.error("Failed to fetch stats:",a)}finally{q(g,!1)}});var m=N(),A=o(B(m),2);{var S=a=>{var e=J();p(a,e)},U=a=>{var e=K(),h=s(e),f=s(h),j=s(f,!0);t(f),i(2),t(h);var c=o(h,2),_=s(c),k=s(_,!0);t(_),i(2),t(c);var u=o(c,2),x=s(u),E=s(x,!0);t(x),i(2),t(u);var d=o(u,2);let y;var D=s(d),F=s(D,!0);t(D),i(2),t(d),t(e),G(()=>{v(j,l(r).totalDomains),v(k,l(r).totalUsers),v(E,l(r).totalAliases),y=I(d,1,"stat-card svelte-1uha8ag",null,y,{warning:l(r).queueSize>10}),v(F,l(r).queueSize)}),p(a,e)};H(A,a=>{l(g)?a(S):a(U,-1)})}p(w,m),C()}export{X as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/3.CFDiiGpK.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/3.CFDiiGpK.js new file mode 100644 index 0000000..0b5a50b --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/3.CFDiiGpK.js @@ -0,0 +1 @@ +import{a as r,f as m}from"../chunks/CJv7FbHz.js";import{i as t}from"../chunks/DFRBE_Uq.js";import{o as i}from"../chunks/DR7h53-u.js";import{p as s,a as n}from"../chunks/DtGl34IE.js";import{g as f}from"../chunks/RKc8iKz_.js";var e=m("

Redirecting to domains...

");function l(o,a){s(a,!1),i(()=>{f("/domains")}),t();var p=e();r(o,p),n()}export{l as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/4.YDL696B2.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/4.YDL696B2.js new file mode 100644 index 0000000..16b5869 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/4.YDL696B2.js @@ -0,0 +1 @@ +import{a as p,f as g}from"../chunks/CJv7FbHz.js";import{o as W}from"../chunks/DR7h53-u.js";import{p as X,a7 as q,g as t,a as Y,a2 as i,a4 as o,a0 as v,a5 as r,a6 as Z,s}from"../chunks/DtGl34IE.js";import{d as aa,a as ea,e as ta,s as B}from"../chunks/n1byU5WW.js";import{i as I}from"../chunks/-EcHSJia.js";import{r as L}from"../chunks/e1WBZ7UL.js";import{b as N}from"../chunks/ayyTDfEa.js";import{g as f}from"../chunks/RKc8iKz_.js";var sa=g("Logged in as "),oa=g('
'),ra=g('
Password changed successfully!
'),ia=g('

Change Password

');function pa(F,J){X(J,!0);let c=null,u=v(""),h=v(""),m=v(""),l=v(""),z=v(!1),n=v(!1);W(async()=>{const a=localStorage.getItem("token");if(!a){await f("/auth/login");return}try{const e=await fetch("/api/auth/me",{headers:{Authorization:`Bearer ${a}`}});if(!e.ok){await f("/auth/login");return}c=(await e.json()).data}catch{await f("/auth/login")}});async function M(a){if(a.preventDefault(),s(l,""),t(h)!==t(m)){s(l,"Passwords do not match");return}if(t(h).length<8){s(l,"Password must be at least 8 characters");return}s(n,!0);try{const e=await fetch("/api/auth/change-password",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${localStorage.getItem("token")}`},body:JSON.stringify({oldPassword:t(u),newPassword:t(h)})}),d=await e.json();if(!e.ok){s(l,d.error||"Failed to change password",!0);return}s(z,!0),s(u,""),s(h,""),s(m,"")}catch{s(l,"Connection error")}finally{s(n,!1)}}function G(){localStorage.removeItem("token"),f("/auth/login")}var w=ia(),b=o(w),A=o(b),D=i(o(A),2),E=o(D);{var H=a=>{var e=sa(),d=i(o(e)),V=o(d,!0);r(d),r(e),q(()=>B(V,c.email||c.username)),p(a,e)};I(E,a=>{c&&a(H)})}var K=i(E,2);r(D),r(A),r(b);var O=i(b,2),T=o(O);{var Q=a=>{var e=oa(),d=o(e,!0);r(e),q(()=>B(d,t(l))),p(a,e)};I(T,a=>{t(l)&&a(Q)})}var $=i(T,2);{var R=a=>{var e=ra();p(a,e)};I($,a=>{t(z)&&a(R)})}var _=i($,2),P=o(_),y=i(o(P));L(y),r(P);var k=i(P,2),C=i(o(k));L(C),r(k);var x=i(k,2),S=i(o(x));L(S),r(x);var j=i(x,2),U=o(j,!0);r(j),r(_),Z(2),r(O),r(w),q(()=>{y.disabled=t(n),C.disabled=t(n),S.disabled=t(n),j.disabled=t(n),B(U,t(n)?"Changing...":"Change Password")}),ea("click",K,G),ta("submit",_,M),N(y,()=>t(u),a=>s(u,a)),N(C,()=>t(h),a=>s(h,a)),N(S,()=>t(m),a=>s(m,a)),p(F,w),Y()}aa(["click"]);export{pa as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/5.DHfYhdex.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/5.DHfYhdex.js new file mode 100644 index 0000000..84e60ea --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/5.DHfYhdex.js @@ -0,0 +1 @@ +import{a as n,f as c}from"../chunks/CJv7FbHz.js";import{o as H}from"../chunks/DR7h53-u.js";import{p as J,a as K,a2 as r,a4 as a,s as O,a5 as s,g as T,a0 as V,a7 as g,a3 as W,a6 as X}from"../chunks/DtGl34IE.js";import{d as Y,a as Z,s as i}from"../chunks/n1byU5WW.js";import{i as h}from"../chunks/-EcHSJia.js";import{g as d}from"../chunks/RKc8iKz_.js";var $=c("Logged in as "),aa=c("

Loading...

"),sa=c('
Quota:
'),ta=c('

Account Information

Email:
Username:
Role:

Quick Actions

',1),ea=c('

User Dashboard

');function da(U,B){J(B,!0);let t=null,_=V(!0);H(async()=>{const e=localStorage.getItem("token");if(!e){await d("/auth/login");return}try{const o=await fetch("/api/auth/me",{headers:{Authorization:`Bearer ${e}`}});if(!o.ok){await d("/auth/login");return}if(t=(await o.json()).data,(t==null?void 0:t.role)==="admin"){await d("/");return}}catch{await d("/auth/login")}finally{O(_,!1)}});function M(){localStorage.removeItem("token"),d("/auth/login")}var m=ea(),p=a(m),w=r(a(p),2),b=a(w);{var N=e=>{var o=$(),l=r(a(o)),v=a(l,!0);s(l),s(o),g(()=>i(v,t.email||t.username)),n(e,o)};h(b,e=>{t&&e(N)})}var Q=r(b,2);s(w),s(p);var A=r(p,2),S=a(A);{var j=e=>{var o=aa();n(e,o)},z=e=>{var o=ta(),l=W(o),v=r(a(l),2),L=r(a(v),2),C=a(L,!0);s(L),s(v);var u=r(v,2),q=r(a(u),2),D=a(q,!0);s(q),s(u);var f=r(u,2),y=r(a(f),2),E=a(y,!0);s(y),s(f);var F=r(f,2);{var P=x=>{var k=sa(),I=r(a(k),2),R=a(I,!0);s(I),s(k),g(G=>i(R,G),[()=>t.quota>0?(t.quota/1024/1024).toFixed(0)+" MB":"Unlimited"]),n(x,k)};h(F,x=>{t.quota!==void 0&&x(P)})}s(l),X(2),g(()=>{i(C,t.email||"N/A"),i(D,t.username||"N/A"),i(E,t.role)}),n(e,o)};h(S,e=>{T(_)?e(j):t&&e(z,1)})}s(A),s(m),Z("click",Q,M),n(U,m),K()}Y(["click"]);export{da as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/6.BiQ3_GJa.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/6.BiQ3_GJa.js new file mode 100644 index 0000000..b512f8a --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/6.BiQ3_GJa.js @@ -0,0 +1 @@ +import{a as v,f}from"../chunks/CJv7FbHz.js";import{a2 as c,a4 as i,g as s,a5 as o,a0 as d,a7 as y,a6 as k,a3 as E,s as r}from"../chunks/DtGl34IE.js";import{s as x,e as O}from"../chunks/n1byU5WW.js";import{i as w}from"../chunks/-EcHSJia.js";import{r as T}from"../chunks/e1WBZ7UL.js";import{b as D}from"../chunks/ayyTDfEa.js";import"../chunks/CfgL3m1f.js";var I=f('
'),J=f('

If an account exists with that email or username, a password reset link has been sent.

Please check your inbox.

',1),N=f(`

Enter your email address or username and we'll send you a link to reset your password.

`,1),U=f('');function V(S){let u=d(""),l=d(""),b=d(!1),n=d(!1);async function L(e){e.preventDefault(),r(l,""),r(n,!0);try{const a=await fetch("/api/auth/forgot",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({identifier:s(u)})}),t=await a.json();if(!a.ok){r(l,t.error||"Request failed",!0);return}r(b,!0)}catch{r(l,"Connection error")}finally{r(n,!1)}}var m=U(),g=i(m),_=c(i(g),2);{var P=e=>{var a=I(),t=i(a,!0);o(a),y(()=>x(t,s(l))),v(e,a)};w(_,e=>{s(l)&&e(P)})}var R=c(_,2);{var j=e=>{var a=J();k(2),v(e,a)},q=e=>{var a=N(),t=c(E(a),2),p=i(t),z=c(i(p));T(z),o(p);var h=c(p,2),B=i(h,!0);o(h),o(t),k(2),y(()=>{z.disabled=s(n),h.disabled=s(n),x(B,s(n)?"Sending...":"Send Reset Link")}),O("submit",t,L),D(z,()=>s(u),C=>r(u,C)),v(e,a)};w(R,e=>{s(b)?e(j):e(q,-1)})}o(g),o(m),v(S,m)}export{V as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/7.BEIquz8f.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/7.BEIquz8f.js new file mode 100644 index 0000000..8e5713c --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/7.BEIquz8f.js @@ -0,0 +1 @@ +import{a as y,f as j}from"../chunks/CJv7FbHz.js";import{p as A,a7 as S,g as t,a as D,a2 as i,a4 as s,s as r,a0 as p,a5 as o}from"../chunks/DtGl34IE.js";import{e as F,s as x}from"../chunks/n1byU5WW.js";import{i as J}from"../chunks/-EcHSJia.js";import{r as k}from"../chunks/e1WBZ7UL.js";import{b as C}from"../chunks/ayyTDfEa.js";import{g as I}from"../chunks/RKc8iKz_.js";var L=j('
'),N=j('');function Q(q,E){A(E,!0);let m=p(""),d=p(""),l=p(""),n=p(!1);async function M(){r(n,!0),r(l,"");try{const e=await fetch("/api/auth/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:t(m),password:t(d)})}),a=await e.json();if(!e.ok){r(l,a.error||"Login failed",!0);return}localStorage.setItem("token",a.data.token),a.data.user.role==="admin"?I("/"):I("/auth/dashboard")}catch{r(l,"Connection error")}finally{r(n,!1)}}var v=N(),g=s(v),h=i(s(g),4);{var O=e=>{var a=L(),T=s(a,!0);o(a),S(()=>x(T,t(l))),y(e,a)};J(h,e=>{t(l)&&e(O)})}var u=i(h,2),c=s(u),_=i(s(c));k(_),o(c);var f=i(c,2),w=i(s(f));k(w),o(f);var b=i(f,4),P=s(b,!0);o(b),o(u),o(g),o(v),S(()=>{b.disabled=t(n),x(P,t(n)?"Signing in...":"Sign In")}),F("submit",u,e=>{e.preventDefault(),M()}),C(_,()=>t(m),e=>r(m,e)),C(w,()=>t(d),e=>r(d,e)),y(q,v),D()}export{Q as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/8.D4QctIPu.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/8.D4QctIPu.js new file mode 100644 index 0000000..19836cd --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/8.D4QctIPu.js @@ -0,0 +1 @@ +import{a as m,f}from"../chunks/CJv7FbHz.js";import{p as K,a0 as w,a1 as j,a8 as Q,a3 as R,a as V,s as c,a2 as r,a4 as s,a5 as e,g as o,a6 as W,a7 as X}from"../chunks/DtGl34IE.js";import{d as Y,a as h,e as Z,s as C}from"../chunks/n1byU5WW.js";import{i as L}from"../chunks/-EcHSJia.js";import{e as $,i as aa}from"../chunks/ecAlPOj8.js";import{r as ta,s as ea}from"../chunks/e1WBZ7UL.js";import{b as sa}from"../chunks/ayyTDfEa.js";var oa=f("

Loading...

"),ra=f("

No domains configured yet.

"),la=f(' '),ia=f('
DomainUsersAliasesActions
'),ca=f(''),na=f('

Domains

',1);function ha(N,O){K(O,!0);let _=w(j([])),A=w(!0),p=w(!1),b=w(j({name:""}));async function g(){try{const a=await fetch("/api/domains");if(a.ok){const t=await a.json();c(_,t.data||[],!0)}}catch(a){console.error("Failed to load domains:",a)}finally{c(A,!1)}}async function P(){try{(await fetch("/api/domains",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o(b))})).ok&&(c(p,!1),c(b,{name:""},!0),await g())}catch(a){console.error("Failed to create domain:",a)}}async function S(a){if(confirm("Delete this domain? Users and aliases will be deleted."))try{await fetch(`/api/domains/${a}`,{method:"DELETE"}),await g()}catch(t){console.error("Failed to delete domain:",t)}}Q(()=>{g()});var E=na(),D=R(E),U=r(s(D),2);e(D);var F=r(D,2);{var q=a=>{var t=oa();m(a,t)},J=a=>{var t=ra();m(a,t)},M=a=>{var t=ia(),n=r(s(t));$(n,21,()=>o(_),aa,(u,l)=>{var d=la(),v=s(d),y=s(v),i=s(y,!0);e(y),e(v);var k=r(v),G=s(k,!0);e(k);var x=r(k),H=s(x,!0);e(x);var T=r(x),I=s(T);e(T),e(d),X(()=>{ea(y,"href",`/domains/${o(l).name??""}/users`),C(i,o(l).name),C(G,o(l).userCount),C(H,o(l).aliasCount)}),h("click",I,()=>S(o(l).id)),m(u,d)}),e(n),e(t),m(a,t)};L(F,a=>{o(A)?a(q):o(_).length===0?a(J,1):a(M,-1)})}var z=r(F,2);{var B=a=>{var t=ca(),n=s(t),u=r(s(n),2),l=s(u),d=r(s(l));ta(d),e(l);var v=r(l,2),y=s(v);W(2),e(v),e(u),e(n),e(t),h("click",t,()=>c(p,!1)),h("click",n,i=>i.stopPropagation()),Z("submit",u,i=>{i.preventDefault(),P()}),sa(d,()=>o(b).name,i=>o(b).name=i),h("click",y,()=>c(p,!1)),m(a,t)};L(z,a=>{o(p)&&a(B)})}h("click",U,()=>c(p,!0)),m(N,E),V()}Y(["click"]);export{ha as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/9.DflEy3LG.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/9.DflEy3LG.js new file mode 100644 index 0000000..2ac9188 --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/immutable/nodes/9.DflEy3LG.js @@ -0,0 +1 @@ +import{c as J,a as i,f as c}from"../chunks/CJv7FbHz.js";import{p as K,a8 as M,a3 as D,a as N,s as m,a0 as d,g as e,a4 as t,a5 as r,a7 as y,a2 as _,a6 as C}from"../chunks/DtGl34IE.js";import{s as O,a as P}from"../chunks/B3ZK_jYJ.js";import{s as p}from"../chunks/n1byU5WW.js";import{i as Q}from"../chunks/-EcHSJia.js";import{s as $}from"../chunks/e1WBZ7UL.js";import{p as S}from"../chunks/B7kAneMc.js";var T=c("

Loading...

"),V=c('

'),W=c(' ',1),X=c("

Domain not found

");function oa(w,U){K(U,!0);const j=()=>O(S,"$page",A),[A,B]=P();let o=d(null),u=d(!0),n=d("");async function F(a){try{const s=await fetch(`/api/domains/${encodeURIComponent(a)}`);if(s.ok){const l=await s.json();m(o,l.data,!0)}else m(n,"Domain not found")}catch{m(n,"Failed to load domain")}finally{m(u,!1)}}M(()=>{const a=j().params.name;a&&F(a)});var h=J(),I=D(h);{var L=a=>{var s=T();i(a,s)},R=a=>{var s=V(),l=t(s,!0);r(s),y(()=>p(l,e(n))),i(a,s)},q=a=>{var s=W(),l=D(s),x=_(t(l),2),E=t(x,!0);r(x),r(l);var b=_(l,2),v=t(b),g=t(v),G=t(g,!0);r(g),C(2),r(v);var f=_(v,2),k=t(f),H=t(k,!0);r(k),C(2),r(f),r(b),y(()=>{p(E,e(o).name),$(v,"href",`/domains/${e(o).name??""}/users`),p(G,e(o).userCount),$(f,"href",`/domains/${e(o).name??""}/aliases`),p(H,e(o).aliasCount)}),i(a,s)},z=a=>{var s=X();i(a,s)};Q(I,a=>{e(u)?a(L):e(n)?a(R,1):e(o)?a(q,2):a(z,-1)})}i(w,h),N(),B()}export{oa as component}; diff --git a/frontend/.svelte-kit/output/client/_app/version.json b/frontend/.svelte-kit/output/client/_app/version.json new file mode 100644 index 0000000..1afd2af --- /dev/null +++ b/frontend/.svelte-kit/output/client/_app/version.json @@ -0,0 +1 @@ +{"version":"1774129207705"} \ No newline at end of file diff --git a/frontend/.svelte-kit/output/client/favicon.png b/frontend/.svelte-kit/output/client/favicon.png new file mode 100644 index 0000000..47ce666 --- /dev/null +++ b/frontend/.svelte-kit/output/client/favicon.png @@ -0,0 +1,4 @@ + + + V + diff --git a/frontend/.svelte-kit/output/prerendered/dependencies/_app/env.js b/frontend/.svelte-kit/output/prerendered/dependencies/_app/env.js new file mode 100644 index 0000000..f5427da --- /dev/null +++ b/frontend/.svelte-kit/output/prerendered/dependencies/_app/env.js @@ -0,0 +1 @@ +export const env={} \ No newline at end of file diff --git a/frontend/.svelte-kit/output/server/.vite/manifest.json b/frontend/.svelte-kit/output/server/.vite/manifest.json new file mode 100644 index 0000000..d0f7721 --- /dev/null +++ b/frontend/.svelte-kit/output/server/.vite/manifest.json @@ -0,0 +1,301 @@ +{ + ".svelte-kit/generated/server/internal.js": { + "file": "internal.js", + "name": "internal", + "src": ".svelte-kit/generated/server/internal.js", + "isEntry": true, + "imports": [ + "_root.js", + "_environment.js", + "_internal.js" + ] + }, + "_environment.js": { + "file": "chunks/environment.js", + "name": "environment" + }, + "_exports.js": { + "file": "chunks/exports.js", + "name": "exports" + }, + "_false.js": { + "file": "chunks/false.js", + "name": "false" + }, + "_index.js": { + "file": "chunks/index.js", + "name": "index", + "imports": [ + "_index2.js", + "_root.js" + ] + }, + "_index2.js": { + "file": "chunks/index2.js", + "name": "index" + }, + "_internal.js": { + "file": "chunks/internal.js", + "name": "internal", + "imports": [ + "_root.js", + "_environment.js" + ] + }, + "_root.js": { + "file": "chunks/root.js", + "name": "root", + "imports": [ + "_index2.js", + "_false.js" + ] + }, + "_shared.js": { + "file": "chunks/shared.js", + "name": "shared", + "imports": [ + "_utils.js" + ] + }, + "_state.svelte.js": { + "file": "chunks/state.svelte.js", + "name": "state.svelte", + "imports": [ + "_index2.js", + "_exports.js", + "_root.js" + ] + }, + "_utils.js": { + "file": "chunks/utils.js", + "name": "utils" + }, + "node_modules/@sveltejs/kit/src/runtime/app/server/remote/index.js": { + "file": "remote-entry.js", + "name": "remote-entry", + "src": "node_modules/@sveltejs/kit/src/runtime/app/server/remote/index.js", + "isEntry": true, + "imports": [ + "_shared.js", + "_false.js", + "_environment.js" + ] + }, + "node_modules/@sveltejs/kit/src/runtime/components/svelte-5/error.svelte": { + "file": "entries/fallbacks/error.svelte.js", + "name": "entries/fallbacks/error.svelte", + "src": "node_modules/@sveltejs/kit/src/runtime/components/svelte-5/error.svelte", + "isEntry": true, + "imports": [ + "_index2.js", + "_state.svelte.js", + "_exports.js", + "_utils.js", + "_index.js", + "_root.js" + ] + }, + "node_modules/@sveltejs/kit/src/runtime/server/index.js": { + "file": "index.js", + "name": "index", + "src": "node_modules/@sveltejs/kit/src/runtime/server/index.js", + "isEntry": true, + "imports": [ + "_false.js", + "_environment.js", + "_shared.js", + "_exports.js", + "_utils.js", + "_index.js", + "_internal.js" + ] + }, + "src/routes/+layout.svelte": { + "file": "entries/pages/_layout.svelte.js", + "name": "entries/pages/_layout.svelte", + "src": "src/routes/+layout.svelte", + "isEntry": true, + "imports": [ + "_exports.js", + "_utils.js", + "_root.js", + "_state.svelte.js" + ], + "css": [ + "_app/immutable/assets/_layout.DkgBtk4_.css" + ] + }, + "src/routes/+page.svelte": { + "file": "entries/pages/_page.svelte.js", + "name": "entries/pages/_page.svelte", + "src": "src/routes/+page.svelte", + "isEntry": true, + "css": [ + "_app/immutable/assets/_page.By2d6Bxb.css" + ] + }, + "src/routes/aliases/+page.svelte": { + "file": "entries/pages/aliases/_page.svelte.js", + "name": "entries/pages/aliases/_page.svelte", + "src": "src/routes/aliases/+page.svelte", + "isEntry": true, + "imports": [ + "_exports.js", + "_utils.js", + "_root.js", + "_state.svelte.js" + ] + }, + "src/routes/auth/change-password/+page.svelte": { + "file": "entries/pages/auth/change-password/_page.svelte.js", + "name": "entries/pages/auth/change-password/_page.svelte", + "src": "src/routes/auth/change-password/+page.svelte", + "isEntry": true, + "imports": [ + "_index2.js", + "_exports.js", + "_utils.js", + "_root.js", + "_state.svelte.js" + ], + "css": [ + "_app/immutable/assets/_page.CG2X--Z8.css" + ] + }, + "src/routes/auth/dashboard/+page.svelte": { + "file": "entries/pages/auth/dashboard/_page.svelte.js", + "name": "entries/pages/auth/dashboard/_page.svelte", + "src": "src/routes/auth/dashboard/+page.svelte", + "isEntry": true, + "imports": [ + "_exports.js", + "_utils.js", + "_root.js", + "_state.svelte.js" + ], + "css": [ + "_app/immutable/assets/_page.YbbfqdJp.css" + ] + }, + "src/routes/auth/forgot/+page.svelte": { + "file": "entries/pages/auth/forgot/_page.svelte.js", + "name": "entries/pages/auth/forgot/_page.svelte", + "src": "src/routes/auth/forgot/+page.svelte", + "isEntry": true, + "imports": [ + "_index2.js", + "_exports.js", + "_utils.js", + "_root.js", + "_state.svelte.js" + ], + "css": [ + "_app/immutable/assets/_page.w_qTFDpy.css" + ] + }, + "src/routes/auth/login/+page.svelte": { + "file": "entries/pages/auth/login/_page.svelte.js", + "name": "entries/pages/auth/login/_page.svelte", + "src": "src/routes/auth/login/+page.svelte", + "isEntry": true, + "imports": [ + "_index2.js", + "_exports.js", + "_utils.js", + "_root.js", + "_state.svelte.js" + ], + "css": [ + "_app/immutable/assets/_page.Bq7myTre.css" + ] + }, + "src/routes/domains/+page.svelte": { + "file": "entries/pages/domains/_page.svelte.js", + "name": "entries/pages/domains/_page.svelte", + "src": "src/routes/domains/+page.svelte", + "isEntry": true, + "css": [ + "_app/immutable/assets/_page.Sd9PQMHc.css" + ] + }, + "src/routes/domains/[name]/+page.svelte": { + "file": "entries/pages/domains/_name_/_page.svelte.js", + "name": "entries/pages/domains/_name_/_page.svelte", + "src": "src/routes/domains/[name]/+page.svelte", + "isEntry": true, + "imports": [ + "_exports.js", + "_utils.js", + "_root.js", + "_state.svelte.js" + ], + "css": [ + "_app/immutable/assets/_page.Ci0QlAaW.css" + ] + }, + "src/routes/domains/[name]/aliases/+page.svelte": { + "file": "entries/pages/domains/_name_/aliases/_page.svelte.js", + "name": "entries/pages/domains/_name_/aliases/_page.svelte", + "src": "src/routes/domains/[name]/aliases/+page.svelte", + "isEntry": true, + "imports": [ + "_index2.js", + "_exports.js", + "_utils.js", + "_root.js", + "_state.svelte.js" + ], + "css": [ + "_app/immutable/assets/_page.CvxoqpCi.css" + ] + }, + "src/routes/domains/[name]/users/+page.svelte": { + "file": "entries/pages/domains/_name_/users/_page.svelte.js", + "name": "entries/pages/domains/_name_/users/_page.svelte", + "src": "src/routes/domains/[name]/users/+page.svelte", + "isEntry": true, + "imports": [ + "_index2.js", + "_exports.js", + "_utils.js", + "_root.js", + "_state.svelte.js" + ], + "css": [ + "_app/immutable/assets/_page.Bmr1F0Zh.css" + ] + }, + "src/routes/logs/+page.svelte": { + "file": "entries/pages/logs/_page.svelte.js", + "name": "entries/pages/logs/_page.svelte", + "src": "src/routes/logs/+page.svelte", + "isEntry": true, + "imports": [ + "_index2.js" + ], + "css": [ + "_app/immutable/assets/_page.DQdHIvb_.css" + ] + }, + "src/routes/queue/+page.svelte": { + "file": "entries/pages/queue/_page.svelte.js", + "name": "entries/pages/queue/_page.svelte", + "src": "src/routes/queue/+page.svelte", + "isEntry": true, + "css": [ + "_app/immutable/assets/_page.DnP_H9DZ.css" + ] + }, + "src/routes/users/+page.svelte": { + "file": "entries/pages/users/_page.svelte.js", + "name": "entries/pages/users/_page.svelte", + "src": "src/routes/users/+page.svelte", + "isEntry": true, + "imports": [ + "_exports.js", + "_utils.js", + "_root.js", + "_state.svelte.js" + ] + } +} \ No newline at end of file diff --git a/frontend/.svelte-kit/output/server/_app/immutable/assets/_layout.DkgBtk4_.css b/frontend/.svelte-kit/output/server/_app/immutable/assets/_layout.DkgBtk4_.css new file mode 100644 index 0000000..792fc3f --- /dev/null +++ b/frontend/.svelte-kit/output/server/_app/immutable/assets/_layout.DkgBtk4_.css @@ -0,0 +1 @@ +.loading.svelte-12qhfyh{min-height:100vh;display:flex;align-items:center;justify-content:center;font-size:1.2rem;color:#666}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,sans-serif;background:#f5f5f5}.app.svelte-12qhfyh{min-height:100vh}header.svelte-12qhfyh{background:#2c3e50;color:#fff;padding:.75rem 2rem;display:flex;align-items:center;gap:2rem;flex-wrap:wrap}h1.svelte-12qhfyh{margin:0;font-size:1.25rem}nav.svelte-12qhfyh{display:flex;gap:.5rem;flex:1}nav.svelte-12qhfyh a:where(.svelte-12qhfyh){color:#ecf0f1;text-decoration:none;padding:.5rem 1rem;border-radius:4px;font-size:.9rem;transition:background .2s}nav.svelte-12qhfyh a:where(.svelte-12qhfyh):hover{background:#34495e}main.svelte-12qhfyh{padding:2rem;max-width:1400px;margin:0 auto}.user-menu.svelte-12qhfyh{display:flex;align-items:center;gap:1rem;font-size:.9rem}.user-menu.svelte-12qhfyh span:where(.svelte-12qhfyh){color:#ecf0f1}.user-menu.svelte-12qhfyh a:where(.svelte-12qhfyh){color:#ecf0f1;text-decoration:none;padding:.375rem .75rem;border:1px solid #7f8c8d;border-radius:4px;font-size:.85rem}.user-menu.svelte-12qhfyh a:where(.svelte-12qhfyh):hover{background:#34495e}.user-menu.svelte-12qhfyh button:where(.svelte-12qhfyh){background:transparent;border:1px solid #7f8c8d;color:#ecf0f1;padding:.375rem .75rem;border-radius:4px;cursor:pointer;font-size:.85rem}.user-menu.svelte-12qhfyh button:where(.svelte-12qhfyh):hover{background:#34495e} diff --git a/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Bmr1F0Zh.css b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Bmr1F0Zh.css new file mode 100644 index 0000000..a5fa7a6 --- /dev/null +++ b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Bmr1F0Zh.css @@ -0,0 +1 @@ +.header.svelte-oa5z6t{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem;gap:1rem}.back.svelte-oa5z6t{color:#3498db;text-decoration:none;font-size:.9rem}.back.svelte-oa5z6t:hover{text-decoration:underline}.header.svelte-oa5z6t h2:where(.svelte-oa5z6t){flex:1;margin:0}table.svelte-oa5z6t{width:100%;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}th.svelte-oa5z6t,td.svelte-oa5z6t{padding:1rem;text-align:left;border-bottom:1px solid #eee}th.svelte-oa5z6t{background:#f8f9fa;font-weight:600}button.svelte-oa5z6t{padding:.5rem 1rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff}button.danger.svelte-oa5z6t{background:#e74c3c}.modal-backdrop.svelte-oa5z6t{position:fixed;inset:0;background:#00000080;border:none;cursor:pointer;z-index:100}.modal.svelte-oa5z6t{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;padding:2rem;border-radius:8px;min-width:400px;z-index:101}.modal.svelte-oa5z6t h3:where(.svelte-oa5z6t){margin-top:0}.modal.svelte-oa5z6t form:where(.svelte-oa5z6t){display:flex;flex-direction:column;gap:1rem}.modal.svelte-oa5z6t label:where(.svelte-oa5z6t){display:flex;flex-direction:column;gap:.5rem}.modal.svelte-oa5z6t input:where(.svelte-oa5z6t){padding:.5rem;border:1px solid #ddd;border-radius:4px}.actions.svelte-oa5z6t{display:flex;gap:1rem;justify-content:flex-end} diff --git a/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Bq7myTre.css b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Bq7myTre.css new file mode 100644 index 0000000..5e0a5f3 --- /dev/null +++ b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Bq7myTre.css @@ -0,0 +1 @@ +.login-container.svelte-1i2smtp{min-height:100vh;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#2c3e50,#34495e)}.login-card.svelte-1i2smtp{background:#fff;padding:3rem;border-radius:12px;box-shadow:0 10px 40px #0003;width:100%;max-width:400px}h1.svelte-1i2smtp{margin:0;text-align:center;color:#2c3e50;font-size:2rem}.subtitle.svelte-1i2smtp{text-align:center;color:#7f8c8d;margin:.5rem 0 2rem}.error.svelte-1i2smtp{background:#fee;border:1px solid #fcc;color:#c00;padding:.75rem;border-radius:4px;margin-bottom:1rem;font-size:.9rem}form.svelte-1i2smtp{display:flex;flex-direction:column;gap:1.25rem}label.svelte-1i2smtp{display:flex;flex-direction:column;gap:.5rem;font-weight:500;color:#2c3e50}input.svelte-1i2smtp{padding:.75rem;border:1px solid #ddd;border-radius:6px;font-size:1rem;transition:border-color .2s}input.svelte-1i2smtp:focus{outline:none;border-color:#3498db}.forgot.svelte-1i2smtp{text-align:right;margin-top:-.5rem}.forgot.svelte-1i2smtp a:where(.svelte-1i2smtp){color:#3498db;text-decoration:none;font-size:.9rem}.forgot.svelte-1i2smtp a:where(.svelte-1i2smtp):hover{text-decoration:underline}button.svelte-1i2smtp{padding:.875rem;background:#3498db;color:#fff;border:none;border-radius:6px;font-size:1rem;font-weight:600;cursor:pointer;transition:background .2s;margin-top:.5rem}button.svelte-1i2smtp:hover:not(:disabled){background:#2980b9}button.svelte-1i2smtp:disabled{opacity:.7;cursor:not-allowed} diff --git a/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.By2d6Bxb.css b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.By2d6Bxb.css new file mode 100644 index 0000000..f2098ff --- /dev/null +++ b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.By2d6Bxb.css @@ -0,0 +1 @@ +.stats-grid.svelte-1uha8ag{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:1.5rem;margin-top:2rem}.stat-card.svelte-1uha8ag{background:#fff;padding:1.5rem;border-radius:8px;box-shadow:0 2px 4px #0000001a;text-align:center}.stat-card.warning.svelte-1uha8ag{border:2px solid #e74c3c}.stat-card.svelte-1uha8ag h3:where(.svelte-1uha8ag){font-size:2.5rem;margin:0;color:#2c3e50}.stat-card.svelte-1uha8ag p:where(.svelte-1uha8ag){margin:.5rem 0 0;color:#7f8c8d}.warning.svelte-1uha8ag h3:where(.svelte-1uha8ag){color:#e74c3c} diff --git a/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.CG2X--Z8.css b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.CG2X--Z8.css new file mode 100644 index 0000000..ea80681 --- /dev/null +++ b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.CG2X--Z8.css @@ -0,0 +1 @@ +.page-container.svelte-imhhoo{min-height:100vh;background:#f5f7fa}.header.svelte-imhhoo{background:#fff;padding:1rem 2rem;box-shadow:0 2px 4px #0000001a}.header-content.svelte-imhhoo{max-width:800px;margin:0 auto;display:flex;justify-content:space-between;align-items:center}.header.svelte-imhhoo h1:where(.svelte-imhhoo){margin:0;font-size:1.5rem;color:#2c3e50}.user-info.svelte-imhhoo{display:flex;align-items:center;gap:1rem}.logout.svelte-imhhoo{padding:.5rem 1rem;background:#e74c3c;color:#fff;border:none;border-radius:4px;cursor:pointer}.content.svelte-imhhoo{max-width:500px;margin:2rem auto;padding:2rem;background:#fff;border-radius:12px;box-shadow:0 2px 8px #0000001a}.error.svelte-imhhoo{background:#fee;color:#c00;padding:.75rem;border-radius:4px;margin-bottom:1rem}.success.svelte-imhhoo{background:#efe;color:#060;padding:.75rem;border-radius:4px;margin-bottom:1rem}form.svelte-imhhoo{display:flex;flex-direction:column;gap:1rem}label.svelte-imhhoo{display:flex;flex-direction:column;gap:.5rem;font-weight:500;color:#555}input.svelte-imhhoo{padding:.75rem;border:1px solid #ddd;border-radius:6px;font-size:1rem}input.svelte-imhhoo:focus{outline:none;border-color:#667eea;box-shadow:0 0 0 3px #667eea1a}button.svelte-imhhoo{padding:.75rem;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;border-radius:6px;font-size:1rem;font-weight:500;cursor:pointer;margin-top:.5rem}button.svelte-imhhoo:hover:not(:disabled){opacity:.9}button.svelte-imhhoo:disabled{opacity:.6;cursor:not-allowed}.links.svelte-imhhoo{margin-top:1.5rem;text-align:center}.links.svelte-imhhoo a:where(.svelte-imhhoo){color:#667eea;text-decoration:none}.links.svelte-imhhoo a:where(.svelte-imhhoo):hover{text-decoration:underline} diff --git a/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Ci0QlAaW.css b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Ci0QlAaW.css new file mode 100644 index 0000000..6ef841b --- /dev/null +++ b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Ci0QlAaW.css @@ -0,0 +1 @@ +.header.svelte-lb8x40{margin-bottom:2rem}.back.svelte-lb8x40{display:inline-block;margin-bottom:1rem;color:#3498db;text-decoration:none}.back.svelte-lb8x40:hover{text-decoration:underline}.error.svelte-lb8x40{color:#e74c3c}.cards-grid.svelte-lb8x40{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:1.5rem}.card.svelte-lb8x40{background:#fff;padding:2rem;border-radius:8px;box-shadow:0 2px 4px #0000001a;text-align:center;text-decoration:none;color:inherit;transition:transform .2s,box-shadow .2s}.card.svelte-lb8x40:hover{transform:translateY(-2px);box-shadow:0 4px 8px #00000026}.card.svelte-lb8x40 h3:where(.svelte-lb8x40){font-size:3rem;margin:0;color:#3498db}.card.svelte-lb8x40 p:where(.svelte-lb8x40){margin:.5rem 0 0;color:#7f8c8d;font-size:1.1rem} diff --git a/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.CvxoqpCi.css b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.CvxoqpCi.css new file mode 100644 index 0000000..f53ac9e --- /dev/null +++ b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.CvxoqpCi.css @@ -0,0 +1 @@ +.header.svelte-15uyvzd{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem;gap:1rem}.back.svelte-15uyvzd{color:#3498db;text-decoration:none;font-size:.9rem}.back.svelte-15uyvzd:hover{text-decoration:underline}.header.svelte-15uyvzd h2:where(.svelte-15uyvzd){flex:1;margin:0}table.svelte-15uyvzd{width:100%;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}th.svelte-15uyvzd,td.svelte-15uyvzd{padding:1rem;text-align:left;border-bottom:1px solid #eee}th.svelte-15uyvzd{background:#f8f9fa;font-weight:600}button.svelte-15uyvzd{padding:.5rem 1rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff}button.danger.svelte-15uyvzd{background:#e74c3c}.modal-backdrop.svelte-15uyvzd{position:fixed;inset:0;background:#00000080;border:none;cursor:pointer;z-index:100}.modal.svelte-15uyvzd{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;padding:2rem;border-radius:8px;min-width:400px;z-index:101}.modal.svelte-15uyvzd h3:where(.svelte-15uyvzd){margin-top:0}.modal.svelte-15uyvzd form:where(.svelte-15uyvzd){display:flex;flex-direction:column;gap:1rem}.modal.svelte-15uyvzd label:where(.svelte-15uyvzd){display:flex;flex-direction:column;gap:.5rem}.modal.svelte-15uyvzd input:where(.svelte-15uyvzd){padding:.5rem;border:1px solid #ddd;border-radius:4px}.actions.svelte-15uyvzd{display:flex;gap:1rem;justify-content:flex-end} diff --git a/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.DQdHIvb_.css b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.DQdHIvb_.css new file mode 100644 index 0000000..3f6263d --- /dev/null +++ b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.DQdHIvb_.css @@ -0,0 +1 @@ +.header.svelte-1lsf4ps{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem;flex-wrap:wrap;gap:1rem}.controls.svelte-1lsf4ps{display:flex;gap:1rem;align-items:center}.controls.svelte-1lsf4ps label:where(.svelte-1lsf4ps){display:flex;align-items:center;gap:.5rem}.controls.svelte-1lsf4ps select:where(.svelte-1lsf4ps),.controls.svelte-1lsf4ps input:where(.svelte-1lsf4ps){padding:.5rem;border:1px solid #ddd;border-radius:4px}button.svelte-1lsf4ps{padding:.5rem 1rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff}.log-container.svelte-1lsf4ps{background:#1a1a2e;color:#eee;padding:1rem;border-radius:8px;max-height:600px;overflow-y:auto;font-family:monospace;font-size:.85rem}.log-entry.svelte-1lsf4ps{padding:.25rem 0;border-bottom:1px solid #333}.log-entry.svelte-1lsf4ps:last-child{border-bottom:none}.timestamp.svelte-1lsf4ps{color:#888;margin-right:.5rem}.priority.svelte-1lsf4ps{margin-right:.5rem;font-weight:700}.log-entry.error.svelte-1lsf4ps .priority:where(.svelte-1lsf4ps){color:#e74c3c}.log-entry.warning.svelte-1lsf4ps .priority:where(.svelte-1lsf4ps){color:#f39c12}.log-entry.info.svelte-1lsf4ps .priority:where(.svelte-1lsf4ps){color:#3498db}.error.svelte-1lsf4ps{color:#e74c3c} diff --git a/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.DnP_H9DZ.css b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.DnP_H9DZ.css new file mode 100644 index 0000000..5caa7e3 --- /dev/null +++ b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.DnP_H9DZ.css @@ -0,0 +1 @@ +.header.svelte-qegr5c{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem}table.svelte-qegr5c{width:100%;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}th.svelte-qegr5c,td.svelte-qegr5c{padding:.75rem;text-align:left;border-bottom:1px solid #eee;font-size:.9rem}th.svelte-qegr5c{background:#f8f9fa;font-weight:600}.id.svelte-qegr5c{font-family:monospace;font-size:.8rem}.reason.svelte-qegr5c{color:#e74c3c}button.svelte-qegr5c{padding:.25rem .5rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff;font-size:.8rem;margin-right:.25rem}button.danger.svelte-qegr5c{background:#e74c3c}.error.svelte-qegr5c{color:#e74c3c} diff --git a/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Sd9PQMHc.css b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Sd9PQMHc.css new file mode 100644 index 0000000..c9d7879 --- /dev/null +++ b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Sd9PQMHc.css @@ -0,0 +1 @@ +.header.svelte-83awcy{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem}table.svelte-83awcy{width:100%;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}th.svelte-83awcy,td.svelte-83awcy{padding:1rem;text-align:left;border-bottom:1px solid #eee}th.svelte-83awcy{background:#f8f9fa;font-weight:600}button.svelte-83awcy{padding:.5rem 1rem;border:none;border-radius:4px;cursor:pointer;background:#3498db;color:#fff}button.danger.svelte-83awcy{background:#e74c3c}.modal-backdrop.svelte-83awcy{position:fixed;inset:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:100}.modal.svelte-83awcy{background:#fff;padding:2rem;border-radius:8px;min-width:400px}.modal.svelte-83awcy form:where(.svelte-83awcy){display:flex;flex-direction:column;gap:1rem}.modal.svelte-83awcy label:where(.svelte-83awcy){display:flex;flex-direction:column;gap:.5rem}.modal.svelte-83awcy input:where(.svelte-83awcy){padding:.5rem;border:1px solid #ddd;border-radius:4px}.actions.svelte-83awcy{display:flex;gap:1rem;justify-content:flex-end} diff --git a/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.YbbfqdJp.css b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.YbbfqdJp.css new file mode 100644 index 0000000..47f5e83 --- /dev/null +++ b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.YbbfqdJp.css @@ -0,0 +1 @@ +.page-container.svelte-1s1ktxm{min-height:100vh;background:#f5f7fa}.header.svelte-1s1ktxm{background:#fff;padding:1rem 2rem;box-shadow:0 2px 4px #0000001a;display:flex;justify-content:space-between;align-items:center}.header.svelte-1s1ktxm h1:where(.svelte-1s1ktxm){margin:0;font-size:1.5rem;color:#2c3e50}.user-info.svelte-1s1ktxm{display:flex;align-items:center;gap:1rem}.logout.svelte-1s1ktxm{padding:.5rem 1rem;background:#e74c3c;color:#fff;border:none;border-radius:4px;cursor:pointer}.content.svelte-1s1ktxm{max-width:800px;margin:2rem auto;padding:0 1rem}.card.svelte-1s1ktxm{background:#fff;padding:1.5rem;border-radius:12px;box-shadow:0 2px 8px #0000001a;margin-bottom:1.5rem}.card.svelte-1s1ktxm h2:where(.svelte-1s1ktxm){margin:0 0 1rem;color:#2c3e50;font-size:1.2rem}.info-row.svelte-1s1ktxm{display:flex;padding:.75rem 0;border-bottom:1px solid #eee}.info-row.svelte-1s1ktxm:last-child{border-bottom:none}.label.svelte-1s1ktxm{font-weight:500;color:#666;width:120px}.value.svelte-1s1ktxm{color:#2c3e50}.actions.svelte-1s1ktxm{display:flex;gap:1rem;flex-wrap:wrap}.action-btn.svelte-1s1ktxm{padding:.75rem 1.5rem;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;text-decoration:none;border-radius:6px;font-weight:500;transition:opacity .2s}.action-btn.svelte-1s1ktxm:hover{opacity:.9} diff --git a/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.w_qTFDpy.css b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.w_qTFDpy.css new file mode 100644 index 0000000..4f2c471 --- /dev/null +++ b/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.w_qTFDpy.css @@ -0,0 +1 @@ +.login-container.svelte-15sczaz{min-height:100vh;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#667eea,#764ba2);padding:1rem}.login-card.svelte-15sczaz{background:#fff;padding:2rem;border-radius:12px;box-shadow:0 10px 40px #0003;width:100%;max-width:400px}h1.svelte-15sczaz{text-align:center;margin:0 0 1rem;color:#2c3e50}.info.svelte-15sczaz{color:#666;text-align:center;margin-bottom:1.5rem;font-size:.9rem}.error.svelte-15sczaz{background:#fee;color:#c00;padding:.75rem;border-radius:4px;margin-bottom:1rem;font-size:.9rem}.success.svelte-15sczaz{background:#efe;color:#060;padding:1rem;border-radius:4px;margin-bottom:1rem;text-align:center}.success.svelte-15sczaz p:where(.svelte-15sczaz){margin:.5rem 0}form.svelte-15sczaz{display:flex;flex-direction:column;gap:1rem}label.svelte-15sczaz{display:flex;flex-direction:column;gap:.5rem;font-weight:500;color:#555}input.svelte-15sczaz{padding:.75rem;border:1px solid #ddd;border-radius:6px;font-size:1rem}input.svelte-15sczaz:focus{outline:none;border-color:#667eea;box-shadow:0 0 0 3px #667eea1a}button.svelte-15sczaz{padding:.75rem;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;border-radius:6px;font-size:1rem;font-weight:500;cursor:pointer;transition:opacity .2s}button.svelte-15sczaz:hover:not(:disabled){opacity:.9}button.svelte-15sczaz:disabled{opacity:.6;cursor:not-allowed}.links.svelte-15sczaz{margin-top:1.5rem;text-align:center;padding-top:1rem;border-top:1px solid #eee}.links.svelte-15sczaz a:where(.svelte-15sczaz){color:#667eea;text-decoration:none;font-size:.9rem}.links.svelte-15sczaz a:where(.svelte-15sczaz):hover{text-decoration:underline} diff --git a/frontend/.svelte-kit/output/server/chunks/environment.js b/frontend/.svelte-kit/output/server/chunks/environment.js new file mode 100644 index 0000000..ad45c3c --- /dev/null +++ b/frontend/.svelte-kit/output/server/chunks/environment.js @@ -0,0 +1,34 @@ +let base = ""; +let assets = base; +const app_dir = "_app"; +const relative = true; +const initial = { base, assets }; +function override(paths) { + base = paths.base; + assets = paths.assets; +} +function reset() { + base = initial.base; + assets = initial.assets; +} +function set_assets(path) { + assets = initial.assets = path; +} +let prerendering = false; +function set_building() { +} +function set_prerendering() { + prerendering = true; +} +export { + assets as a, + base as b, + app_dir as c, + reset as d, + set_building as e, + set_prerendering as f, + override as o, + prerendering as p, + relative as r, + set_assets as s +}; diff --git a/frontend/.svelte-kit/output/server/chunks/exports.js b/frontend/.svelte-kit/output/server/chunks/exports.js new file mode 100644 index 0000000..81554d4 --- /dev/null +++ b/frontend/.svelte-kit/output/server/chunks/exports.js @@ -0,0 +1,174 @@ +const SCHEME = /^[a-z][a-z\d+\-.]+:/i; +const internal = new URL("sveltekit-internal://"); +function resolve(base, path) { + if (path[0] === "/" && path[1] === "/") return path; + let url = new URL(base, internal); + url = new URL(path, url); + return url.protocol === internal.protocol ? url.pathname + url.search + url.hash : url.href; +} +function normalize_path(path, trailing_slash) { + if (path === "/" || trailing_slash === "ignore") return path; + if (trailing_slash === "never") { + return path.endsWith("/") ? path.slice(0, -1) : path; + } else if (trailing_slash === "always" && !path.endsWith("/")) { + return path + "/"; + } + return path; +} +function decode_pathname(pathname) { + return pathname.split("%25").map(decodeURI).join("%25"); +} +function decode_params(params) { + for (const key in params) { + params[key] = decodeURIComponent(params[key]); + } + return params; +} +function make_trackable(url, callback, search_params_callback, allow_hash = false) { + const tracked = new URL(url); + Object.defineProperty(tracked, "searchParams", { + value: new Proxy(tracked.searchParams, { + get(obj, key) { + if (key === "get" || key === "getAll" || key === "has") { + return (param, ...rest) => { + search_params_callback(param); + return obj[key](param, ...rest); + }; + } + callback(); + const value = Reflect.get(obj, key); + return typeof value === "function" ? value.bind(obj) : value; + } + }), + enumerable: true, + configurable: true + }); + const tracked_url_properties = ["href", "pathname", "search", "toString", "toJSON"]; + if (allow_hash) tracked_url_properties.push("hash"); + for (const property of tracked_url_properties) { + Object.defineProperty(tracked, property, { + get() { + callback(); + return url[property]; + }, + enumerable: true, + configurable: true + }); + } + { + tracked[Symbol.for("nodejs.util.inspect.custom")] = (depth, opts, inspect) => { + return inspect(url, opts); + }; + tracked.searchParams[Symbol.for("nodejs.util.inspect.custom")] = (depth, opts, inspect) => { + return inspect(url.searchParams, opts); + }; + } + if (!allow_hash) { + disable_hash(tracked); + } + return tracked; +} +function disable_hash(url) { + allow_nodejs_console_log(url); + Object.defineProperty(url, "hash", { + get() { + throw new Error( + "Cannot access event.url.hash. Consider using `page.url.hash` inside a component instead" + ); + } + }); +} +function disable_search(url) { + allow_nodejs_console_log(url); + for (const property of ["search", "searchParams"]) { + Object.defineProperty(url, property, { + get() { + throw new Error(`Cannot access url.${property} on a page with prerendering enabled`); + } + }); + } +} +function allow_nodejs_console_log(url) { + { + url[Symbol.for("nodejs.util.inspect.custom")] = (depth, opts, inspect) => { + return inspect(new URL(url), opts); + }; + } +} +function validator(expected) { + function validate(module, file) { + if (!module) return; + for (const key in module) { + if (key[0] === "_" || expected.has(key)) continue; + const values = [...expected.values()]; + const hint = hint_for_supported_files(key, file?.slice(file.lastIndexOf("."))) ?? `valid exports are ${values.join(", ")}, or anything with a '_' prefix`; + throw new Error(`Invalid export '${key}'${file ? ` in ${file}` : ""} (${hint})`); + } + } + return validate; +} +function hint_for_supported_files(key, ext = ".js") { + const supported_files = []; + if (valid_layout_exports.has(key)) { + supported_files.push(`+layout${ext}`); + } + if (valid_page_exports.has(key)) { + supported_files.push(`+page${ext}`); + } + if (valid_layout_server_exports.has(key)) { + supported_files.push(`+layout.server${ext}`); + } + if (valid_page_server_exports.has(key)) { + supported_files.push(`+page.server${ext}`); + } + if (valid_server_exports.has(key)) { + supported_files.push(`+server${ext}`); + } + if (supported_files.length > 0) { + return `'${key}' is a valid export in ${supported_files.slice(0, -1).join(", ")}${supported_files.length > 1 ? " or " : ""}${supported_files.at(-1)}`; + } +} +const valid_layout_exports = /* @__PURE__ */ new Set([ + "load", + "prerender", + "csr", + "ssr", + "trailingSlash", + "config" +]); +const valid_page_exports = /* @__PURE__ */ new Set([...valid_layout_exports, "entries"]); +const valid_layout_server_exports = /* @__PURE__ */ new Set([...valid_layout_exports]); +const valid_page_server_exports = /* @__PURE__ */ new Set([...valid_layout_server_exports, "actions", "entries"]); +const valid_server_exports = /* @__PURE__ */ new Set([ + "GET", + "POST", + "PATCH", + "PUT", + "DELETE", + "OPTIONS", + "HEAD", + "fallback", + "prerender", + "trailingSlash", + "config", + "entries" +]); +const validate_layout_exports = validator(valid_layout_exports); +const validate_page_exports = validator(valid_page_exports); +const validate_layout_server_exports = validator(valid_layout_server_exports); +const validate_page_server_exports = validator(valid_page_server_exports); +const validate_server_exports = validator(valid_server_exports); +export { + SCHEME as S, + decode_params as a, + validate_layout_exports as b, + validate_page_server_exports as c, + disable_search as d, + validate_page_exports as e, + decode_pathname as f, + validate_server_exports as g, + make_trackable as m, + normalize_path as n, + resolve as r, + validate_layout_server_exports as v +}; diff --git a/frontend/.svelte-kit/output/server/chunks/false.js b/frontend/.svelte-kit/output/server/chunks/false.js new file mode 100644 index 0000000..85bc56d --- /dev/null +++ b/frontend/.svelte-kit/output/server/chunks/false.js @@ -0,0 +1,4 @@ +const BROWSER = false; +export { + BROWSER as B +}; diff --git a/frontend/.svelte-kit/output/server/chunks/index.js b/frontend/.svelte-kit/output/server/chunks/index.js new file mode 100644 index 0000000..aff0709 --- /dev/null +++ b/frontend/.svelte-kit/output/server/chunks/index.js @@ -0,0 +1,59 @@ +import { n as noop } from "./index2.js"; +import { s as safe_not_equal } from "./root.js"; +const subscriber_queue = []; +function readable(value, start) { + return { + subscribe: writable(value, start).subscribe + }; +} +function writable(value, start = noop) { + let stop = null; + const subscribers = /* @__PURE__ */ new Set(); + function set(new_value) { + if (safe_not_equal(value, new_value)) { + value = new_value; + if (stop) { + const run_queue = !subscriber_queue.length; + for (const subscriber of subscribers) { + subscriber[1](); + subscriber_queue.push(subscriber, value); + } + if (run_queue) { + for (let i = 0; i < subscriber_queue.length; i += 2) { + subscriber_queue[i][0](subscriber_queue[i + 1]); + } + subscriber_queue.length = 0; + } + } + } + } + function update(fn) { + set(fn( + /** @type {T} */ + value + )); + } + function subscribe(run, invalidate = noop) { + const subscriber = [run, invalidate]; + subscribers.add(subscriber); + if (subscribers.size === 1) { + stop = start(set, update) || noop; + } + run( + /** @type {T} */ + value + ); + return () => { + subscribers.delete(subscriber); + if (subscribers.size === 0 && stop) { + stop(); + stop = null; + } + }; + } + return { set, update, subscribe }; +} +export { + readable as r, + writable as w +}; diff --git a/frontend/.svelte-kit/output/server/chunks/index2.js b/frontend/.svelte-kit/output/server/chunks/index2.js new file mode 100644 index 0000000..9953b10 --- /dev/null +++ b/frontend/.svelte-kit/output/server/chunks/index2.js @@ -0,0 +1,1250 @@ +import { clsx as clsx$1 } from "clsx"; +import * as devalue from "devalue"; +var is_array = Array.isArray; +var index_of = Array.prototype.indexOf; +var includes = Array.prototype.includes; +var array_from = Array.from; +var define_property = Object.defineProperty; +var get_descriptor = Object.getOwnPropertyDescriptor; +var object_prototype = Object.prototype; +var array_prototype = Array.prototype; +var get_prototype_of = Object.getPrototypeOf; +var is_extensible = Object.isExtensible; +var has_own_property = Object.prototype.hasOwnProperty; +const noop = () => { +}; +function run_all(arr) { + for (var i = 0; i < arr.length; i++) { + arr[i](); + } +} +function deferred() { + var resolve; + var reject; + var promise = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + return { promise, resolve, reject }; +} +const DERIVED = 1 << 1; +const EFFECT = 1 << 2; +const RENDER_EFFECT = 1 << 3; +const MANAGED_EFFECT = 1 << 24; +const BLOCK_EFFECT = 1 << 4; +const BRANCH_EFFECT = 1 << 5; +const ROOT_EFFECT = 1 << 6; +const BOUNDARY_EFFECT = 1 << 7; +const CONNECTED = 1 << 9; +const CLEAN = 1 << 10; +const DIRTY = 1 << 11; +const MAYBE_DIRTY = 1 << 12; +const INERT = 1 << 13; +const DESTROYED = 1 << 14; +const REACTION_RAN = 1 << 15; +const DESTROYING = 1 << 25; +const EFFECT_TRANSPARENT = 1 << 16; +const EAGER_EFFECT = 1 << 17; +const HEAD_EFFECT = 1 << 18; +const EFFECT_PRESERVED = 1 << 19; +const USER_EFFECT = 1 << 20; +const WAS_MARKED = 1 << 16; +const REACTION_IS_UPDATING = 1 << 21; +const ASYNC = 1 << 22; +const ERROR_VALUE = 1 << 23; +const STATE_SYMBOL = Symbol("$state"); +const LEGACY_PROPS = Symbol("legacy props"); +const STALE_REACTION = new class StaleReactionError extends Error { + name = "StaleReactionError"; + message = "The reaction that called `getAbortSignal()` was re-run or destroyed"; +}(); +const COMMENT_NODE = 8; +function lifecycle_outside_component(name) { + { + throw new Error(`https://svelte.dev/e/lifecycle_outside_component`); + } +} +const HYDRATION_START = "["; +const HYDRATION_START_ELSE = "[!"; +const HYDRATION_START_FAILED = "[?"; +const HYDRATION_END = "]"; +const HYDRATION_ERROR = {}; +const ELEMENT_IS_NAMESPACED = 1; +const ELEMENT_PRESERVE_ATTRIBUTE_CASE = 1 << 1; +const ELEMENT_IS_INPUT = 1 << 2; +const UNINITIALIZED = Symbol(); +const DOM_BOOLEAN_ATTRIBUTES = [ + "allowfullscreen", + "async", + "autofocus", + "autoplay", + "checked", + "controls", + "default", + "disabled", + "formnovalidate", + "indeterminate", + "inert", + "ismap", + "loop", + "multiple", + "muted", + "nomodule", + "novalidate", + "open", + "playsinline", + "readonly", + "required", + "reversed", + "seamless", + "selected", + "webkitdirectory", + "defer", + "disablepictureinpicture", + "disableremoteplayback" +]; +function is_boolean_attribute(name) { + return DOM_BOOLEAN_ATTRIBUTES.includes(name); +} +const PASSIVE_EVENTS = ["touchstart", "touchmove"]; +function is_passive_event(name) { + return PASSIVE_EVENTS.includes(name); +} +const ATTR_REGEX = /[&"<]/g; +const CONTENT_REGEX = /[&<]/g; +function escape_html(value, is_attr) { + const str = String(value ?? ""); + const pattern = is_attr ? ATTR_REGEX : CONTENT_REGEX; + pattern.lastIndex = 0; + let escaped = ""; + let last = 0; + while (pattern.test(str)) { + const i = pattern.lastIndex - 1; + const ch = str[i]; + escaped += str.substring(last, i) + (ch === "&" ? "&" : ch === '"' ? """ : "<"); + last = i + 1; + } + return escaped + str.substring(last); +} +const replacements = { + translate: /* @__PURE__ */ new Map([ + [true, "yes"], + [false, "no"] + ]) +}; +function attr(name, value, is_boolean = false) { + if (name === "hidden" && value !== "until-found") { + is_boolean = true; + } + if (value == null || !value && is_boolean) return ""; + const normalized = has_own_property.call(replacements, name) && replacements[name].get(value) || value; + const assignment = is_boolean ? `=""` : `="${escape_html(normalized, true)}"`; + return ` ${name}${assignment}`; +} +function clsx(value) { + if (typeof value === "object") { + return clsx$1(value); + } else { + return value ?? ""; + } +} +const whitespace = [..." \n\r\f \v\uFEFF"]; +function to_class(value, hash, directives) { + var classname = value == null ? "" : "" + value; + if (hash) { + classname = classname ? classname + " " + hash : hash; + } + if (directives) { + for (var key of Object.keys(directives)) { + if (directives[key]) { + classname = classname ? classname + " " + key : key; + } else if (classname.length) { + var len = key.length; + var a = 0; + while ((a = classname.indexOf(key, a)) >= 0) { + var b = a + len; + if ((a === 0 || whitespace.includes(classname[a - 1])) && (b === classname.length || whitespace.includes(classname[b]))) { + classname = (a === 0 ? "" : classname.substring(0, a)) + classname.substring(b + 1); + } else { + a = b; + } + } + } + } + } + return classname === "" ? null : classname; +} +function append_styles(styles, important = false) { + var separator = important ? " !important;" : ";"; + var css = ""; + for (var key of Object.keys(styles)) { + var value = styles[key]; + if (value != null && value !== "") { + css += " " + key + ": " + value + separator; + } + } + return css; +} +function to_css_name(name) { + if (name[0] !== "-" || name[1] !== "-") { + return name.toLowerCase(); + } + return name; +} +function to_style(value, styles) { + if (styles) { + var new_style = ""; + var normal_styles; + var important_styles; + if (Array.isArray(styles)) { + normal_styles = styles[0]; + important_styles = styles[1]; + } else { + normal_styles = styles; + } + if (value) { + value = String(value).replaceAll(/\s*\/\*.*?\*\/\s*/g, "").trim(); + var in_str = false; + var in_apo = 0; + var in_comment = false; + var reserved_names = []; + if (normal_styles) { + reserved_names.push(...Object.keys(normal_styles).map(to_css_name)); + } + if (important_styles) { + reserved_names.push(...Object.keys(important_styles).map(to_css_name)); + } + var start_index = 0; + var name_index = -1; + const len = value.length; + for (var i = 0; i < len; i++) { + var c = value[i]; + if (in_comment) { + if (c === "/" && value[i - 1] === "*") { + in_comment = false; + } + } else if (in_str) { + if (in_str === c) { + in_str = false; + } + } else if (c === "/" && value[i + 1] === "*") { + in_comment = true; + } else if (c === '"' || c === "'") { + in_str = c; + } else if (c === "(") { + in_apo++; + } else if (c === ")") { + in_apo--; + } + if (!in_comment && in_str === false && in_apo === 0) { + if (c === ":" && name_index === -1) { + name_index = i; + } else if (c === ";" || i === len - 1) { + if (name_index !== -1) { + var name = to_css_name(value.substring(start_index, name_index).trim()); + if (!reserved_names.includes(name)) { + if (c !== ";") { + i++; + } + var property = value.substring(start_index, i).trim(); + new_style += " " + property + ";"; + } + } + start_index = i + 1; + name_index = -1; + } + } + } + } + if (normal_styles) { + new_style += append_styles(normal_styles); + } + if (important_styles) { + new_style += append_styles(important_styles, true); + } + new_style = new_style.trim(); + return new_style === "" ? null : new_style; + } + return value == null ? null : String(value); +} +const BLOCK_OPEN = ``; +const BLOCK_CLOSE = ``; +let controller = null; +function abort() { + controller?.abort(STALE_REACTION); + controller = null; +} +function await_invalid() { + const error = new Error(`await_invalid +Encountered asynchronous work while rendering synchronously. +https://svelte.dev/e/await_invalid`); + error.name = "Svelte error"; + throw error; +} +function invalid_csp() { + const error = new Error(`invalid_csp +\`csp.nonce\` was set while \`csp.hash\` was \`true\`. These options cannot be used simultaneously. +https://svelte.dev/e/invalid_csp`); + error.name = "Svelte error"; + throw error; +} +function server_context_required() { + const error = new Error(`server_context_required +Could not resolve \`render\` context. +https://svelte.dev/e/server_context_required`); + error.name = "Svelte error"; + throw error; +} +var ssr_context = null; +function set_ssr_context(v) { + ssr_context = v; +} +function getContext(key) { + const context_map = get_or_init_context_map(); + const result = ( + /** @type {T} */ + context_map.get(key) + ); + return result; +} +function setContext(key, context) { + get_or_init_context_map().set(key, context); + return context; +} +function get_or_init_context_map(name) { + if (ssr_context === null) { + lifecycle_outside_component(); + } + return ssr_context.c ??= new Map(get_parent_context(ssr_context) || void 0); +} +function push(fn) { + ssr_context = { p: ssr_context, c: null, r: null }; +} +function pop() { + ssr_context = /** @type {SSRContext} */ + ssr_context.p; +} +function get_parent_context(ssr_context2) { + let parent = ssr_context2.p; + while (parent !== null) { + const context_map = parent.c; + if (context_map !== null) { + return context_map; + } + parent = parent.p; + } + return null; +} +function unresolved_hydratable(key, stack) { + { + console.warn(`https://svelte.dev/e/unresolved_hydratable`); + } +} +function get_render_context() { + const store = als?.getStore(); + { + server_context_required(); + } + return store; +} +let als = null; +let text_encoder; +let crypto; +const obfuscated_import = (module_name) => import( + /* @vite-ignore */ + module_name +); +async function sha256(data) { + text_encoder ??= new TextEncoder(); + crypto ??= globalThis.crypto?.subtle?.digest ? globalThis.crypto : ( + // @ts-ignore - we don't install node types in the prod build + // don't use import('node:crypto') directly because static analysers will think we rely on node when we don't + (await obfuscated_import("node:crypto")).webcrypto + ); + const hash_buffer = await crypto.subtle.digest("SHA-256", text_encoder.encode(data)); + return base64_encode(hash_buffer); +} +function base64_encode(bytes) { + if (globalThis.Buffer) { + return globalThis.Buffer.from(bytes).toString("base64"); + } + let binary = ""; + for (let i = 0; i < bytes.length; i++) { + binary += String.fromCharCode(bytes[i]); + } + return btoa(binary); +} +class Renderer { + /** + * The contents of the renderer. + * @type {RendererItem[]} + */ + #out = []; + /** + * Any `onDestroy` callbacks registered during execution of this renderer. + * @type {(() => void)[] | undefined} + */ + #on_destroy = void 0; + /** + * Whether this renderer is a component body. + * @type {boolean} + */ + #is_component_body = false; + /** + * If set, this renderer is an error boundary. When async collection + * of the children fails, the failed snippet is rendered instead. + * @type {{ + * failed: (renderer: Renderer, error: unknown, reset: () => void) => void; + * transformError: (error: unknown) => unknown; + * context: SSRContext | null; + * } | null} + */ + #boundary = null; + /** + * The type of string content that this renderer is accumulating. + * @type {RendererType} + */ + type; + /** @type {Renderer | undefined} */ + #parent; + /** + * Asynchronous work associated with this renderer + * @type {Promise | undefined} + */ + promise = void 0; + /** + * State which is associated with the content tree as a whole. + * It will be re-exposed, uncopied, on all children. + * @type {SSRState} + * @readonly + */ + global; + /** + * State that is local to the branch it is declared in. + * It will be shallow-copied to all children. + * + * @type {{ select_value: string | undefined }} + */ + local; + /** + * @param {SSRState} global + * @param {Renderer | undefined} [parent] + */ + constructor(global, parent) { + this.#parent = parent; + this.global = global; + this.local = parent ? { ...parent.local } : { select_value: void 0 }; + this.type = parent ? parent.type : "body"; + } + /** + * @param {(renderer: Renderer) => void} fn + */ + head(fn) { + const head = new Renderer(this.global, this); + head.type = "head"; + this.#out.push(head); + head.child(fn); + } + /** + * @param {Array>} blockers + * @param {(renderer: Renderer) => void} fn + */ + async_block(blockers, fn) { + this.#out.push(BLOCK_OPEN); + this.async(blockers, fn); + this.#out.push(BLOCK_CLOSE); + } + /** + * @param {Array>} blockers + * @param {(renderer: Renderer) => void} fn + */ + async(blockers, fn) { + let callback = fn; + if (blockers.length > 0) { + const context = ssr_context; + callback = (renderer) => { + return Promise.all(blockers).then(() => { + const previous_context = ssr_context; + try { + set_ssr_context(context); + return fn(renderer); + } finally { + set_ssr_context(previous_context); + } + }); + }; + } + this.child(callback); + } + /** + * @param {Array<() => void>} thunks + */ + run(thunks) { + const context = ssr_context; + let promise = Promise.resolve(thunks[0]()); + const promises = [promise]; + for (const fn of thunks.slice(1)) { + promise = promise.then(() => { + const previous_context = ssr_context; + set_ssr_context(context); + try { + return fn(); + } finally { + set_ssr_context(previous_context); + } + }); + promises.push(promise); + } + promise.catch(noop); + this.promise = promise; + return promises; + } + /** + * @param {(renderer: Renderer) => MaybePromise} fn + */ + child_block(fn) { + this.#out.push(BLOCK_OPEN); + this.child(fn); + this.#out.push(BLOCK_CLOSE); + } + /** + * Create a child renderer. The child renderer inherits the state from the parent, + * but has its own content. + * @param {(renderer: Renderer) => MaybePromise} fn + */ + child(fn) { + const child = new Renderer(this.global, this); + this.#out.push(child); + const parent = ssr_context; + set_ssr_context({ + ...ssr_context, + p: parent, + c: null, + r: child + }); + const result = fn(child); + set_ssr_context(parent); + if (result instanceof Promise) { + result.catch(noop); + result.finally(() => set_ssr_context(null)).catch(noop); + if (child.global.mode === "sync") { + await_invalid(); + } + child.promise = result; + } + return child; + } + /** + * Render children inside an error boundary. If the children throw and the API-level + * `transformError` transform handles the error (doesn't re-throw), the `failed` snippet is + * rendered instead. Otherwise the error propagates. + * + * @param {{ failed?: (renderer: Renderer, error: unknown, reset: () => void) => void }} props + * @param {(renderer: Renderer) => MaybePromise} children_fn + */ + boundary(props, children_fn) { + const child = new Renderer(this.global, this); + this.#out.push(child); + const parent_context = ssr_context; + if (props.failed) { + child.#boundary = { + failed: props.failed, + transformError: this.global.transformError, + context: parent_context + }; + } + set_ssr_context({ + ...ssr_context, + p: parent_context, + c: null, + r: child + }); + try { + const result = children_fn(child); + set_ssr_context(parent_context); + if (result instanceof Promise) { + if (child.global.mode === "sync") { + await_invalid(); + } + result.catch(noop); + child.promise = result; + } + } catch (error) { + set_ssr_context(parent_context); + const failed_snippet = props.failed; + if (!failed_snippet) throw error; + const result = this.global.transformError(error); + child.#out.length = 0; + child.#boundary = null; + if (result instanceof Promise) { + if (this.global.mode === "sync") { + await_invalid(); + } + child.promise = /** @type {Promise} */ + result.then((transformed) => { + set_ssr_context(parent_context); + child.#out.push(Renderer.#serialize_failed_boundary(transformed)); + failed_snippet(child, transformed, noop); + child.#out.push(BLOCK_CLOSE); + }); + child.promise.catch(noop); + } else { + child.#out.push(Renderer.#serialize_failed_boundary(result)); + failed_snippet(child, result, noop); + child.#out.push(BLOCK_CLOSE); + } + } + } + /** + * Create a component renderer. The component renderer inherits the state from the parent, + * but has its own content. It is treated as an ordering boundary for ondestroy callbacks. + * @param {(renderer: Renderer) => MaybePromise} fn + * @param {Function} [component_fn] + * @returns {void} + */ + component(fn, component_fn) { + push(); + const child = this.child(fn); + child.#is_component_body = true; + pop(); + } + /** + * @param {Record} attrs + * @param {(renderer: Renderer) => void} fn + * @param {string | undefined} [css_hash] + * @param {Record | undefined} [classes] + * @param {Record | undefined} [styles] + * @param {number | undefined} [flags] + * @param {boolean | undefined} [is_rich] + * @returns {void} + */ + select(attrs, fn, css_hash, classes, styles, flags, is_rich) { + const { value, ...select_attrs } = attrs; + this.push(``); + this.child((renderer) => { + renderer.local.select_value = value; + fn(renderer); + }); + this.push(`${is_rich ? "" : ""}`); + } + /** + * @param {Record} attrs + * @param {string | number | boolean | ((renderer: Renderer) => void)} body + * @param {string | undefined} [css_hash] + * @param {Record | undefined} [classes] + * @param {Record | undefined} [styles] + * @param {number | undefined} [flags] + * @param {boolean | undefined} [is_rich] + */ + option(attrs, body, css_hash, classes, styles, flags, is_rich) { + this.#out.push(` { + if (has_own_property.call(attrs, "value")) { + value = attrs.value; + } + if (value === this.local.select_value) { + renderer.#out.push(' selected=""'); + } + renderer.#out.push(`>${body2}${is_rich ? "" : ""}`); + if (head) { + renderer.head((child) => child.push(head)); + } + }; + if (typeof body === "function") { + this.child((renderer) => { + const r = new Renderer(this.global, this); + body(r); + if (this.global.mode === "async") { + return r.#collect_content_async().then((content) => { + close(renderer, content.body.replaceAll("", ""), content); + }); + } else { + const content = r.#collect_content(); + close(renderer, content.body.replaceAll("", ""), content); + } + }); + } else { + close(this, body, { body: escape_html(body) }); + } + } + /** + * @param {(renderer: Renderer) => void} fn + */ + title(fn) { + const path = this.get_path(); + const close = (head) => { + this.global.set_title(head, path); + }; + this.child((renderer) => { + const r = new Renderer(renderer.global, renderer); + fn(r); + if (renderer.global.mode === "async") { + return r.#collect_content_async().then((content) => { + close(content.head); + }); + } else { + const content = r.#collect_content(); + close(content.head); + } + }); + } + /** + * @param {string | (() => Promise)} content + */ + push(content) { + if (typeof content === "function") { + this.child(async (renderer) => renderer.push(await content())); + } else { + this.#out.push(content); + } + } + /** + * @param {() => void} fn + */ + on_destroy(fn) { + (this.#on_destroy ??= []).push(fn); + } + /** + * @returns {number[]} + */ + get_path() { + return this.#parent ? [...this.#parent.get_path(), this.#parent.#out.indexOf(this)] : []; + } + /** + * @deprecated this is needed for legacy component bindings + */ + copy() { + const copy = new Renderer(this.global, this.#parent); + copy.#out = this.#out.map((item) => item instanceof Renderer ? item.copy() : item); + copy.promise = this.promise; + return copy; + } + /** + * @param {Renderer} other + * @deprecated this is needed for legacy component bindings + */ + subsume(other) { + if (this.global.mode !== other.global.mode) { + throw new Error( + "invariant: A renderer cannot switch modes. If you're seeing this, there's a compiler bug. File an issue!" + ); + } + this.local = other.local; + this.#out = other.#out.map((item) => { + if (item instanceof Renderer) { + item.subsume(item); + } + return item; + }); + this.promise = other.promise; + this.type = other.type; + } + get length() { + return this.#out.length; + } + /** + * Creates the hydration comment that marks the start of a failed boundary. + * The error is JSON-serialized and embedded inside an HTML comment for the client + * to parse during hydration. The JSON is escaped to prevent `-->` or ``; + } + /** + * Only available on the server and when compiling with the `server` option. + * Takes a component and returns an object with `body` and `head` properties on it, which you can use to populate the HTML when server-rendering your app. + * @template {Record} Props + * @param {Component} component + * @param {{ props?: Omit; context?: Map; idPrefix?: string; csp?: Csp }} [options] + * @returns {RenderOutput} + */ + static render(component, options = {}) { + let sync; + const result = ( + /** @type {RenderOutput} */ + {} + ); + Object.defineProperties(result, { + html: { + get: () => { + return (sync ??= Renderer.#render(component, options)).body; + } + }, + head: { + get: () => { + return (sync ??= Renderer.#render(component, options)).head; + } + }, + body: { + get: () => { + return (sync ??= Renderer.#render(component, options)).body; + } + }, + hashes: { + value: { + script: "" + } + }, + then: { + value: ( + /** + * this is not type-safe, but honestly it's the best I can do right now, and it's a straightforward function. + * + * @template TResult1 + * @template [TResult2=never] + * @param { (value: SyncRenderOutput) => TResult1 } onfulfilled + * @param { (reason: unknown) => TResult2 } onrejected + */ + (onfulfilled, onrejected) => { + { + const result2 = sync ??= Renderer.#render(component, options); + const user_result = onfulfilled({ + head: result2.head, + body: result2.body, + html: result2.body, + hashes: { script: [] } + }); + return Promise.resolve(user_result); + } + } + ) + } + }); + return result; + } + /** + * Collect all of the `onDestroy` callbacks registered during rendering. In an async context, this is only safe to call + * after awaiting `collect_async`. + * + * Child renderers are "porous" and don't affect execution order, but component body renderers + * create ordering boundaries. Within a renderer, callbacks run in order until hitting a component boundary. + * @returns {Iterable<() => void>} + */ + *#collect_on_destroy() { + for (const component of this.#traverse_components()) { + yield* component.#collect_ondestroy(); + } + } + /** + * Performs a depth-first search of renderers, yielding the deepest components first, then additional components as we backtrack up the tree. + * @returns {Iterable} + */ + *#traverse_components() { + for (const child of this.#out) { + if (typeof child !== "string") { + yield* child.#traverse_components(); + } + } + if (this.#is_component_body) { + yield this; + } + } + /** + * @returns {Iterable<() => void>} + */ + *#collect_ondestroy() { + if (this.#on_destroy) { + for (const fn of this.#on_destroy) { + yield fn; + } + } + for (const child of this.#out) { + if (child instanceof Renderer && !child.#is_component_body) { + yield* child.#collect_ondestroy(); + } + } + } + /** + * Render a component. Throws if any of the children are performing asynchronous work. + * + * @template {Record} Props + * @param {Component} component + * @param {{ props?: Omit; context?: Map; idPrefix?: string }} options + * @returns {AccumulatedContent} + */ + static #render(component, options) { + var previous_context = ssr_context; + try { + const renderer = Renderer.#open_render("sync", component, options); + const content = renderer.#collect_content(); + return Renderer.#close_render(content, renderer); + } finally { + abort(); + set_ssr_context(previous_context); + } + } + /** + * Render a component. + * + * @template {Record} Props + * @param {Component} component + * @param {{ props?: Omit; context?: Map; idPrefix?: string; csp?: Csp }} options + * @returns {Promise} + */ + static async #render_async(component, options) { + const previous_context = ssr_context; + try { + const renderer = Renderer.#open_render("async", component, options); + const content = await renderer.#collect_content_async(); + const hydratables = await renderer.#collect_hydratables(); + if (hydratables !== null) { + content.head = hydratables + content.head; + } + return Renderer.#close_render(content, renderer); + } finally { + set_ssr_context(previous_context); + abort(); + } + } + /** + * Collect all of the code from the `out` array and return it as a string, or a promise resolving to a string. + * @param {AccumulatedContent} content + * @returns {AccumulatedContent} + */ + #collect_content(content = { head: "", body: "" }) { + for (const item of this.#out) { + if (typeof item === "string") { + content[this.type] += item; + } else if (item instanceof Renderer) { + item.#collect_content(content); + } + } + return content; + } + /** + * Collect all of the code from the `out` array and return it as a string. + * @param {AccumulatedContent} content + * @returns {Promise} + */ + async #collect_content_async(content = { head: "", body: "" }) { + await this.promise; + for (const item of this.#out) { + if (typeof item === "string") { + content[this.type] += item; + } else if (item instanceof Renderer) { + if (item.#boundary) { + const boundary_content = { head: "", body: "" }; + try { + await item.#collect_content_async(boundary_content); + content.head += boundary_content.head; + content.body += boundary_content.body; + } catch (error) { + const { context, failed, transformError } = item.#boundary; + set_ssr_context(context); + let transformed = await transformError(error); + const failed_renderer = new Renderer(item.global, item); + failed_renderer.type = item.type; + failed_renderer.#out.push(Renderer.#serialize_failed_boundary(transformed)); + failed(failed_renderer, transformed, noop); + failed_renderer.#out.push(BLOCK_CLOSE); + await failed_renderer.#collect_content_async(content); + } + } else { + await item.#collect_content_async(content); + } + } + } + return content; + } + async #collect_hydratables() { + const ctx = get_render_context().hydratable; + for (const [_, key] of ctx.unresolved_promises) { + unresolved_hydratable(key, ctx.lookup.get(key)?.stack ?? ""); + } + for (const comparison of ctx.comparisons) { + await comparison; + } + return await this.#hydratable_block(ctx); + } + /** + * @template {Record} Props + * @param {'sync' | 'async'} mode + * @param {import('svelte').Component} component + * @param {{ props?: Omit; context?: Map; idPrefix?: string; csp?: Csp; transformError?: (error: unknown) => unknown }} options + * @returns {Renderer} + */ + static #open_render(mode, component, options) { + var previous_context = ssr_context; + try { + const renderer = new Renderer( + new SSRState( + mode, + options.idPrefix ? options.idPrefix + "-" : "", + options.csp, + options.transformError + ) + ); + const context = { p: null, c: options.context ?? null, r: renderer }; + set_ssr_context(context); + renderer.push(BLOCK_OPEN); + component(renderer, options.props ?? {}); + renderer.push(BLOCK_CLOSE); + return renderer; + } finally { + set_ssr_context(previous_context); + } + } + /** + * @param {AccumulatedContent} content + * @param {Renderer} renderer + * @returns {AccumulatedContent & { hashes: { script: Sha256Source[] } }} + */ + static #close_render(content, renderer) { + for (const cleanup of renderer.#collect_on_destroy()) { + cleanup(); + } + let head = content.head + renderer.global.get_title(); + let body = content.body; + for (const { hash, code } of renderer.global.css) { + head += ``; + } + return { + head, + body, + hashes: { + script: renderer.global.csp.script_hashes + } + }; + } + /** + * @param {HydratableContext} ctx + */ + async #hydratable_block(ctx) { + if (ctx.lookup.size === 0) { + return null; + } + let entries = []; + let has_promises = false; + for (const [k, v] of ctx.lookup) { + if (v.promises) { + has_promises = true; + for (const p of v.promises) await p; + } + entries.push(`[${devalue.uneval(k)},${v.serialized}]`); + } + let prelude = `const h = (window.__svelte ??= {}).h ??= new Map();`; + if (has_promises) { + prelude = `const r = (v) => Promise.resolve(v); + ${prelude}`; + } + const body = ` + { + ${prelude} + + for (const [k, v] of [ + ${entries.join(",\n ")} + ]) { + h.set(k, v); + } + } + `; + let csp_attr = ""; + if (this.global.csp.nonce) { + csp_attr = ` nonce="${this.global.csp.nonce}"`; + } else if (this.global.csp.hash) { + const hash = await sha256(body); + this.global.csp.script_hashes.push(`sha256-${hash}`); + } + return ` + ${body}<\/script>`; + } +} +class SSRState { + /** @readonly @type {Csp & { script_hashes: Sha256Source[] }} */ + csp; + /** @readonly @type {'sync' | 'async'} */ + mode; + /** @readonly @type {() => string} */ + uid; + /** @readonly @type {Set<{ hash: string; code: string }>} */ + css = /* @__PURE__ */ new Set(); + /** + * `transformError` passed to `render`. Called when an error boundary catches an error. + * Throws by default if unset in `render`. + * @type {(error: unknown) => unknown} + */ + transformError; + /** @type {{ path: number[], value: string }} */ + #title = { path: [], value: "" }; + /** + * @param {'sync' | 'async'} mode + * @param {string} id_prefix + * @param {Csp} csp + * @param {((error: unknown) => unknown) | undefined} [transformError] + */ + constructor(mode, id_prefix = "", csp = { hash: false }, transformError) { + this.mode = mode; + this.csp = { ...csp, script_hashes: [] }; + this.transformError = transformError ?? ((error) => { + throw error; + }); + let uid = 1; + this.uid = () => `${id_prefix}s${uid++}`; + } + get_title() { + return this.#title.value; + } + /** + * Performs a depth-first (lexicographic) comparison using the path. Rejects sets + * from earlier than or equal to the current value. + * @param {string} value + * @param {number[]} path + */ + set_title(value, path) { + const current = this.#title.path; + let i = 0; + let l = Math.min(path.length, current.length); + while (i < l && path[i] === current[i]) i += 1; + if (path[i] === void 0) return; + if (current[i] === void 0 || path[i] > current[i]) { + this.#title.path = path; + this.#title.value = value; + } + } +} +const INVALID_ATTR_NAME_CHAR_REGEX = /[\s'">/=\u{FDD0}-\u{FDEF}\u{FFFE}\u{FFFF}\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/u; +function render(component, options = {}) { + if (options.csp?.hash && options.csp.nonce) { + invalid_csp(); + } + return Renderer.render( + /** @type {Component} */ + component, + options + ); +} +function attributes(attrs, css_hash, classes, styles, flags = 0) { + if (styles) { + attrs.style = to_style(attrs.style, styles); + } + if (attrs.class) { + attrs.class = clsx(attrs.class); + } + if (css_hash || classes) { + attrs.class = to_class(attrs.class, css_hash, classes); + } + let attr_str = ""; + let name; + const is_html = (flags & ELEMENT_IS_NAMESPACED) === 0; + const lowercase = (flags & ELEMENT_PRESERVE_ATTRIBUTE_CASE) === 0; + const is_input = (flags & ELEMENT_IS_INPUT) !== 0; + for (name of Object.keys(attrs)) { + if (typeof attrs[name] === "function") continue; + if (name[0] === "$" && name[1] === "$") continue; + if (INVALID_ATTR_NAME_CHAR_REGEX.test(name)) continue; + var value = attrs[name]; + var lower = name.toLowerCase(); + if (lowercase) name = lower; + if (lower.length > 2 && lower.startsWith("on")) continue; + if (is_input) { + if (name === "defaultvalue" || name === "defaultchecked") { + name = name === "defaultvalue" ? "value" : "checked"; + if (attrs[name]) continue; + } + } + attr_str += attr(name, value, is_html && is_boolean_attribute(name)); + } + return attr_str; +} +function stringify(value) { + return typeof value === "string" ? value : value == null ? "" : value + ""; +} +function attr_class(value, hash, directives) { + var result = to_class(value, hash, directives); + return result ? ` class="${escape_html(result, true)}"` : ""; +} +function ensure_array_like(array_like_or_iterator) { + if (array_like_or_iterator) { + return array_like_or_iterator.length !== void 0 ? array_like_or_iterator : Array.from(array_like_or_iterator); + } + return []; +} +function once(get_value) { + let value = ( + /** @type {V} */ + UNINITIALIZED + ); + return () => { + if (value === UNINITIALIZED) { + value = get_value(); + } + return value; + }; +} +function derived(fn) { + const get_value = ssr_context === null ? fn : once(fn); + let updated_value; + return function(new_value) { + if (arguments.length === 0) { + return updated_value ?? get_value(); + } + updated_value = new_value; + return updated_value; + }; +} +export { + is_passive_event as $, + ASYNC as A, + BOUNDARY_EFFECT as B, + COMMENT_NODE as C, + DIRTY as D, + ERROR_VALUE as E, + EAGER_EFFECT as F, + STATE_SYMBOL as G, + HYDRATION_ERROR as H, + INERT as I, + object_prototype as J, + array_prototype as K, + get_descriptor as L, + MAYBE_DIRTY as M, + get_prototype_of as N, + is_array as O, + is_extensible as P, + HEAD_EFFECT as Q, + REACTION_RAN as R, + STALE_REACTION as S, + DESTROYING as T, + UNINITIALIZED as U, + USER_EFFECT as V, + WAS_MARKED as W, + REACTION_IS_UPDATING as X, + index_of as Y, + define_property as Z, + array_from as _, + attr as a, + LEGACY_PROPS as a0, + render as a1, + setContext as a2, + derived as a3, + ensure_array_like as b, + attr_class as c, + HYDRATION_END as d, + escape_html as e, + HYDRATION_START as f, + getContext as g, + HYDRATION_START_ELSE as h, + EFFECT as i, + CONNECTED as j, + CLEAN as k, + DERIVED as l, + BLOCK_EFFECT as m, + noop as n, + deferred as o, + RENDER_EFFECT as p, + MANAGED_EFFECT as q, + run_all as r, + stringify as s, + ROOT_EFFECT as t, + BRANCH_EFFECT as u, + DESTROYED as v, + includes as w, + HYDRATION_START_FAILED as x, + EFFECT_TRANSPARENT as y, + EFFECT_PRESERVED as z +}; diff --git a/frontend/.svelte-kit/output/server/chunks/internal.js b/frontend/.svelte-kit/output/server/chunks/internal.js new file mode 100644 index 0000000..da05518 --- /dev/null +++ b/frontend/.svelte-kit/output/server/chunks/internal.js @@ -0,0 +1,134 @@ +import { r as root } from "./root.js"; +import "./environment.js"; +let public_env = {}; +function set_private_env(environment) { +} +function set_public_env(environment) { + public_env = environment; +} +let read_implementation = null; +function set_read_implementation(fn) { + read_implementation = fn; +} +function set_manifest(_) { +} +const options = { + app_template_contains_nonce: false, + async: false, + csp: { "mode": "auto", "directives": { "upgrade-insecure-requests": false, "block-all-mixed-content": false }, "reportOnly": { "upgrade-insecure-requests": false, "block-all-mixed-content": false } }, + csrf_check_origin: true, + csrf_trusted_origins: [], + embedded: false, + env_public_prefix: "PUBLIC_", + env_private_prefix: "", + hash_routing: false, + hooks: null, + // added lazily, via `get_hooks` + preload_strategy: "modulepreload", + root, + service_worker: false, + service_worker_options: void 0, + server_error_boundaries: false, + templates: { + app: ({ head, body, assets, nonce, env }) => '\n\n \n \n \n \n ' + head + '\n \n \n
' + body + "
\n \n\n", + error: ({ status, message }) => '\n\n \n \n ' + message + ` + + + + +
+ ` + status + '\n
\n

' + message + "

\n
\n
\n \n\n" + }, + version_hash: "63i6zh" +}; +async function get_hooks() { + let handle; + let handleFetch; + let handleError; + let handleValidationError; + let init; + let reroute; + let transport; + return { + handle, + handleFetch, + handleError, + handleValidationError, + init, + reroute, + transport + }; +} +export { + set_public_env as a, + set_read_implementation as b, + set_manifest as c, + get_hooks as g, + options as o, + public_env as p, + read_implementation as r, + set_private_env as s +}; diff --git a/frontend/.svelte-kit/output/server/chunks/root.js b/frontend/.svelte-kit/output/server/chunks/root.js new file mode 100644 index 0000000..8afa68f --- /dev/null +++ b/frontend/.svelte-kit/output/server/chunks/root.js @@ -0,0 +1,2732 @@ +import { H as HYDRATION_ERROR, C as COMMENT_NODE, d as HYDRATION_END, f as HYDRATION_START, h as HYDRATION_START_ELSE, r as run_all, B as BOUNDARY_EFFECT, R as REACTION_RAN, E as ERROR_VALUE, i as EFFECT, j as CONNECTED, k as CLEAN, M as MAYBE_DIRTY, D as DIRTY, l as DERIVED, W as WAS_MARKED, I as INERT, m as BLOCK_EFFECT, U as UNINITIALIZED, o as deferred, p as RENDER_EFFECT, q as MANAGED_EFFECT, t as ROOT_EFFECT, u as BRANCH_EFFECT, v as DESTROYED, A as ASYNC, w as includes, x as HYDRATION_START_FAILED, y as EFFECT_TRANSPARENT, z as EFFECT_PRESERVED, S as STALE_REACTION, n as noop, F as EAGER_EFFECT, G as STATE_SYMBOL, J as object_prototype, K as array_prototype, L as get_descriptor, N as get_prototype_of, O as is_array, P as is_extensible, Q as HEAD_EFFECT, T as DESTROYING, V as USER_EFFECT, X as REACTION_IS_UPDATING, Y as index_of, Z as define_property, _ as array_from, $ as is_passive_event, a0 as LEGACY_PROPS, a1 as render, a2 as setContext, a3 as derived } from "./index2.js"; +import { B as BROWSER } from "./false.js"; +function equals(value) { + return value === this.v; +} +function safe_not_equal(a, b) { + return a != a ? b == b : a !== b || a !== null && typeof a === "object" || typeof a === "function"; +} +function safe_equals(value) { + return !safe_not_equal(value, this.v); +} +function effect_update_depth_exceeded() { + { + throw new Error(`https://svelte.dev/e/effect_update_depth_exceeded`); + } +} +function hydration_failed() { + { + throw new Error(`https://svelte.dev/e/hydration_failed`); + } +} +function state_descriptors_fixed() { + { + throw new Error(`https://svelte.dev/e/state_descriptors_fixed`); + } +} +function state_prototype_fixed() { + { + throw new Error(`https://svelte.dev/e/state_prototype_fixed`); + } +} +function state_unsafe_mutation() { + { + throw new Error(`https://svelte.dev/e/state_unsafe_mutation`); + } +} +function svelte_boundary_reset_onerror() { + { + throw new Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`); + } +} +function hydration_mismatch(location) { + { + console.warn(`https://svelte.dev/e/hydration_mismatch`); + } +} +function svelte_boundary_reset_noop() { + { + console.warn(`https://svelte.dev/e/svelte_boundary_reset_noop`); + } +} +let hydrating = false; +function set_hydrating(value) { + hydrating = value; +} +let hydrate_node; +function set_hydrate_node(node) { + if (node === null) { + hydration_mismatch(); + throw HYDRATION_ERROR; + } + return hydrate_node = node; +} +function hydrate_next() { + return set_hydrate_node(/* @__PURE__ */ get_next_sibling(hydrate_node)); +} +function next(count = 1) { + if (hydrating) { + var i = count; + var node = hydrate_node; + while (i--) { + node = /** @type {TemplateNode} */ + /* @__PURE__ */ get_next_sibling(node); + } + hydrate_node = node; + } +} +function skip_nodes(remove = true) { + var depth = 0; + var node = hydrate_node; + while (true) { + if (node.nodeType === COMMENT_NODE) { + var data = ( + /** @type {Comment} */ + node.data + ); + if (data === HYDRATION_END) { + if (depth === 0) return node; + depth -= 1; + } else if (data === HYDRATION_START || data === HYDRATION_START_ELSE || // "[1", "[2", etc. for if blocks + data[0] === "[" && !isNaN(Number(data.slice(1)))) { + depth += 1; + } + } + var next2 = ( + /** @type {TemplateNode} */ + /* @__PURE__ */ get_next_sibling(node) + ); + if (remove) node.remove(); + node = next2; + } +} +let tracing_mode_flag = false; +let component_context = null; +function set_component_context(context) { + component_context = context; +} +function push(props, runes = false, fn) { + component_context = { + p: component_context, + i: false, + c: null, + e: null, + s: props, + x: null, + r: ( + /** @type {Effect} */ + active_effect + ), + l: null + }; +} +function pop(component) { + var context = ( + /** @type {ComponentContext} */ + component_context + ); + var effects = context.e; + if (effects !== null) { + context.e = null; + for (var fn of effects) { + create_user_effect(fn); + } + } + context.i = true; + component_context = context.p; + return ( + /** @type {T} */ + {} + ); +} +function is_runes() { + return true; +} +let micro_tasks = []; +function run_micro_tasks() { + var tasks = micro_tasks; + micro_tasks = []; + run_all(tasks); +} +function queue_micro_task(fn) { + if (micro_tasks.length === 0 && !is_flushing_sync) { + var tasks = micro_tasks; + queueMicrotask(() => { + if (tasks === micro_tasks) run_micro_tasks(); + }); + } + micro_tasks.push(fn); +} +function flush_tasks() { + while (micro_tasks.length > 0) { + run_micro_tasks(); + } +} +function handle_error(error) { + var effect = active_effect; + if (effect === null) { + active_reaction.f |= ERROR_VALUE; + return error; + } + if ((effect.f & REACTION_RAN) === 0 && (effect.f & EFFECT) === 0) { + throw error; + } + invoke_error_boundary(error, effect); +} +function invoke_error_boundary(error, effect) { + while (effect !== null) { + if ((effect.f & BOUNDARY_EFFECT) !== 0) { + if ((effect.f & REACTION_RAN) === 0) { + throw error; + } + try { + effect.b.error(error); + return; + } catch (e) { + error = e; + } + } + effect = effect.parent; + } + throw error; +} +const STATUS_MASK = -7169; +function set_signal_status(signal, status) { + signal.f = signal.f & STATUS_MASK | status; +} +function update_derived_status(derived2) { + if ((derived2.f & CONNECTED) !== 0 || derived2.deps === null) { + set_signal_status(derived2, CLEAN); + } else { + set_signal_status(derived2, MAYBE_DIRTY); + } +} +function clear_marked(deps) { + if (deps === null) return; + for (const dep of deps) { + if ((dep.f & DERIVED) === 0 || (dep.f & WAS_MARKED) === 0) { + continue; + } + dep.f ^= WAS_MARKED; + clear_marked( + /** @type {Derived} */ + dep.deps + ); + } +} +function defer_effect(effect, dirty_effects, maybe_dirty_effects) { + if ((effect.f & DIRTY) !== 0) { + dirty_effects.add(effect); + } else if ((effect.f & MAYBE_DIRTY) !== 0) { + maybe_dirty_effects.add(effect); + } + clear_marked(effect.deps); + set_signal_status(effect, CLEAN); +} +const batches = /* @__PURE__ */ new Set(); +let current_batch = null; +let batch_values = null; +let last_scheduled_effect = null; +let is_flushing_sync = false; +let is_processing = false; +let collected_effects = null; +let legacy_updates = null; +var flush_count = 0; +let uid = 1; +class Batch { + // for debugging. TODO remove once async is stable + id = uid++; + /** + * The current values of any sources that are updated in this batch + * They keys of this map are identical to `this.#previous` + * @type {Map} + */ + current = /* @__PURE__ */ new Map(); + /** + * The values of any sources that are updated in this batch _before_ those updates took place. + * They keys of this map are identical to `this.#current` + * @type {Map} + */ + previous = /* @__PURE__ */ new Map(); + /** + * When the batch is committed (and the DOM is updated), we need to remove old branches + * and append new ones by calling the functions added inside (if/each/key/etc) blocks + * @type {Set<(batch: Batch) => void>} + */ + #commit_callbacks = /* @__PURE__ */ new Set(); + /** + * If a fork is discarded, we need to destroy any effects that are no longer needed + * @type {Set<(batch: Batch) => void>} + */ + #discard_callbacks = /* @__PURE__ */ new Set(); + /** + * The number of async effects that are currently in flight + */ + #pending = 0; + /** + * The number of async effects that are currently in flight, _not_ inside a pending boundary + */ + #blocking_pending = 0; + /** + * A deferred that resolves when the batch is committed, used with `settled()` + * TODO replace with Promise.withResolvers once supported widely enough + * @type {{ promise: Promise, resolve: (value?: any) => void, reject: (reason: unknown) => void } | null} + */ + #deferred = null; + /** + * The root effects that need to be flushed + * @type {Effect[]} + */ + #roots = []; + /** + * Deferred effects (which run after async work has completed) that are DIRTY + * @type {Set} + */ + #dirty_effects = /* @__PURE__ */ new Set(); + /** + * Deferred effects that are MAYBE_DIRTY + * @type {Set} + */ + #maybe_dirty_effects = /* @__PURE__ */ new Set(); + /** + * A map of branches that still exist, but will be destroyed when this batch + * is committed — we skip over these during `process`. + * The value contains child effects that were dirty/maybe_dirty before being reset, + * so they can be rescheduled if the branch survives. + * @type {Map} + */ + #skipped_branches = /* @__PURE__ */ new Map(); + is_fork = false; + #decrement_queued = false; + #is_deferred() { + return this.is_fork || this.#blocking_pending > 0; + } + /** + * Add an effect to the #skipped_branches map and reset its children + * @param {Effect} effect + */ + skip_effect(effect) { + if (!this.#skipped_branches.has(effect)) { + this.#skipped_branches.set(effect, { d: [], m: [] }); + } + } + /** + * Remove an effect from the #skipped_branches map and reschedule + * any tracked dirty/maybe_dirty child effects + * @param {Effect} effect + */ + unskip_effect(effect) { + var tracked = this.#skipped_branches.get(effect); + if (tracked) { + this.#skipped_branches.delete(effect); + for (var e of tracked.d) { + set_signal_status(e, DIRTY); + this.schedule(e); + } + for (e of tracked.m) { + set_signal_status(e, MAYBE_DIRTY); + this.schedule(e); + } + } + } + #process() { + if (flush_count++ > 1e3) { + batches.delete(this); + infinite_loop_guard(); + } + if (!this.#is_deferred()) { + for (const e of this.#dirty_effects) { + this.#maybe_dirty_effects.delete(e); + set_signal_status(e, DIRTY); + this.schedule(e); + } + for (const e of this.#maybe_dirty_effects) { + set_signal_status(e, MAYBE_DIRTY); + this.schedule(e); + } + } + const roots = this.#roots; + this.#roots = []; + this.apply(); + var effects = collected_effects = []; + var render_effects = []; + var updates = legacy_updates = []; + for (const root2 of roots) { + try { + this.#traverse(root2, effects, render_effects); + } catch (e) { + reset_all(root2); + throw e; + } + } + current_batch = null; + if (updates.length > 0) { + var batch = Batch.ensure(); + for (const e of updates) { + batch.schedule(e); + } + } + collected_effects = null; + legacy_updates = null; + if (this.#is_deferred()) { + this.#defer_effects(render_effects); + this.#defer_effects(effects); + for (const [e, t] of this.#skipped_branches) { + reset_branch(e, t); + } + } else { + if (this.#pending === 0) { + batches.delete(this); + } + this.#dirty_effects.clear(); + this.#maybe_dirty_effects.clear(); + for (const fn of this.#commit_callbacks) fn(this); + this.#commit_callbacks.clear(); + flush_queued_effects(render_effects); + flush_queued_effects(effects); + this.#deferred?.resolve(); + } + var next_batch = ( + /** @type {Batch | null} */ + /** @type {unknown} */ + current_batch + ); + if (this.#roots.length > 0) { + const batch2 = next_batch ??= this; + batch2.#roots.push(...this.#roots.filter((r) => !batch2.#roots.includes(r))); + } + if (next_batch !== null) { + batches.add(next_batch); + next_batch.#process(); + } + if (!batches.has(this)) { + this.#commit(); + } + } + /** + * Traverse the effect tree, executing effects or stashing + * them for later execution as appropriate + * @param {Effect} root + * @param {Effect[]} effects + * @param {Effect[]} render_effects + */ + #traverse(root2, effects, render_effects) { + root2.f ^= CLEAN; + var effect = root2.first; + while (effect !== null) { + var flags2 = effect.f; + var is_branch = (flags2 & (BRANCH_EFFECT | ROOT_EFFECT)) !== 0; + var is_skippable_branch = is_branch && (flags2 & CLEAN) !== 0; + var skip = is_skippable_branch || (flags2 & INERT) !== 0 || this.#skipped_branches.has(effect); + if (!skip && effect.fn !== null) { + if (is_branch) { + effect.f ^= CLEAN; + } else if ((flags2 & EFFECT) !== 0) { + effects.push(effect); + } else if (is_dirty(effect)) { + if ((flags2 & BLOCK_EFFECT) !== 0) this.#maybe_dirty_effects.add(effect); + update_effect(effect); + } + var child = effect.first; + if (child !== null) { + effect = child; + continue; + } + } + while (effect !== null) { + var next2 = effect.next; + if (next2 !== null) { + effect = next2; + break; + } + effect = effect.parent; + } + } + } + /** + * @param {Effect[]} effects + */ + #defer_effects(effects) { + for (var i = 0; i < effects.length; i += 1) { + defer_effect(effects[i], this.#dirty_effects, this.#maybe_dirty_effects); + } + } + /** + * Associate a change to a given source with the current + * batch, noting its previous and current values + * @param {Source} source + * @param {any} old_value + */ + capture(source2, old_value) { + if (old_value !== UNINITIALIZED && !this.previous.has(source2)) { + this.previous.set(source2, old_value); + } + if ((source2.f & ERROR_VALUE) === 0) { + this.current.set(source2, source2.v); + batch_values?.set(source2, source2.v); + } + } + activate() { + current_batch = this; + } + deactivate() { + current_batch = null; + batch_values = null; + } + flush() { + try { + is_processing = true; + current_batch = this; + this.#process(); + } finally { + flush_count = 0; + last_scheduled_effect = null; + collected_effects = null; + legacy_updates = null; + is_processing = false; + current_batch = null; + batch_values = null; + old_values.clear(); + } + } + discard() { + for (const fn of this.#discard_callbacks) fn(this); + this.#discard_callbacks.clear(); + batches.delete(this); + } + #commit() { + for (const batch of batches) { + var is_earlier = batch.id < this.id; + var sources = []; + for (const [source3, value] of this.current) { + if (batch.current.has(source3)) { + if (is_earlier && value !== batch.current.get(source3)) { + batch.current.set(source3, value); + } else { + continue; + } + } + sources.push(source3); + } + var others = [...batch.current.keys()].filter((s) => !this.current.has(s)); + if (others.length === 0) { + if (is_earlier) { + batch.discard(); + } + } else if (sources.length > 0) { + batch.activate(); + var marked = /* @__PURE__ */ new Set(); + var checked = /* @__PURE__ */ new Map(); + for (var source2 of sources) { + mark_effects(source2, others, marked, checked); + } + if (batch.#roots.length > 0) { + batch.apply(); + for (var root2 of batch.#roots) { + batch.#traverse(root2, [], []); + } + batch.#roots = []; + } + batch.deactivate(); + } + } + } + /** + * + * @param {boolean} blocking + */ + increment(blocking) { + this.#pending += 1; + if (blocking) this.#blocking_pending += 1; + } + /** + * @param {boolean} blocking + * @param {boolean} skip - whether to skip updates (because this is triggered by a stale reaction) + */ + decrement(blocking, skip) { + this.#pending -= 1; + if (blocking) this.#blocking_pending -= 1; + if (this.#decrement_queued || skip) return; + this.#decrement_queued = true; + queue_micro_task(() => { + this.#decrement_queued = false; + this.flush(); + }); + } + /** + * @param {Set} dirty_effects + * @param {Set} maybe_dirty_effects + */ + transfer_effects(dirty_effects, maybe_dirty_effects) { + for (const e of dirty_effects) { + this.#dirty_effects.add(e); + } + for (const e of maybe_dirty_effects) { + this.#maybe_dirty_effects.add(e); + } + dirty_effects.clear(); + maybe_dirty_effects.clear(); + } + /** @param {(batch: Batch) => void} fn */ + oncommit(fn) { + this.#commit_callbacks.add(fn); + } + /** @param {(batch: Batch) => void} fn */ + ondiscard(fn) { + this.#discard_callbacks.add(fn); + } + settled() { + return (this.#deferred ??= deferred()).promise; + } + static ensure() { + if (current_batch === null) { + const batch = current_batch = new Batch(); + if (!is_processing) { + batches.add(current_batch); + if (!is_flushing_sync) { + queue_micro_task(() => { + if (current_batch !== batch) { + return; + } + batch.flush(); + }); + } + } + } + return current_batch; + } + apply() { + { + batch_values = null; + return; + } + } + /** + * + * @param {Effect} effect + */ + schedule(effect) { + last_scheduled_effect = effect; + if (effect.b?.is_pending && (effect.f & (EFFECT | RENDER_EFFECT | MANAGED_EFFECT)) !== 0 && (effect.f & REACTION_RAN) === 0) { + effect.b.defer_effect(effect); + return; + } + var e = effect; + while (e.parent !== null) { + e = e.parent; + var flags2 = e.f; + if (collected_effects !== null && e === active_effect) { + if ((active_reaction === null || (active_reaction.f & DERIVED) === 0) && true) { + return; + } + } + if ((flags2 & (ROOT_EFFECT | BRANCH_EFFECT)) !== 0) { + if ((flags2 & CLEAN) === 0) { + return; + } + e.f ^= CLEAN; + } + } + this.#roots.push(e); + } +} +function flushSync(fn) { + var was_flushing_sync = is_flushing_sync; + is_flushing_sync = true; + try { + var result; + if (fn) ; + while (true) { + flush_tasks(); + if (current_batch === null) { + return ( + /** @type {T} */ + result + ); + } + current_batch.flush(); + } + } finally { + is_flushing_sync = was_flushing_sync; + } +} +function infinite_loop_guard() { + try { + effect_update_depth_exceeded(); + } catch (error) { + invoke_error_boundary(error, last_scheduled_effect); + } +} +let eager_block_effects = null; +function flush_queued_effects(effects) { + var length = effects.length; + if (length === 0) return; + var i = 0; + while (i < length) { + var effect = effects[i++]; + if ((effect.f & (DESTROYED | INERT)) === 0 && is_dirty(effect)) { + eager_block_effects = /* @__PURE__ */ new Set(); + update_effect(effect); + if (effect.deps === null && effect.first === null && effect.nodes === null && effect.teardown === null && effect.ac === null) { + unlink_effect(effect); + } + if (eager_block_effects?.size > 0) { + old_values.clear(); + for (const e of eager_block_effects) { + if ((e.f & (DESTROYED | INERT)) !== 0) continue; + const ordered_effects = [e]; + let ancestor = e.parent; + while (ancestor !== null) { + if (eager_block_effects.has(ancestor)) { + eager_block_effects.delete(ancestor); + ordered_effects.push(ancestor); + } + ancestor = ancestor.parent; + } + for (let j = ordered_effects.length - 1; j >= 0; j--) { + const e2 = ordered_effects[j]; + if ((e2.f & (DESTROYED | INERT)) !== 0) continue; + update_effect(e2); + } + } + eager_block_effects.clear(); + } + } + } + eager_block_effects = null; +} +function mark_effects(value, sources, marked, checked) { + if (marked.has(value)) return; + marked.add(value); + if (value.reactions !== null) { + for (const reaction of value.reactions) { + const flags2 = reaction.f; + if ((flags2 & DERIVED) !== 0) { + mark_effects( + /** @type {Derived} */ + reaction, + sources, + marked, + checked + ); + } else if ((flags2 & (ASYNC | BLOCK_EFFECT)) !== 0 && (flags2 & DIRTY) === 0 && depends_on(reaction, sources, checked)) { + set_signal_status(reaction, DIRTY); + schedule_effect( + /** @type {Effect} */ + reaction + ); + } + } + } +} +function depends_on(reaction, sources, checked) { + const depends = checked.get(reaction); + if (depends !== void 0) return depends; + if (reaction.deps !== null) { + for (const dep of reaction.deps) { + if (includes.call(sources, dep)) { + return true; + } + if ((dep.f & DERIVED) !== 0 && depends_on( + /** @type {Derived} */ + dep, + sources, + checked + )) { + checked.set( + /** @type {Derived} */ + dep, + true + ); + return true; + } + } + } + checked.set(reaction, false); + return false; +} +function schedule_effect(effect) { + current_batch.schedule(effect); +} +function reset_branch(effect, tracked) { + if ((effect.f & BRANCH_EFFECT) !== 0 && (effect.f & CLEAN) !== 0) { + return; + } + if ((effect.f & DIRTY) !== 0) { + tracked.d.push(effect); + } else if ((effect.f & MAYBE_DIRTY) !== 0) { + tracked.m.push(effect); + } + set_signal_status(effect, CLEAN); + var e = effect.first; + while (e !== null) { + reset_branch(e, tracked); + e = e.next; + } +} +function reset_all(effect) { + set_signal_status(effect, CLEAN); + var e = effect.first; + while (e !== null) { + reset_all(e); + e = e.next; + } +} +function createSubscriber(start) { + let subscribers = 0; + let version = source(0); + let stop; + return () => { + if (effect_tracking()) { + get(version); + render_effect(() => { + if (subscribers === 0) { + stop = untrack(() => start(() => increment(version))); + } + subscribers += 1; + return () => { + queue_micro_task(() => { + subscribers -= 1; + if (subscribers === 0) { + stop?.(); + stop = void 0; + increment(version); + } + }); + }; + }); + } + }; +} +var flags = EFFECT_TRANSPARENT | EFFECT_PRESERVED; +function boundary(node, props, children, transform_error) { + new Boundary(node, props, children, transform_error); +} +class Boundary { + /** @type {Boundary | null} */ + parent; + is_pending = false; + /** + * API-level transformError transform function. Transforms errors before they reach the `failed` snippet. + * Inherited from parent boundary, or defaults to identity. + * @type {(error: unknown) => unknown} + */ + transform_error; + /** @type {TemplateNode} */ + #anchor; + /** @type {TemplateNode | null} */ + #hydrate_open = hydrating ? hydrate_node : null; + /** @type {BoundaryProps} */ + #props; + /** @type {((anchor: Node) => void)} */ + #children; + /** @type {Effect} */ + #effect; + /** @type {Effect | null} */ + #main_effect = null; + /** @type {Effect | null} */ + #pending_effect = null; + /** @type {Effect | null} */ + #failed_effect = null; + /** @type {DocumentFragment | null} */ + #offscreen_fragment = null; + #local_pending_count = 0; + #pending_count = 0; + #pending_count_update_queued = false; + /** @type {Set} */ + #dirty_effects = /* @__PURE__ */ new Set(); + /** @type {Set} */ + #maybe_dirty_effects = /* @__PURE__ */ new Set(); + /** + * A source containing the number of pending async deriveds/expressions. + * Only created if `$effect.pending()` is used inside the boundary, + * otherwise updating the source results in needless `Batch.ensure()` + * calls followed by no-op flushes + * @type {Source | null} + */ + #effect_pending = null; + #effect_pending_subscriber = createSubscriber(() => { + this.#effect_pending = source(this.#local_pending_count); + return () => { + this.#effect_pending = null; + }; + }); + /** + * @param {TemplateNode} node + * @param {BoundaryProps} props + * @param {((anchor: Node) => void)} children + * @param {((error: unknown) => unknown) | undefined} [transform_error] + */ + constructor(node, props, children, transform_error) { + this.#anchor = node; + this.#props = props; + this.#children = (anchor) => { + var effect = ( + /** @type {Effect} */ + active_effect + ); + effect.b = this; + effect.f |= BOUNDARY_EFFECT; + children(anchor); + }; + this.parent = /** @type {Effect} */ + active_effect.b; + this.transform_error = transform_error ?? this.parent?.transform_error ?? ((e) => e); + this.#effect = block(() => { + if (hydrating) { + const comment = ( + /** @type {Comment} */ + this.#hydrate_open + ); + hydrate_next(); + const server_rendered_pending = comment.data === HYDRATION_START_ELSE; + const server_rendered_failed = comment.data.startsWith(HYDRATION_START_FAILED); + if (server_rendered_failed) { + const serialized_error = JSON.parse(comment.data.slice(HYDRATION_START_FAILED.length)); + this.#hydrate_failed_content(serialized_error); + } else if (server_rendered_pending) { + this.#hydrate_pending_content(); + } else { + this.#hydrate_resolved_content(); + } + } else { + this.#render(); + } + }, flags); + if (hydrating) { + this.#anchor = hydrate_node; + } + } + #hydrate_resolved_content() { + try { + this.#main_effect = branch(() => this.#children(this.#anchor)); + } catch (error) { + this.error(error); + } + } + /** + * @param {unknown} error The deserialized error from the server's hydration comment + */ + #hydrate_failed_content(error) { + const failed = this.#props.failed; + if (!failed) return; + this.#failed_effect = branch(() => { + failed( + this.#anchor, + () => error, + () => () => { + } + ); + }); + } + #hydrate_pending_content() { + const pending = this.#props.pending; + if (!pending) return; + this.is_pending = true; + this.#pending_effect = branch(() => pending(this.#anchor)); + queue_micro_task(() => { + var fragment = this.#offscreen_fragment = document.createDocumentFragment(); + var anchor = create_text(); + fragment.append(anchor); + this.#main_effect = this.#run(() => { + return branch(() => this.#children(anchor)); + }); + if (this.#pending_count === 0) { + this.#anchor.before(fragment); + this.#offscreen_fragment = null; + pause_effect( + /** @type {Effect} */ + this.#pending_effect, + () => { + this.#pending_effect = null; + } + ); + this.#resolve( + /** @type {Batch} */ + current_batch + ); + } + }); + } + #render() { + try { + this.is_pending = this.has_pending_snippet(); + this.#pending_count = 0; + this.#local_pending_count = 0; + this.#main_effect = branch(() => { + this.#children(this.#anchor); + }); + if (this.#pending_count > 0) { + var fragment = this.#offscreen_fragment = document.createDocumentFragment(); + move_effect(this.#main_effect, fragment); + const pending = ( + /** @type {(anchor: Node) => void} */ + this.#props.pending + ); + this.#pending_effect = branch(() => pending(this.#anchor)); + } else { + this.#resolve( + /** @type {Batch} */ + current_batch + ); + } + } catch (error) { + this.error(error); + } + } + /** + * @param {Batch} batch + */ + #resolve(batch) { + this.is_pending = false; + batch.transfer_effects(this.#dirty_effects, this.#maybe_dirty_effects); + } + /** + * Defer an effect inside a pending boundary until the boundary resolves + * @param {Effect} effect + */ + defer_effect(effect) { + defer_effect(effect, this.#dirty_effects, this.#maybe_dirty_effects); + } + /** + * Returns `false` if the effect exists inside a boundary whose pending snippet is shown + * @returns {boolean} + */ + is_rendered() { + return !this.is_pending && (!this.parent || this.parent.is_rendered()); + } + has_pending_snippet() { + return !!this.#props.pending; + } + /** + * @template T + * @param {() => T} fn + */ + #run(fn) { + var previous_effect = active_effect; + var previous_reaction = active_reaction; + var previous_ctx = component_context; + set_active_effect(this.#effect); + set_active_reaction(this.#effect); + set_component_context(this.#effect.ctx); + try { + Batch.ensure(); + return fn(); + } catch (e) { + handle_error(e); + return null; + } finally { + set_active_effect(previous_effect); + set_active_reaction(previous_reaction); + set_component_context(previous_ctx); + } + } + /** + * Updates the pending count associated with the currently visible pending snippet, + * if any, such that we can replace the snippet with content once work is done + * @param {1 | -1} d + * @param {Batch} batch + */ + #update_pending_count(d, batch) { + if (!this.has_pending_snippet()) { + if (this.parent) { + this.parent.#update_pending_count(d, batch); + } + return; + } + this.#pending_count += d; + if (this.#pending_count === 0) { + this.#resolve(batch); + if (this.#pending_effect) { + pause_effect(this.#pending_effect, () => { + this.#pending_effect = null; + }); + } + if (this.#offscreen_fragment) { + this.#anchor.before(this.#offscreen_fragment); + this.#offscreen_fragment = null; + } + } + } + /** + * Update the source that powers `$effect.pending()` inside this boundary, + * and controls when the current `pending` snippet (if any) is removed. + * Do not call from inside the class + * @param {1 | -1} d + * @param {Batch} batch + */ + update_pending_count(d, batch) { + this.#update_pending_count(d, batch); + this.#local_pending_count += d; + if (!this.#effect_pending || this.#pending_count_update_queued) return; + this.#pending_count_update_queued = true; + queue_micro_task(() => { + this.#pending_count_update_queued = false; + if (this.#effect_pending) { + internal_set(this.#effect_pending, this.#local_pending_count); + } + }); + } + get_effect_pending() { + this.#effect_pending_subscriber(); + return get( + /** @type {Source} */ + this.#effect_pending + ); + } + /** @param {unknown} error */ + error(error) { + var onerror = this.#props.onerror; + let failed = this.#props.failed; + if (!onerror && !failed) { + throw error; + } + if (this.#main_effect) { + destroy_effect(this.#main_effect); + this.#main_effect = null; + } + if (this.#pending_effect) { + destroy_effect(this.#pending_effect); + this.#pending_effect = null; + } + if (this.#failed_effect) { + destroy_effect(this.#failed_effect); + this.#failed_effect = null; + } + if (hydrating) { + set_hydrate_node( + /** @type {TemplateNode} */ + this.#hydrate_open + ); + next(); + set_hydrate_node(skip_nodes()); + } + var did_reset = false; + var calling_on_error = false; + const reset = () => { + if (did_reset) { + svelte_boundary_reset_noop(); + return; + } + did_reset = true; + if (calling_on_error) { + svelte_boundary_reset_onerror(); + } + if (this.#failed_effect !== null) { + pause_effect(this.#failed_effect, () => { + this.#failed_effect = null; + }); + } + this.#run(() => { + this.#render(); + }); + }; + const handle_error_result = (transformed_error) => { + try { + calling_on_error = true; + onerror?.(transformed_error, reset); + calling_on_error = false; + } catch (error2) { + invoke_error_boundary(error2, this.#effect && this.#effect.parent); + } + if (failed) { + this.#failed_effect = this.#run(() => { + try { + return branch(() => { + var effect = ( + /** @type {Effect} */ + active_effect + ); + effect.b = this; + effect.f |= BOUNDARY_EFFECT; + failed( + this.#anchor, + () => transformed_error, + () => reset + ); + }); + } catch (error2) { + invoke_error_boundary( + error2, + /** @type {Effect} */ + this.#effect.parent + ); + return null; + } + }); + } + }; + queue_micro_task(() => { + var result; + try { + result = this.transform_error(error); + } catch (e) { + invoke_error_boundary(e, this.#effect && this.#effect.parent); + return; + } + if (result !== null && typeof result === "object" && typeof /** @type {any} */ + result.then === "function") { + result.then( + handle_error_result, + /** @param {unknown} e */ + (e) => invoke_error_boundary(e, this.#effect && this.#effect.parent) + ); + } else { + handle_error_result(result); + } + }); + } +} +function destroy_derived_effects(derived2) { + var effects = derived2.effects; + if (effects !== null) { + derived2.effects = null; + for (var i = 0; i < effects.length; i += 1) { + destroy_effect( + /** @type {Effect} */ + effects[i] + ); + } + } +} +function get_derived_parent_effect(derived2) { + var parent = derived2.parent; + while (parent !== null) { + if ((parent.f & DERIVED) === 0) { + return (parent.f & DESTROYED) === 0 ? ( + /** @type {Effect} */ + parent + ) : null; + } + parent = parent.parent; + } + return null; +} +function execute_derived(derived2) { + var value; + var prev_active_effect = active_effect; + set_active_effect(get_derived_parent_effect(derived2)); + { + try { + derived2.f &= ~WAS_MARKED; + destroy_derived_effects(derived2); + value = update_reaction(derived2); + } finally { + set_active_effect(prev_active_effect); + } + } + return value; +} +function update_derived(derived2) { + var old_value = derived2.v; + var value = execute_derived(derived2); + if (!derived2.equals(value)) { + derived2.wv = increment_write_version(); + if (!current_batch?.is_fork || derived2.deps === null) { + derived2.v = value; + current_batch?.capture(derived2, old_value); + if (derived2.deps === null) { + set_signal_status(derived2, CLEAN); + return; + } + } + } + if (is_destroying_effect) { + return; + } + if (batch_values !== null) { + if (effect_tracking() || current_batch?.is_fork) { + batch_values.set(derived2, value); + } + } else { + update_derived_status(derived2); + } +} +function freeze_derived_effects(derived2) { + if (derived2.effects === null) return; + for (const e of derived2.effects) { + if (e.teardown || e.ac) { + e.teardown?.(); + e.ac?.abort(STALE_REACTION); + e.teardown = noop; + e.ac = null; + remove_reactions(e, 0); + destroy_effect_children(e); + } + } +} +function unfreeze_derived_effects(derived2) { + if (derived2.effects === null) return; + for (const e of derived2.effects) { + if (e.teardown) { + update_effect(e); + } + } +} +let eager_effects = /* @__PURE__ */ new Set(); +const old_values = /* @__PURE__ */ new Map(); +let eager_effects_deferred = false; +function source(v, stack) { + var signal = { + f: 0, + // TODO ideally we could skip this altogether, but it causes type errors + v, + reactions: null, + equals, + rv: 0, + wv: 0 + }; + return signal; +} +// @__NO_SIDE_EFFECTS__ +function state(v, stack) { + const s = source(v); + push_reaction_value(s); + return s; +} +// @__NO_SIDE_EFFECTS__ +function mutable_source(initial_value, immutable = false, trackable = true) { + const s = source(initial_value); + if (!immutable) { + s.equals = safe_equals; + } + return s; +} +function set(source2, value, should_proxy = false) { + if (active_reaction !== null && // since we are untracking the function inside `$inspect.with` we need to add this check + // to ensure we error if state is set inside an inspect effect + (!untracking || (active_reaction.f & EAGER_EFFECT) !== 0) && is_runes() && (active_reaction.f & (DERIVED | BLOCK_EFFECT | ASYNC | EAGER_EFFECT)) !== 0 && (current_sources === null || !includes.call(current_sources, source2))) { + state_unsafe_mutation(); + } + let new_value = should_proxy ? proxy(value) : value; + return internal_set(source2, new_value, legacy_updates); +} +function internal_set(source2, value, updated_during_traversal = null) { + if (!source2.equals(value)) { + var old_value = source2.v; + if (is_destroying_effect) { + old_values.set(source2, value); + } else { + old_values.set(source2, old_value); + } + source2.v = value; + var batch = Batch.ensure(); + batch.capture(source2, old_value); + if ((source2.f & DERIVED) !== 0) { + const derived2 = ( + /** @type {Derived} */ + source2 + ); + if ((source2.f & DIRTY) !== 0) { + execute_derived(derived2); + } + if (batch_values === null) { + update_derived_status(derived2); + } + } + source2.wv = increment_write_version(); + mark_reactions(source2, DIRTY, updated_during_traversal); + if (active_effect !== null && (active_effect.f & CLEAN) !== 0 && (active_effect.f & (BRANCH_EFFECT | ROOT_EFFECT)) === 0) { + if (untracked_writes === null) { + set_untracked_writes([source2]); + } else { + untracked_writes.push(source2); + } + } + if (!batch.is_fork && eager_effects.size > 0 && !eager_effects_deferred) { + flush_eager_effects(); + } + } + return value; +} +function flush_eager_effects() { + eager_effects_deferred = false; + for (const effect of eager_effects) { + if ((effect.f & CLEAN) !== 0) { + set_signal_status(effect, MAYBE_DIRTY); + } + if (is_dirty(effect)) { + update_effect(effect); + } + } + eager_effects.clear(); +} +function increment(source2) { + set(source2, source2.v + 1); +} +function mark_reactions(signal, status, updated_during_traversal) { + var reactions = signal.reactions; + if (reactions === null) return; + var length = reactions.length; + for (var i = 0; i < length; i++) { + var reaction = reactions[i]; + var flags2 = reaction.f; + var not_dirty = (flags2 & DIRTY) === 0; + if (not_dirty) { + set_signal_status(reaction, status); + } + if ((flags2 & DERIVED) !== 0) { + var derived2 = ( + /** @type {Derived} */ + reaction + ); + batch_values?.delete(derived2); + if ((flags2 & WAS_MARKED) === 0) { + if (flags2 & CONNECTED) { + reaction.f |= WAS_MARKED; + } + mark_reactions(derived2, MAYBE_DIRTY, updated_during_traversal); + } + } else if (not_dirty) { + var effect = ( + /** @type {Effect} */ + reaction + ); + if ((flags2 & BLOCK_EFFECT) !== 0 && eager_block_effects !== null) { + eager_block_effects.add(effect); + } + if (updated_during_traversal !== null) { + updated_during_traversal.push(effect); + } else { + schedule_effect(effect); + } + } + } +} +function proxy(value) { + if (typeof value !== "object" || value === null || STATE_SYMBOL in value) { + return value; + } + const prototype = get_prototype_of(value); + if (prototype !== object_prototype && prototype !== array_prototype) { + return value; + } + var sources = /* @__PURE__ */ new Map(); + var is_proxied_array = is_array(value); + var version = /* @__PURE__ */ state(0); + var parent_version = update_version; + var with_parent = (fn) => { + if (update_version === parent_version) { + return fn(); + } + var reaction = active_reaction; + var version2 = update_version; + set_active_reaction(null); + set_update_version(parent_version); + var result = fn(); + set_active_reaction(reaction); + set_update_version(version2); + return result; + }; + if (is_proxied_array) { + sources.set("length", /* @__PURE__ */ state( + /** @type {any[]} */ + value.length + )); + } + return new Proxy( + /** @type {any} */ + value, + { + defineProperty(_, prop, descriptor) { + if (!("value" in descriptor) || descriptor.configurable === false || descriptor.enumerable === false || descriptor.writable === false) { + state_descriptors_fixed(); + } + var s = sources.get(prop); + if (s === void 0) { + with_parent(() => { + var s2 = /* @__PURE__ */ state(descriptor.value); + sources.set(prop, s2); + return s2; + }); + } else { + set(s, descriptor.value, true); + } + return true; + }, + deleteProperty(target, prop) { + var s = sources.get(prop); + if (s === void 0) { + if (prop in target) { + const s2 = with_parent(() => /* @__PURE__ */ state(UNINITIALIZED)); + sources.set(prop, s2); + increment(version); + } + } else { + set(s, UNINITIALIZED); + increment(version); + } + return true; + }, + get(target, prop, receiver) { + if (prop === STATE_SYMBOL) { + return value; + } + var s = sources.get(prop); + var exists = prop in target; + if (s === void 0 && (!exists || get_descriptor(target, prop)?.writable)) { + s = with_parent(() => { + var p = proxy(exists ? target[prop] : UNINITIALIZED); + var s2 = /* @__PURE__ */ state(p); + return s2; + }); + sources.set(prop, s); + } + if (s !== void 0) { + var v = get(s); + return v === UNINITIALIZED ? void 0 : v; + } + return Reflect.get(target, prop, receiver); + }, + getOwnPropertyDescriptor(target, prop) { + var descriptor = Reflect.getOwnPropertyDescriptor(target, prop); + if (descriptor && "value" in descriptor) { + var s = sources.get(prop); + if (s) descriptor.value = get(s); + } else if (descriptor === void 0) { + var source2 = sources.get(prop); + var value2 = source2?.v; + if (source2 !== void 0 && value2 !== UNINITIALIZED) { + return { + enumerable: true, + configurable: true, + value: value2, + writable: true + }; + } + } + return descriptor; + }, + has(target, prop) { + if (prop === STATE_SYMBOL) { + return true; + } + var s = sources.get(prop); + var has = s !== void 0 && s.v !== UNINITIALIZED || Reflect.has(target, prop); + if (s !== void 0 || active_effect !== null && (!has || get_descriptor(target, prop)?.writable)) { + if (s === void 0) { + s = with_parent(() => { + var p = has ? proxy(target[prop]) : UNINITIALIZED; + var s2 = /* @__PURE__ */ state(p); + return s2; + }); + sources.set(prop, s); + } + var value2 = get(s); + if (value2 === UNINITIALIZED) { + return false; + } + } + return has; + }, + set(target, prop, value2, receiver) { + var s = sources.get(prop); + var has = prop in target; + if (is_proxied_array && prop === "length") { + for (var i = value2; i < /** @type {Source} */ + s.v; i += 1) { + var other_s = sources.get(i + ""); + if (other_s !== void 0) { + set(other_s, UNINITIALIZED); + } else if (i in target) { + other_s = with_parent(() => /* @__PURE__ */ state(UNINITIALIZED)); + sources.set(i + "", other_s); + } + } + } + if (s === void 0) { + if (!has || get_descriptor(target, prop)?.writable) { + s = with_parent(() => /* @__PURE__ */ state(void 0)); + set(s, proxy(value2)); + sources.set(prop, s); + } + } else { + has = s.v !== UNINITIALIZED; + var p = with_parent(() => proxy(value2)); + set(s, p); + } + var descriptor = Reflect.getOwnPropertyDescriptor(target, prop); + if (descriptor?.set) { + descriptor.set.call(receiver, value2); + } + if (!has) { + if (is_proxied_array && typeof prop === "string") { + var ls = ( + /** @type {Source} */ + sources.get("length") + ); + var n = Number(prop); + if (Number.isInteger(n) && n >= ls.v) { + set(ls, n + 1); + } + } + increment(version); + } + return true; + }, + ownKeys(target) { + get(version); + var own_keys = Reflect.ownKeys(target).filter((key2) => { + var source3 = sources.get(key2); + return source3 === void 0 || source3.v !== UNINITIALIZED; + }); + for (var [key, source2] of sources) { + if (source2.v !== UNINITIALIZED && !(key in target)) { + own_keys.push(key); + } + } + return own_keys; + }, + setPrototypeOf() { + state_prototype_fixed(); + } + } + ); +} +var $window; +var first_child_getter; +var next_sibling_getter; +function init_operations() { + if ($window !== void 0) { + return; + } + $window = window; + var element_prototype = Element.prototype; + var node_prototype = Node.prototype; + var text_prototype = Text.prototype; + first_child_getter = get_descriptor(node_prototype, "firstChild").get; + next_sibling_getter = get_descriptor(node_prototype, "nextSibling").get; + if (is_extensible(element_prototype)) { + element_prototype.__click = void 0; + element_prototype.__className = void 0; + element_prototype.__attributes = null; + element_prototype.__style = void 0; + element_prototype.__e = void 0; + } + if (is_extensible(text_prototype)) { + text_prototype.__t = void 0; + } +} +function create_text(value = "") { + return document.createTextNode(value); +} +// @__NO_SIDE_EFFECTS__ +function get_first_child(node) { + return ( + /** @type {TemplateNode | null} */ + first_child_getter.call(node) + ); +} +// @__NO_SIDE_EFFECTS__ +function get_next_sibling(node) { + return ( + /** @type {TemplateNode | null} */ + next_sibling_getter.call(node) + ); +} +function clear_text_content(node) { + node.textContent = ""; +} +function without_reactive_context(fn) { + var previous_reaction = active_reaction; + var previous_effect = active_effect; + set_active_reaction(null); + set_active_effect(null); + try { + return fn(); + } finally { + set_active_reaction(previous_reaction); + set_active_effect(previous_effect); + } +} +function push_effect(effect, parent_effect) { + var parent_last = parent_effect.last; + if (parent_last === null) { + parent_effect.last = parent_effect.first = effect; + } else { + parent_last.next = effect; + effect.prev = parent_last; + parent_effect.last = effect; + } +} +function create_effect(type, fn) { + var parent = active_effect; + if (parent !== null && (parent.f & INERT) !== 0) { + type |= INERT; + } + var effect = { + ctx: component_context, + deps: null, + nodes: null, + f: type | DIRTY | CONNECTED, + first: null, + fn, + last: null, + next: null, + parent, + b: parent && parent.b, + prev: null, + teardown: null, + wv: 0, + ac: null + }; + var e = effect; + if ((type & EFFECT) !== 0) { + if (collected_effects !== null) { + collected_effects.push(effect); + } else { + Batch.ensure().schedule(effect); + } + } else if (fn !== null) { + try { + update_effect(effect); + } catch (e2) { + destroy_effect(effect); + throw e2; + } + if (e.deps === null && e.teardown === null && e.nodes === null && e.first === e.last && // either `null`, or a singular child + (e.f & EFFECT_PRESERVED) === 0) { + e = e.first; + if ((type & BLOCK_EFFECT) !== 0 && (type & EFFECT_TRANSPARENT) !== 0 && e !== null) { + e.f |= EFFECT_TRANSPARENT; + } + } + } + if (e !== null) { + e.parent = parent; + if (parent !== null) { + push_effect(e, parent); + } + if (active_reaction !== null && (active_reaction.f & DERIVED) !== 0 && (type & ROOT_EFFECT) === 0) { + var derived2 = ( + /** @type {Derived} */ + active_reaction + ); + (derived2.effects ??= []).push(e); + } + } + return effect; +} +function effect_tracking() { + return active_reaction !== null && !untracking; +} +function create_user_effect(fn) { + return create_effect(EFFECT | USER_EFFECT, fn); +} +function component_root(fn) { + Batch.ensure(); + const effect = create_effect(ROOT_EFFECT | EFFECT_PRESERVED, fn); + return (options = {}) => { + return new Promise((fulfil) => { + if (options.outro) { + pause_effect(effect, () => { + destroy_effect(effect); + fulfil(void 0); + }); + } else { + destroy_effect(effect); + fulfil(void 0); + } + }); + }; +} +function render_effect(fn, flags2 = 0) { + return create_effect(RENDER_EFFECT | flags2, fn); +} +function block(fn, flags2 = 0) { + var effect = create_effect(BLOCK_EFFECT | flags2, fn); + return effect; +} +function branch(fn) { + return create_effect(BRANCH_EFFECT | EFFECT_PRESERVED, fn); +} +function execute_effect_teardown(effect) { + var teardown = effect.teardown; + if (teardown !== null) { + const previously_destroying_effect = is_destroying_effect; + const previous_reaction = active_reaction; + set_is_destroying_effect(true); + set_active_reaction(null); + try { + teardown.call(null); + } finally { + set_is_destroying_effect(previously_destroying_effect); + set_active_reaction(previous_reaction); + } + } +} +function destroy_effect_children(signal, remove_dom = false) { + var effect = signal.first; + signal.first = signal.last = null; + while (effect !== null) { + const controller = effect.ac; + if (controller !== null) { + without_reactive_context(() => { + controller.abort(STALE_REACTION); + }); + } + var next2 = effect.next; + if ((effect.f & ROOT_EFFECT) !== 0) { + effect.parent = null; + } else { + destroy_effect(effect, remove_dom); + } + effect = next2; + } +} +function destroy_block_effect_children(signal) { + var effect = signal.first; + while (effect !== null) { + var next2 = effect.next; + if ((effect.f & BRANCH_EFFECT) === 0) { + destroy_effect(effect); + } + effect = next2; + } +} +function destroy_effect(effect, remove_dom = true) { + var removed = false; + if ((remove_dom || (effect.f & HEAD_EFFECT) !== 0) && effect.nodes !== null && effect.nodes.end !== null) { + remove_effect_dom( + effect.nodes.start, + /** @type {TemplateNode} */ + effect.nodes.end + ); + removed = true; + } + set_signal_status(effect, DESTROYING); + destroy_effect_children(effect, remove_dom && !removed); + remove_reactions(effect, 0); + var transitions = effect.nodes && effect.nodes.t; + if (transitions !== null) { + for (const transition of transitions) { + transition.stop(); + } + } + execute_effect_teardown(effect); + effect.f ^= DESTROYING; + effect.f |= DESTROYED; + var parent = effect.parent; + if (parent !== null && parent.first !== null) { + unlink_effect(effect); + } + effect.next = effect.prev = effect.teardown = effect.ctx = effect.deps = effect.fn = effect.nodes = effect.ac = null; +} +function remove_effect_dom(node, end) { + while (node !== null) { + var next2 = node === end ? null : /* @__PURE__ */ get_next_sibling(node); + node.remove(); + node = next2; + } +} +function unlink_effect(effect) { + var parent = effect.parent; + var prev = effect.prev; + var next2 = effect.next; + if (prev !== null) prev.next = next2; + if (next2 !== null) next2.prev = prev; + if (parent !== null) { + if (parent.first === effect) parent.first = next2; + if (parent.last === effect) parent.last = prev; + } +} +function pause_effect(effect, callback, destroy = true) { + var transitions = []; + pause_children(effect, transitions, true); + var fn = () => { + if (destroy) destroy_effect(effect); + if (callback) callback(); + }; + var remaining = transitions.length; + if (remaining > 0) { + var check = () => --remaining || fn(); + for (var transition of transitions) { + transition.out(check); + } + } else { + fn(); + } +} +function pause_children(effect, transitions, local) { + if ((effect.f & INERT) !== 0) return; + effect.f ^= INERT; + var t = effect.nodes && effect.nodes.t; + if (t !== null) { + for (const transition of t) { + if (transition.is_global || local) { + transitions.push(transition); + } + } + } + var child = effect.first; + while (child !== null) { + var sibling = child.next; + var transparent = (child.f & EFFECT_TRANSPARENT) !== 0 || // If this is a branch effect without a block effect parent, + // it means the parent block effect was pruned. In that case, + // transparency information was transferred to the branch effect. + (child.f & BRANCH_EFFECT) !== 0 && (effect.f & BLOCK_EFFECT) !== 0; + pause_children(child, transitions, transparent ? local : false); + child = sibling; + } +} +function move_effect(effect, fragment) { + if (!effect.nodes) return; + var node = effect.nodes.start; + var end = effect.nodes.end; + while (node !== null) { + var next2 = node === end ? null : /* @__PURE__ */ get_next_sibling(node); + fragment.append(node); + node = next2; + } +} +let is_updating_effect = false; +let is_destroying_effect = false; +function set_is_destroying_effect(value) { + is_destroying_effect = value; +} +let active_reaction = null; +let untracking = false; +function set_active_reaction(reaction) { + active_reaction = reaction; +} +let active_effect = null; +function set_active_effect(effect) { + active_effect = effect; +} +let current_sources = null; +function push_reaction_value(value) { + if (active_reaction !== null && true) { + if (current_sources === null) { + current_sources = [value]; + } else { + current_sources.push(value); + } + } +} +let new_deps = null; +let skipped_deps = 0; +let untracked_writes = null; +function set_untracked_writes(value) { + untracked_writes = value; +} +let write_version = 1; +let read_version = 0; +let update_version = read_version; +function set_update_version(value) { + update_version = value; +} +function increment_write_version() { + return ++write_version; +} +function is_dirty(reaction) { + var flags2 = reaction.f; + if ((flags2 & DIRTY) !== 0) { + return true; + } + if (flags2 & DERIVED) { + reaction.f &= ~WAS_MARKED; + } + if ((flags2 & MAYBE_DIRTY) !== 0) { + var dependencies = ( + /** @type {Value[]} */ + reaction.deps + ); + var length = dependencies.length; + for (var i = 0; i < length; i++) { + var dependency = dependencies[i]; + if (is_dirty( + /** @type {Derived} */ + dependency + )) { + update_derived( + /** @type {Derived} */ + dependency + ); + } + if (dependency.wv > reaction.wv) { + return true; + } + } + if ((flags2 & CONNECTED) !== 0 && // During time traveling we don't want to reset the status so that + // traversal of the graph in the other batches still happens + batch_values === null) { + set_signal_status(reaction, CLEAN); + } + } + return false; +} +function schedule_possible_effect_self_invalidation(signal, effect, root2 = true) { + var reactions = signal.reactions; + if (reactions === null) return; + if (current_sources !== null && includes.call(current_sources, signal)) { + return; + } + for (var i = 0; i < reactions.length; i++) { + var reaction = reactions[i]; + if ((reaction.f & DERIVED) !== 0) { + schedule_possible_effect_self_invalidation( + /** @type {Derived} */ + reaction, + effect, + false + ); + } else if (effect === reaction) { + if (root2) { + set_signal_status(reaction, DIRTY); + } else if ((reaction.f & CLEAN) !== 0) { + set_signal_status(reaction, MAYBE_DIRTY); + } + schedule_effect( + /** @type {Effect} */ + reaction + ); + } + } +} +function update_reaction(reaction) { + var previous_deps = new_deps; + var previous_skipped_deps = skipped_deps; + var previous_untracked_writes = untracked_writes; + var previous_reaction = active_reaction; + var previous_sources = current_sources; + var previous_component_context = component_context; + var previous_untracking = untracking; + var previous_update_version = update_version; + var flags2 = reaction.f; + new_deps = /** @type {null | Value[]} */ + null; + skipped_deps = 0; + untracked_writes = null; + active_reaction = (flags2 & (BRANCH_EFFECT | ROOT_EFFECT)) === 0 ? reaction : null; + current_sources = null; + set_component_context(reaction.ctx); + untracking = false; + update_version = ++read_version; + if (reaction.ac !== null) { + without_reactive_context(() => { + reaction.ac.abort(STALE_REACTION); + }); + reaction.ac = null; + } + try { + reaction.f |= REACTION_IS_UPDATING; + var fn = ( + /** @type {Function} */ + reaction.fn + ); + var result = fn(); + reaction.f |= REACTION_RAN; + var deps = reaction.deps; + var is_fork = current_batch?.is_fork; + if (new_deps !== null) { + var i; + if (!is_fork) { + remove_reactions(reaction, skipped_deps); + } + if (deps !== null && skipped_deps > 0) { + deps.length = skipped_deps + new_deps.length; + for (i = 0; i < new_deps.length; i++) { + deps[skipped_deps + i] = new_deps[i]; + } + } else { + reaction.deps = deps = new_deps; + } + if (effect_tracking() && (reaction.f & CONNECTED) !== 0) { + for (i = skipped_deps; i < deps.length; i++) { + (deps[i].reactions ??= []).push(reaction); + } + } + } else if (!is_fork && deps !== null && skipped_deps < deps.length) { + remove_reactions(reaction, skipped_deps); + deps.length = skipped_deps; + } + if (is_runes() && untracked_writes !== null && !untracking && deps !== null && (reaction.f & (DERIVED | MAYBE_DIRTY | DIRTY)) === 0) { + for (i = 0; i < /** @type {Source[]} */ + untracked_writes.length; i++) { + schedule_possible_effect_self_invalidation( + untracked_writes[i], + /** @type {Effect} */ + reaction + ); + } + } + if (previous_reaction !== null && previous_reaction !== reaction) { + read_version++; + if (previous_reaction.deps !== null) { + for (let i2 = 0; i2 < previous_skipped_deps; i2 += 1) { + previous_reaction.deps[i2].rv = read_version; + } + } + if (previous_deps !== null) { + for (const dep of previous_deps) { + dep.rv = read_version; + } + } + if (untracked_writes !== null) { + if (previous_untracked_writes === null) { + previous_untracked_writes = untracked_writes; + } else { + previous_untracked_writes.push(.../** @type {Source[]} */ + untracked_writes); + } + } + } + if ((reaction.f & ERROR_VALUE) !== 0) { + reaction.f ^= ERROR_VALUE; + } + return result; + } catch (error) { + return handle_error(error); + } finally { + reaction.f ^= REACTION_IS_UPDATING; + new_deps = previous_deps; + skipped_deps = previous_skipped_deps; + untracked_writes = previous_untracked_writes; + active_reaction = previous_reaction; + current_sources = previous_sources; + set_component_context(previous_component_context); + untracking = previous_untracking; + update_version = previous_update_version; + } +} +function remove_reaction(signal, dependency) { + let reactions = dependency.reactions; + if (reactions !== null) { + var index = index_of.call(reactions, signal); + if (index !== -1) { + var new_length = reactions.length - 1; + if (new_length === 0) { + reactions = dependency.reactions = null; + } else { + reactions[index] = reactions[new_length]; + reactions.pop(); + } + } + } + if (reactions === null && (dependency.f & DERIVED) !== 0 && // Destroying a child effect while updating a parent effect can cause a dependency to appear + // to be unused, when in fact it is used by the currently-updating parent. Checking `new_deps` + // allows us to skip the expensive work of disconnecting and immediately reconnecting it + (new_deps === null || !includes.call(new_deps, dependency))) { + var derived2 = ( + /** @type {Derived} */ + dependency + ); + if ((derived2.f & CONNECTED) !== 0) { + derived2.f ^= CONNECTED; + derived2.f &= ~WAS_MARKED; + } + update_derived_status(derived2); + freeze_derived_effects(derived2); + remove_reactions(derived2, 0); + } +} +function remove_reactions(signal, start_index) { + var dependencies = signal.deps; + if (dependencies === null) return; + for (var i = start_index; i < dependencies.length; i++) { + remove_reaction(signal, dependencies[i]); + } +} +function update_effect(effect) { + var flags2 = effect.f; + if ((flags2 & DESTROYED) !== 0) { + return; + } + set_signal_status(effect, CLEAN); + var previous_effect = active_effect; + var was_updating_effect = is_updating_effect; + active_effect = effect; + is_updating_effect = true; + try { + if ((flags2 & (BLOCK_EFFECT | MANAGED_EFFECT)) !== 0) { + destroy_block_effect_children(effect); + } else { + destroy_effect_children(effect); + } + execute_effect_teardown(effect); + var teardown = update_reaction(effect); + effect.teardown = typeof teardown === "function" ? teardown : null; + effect.wv = write_version; + var dep; + if (BROWSER && tracing_mode_flag && (effect.f & DIRTY) !== 0 && effect.deps !== null) ; + } finally { + is_updating_effect = was_updating_effect; + active_effect = previous_effect; + } +} +function get(signal) { + var flags2 = signal.f; + var is_derived = (flags2 & DERIVED) !== 0; + if (active_reaction !== null && !untracking) { + var destroyed = active_effect !== null && (active_effect.f & DESTROYED) !== 0; + if (!destroyed && (current_sources === null || !includes.call(current_sources, signal))) { + var deps = active_reaction.deps; + if ((active_reaction.f & REACTION_IS_UPDATING) !== 0) { + if (signal.rv < read_version) { + signal.rv = read_version; + if (new_deps === null && deps !== null && deps[skipped_deps] === signal) { + skipped_deps++; + } else if (new_deps === null) { + new_deps = [signal]; + } else { + new_deps.push(signal); + } + } + } else { + (active_reaction.deps ??= []).push(signal); + var reactions = signal.reactions; + if (reactions === null) { + signal.reactions = [active_reaction]; + } else if (!includes.call(reactions, active_reaction)) { + reactions.push(active_reaction); + } + } + } + } + if (is_destroying_effect && old_values.has(signal)) { + return old_values.get(signal); + } + if (is_derived) { + var derived2 = ( + /** @type {Derived} */ + signal + ); + if (is_destroying_effect) { + var value = derived2.v; + if ((derived2.f & CLEAN) === 0 && derived2.reactions !== null || depends_on_old_values(derived2)) { + value = execute_derived(derived2); + } + old_values.set(derived2, value); + return value; + } + var should_connect = (derived2.f & CONNECTED) === 0 && !untracking && active_reaction !== null && (is_updating_effect || (active_reaction.f & CONNECTED) !== 0); + var is_new = (derived2.f & REACTION_RAN) === 0; + if (is_dirty(derived2)) { + if (should_connect) { + derived2.f |= CONNECTED; + } + update_derived(derived2); + } + if (should_connect && !is_new) { + unfreeze_derived_effects(derived2); + reconnect(derived2); + } + } + if (batch_values?.has(signal)) { + return batch_values.get(signal); + } + if ((signal.f & ERROR_VALUE) !== 0) { + throw signal.v; + } + return signal.v; +} +function reconnect(derived2) { + derived2.f |= CONNECTED; + if (derived2.deps === null) return; + for (const dep of derived2.deps) { + (dep.reactions ??= []).push(derived2); + if ((dep.f & DERIVED) !== 0 && (dep.f & CONNECTED) === 0) { + unfreeze_derived_effects( + /** @type {Derived} */ + dep + ); + reconnect( + /** @type {Derived} */ + dep + ); + } + } +} +function depends_on_old_values(derived2) { + if (derived2.v === UNINITIALIZED) return true; + if (derived2.deps === null) return false; + for (const dep of derived2.deps) { + if (old_values.has(dep)) { + return true; + } + if ((dep.f & DERIVED) !== 0 && depends_on_old_values( + /** @type {Derived} */ + dep + )) { + return true; + } + } + return false; +} +function untrack(fn) { + var previous_untracking = untracking; + try { + untracking = true; + return fn(); + } finally { + untracking = previous_untracking; + } +} +const event_symbol = Symbol("events"); +const all_registered_events = /* @__PURE__ */ new Set(); +const root_event_handles = /* @__PURE__ */ new Set(); +let last_propagated_event = null; +function handle_event_propagation(event) { + var handler_element = this; + var owner_document = ( + /** @type {Node} */ + handler_element.ownerDocument + ); + var event_name = event.type; + var path = event.composedPath?.() || []; + var current_target = ( + /** @type {null | Element} */ + path[0] || event.target + ); + last_propagated_event = event; + var path_idx = 0; + var handled_at = last_propagated_event === event && event[event_symbol]; + if (handled_at) { + var at_idx = path.indexOf(handled_at); + if (at_idx !== -1 && (handler_element === document || handler_element === /** @type {any} */ + window)) { + event[event_symbol] = handler_element; + return; + } + var handler_idx = path.indexOf(handler_element); + if (handler_idx === -1) { + return; + } + if (at_idx <= handler_idx) { + path_idx = at_idx; + } + } + current_target = /** @type {Element} */ + path[path_idx] || event.target; + if (current_target === handler_element) return; + define_property(event, "currentTarget", { + configurable: true, + get() { + return current_target || owner_document; + } + }); + var previous_reaction = active_reaction; + var previous_effect = active_effect; + set_active_reaction(null); + set_active_effect(null); + try { + var throw_error; + var other_errors = []; + while (current_target !== null) { + var parent_element = current_target.assignedSlot || current_target.parentNode || /** @type {any} */ + current_target.host || null; + try { + var delegated = current_target[event_symbol]?.[event_name]; + if (delegated != null && (!/** @type {any} */ + current_target.disabled || // DOM could've been updated already by the time this is reached, so we check this as well + // -> the target could not have been disabled because it emits the event in the first place + event.target === current_target)) { + delegated.call(current_target, event); + } + } catch (error) { + if (throw_error) { + other_errors.push(error); + } else { + throw_error = error; + } + } + if (event.cancelBubble || parent_element === handler_element || parent_element === null) { + break; + } + current_target = parent_element; + } + if (throw_error) { + for (let error of other_errors) { + queueMicrotask(() => { + throw error; + }); + } + throw throw_error; + } + } finally { + event[event_symbol] = handler_element; + delete event.currentTarget; + set_active_reaction(previous_reaction); + set_active_effect(previous_effect); + } +} +function assign_nodes(start, end) { + var effect = ( + /** @type {Effect} */ + active_effect + ); + if (effect.nodes === null) { + effect.nodes = { start, end, a: null, t: null }; + } +} +function mount(component, options) { + return _mount(component, options); +} +function hydrate(component, options) { + init_operations(); + options.intro = options.intro ?? false; + const target = options.target; + const was_hydrating = hydrating; + const previous_hydrate_node = hydrate_node; + try { + var anchor = /* @__PURE__ */ get_first_child(target); + while (anchor && (anchor.nodeType !== COMMENT_NODE || /** @type {Comment} */ + anchor.data !== HYDRATION_START)) { + anchor = /* @__PURE__ */ get_next_sibling(anchor); + } + if (!anchor) { + throw HYDRATION_ERROR; + } + set_hydrating(true); + set_hydrate_node( + /** @type {Comment} */ + anchor + ); + const instance = _mount(component, { ...options, anchor }); + set_hydrating(false); + return ( + /** @type {Exports} */ + instance + ); + } catch (error) { + if (error instanceof Error && error.message.split("\n").some((line) => line.startsWith("https://svelte.dev/e/"))) { + throw error; + } + if (error !== HYDRATION_ERROR) { + console.warn("Failed to hydrate: ", error); + } + if (options.recover === false) { + hydration_failed(); + } + init_operations(); + clear_text_content(target); + set_hydrating(false); + return mount(component, options); + } finally { + set_hydrating(was_hydrating); + set_hydrate_node(previous_hydrate_node); + } +} +const listeners = /* @__PURE__ */ new Map(); +function _mount(Component, { target, anchor, props = {}, events, context, intro = true, transformError }) { + init_operations(); + var component = void 0; + var unmount2 = component_root(() => { + var anchor_node = anchor ?? target.appendChild(create_text()); + boundary( + /** @type {TemplateNode} */ + anchor_node, + { + pending: () => { + } + }, + (anchor_node2) => { + push({}); + var ctx = ( + /** @type {ComponentContext} */ + component_context + ); + if (context) ctx.c = context; + if (events) { + props.$$events = events; + } + if (hydrating) { + assign_nodes( + /** @type {TemplateNode} */ + anchor_node2, + null + ); + } + component = Component(anchor_node2, props) || {}; + if (hydrating) { + active_effect.nodes.end = hydrate_node; + if (hydrate_node === null || hydrate_node.nodeType !== COMMENT_NODE || /** @type {Comment} */ + hydrate_node.data !== HYDRATION_END) { + hydration_mismatch(); + throw HYDRATION_ERROR; + } + } + pop(); + }, + transformError + ); + var registered_events = /* @__PURE__ */ new Set(); + var event_handle = (events2) => { + for (var i = 0; i < events2.length; i++) { + var event_name = events2[i]; + if (registered_events.has(event_name)) continue; + registered_events.add(event_name); + var passive = is_passive_event(event_name); + for (const node of [target, document]) { + var counts = listeners.get(node); + if (counts === void 0) { + counts = /* @__PURE__ */ new Map(); + listeners.set(node, counts); + } + var count = counts.get(event_name); + if (count === void 0) { + node.addEventListener(event_name, handle_event_propagation, { passive }); + counts.set(event_name, 1); + } else { + counts.set(event_name, count + 1); + } + } + } + }; + event_handle(array_from(all_registered_events)); + root_event_handles.add(event_handle); + return () => { + for (var event_name of registered_events) { + for (const node of [target, document]) { + var counts = ( + /** @type {Map} */ + listeners.get(node) + ); + var count = ( + /** @type {number} */ + counts.get(event_name) + ); + if (--count == 0) { + node.removeEventListener(event_name, handle_event_propagation); + counts.delete(event_name); + if (counts.size === 0) { + listeners.delete(node); + } + } else { + counts.set(event_name, count); + } + } + } + root_event_handles.delete(event_handle); + if (anchor_node !== anchor) { + anchor_node.parentNode?.removeChild(anchor_node); + } + }; + }); + mounted_components.set(component, unmount2); + return component; +} +let mounted_components = /* @__PURE__ */ new WeakMap(); +function unmount(component, options) { + const fn = mounted_components.get(component); + if (fn) { + mounted_components.delete(component); + return fn(options); + } + return Promise.resolve(); +} +function asClassComponent$1(component) { + return class extends Svelte4Component { + /** @param {any} options */ + constructor(options) { + super({ + component, + ...options + }); + } + }; +} +class Svelte4Component { + /** @type {any} */ + #events; + /** @type {Record} */ + #instance; + /** + * @param {ComponentConstructorOptions & { + * component: any; + * }} options + */ + constructor(options) { + var sources = /* @__PURE__ */ new Map(); + var add_source = (key, value) => { + var s = /* @__PURE__ */ mutable_source(value, false, false); + sources.set(key, s); + return s; + }; + const props = new Proxy( + { ...options.props || {}, $$events: {} }, + { + get(target, prop) { + return get(sources.get(prop) ?? add_source(prop, Reflect.get(target, prop))); + }, + has(target, prop) { + if (prop === LEGACY_PROPS) return true; + get(sources.get(prop) ?? add_source(prop, Reflect.get(target, prop))); + return Reflect.has(target, prop); + }, + set(target, prop, value) { + set(sources.get(prop) ?? add_source(prop, value), value); + return Reflect.set(target, prop, value); + } + } + ); + this.#instance = (options.hydrate ? hydrate : mount)(options.component, { + target: options.target, + anchor: options.anchor, + props, + context: options.context, + intro: options.intro ?? false, + recover: options.recover, + transformError: options.transformError + }); + if (!options?.props?.$$host || options.sync === false) { + flushSync(); + } + this.#events = props.$$events; + for (const key of Object.keys(this.#instance)) { + if (key === "$set" || key === "$destroy" || key === "$on") continue; + define_property(this, key, { + get() { + return this.#instance[key]; + }, + /** @param {any} value */ + set(value) { + this.#instance[key] = value; + }, + enumerable: true + }); + } + this.#instance.$set = /** @param {Record} next */ + (next2) => { + Object.assign(props, next2); + }; + this.#instance.$destroy = () => { + unmount(this.#instance); + }; + } + /** @param {Record} props */ + $set(props) { + this.#instance.$set(props); + } + /** + * @param {string} event + * @param {(...args: any[]) => any} callback + * @returns {any} + */ + $on(event, callback) { + this.#events[event] = this.#events[event] || []; + const cb = (...args) => callback.call(this, ...args); + this.#events[event].push(cb); + return () => { + this.#events[event] = this.#events[event].filter( + /** @param {any} fn */ + (fn) => fn !== cb + ); + }; + } + $destroy() { + this.#instance.$destroy(); + } +} +function asClassComponent(component) { + const component_constructor = asClassComponent$1(component); + const _render = (props, { context, csp, transformError } = {}) => { + const result = render(component, { props, context, csp, transformError }); + const munged = Object.defineProperties( + /** @type {LegacyRenderResult & PromiseLike} */ + {}, + { + css: { + value: { code: "", map: null } + }, + head: { + get: () => result.head + }, + html: { + get: () => result.body + }, + then: { + /** + * this is not type-safe, but honestly it's the best I can do right now, and it's a straightforward function. + * + * @template TResult1 + * @template [TResult2=never] + * @param { (value: LegacyRenderResult) => TResult1 } onfulfilled + * @param { (reason: unknown) => TResult2 } onrejected + */ + value: (onfulfilled, onrejected) => { + { + const user_result = onfulfilled({ + css: munged.css, + head: munged.head, + html: munged.html + }); + return Promise.resolve(user_result); + } + } + } + } + ); + return munged; + }; + component_constructor.render = _render; + return component_constructor; +} +function Root($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + let { + stores, + page, + constructors, + components = [], + form, + data_0 = null, + data_1 = null + } = $$props; + { + setContext("__svelte__", stores); + } + { + stores.page.set(page); + } + const Pyramid_1 = derived(() => constructors[1]); + if (constructors[1]) { + $$renderer2.push(""); + const Pyramid_0 = constructors[0]; + if (Pyramid_0) { + $$renderer2.push(""); + Pyramid_0($$renderer2, { + data: data_0, + form, + params: page.params, + children: ($$renderer3) => { + if (Pyramid_1()) { + $$renderer3.push(""); + Pyramid_1()($$renderer3, { data: data_1, form, params: page.params }); + $$renderer3.push(""); + } else { + $$renderer3.push(""); + $$renderer3.push(""); + } + }, + $$slots: { default: true } + }); + $$renderer2.push(""); + } else { + $$renderer2.push(""); + $$renderer2.push(""); + } + } else { + $$renderer2.push(""); + const Pyramid_0 = constructors[0]; + if (Pyramid_0) { + $$renderer2.push(""); + Pyramid_0($$renderer2, { data: data_0, form, params: page.params }); + $$renderer2.push(""); + } else { + $$renderer2.push(""); + $$renderer2.push(""); + } + } + $$renderer2.push(` `); + { + $$renderer2.push(""); + } + $$renderer2.push(``); + }); +} +const root = asClassComponent(Root); +export { + root as r, + safe_not_equal as s +}; diff --git a/frontend/.svelte-kit/output/server/chunks/shared.js b/frontend/.svelte-kit/output/server/chunks/shared.js new file mode 100644 index 0000000..a0fdd68 --- /dev/null +++ b/frontend/.svelte-kit/output/server/chunks/shared.js @@ -0,0 +1,789 @@ +import { json, text } from "@sveltejs/kit"; +import { SvelteKitError, HttpError } from "@sveltejs/kit/internal"; +import { with_request_store } from "@sveltejs/kit/internal/server"; +import * as devalue from "devalue"; +import { t as text_decoder, b as base64_encode, c as base64_decode } from "./utils.js"; +const SVELTE_KIT_ASSETS = "/_svelte_kit_assets"; +const ENDPOINT_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]; +const MUTATIVE_METHODS = ["POST", "PUT", "PATCH", "DELETE"]; +const PAGE_METHODS = ["GET", "POST", "HEAD"]; +function set_nested_value(object, path_string, value) { + if (path_string.startsWith("n:")) { + path_string = path_string.slice(2); + value = value === "" ? void 0 : parseFloat(value); + } else if (path_string.startsWith("b:")) { + path_string = path_string.slice(2); + value = value === "on"; + } + deep_set(object, split_path(path_string), value); +} +function convert_formdata(data) { + const result = {}; + for (let key of data.keys()) { + const is_array = key.endsWith("[]"); + let values = data.getAll(key); + if (is_array) key = key.slice(0, -2); + if (values.length > 1 && !is_array) { + throw new Error(`Form cannot contain duplicated keys — "${key}" has ${values.length} values`); + } + values = values.filter( + (entry) => typeof entry === "string" || entry.name !== "" || entry.size > 0 + ); + if (key.startsWith("n:")) { + key = key.slice(2); + values = values.map((v) => v === "" ? void 0 : parseFloat( + /** @type {string} */ + v + )); + } else if (key.startsWith("b:")) { + key = key.slice(2); + values = values.map((v) => v === "on"); + } + set_nested_value(result, key, is_array ? values : values[0]); + } + return result; +} +const BINARY_FORM_CONTENT_TYPE = "application/x-sveltekit-formdata"; +const BINARY_FORM_VERSION = 0; +const HEADER_BYTES = 1 + 4 + 2; +async function deserialize_binary_form(request) { + if (request.headers.get("content-type") !== BINARY_FORM_CONTENT_TYPE) { + const form_data = await request.formData(); + return { data: convert_formdata(form_data), meta: {}, form_data }; + } + if (!request.body) { + throw deserialize_error("no body"); + } + const content_length = parseInt(request.headers.get("content-length") ?? ""); + if (Number.isNaN(content_length)) { + throw deserialize_error("invalid Content-Length header"); + } + const reader = request.body.getReader(); + const chunks = []; + function get_chunk(index) { + if (index in chunks) return chunks[index]; + let i = chunks.length; + while (i <= index) { + chunks[i] = reader.read().then((chunk) => chunk.value); + i++; + } + return chunks[index]; + } + async function get_buffer(offset, length) { + let start_chunk; + let chunk_start = 0; + let chunk_index; + for (chunk_index = 0; ; chunk_index++) { + const chunk = await get_chunk(chunk_index); + if (!chunk) return null; + const chunk_end = chunk_start + chunk.byteLength; + if (offset >= chunk_start && offset < chunk_end) { + start_chunk = chunk; + break; + } + chunk_start = chunk_end; + } + if (offset + length <= chunk_start + start_chunk.byteLength) { + return start_chunk.subarray(offset - chunk_start, offset + length - chunk_start); + } + const chunks2 = [start_chunk.subarray(offset - chunk_start)]; + let cursor = start_chunk.byteLength - offset + chunk_start; + while (cursor < length) { + chunk_index++; + let chunk = await get_chunk(chunk_index); + if (!chunk) return null; + if (chunk.byteLength > length - cursor) { + chunk = chunk.subarray(0, length - cursor); + } + chunks2.push(chunk); + cursor += chunk.byteLength; + } + const buffer = new Uint8Array(length); + cursor = 0; + for (const chunk of chunks2) { + buffer.set(chunk, cursor); + cursor += chunk.byteLength; + } + return buffer; + } + const header = await get_buffer(0, HEADER_BYTES); + if (!header) throw deserialize_error("too short"); + if (header[0] !== BINARY_FORM_VERSION) { + throw deserialize_error(`got version ${header[0]}, expected version ${BINARY_FORM_VERSION}`); + } + const header_view = new DataView(header.buffer, header.byteOffset, header.byteLength); + const data_length = header_view.getUint32(1, true); + if (HEADER_BYTES + data_length > content_length) { + throw deserialize_error("data overflow"); + } + const file_offsets_length = header_view.getUint16(5, true); + if (HEADER_BYTES + data_length + file_offsets_length > content_length) { + throw deserialize_error("file offset table overflow"); + } + const data_buffer = await get_buffer(HEADER_BYTES, data_length); + if (!data_buffer) throw deserialize_error("data too short"); + let file_offsets; + let files_start_offset; + if (file_offsets_length > 0) { + const file_offsets_buffer = await get_buffer(HEADER_BYTES + data_length, file_offsets_length); + if (!file_offsets_buffer) throw deserialize_error("file offset table too short"); + const parsed_offsets = JSON.parse(text_decoder.decode(file_offsets_buffer)); + if (!Array.isArray(parsed_offsets) || parsed_offsets.some((n) => typeof n !== "number" || !Number.isInteger(n) || n < 0)) { + throw deserialize_error("invalid file offset table"); + } + file_offsets = /** @type {Array} */ + parsed_offsets; + files_start_offset = HEADER_BYTES + data_length + file_offsets_length; + } + const file_spans = []; + const [data, meta] = devalue.parse(text_decoder.decode(data_buffer), { + File: ([name, type, size, last_modified, index]) => { + if (typeof name !== "string" || typeof type !== "string" || typeof size !== "number" || typeof last_modified !== "number" || typeof index !== "number") { + throw deserialize_error("invalid file metadata"); + } + let offset = file_offsets[index]; + if (offset === void 0) { + throw deserialize_error("duplicate file offset table index"); + } + file_offsets[index] = void 0; + offset += files_start_offset; + if (offset + size > content_length) { + throw deserialize_error("file data overflow"); + } + file_spans.push({ offset, size }); + return new Proxy(new LazyFile(name, type, size, last_modified, get_chunk, offset), { + getPrototypeOf() { + return File.prototype; + } + }); + } + }); + file_spans.sort((a, b) => a.offset - b.offset || a.size - b.size); + for (let i = 1; i < file_spans.length; i++) { + const previous = file_spans[i - 1]; + const current = file_spans[i]; + const previous_end = previous.offset + previous.size; + if (previous_end < current.offset) { + throw deserialize_error("gaps in file data"); + } + if (previous_end > current.offset) { + throw deserialize_error("overlapping file data"); + } + } + void (async () => { + let has_more = true; + while (has_more) { + const chunk = await get_chunk(chunks.length); + has_more = !!chunk; + } + })(); + return { data, meta, form_data: null }; +} +function deserialize_error(message) { + return new SvelteKitError(400, "Bad Request", `Could not deserialize binary form: ${message}`); +} +class LazyFile { + /** @type {(index: number) => Promise | undefined>} */ + #get_chunk; + /** @type {number} */ + #offset; + /** + * @param {string} name + * @param {string} type + * @param {number} size + * @param {number} last_modified + * @param {(index: number) => Promise | undefined>} get_chunk + * @param {number} offset + */ + constructor(name, type, size, last_modified, get_chunk, offset) { + this.name = name; + this.type = type; + this.size = size; + this.lastModified = last_modified; + this.webkitRelativePath = ""; + this.#get_chunk = get_chunk; + this.#offset = offset; + this.arrayBuffer = this.arrayBuffer.bind(this); + this.bytes = this.bytes.bind(this); + this.slice = this.slice.bind(this); + this.stream = this.stream.bind(this); + this.text = this.text.bind(this); + } + /** @type {ArrayBuffer | undefined} */ + #buffer; + async arrayBuffer() { + this.#buffer ??= await new Response(this.stream()).arrayBuffer(); + return this.#buffer; + } + async bytes() { + return new Uint8Array(await this.arrayBuffer()); + } + /** + * @param {number=} start + * @param {number=} end + * @param {string=} contentType + */ + slice(start = 0, end = this.size, contentType = this.type) { + if (start < 0) { + start = Math.max(this.size + start, 0); + } else { + start = Math.min(start, this.size); + } + if (end < 0) { + end = Math.max(this.size + end, 0); + } else { + end = Math.min(end, this.size); + } + const size = Math.max(end - start, 0); + const file = new LazyFile( + this.name, + contentType, + size, + this.lastModified, + this.#get_chunk, + this.#offset + start + ); + return file; + } + stream() { + let cursor = 0; + let chunk_index = 0; + return new ReadableStream({ + start: async (controller) => { + let chunk_start = 0; + let start_chunk; + for (chunk_index = 0; ; chunk_index++) { + const chunk = await this.#get_chunk(chunk_index); + if (!chunk) return null; + const chunk_end = chunk_start + chunk.byteLength; + if (this.#offset >= chunk_start && this.#offset < chunk_end) { + start_chunk = chunk; + break; + } + chunk_start = chunk_end; + } + if (this.#offset + this.size <= chunk_start + start_chunk.byteLength) { + controller.enqueue( + start_chunk.subarray(this.#offset - chunk_start, this.#offset + this.size - chunk_start) + ); + controller.close(); + } else { + controller.enqueue(start_chunk.subarray(this.#offset - chunk_start)); + cursor = start_chunk.byteLength - this.#offset + chunk_start; + } + }, + pull: async (controller) => { + chunk_index++; + let chunk = await this.#get_chunk(chunk_index); + if (!chunk) { + controller.error("incomplete file data"); + controller.close(); + return; + } + if (chunk.byteLength > this.size - cursor) { + chunk = chunk.subarray(0, this.size - cursor); + } + controller.enqueue(chunk); + cursor += chunk.byteLength; + if (cursor >= this.size) { + controller.close(); + } + } + }); + } + async text() { + return text_decoder.decode(await this.arrayBuffer()); + } +} +const path_regex = /^[a-zA-Z_$]\w*(\.[a-zA-Z_$]\w*|\[\d+\])*$/; +function split_path(path) { + if (!path_regex.test(path)) { + throw new Error(`Invalid path ${path}`); + } + return path.split(/\.|\[|\]/).filter(Boolean); +} +function check_prototype_pollution(key) { + if (key === "__proto__" || key === "constructor" || key === "prototype") { + throw new Error( + `Invalid key "${key}"` + ); + } +} +function deep_set(object, keys, value) { + let current = object; + for (let i = 0; i < keys.length - 1; i += 1) { + const key = keys[i]; + check_prototype_pollution(key); + const is_array = /^\d+$/.test(keys[i + 1]); + const exists = Object.hasOwn(current, key); + const inner = current[key]; + if (exists && is_array !== Array.isArray(inner)) { + throw new Error(`Invalid array key ${keys[i + 1]}`); + } + if (!exists) { + current[key] = is_array ? [] : {}; + } + current = current[key]; + } + const final_key = keys[keys.length - 1]; + check_prototype_pollution(final_key); + current[final_key] = value; +} +function normalize_issue(issue, server = false) { + const normalized = { name: "", path: [], message: issue.message, server }; + if (issue.path !== void 0) { + let name = ""; + for (const segment of issue.path) { + const key = ( + /** @type {string | number} */ + typeof segment === "object" ? segment.key : segment + ); + normalized.path.push(key); + if (typeof key === "number") { + name += `[${key}]`; + } else if (typeof key === "string") { + name += name === "" ? key : "." + key; + } + } + normalized.name = name; + } + return normalized; +} +function flatten_issues(issues) { + const result = {}; + for (const issue of issues) { + (result.$ ??= []).push(issue); + let name = ""; + if (issue.path !== void 0) { + for (const key of issue.path) { + if (typeof key === "number") { + name += `[${key}]`; + } else if (typeof key === "string") { + name += name === "" ? key : "." + key; + } + (result[name] ??= []).push(issue); + } + } + } + return result; +} +function deep_get(object, path) { + let current = object; + for (const key of path) { + if (current == null || typeof current !== "object") { + return current; + } + current = current[key]; + } + return current; +} +function create_field_proxy(target, get_input, set_input, get_issues, path = []) { + const get_value = () => { + return deep_get(get_input(), path); + }; + return new Proxy(target, { + get(target2, prop) { + if (typeof prop === "symbol") return target2[prop]; + if (/^\d+$/.test(prop)) { + return create_field_proxy({}, get_input, set_input, get_issues, [ + ...path, + parseInt(prop, 10) + ]); + } + const key = build_path_string(path); + if (prop === "set") { + const set_func = function(newValue) { + set_input(path, newValue); + return newValue; + }; + return create_field_proxy(set_func, get_input, set_input, get_issues, [...path, prop]); + } + if (prop === "value") { + return create_field_proxy(get_value, get_input, set_input, get_issues, [...path, prop]); + } + if (prop === "issues" || prop === "allIssues") { + const issues_func = () => { + const all_issues = get_issues()[key === "" ? "$" : key]; + if (prop === "allIssues") { + return all_issues?.map((issue) => ({ + path: issue.path, + message: issue.message + })); + } + return all_issues?.filter((issue) => issue.name === key)?.map((issue) => ({ + path: issue.path, + message: issue.message + })); + }; + return create_field_proxy(issues_func, get_input, set_input, get_issues, [...path, prop]); + } + if (prop === "as") { + const as_func = (type, input_value) => { + const is_array = type === "file multiple" || type === "select multiple" || type === "checkbox" && typeof input_value === "string"; + const prefix = type === "number" || type === "range" ? "n:" : type === "checkbox" && !is_array ? "b:" : ""; + const base_props = { + name: prefix + key + (is_array ? "[]" : ""), + get "aria-invalid"() { + const issues = get_issues(); + return key in issues ? "true" : void 0; + } + }; + if (type !== "text" && type !== "select" && type !== "select multiple") { + base_props.type = type === "file multiple" ? "file" : type; + } + if (type === "submit" || type === "hidden") { + return Object.defineProperties(base_props, { + value: { value: input_value, enumerable: true } + }); + } + if (type === "select" || type === "select multiple") { + return Object.defineProperties(base_props, { + multiple: { value: is_array, enumerable: true }, + value: { + enumerable: true, + get() { + return get_value(); + } + } + }); + } + if (type === "checkbox" || type === "radio") { + return Object.defineProperties(base_props, { + value: { value: input_value ?? "on", enumerable: true }, + checked: { + enumerable: true, + get() { + const value = get_value(); + if (type === "radio") { + return value === input_value; + } + if (is_array) { + return (value ?? []).includes(input_value); + } + return value; + } + } + }); + } + if (type === "file" || type === "file multiple") { + return Object.defineProperties(base_props, { + multiple: { value: is_array, enumerable: true }, + files: { + enumerable: true, + get() { + const value = get_value(); + if (value instanceof File) { + if (typeof DataTransfer !== "undefined") { + const fileList = new DataTransfer(); + fileList.items.add(value); + return fileList.files; + } + return { 0: value, length: 1 }; + } + if (Array.isArray(value) && value.every((f) => f instanceof File)) { + if (typeof DataTransfer !== "undefined") { + const fileList = new DataTransfer(); + value.forEach((file) => fileList.items.add(file)); + return fileList.files; + } + const fileListLike = { length: value.length }; + value.forEach((file, index) => { + fileListLike[index] = file; + }); + return fileListLike; + } + return null; + } + } + }); + } + return Object.defineProperties(base_props, { + value: { + enumerable: true, + get() { + const value = get_value(); + return value != null ? String(value) : ""; + } + } + }); + }; + return create_field_proxy(as_func, get_input, set_input, get_issues, [...path, "as"]); + } + return create_field_proxy({}, get_input, set_input, get_issues, [...path, prop]); + } + }); +} +function build_path_string(path) { + let result = ""; + for (const segment of path) { + if (typeof segment === "number") { + result += `[${segment}]`; + } else { + result += result === "" ? segment : "." + segment; + } + } + return result; +} +function negotiate(accept, types) { + const parts = []; + accept.split(",").forEach((str, i) => { + const match = /([^/ \t]+)\/([^; \t]+)[ \t]*(?:;[ \t]*q=([0-9.]+))?/.exec(str); + if (match) { + const [, type, subtype, q = "1"] = match; + parts.push({ type, subtype, q: +q, i }); + } + }); + parts.sort((a, b) => { + if (a.q !== b.q) { + return b.q - a.q; + } + if (a.subtype === "*" !== (b.subtype === "*")) { + return a.subtype === "*" ? 1 : -1; + } + if (a.type === "*" !== (b.type === "*")) { + return a.type === "*" ? 1 : -1; + } + return a.i - b.i; + }); + let accepted; + let min_priority = Infinity; + for (const mimetype of types) { + const [type, subtype] = mimetype.split("/"); + const priority = parts.findIndex( + (part) => (part.type === type || part.type === "*") && (part.subtype === subtype || part.subtype === "*") + ); + if (priority !== -1 && priority < min_priority) { + accepted = mimetype; + min_priority = priority; + } + } + return accepted; +} +function is_content_type(request, ...types) { + const type = request.headers.get("content-type")?.split(";", 1)[0].trim() ?? ""; + return types.includes(type.toLowerCase()); +} +function is_form_content_type(request) { + return is_content_type( + request, + "application/x-www-form-urlencoded", + "multipart/form-data", + "text/plain", + BINARY_FORM_CONTENT_TYPE + ); +} +function coalesce_to_error(err) { + return err instanceof Error || err && /** @type {any} */ + err.name && /** @type {any} */ + err.message ? ( + /** @type {Error} */ + err + ) : new Error(JSON.stringify(err)); +} +function normalize_error(error) { + return ( + /** @type {import('../exports/internal/index.js').Redirect | HttpError | SvelteKitError | Error} */ + error + ); +} +function get_status(error) { + return error instanceof HttpError || error instanceof SvelteKitError ? error.status : 500; +} +function get_message(error) { + return error instanceof SvelteKitError ? error.text : "Internal Error"; +} +const escape_html_attr_dict = { + "&": "&", + '"': """ + // Svelte also escapes < because the escape function could be called inside a `noscript` there + // https://github.com/sveltejs/svelte/security/advisories/GHSA-8266-84wp-wv5c + // However, that doesn't apply in SvelteKit +}; +const escape_html_dict = { + "&": "&", + "<": "<" +}; +const surrogates = ( + // high surrogate without paired low surrogate + "[\\ud800-\\udbff](?![\\udc00-\\udfff])|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\udc00-\\udfff]" +); +const escape_html_attr_regex = new RegExp( + `[${Object.keys(escape_html_attr_dict).join("")}]|` + surrogates, + "g" +); +const escape_html_regex = new RegExp( + `[${Object.keys(escape_html_dict).join("")}]|` + surrogates, + "g" +); +function escape_html(str, is_attr) { + const dict = is_attr ? escape_html_attr_dict : escape_html_dict; + const escaped_str = str.replace(is_attr ? escape_html_attr_regex : escape_html_regex, (match) => { + if (match.length === 2) { + return match; + } + return dict[match] ?? `&#${match.charCodeAt(0)};`; + }); + return escaped_str; +} +function method_not_allowed(mod, method) { + return text(`${method} method not allowed`, { + status: 405, + headers: { + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405 + // "The server must generate an Allow header field in a 405 status code response" + allow: allowed_methods(mod).join(", ") + } + }); +} +function allowed_methods(mod) { + const allowed = ENDPOINT_METHODS.filter((method) => method in mod); + if ("GET" in mod && !("HEAD" in mod)) { + allowed.push("HEAD"); + } + return allowed; +} +function get_global_name(options) { + return `__sveltekit_${options.version_hash}`; +} +function static_error_page(options, status, message) { + let page = options.templates.error({ status, message: escape_html(message) }); + return text(page, { + headers: { "content-type": "text/html; charset=utf-8" }, + status + }); +} +async function handle_fatal_error(event, state, options, error) { + error = error instanceof HttpError ? error : coalesce_to_error(error); + const status = get_status(error); + const body = await handle_error_and_jsonify(event, state, options, error); + const type = negotiate(event.request.headers.get("accept") || "text/html", [ + "application/json", + "text/html" + ]); + if (event.isDataRequest || type === "application/json") { + return json(body, { + status + }); + } + return static_error_page(options, status, body.message); +} +async function handle_error_and_jsonify(event, state, options, error) { + if (error instanceof HttpError) { + return { message: "Unknown Error", ...error.body }; + } + const status = get_status(error); + const message = get_message(error); + return await with_request_store( + { event, state }, + () => options.hooks.handleError({ error, event, status, message }) + ) ?? { message }; +} +function redirect_response(status, location) { + const response = new Response(void 0, { + status, + headers: { location } + }); + return response; +} +function clarify_devalue_error(event, error) { + if (error.path) { + return `Data returned from \`load\` while rendering ${event.route.id} is not serializable: ${error.message} (${error.path}). If you need to serialize/deserialize custom types, use transport hooks: https://svelte.dev/docs/kit/hooks#Universal-hooks-transport.`; + } + if (error.path === "") { + return `Data returned from \`load\` while rendering ${event.route.id} is not a plain object`; + } + return error.message; +} +function serialize_uses(node) { + const uses = {}; + if (node.uses && node.uses.dependencies.size > 0) { + uses.dependencies = Array.from(node.uses.dependencies); + } + if (node.uses && node.uses.search_params.size > 0) { + uses.search_params = Array.from(node.uses.search_params); + } + if (node.uses && node.uses.params.size > 0) { + uses.params = Array.from(node.uses.params); + } + if (node.uses?.parent) uses.parent = 1; + if (node.uses?.route) uses.route = 1; + if (node.uses?.url) uses.url = 1; + return uses; +} +function has_prerendered_path(manifest, pathname) { + return manifest._.prerendered_routes.has(pathname) || pathname.at(-1) === "/" && manifest._.prerendered_routes.has(pathname.slice(0, -1)); +} +function format_server_error(status, error, event) { + const formatted_text = ` +\x1B[1;31m[${status}] ${event.request.method} ${event.url.pathname}\x1B[0m`; + if (status === 404) { + return formatted_text; + } + return `${formatted_text} +${error.stack}`; +} +function get_node_type(node_id) { + const parts = node_id?.split("/"); + const filename = parts?.at(-1); + if (!filename) return "unknown"; + const dot_parts = filename.split("."); + return dot_parts.slice(0, -1).join("."); +} +const INVALIDATED_PARAM = "x-sveltekit-invalidated"; +const TRAILING_SLASH_PARAM = "x-sveltekit-trailing-slash"; +function stringify(data, transport) { + const encoders = Object.fromEntries(Object.entries(transport).map(([k, v]) => [k, v.encode])); + return devalue.stringify(data, encoders); +} +function stringify_remote_arg(value, transport) { + if (value === void 0) return ""; + const json_string = stringify(value, transport); + const bytes = new TextEncoder().encode(json_string); + return base64_encode(bytes).replaceAll("=", "").replaceAll("+", "-").replaceAll("/", "_"); +} +function parse_remote_arg(string, transport) { + if (!string) return void 0; + const json_string = text_decoder.decode( + // no need to add back `=` characters, atob can handle it + base64_decode(string.replaceAll("-", "+").replaceAll("_", "/")) + ); + const decoders = Object.fromEntries(Object.entries(transport).map(([k, v]) => [k, v.decode])); + return devalue.parse(json_string, decoders); +} +function create_remote_key(id, payload) { + return id + "/" + payload; +} +export { + ENDPOINT_METHODS as E, + INVALIDATED_PARAM as I, + MUTATIVE_METHODS as M, + PAGE_METHODS as P, + SVELTE_KIT_ASSETS as S, + TRAILING_SLASH_PARAM as T, + normalize_error as a, + get_global_name as b, + clarify_devalue_error as c, + get_node_type as d, + escape_html as e, + create_remote_key as f, + get_status as g, + handle_error_and_jsonify as h, + is_form_content_type as i, + static_error_page as j, + stringify as k, + deserialize_binary_form as l, + method_not_allowed as m, + negotiate as n, + has_prerendered_path as o, + parse_remote_arg as p, + handle_fatal_error as q, + redirect_response as r, + serialize_uses as s, + format_server_error as t, + stringify_remote_arg as u, + create_field_proxy as v, + normalize_issue as w, + set_nested_value as x, + flatten_issues as y, + deep_set as z +}; diff --git a/frontend/.svelte-kit/output/server/chunks/state.svelte.js b/frontend/.svelte-kit/output/server/chunks/state.svelte.js new file mode 100644 index 0000000..8f471d9 --- /dev/null +++ b/frontend/.svelte-kit/output/server/chunks/state.svelte.js @@ -0,0 +1,19 @@ +import "clsx"; +import { n as noop } from "./index2.js"; +import "./exports.js"; +import "@sveltejs/kit/internal/server"; +import "./root.js"; +const is_legacy = noop.toString().includes("$$") || /function \w+\(\) \{\}/.test(noop.toString()); +const placeholder_url = "a:"; +if (is_legacy) { + ({ + data: {}, + form: null, + error: null, + params: {}, + route: { id: null }, + state: {}, + status: -1, + url: new URL(placeholder_url) + }); +} diff --git a/frontend/.svelte-kit/output/server/chunks/utils.js b/frontend/.svelte-kit/output/server/chunks/utils.js new file mode 100644 index 0000000..78e5bde --- /dev/null +++ b/frontend/.svelte-kit/output/server/chunks/utils.js @@ -0,0 +1,43 @@ +const text_encoder = new TextEncoder(); +const text_decoder = new TextDecoder(); +function get_relative_path(from, to) { + const from_parts = from.split(/[/\\]/); + const to_parts = to.split(/[/\\]/); + from_parts.pop(); + while (from_parts[0] === to_parts[0]) { + from_parts.shift(); + to_parts.shift(); + } + let i = from_parts.length; + while (i--) from_parts[i] = ".."; + return from_parts.concat(to_parts).join("/"); +} +function base64_encode(bytes) { + if (globalThis.Buffer) { + return globalThis.Buffer.from(bytes).toString("base64"); + } + let binary = ""; + for (let i = 0; i < bytes.length; i++) { + binary += String.fromCharCode(bytes[i]); + } + return btoa(binary); +} +function base64_decode(encoded) { + if (globalThis.Buffer) { + const buffer = globalThis.Buffer.from(encoded, "base64"); + return new Uint8Array(buffer); + } + const binary = atob(encoded); + const bytes = new Uint8Array(binary.length); + for (let i = 0; i < binary.length; i++) { + bytes[i] = binary.charCodeAt(i); + } + return bytes; +} +export { + text_encoder as a, + base64_encode as b, + base64_decode as c, + get_relative_path as g, + text_decoder as t +}; diff --git a/frontend/.svelte-kit/output/server/entries/fallbacks/error.svelte.js b/frontend/.svelte-kit/output/server/entries/fallbacks/error.svelte.js new file mode 100644 index 0000000..d1e09f2 --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/fallbacks/error.svelte.js @@ -0,0 +1,45 @@ +import { g as getContext, e as escape_html } from "../../chunks/index2.js"; +import "clsx"; +import "../../chunks/state.svelte.js"; +import "@sveltejs/kit/internal"; +import "../../chunks/exports.js"; +import "../../chunks/utils.js"; +import { w as writable } from "../../chunks/index.js"; +import "@sveltejs/kit/internal/server"; +import "../../chunks/root.js"; +function create_updated_store() { + const { set, subscribe } = writable(false); + { + return { + subscribe, + // eslint-disable-next-line @typescript-eslint/require-await + check: async () => false + }; + } +} +const stores = { + updated: /* @__PURE__ */ create_updated_store() +}; +({ + check: stores.updated.check +}); +function context() { + return getContext("__request__"); +} +const page$1 = { + get error() { + return context().page.error; + }, + get status() { + return context().page.status; + } +}; +const page = page$1; +function Error$1($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + $$renderer2.push(`

${escape_html(page.status)}

${escape_html(page.error?.message)}

`); + }); +} +export { + Error$1 as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/_layout.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/_layout.svelte.js new file mode 100644 index 0000000..334fe5b --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/_layout.svelte.js @@ -0,0 +1,20 @@ +import "clsx"; +import "@sveltejs/kit/internal"; +import "../../chunks/exports.js"; +import "../../chunks/utils.js"; +import "@sveltejs/kit/internal/server"; +import "../../chunks/root.js"; +import "../../chunks/state.svelte.js"; +function _layout($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + let { children } = $$props; + { + $$renderer2.push(""); + $$renderer2.push(`
Loading...
`); + } + $$renderer2.push(``); + }); +} +export { + _layout as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/_page.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/_page.svelte.js new file mode 100644 index 0000000..eb0b6a2 --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/_page.svelte.js @@ -0,0 +1,14 @@ +import "clsx"; +function _page($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + $$renderer2.push(`

Dashboard

`); + { + $$renderer2.push(""); + $$renderer2.push(`

Loading...

`); + } + $$renderer2.push(``); + }); +} +export { + _page as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/aliases/_page.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/aliases/_page.svelte.js new file mode 100644 index 0000000..fb71a6f --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/aliases/_page.svelte.js @@ -0,0 +1,15 @@ +import "clsx"; +import "@sveltejs/kit/internal"; +import "../../../chunks/exports.js"; +import "../../../chunks/utils.js"; +import "@sveltejs/kit/internal/server"; +import "../../../chunks/root.js"; +import "../../../chunks/state.svelte.js"; +function _page($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + $$renderer2.push(`

Redirecting to domains...

`); + }); +} +export { + _page as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/auth/change-password/_page.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/auth/change-password/_page.svelte.js new file mode 100644 index 0000000..d3de0ac --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/auth/change-password/_page.svelte.js @@ -0,0 +1,31 @@ +import { a as attr, e as escape_html } from "../../../../chunks/index2.js"; +import "@sveltejs/kit/internal"; +import "../../../../chunks/exports.js"; +import "../../../../chunks/utils.js"; +import "@sveltejs/kit/internal/server"; +import "../../../../chunks/root.js"; +import "../../../../chunks/state.svelte.js"; +function _page($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + let oldPassword = ""; + let newPassword = ""; + let confirmPassword = ""; + let loading = false; + $$renderer2.push(`

Change Password

`); + { + $$renderer2.push(""); + } + $$renderer2.push(` `); + { + $$renderer2.push(""); + } + $$renderer2.push(`
`); + }); +} +export { + _page as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/auth/dashboard/_page.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/auth/dashboard/_page.svelte.js new file mode 100644 index 0000000..422ded5 --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/auth/dashboard/_page.svelte.js @@ -0,0 +1,24 @@ +import "clsx"; +import "@sveltejs/kit/internal"; +import "../../../../chunks/exports.js"; +import "../../../../chunks/utils.js"; +import "@sveltejs/kit/internal/server"; +import "../../../../chunks/root.js"; +import "../../../../chunks/state.svelte.js"; +function _page($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + $$renderer2.push(`

User Dashboard

`); + { + $$renderer2.push(""); + $$renderer2.push(`

Loading...

`); + } + $$renderer2.push(`
`); + }); +} +export { + _page as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/auth/forgot/_page.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/auth/forgot/_page.svelte.js new file mode 100644 index 0000000..d9947d9 --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/auth/forgot/_page.svelte.js @@ -0,0 +1,24 @@ +import { a as attr, e as escape_html } from "../../../../chunks/index2.js"; +import "@sveltejs/kit/internal"; +import "../../../../chunks/exports.js"; +import "../../../../chunks/utils.js"; +import "@sveltejs/kit/internal/server"; +import "../../../../chunks/root.js"; +import "../../../../chunks/state.svelte.js"; +function _page($$renderer) { + let identifier = ""; + let loading = false; + $$renderer.push(``); +} +export { + _page as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/auth/login/_page.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/auth/login/_page.svelte.js new file mode 100644 index 0000000..f9e10ba --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/auth/login/_page.svelte.js @@ -0,0 +1,22 @@ +import { a as attr, e as escape_html } from "../../../../chunks/index2.js"; +import "@sveltejs/kit/internal"; +import "../../../../chunks/exports.js"; +import "../../../../chunks/utils.js"; +import "@sveltejs/kit/internal/server"; +import "../../../../chunks/root.js"; +import "../../../../chunks/state.svelte.js"; +function _page($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + let identifier = ""; + let password = ""; + let loading = false; + $$renderer2.push(``); + }); +} +export { + _page as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/domains/_name_/_page.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/domains/_name_/_page.svelte.js new file mode 100644 index 0000000..c5010fc --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/domains/_name_/_page.svelte.js @@ -0,0 +1,19 @@ +import "clsx"; +import "@sveltejs/kit/internal"; +import "../../../../chunks/exports.js"; +import "../../../../chunks/utils.js"; +import "@sveltejs/kit/internal/server"; +import "../../../../chunks/root.js"; +import "../../../../chunks/state.svelte.js"; +function _page($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + { + $$renderer2.push(""); + $$renderer2.push(`

Loading...

`); + } + $$renderer2.push(``); + }); +} +export { + _page as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/domains/_name_/aliases/_page.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/domains/_name_/aliases/_page.svelte.js new file mode 100644 index 0000000..4d0f8a1 --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/domains/_name_/aliases/_page.svelte.js @@ -0,0 +1,25 @@ +import { a as attr, e as escape_html, s as stringify } from "../../../../../chunks/index2.js"; +import "@sveltejs/kit/internal"; +import "../../../../../chunks/exports.js"; +import "../../../../../chunks/utils.js"; +import "@sveltejs/kit/internal/server"; +import "../../../../../chunks/root.js"; +import "../../../../../chunks/state.svelte.js"; +function _page($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + let domainName = ""; + $$renderer2.push(`
← Back to ${escape_html(domainName)}

Aliases

`); + { + $$renderer2.push(""); + $$renderer2.push(`

Loading...

`); + } + $$renderer2.push(` `); + { + $$renderer2.push(""); + } + $$renderer2.push(``); + }); +} +export { + _page as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/domains/_name_/users/_page.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/domains/_name_/users/_page.svelte.js new file mode 100644 index 0000000..88a7030 --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/domains/_name_/users/_page.svelte.js @@ -0,0 +1,25 @@ +import { a as attr, e as escape_html, s as stringify } from "../../../../../chunks/index2.js"; +import "@sveltejs/kit/internal"; +import "../../../../../chunks/exports.js"; +import "../../../../../chunks/utils.js"; +import "@sveltejs/kit/internal/server"; +import "../../../../../chunks/root.js"; +import "../../../../../chunks/state.svelte.js"; +function _page($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + let domainName = ""; + $$renderer2.push(`
← Back to ${escape_html(domainName)}

Users

`); + { + $$renderer2.push(""); + $$renderer2.push(`

Loading...

`); + } + $$renderer2.push(` `); + { + $$renderer2.push(""); + } + $$renderer2.push(``); + }); +} +export { + _page as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/domains/_page.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/domains/_page.svelte.js new file mode 100644 index 0000000..45abe47 --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/domains/_page.svelte.js @@ -0,0 +1,18 @@ +import "clsx"; +function _page($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + $$renderer2.push(`

Domains

`); + { + $$renderer2.push(""); + $$renderer2.push(`

Loading...

`); + } + $$renderer2.push(` `); + { + $$renderer2.push(""); + } + $$renderer2.push(``); + }); +} +export { + _page as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/logs/_page.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/logs/_page.svelte.js new file mode 100644 index 0000000..f3ac280 --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/logs/_page.svelte.js @@ -0,0 +1,78 @@ +import { a as attr, e as escape_html, b as ensure_array_like, c as attr_class, s as stringify } from "../../../chunks/index2.js"; +function _page($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + let logs = []; + let loading = true; + let error = ""; + let filter = ""; + let hours = 1; + async function loadLogs() { + loading = true; + error = ""; + try { + const res = await fetch(`/api/logs?hours=${hours}&filter=${encodeURIComponent(filter)}`); + if (res.ok) { + const data = await res.json(); + logs = data.data || []; + } else { + error = "Failed to load logs"; + } + } catch (e) { + error = "Connection error"; + console.error("Failed to load logs:", e); + } finally { + loading = false; + } + } + function getPriorityClass(priority) { + const p = priority.toLowerCase(); + if (p === "err" || p === "error") return "error"; + if (p === "warning" || p === "warn") return "warning"; + if (p === "info") return "info"; + return ""; + } + $$renderer2.push(`

Mail Logs

`); + if (loading) { + $$renderer2.push(""); + $$renderer2.push(`

Loading...

`); + } else if (error) { + $$renderer2.push(""); + $$renderer2.push(`

${escape_html(error)}

`); + } else if (logs.length === 0) { + $$renderer2.push(""); + $$renderer2.push(`

No log entries found.

`); + } else { + $$renderer2.push(""); + $$renderer2.push(`
`); + const each_array = ensure_array_like(logs); + for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) { + let entry = each_array[$$index]; + $$renderer2.push(`${escape_html(entry.timestamp)} [${escape_html(entry.priority)}] ${escape_html(entry.message)}
`); + } + $$renderer2.push(``); + } + $$renderer2.push(``); + }); +} +export { + _page as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/queue/_page.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/queue/_page.svelte.js new file mode 100644 index 0000000..3cb5f5f --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/queue/_page.svelte.js @@ -0,0 +1,14 @@ +import "clsx"; +function _page($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + $$renderer2.push(`

Mail Queue

`); + { + $$renderer2.push(""); + $$renderer2.push(`

Loading...

`); + } + $$renderer2.push(``); + }); +} +export { + _page as default +}; diff --git a/frontend/.svelte-kit/output/server/entries/pages/users/_page.svelte.js b/frontend/.svelte-kit/output/server/entries/pages/users/_page.svelte.js new file mode 100644 index 0000000..fb71a6f --- /dev/null +++ b/frontend/.svelte-kit/output/server/entries/pages/users/_page.svelte.js @@ -0,0 +1,15 @@ +import "clsx"; +import "@sveltejs/kit/internal"; +import "../../../chunks/exports.js"; +import "../../../chunks/utils.js"; +import "@sveltejs/kit/internal/server"; +import "../../../chunks/root.js"; +import "../../../chunks/state.svelte.js"; +function _page($$renderer, $$props) { + $$renderer.component(($$renderer2) => { + $$renderer2.push(`

Redirecting to domains...

`); + }); +} +export { + _page as default +}; diff --git a/frontend/.svelte-kit/output/server/index.js b/frontend/.svelte-kit/output/server/index.js new file mode 100644 index 0000000..36ef982 --- /dev/null +++ b/frontend/.svelte-kit/output/server/index.js @@ -0,0 +1,3821 @@ +import { B as BROWSER } from "./chunks/false.js"; +import { json, text, error } from "@sveltejs/kit"; +import { Redirect, SvelteKitError, ActionFailure, HttpError } from "@sveltejs/kit/internal"; +import { with_request_store, merge_tracing, try_get_request_store } from "@sveltejs/kit/internal/server"; +import { a as assets, b as base, c as app_dir, r as relative, o as override, d as reset } from "./chunks/environment.js"; +import { E as ENDPOINT_METHODS, P as PAGE_METHODS, n as negotiate, m as method_not_allowed, h as handle_error_and_jsonify, g as get_status, i as is_form_content_type, a as normalize_error, b as get_global_name, s as serialize_uses, c as clarify_devalue_error, d as get_node_type, e as escape_html, S as SVELTE_KIT_ASSETS, f as create_remote_key, j as static_error_page, r as redirect_response, p as parse_remote_arg, k as stringify, l as deserialize_binary_form, o as has_prerendered_path, T as TRAILING_SLASH_PARAM, I as INVALIDATED_PARAM, q as handle_fatal_error, M as MUTATIVE_METHODS, t as format_server_error } from "./chunks/shared.js"; +import * as devalue from "devalue"; +import { m as make_trackable, d as disable_search, a as decode_params, S as SCHEME, v as validate_layout_server_exports, b as validate_layout_exports, c as validate_page_server_exports, e as validate_page_exports, n as normalize_path, r as resolve, f as decode_pathname, g as validate_server_exports } from "./chunks/exports.js"; +import { b as base64_encode, t as text_decoder, a as text_encoder, g as get_relative_path } from "./chunks/utils.js"; +import { w as writable, r as readable } from "./chunks/index.js"; +import { p as public_env, r as read_implementation, o as options, s as set_private_env, a as set_public_env, g as get_hooks, b as set_read_implementation } from "./chunks/internal.js"; +import { parse, serialize } from "cookie"; +import * as set_cookie_parser from "set-cookie-parser"; +function with_resolvers() { + let resolve2; + let reject; + const promise = new Promise((res, rej) => { + resolve2 = res; + reject = rej; + }); + return { promise, resolve: resolve2, reject }; +} +const NULL_BODY_STATUS = [101, 103, 204, 205, 304]; +const IN_WEBCONTAINER = !!globalThis.process?.versions?.webcontainer; +async function render_endpoint(event, event_state, mod, state) { + const method = ( + /** @type {import('types').HttpMethod} */ + event.request.method + ); + let handler = mod[method] || mod.fallback; + if (method === "HEAD" && !mod.HEAD && mod.GET) { + handler = mod.GET; + } + if (!handler) { + return method_not_allowed(mod, method); + } + const prerender = mod.prerender ?? state.prerender_default; + if (prerender && (mod.POST || mod.PATCH || mod.PUT || mod.DELETE)) { + throw new Error("Cannot prerender endpoints that have mutative methods"); + } + if (state.prerendering && !state.prerendering.inside_reroute && !prerender) { + if (state.depth > 0) { + throw new Error(`${event.route.id} is not prerenderable`); + } else { + return new Response(void 0, { status: 204 }); + } + } + try { + event_state.allows_commands = true; + const response = await with_request_store( + { event, state: event_state }, + () => handler( + /** @type {import('@sveltejs/kit').RequestEvent>} */ + event + ) + ); + if (!(response instanceof Response)) { + throw new Error( + `Invalid response from route ${event.url.pathname}: handler should return a Response object` + ); + } + if (state.prerendering && (!state.prerendering.inside_reroute || prerender)) { + const cloned = new Response(response.clone().body, { + status: response.status, + statusText: response.statusText, + headers: new Headers(response.headers) + }); + cloned.headers.set("x-sveltekit-prerender", String(prerender)); + if (state.prerendering.inside_reroute && prerender) { + cloned.headers.set( + "x-sveltekit-routeid", + encodeURI( + /** @type {string} */ + event.route.id + ) + ); + state.prerendering.dependencies.set(event.url.pathname, { response: cloned, body: null }); + } else { + return cloned; + } + } + return response; + } catch (e) { + if (e instanceof Redirect) { + return new Response(void 0, { + status: e.status, + headers: { location: e.location } + }); + } + throw e; + } +} +function is_endpoint_request(event) { + const { method, headers: headers2 } = event.request; + if (ENDPOINT_METHODS.includes(method) && !PAGE_METHODS.includes(method)) { + return true; + } + if (method === "POST" && headers2.get("x-sveltekit-action") === "true") return false; + const accept = event.request.headers.get("accept") ?? "*/*"; + return negotiate(accept, ["*", "text/html"]) !== "text/html"; +} +function compact(arr) { + return arr.filter( + /** @returns {val is NonNullable} */ + (val) => val != null + ); +} +const DATA_SUFFIX = "/__data.json"; +const HTML_DATA_SUFFIX = ".html__data.json"; +function has_data_suffix(pathname) { + return pathname.endsWith(DATA_SUFFIX) || pathname.endsWith(HTML_DATA_SUFFIX); +} +function add_data_suffix(pathname) { + if (pathname.endsWith(".html")) return pathname.replace(/\.html$/, HTML_DATA_SUFFIX); + return pathname.replace(/\/$/, "") + DATA_SUFFIX; +} +function strip_data_suffix(pathname) { + if (pathname.endsWith(HTML_DATA_SUFFIX)) { + return pathname.slice(0, -HTML_DATA_SUFFIX.length) + ".html"; + } + return pathname.slice(0, -DATA_SUFFIX.length); +} +const ROUTE_SUFFIX = "/__route.js"; +function has_resolution_suffix(pathname) { + return pathname.endsWith(ROUTE_SUFFIX); +} +function add_resolution_suffix(pathname) { + return pathname.replace(/\/$/, "") + ROUTE_SUFFIX; +} +function strip_resolution_suffix(pathname) { + return pathname.slice(0, -ROUTE_SUFFIX.length); +} +const noop_span = { + spanContext() { + return noop_span_context; + }, + setAttribute() { + return this; + }, + setAttributes() { + return this; + }, + addEvent() { + return this; + }, + setStatus() { + return this; + }, + updateName() { + return this; + }, + end() { + return this; + }, + isRecording() { + return false; + }, + recordException() { + return this; + }, + addLink() { + return this; + }, + addLinks() { + return this; + } +}; +const noop_span_context = { + traceId: "", + spanId: "", + traceFlags: 0 +}; +async function record_span({ name, attributes, fn }) { + { + return fn(noop_span); + } +} +function is_action_json_request(event) { + const accept = negotiate(event.request.headers.get("accept") ?? "*/*", [ + "application/json", + "text/html" + ]); + return accept === "application/json" && event.request.method === "POST"; +} +async function handle_action_json_request(event, event_state, options2, server) { + const actions = server?.actions; + if (!actions) { + const no_actions_error = new SvelteKitError( + 405, + "Method Not Allowed", + `POST method not allowed. No form actions exist for ${"this page"}` + ); + return action_json( + { + type: "error", + error: await handle_error_and_jsonify(event, event_state, options2, no_actions_error) + }, + { + status: no_actions_error.status, + headers: { + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405 + // "The server must generate an Allow header field in a 405 status code response" + allow: "GET" + } + } + ); + } + check_named_default_separate(actions); + try { + const data = await call_action(event, event_state, actions); + if (BROWSER) ; + if (data instanceof ActionFailure) { + return action_json({ + type: "failure", + status: data.status, + // @ts-expect-error we assign a string to what is supposed to be an object. That's ok + // because we don't use the object outside, and this way we have better code navigation + // through knowing where the related interface is used. + data: stringify_action_response( + data.data, + /** @type {string} */ + event.route.id, + options2.hooks.transport + ) + }); + } else { + return action_json({ + type: "success", + status: data ? 200 : 204, + // @ts-expect-error see comment above + data: stringify_action_response( + data, + /** @type {string} */ + event.route.id, + options2.hooks.transport + ) + }); + } + } catch (e) { + const err = normalize_error(e); + if (err instanceof Redirect) { + return action_json_redirect(err); + } + return action_json( + { + type: "error", + error: await handle_error_and_jsonify( + event, + event_state, + options2, + check_incorrect_fail_use(err) + ) + }, + { + status: get_status(err) + } + ); + } +} +function check_incorrect_fail_use(error2) { + return error2 instanceof ActionFailure ? new Error('Cannot "throw fail()". Use "return fail()"') : error2; +} +function action_json_redirect(redirect) { + return action_json({ + type: "redirect", + status: redirect.status, + location: redirect.location + }); +} +function action_json(data, init2) { + return json(data, init2); +} +function is_action_request(event) { + return event.request.method === "POST"; +} +async function handle_action_request(event, event_state, server) { + const actions = server?.actions; + if (!actions) { + event.setHeaders({ + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405 + // "The server must generate an Allow header field in a 405 status code response" + allow: "GET" + }); + return { + type: "error", + error: new SvelteKitError( + 405, + "Method Not Allowed", + `POST method not allowed. No form actions exist for ${"this page"}` + ) + }; + } + check_named_default_separate(actions); + try { + const data = await call_action(event, event_state, actions); + if (BROWSER) ; + if (data instanceof ActionFailure) { + return { + type: "failure", + status: data.status, + data: data.data + }; + } else { + return { + type: "success", + status: 200, + // @ts-expect-error this will be removed upon serialization, so `undefined` is the same as omission + data + }; + } + } catch (e) { + const err = normalize_error(e); + if (err instanceof Redirect) { + return { + type: "redirect", + status: err.status, + location: err.location + }; + } + return { + type: "error", + error: check_incorrect_fail_use(err) + }; + } +} +function check_named_default_separate(actions) { + if (actions.default && Object.keys(actions).length > 1) { + throw new Error( + "When using named actions, the default action cannot be used. See the docs for more info: https://svelte.dev/docs/kit/form-actions#named-actions" + ); + } +} +async function call_action(event, event_state, actions) { + const url = new URL(event.request.url); + let name = "default"; + for (const param of url.searchParams) { + if (param[0].startsWith("/")) { + name = param[0].slice(1); + if (name === "default") { + throw new Error('Cannot use reserved action name "default"'); + } + break; + } + } + const action = actions[name]; + if (!action) { + throw new SvelteKitError(404, "Not Found", `No action with name '${name}' found`); + } + if (!is_form_content_type(event.request)) { + throw new SvelteKitError( + 415, + "Unsupported Media Type", + `Form actions expect form-encoded data — received ${event.request.headers.get( + "content-type" + )}` + ); + } + return record_span({ + name: "sveltekit.form_action", + attributes: { + "http.route": event.route.id || "unknown" + }, + fn: async (current2) => { + const traced_event = merge_tracing(event, current2); + event_state.allows_commands = true; + const result = await with_request_store( + { event: traced_event, state: event_state }, + () => action(traced_event) + ); + if (result instanceof ActionFailure) { + current2.setAttributes({ + "sveltekit.form_action.result.type": "failure", + "sveltekit.form_action.result.status": result.status + }); + } + return result; + } + }); +} +function validate_action_return(data) { + if (data instanceof Redirect) { + throw new Error("Cannot `return redirect(...)` — use `redirect(...)` instead"); + } + if (data instanceof HttpError) { + throw new Error("Cannot `return error(...)` — use `error(...)` or `return fail(...)` instead"); + } +} +function uneval_action_response(data, route_id, transport) { + const replacer = (thing) => { + for (const key2 in transport) { + const encoded = transport[key2].encode(thing); + if (encoded) { + return `app.decode('${key2}', ${devalue.uneval(encoded, replacer)})`; + } + } + }; + return try_serialize(data, (value) => devalue.uneval(value, replacer), route_id); +} +function stringify_action_response(data, route_id, transport) { + const encoders = Object.fromEntries( + Object.entries(transport).map(([key2, value]) => [key2, value.encode]) + ); + return try_serialize(data, (value) => devalue.stringify(value, encoders), route_id); +} +function try_serialize(data, fn, route_id) { + try { + return fn(data); + } catch (e) { + const error2 = ( + /** @type {any} */ + e + ); + if (data instanceof Response) { + throw new Error( + `Data returned from action inside ${route_id} is not serializable. Form actions need to return plain objects or fail(). E.g. return { success: true } or return fail(400, { message: "invalid" });`, + { cause: e } + ); + } + if ("path" in error2) { + let message = `Data returned from action inside ${route_id} is not serializable: ${error2.message}`; + if (error2.path !== "") message += ` (data.${error2.path})`; + throw new Error(message, { cause: e }); + } + throw error2; + } +} +function create_async_iterator() { + let resolved = -1; + let returned = -1; + const deferred = []; + return { + iterate: (transform = (x) => x) => { + return { + [Symbol.asyncIterator]() { + return { + next: async () => { + const next = deferred[++returned]; + if (!next) return { value: null, done: true }; + const value = await next.promise; + return { value: transform(value), done: false }; + } + }; + } + }; + }, + add: (promise) => { + deferred.push(with_resolvers()); + void promise.then((value) => { + deferred[++resolved].resolve(value); + }); + } + }; +} +function server_data_serializer(event, event_state, options2) { + let promise_id = 1; + let max_nodes = -1; + const iterator = create_async_iterator(); + const global = get_global_name(options2); + function get_replacer(index) { + return function replacer(thing) { + if (typeof thing?.then === "function") { + const id = promise_id++; + const promise = thing.then( + /** @param {any} data */ + (data) => ({ data }) + ).catch( + /** @param {any} error */ + async (error2) => ({ + error: await handle_error_and_jsonify(event, event_state, options2, error2) + }) + ).then( + /** + * @param {{data: any; error: any}} result + */ + async ({ data, error: error2 }) => { + let str; + try { + str = devalue.uneval(error2 ? [, error2] : [data], replacer); + } catch { + error2 = await handle_error_and_jsonify( + event, + event_state, + options2, + new Error(`Failed to serialize promise while rendering ${event.route.id}`) + ); + str = devalue.uneval([, error2], replacer); + } + return { + index, + str: `${global}.resolve(${id}, ${str.includes("app.decode") ? `(app) => ${str}` : `() => ${str}`})` + }; + } + ); + iterator.add(promise); + return `${global}.defer(${id})`; + } else { + for (const key2 in options2.hooks.transport) { + const encoded = options2.hooks.transport[key2].encode(thing); + if (encoded) { + return `app.decode('${key2}', ${devalue.uneval(encoded, replacer)})`; + } + } + } + }; + } + const strings = ( + /** @type {string[]} */ + [] + ); + return { + set_max_nodes(i) { + max_nodes = i; + }, + add_node(i, node) { + try { + if (!node) { + strings[i] = "null"; + return; + } + const payload = { type: "data", data: node.data, uses: serialize_uses(node) }; + if (node.slash) payload.slash = node.slash; + strings[i] = devalue.uneval(payload, get_replacer(i)); + } catch (e) { + e.path = e.path.slice(1); + throw new Error(clarify_devalue_error( + event, + /** @type {any} */ + e + ), { cause: e }); + } + }, + get_data(csp) { + const open = ``; + const close = `<\/script> +`; + return { + data: `[${compact(max_nodes > -1 ? strings.slice(0, max_nodes) : strings).join(",")}]`, + chunks: promise_id > 1 ? iterator.iterate(({ index, str }) => { + if (max_nodes > -1 && index >= max_nodes) { + return ""; + } + return open + str + close; + }) : null + }; + } + }; +} +function server_data_serializer_json(event, event_state, options2) { + let promise_id = 1; + const iterator = create_async_iterator(); + const reducers = { + ...Object.fromEntries( + Object.entries(options2.hooks.transport).map(([key2, value]) => [key2, value.encode]) + ), + /** @param {any} thing */ + Promise: (thing) => { + if (typeof thing?.then !== "function") { + return; + } + const id = promise_id++; + let key2 = "data"; + const promise = thing.catch( + /** @param {any} e */ + async (e) => { + key2 = "error"; + return handle_error_and_jsonify( + event, + event_state, + options2, + /** @type {any} */ + e + ); + } + ).then( + /** @param {any} value */ + async (value) => { + let str; + try { + str = devalue.stringify(value, reducers); + } catch { + const error2 = await handle_error_and_jsonify( + event, + event_state, + options2, + new Error(`Failed to serialize promise while rendering ${event.route.id}`) + ); + key2 = "error"; + str = devalue.stringify(error2, reducers); + } + return `{"type":"chunk","id":${id},"${key2}":${str}} +`; + } + ); + iterator.add(promise); + return id; + } + }; + const strings = ( + /** @type {string[]} */ + [] + ); + return { + add_node(i, node) { + try { + if (!node) { + strings[i] = "null"; + return; + } + if (node.type === "error" || node.type === "skip") { + strings[i] = JSON.stringify(node); + return; + } + strings[i] = `{"type":"data","data":${devalue.stringify(node.data, reducers)},"uses":${JSON.stringify( + serialize_uses(node) + )}${node.slash ? `,"slash":${JSON.stringify(node.slash)}` : ""}}`; + } catch (e) { + e.path = "data" + e.path; + throw new Error(clarify_devalue_error( + event, + /** @type {any} */ + e + ), { cause: e }); + } + }, + get_data() { + return { + data: `{"type":"data","nodes":[${strings.join(",")}]} +`, + chunks: promise_id > 1 ? iterator.iterate() : null + }; + } + }; +} +async function load_server_data({ event, event_state, state, node, parent }) { + if (!node?.server) return null; + let is_tracking = true; + const uses = { + dependencies: /* @__PURE__ */ new Set(), + params: /* @__PURE__ */ new Set(), + parent: false, + route: false, + url: false, + search_params: /* @__PURE__ */ new Set() + }; + const load = node.server.load; + const slash = node.server.trailingSlash; + if (!load) { + return { type: "data", data: null, uses, slash }; + } + const url = make_trackable( + event.url, + () => { + if (is_tracking) { + uses.url = true; + } + }, + (param) => { + if (is_tracking) { + uses.search_params.add(param); + } + } + ); + if (state.prerendering) { + disable_search(url); + } + const result = await record_span({ + name: "sveltekit.load", + attributes: { + "sveltekit.load.node_id": node.server_id || "unknown", + "sveltekit.load.node_type": get_node_type(node.server_id), + "http.route": event.route.id || "unknown" + }, + fn: async (current2) => { + const traced_event = merge_tracing(event, current2); + const result2 = await with_request_store( + { event: traced_event, state: event_state }, + () => load.call(null, { + ...traced_event, + fetch: (info, init2) => { + new URL(info instanceof Request ? info.url : info, event.url); + return event.fetch(info, init2); + }, + /** @param {string[]} deps */ + depends: (...deps) => { + for (const dep of deps) { + const { href } = new URL(dep, event.url); + uses.dependencies.add(href); + } + }, + params: new Proxy(event.params, { + get: (target, key2) => { + if (is_tracking) { + uses.params.add(key2); + } + return target[ + /** @type {string} */ + key2 + ]; + } + }), + parent: async () => { + if (is_tracking) { + uses.parent = true; + } + return parent(); + }, + route: new Proxy(event.route, { + get: (target, key2) => { + if (is_tracking) { + uses.route = true; + } + return target[ + /** @type {'id'} */ + key2 + ]; + } + }), + url, + untrack(fn) { + is_tracking = false; + try { + return fn(); + } finally { + is_tracking = true; + } + } + }) + ); + return result2; + } + }); + return { + type: "data", + data: result ?? null, + uses, + slash + }; +} +async function load_data({ + event, + event_state, + fetched, + node, + parent, + server_data_promise, + state, + resolve_opts, + csr +}) { + const server_data_node = await server_data_promise; + const load = node?.universal?.load; + if (!load) { + return server_data_node?.data ?? null; + } + const result = await record_span({ + name: "sveltekit.load", + attributes: { + "sveltekit.load.node_id": node.universal_id || "unknown", + "sveltekit.load.node_type": get_node_type(node.universal_id), + "http.route": event.route.id || "unknown" + }, + fn: async (current2) => { + const traced_event = merge_tracing(event, current2); + return await with_request_store( + { event: traced_event, state: event_state }, + () => load.call(null, { + url: event.url, + params: event.params, + data: server_data_node?.data ?? null, + route: event.route, + fetch: create_universal_fetch(event, state, fetched, csr, resolve_opts), + setHeaders: event.setHeaders, + depends: () => { + }, + parent, + untrack: (fn) => fn(), + tracing: traced_event.tracing + }) + ); + } + }); + return result ?? null; +} +function create_universal_fetch(event, state, fetched, csr, resolve_opts) { + const universal_fetch = async (input, init2) => { + const cloned_body = input instanceof Request && input.body ? input.clone().body : null; + const cloned_headers = input instanceof Request && [...input.headers].length ? new Headers(input.headers) : init2?.headers; + let response = await event.fetch(input, init2); + const url = new URL(input instanceof Request ? input.url : input, event.url); + const same_origin = url.origin === event.url.origin; + let dependency; + if (same_origin) { + if (state.prerendering) { + dependency = { response, body: null }; + state.prerendering.dependencies.set(url.pathname, dependency); + } + } else if (url.protocol === "https:" || url.protocol === "http:") { + const mode = input instanceof Request ? input.mode : init2?.mode ?? "cors"; + if (mode === "no-cors") { + response = new Response("", { + status: response.status, + statusText: response.statusText, + headers: response.headers + }); + } else { + const acao = response.headers.get("access-control-allow-origin"); + if (!acao || acao !== event.url.origin && acao !== "*") { + throw new Error( + `CORS error: ${acao ? "Incorrect" : "No"} 'Access-Control-Allow-Origin' header is present on the requested resource` + ); + } + } + } + let teed_body; + const proxy = new Proxy(response, { + get(response2, key2, receiver) { + async function push_fetched(body2, is_b64) { + const status_number = Number(response2.status); + if (isNaN(status_number)) { + throw new Error( + `response.status is not a number. value: "${response2.status}" type: ${typeof response2.status}` + ); + } + fetched.push({ + url: same_origin ? url.href.slice(event.url.origin.length) : url.href, + method: event.request.method, + request_body: ( + /** @type {string | ArrayBufferView | undefined} */ + input instanceof Request && cloned_body ? await stream_to_string(cloned_body) : init2?.body + ), + request_headers: cloned_headers, + response_body: body2, + response: response2, + is_b64 + }); + } + if (key2 === "body") { + if (response2.body === null) { + return null; + } + if (teed_body) { + return teed_body; + } + const [a, b] = response2.body.tee(); + void (async () => { + let result = new Uint8Array(); + for await (const chunk of a) { + const combined = new Uint8Array(result.length + chunk.length); + combined.set(result, 0); + combined.set(chunk, result.length); + result = combined; + } + if (dependency) { + dependency.body = new Uint8Array(result); + } + void push_fetched(base64_encode(result), true); + })(); + return teed_body = b; + } + if (key2 === "arrayBuffer") { + return async () => { + const buffer = await response2.arrayBuffer(); + const bytes = new Uint8Array(buffer); + if (dependency) { + dependency.body = bytes; + } + if (buffer instanceof ArrayBuffer) { + await push_fetched(base64_encode(bytes), true); + } + return buffer; + }; + } + async function text2() { + const body2 = await response2.text(); + if (body2 === "" && NULL_BODY_STATUS.includes(response2.status)) { + await push_fetched(void 0, false); + return void 0; + } + if (!body2 || typeof body2 === "string") { + await push_fetched(body2, false); + } + if (dependency) { + dependency.body = body2; + } + return body2; + } + if (key2 === "text") { + return text2; + } + if (key2 === "json") { + return async () => { + const body2 = await text2(); + return body2 ? JSON.parse(body2) : void 0; + }; + } + const value = Reflect.get(response2, key2, response2); + if (value instanceof Function) { + return Object.defineProperties( + /** + * @this {any} + */ + function() { + return Reflect.apply(value, this === receiver ? response2 : this, arguments); + }, + { + name: { value: value.name }, + length: { value: value.length } + } + ); + } + return value; + } + }); + if (csr) { + const get = response.headers.get; + response.headers.get = (key2) => { + const lower = key2.toLowerCase(); + const value = get.call(response.headers, lower); + if (value && !lower.startsWith("x-sveltekit-")) { + const included = resolve_opts.filterSerializedResponseHeaders(lower, value); + if (!included) { + throw new Error( + `Failed to get response header "${lower}" — it must be included by the \`filterSerializedResponseHeaders\` option: https://svelte.dev/docs/kit/hooks#Server-hooks-handle (at ${event.route.id})` + ); + } + } + return value; + }; + } + return proxy; + }; + return (input, init2) => { + const response = universal_fetch(input, init2); + response.catch(() => { + }); + return response; + }; +} +async function stream_to_string(stream) { + let result = ""; + const reader = stream.getReader(); + while (true) { + const { done, value } = await reader.read(); + if (done) { + break; + } + result += text_decoder.decode(value); + } + return result; +} +function hash(...values) { + let hash2 = 5381; + for (const value of values) { + if (typeof value === "string") { + let i = value.length; + while (i) hash2 = hash2 * 33 ^ value.charCodeAt(--i); + } else if (ArrayBuffer.isView(value)) { + const buffer = new Uint8Array(value.buffer, value.byteOffset, value.byteLength); + let i = buffer.length; + while (i) hash2 = hash2 * 33 ^ buffer[--i]; + } else { + throw new TypeError("value must be a string or TypedArray"); + } + } + return (hash2 >>> 0).toString(36); +} +const replacements = { + "<": "\\u003C", + "\u2028": "\\u2028", + "\u2029": "\\u2029" +}; +const pattern = new RegExp(`[${Object.keys(replacements).join("")}]`, "g"); +function serialize_data(fetched, filter, prerendering = false) { + const headers2 = {}; + let cache_control = null; + let age = null; + let varyAny = false; + for (const [key2, value] of fetched.response.headers) { + if (filter(key2, value)) { + headers2[key2] = value; + } + if (key2 === "cache-control") cache_control = value; + else if (key2 === "age") age = value; + else if (key2 === "vary" && value.trim() === "*") varyAny = true; + } + const payload = { + status: fetched.response.status, + statusText: fetched.response.statusText, + headers: headers2, + body: fetched.response_body + }; + const safe_payload = JSON.stringify(payload).replace(pattern, (match) => replacements[match]); + const attrs = [ + 'type="application/json"', + "data-sveltekit-fetched", + `data-url="${escape_html(fetched.url, true)}"` + ]; + if (fetched.is_b64) { + attrs.push("data-b64"); + } + if (fetched.request_headers || fetched.request_body) { + const values = []; + if (fetched.request_headers) { + values.push([...new Headers(fetched.request_headers)].join(",")); + } + if (fetched.request_body) { + values.push(fetched.request_body); + } + attrs.push(`data-hash="${hash(...values)}"`); + } + if (!prerendering && fetched.method === "GET" && cache_control && !varyAny) { + const match = /s-maxage=(\d+)/g.exec(cache_control) ?? /max-age=(\d+)/g.exec(cache_control); + if (match) { + const ttl = +match[1] - +(age ?? "0"); + attrs.push(`data-ttl="${ttl}"`); + } + } + return `` + ); + + written.add(file); + + if (!prerendered.redirects.has(decoded)) { + prerendered.redirects.set(decoded, { + status: response.status, + location: resolved + }); + + prerendered.paths.push(decoded); + } + } + } else { + log.warn(`location header missing on redirect received from ${decoded}`); + } + + return; + } + + if (response.status === 200) { + if (existsSync(dest) && statSync(dest).isDirectory()) { + throw new Error( + `Cannot save ${decoded} as it is already a directory. See https://svelte.dev/docs/kit/page-options#prerender-route-conflicts for more information` + ); + } + + const dir = dirname(dest); + + if (existsSync(dir) && !statSync(dir).isDirectory()) { + const parent = decoded.split('/').slice(0, -1).join('/'); + throw new Error( + `Cannot save ${decoded} as ${parent} is already a file. See https://svelte.dev/docs/kit/page-options#prerender-route-conflicts for more information` + ); + } + + mkdirp(dir); + + log.info(`${response.status} ${decoded}`); + writeFileSync(dest, body); + written.add(file); + + if (is_html) { + prerendered.pages.set(decoded, { + file + }); + } else { + prerendered.assets.set(decoded, { + type + }); + } + + prerendered.paths.push(decoded); + } else if (response_type !== OK) { + handle_http_error({ status: response.status, path: decoded, referrer, referenceType }); + } + + manifest.assets.add(file); + saved.set(file, dest); + } + + /** @type {Array<{ id: string, entries: Array}>} */ + const route_level_entries = []; + for (const [id, { entries }] of metadata.routes.entries()) { + if (entries) { + route_level_entries.push({ id, entries }); + } + } + + let should_prerender = false; + + for (const value of prerender_map.values()) { + if (value) { + should_prerender = true; + break; + } + } + + // the user's remote function modules may reference environment variables, + // `read` or the `manifest` at the top-level so we need to set them before + // evaluating those modules to avoid potential runtime errors + const { publicPrefix: public_prefix, privatePrefix: private_prefix } = config.env; + const private_env = filter_env(env, private_prefix, public_prefix); + const public_env = filter_env(env, public_prefix, private_prefix); + internal.set_private_env(private_env); + internal.set_public_env(public_env); + internal.set_manifest(manifest); + internal.set_read_implementation((file) => createReadableStream(`${out}/server/${file}`)); + + /** @type {Array} */ + const prerender_functions = []; + + for (const loader of Object.values(manifest._.remotes)) { + const module = await loader(); + + for (const fn of Object.values(module.default)) { + if (fn?.__?.type === 'prerender') { + prerender_functions.push(fn.__); + should_prerender = true; + } + } + } + + if (!should_prerender) { + return { prerendered, prerender_map }; + } + + // only run the server after the `should_prerender` check so that we + // don't run the user's init hook unnecessarily + const server = new Server(manifest); + await server.init({ + env, + read: (file) => createReadableStream(`${config.outDir}/output/server/${file}`) + }); + + log.info('Prerendering'); + + for (const entry of config.prerender.entries) { + if (entry === '*') { + for (const [id, prerender] of prerender_map) { + if (prerender) { + // remove optional parameters from the route + const segments = get_route_segments(id).filter((segment) => !segment.startsWith('[[')); + const processed_id = '/' + segments.join('/'); + + if (processed_id.includes('[')) continue; + const path = `/${get_route_segments(processed_id).join('/')}`; + void enqueue(null, config.paths.base + path); + } + } + } else { + void enqueue(null, config.paths.base + entry); + } + } + + for (const { id, entries } of route_level_entries) { + for (const entry of entries) { + void enqueue(null, config.paths.base + entry, undefined, id); + } + } + + const transport = (await internal.get_hooks()).transport ?? {}; + for (const info of prerender_functions) { + if (info.has_arg) { + for (const arg of (await info.inputs?.()) ?? []) { + void enqueue(null, remote_prefix + info.id + '/' + stringify_remote_arg(arg, transport)); + } + } else { + void enqueue(null, remote_prefix + info.id); + } + } + + await q.done(); + + // handle invalid fragment links + for (const [key, referrers] of expected_hashlinks) { + const index = key.indexOf('#'); + const path = key.slice(0, index); + const id = key.slice(index + 1); + + const hashlinks = actual_hashlinks.get(path); + // ignore fragment links to pages that were not prerendered + if (!hashlinks) continue; + + if (!hashlinks.includes(id) && !SPECIAL_HASHLINKS.has(id)) { + handle_missing_id({ id, path, referrers: Array.from(referrers) }); + } + } + + /** @type {string[]} */ + const not_prerendered = []; + + for (const [route_id, prerender] of prerender_map) { + if (prerender === true && !prerendered_routes.has(route_id)) { + not_prerendered.push(route_id); + } + } + + if (not_prerendered.length > 0) { + handle_not_prerendered_route({ routes: not_prerendered }); + } + + return { prerendered, prerender_map }; +} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/postbuild/queue.js b/frontend/node_modules/@sveltejs/kit/src/core/postbuild/queue.js new file mode 100644 index 0000000..a816e6e --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/postbuild/queue.js @@ -0,0 +1,72 @@ +/** @import { PromiseWithResolvers } from '../../utils/promise.js' */ +import { with_resolvers } from '../../utils/promise.js'; + +/** + * @typedef {{ + * fn: () => Promise, + * fulfil: (value: any) => void, + * reject: (error: Error) => void + * }} Task + */ + +/** @param {number} concurrency */ +export function queue(concurrency) { + /** @type {Task[]} */ + const tasks = []; + const { promise, resolve, reject } = /** @type {PromiseWithResolvers} */ (with_resolvers()); + + let current = 0; + let closed = false; + + promise.catch(() => { + // this is necessary in case a catch handler is never added + // to the done promise by the user + }); + + function dequeue() { + if (current < concurrency) { + const task = tasks.shift(); + + if (task) { + current += 1; + const promise = Promise.resolve(task.fn()); + + void promise + .then(task.fulfil, (err) => { + task.reject(err); + reject(err); + }) + .then(() => { + current -= 1; + dequeue(); + }); + } else if (current === 0) { + closed = true; + resolve(); + } + } + } + + return { + /** @param {() => any} fn */ + add: (fn) => { + if (closed) throw new Error('Cannot add tasks to a queue that has ended'); + + const promise = new Promise((fulfil, reject) => { + tasks.push({ fn, fulfil, reject }); + }); + + dequeue(); + return promise; + }, + + done: () => { + if (current === 0) { + closed = true; + resolve(); + } + + return promise; + } + }; +} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/conflict.js b/frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/conflict.js new file mode 100644 index 0000000..e69de29 diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/index.js b/frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/index.js new file mode 100644 index 0000000..5facdc7 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/index.js @@ -0,0 +1,613 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; +import colors from 'kleur'; +import { lookup } from 'mrmime'; +import { list_files, runtime_directory } from '../../utils.js'; +import { posixify, resolve_entry } from '../../../utils/filesystem.js'; +import { parse_route_id } from '../../../utils/routing.js'; +import { sort_routes } from './sort.js'; +import { isSvelte5Plus } from '../utils.js'; +import { + create_node_analyser, + get_page_options +} from '../../../exports/vite/static_analysis/index.js'; + +/** + * Generates the manifest data used for the client-side manifest and types generation. + * @param {{ + * config: import('types').ValidatedConfig; + * fallback?: string; + * cwd?: string; + * }} opts + * @returns {import('types').ManifestData} + */ +export default function create_manifest_data({ + config, + fallback = `${runtime_directory}/components/${isSvelte5Plus() ? 'svelte-5' : 'svelte-4'}`, + cwd = process.cwd() +}) { + const assets = create_assets(config); + const hooks = create_hooks(config, cwd); + const matchers = create_matchers(config, cwd); + const { nodes, routes } = create_routes_and_nodes(cwd, config, fallback); + + for (const route of routes) { + for (const param of route.params) { + if (param.matcher && !matchers[param.matcher]) { + throw new Error(`No matcher found for parameter '${param.matcher}' in route ${route.id}`); + } + } + } + + return { + assets, + hooks, + matchers, + nodes, + routes + }; +} + +/** + * @param {import('types').ValidatedConfig} config + */ +export function create_assets(config) { + return list_files(config.kit.files.assets).map((file) => ({ + file, + size: fs.statSync(path.resolve(config.kit.files.assets, file)).size, + type: lookup(file) || null + })); +} + +/** + * @param {import('types').ValidatedConfig} config + * @param {string} cwd + */ +function create_hooks(config, cwd) { + const client = resolve_entry(config.kit.files.hooks.client); + const server = resolve_entry(config.kit.files.hooks.server); + const universal = resolve_entry(config.kit.files.hooks.universal); + + return { + client: client && posixify(path.relative(cwd, client)), + server: server && posixify(path.relative(cwd, server)), + universal: universal && posixify(path.relative(cwd, universal)) + }; +} + +/** + * @param {import('types').ValidatedConfig} config + * @param {string} cwd + */ +function create_matchers(config, cwd) { + const params_base = path.relative(cwd, config.kit.files.params); + + /** @type {Record} */ + const matchers = {}; + if (fs.existsSync(config.kit.files.params)) { + for (const file of fs.readdirSync(config.kit.files.params)) { + const ext = path.extname(file); + if (!config.kit.moduleExtensions.includes(ext)) continue; + const type = file.slice(0, -ext.length); + + if (/^\w+$/.test(type)) { + const matcher_file = path.join(params_base, file); + + // Disallow same matcher with different extensions + if (matchers[type]) { + throw new Error(`Duplicate matchers: ${matcher_file} and ${matchers[type]}`); + } else { + matchers[type] = matcher_file; + } + } else { + // Allow for matcher test collocation + if (type.endsWith('.test') || type.endsWith('.spec')) continue; + + throw new Error( + `Matcher names can only have underscores and alphanumeric characters — "${file}" is invalid` + ); + } + } + } + + return matchers; +} + +/** + * @param {import('types').ValidatedConfig} config + * @param {string} cwd + * @param {string} fallback + */ +function create_routes_and_nodes(cwd, config, fallback) { + /** @type {import('types').RouteData[]} */ + const routes = []; + + const routes_base = posixify(path.relative(cwd, config.kit.files.routes)); + + const valid_extensions = [...config.extensions, ...config.kit.moduleExtensions]; + + /** @type {import('types').PageNode[]} */ + const nodes = []; + + if (fs.existsSync(config.kit.files.routes)) { + /** + * @param {number} depth + * @param {string} id + * @param {string} segment + * @param {import('types').RouteData | null} parent + */ + const walk = (depth, id, segment, parent) => { + const unescaped = id.replace(/\[([ux])\+([^\]]+)\]/gi, (match, type, code) => { + if (match !== match.toLowerCase()) { + throw new Error(`Character escape sequence in ${id} must be lowercase`); + } + + if (!/[0-9a-f]+/.test(code)) { + throw new Error(`Invalid character escape sequence in ${id}`); + } + + if (type === 'x') { + if (code.length !== 2) { + throw new Error(`Hexadecimal escape sequence in ${id} must be two characters`); + } + + return String.fromCharCode(parseInt(code, 16)); + } else { + if (code.length < 4 || code.length > 6) { + throw new Error( + `Unicode escape sequence in ${id} must be between four and six characters` + ); + } + + return String.fromCharCode(parseInt(code, 16)); + } + }); + + if (/\]\[/.test(unescaped)) { + throw new Error(`Invalid route ${id} — parameters must be separated`); + } + + if (count_occurrences('[', id) !== count_occurrences(']', id)) { + throw new Error(`Invalid route ${id} — brackets are unbalanced`); + } + + if (/#/.test(segment)) { + // Vite will barf on files with # in them + throw new Error(`Route ${id} should be renamed to ${id.replace(/#/g, '[x+23]')}`); + } + + if (/\[\.\.\.\w+\]\/\[\[/.test(id)) { + throw new Error( + `Invalid route ${id} — an [[optional]] route segment cannot follow a [...rest] route segment` + ); + } + + if (/\[\[\.\.\./.test(id)) { + throw new Error( + `Invalid route ${id} — a rest route segment is always optional, remove the outer square brackets` + ); + } + + const { pattern, params } = parse_route_id(id); + + /** @type {import('types').RouteData} */ + const route = { + id, + parent, + + segment, + pattern, + params, + + layout: null, + error: null, + leaf: null, + page: null, + endpoint: null + }; + + // important to do this before walking children, so that child + // routes appear later + routes.push(route); + + // if we don't do this, the route map becomes unwieldy to console.log + Object.defineProperty(route, 'parent', { enumerable: false }); + + const dir = path.join(cwd, routes_base, id); + + // We can't use withFileTypes because of a NodeJs bug which returns wrong results + // with isDirectory() in case of symlinks: https://github.com/nodejs/node/issues/30646 + const files = fs.readdirSync(dir).map((name) => ({ + is_dir: fs.statSync(path.join(dir, name)).isDirectory(), + name + })); + + // process files first + for (const file of files) { + if (file.is_dir) continue; + + const ext = valid_extensions.find((ext) => file.name.endsWith(ext)); + if (!ext) continue; + + if (!file.name.startsWith('+')) { + const name = file.name.slice(0, -ext.length); + // check if it is a valid route filename but missing the + prefix + const typo = + /^(?:(page(?:@(.*))?)|(layout(?:@(.*))?)|(error))$/.test(name) || + /^(?:(server)|(page(?:(@[a-zA-Z0-9_-]*))?(\.server)?)|(layout(?:(@[a-zA-Z0-9_-]*))?(\.server)?))$/.test( + name + ); + if (typo) { + console.log( + colors + .bold() + .yellow( + `Missing route file prefix. Did you mean +${file.name}?` + + ` at ${path.join(dir, file.name)}` + ) + ); + } + + continue; + } + + if (file.name.endsWith('.d.ts')) { + let name = file.name.slice(0, -5); + const ext = valid_extensions.find((ext) => name.endsWith(ext)); + if (ext) name = name.slice(0, -ext.length); + + const valid = + /^\+(?:(page(?:@(.*))?)|(layout(?:@(.*))?)|(error))$/.test(name) || + /^\+(?:(server)|(page(?:(@[a-zA-Z0-9_-]*))?(\.server)?)|(layout(?:(@[a-zA-Z0-9_-]*))?(\.server)?))$/.test( + name + ); + + if (valid) continue; + } + + const project_relative = posixify(path.relative(cwd, path.join(dir, file.name))); + + const item = analyze( + project_relative, + file.name, + config.extensions, + config.kit.moduleExtensions + ); + + if (config.kit.router.type === 'hash' && item.kind === 'server') { + throw new Error( + `Cannot use server-only files in an app with \`router.type === 'hash': ${project_relative}` + ); + } + + /** + * @param {string} type + * @param {string} existing_file + */ + function duplicate_files_error(type, existing_file) { + return new Error( + `Multiple ${type} files found in ${routes_base}${route.id} : ${path.basename( + existing_file + )} and ${file.name}` + ); + } + + if (item.kind === 'component') { + if (item.is_error) { + route.error = { + depth, + component: project_relative + }; + } else if (item.is_layout) { + if (!route.layout) { + route.layout = { depth, child_pages: [] }; + } else if (route.layout.component) { + throw duplicate_files_error('layout component', route.layout.component); + } + + route.layout.component = project_relative; + if (item.uses_layout !== undefined) route.layout.parent_id = item.uses_layout; + } else { + if (!route.leaf) { + route.leaf = { depth }; + } else if (route.leaf.component) { + throw duplicate_files_error('page component', route.leaf.component); + } + + route.leaf.component = project_relative; + if (item.uses_layout !== undefined) route.leaf.parent_id = item.uses_layout; + } + } else if (item.is_layout) { + if (!route.layout) { + route.layout = { depth, child_pages: [] }; + } else if (route.layout[item.kind]) { + throw duplicate_files_error( + item.kind + ' layout module', + /** @type {string} */ (route.layout[item.kind]) + ); + } + + route.layout[item.kind] = project_relative; + } else if (item.is_page) { + if (!route.leaf) { + route.leaf = { depth }; + } else if (route.leaf[item.kind]) { + throw duplicate_files_error( + item.kind + ' page module', + /** @type {string} */ (route.leaf[item.kind]) + ); + } + + route.leaf[item.kind] = project_relative; + } else { + if (route.endpoint) { + throw duplicate_files_error('endpoint', route.endpoint.file); + } + + route.endpoint = { + file: project_relative, + page_options: null // will be filled later + }; + } + } + + // then handle children + for (const file of files) { + if (file.is_dir) { + walk(depth + 1, path.posix.join(id, file.name), file.name, route); + } + } + }; + + walk(0, '/', '', null); + + if (routes.length === 1) { + const root = routes[0]; + if (!root.leaf && !root.error && !root.layout && !root.endpoint) { + throw new Error( + 'No routes found. If you are using a custom src/routes directory, make sure it is specified in your Svelte config file' + ); + } + } + } else { + // If there's no routes directory, we'll just create a single empty route. This ensures the root layout and + // error components are included in the manifest, which is needed for subsequent build/dev commands to work + routes.push({ + id: '/', + segment: '', + pattern: /^$/, + params: [], + parent: null, + layout: null, + error: null, + leaf: null, + page: null, + endpoint: null + }); + } + + prevent_conflicts(routes); + + const root = routes[0]; + + if (!root.layout?.component) { + if (!root.layout) root.layout = { depth: 0, child_pages: [] }; + root.layout.component = posixify(path.relative(cwd, `${fallback}/layout.svelte`)); + } + + if (!root.error?.component) { + if (!root.error) root.error = { depth: 0 }; + root.error.component = posixify(path.relative(cwd, `${fallback}/error.svelte`)); + } + + // we do layouts/errors first as they are more likely to be reused, + // and smaller indexes take fewer bytes. also, this guarantees that + // the default error/layout are 0/1 + for (const route of routes) { + if (route.layout) { + if (!route.layout?.component) { + route.layout.component = posixify(path.relative(cwd, `${fallback}/layout.svelte`)); + } + nodes.push(route.layout); + } + if (route.error) nodes.push(route.error); + } + + for (const route of routes) { + if (route.leaf) nodes.push(route.leaf); + } + + const indexes = new Map(nodes.map((node, i) => [node, i])); + + const node_analyser = create_node_analyser(); + + for (const route of routes) { + if (!route.leaf) continue; + + route.page = { + layouts: [], + errors: [], + leaf: /** @type {number} */ (indexes.get(route.leaf)) + }; + + /** @type {import('types').RouteData | null} */ + let current_route = route; + let current_node = route.leaf; + let parent_id = route.leaf.parent_id; + + while (current_route) { + if (parent_id === undefined || current_route.segment === parent_id) { + if (current_route.layout || current_route.error) { + route.page.layouts.unshift( + current_route.layout ? indexes.get(current_route.layout) : undefined + ); + route.page.errors.unshift( + current_route.error ? indexes.get(current_route.error) : undefined + ); + } + + if (current_route.layout) { + /** @type {import('types').PageNode[]} */ (current_route.layout.child_pages).push( + route.leaf + ); + current_node.parent = current_node = current_route.layout; + parent_id = current_node.parent_id; + } else { + parent_id = undefined; + } + } + + current_route = current_route.parent; + } + + if (parent_id !== undefined) { + throw new Error(`${current_node.component} references missing segment "${parent_id}"`); + } + } + + for (const node of nodes) { + node.page_options = node_analyser.get_page_options(node); + } + + for (const route of routes) { + if (route.endpoint) { + route.endpoint.page_options = get_page_options(route.endpoint.file); + } + } + + return { + nodes, + routes: sort_routes(routes) + }; +} + +/** + * @param {string} project_relative + * @param {string} file + * @param {string[]} component_extensions + * @param {string[]} module_extensions + * @returns {import('./types.js').RouteFile} + */ +function analyze(project_relative, file, component_extensions, module_extensions) { + const component_extension = component_extensions.find((ext) => file.endsWith(ext)); + if (component_extension) { + const name = file.slice(0, -component_extension.length); + const pattern = /^\+(?:(page(?:@(.*))?)|(layout(?:@(.*))?)|(error))$/; + const match = pattern.exec(name); + if (!match) { + throw new Error(`Files prefixed with + are reserved (saw ${project_relative})`); + } + + return { + kind: 'component', + is_page: !!match[1], + is_layout: !!match[3], + is_error: !!match[5], + uses_layout: match[2] ?? match[4] + }; + } + + const module_extension = module_extensions.find((ext) => file.endsWith(ext)); + if (module_extension) { + const name = file.slice(0, -module_extension.length); + const pattern = + /^\+(?:(server)|(page(?:(@[a-zA-Z0-9_-]*))?(\.server)?)|(layout(?:(@[a-zA-Z0-9_-]*))?(\.server)?))$/; + const match = pattern.exec(name); + if (!match) { + throw new Error(`Files prefixed with + are reserved (saw ${project_relative})`); + } else if (match[3] || match[6]) { + throw new Error( + // prettier-ignore + `Only Svelte files can reference named layouts. Remove '${match[3] || match[6]}' from ${file} (at ${project_relative})` + ); + } + + const kind = match[1] || match[4] || match[7] ? 'server' : 'universal'; + + return { + kind, + is_page: !!match[2], + is_layout: !!match[5] + }; + } + + throw new Error(`Files and directories prefixed with + are reserved (saw ${project_relative})`); +} + +/** + * @param {string} needle + * @param {string} haystack + */ +function count_occurrences(needle, haystack) { + let count = 0; + for (let i = 0; i < haystack.length; i += 1) { + if (haystack[i] === needle) count += 1; + } + return count; +} + +/** @param {import('types').RouteData[]} routes */ +function prevent_conflicts(routes) { + /** @type {Map} */ + const lookup = new Map(); + + for (const route of routes) { + if (!route.leaf && !route.endpoint) continue; + + const normalized = normalize_route_id(route.id); + + // find all permutations created by optional parameters + const split = normalized.split(/<\?(.+?)>/g); + + let permutations = [/** @type {string} */ (split[0])]; + + // turn `x/[[optional]]/y` into `x/y` and `x/[required]/y` + for (let i = 1; i < split.length; i += 2) { + const matcher = split[i]; + const next = split[i + 1]; + + permutations = permutations.reduce((a, b) => { + a.push(b + next); + if (!(matcher === '*' && b.endsWith('//'))) a.push(b + `<${matcher}>${next}`); + return a; + }, /** @type {string[]} */ ([])); + } + + for (const permutation of permutations) { + // remove leading/trailing/duplicated slashes caused by prior + // manipulation of optional parameters and (groups) + const key = permutation + .replace(/\/{2,}/, '/') + .replace(/^\//, '') + .replace(/\/$/, ''); + + if (lookup.has(key)) { + throw new Error( + `The "${lookup.get(key)}" and "${route.id}" routes conflict with each other` + ); + } + + lookup.set(key, route.id); + } + } +} + +/** @param {string} id */ +function normalize_route_id(id) { + return ( + id + // remove groups + .replace(/(?<=^|\/)\(.+?\)(?=$|\/)/g, '') + + .replace(/\[[ux]\+([0-9a-f]+)\]/g, (_, x) => + String.fromCharCode(parseInt(x, 16)).replace(/\//g, '%2f') + ) + + // replace `[param]` with `<*>`, `[param=x]` with ``, and `[[param]]` with `` + .replace( + /\[(?:(\[)|(\.\.\.))?.+?(=.+?)?\]\]?/g, + (_, optional, rest, matcher) => `<${optional ? '?' : ''}${rest ?? ''}${matcher ?? '*'}>` + ) + ); +} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/sort.js b/frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/sort.js new file mode 100644 index 0000000..1629d14 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/sort.js @@ -0,0 +1,162 @@ +import { get_route_segments } from '../../../utils/routing.js'; + +/** + * @typedef {{ + * type: 'static' | 'required' | 'optional' | 'rest'; + * content: string; + * matched: boolean; + * }} Part + */ + +/** + * @typedef {Part[]} Segment + */ + +const EMPTY = { type: 'static', content: '', matched: false }; + +/** @param {import('types').RouteData[]} routes */ +export function sort_routes(routes) { + /** @type {Map} */ + const segment_cache = new Map(); + + /** @param {string} segment */ + function get_parts(segment) { + if (!segment_cache.has(segment)) { + segment_cache.set(segment, split(segment)); + } + + return segment_cache.get(segment); + } + + /** @param {string} id */ + function split(id) { + /** @type {Part[]} */ + const parts = []; + + let i = 0; + while (i <= id.length) { + const start = id.indexOf('[', i); + if (start === -1) { + parts.push({ type: 'static', content: id.slice(i), matched: false }); + break; + } + + parts.push({ type: 'static', content: id.slice(i, start), matched: false }); + + const type = id[start + 1] === '[' ? 'optional' : id[start + 1] === '.' ? 'rest' : 'required'; + const delimiter = type === 'optional' ? ']]' : ']'; + const end = id.indexOf(delimiter, start); + + if (end === -1) { + throw new Error(`Invalid route ID ${id}`); + } + + const content = id.slice(start, (i = end + delimiter.length)); + + parts.push({ + type, + content, + matched: content.includes('=') + }); + } + + return parts; + } + + return routes.sort((route_a, route_b) => { + const segments_a = split_route_id(route_a.id).map(get_parts); + const segments_b = split_route_id(route_b.id).map(get_parts); + + for (let i = 0; i < Math.max(segments_a.length, segments_b.length); i += 1) { + const segment_a = segments_a[i] ?? [EMPTY]; + const segment_b = segments_b[i] ?? [EMPTY]; + + for (let j = 0; j < Math.max(segment_a.length, segment_b.length); j += 1) { + const a = segment_a[j]; + const b = segment_b[j]; + + // first part of each segment is always static + // (though it may be the empty string), then + // it alternates between dynamic and static + // (i.e. [foo][bar] is disallowed) + const dynamic = j % 2 === 1; + + if (dynamic) { + if (!a) return -1; + if (!b) return +1; + + // get the next static chunk, so we can handle [...rest] edge cases + const next_a = segment_a[j + 1].content || segments_a[i + 1]?.[0].content; + const next_b = segment_b[j + 1].content || segments_b[i + 1]?.[0].content; + + // `[...rest]/x` outranks `[...rest]` + if (a.type === 'rest' && b.type === 'rest') { + if (next_a && next_b) continue; + if (next_a) return -1; + if (next_b) return +1; + } + + // `[...rest]/x` outranks `[required]` or `[required]/[required]` + // but not `[required]/x` + if (a.type === 'rest') { + return next_a && !next_b ? -1 : +1; + } + + if (b.type === 'rest') { + return next_b && !next_a ? +1 : -1; + } + + // part with matcher outranks one without + if (a.matched !== b.matched) { + return a.matched ? -1 : +1; + } + + if (a.type !== b.type) { + // `[...rest]` has already been accounted for, so here + // we're comparing between `[required]` and `[[optional]]` + if (a.type === 'required') return -1; + if (b.type === 'required') return +1; + } + } else if (a.content !== b.content) { + // shallower path outranks deeper path + if (a === EMPTY) return -1; + if (b === EMPTY) return +1; + + return sort_static(a.content, b.content); + } + } + } + + return route_a.id < route_b.id ? +1 : -1; + }); +} + +/** @param {string} id */ +function split_route_id(id) { + return get_route_segments( + id + // remove all [[optional]] parts unless they're at the very end + // or it ends with a route group + .replace(/\[\[[^\]]+\]\](?!(?:\/\([^/]+\))*$)/g, '') + ).filter(Boolean); +} + +/** + * Sort two strings lexicographically, except `foobar` outranks `foo` + * @param {string} a + * @param {string} b + */ +function sort_static(a, b) { + if (a === b) return 0; + + for (let i = 0; true; i += 1) { + const char_a = a[i]; + const char_b = b[i]; + + if (char_a !== char_b) { + if (char_a === undefined) return +1; + if (char_b === undefined) return -1; + return char_a < char_b ? -1 : +1; + } + } +} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/types.d.ts b/frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/types.d.ts new file mode 100644 index 0000000..ec5c01b --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/types.d.ts @@ -0,0 +1,37 @@ +import { PageNode } from 'types'; + +interface Part { + dynamic: boolean; + optional: boolean; + rest: boolean; + type: string | null; +} + +interface RouteTreeNode { + error: PageNode | undefined; + layout: PageNode | undefined; +} + +export type RouteTree = Map; + +interface RouteComponent { + kind: 'component'; + is_page: boolean; + is_layout: boolean; + is_error: boolean; + uses_layout: string | undefined; +} + +interface RouteSharedModule { + kind: 'universal'; + is_page: boolean; + is_layout: boolean; +} + +interface RouteServerModule { + kind: 'server'; + is_page: boolean; + is_layout: boolean; +} + +export type RouteFile = RouteComponent | RouteSharedModule | RouteServerModule; diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/sync.js b/frontend/node_modules/@sveltejs/kit/src/core/sync/sync.js new file mode 100644 index 0000000..d9680e8 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/sync/sync.js @@ -0,0 +1,96 @@ +import path from 'node:path'; +import create_manifest_data from './create_manifest_data/index.js'; +import { write_client_manifest } from './write_client_manifest.js'; +import { write_root } from './write_root.js'; +import { write_tsconfig } from './write_tsconfig.js'; +import { write_types, write_all_types } from './write_types/index.js'; +import { write_ambient } from './write_ambient.js'; +import { write_non_ambient } from './write_non_ambient.js'; +import { write_server } from './write_server.js'; +import { + create_node_analyser, + get_page_options +} from '../../exports/vite/static_analysis/index.js'; + +/** + * Initialize SvelteKit's generated files that only depend on the config and mode. + * @param {import('types').ValidatedConfig} config + * @param {string} mode + */ +export function init(config, mode) { + write_tsconfig(config.kit); + write_ambient(config.kit, mode); +} + +/** + * Update SvelteKit's generated files + * @param {import('types').ValidatedConfig} config + */ +export function create(config) { + const manifest_data = create_manifest_data({ config }); + + const output = path.join(config.kit.outDir, 'generated'); + + write_client_manifest(config.kit, manifest_data, `${output}/client`); + write_server(config, output); + write_root(manifest_data, config, output); + write_all_types(config, manifest_data); + write_non_ambient(config.kit, manifest_data); + + return { manifest_data }; +} + +/** + * Update SvelteKit's generated files in response to a single file content update. + * Do not call this when the file in question was created/deleted. + * + * @param {import('types').ValidatedConfig} config + * @param {import('types').ManifestData} manifest_data + * @param {string} file + */ +export function update(config, manifest_data, file) { + const node_analyser = create_node_analyser(); + + for (const node of manifest_data.nodes) { + node.page_options = node_analyser.get_page_options(node); + } + + for (const route of manifest_data.routes) { + if (route.endpoint) { + route.endpoint.page_options = get_page_options(route.endpoint.file); + } + } + + write_types(config, manifest_data, file); + write_non_ambient(config.kit, manifest_data); +} + +/** + * Run sync.init and sync.create in series, returning the result from sync.create. + * @param {import('types').ValidatedConfig} config + * @param {string} mode The Vite mode + */ +export function all(config, mode) { + init(config, mode); + return create(config); +} + +/** + * Run sync.init and then generate all type files. + * @param {import('types').ValidatedConfig} config + * @param {string} mode The Vite mode + */ +export function all_types(config, mode) { + init(config, mode); + const manifest_data = create_manifest_data({ config }); + write_all_types(config, manifest_data); + write_non_ambient(config.kit, manifest_data); +} + +/** + * Regenerate __SERVER__/internal.js in response to src/{app.html,error.html,service-worker.js} changing + * @param {import('types').ValidatedConfig} config + */ +export function server(config) { + write_server(config, path.join(config.kit.outDir, 'generated')); +} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/ts.js b/frontend/node_modules/@sveltejs/kit/src/core/sync/ts.js new file mode 100644 index 0000000..61c79e3 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/sync/ts.js @@ -0,0 +1,6 @@ +/** @type {import('typescript')} */ +// @ts-ignore +export let ts = undefined; +try { + ts = (await import('typescript')).default; +} catch {} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/utils.js b/frontend/node_modules/@sveltejs/kit/src/core/sync/utils.js new file mode 100644 index 0000000..be3ecc2 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/sync/utils.js @@ -0,0 +1,78 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { mkdirp } from '../../utils/filesystem.js'; +import { import_peer } from '../../utils/import.js'; + +/** @type {{ VERSION: string }} */ +const { VERSION } = await import_peer('svelte/compiler'); + +/** @type {Map} */ +const previous_contents = new Map(); + +/** + * @param {string} file + * @param {string} code + */ +export function write_if_changed(file, code) { + if (code !== previous_contents.get(file)) { + write(file, code); + } +} + +/** + * @param {string} file + * @param {string} code + */ +export function write(file, code) { + previous_contents.set(file, code); + mkdirp(path.dirname(file)); + fs.writeFileSync(file, code); +} + +/** @type {WeakMap} */ +const dedent_map = new WeakMap(); + +/** + * Allows indenting template strings without the extra indentation ending up in the result. + * Still allows indentation of lines relative to one another in the template string. + * @param {TemplateStringsArray} strings + * @param {any[]} values + */ +export function dedent(strings, ...values) { + let dedented = dedent_map.get(strings); + + if (!dedented) { + const indentation = /** @type {RegExpExecArray} */ (/\n?([ \t]*)/.exec(strings[0]))[1]; + const pattern = new RegExp(`^${indentation}`, 'gm'); + + dedented = { + strings: strings.map((str) => str.replace(pattern, '')), + indents: [] + }; + + let current = '\n'; + + for (let i = 0; i < values.length; i += 1) { + const string = dedented.strings[i]; + const match = /\n([ \t]*)$/.exec(string); + + if (match) current = match[0]; + dedented.indents[i] = current; + } + + dedent_map.set(strings, dedented); + } + + let str = dedented.strings[0]; + for (let i = 0; i < values.length; i += 1) { + str += String(values[i]).replace(/\n/g, dedented.indents[i]) + dedented.strings[i + 1]; + } + + str = str.trim(); + + return str; +} + +export function isSvelte5Plus() { + return Number(VERSION[0]) >= 5; +} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/write_ambient.js b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_ambient.js new file mode 100644 index 0000000..1f21880 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_ambient.js @@ -0,0 +1,63 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { get_env } from '../../exports/vite/utils.js'; +import { GENERATED_COMMENT } from '../../constants.js'; +import { create_dynamic_types, create_static_types } from '../env.js'; +import { write_if_changed } from './utils.js'; + +// TODO these types should be described in a neutral place, rather than +// inside either `packages/kit` or `svelte.dev/docs/kit` +const descriptions_dir = fileURLToPath(new URL('../../../src/types/synthetic', import.meta.url)); + +/** @param {string} filename */ +function read_description(filename) { + const content = fs.readFileSync(`${descriptions_dir}/${filename}`, 'utf8'); + return `/**\n${content + .trim() + .split('\n') + .map((line) => ` * ${line}`) + .join('\n')}\n */`; +} + +/** + * @param {import('types').Env} env + * @param {{ + * public_prefix: string; + * private_prefix: string; + * }} prefixes + */ +const template = (env, prefixes) => ` +${GENERATED_COMMENT} + +/// + +${read_description('$env+static+private.md')} +${create_static_types('private', env)} + +${read_description('$env+static+public.md')} +${create_static_types('public', env)} + +${read_description('$env+dynamic+private.md')} +${create_dynamic_types('private', env, prefixes)} + +${read_description('$env+dynamic+public.md')} +${create_dynamic_types('public', env, prefixes)} +`; + +/** + * Writes ambient declarations including types reference to @sveltejs/kit, + * and the existing environment variables in process.env to + * $env/static/private and $env/static/public + * @param {import('types').ValidatedKitConfig} config + * @param {string} mode The Vite mode + */ +export function write_ambient(config, mode) { + const env = get_env(config.env, mode); + const { publicPrefix: public_prefix, privatePrefix: private_prefix } = config.env; + + write_if_changed( + path.join(config.outDir, 'ambient.d.ts'), + template(env, { public_prefix, private_prefix }) + ); +} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/write_client_manifest.js b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_client_manifest.js new file mode 100644 index 0000000..7495e31 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_client_manifest.js @@ -0,0 +1,203 @@ +import path from 'node:path'; +import { relative_path, resolve_entry } from '../../utils/filesystem.js'; +import { s } from '../../utils/misc.js'; +import { dedent, isSvelte5Plus, write_if_changed } from './utils.js'; +import colors from 'kleur'; + +/** + * Writes the client manifest to disk. The manifest is used to power the router. It contains the + * list of routes and corresponding Svelte components (i.e. pages and layouts). + * @param {import('types').ValidatedKitConfig} kit + * @param {import('types').ManifestData} manifest_data + * @param {string} output + * @param {import('types').ServerMetadata['nodes']} [metadata] If this is omitted, we have to assume that all routes with a `+layout/page.server.js` file have a server load function + */ +export function write_client_manifest(kit, manifest_data, output, metadata) { + const client_routing = kit.router.resolution === 'client'; + + /** + * Creates a module that exports a `CSRPageNode` + * @param {import('types').PageNode} node + */ + function generate_node(node) { + const declarations = []; + + if (node.universal) { + declarations.push( + `import * as universal from ${s(relative_path(`${output}/nodes`, node.universal))};`, + 'export { universal };' + ); + } + + if (node.component) { + declarations.push( + `export { default as component } from ${s( + relative_path(`${output}/nodes`, node.component) + )};` + ); + } + + return declarations.join('\n'); + } + + /** @type {Map} */ + const indices = new Map(); + const nodes = manifest_data.nodes + .map((node, i) => { + indices.set(node, i); + + write_if_changed(`${output}/nodes/${i}.js`, generate_node(node)); + return `() => import('./nodes/${i}')`; + }) + // If route resolution happens on the server, we only need the root layout and root error page + // upfront, the rest is loaded on demand as the user navigates the app + .slice(0, client_routing ? manifest_data.nodes.length : 2) + .join(',\n'); + + const layouts_with_server_load = new Set(); + + let dictionary = dedent` + { + ${manifest_data.routes + .map((route) => { + if (route.page) { + const errors = route.page.errors.slice(1).map((n) => n ?? ''); + const layouts = route.page.layouts.slice(1).map((n) => n ?? ''); + + while (layouts.at(-1) === '') layouts.pop(); + while (errors.at(-1) === '') errors.pop(); + + let leaf_has_server_load = false; + if (route.leaf) { + if (metadata) { + const i = /** @type {number} */ (indices.get(route.leaf)); + + leaf_has_server_load = metadata[i].has_server_load; + } else if (route.leaf.server) { + leaf_has_server_load = true; + } + } + + // Encode whether or not the route uses server data + // using the ones' complement, to save space + const array = [`${leaf_has_server_load ? '~' : ''}${route.page.leaf}`]; + + // Encode whether or not the layout uses server data. + // It's a different method compared to pages because layouts + // are reused across pages, so we save space by doing it this way. + route.page.layouts.forEach((layout) => { + if (layout == undefined) return; + + let layout_has_server_load = false; + + if (metadata) { + layout_has_server_load = metadata[layout].has_server_load; + } else if (manifest_data.nodes[layout].server) { + layout_has_server_load = true; + } + + if (layout_has_server_load) { + layouts_with_server_load.add(layout); + } + }); + + // only include non-root layout/error nodes if they exist + if (layouts.length > 0 || errors.length > 0) array.push(`[${layouts.join(',')}]`); + if (errors.length > 0) array.push(`[${errors.join(',')}]`); + + return `${s(route.id)}: [${array.join(',')}]`; + } + }) + .filter(Boolean) + .join(',\n')} + } + `; + + if (!client_routing) { + dictionary = '{}'; + const root_layout = layouts_with_server_load.has(0); + layouts_with_server_load.clear(); + if (root_layout) layouts_with_server_load.add(0); + } + + const client_hooks_file = resolve_entry(kit.files.hooks.client); + const universal_hooks_file = resolve_entry(kit.files.hooks.universal); + + const typo = resolve_entry('src/+hooks.client'); + if (typo) { + console.log( + colors + .bold() + .yellow( + `Unexpected + prefix. Did you mean ${typo.split('/').at(-1)?.slice(1)}?` + + ` at ${path.resolve(typo)}` + ) + ); + } + + // Stringified version of + /** @type {import('../../runtime/client/types.js').SvelteKitApp} */ + write_if_changed( + `${output}/app.js`, + dedent` + ${ + client_hooks_file + ? `import * as client_hooks from '${relative_path(output, client_hooks_file)}';` + : '' + } + ${ + universal_hooks_file + ? `import * as universal_hooks from '${relative_path(output, universal_hooks_file)}';` + : '' + } + + ${client_routing ? "export { matchers } from './matchers.js';" : 'export const matchers = {};'} + + export const nodes = [ + ${nodes} + ]; + + export const server_loads = [${[...layouts_with_server_load].join(',')}]; + + export const dictionary = ${dictionary}; + + export const hooks = { + handleError: ${ + client_hooks_file ? 'client_hooks.handleError || ' : '' + }(({ error }) => { console.error(error) }), + ${client_hooks_file ? 'init: client_hooks.init,' : ''} + reroute: ${universal_hooks_file ? 'universal_hooks.reroute || ' : ''}(() => {}), + transport: ${universal_hooks_file ? 'universal_hooks.transport || ' : ''}{} + }; + + export const decoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.decode])); + export const encoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.encode])); + + export const hash = ${s(kit.router.type === 'hash')}; + + export const decode = (type, value) => decoders[type](value); + + export { default as root } from '../root.${isSvelte5Plus() ? 'js' : 'svelte'}'; + ` + ); + + if (client_routing) { + // write matchers to a separate module so that we don't + // need to worry about name conflicts + const imports = []; + const matchers = []; + + for (const key in manifest_data.matchers) { + const src = manifest_data.matchers[key]; + + imports.push(`import { match as ${key} } from ${s(relative_path(output, src))};`); + matchers.push(key); + } + + const module = imports.length + ? `${imports.join('\n')}\n\nexport const matchers = { ${matchers.join(', ')} };` + : 'export const matchers = {};'; + + write_if_changed(`${output}/matchers.js`, module); + } +} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/write_non_ambient.js b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_non_ambient.js new file mode 100644 index 0000000..3b92b73 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_non_ambient.js @@ -0,0 +1,266 @@ +import path from 'node:path'; +import { GENERATED_COMMENT } from '../../constants.js'; +import { posixify } from '../../utils/filesystem.js'; +import { write_if_changed } from './utils.js'; +import { s } from '../../utils/misc.js'; +import { get_route_segments } from '../../utils/routing.js'; + +const replace_optional_params = (/** @type {string} */ id) => + id.replace(/\/\[\[[^\]]+\]\]/g, '${string}'); +const replace_required_params = (/** @type {string} */ id) => + id.replace(/\/\[[^\]]+\]/g, '/${string}'); +/** Convert route ID to pathname by removing layout groups */ +const remove_group_segments = (/** @type {string} */ id) => { + return '/' + get_route_segments(id).join('/'); +}; + +/** + * Get pathnames to add based on trailingSlash settings + * @param {string} pathname + * @param {import('types').RouteData} route + * @returns {string[]} + */ +function get_pathnames_for_trailing_slash(pathname, route) { + if (pathname === '/') { + return [pathname]; + } + + /** @type {Set} */ + const pathnames = new Set(); + + /** + * @param {{ trailingSlash?: import('types').TrailingSlash } | null | undefined} page_options + */ + const add_pathnames = (page_options) => { + if (page_options === null || page_options?.trailingSlash === 'ignore') { + pathnames.add(pathname); + pathnames.add(pathname + '/'); + } else if (page_options?.trailingSlash === 'always') { + pathnames.add(pathname + '/'); + } else { + pathnames.add(pathname); + } + }; + + if (route.leaf) add_pathnames(route.leaf.page_options ?? null); + if (route.endpoint) add_pathnames(route.endpoint.page_options); + + return Array.from(pathnames); +} + +// `declare module "svelte/elements"` needs to happen in a non-ambient module, and dts-buddy generates one big ambient module, +// so we can't add it there - therefore generate the typings ourselves here. +// We're not using the `declare namespace svelteHTML` variant because that one doesn't augment the HTMLAttributes interface +// people could use to type their own components. +// The T generic is needed or else there's a "all declarations must have identical type parameters" error. +const template = ` +${GENERATED_COMMENT} + +declare module "svelte/elements" { + export interface HTMLAttributes { + 'data-sveltekit-keepfocus'?: true | '' | 'off' | undefined | null; + 'data-sveltekit-noscroll'?: true | '' | 'off' | undefined | null; + 'data-sveltekit-preload-code'?: + | true + | '' + | 'eager' + | 'viewport' + | 'hover' + | 'tap' + | 'off' + | undefined + | null; + 'data-sveltekit-preload-data'?: true | '' | 'hover' | 'tap' | 'off' | undefined | null; + 'data-sveltekit-reload'?: true | '' | 'off' | undefined | null; + 'data-sveltekit-replacestate'?: true | '' | 'off' | undefined | null; + } +} + +export {}; +`; + +/** + * Generate app types interface extension + * @param {import('types').ManifestData} manifest_data + * @param {import('types').ValidatedKitConfig} config + */ +function generate_app_types(manifest_data, config) { + /** @param {string} matcher */ + const path_to_matcher = (matcher) => + posixify(path.relative(config.outDir, path.join(config.files.params, matcher + '.js'))); + + /** @type {Map} */ + const matcher_types = new Map(); + + /** @param {string | undefined} matcher */ + const get_matcher_type = (matcher) => { + if (!matcher) return 'string'; + + let type = matcher_types.get(matcher); + if (!type) { + type = `MatcherParam`; + matcher_types.set(matcher, type); + } + + return type; + }; + + /** @param {Set | null} matchers */ + const get_matchers_type = (matchers) => { + if (matchers === null) return 'string'; + + return Array.from(matchers) + .map((matcher) => get_matcher_type(matcher)) + .join(' | '); + }; + + /** @type {Set} */ + const route_ids = new Set(manifest_data.routes.map((route) => route.id)); + + /** + * @param {string} id + * @returns {string[]} + */ + const get_ancestor_route_ids = (id) => { + /** @type {string[]} */ + const ancestors = []; + + if (route_ids.has('/')) { + ancestors.push('/'); + } + + let current = ''; + for (const segment of id.slice(1).split('/')) { + if (!segment) continue; + + current += '/' + segment; + if (route_ids.has(current)) { + ancestors.push(current); + } + } + + return ancestors; + }; + + /** @type {Set} */ + const pathnames = new Set(); + + /** @type {string[]} */ + const dynamic_routes = []; + + /** @type {string[]} */ + const layouts = []; + + /** @type {Map | null }>>} */ + const layout_params_by_route = new Map( + manifest_data.routes.map((route) => [ + route.id, + new Map( + route.params.map((p) => [ + p.name, + { optional: p.optional, matchers: p.matcher ? new Set([p.matcher]) : null } + ]) + ) + ]) + ); + + for (const route of manifest_data.routes) { + const ancestors = get_ancestor_route_ids(route.id); + + for (const ancestor_id of ancestors) { + const ancestor_params = layout_params_by_route.get(ancestor_id); + if (!ancestor_params) continue; + + for (const p of route.params) { + const matcher = p.matcher ?? null; + const entry = ancestor_params.get(p.name); + if (!entry) { + ancestor_params.set(p.name, { + optional: true, + matchers: matcher === null ? null : new Set([matcher]) + }); + continue; + } + + if (entry.matchers === null) continue; + + if (matcher === null) { + entry.matchers = null; + continue; + } + + entry.matchers.add(matcher); + } + } + } + + for (const route of manifest_data.routes) { + const pathname = remove_group_segments(route.id); + let normalized_pathname = pathname; + + /** @type {(path: string) => string} */ + let serialise = s; + + if (route.params.length > 0) { + const params = route.params.map((p) => { + const type = get_matcher_type(p.matcher); + return `${p.name}${p.optional ? '?:' : ':'} ${type}`; + }); + const route_type = `${s(route.id)}: { ${params.join('; ')} }`; + + dynamic_routes.push(route_type); + + normalized_pathname = replace_required_params(replace_optional_params(pathname)); + serialise = (p) => `\`${p}\` & {}`; + } + + for (const p of get_pathnames_for_trailing_slash(normalized_pathname, route)) { + pathnames.add(serialise(p)); + } + + let layout_type = 'Record'; + + const layout_params = layout_params_by_route.get(route.id); + if (layout_params) { + const params = Array.from(layout_params) + .map(([name, { optional, matchers }]) => { + const type = get_matchers_type(matchers); + return `${name}${optional ? '?:' : ':'} ${type}`; + }) + .join('; '); + + if (params.length > 0) layout_type = `{ ${params} }`; + } + + layouts.push(`${s(route.id)}: ${layout_type}`); + } + + const assets = manifest_data.assets.map((asset) => s('/' + asset.file)); + + return [ + 'declare module "$app/types" {', + '\ttype MatcherParam = M extends (param : string) => param is (infer U extends string) ? U : string;', + '', + '\texport interface AppTypes {', + `\t\tRouteId(): ${manifest_data.routes.map((r) => s(r.id)).join(' | ')};`, + `\t\tRouteParams(): {\n\t\t\t${dynamic_routes.join(';\n\t\t\t')}\n\t\t};`, + `\t\tLayoutParams(): {\n\t\t\t${layouts.join(';\n\t\t\t')}\n\t\t};`, + `\t\tPathname(): ${Array.from(pathnames).join(' | ')};`, + '\t\tResolvedPathname(): `${"" | `/${string}`}${ReturnType}`;', + `\t\tAsset(): ${assets.concat('string & {}').join(' | ')};`, + '\t}', + '}' + ].join('\n'); +} + +/** + * Writes non-ambient declarations to the output directory + * @param {import('types').ValidatedKitConfig} config + * @param {import('types').ManifestData} manifest_data + */ +export function write_non_ambient(config, manifest_data) { + const app_types = generate_app_types(manifest_data, config); + const content = [template, app_types].join('\n\n'); + + write_if_changed(path.join(config.outDir, 'non-ambient.d.ts'), content); +} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/write_root.js b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_root.js new file mode 100644 index 0000000..445c17e --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_root.js @@ -0,0 +1,196 @@ +import { dedent, isSvelte5Plus, write_if_changed } from './utils.js'; + +/** + * @param {import('types').ManifestData} manifest_data + * @param {import('types').ValidatedConfig} config + * @param {string} output + */ +export function write_root(manifest_data, config, output) { + // TODO remove default layout altogether + + const use_boundaries = config.kit.experimental.handleRenderingErrors && isSvelte5Plus(); + + const max_depth = Math.max( + ...manifest_data.routes.map((route) => + route.page ? route.page.layouts.filter(Boolean).length + 1 : 0 + ), + 1 + ); + + const levels = []; + for (let i = 0; i <= max_depth; i += 1) { + levels.push(i); + } + + let l = max_depth; + /** @type {string} */ + let pyramid; + + if (isSvelte5Plus() && use_boundaries) { + // with the @const we force the data[depth] access to be derived, which is important to not fire updates needlessly + // TODO in Svelte 5 we should rethink the client.js side, we can likely make data a $state and only update indexes that changed there, simplifying this a lot + pyramid = dedent` + {#snippet pyramid(depth)} + {@const Pyramid = constructors[depth]} + {#snippet failed(error)} + {@const ErrorPage = errors[depth]} + + {/snippet} + + {#if constructors[depth + 1]} + {@const d = data[depth]} + + + {@render pyramid(depth + 1)} + + {:else} + {@const d = data[depth]} + + + {/if} + + {/snippet} + + {@render pyramid(0)} + `; + } else { + pyramid = dedent` + ${ + isSvelte5Plus() + ? ` + ` + : `` + }`; + + while (l--) { + pyramid = dedent` + {#if constructors[${l + 1}]} + ${ + isSvelte5Plus() + ? dedent`{@const Pyramid_${l} = constructors[${l}]} + + + ${pyramid} + ` + : dedent` + ${pyramid} + ` + } + + {:else} + ${ + isSvelte5Plus() + ? dedent` + {@const Pyramid_${l} = constructors[${l}]} + + + ` + : dedent`` + } + + {/if} + `; + } + } + + write_if_changed( + `${output}/root.svelte`, + dedent` + + ${isSvelte5Plus() ? '' : ''} + + + ${pyramid} + + {#if mounted} +
+ {#if navigated} + {title} + {/if} +
+ {/if} + ` + ); + + if (isSvelte5Plus()) { + write_if_changed( + `${output}/root.js`, + dedent` + import { asClassComponent } from 'svelte/legacy'; + import Root from './root.svelte'; + export default asClassComponent(Root); + ` + ); + } +} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/write_server.js b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_server.js new file mode 100644 index 0000000..711a007 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_server.js @@ -0,0 +1,143 @@ +import path from 'node:path'; +import process from 'node:process'; +import { hash } from '../../utils/hash.js'; +import { posixify, resolve_entry } from '../../utils/filesystem.js'; +import { s } from '../../utils/misc.js'; +import { load_error_page, load_template } from '../config/index.js'; +import { runtime_directory } from '../utils.js'; +import { isSvelte5Plus, write_if_changed } from './utils.js'; +import colors from 'kleur'; +import { escape_html } from '../../utils/escape.js'; + +/** + * @param {{ + * server_hooks: string | null; + * universal_hooks: string | null; + * config: import('types').ValidatedConfig; + * has_service_worker: boolean; + * runtime_directory: string; + * template: string; + * error_page: string; + * }} opts + */ +const server_template = ({ + config, + server_hooks, + universal_hooks, + has_service_worker, + runtime_directory, + template, + error_page +}) => ` +import root from '../root.${isSvelte5Plus() ? 'js' : 'svelte'}'; +import { set_building, set_prerendering } from '__sveltekit/environment'; +import { set_assets } from '$app/paths/internal/server'; +import { set_manifest, set_read_implementation } from '__sveltekit/server'; +import { set_private_env, set_public_env } from '${runtime_directory}/shared-server.js'; + +export const options = { + app_template_contains_nonce: ${template.includes('%sveltekit.nonce%')}, + async: ${s(!!config.compilerOptions?.experimental?.async)}, + csp: ${s(config.kit.csp)}, + csrf_check_origin: ${s(config.kit.csrf.checkOrigin && !config.kit.csrf.trustedOrigins.includes('*'))}, + csrf_trusted_origins: ${s(config.kit.csrf.trustedOrigins)}, + embedded: ${config.kit.embedded}, + env_public_prefix: '${config.kit.env.publicPrefix}', + env_private_prefix: '${config.kit.env.privatePrefix}', + hash_routing: ${s(config.kit.router.type === 'hash')}, + hooks: null, // added lazily, via \`get_hooks\` + preload_strategy: ${s(config.kit.output.preloadStrategy)}, + root, + service_worker: ${has_service_worker}, + service_worker_options: ${config.kit.serviceWorker.register ? s(config.kit.serviceWorker.options) : 'null'}, + server_error_boundaries: ${s(!!config.kit.experimental.handleRenderingErrors)}, + templates: { + app: ({ head, body, assets, nonce, env }) => ${s(template) + .replace('%sveltekit.head%', '" + head + "') + .replace('%sveltekit.body%', '" + body + "') + .replace(/%sveltekit\.assets%/g, '" + assets + "') + .replace(/%sveltekit\.nonce%/g, '" + nonce + "') + .replace(/%sveltekit\.version%/g, escape_html(config.kit.version.name)) + .replace( + /%sveltekit\.env\.([^%]+)%/g, + (_match, capture) => `" + (env[${s(capture)}] ?? "") + "` + )}, + error: ({ status, message }) => ${s(error_page) + .replace(/%sveltekit\.status%/g, '" + status + "') + .replace(/%sveltekit\.error\.message%/g, '" + message + "')} + }, + version_hash: ${s(hash(config.kit.version.name))} +}; + +export async function get_hooks() { + let handle; + let handleFetch; + let handleError; + let handleValidationError; + let init; + ${server_hooks ? `({ handle, handleFetch, handleError, handleValidationError, init } = await import(${s(server_hooks)}));` : ''} + + let reroute; + let transport; + ${universal_hooks ? `({ reroute, transport } = await import(${s(universal_hooks)}));` : ''} + + return { + handle, + handleFetch, + handleError, + handleValidationError, + init, + reroute, + transport + }; +} + +export { set_assets, set_building, set_manifest, set_prerendering, set_private_env, set_public_env, set_read_implementation }; +`; + +// TODO need to re-run this whenever src/app.html or src/error.html are +// created or changed, or src/service-worker.js is created or deleted. +// Also, need to check that updating hooks.server.js works + +/** + * Write server configuration to disk + * @param {import('types').ValidatedConfig} config + * @param {string} output + */ +export function write_server(config, output) { + const server_hooks_file = resolve_entry(config.kit.files.hooks.server); + const universal_hooks_file = resolve_entry(config.kit.files.hooks.universal); + + const typo = resolve_entry('src/+hooks.server'); + if (typo) { + console.log( + colors + .bold() + .yellow( + `Unexpected + prefix. Did you mean ${typo.split('/').at(-1)?.slice(1)}?` + + ` at ${path.resolve(typo)}` + ) + ); + } + + /** @param {string} file */ + function relative(file) { + return posixify(path.relative(`${output}/server`, file)); + } + + // Contains the stringified version of + /** @type {import('types').SSROptions} */ + write_if_changed( + `${output}/server/internal.js`, + server_template({ + config, + server_hooks: server_hooks_file ? relative(server_hooks_file) : null, + universal_hooks: universal_hooks_file ? relative(universal_hooks_file) : null, + has_service_worker: + config.kit.serviceWorker.register && !!resolve_entry(config.kit.files.serviceWorker), + runtime_directory: relative(runtime_directory), + template: load_template(process.cwd(), config), + error_page: load_error_page(config) + }) + ); +} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/write_tsconfig.js b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_tsconfig.js new file mode 100644 index 0000000..9451c8a --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_tsconfig.js @@ -0,0 +1,243 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; +import colors from 'kleur'; +import { posixify } from '../../utils/filesystem.js'; +import { write_if_changed } from './utils.js'; + +/** + * @param {string} cwd + * @param {string} file + */ +function maybe_file(cwd, file) { + const resolved = path.resolve(cwd, file); + if (fs.existsSync(resolved)) { + return resolved; + } +} + +/** + * @param {string} file + */ +function project_relative(file) { + return posixify(path.relative('.', file)); +} + +/** + * @param {string} file + */ +function remove_trailing_slashstar(file) { + if (file.endsWith('/*')) { + return file.slice(0, -2); + } else { + return file; + } +} + +/** + * Generates the tsconfig that the user's tsconfig inherits from. + * @param {import('types').ValidatedKitConfig} kit + */ +export function write_tsconfig(kit, cwd = process.cwd()) { + const out = path.join(kit.outDir, 'tsconfig.json'); + + const user_config = load_user_tsconfig(cwd); + if (user_config) validate_user_config(cwd, out, user_config); + + write_if_changed(out, JSON.stringify(get_tsconfig(kit), null, '\t')); +} + +/** + * Generates the tsconfig that the user's tsconfig inherits from. + * @param {import('types').ValidatedKitConfig} kit + */ +export function get_tsconfig(kit) { + /** @param {string} file */ + const config_relative = (file) => posixify(path.relative(kit.outDir, file)); + + const include = new Set([ + 'ambient.d.ts', // careful: changing this name would be a breaking change, because it's referenced in the service-workers documentation + 'non-ambient.d.ts', + './types/**/$types.d.ts', + config_relative('vite.config.js'), + config_relative('vite.config.ts') + ]); + const src_includes = [kit.files.routes, kit.files.lib, kit.files.src].filter((dir) => { + const relative = path.relative(kit.files.src, dir); + return !relative || relative.startsWith('..'); + }); + for (const dir of src_includes) { + include.add(config_relative(`${dir}/**/*.js`)); + include.add(config_relative(`${dir}/**/*.ts`)); + include.add(config_relative(`${dir}/**/*.svelte`)); + } + + // Test folder is a special case - we advocate putting tests in a top-level test folder + // and it's not configurable (should we make it?) + const test_folder = project_relative('test'); + include.add(config_relative(`${test_folder}/**/*.js`)); + include.add(config_relative(`${test_folder}/**/*.ts`)); + include.add(config_relative(`${test_folder}/**/*.svelte`)); + const tests_folder = project_relative('tests'); + include.add(config_relative(`${tests_folder}/**/*.js`)); + include.add(config_relative(`${tests_folder}/**/*.ts`)); + include.add(config_relative(`${tests_folder}/**/*.svelte`)); + + const exclude = [config_relative('node_modules/**')]; + // Add service worker to exclude list so that worker types references in it don't spill over into the rest of the app + // (i.e. suddenly ServiceWorkerGlobalScope would be available throughout the app, and some types might even clash) + if (path.extname(kit.files.serviceWorker)) { + exclude.push(config_relative(kit.files.serviceWorker)); + } else { + exclude.push(config_relative(`${kit.files.serviceWorker}.js`)); + exclude.push(config_relative(`${kit.files.serviceWorker}/**/*.js`)); + exclude.push(config_relative(`${kit.files.serviceWorker}.ts`)); + exclude.push(config_relative(`${kit.files.serviceWorker}/**/*.ts`)); + exclude.push(config_relative(`${kit.files.serviceWorker}.d.ts`)); + exclude.push(config_relative(`${kit.files.serviceWorker}/**/*.d.ts`)); + } + + const config = { + compilerOptions: { + // generated options + paths: { + ...get_tsconfig_paths(kit), + '$app/types': ['./types/index.d.ts'] + }, + rootDirs: [config_relative('.'), './types'], + + // essential options + // svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript + // to enforce using \`import type\` instead of \`import\` for Types. + // Also, TypeScript doesn't know about import usages in the template because it only sees the + // script of a Svelte file. Therefore preserve all value imports. + verbatimModuleSyntax: true, + // Vite compiles modules one at a time + isolatedModules: true, + + // This is required for svelte-package to work as expected + // Can be overwritten + lib: ['esnext', 'DOM', 'DOM.Iterable'], + moduleResolution: 'bundler', + module: 'esnext', + noEmit: true, // prevent tsconfig error "overwriting input files" - Vite handles the build and ignores this + target: 'esnext' + }, + include: [...include], + exclude + }; + + return kit.typescript.config(config) ?? config; +} + +/** @param {string} cwd */ +function load_user_tsconfig(cwd) { + const file = maybe_file(cwd, 'tsconfig.json') || maybe_file(cwd, 'jsconfig.json'); + + if (!file) return; + + // we have to eval the file, since it's not parseable as JSON (contains comments) + const json = fs.readFileSync(file, 'utf-8'); + + return { + kind: path.basename(file), + options: (0, eval)(`(${json})`) + }; +} + +/** + * @param {string} cwd + * @param {string} out + * @param {{ kind: string, options: any }} config + */ +function validate_user_config(cwd, out, config) { + // we need to check that the user's tsconfig extends the framework config + const extend = config.options.extends; + const extends_framework_config = + typeof extend === 'string' + ? path.resolve(cwd, extend) === out + : Array.isArray(extend) + ? extend.some((e) => path.resolve(cwd, e) === out) + : false; + + const options = config.options.compilerOptions || {}; + + if (extends_framework_config) { + const { paths, baseUrl } = options; + + if (baseUrl || paths) { + console.warn( + colors + .bold() + .yellow( + `You have specified a baseUrl and/or paths in your ${config.kind} which interferes with SvelteKit's auto-generated tsconfig.json. ` + + 'Remove it to avoid problems with intellisense. For path aliases, use `kit.alias` instead: https://svelte.dev/docs/kit/configuration#alias' + ) + ); + } + } else { + let relative = posixify(path.relative('.', out)); + if (!relative.startsWith('./')) relative = './' + relative; + + console.warn( + colors + .bold() + .yellow(`Your ${config.kind} should extend the configuration generated by SvelteKit:`) + ); + console.warn(`{\n "extends": "${relative}"\n}`); + } +} + +// +const alias_regex = /^(.+?)(\/\*)?$/; +// +const value_regex = /^(.*?)((\/\*)|(\.\w+))?$/; + +/** + * Generates tsconfig path aliases from kit's aliases. + * Related to vite alias creation. + * + * @param {import('types').ValidatedKitConfig} config + */ +function get_tsconfig_paths(config) { + /** @param {string} file */ + const config_relative = (file) => { + let relative_path = path.relative(config.outDir, file); + if (!relative_path.startsWith('..')) { + relative_path = './' + relative_path; + } + return posixify(relative_path); + }; + + const alias = { ...config.alias }; + if (fs.existsSync(project_relative(config.files.lib))) { + alias['$lib'] = project_relative(config.files.lib); + } + + /** @type {Record} */ + const paths = {}; + + for (const [key, value] of Object.entries(alias)) { + const key_match = alias_regex.exec(key); + if (!key_match) throw new Error(`Invalid alias key: ${key}`); + + const value_match = value_regex.exec(value); + if (!value_match) throw new Error(`Invalid alias value: ${value}`); + + const rel_path = config_relative(remove_trailing_slashstar(value)); + const slashstar = key_match[2]; + + if (slashstar) { + paths[key] = [rel_path + '/*']; + } else { + paths[key] = [rel_path]; + const fileending = value_match[4]; + + if (!fileending && !(key + '/*' in alias)) { + paths[key + '/*'] = [rel_path + '/*']; + } + } + } + + return paths; +} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/sync/write_types/index.js b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_types/index.js new file mode 100644 index 0000000..bbf63ec --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/sync/write_types/index.js @@ -0,0 +1,869 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; +import MagicString from 'magic-string'; +import { posixify, rimraf, walk } from '../../../utils/filesystem.js'; +import { compact } from '../../../utils/array.js'; +import { ts } from '../ts.js'; +const remove_relative_parent_traversals = (/** @type {string} */ path) => + path.replace(/\.\.\//g, ''); +const is_whitespace = (/** @type {string} */ char) => /\s/.test(char); + +/** + * @typedef {{ + * file_name: string; + * modified: boolean; + * code: string; + * exports: any[]; + * } | null} Proxy + * + * @typedef {{ + * server: Proxy, + * universal: Proxy + * }} Proxies + * + * @typedef {Map} RoutesMap + */ + +const cwd = process.cwd(); + +/** + * Creates types for the whole manifest + * @param {import('types').ValidatedConfig} config + * @param {import('types').ManifestData} manifest_data + */ +export function write_all_types(config, manifest_data) { + if (!ts) return; + + const types_dir = `${config.kit.outDir}/types`; + + // empty out files that no longer need to exist + const routes_dir = remove_relative_parent_traversals( + posixify(path.relative('.', config.kit.files.routes)) + ); + const expected_directories = new Set( + manifest_data.routes.map((route) => path.join(routes_dir, route.id)) + ); + + if (fs.existsSync(types_dir)) { + for (const file of walk(types_dir)) { + const dir = path.dirname(file); + if (!expected_directories.has(dir)) { + rimraf(path.join(types_dir, file)); + } + } + } + + // Read/write meta data on each invocation, not once per node process, + // it could be invoked by another process in the meantime. + const meta_data_file = `${types_dir}/route_meta_data.json`; + const has_meta_data = fs.existsSync(meta_data_file); + const meta_data = has_meta_data + ? /** @type {Record} */ (JSON.parse(fs.readFileSync(meta_data_file, 'utf-8'))) + : {}; + const routes_map = create_routes_map(manifest_data); + // For each directory, write $types.d.ts + for (const route of manifest_data.routes) { + if (!route.leaf && !route.layout && !route.endpoint) continue; // nothing to do + + const outdir = path.join(config.kit.outDir, 'types', routes_dir, route.id); + + // check if the types are out of date + /** @type {string[]} */ + const input_files = []; + + /** @type {import('types').PageNode | null} */ + let node = route.leaf; + while (node) { + if (node.universal) input_files.push(node.universal); + if (node.server) input_files.push(node.server); + node = node.parent ?? null; + } + + /** @type {import('types').PageNode | null} */ + node = route.layout; + while (node) { + if (node.universal) input_files.push(node.universal); + if (node.server) input_files.push(node.server); + node = node.parent ?? null; + } + + if (route.endpoint) { + input_files.push(route.endpoint.file); + } + + try { + fs.mkdirSync(outdir, { recursive: true }); + } catch {} + + const output_files = compact( + fs.readdirSync(outdir).map((name) => { + const stats = fs.statSync(path.join(outdir, name)); + if (stats.isDirectory()) return; + return { + name, + updated: stats.mtimeMs + }; + }) + ); + + const source_last_updated = Math.max( + // ctimeMs includes move operations whereas mtimeMs does not + ...input_files.map((file) => fs.statSync(file).ctimeMs) + ); + const types_last_updated = Math.max(...output_files.map((file) => file.updated)); + + const should_generate = + // source files were generated more recently than the types + source_last_updated > types_last_updated || + // no meta data file exists yet + !has_meta_data || + // some file was deleted + !meta_data[route.id]?.every((file) => input_files.includes(file)); + + if (should_generate) { + // track which old files end up being surplus to requirements + const to_delete = new Set(output_files.map((file) => file.name)); + update_types(config, routes_map, route, to_delete); + meta_data[route.id] = input_files; + } + } + + fs.writeFileSync(meta_data_file, JSON.stringify(meta_data, null, '\t')); +} + +/** + * Creates types related to the given file. This should only be called + * if the file in question was edited, not if it was created/deleted/moved. + * @param {import('types').ValidatedConfig} config + * @param {import('types').ManifestData} manifest_data + * @param {string} file + */ +export function write_types(config, manifest_data, file) { + if (!ts) return; + + if (!path.basename(file).startsWith('+')) { + // Not a route file + return; + } + + const id = '/' + posixify(path.relative(config.kit.files.routes, path.dirname(file))); + + const route = manifest_data.routes.find((route) => route.id === id); + if (!route) return; + if (!route.leaf && !route.layout && !route.endpoint) return; // nothing to do + + update_types(config, create_routes_map(manifest_data), route); +} + +/** + * Collect all leafs into a leaf -> route map + * @param {import('types').ManifestData} manifest_data + */ +function create_routes_map(manifest_data) { + /** @type {RoutesMap} */ + const map = new Map(); + for (const route of manifest_data.routes) { + if (route.leaf) { + map.set(route.leaf, { route, proxies: { server: null, universal: null } }); + } + } + return map; +} + +/** + * Update types for a specific route + * @param {import('types').ValidatedConfig} config + * @param {RoutesMap} routes + * @param {import('types').RouteData} route + * @param {Set} [to_delete] + */ +function update_types(config, routes, route, to_delete = new Set()) { + const routes_dir = remove_relative_parent_traversals( + posixify(path.relative('.', config.kit.files.routes)) + ); + const outdir = path.join(config.kit.outDir, 'types', routes_dir, route.id); + + // now generate new types + const imports = ["import type * as Kit from '@sveltejs/kit';"]; + + /** @type {string[]} */ + const declarations = []; + + /** @type {string[]} */ + const exports = []; + + // add 'Expand' helper + // Makes sure a type is "repackaged" and therefore more readable + declarations.push('type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never;'); + + // returns the predicate of a matcher's type guard - or string if there is no type guard + declarations.push( + 'type MatcherParam = M extends (param : string) => param is (infer U extends string) ? U : string;' + ); + + declarations.push( + 'type RouteParams = ' + generate_params_type(route.params, outdir, config) + ';' + ); + + if (route.params.length > 0) { + exports.push( + 'export type EntryGenerator = () => Promise> | Array;' + ); + } + + declarations.push(`type RouteId = '${route.id}';`); + + // These could also be placed in our public types, but it would bloat them unnecessarily and we may want to change these in the future + if (route.layout || route.leaf) { + declarations.push( + // If T extends the empty object, void is also allowed as a return type + 'type MaybeWithVoid = {} extends T ? T | void : T;', + + // Returns the key of the object whose values are required. + 'export type RequiredKeys = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T];', + + // Helper type to get the correct output type for load functions. It should be passed the parent type to check what types from App.PageData are still required. + // If none, void is also allowed as a return type. + 'type OutputDataShape = MaybeWithVoid> & Partial> & Record>', + + // null & {} == null, we need to prevent that in some situations + 'type EnsureDefined = T extends null | undefined ? {} : T;', + + // Takes a union type and returns a union type where each type also has all properties + // of all possible types (typed as undefined), making accessing them more ergonomic + 'type OptionalUnion, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude]?: never } & U : never;', + + // Re-export `Snapshot` from @sveltejs/kit — in future we could use this to infer from the return type of `snapshot.capture` + 'export type Snapshot = Kit.Snapshot;' + ); + } + + if (route.leaf) { + let route_info = routes.get(route.leaf); + if (!route_info) { + // This should be defined, but belts and braces + route_info = { route, proxies: { server: null, universal: null } }; + routes.set(route.leaf, route_info); + } + + const { + declarations: d, + exports: e, + proxies + } = process_node(route.leaf, outdir, true, route_info.proxies); + + exports.push(...e); + declarations.push(...d); + + if (proxies.server) { + route_info.proxies.server = proxies.server; + if (proxies.server?.modified) to_delete.delete(proxies.server.file_name); + } + if (proxies.universal) { + route_info.proxies.universal = proxies.universal; + if (proxies.universal?.modified) to_delete.delete(proxies.universal.file_name); + } + + if (route.leaf.server) { + exports.push( + 'export type Action | void = Record | void> = Kit.Action' + ); + exports.push( + 'export type Actions | void = Record | void> = Kit.Actions' + ); + } + + if (route.leaf.server) { + exports.push( + 'export type PageProps = { params: RouteParams; data: PageData; form: ActionData }' + ); + } else { + exports.push('export type PageProps = { params: RouteParams; data: PageData }'); + } + } + + if (route.layout) { + let all_pages_have_load = true; + /** @type {import('types').RouteParam[]} */ + const layout_params = []; + const ids = ['RouteId']; + + route.layout.child_pages?.forEach((page) => { + const leaf = routes.get(page); + if (leaf) { + if (leaf.route.page) ids.push(`"${leaf.route.id}"`); + + for (const param of leaf.route.params) { + // skip if already added + if (layout_params.some((p) => p.name === param.name)) continue; + layout_params.push({ ...param, optional: true }); + } + + ensureProxies(page, leaf.proxies); + + if ( + // Be defensive - if a proxy doesn't exist (because it couldn't be created), assume a load function exists. + // If we didn't and it's a false negative, the user could wrongfully get a type error on layouts. + (leaf.proxies.server && !leaf.proxies.server.exports.includes('load')) || + (leaf.proxies.universal && !leaf.proxies.universal.exports.includes('load')) + ) { + all_pages_have_load = false; + } + } + if (!page.server && !page.universal) { + all_pages_have_load = false; + } + }); + + if (route.id === '/') { + // root layout is used for fallback error page, where ID can be null + ids.push('null'); + } + + declarations.push(`type LayoutRouteId = ${ids.join(' | ')}`); + + declarations.push( + 'type LayoutParams = RouteParams & ' + generate_params_type(layout_params, outdir, config) + ); + + const { + exports: e, + declarations: d, + proxies + } = process_node( + route.layout, + outdir, + false, + { server: null, universal: null }, + all_pages_have_load + ); + + exports.push(...e); + declarations.push(...d); + + if (proxies.server?.modified) to_delete.delete(proxies.server.file_name); + if (proxies.universal?.modified) to_delete.delete(proxies.universal.file_name); + + exports.push( + 'export type LayoutProps = { params: LayoutParams; data: LayoutData; children: import("svelte").Snippet }' + ); + } + + if (route.endpoint) { + exports.push('export type RequestHandler = Kit.RequestHandler;'); + } + + if (route.leaf?.server || route.layout?.server || route.endpoint) { + exports.push('export type RequestEvent = Kit.RequestEvent;'); + } + + const output = [imports.join('\n'), declarations.join('\n'), exports.join('\n')] + .filter(Boolean) + .join('\n\n'); + + fs.writeFileSync(`${outdir}/$types.d.ts`, output); + to_delete.delete('$types.d.ts'); + + for (const file of to_delete) { + fs.unlinkSync(path.join(outdir, file)); + } +} + +/** + * @param {import('types').PageNode} node + * @param {string} outdir + * @param {boolean} is_page + * @param {Proxies} proxies + * @param {boolean} [all_pages_have_load] + */ +function process_node(node, outdir, is_page, proxies, all_pages_have_load = true) { + const params = `${is_page ? 'Route' : 'Layout'}Params`; + const prefix = is_page ? 'Page' : 'Layout'; + + const route_id = is_page ? 'RouteId' : 'LayoutRouteId'; + + /** @type {string[]} */ + const declarations = []; + /** @type {string[]} */ + const exports = []; + + /** @type {string} */ + let server_data; + /** @type {string} */ + let data; + + ensureProxies(node, proxies); + + if (node.server) { + const basename = path.basename(node.server); + const proxy = proxies.server; + if (proxy?.modified) { + fs.writeFileSync(`${outdir}/proxy${basename}`, proxy.code); + } + + server_data = get_data_type(node.server, 'null', proxy, true); + + const parent_type = `${prefix}ServerParentData`; + + declarations.push(`type ${parent_type} = ${get_parent_type(node, 'LayoutServerData')};`); + + // +page.js load present -> server can return all-optional data + const output_data_shape = + node.universal || (!is_page && all_pages_have_load) + ? 'Partial & Record | void' + : `OutputDataShape<${parent_type}>`; + exports.push( + `export type ${prefix}ServerLoad = Kit.ServerLoad<${params}, ${parent_type}, OutputData, ${route_id}>;` + ); + + exports.push(`export type ${prefix}ServerLoadEvent = Parameters<${prefix}ServerLoad>[0];`); + + if (is_page) { + let type = 'unknown'; + if (proxy && proxy.exports.includes('actions')) { + // If the file wasn't tweaked, we can use the return type of the original file. + // The advantage is that type updates are reflected without saving. + const from = proxy.modified + ? `./proxy${replace_ext_with_js(basename)}` + : path_to_original(outdir, node.server); + + exports.push( + 'type ExcludeActionFailure = T extends Kit.ActionFailure ? never : T extends void ? never : T;', + 'type ActionsSuccess any>> = { [Key in keyof T]: ExcludeActionFailure>>; }[keyof T];', + 'type ExtractActionFailure = T extends Kit.ActionFailure ? X extends void ? never : X : never;', + 'type ActionsFailure any>> = { [Key in keyof T]: Exclude>>, void>; }[keyof T];', + `type ActionsExport = typeof import('${from}').actions`, + 'export type SubmitFunction = Kit.SubmitFunction>, Expand>>' + ); + + type = 'Expand> | null'; + } + exports.push(`export type ActionData = ${type};`); + } + } else { + server_data = 'null'; + } + exports.push(`export type ${prefix}ServerData = ${server_data};`); + + const parent_type = `${prefix}ParentData`; + declarations.push(`type ${parent_type} = ${get_parent_type(node, 'LayoutData')};`); + + if (node.universal) { + const proxy = proxies.universal; + if (proxy?.modified) { + fs.writeFileSync(`${outdir}/proxy${path.basename(node.universal)}`, proxy.code); + } + + const type = get_data_type( + node.universal, + `${parent_type} & EnsureDefined<${prefix}ServerData>`, + proxy + ); + + data = `Expand & OptionalUnion>>`; + + const output_data_shape = + !is_page && all_pages_have_load + ? 'Partial & Record | void' + : `OutputDataShape<${parent_type}>`; + exports.push( + `export type ${prefix}Load = Kit.Load<${params}, ${prefix}ServerData, ${parent_type}, OutputData, ${route_id}>;` + ); + + exports.push(`export type ${prefix}LoadEvent = Parameters<${prefix}Load>[0];`); + } else if (server_data === 'null') { + data = `Expand<${parent_type}>`; + } else { + data = `Expand & EnsureDefined<${prefix}ServerData>>`; + } + + exports.push(`export type ${prefix}Data = ${data};`); + + return { declarations, exports, proxies }; + + /** + * @param {string} file_path + * @param {string} fallback + * @param {Proxy} proxy + * @param {boolean} expand + */ + function get_data_type(file_path, fallback, proxy, expand = false) { + if (proxy) { + if (proxy.exports.includes('load')) { + // If the file wasn't tweaked, we can use the return type of the original file. + // The advantage is that type updates are reflected without saving. + const from = proxy.modified + ? `./proxy${replace_ext_with_js(path.basename(file_path))}` + : path_to_original(outdir, file_path); + const type = `Kit.LoadProperties>>`; + return expand ? `Expand>>` : type; + } else { + return fallback; + } + } else { + return 'unknown'; + } + } +} + +/** + * This function populates the proxies object, if necessary and not already done. + * Proxies are used to tweak the code of a file before it's typechecked. + * They are needed in two places - when generating the types for a page or layout. + * To not do the same work twice, we generate the proxies once and pass them around. + * + * @param {import('types').PageNode} node + * @param {Proxies} proxies + */ +function ensureProxies(node, proxies) { + if (node.server && !proxies.server) { + proxies.server = createProxy(node.server, true); + } + + if (node.universal && !proxies.universal) { + proxies.universal = createProxy(node.universal, false); + } +} + +/** + * @param {string} file_path + * @param {boolean} is_server + * @returns {Proxy} + */ +function createProxy(file_path, is_server) { + const proxy = tweak_types(fs.readFileSync(file_path, 'utf8'), is_server); + if (proxy) { + return { + ...proxy, + file_name: `proxy${path.basename(file_path)}` + }; + } else { + return null; + } +} + +/** + * Get the parent type string by recursively looking up the parent layout and accumulate them to one type. + * @param {import('types').PageNode} node + * @param {string} type + */ +function get_parent_type(node, type) { + const parent_imports = []; + + let parent = node.parent; + + while (parent) { + const d = node.depth - parent.depth; + // unshift because we need it the other way round for the import string + parent_imports.unshift( + `${d === 0 ? '' : `import('${'../'.repeat(d)}${'$types.js'}').`}${type}` + ); + parent = parent.parent; + } + + let parent_str = `EnsureDefined<${parent_imports[0] || '{}'}>`; + for (let i = 1; i < parent_imports.length; i++) { + // Omit is necessary because a parent could have a property with the same key which would + // cause a type conflict. At runtime the child overwrites the parent property in this case, + // so reflect that in the type definition. + // EnsureDefined is necessary because {something: string} & null becomes null. + // Output types of server loads can be null but when passed in through the `parent` parameter they are the empty object instead. + parent_str = `Omit<${parent_str}, keyof ${parent_imports[i]}> & EnsureDefined<${parent_imports[i]}>`; + } + return parent_str; +} + +/** + * @param {string} outdir + * @param {string} file_path + */ +function path_to_original(outdir, file_path) { + return posixify(path.relative(outdir, path.join(cwd, replace_ext_with_js(file_path)))); +} + +/** + * @param {string} file_path + */ +function replace_ext_with_js(file_path) { + // Another extension than `.js` (or nothing, but that fails with node16 moduleResolution) + // will result in TS failing to lookup the file + const ext = path.extname(file_path); + return file_path.slice(0, -ext.length) + '.js'; +} + +/** + * @param {import('types').RouteParam[]} params + * @param {string} outdir + * @param {import('types').ValidatedConfig} config + */ +function generate_params_type(params, outdir, config) { + /** @param {string} matcher */ + const path_to_matcher = (matcher) => + posixify(path.relative(outdir, path.join(config.kit.files.params, matcher + '.js'))); + + return `{ ${params + .map( + (param) => + `${param.name}${param.optional ? '?' : ''}: ${ + param.matcher + ? `MatcherParam` + : 'string' + }` + ) + .join('; ')} }`; +} + +/** + * @param {string} content + * @param {boolean} is_server + * @returns {Omit, 'file_name'> | null} + */ +export function tweak_types(content, is_server) { + const names = new Set(is_server ? ['load', 'actions'] : ['load']); + + try { + let modified = false; + + const ast = ts.createSourceFile( + 'filename.ts', + content, + ts.ScriptTarget.Latest, + false, + ts.ScriptKind.TS + ); + + const code = new MagicString(content); + + const exports = new Map(); + + ast.forEachChild((node) => { + if ( + ts.isExportDeclaration(node) && + node.exportClause && + ts.isNamedExports(node.exportClause) + ) { + node.exportClause.elements.forEach((element) => { + const exported = element.name; + if (names.has(element.name.text)) { + const local = element.propertyName || element.name; + exports.set(exported.text, local.text); + } + }); + } + + if ( + ts.canHaveModifiers(node) && + ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword) + ) { + if (ts.isFunctionDeclaration(node) && node.name?.text && names.has(node.name?.text)) { + exports.set(node.name.text, node.name.text); + } + + if (ts.isVariableStatement(node)) { + node.declarationList.declarations.forEach((declaration) => { + if (ts.isIdentifier(declaration.name) && names.has(declaration.name.text)) { + exports.set(declaration.name.text, declaration.name.text); + } + }); + } + } + }); + + /** + * @param {import('typescript').Node} node + * @param {import('typescript').Node} value + */ + function replace_jsdoc_type_tags(node, value) { + let _modified = false; + // @ts-ignore + if (node.jsDoc) { + // @ts-ignore + for (const comment of node.jsDoc) { + for (const tag of comment.tags ?? []) { + if (ts.isJSDocTypeTag(tag)) { + const is_fn = + ts.isFunctionDeclaration(value) || + ts.isFunctionExpression(value) || + ts.isArrowFunction(value); + + if (is_fn && value.parameters?.length > 0) { + const name = ts.isIdentifier(value.parameters[0].name) + ? value.parameters[0].name.text + : 'event'; + code.overwrite(tag.tagName.pos, tag.tagName.end, 'param'); + code.prependRight(tag.typeExpression.pos + 1, 'Parameters<'); + code.appendLeft(tag.typeExpression.end - 1, '>[0]'); + code.appendLeft(tag.typeExpression.end, ` ${name}`); + } else { + code.overwrite(tag.pos, tag.end, ''); + } + _modified = true; + } + } + } + } + modified = modified || _modified; + return _modified; + } + + ast.forEachChild((node) => { + if (ts.isFunctionDeclaration(node) && node.name?.text && node.name?.text === 'load') { + // remove JSDoc comment above `export function load ...` + replace_jsdoc_type_tags(node, node); + } + + if (ts.isVariableStatement(node)) { + // remove JSDoc comment above `export const load = ...` + if ( + ts.isIdentifier(node.declarationList.declarations[0].name) && + names.has(node.declarationList.declarations[0].name.text) && + node.declarationList.declarations[0].initializer + ) { + replace_jsdoc_type_tags(node, node.declarationList.declarations[0].initializer); + } + + for (const declaration of node.declarationList.declarations) { + if ( + ts.isIdentifier(declaration.name) && + declaration.name.text === 'load' && + declaration.initializer + ) { + // edge case — remove JSDoc comment above individual export + replace_jsdoc_type_tags(declaration, declaration.initializer); + + // remove type from `export const load: Load ...` + if (declaration.type) { + let a = declaration.type.pos; + const b = declaration.type.end; + while (is_whitespace(content[a])) a += 1; + + const type = content.slice(a, b); + code.remove(declaration.name.end, declaration.type.end); + + const rhs = declaration.initializer; + + if ( + rhs && + (ts.isArrowFunction(rhs) || ts.isFunctionExpression(rhs)) && + rhs.parameters.length + ) { + const arg = rhs.parameters[0]; + const add_parens = content[arg.pos - 1] !== '('; + + if (add_parens) code.prependRight(arg.pos, '('); + + if (arg && !arg.type) { + code.appendLeft( + arg.name.end, + `: Parameters<${type}>[0]` + (add_parens ? ')' : '') + ); + } else { + // prevent "type X is imported but not used" (isn't silenced by @ts-nocheck) when svelte-check runs + code.append(`;null as any as ${type};`); + } + } else { + // prevent "type X is imported but not used" (isn't silenced by @ts-nocheck) when svelte-check runs + code.append(`;null as any as ${type};`); + } + + modified = true; + } + } else if ( + is_server && + ts.isIdentifier(declaration.name) && + declaration.name?.text === 'actions' && + declaration.initializer + ) { + // remove JSDoc comment from `export const actions = ..` + const removed = replace_jsdoc_type_tags(node, declaration.initializer); + // ... and move type to each individual action + if (removed) { + const rhs = declaration.initializer; + if (ts.isObjectLiteralExpression(rhs)) { + for (const prop of rhs.properties) { + if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) { + const rhs = prop.initializer; + const replaced = replace_jsdoc_type_tags(prop, rhs); + if ( + !replaced && + rhs && + (ts.isArrowFunction(rhs) || ts.isFunctionExpression(rhs)) && + rhs.parameters?.[0] + ) { + const name = ts.isIdentifier(rhs.parameters[0].name) + ? rhs.parameters[0].name.text + : 'event'; + code.prependRight( + rhs.pos, + `/** @param {import('./$types').RequestEvent} ${name} */ ` + ); + } + } + } + } + } + + // remove type from `export const actions: Actions ...` + if (declaration.type) { + let a = declaration.type.pos; + const b = declaration.type.end; + while (is_whitespace(content[a])) a += 1; + + const type = content.slice(a, b); + code.remove(declaration.name.end, declaration.type.end); + code.append(`;null as any as ${type};`); + modified = true; + + // ... and move type to each individual action + const rhs = declaration.initializer; + if (ts.isObjectLiteralExpression(rhs)) { + for (const prop of rhs.properties) { + if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) { + const rhs = prop.initializer; + + if ( + rhs && + (ts.isArrowFunction(rhs) || ts.isFunctionExpression(rhs)) && + rhs.parameters.length + ) { + const arg = rhs.parameters[0]; + const add_parens = content[arg.pos - 1] !== '('; + + if (add_parens) code.prependRight(arg.pos, '('); + + if (arg && !arg.type) { + code.appendLeft( + arg.name.end, + ": import('./$types').RequestEvent" + (add_parens ? ')' : '') + ); + } + } + } + } + } + } + } + } + } + }); + + if (modified) { + // Ignore all type errors so they don't show up twice when svelte-check runs + // Account for possible @ts-check which would overwrite @ts-nocheck + if (code.original.startsWith('// @ts-check')) { + code.prependLeft('// @ts-check'.length, '\n// @ts-nocheck\n'); + } else { + code.prepend('// @ts-nocheck\n'); + } + } + + return { + modified, + code: code.toString(), + exports: Array.from(exports.keys()) + }; + } catch { + return null; + } +} diff --git a/frontend/node_modules/@sveltejs/kit/src/core/utils.js b/frontend/node_modules/@sveltejs/kit/src/core/utils.js new file mode 100644 index 0000000..668306e --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/core/utils.js @@ -0,0 +1,87 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; +import { fileURLToPath } from 'node:url'; +import colors from 'kleur'; +import { posixify, to_fs } from '../utils/filesystem.js'; + +/** + * Resolved path of the `runtime` directory + * + * TODO Windows issue: + * Vite or sth else somehow sets the driver letter inconsistently to lower or upper case depending on the run environment. + * In playwright debug mode run through VS Code this a root-to-lowercase conversion is needed in order for the tests to run. + * If we do this conversion in other cases it has the opposite effect though and fails. + */ +export const runtime_directory = posixify(fileURLToPath(new URL('../runtime', import.meta.url))); + +/** + * This allows us to import SvelteKit internals that aren't exposed via `pkg.exports` in a + * way that works whether `@sveltejs/kit` is installed inside the project's `node_modules` + * or in a workspace root + */ +export const runtime_base = runtime_directory.startsWith(process.cwd()) + ? `/${path.relative('.', runtime_directory)}` + : to_fs(runtime_directory); + +function noop() {} + +/** @param {{ verbose: boolean }} opts */ +export function logger({ verbose }) { + /** @type {import('types').Logger} */ + const log = (msg) => console.log(msg.replace(/^/gm, ' ')); + + /** @param {string} msg */ + const err = (msg) => console.error(msg.replace(/^/gm, ' ')); + + log.success = (msg) => log(colors.green(`✔ ${msg}`)); + log.error = (msg) => err(colors.bold().red(msg)); + log.warn = (msg) => log(colors.bold().yellow(msg)); + + log.minor = verbose ? (msg) => log(colors.grey(msg)) : noop; + log.info = verbose ? log : noop; + + return log; +} + +/** @param {import('types').ManifestData} manifest_data */ +export function get_mime_lookup(manifest_data) { + /** @type {Record} */ + const mime = {}; + + manifest_data.assets.forEach((asset) => { + if (asset.type) { + const ext = path.extname(asset.file); + mime[ext] = asset.type; + } + }); + + return mime; +} + +/** + * @param {string} dir + * @param {(file: string) => boolean} [filter] + */ +export function list_files(dir, filter) { + /** @type {string[]} */ + const files = []; + + /** @param {string} current */ + function walk(current) { + for (const file of fs.readdirSync(path.resolve(dir, current))) { + const child = path.posix.join(current, file); + if (fs.statSync(path.resolve(dir, child)).isDirectory()) { + walk(child); + } else { + if (!filter || filter(child)) { + files.push(child); + } + } + } + } + + if (fs.existsSync(dir)) walk(''); + + return files; +} diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/hooks/index.js b/frontend/node_modules/@sveltejs/kit/src/exports/hooks/index.js new file mode 100644 index 0000000..98e1e53 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/hooks/index.js @@ -0,0 +1 @@ +export { sequence } from './sequence.js'; diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/hooks/sequence.js b/frontend/node_modules/@sveltejs/kit/src/exports/hooks/sequence.js new file mode 100644 index 0000000..3668c50 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/hooks/sequence.js @@ -0,0 +1,145 @@ +/** @import { Handle, RequestEvent, ResolveOptions } from '@sveltejs/kit' */ +/** @import { MaybePromise } from 'types' */ +import { + merge_tracing, + get_request_store, + with_request_store +} from '@sveltejs/kit/internal/server'; + +/** + * A helper function for sequencing multiple `handle` calls in a middleware-like manner. + * The behavior for the `handle` options is as follows: + * - `transformPageChunk` is applied in reverse order and merged + * - `preload` is applied in forward order, the first option "wins" and no `preload` options after it are called + * - `filterSerializedResponseHeaders` behaves the same as `preload` + * + * ```js + * /// file: src/hooks.server.js + * import { sequence } from '@sveltejs/kit/hooks'; + * + * /// type: import('@sveltejs/kit').Handle + * async function first({ event, resolve }) { + * console.log('first pre-processing'); + * const result = await resolve(event, { + * transformPageChunk: ({ html }) => { + * // transforms are applied in reverse order + * console.log('first transform'); + * return html; + * }, + * preload: () => { + * // this one wins as it's the first defined in the chain + * console.log('first preload'); + * return true; + * } + * }); + * console.log('first post-processing'); + * return result; + * } + * + * /// type: import('@sveltejs/kit').Handle + * async function second({ event, resolve }) { + * console.log('second pre-processing'); + * const result = await resolve(event, { + * transformPageChunk: ({ html }) => { + * console.log('second transform'); + * return html; + * }, + * preload: () => { + * console.log('second preload'); + * return true; + * }, + * filterSerializedResponseHeaders: () => { + * // this one wins as it's the first defined in the chain + * console.log('second filterSerializedResponseHeaders'); + * return true; + * } + * }); + * console.log('second post-processing'); + * return result; + * } + * + * export const handle = sequence(first, second); + * ``` + * + * The example above would print: + * + * ``` + * first pre-processing + * first preload + * second pre-processing + * second filterSerializedResponseHeaders + * second transform + * first transform + * second post-processing + * first post-processing + * ``` + * + * @param {...Handle} handlers The chain of `handle` functions + * @returns {Handle} + */ +export function sequence(...handlers) { + const length = handlers.length; + if (!length) return ({ event, resolve }) => resolve(event); + + return ({ event, resolve }) => { + const { state } = get_request_store(); + return apply_handle(0, event, {}); + + /** + * @param {number} i + * @param {RequestEvent} event + * @param {ResolveOptions | undefined} parent_options + * @returns {MaybePromise} + */ + function apply_handle(i, event, parent_options) { + const handle = handlers[i]; + + return state.tracing.record_span({ + name: `sveltekit.handle.sequenced.${handle.name ? handle.name : i}`, + attributes: {}, + fn: async (current) => { + const traced_event = merge_tracing(event, current); + return await with_request_store({ event: traced_event, state }, () => + handle({ + event: traced_event, + resolve: (event, options) => { + /** @type {ResolveOptions['transformPageChunk']} */ + const transformPageChunk = async ({ html, done }) => { + if (options?.transformPageChunk) { + html = (await options.transformPageChunk({ html, done })) ?? ''; + } + + if (parent_options?.transformPageChunk) { + html = (await parent_options.transformPageChunk({ html, done })) ?? ''; + } + + return html; + }; + + /** @type {ResolveOptions['filterSerializedResponseHeaders']} */ + const filterSerializedResponseHeaders = + parent_options?.filterSerializedResponseHeaders ?? + options?.filterSerializedResponseHeaders; + + /** @type {ResolveOptions['preload']} */ + const preload = parent_options?.preload ?? options?.preload; + + return i < length - 1 + ? apply_handle(i + 1, event, { + transformPageChunk, + filterSerializedResponseHeaders, + preload + }) + : resolve(event, { + transformPageChunk, + filterSerializedResponseHeaders, + preload + }); + } + }) + ); + } + }); + } + }; +} diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/index.js b/frontend/node_modules/@sveltejs/kit/src/exports/index.js new file mode 100644 index 0000000..5cc5429 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/index.js @@ -0,0 +1,308 @@ +/** @import { StandardSchemaV1 } from '@standard-schema/spec' */ + +import { HttpError, Redirect, ActionFailure, ValidationError } from './internal/index.js'; +import { BROWSER, DEV } from 'esm-env'; +import { + add_data_suffix, + add_resolution_suffix, + has_data_suffix, + has_resolution_suffix, + strip_data_suffix, + strip_resolution_suffix +} from '../runtime/pathname.js'; +import { text_encoder } from '../runtime/utils.js'; + +export { VERSION } from '../version.js'; + +// TODO 3.0: remove these types as they are not used anymore (we can't remove them yet because that would be a breaking change) +/** + * @template {number} TNumber + * @template {any[]} [TArray=[]] + * @typedef {TNumber extends TArray['length'] ? TArray[number] : LessThan} LessThan + */ + +/** + * @template {number} TStart + * @template {number} TEnd + * @typedef {Exclude, LessThan>} NumericRange + */ + +// Keep the status codes as `number` because restricting to certain numbers makes it unnecessarily hard to use compared to the benefits +// (we have runtime errors already to check for invalid codes). Also see https://github.com/sveltejs/kit/issues/11780 + +// we have to repeat the JSDoc because the display for function overloads is broken +// see https://github.com/microsoft/TypeScript/issues/55056 + +/** + * Throws an error with a HTTP status code and an optional message. + * When called during request handling, this will cause SvelteKit to + * return an error response without invoking `handleError`. + * Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it. + * @param {number} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599. + * @param {App.Error} body An object that conforms to the App.Error type. If a string is passed, it will be used as the message property. + * @overload + * @param {number} status + * @param {App.Error} body + * @return {never} + * @throws {HttpError} This error instructs SvelteKit to initiate HTTP error handling. + * @throws {Error} If the provided status is invalid (not between 400 and 599). + */ +/** + * Throws an error with a HTTP status code and an optional message. + * When called during request handling, this will cause SvelteKit to + * return an error response without invoking `handleError`. + * Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it. + * @param {number} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599. + * @param {{ message: string } extends App.Error ? App.Error | string | undefined : never} [body] An object that conforms to the App.Error type. If a string is passed, it will be used as the message property. + * @overload + * @param {number} status + * @param {{ message: string } extends App.Error ? App.Error | string | undefined : never} [body] + * @return {never} + * @throws {HttpError} This error instructs SvelteKit to initiate HTTP error handling. + * @throws {Error} If the provided status is invalid (not between 400 and 599). + */ +/** + * Throws an error with a HTTP status code and an optional message. + * When called during request handling, this will cause SvelteKit to + * return an error response without invoking `handleError`. + * Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it. + * @param {number} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599. + * @param {{ message: string } extends App.Error ? App.Error | string | undefined : never} body An object that conforms to the App.Error type. If a string is passed, it will be used as the message property. + * @return {never} + * @throws {HttpError} This error instructs SvelteKit to initiate HTTP error handling. + * @throws {Error} If the provided status is invalid (not between 400 and 599). + */ +export function error(status, body) { + if ((!BROWSER || DEV) && (isNaN(status) || status < 400 || status > 599)) { + throw new Error(`HTTP error status codes must be between 400 and 599 — ${status} is invalid`); + } + + throw new HttpError(status, body); +} + +/** + * Checks whether this is an error thrown by {@link error}. + * @template {number} T + * @param {unknown} e + * @param {T} [status] The status to filter for. + * @return {e is (HttpError & { status: T extends undefined ? never : T })} + */ +export function isHttpError(e, status) { + if (!(e instanceof HttpError)) return false; + return !status || e.status === status; +} + +/** + * Redirect a request. When called during request handling, SvelteKit will return a redirect response. + * Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it. + * + * Most common status codes: + * * `303 See Other`: redirect as a GET request (often used after a form POST request) + * * `307 Temporary Redirect`: redirect will keep the request method + * * `308 Permanent Redirect`: redirect will keep the request method, SEO will be transferred to the new page + * + * [See all redirect status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages) + * + * @param {300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number)} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308. + * @param {string | URL} location The location to redirect to. + * @throws {Redirect} This error instructs SvelteKit to redirect to the specified location. + * @throws {Error} If the provided status is invalid. + * @return {never} + */ +export function redirect(status, location) { + if ((!BROWSER || DEV) && (isNaN(status) || status < 300 || status > 308)) { + throw new Error('Invalid status code'); + } + + throw new Redirect( + // @ts-ignore + status, + location.toString() + ); +} + +/** + * Checks whether this is a redirect thrown by {@link redirect}. + * @param {unknown} e The object to check. + * @return {e is Redirect} + */ +export function isRedirect(e) { + return e instanceof Redirect; +} + +/** + * Create a JSON `Response` object from the supplied data. + * @param {any} data The value that will be serialized as JSON. + * @param {ResponseInit} [init] Options such as `status` and `headers` that will be added to the response. `Content-Type: application/json` and `Content-Length` headers will be added automatically. + */ +export function json(data, init) { + // TODO deprecate this in favour of `Response.json` when it's + // more widely supported + const body = JSON.stringify(data); + + // we can't just do `text(JSON.stringify(data), init)` because + // it will set a default `content-type` header. duplicated code + // means less duplicated work + const headers = new Headers(init?.headers); + if (!headers.has('content-length')) { + headers.set('content-length', text_encoder.encode(body).byteLength.toString()); + } + + if (!headers.has('content-type')) { + headers.set('content-type', 'application/json'); + } + + return new Response(body, { + ...init, + headers + }); +} + +/** + * Create a `Response` object from the supplied body. + * @param {string} body The value that will be used as-is. + * @param {ResponseInit} [init] Options such as `status` and `headers` that will be added to the response. A `Content-Length` header will be added automatically. + */ +export function text(body, init) { + const headers = new Headers(init?.headers); + if (!headers.has('content-length')) { + const encoded = text_encoder.encode(body); + headers.set('content-length', encoded.byteLength.toString()); + return new Response(encoded, { + ...init, + headers + }); + } + + return new Response(body, { + ...init, + headers + }); +} + +/** + * Create an `ActionFailure` object. Call when form submission fails. + * @param {number} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599. + * @overload + * @param {number} status + * @returns {import('./public.js').ActionFailure} + */ +/** + * Create an `ActionFailure` object. Call when form submission fails. + * @template [T=undefined] + * @param {number} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599. + * @param {T} data Data associated with the failure (e.g. validation errors) + * @overload + * @param {number} status + * @param {T} data + * @returns {import('./public.js').ActionFailure} + */ +/** + * Create an `ActionFailure` object. Call when form submission fails. + * @param {number} status + * @param {any} [data] + * @returns {import('./public.js').ActionFailure} + */ +export function fail(status, data) { + // @ts-expect-error unique symbol missing + return new ActionFailure(status, data); +} + +/** + * Checks whether this is an action failure thrown by {@link fail}. + * @param {unknown} e The object to check. + * @return {e is import('./public.js').ActionFailure} + */ +export function isActionFailure(e) { + return e instanceof ActionFailure; +} + +/** + * Use this to throw a validation error to imperatively fail form validation. + * Can be used in combination with `issue` passed to form actions to create field-specific issues. + * + * @example + * ```ts + * import { invalid } from '@sveltejs/kit'; + * import { form } from '$app/server'; + * import { tryLogin } from '$lib/server/auth'; + * import * as v from 'valibot'; + * + * export const login = form( + * v.object({ name: v.string(), _password: v.string() }), + * async ({ name, _password }) => { + * const success = tryLogin(name, _password); + * if (!success) { + * invalid('Incorrect username or password'); + * } + * + * // ... + * } + * ); + * ``` + * @param {...(StandardSchemaV1.Issue | string)} issues + * @returns {never} + * @since 2.47.3 + */ +export function invalid(...issues) { + throw new ValidationError( + issues.map((issue) => (typeof issue === 'string' ? { message: issue } : issue)) + ); +} + +/** + * Checks whether this is an validation error thrown by {@link invalid}. + * @param {unknown} e The object to check. + * @return {e is import('./public.js').ActionFailure} + * @since 2.47.3 + */ +export function isValidationError(e) { + return e instanceof ValidationError; +} + +/** + * Strips possible SvelteKit-internal suffixes and trailing slashes from the URL pathname. + * Returns the normalized URL as well as a method for adding the potential suffix back + * based on a new pathname (possibly including search) or URL. + * ```js + * import { normalizeUrl } from '@sveltejs/kit'; + * + * const { url, denormalize } = normalizeUrl('/blog/post/__data.json'); + * console.log(url.pathname); // /blog/post + * console.log(denormalize('/blog/post/a')); // /blog/post/a/__data.json + * ``` + * @param {URL | string} url + * @returns {{ url: URL, wasNormalized: boolean, denormalize: (url?: string | URL) => URL }} + * @since 2.18.0 + */ +export function normalizeUrl(url) { + url = new URL(url, 'a://a'); + + const is_route_resolution = has_resolution_suffix(url.pathname); + const is_data_request = has_data_suffix(url.pathname); + const has_trailing_slash = url.pathname !== '/' && url.pathname.endsWith('/'); + + if (is_route_resolution) { + url.pathname = strip_resolution_suffix(url.pathname); + } else if (is_data_request) { + url.pathname = strip_data_suffix(url.pathname); + } else if (has_trailing_slash) { + url.pathname = url.pathname.slice(0, -1); + } + + return { + url, + wasNormalized: is_data_request || is_route_resolution || has_trailing_slash, + denormalize: (new_url = url) => { + new_url = new URL(new_url, url); + if (is_route_resolution) { + new_url.pathname = add_resolution_suffix(new_url.pathname); + } else if (is_data_request) { + new_url.pathname = add_data_suffix(new_url.pathname); + } else if (has_trailing_slash && !new_url.pathname.endsWith('/')) { + new_url.pathname += '/'; + } + return new_url; + } + }; +} diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/internal/event.js b/frontend/node_modules/@sveltejs/kit/src/exports/internal/event.js new file mode 100644 index 0000000..9d65849 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/internal/event.js @@ -0,0 +1,85 @@ +/** @import { RequestEvent } from '@sveltejs/kit' */ +/** @import { RequestStore } from 'types' */ +/** @import { AsyncLocalStorage } from 'node:async_hooks' */ + +import { IN_WEBCONTAINER } from '../../runtime/server/constants.js'; + +/** @type {RequestStore | null} */ +let sync_store = null; + +/** @type {AsyncLocalStorage | null} */ +let als; + +import('node:async_hooks') + .then((hooks) => (als = new hooks.AsyncLocalStorage())) + .catch(() => { + // can't use AsyncLocalStorage, but can still call getRequestEvent synchronously. + // this isn't behind `supports` because it's basically just StackBlitz (i.e. + // in-browser usage) that doesn't support it AFAICT + }); + +/** + * Returns the current `RequestEvent`. Can be used inside server hooks, server `load` functions, actions, and endpoints (and functions called by them). + * + * In environments without [`AsyncLocalStorage`](https://nodejs.org/api/async_context.html#class-asynclocalstorage), this must be called synchronously (i.e. not after an `await`). + * @since 2.20.0 + * + * @returns {RequestEvent} + */ +export function getRequestEvent() { + const event = try_get_request_store()?.event; + + if (!event) { + let message = + 'Can only read the current request event inside functions invoked during `handle`, such as server `load` functions, actions, endpoints, and other server hooks.'; + + if (!als) { + message += + ' In environments without `AsyncLocalStorage`, the event must be read synchronously, not after an `await`.'; + } + + throw new Error(message); + } + + return event; +} + +export function get_request_store() { + const result = try_get_request_store(); + if (!result) { + let message = 'Could not get the request store.'; + + if (als) { + message += ' This is an internal error.'; + } else { + message += + ' In environments without `AsyncLocalStorage`, the request store (used by e.g. remote functions) must be accessed synchronously, not after an `await`.' + + ' If it was accessed synchronously then this is an internal error.'; + } + + throw new Error(message); + } + return result; +} + +export function try_get_request_store() { + return sync_store ?? als?.getStore() ?? null; +} + +/** + * @template T + * @param {RequestStore | null} store + * @param {() => T} fn + */ +export function with_request_store(store, fn) { + try { + sync_store = store; + return als ? als.run(store, fn) : fn(); + } finally { + // Since AsyncLocalStorage is not working in webcontainers, we don't reset `sync_store` + // and handle only one request at a time in `src/runtime/server/index.js`. + if (!IN_WEBCONTAINER) { + sync_store = null; + } + } +} diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/internal/index.js b/frontend/node_modules/@sveltejs/kit/src/exports/internal/index.js new file mode 100644 index 0000000..8ef0a32 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/internal/index.js @@ -0,0 +1,81 @@ +/** @import { StandardSchemaV1 } from '@standard-schema/spec' */ + +export class HttpError { + /** + * @param {number} status + * @param {{message: string} extends App.Error ? (App.Error | string | undefined) : App.Error} body + */ + constructor(status, body) { + this.status = status; + if (typeof body === 'string') { + this.body = { message: body }; + } else if (body) { + this.body = body; + } else { + this.body = { message: `Error: ${status}` }; + } + } + + toString() { + return JSON.stringify(this.body); + } +} + +export class Redirect { + /** + * @param {300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308} status + * @param {string} location + */ + constructor(status, location) { + this.status = status; + this.location = location; + } +} + +/** + * An error that was thrown from within the SvelteKit runtime that is not fatal and doesn't result in a 500, such as a 404. + * `SvelteKitError` goes through `handleError`. + * @extends Error + */ +export class SvelteKitError extends Error { + /** + * @param {number} status + * @param {string} text + * @param {string} message + */ + constructor(status, text, message) { + super(message); + this.status = status; + this.text = text; + } +} + +/** + * @template [T=undefined] + */ +export class ActionFailure { + /** + * @param {number} status + * @param {T} data + */ + constructor(status, data) { + this.status = status; + this.data = data; + } +} + +/** + * Error thrown when form validation fails imperatively + */ +export class ValidationError extends Error { + /** + * @param {StandardSchemaV1.Issue[]} issues + */ + constructor(issues) { + super('Validation failed'); + this.name = 'ValidationError'; + this.issues = issues; + } +} + +export { init_remote_functions } from './remote-functions.js'; diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/internal/remote-functions.js b/frontend/node_modules/@sveltejs/kit/src/exports/internal/remote-functions.js new file mode 100644 index 0000000..ae83ed5 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/internal/remote-functions.js @@ -0,0 +1,28 @@ +/** @import { RemoteInfo } from 'types' */ + +/** @type {RemoteInfo['type'][]} */ +const types = ['command', 'form', 'prerender', 'query', 'query_batch']; + +/** + * @param {Record} module + * @param {string} file + * @param {string} hash + */ +export function init_remote_functions(module, file, hash) { + if (module.default) { + throw new Error( + `Cannot export \`default\` from a remote module (${file}) — please use named exports instead` + ); + } + + for (const [name, fn] of Object.entries(module)) { + if (!types.includes(fn?.__?.type)) { + throw new Error( + `\`${name}\` exported from ${file} is invalid — all exports from this file must be remote functions` + ); + } + + fn.__.id = `${hash}/${name}`; + fn.__.name = name; + } +} diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/internal/server.js b/frontend/node_modules/@sveltejs/kit/src/exports/internal/server.js new file mode 100644 index 0000000..ed42506 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/internal/server.js @@ -0,0 +1,22 @@ +/** + * @template {{ tracing: { enabled: boolean, root: import('@opentelemetry/api').Span, current: import('@opentelemetry/api').Span } }} T + * @param {T} event_like + * @param {import('@opentelemetry/api').Span} current + * @returns {T} + */ +export function merge_tracing(event_like, current) { + return { + ...event_like, + tracing: { + ...event_like.tracing, + current + } + }; +} + +export { + with_request_store, + getRequestEvent, + get_request_store, + try_get_request_store +} from './event.js'; diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/node/index.js b/frontend/node_modules/@sveltejs/kit/src/exports/node/index.js new file mode 100644 index 0000000..ae2cae9 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/node/index.js @@ -0,0 +1,238 @@ +import { createReadStream } from 'node:fs'; +import { Readable } from 'node:stream'; +import * as set_cookie_parser from 'set-cookie-parser'; +import { SvelteKitError } from '../internal/index.js'; + +/** + * @param {import('http').IncomingMessage} req + * @param {number} [body_size_limit] + */ +function get_raw_body(req, body_size_limit) { + const h = req.headers; + + if (!h['content-type']) { + return null; + } + + const content_length = Number(h['content-length']); + + // check if no request body + if ( + (req.httpVersionMajor === 1 && isNaN(content_length) && h['transfer-encoding'] == null) || + content_length === 0 + ) { + return null; + } + + if (req.destroyed) { + const readable = new ReadableStream(); + void readable.cancel(); + return readable; + } + + let size = 0; + let cancelled = false; + + return new ReadableStream({ + start(controller) { + if (body_size_limit !== undefined && content_length > body_size_limit) { + let message = `Content-length of ${content_length} exceeds limit of ${body_size_limit} bytes.`; + + if (body_size_limit === 0) { + // https://github.com/sveltejs/kit/pull/11589 + // TODO this exists to aid migration — remove in a future version + message += ' To disable body size limits, specify Infinity rather than 0.'; + } + + const error = new SvelteKitError(413, 'Payload Too Large', message); + + controller.error(error); + return; + } + + req.on('error', (error) => { + cancelled = true; + controller.error(error); + }); + + req.on('end', () => { + if (cancelled) return; + controller.close(); + }); + + req.on('data', (chunk) => { + if (cancelled) return; + + size += chunk.length; + if (size > content_length) { + cancelled = true; + + const constraint = content_length ? 'content-length' : 'BODY_SIZE_LIMIT'; + const message = `request body size exceeded ${constraint} of ${content_length}`; + + const error = new SvelteKitError(413, 'Payload Too Large', message); + controller.error(error); + + return; + } + + controller.enqueue(chunk); + + if (controller.desiredSize === null || controller.desiredSize <= 0) { + req.pause(); + } + }); + }, + + pull() { + req.resume(); + }, + + cancel(reason) { + cancelled = true; + req.destroy(reason); + } + }); +} + +/** + * @param {{ + * request: import('http').IncomingMessage; + * base: string; + * bodySizeLimit?: number; + * }} options + * @returns {Promise} + */ +// TODO 3.0 make the signature synchronous? +// eslint-disable-next-line @typescript-eslint/require-await +export async function getRequest({ request, base, bodySizeLimit }) { + let headers = /** @type {Record} */ (request.headers); + if (request.httpVersionMajor >= 2) { + // the Request constructor rejects headers with ':' in the name + headers = Object.assign({}, headers); + // https://www.rfc-editor.org/rfc/rfc9113.html#section-8.3.1-2.3.5 + if (headers[':authority']) { + headers.host = headers[':authority']; + } + delete headers[':authority']; + delete headers[':method']; + delete headers[':path']; + delete headers[':scheme']; + } + + // TODO: Whenever Node >=22 is minimum supported version, we can use `request.readableAborted` + // @see https://github.com/nodejs/node/blob/5cf3c3e24c7257a0c6192ed8ef71efec8ddac22b/lib/internal/streams/readable.js#L1443-L1453 + const controller = new AbortController(); + let errored = false; + let end_emitted = false; + request.once('error', () => (errored = true)); + request.once('end', () => (end_emitted = true)); + request.once('close', () => { + if ((errored || request.destroyed) && !end_emitted) { + controller.abort(); + } + }); + + return new Request(base + request.url, { + // @ts-expect-error + duplex: 'half', + method: request.method, + headers: Object.entries(headers), + signal: controller.signal, + body: + request.method === 'GET' || request.method === 'HEAD' + ? undefined + : get_raw_body(request, bodySizeLimit) + }); +} + +/** + * @param {import('http').ServerResponse} res + * @param {Response} response + * @returns {Promise} + */ +// TODO 3.0 make the signature synchronous? +// eslint-disable-next-line @typescript-eslint/require-await +export async function setResponse(res, response) { + for (const [key, value] of response.headers) { + try { + res.setHeader( + key, + key === 'set-cookie' + ? set_cookie_parser.splitCookiesString( + // This is absurd but necessary, TODO: investigate why + /** @type {string}*/ (response.headers.get(key)) + ) + : value + ); + } catch (error) { + res.getHeaderNames().forEach((name) => res.removeHeader(name)); + res.writeHead(500).end(String(error)); + return; + } + } + + res.writeHead(response.status); + + if (!response.body) { + res.end(); + return; + } + + if (response.body.locked) { + res.end( + 'Fatal error: Response body is locked. ' + + "This can happen when the response was already read (for example through 'response.json()' or 'response.text()')." + ); + return; + } + + const reader = response.body.getReader(); + + if (res.destroyed) { + void reader.cancel(); + return; + } + + const cancel = (/** @type {Error|undefined} */ error) => { + res.off('close', cancel); + res.off('error', cancel); + + // If the reader has already been interrupted with an error earlier, + // then it will appear here, it is useless, but it needs to be catch. + reader.cancel(error).catch(() => {}); + if (error) res.destroy(error); + }; + + res.on('close', cancel); + res.on('error', cancel); + + void next(); + async function next() { + try { + for (;;) { + const { done, value } = await reader.read(); + + if (done) break; + + if (!res.write(value)) { + res.once('drain', next); + return; + } + } + res.end(); + } catch (error) { + cancel(error instanceof Error ? error : new Error(String(error))); + } + } +} + +/** + * Converts a file on disk to a readable stream + * @param {string} file + * @returns {ReadableStream} + * @since 2.4.0 + */ +export function createReadableStream(file) { + return /** @type {ReadableStream} */ (Readable.toWeb(createReadStream(file))); +} diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/node/polyfills.js b/frontend/node_modules/@sveltejs/kit/src/exports/node/polyfills.js new file mode 100644 index 0000000..347c68c --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/node/polyfills.js @@ -0,0 +1,30 @@ +import buffer from 'node:buffer'; +import { webcrypto as crypto } from 'node:crypto'; + +// `buffer.File` was added in Node 18.13.0 while the `File` global was added in Node 20.0.0 +const File = /** @type {import('node:buffer') & { File?: File}} */ (buffer).File; + +/** @type {Record} */ +const globals = { + crypto, + File +}; + +// exported for dev/preview and node environments +/** + * Make various web APIs available as globals: + * - `crypto` + * - `File` + */ +export function installPolyfills() { + for (const name in globals) { + if (name in globalThis) continue; + + Object.defineProperty(globalThis, name, { + enumerable: true, + configurable: true, + writable: true, + value: globals[name] + }); + } +} diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/public.d.ts b/frontend/node_modules/@sveltejs/kit/src/exports/public.d.ts new file mode 100644 index 0000000..c67fbfe --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/public.d.ts @@ -0,0 +1,2186 @@ +import 'svelte'; // pick up `declare module "*.svelte"` +import 'vite/client'; // pick up `declare module "*.jpg"`, etc. +import '../types/ambient.js'; + +import { + AdapterEntry, + CspDirectives, + HttpMethod, + Logger, + MaybePromise, + Prerendered, + PrerenderEntryGeneratorMismatchHandlerValue, + PrerenderHttpErrorHandlerValue, + PrerenderMissingIdHandlerValue, + PrerenderUnseenRoutesHandlerValue, + PrerenderOption, + RequestOptions, + RouteSegment, + DeepPartial, + IsAny +} from '../types/private.js'; +import { BuildData, SSRNodeLoader, SSRRoute, ValidatedConfig } from 'types'; +import { SvelteConfig } from '@sveltejs/vite-plugin-svelte'; +import { StandardSchemaV1 } from '@standard-schema/spec'; +import { + RouteId as AppRouteId, + LayoutParams as AppLayoutParams, + ResolvedPathname +} from '$app/types'; + +export { PrerenderOption } from '../types/private.js'; + +// @ts-ignore this is an optional peer dependency so could be missing. Written like this so dts-buddy preserves the ts-ignore +type Span = import('@opentelemetry/api').Span; + +/** + * [Adapters](https://svelte.dev/docs/kit/adapters) are responsible for taking the production build and turning it into something that can be deployed to a platform of your choosing. + */ +export interface Adapter { + /** + * The name of the adapter, using for logging. Will typically correspond to the package name. + */ + name: string; + /** + * This function is called after SvelteKit has built your app. + * @param builder An object provided by SvelteKit that contains methods for adapting the app + */ + adapt: (builder: Builder) => MaybePromise; + /** + * Checks called during dev and build to determine whether specific features will work in production with this adapter. + */ + supports?: { + /** + * Test support for `read` from `$app/server`. + * @param details.config The merged route config + */ + read?: (details: { config: any; route: { id: string } }) => boolean; + + /** + * Test support for `instrumentation.server.js`. To pass, the adapter must support running `instrumentation.server.js` prior to the application code. + * @since 2.31.0 + */ + instrumentation?: () => boolean; + }; + /** + * Creates an `Emulator`, which allows the adapter to influence the environment + * during dev, build and prerendering. + */ + emulate?: () => MaybePromise; +} + +export type LoadProperties | void> = input extends void + ? undefined // needs to be undefined, because void will break intellisense + : input extends Record + ? input + : unknown; + +export type AwaitedActions any>> = OptionalUnion< + { + [Key in keyof T]: UnpackValidationError>>; + }[keyof T] +>; + +// Takes a union type and returns a union type where each type also has all properties +// of all possible types (typed as undefined), making accessing them more ergonomic +type OptionalUnion< + U extends Record, // not unknown, else interfaces don't satisfy this constraint + A extends keyof U = U extends U ? keyof U : never +> = U extends unknown ? { [P in Exclude]?: never } & U : never; + +declare const uniqueSymbol: unique symbol; + +export interface ActionFailure { + status: number; + data: T; + [uniqueSymbol]: true; // necessary or else UnpackValidationError could wrongly unpack objects with the same shape as ActionFailure +} + +type UnpackValidationError = + T extends ActionFailure + ? X + : T extends void + ? undefined // needs to be undefined, because void will corrupt union type + : T; + +/** + * This object is passed to the `adapt` function of adapters. + * It contains various methods and properties that are useful for adapting the app. + */ +export interface Builder { + /** Print messages to the console. `log.info` and `log.minor` are silent unless Vite's `logLevel` is `info`. */ + log: Logger; + /** Remove `dir` and all its contents. */ + rimraf: (dir: string) => void; + /** Create `dir` and any required parent directories. */ + mkdirp: (dir: string) => void; + + /** The fully resolved Svelte config. */ + config: ValidatedConfig; + /** Information about prerendered pages and assets, if any. */ + prerendered: Prerendered; + /** An array of all routes (including prerendered) */ + routes: RouteDefinition[]; + + // TODO 3.0 remove this method + /** + * Create separate functions that map to one or more routes of your app. + * @param fn A function that groups a set of routes into an entry point + * @deprecated Use `builder.routes` instead + */ + createEntries: (fn: (route: RouteDefinition) => AdapterEntry) => Promise; + + /** + * Find all the assets imported by server files belonging to `routes` + */ + findServerAssets: (routes: RouteDefinition[]) => string[]; + + /** + * Generate a fallback page for a static webserver to use when no route is matched. Useful for single-page apps. + */ + generateFallback: (dest: string) => Promise; + + /** + * Generate a module exposing build-time environment variables as `$env/dynamic/public`. + */ + generateEnvModule: () => void; + + /** + * Generate a server-side manifest to initialise the SvelteKit [server](https://svelte.dev/docs/kit/@sveltejs-kit#Server) with. + * @param opts a relative path to the base directory of the app and optionally in which format (esm or cjs) the manifest should be generated + */ + generateManifest: (opts: { relativePath: string; routes?: RouteDefinition[] }) => string; + + /** + * Resolve a path to the `name` directory inside `outDir`, e.g. `/path/to/.svelte-kit/my-adapter`. + * @param name path to the file, relative to the build directory + */ + getBuildDirectory: (name: string) => string; + /** Get the fully resolved path to the directory containing client-side assets, including the contents of your `static` directory. */ + getClientDirectory: () => string; + /** Get the fully resolved path to the directory containing server-side code. */ + getServerDirectory: () => string; + /** Get the application path including any configured `base` path, e.g. `my-base-path/_app`. */ + getAppPath: () => string; + + /** + * Write client assets to `dest`. + * @param dest the destination folder + * @returns an array of files written to `dest` + */ + writeClient: (dest: string) => string[]; + /** + * Write prerendered files to `dest`. + * @param dest the destination folder + * @returns an array of files written to `dest` + */ + writePrerendered: (dest: string) => string[]; + /** + * Write server-side code to `dest`. + * @param dest the destination folder + * @returns an array of files written to `dest` + */ + writeServer: (dest: string) => string[]; + /** + * Copy a file or directory. + * @param from the source file or directory + * @param to the destination file or directory + * @param opts.filter a function to determine whether a file or directory should be copied + * @param opts.replace a map of strings to replace + * @returns an array of files that were copied + */ + copy: ( + from: string, + to: string, + opts?: { + filter?(basename: string): boolean; + replace?: Record; + } + ) => string[]; + + /** + * Check if the server instrumentation file exists. + * @returns true if the server instrumentation file exists, false otherwise + * @since 2.31.0 + */ + hasServerInstrumentationFile: () => boolean; + + /** + * Instrument `entrypoint` with `instrumentation`. + * + * Renames `entrypoint` to `start` and creates a new module at + * `entrypoint` which imports `instrumentation` and then dynamically imports `start`. This allows + * the module hooks necessary for instrumentation libraries to be loaded prior to any application code. + * + * Caveats: + * - "Live exports" will not work. If your adapter uses live exports, your users will need to manually import the server instrumentation on startup. + * - If `tla` is `false`, OTEL auto-instrumentation may not work properly. Use it if your environment supports it. + * - Use `hasServerInstrumentationFile` to check if the user has a server instrumentation file; if they don't, you shouldn't do this. + * + * @param options an object containing the following properties: + * @param options.entrypoint the path to the entrypoint to trace. + * @param options.instrumentation the path to the instrumentation file. + * @param options.start the name of the start file. This is what `entrypoint` will be renamed to. + * @param options.module configuration for the resulting entrypoint module. + * @param options.module.exports + * @param options.module.generateText a function that receives the relative paths to the instrumentation and start files, and generates the text of the module to be traced. If not provided, the default implementation will be used, which uses top-level await. + * @since 2.31.0 + */ + instrument: (args: { + entrypoint: string; + instrumentation: string; + start?: string; + module?: + | { + exports: string[]; + } + | { + generateText: (args: { instrumentation: string; start: string }) => string; + }; + }) => void; + + /** + * Compress files in `directory` with gzip and brotli, where appropriate. Generates `.gz` and `.br` files alongside the originals. + * @param {string} directory The directory containing the files to be compressed + */ + compress: (directory: string) => Promise; +} + +/** + * An extension of [`vite-plugin-svelte`'s options](https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/config.md#svelte-options). + */ +export interface Config extends SvelteConfig { + /** + * SvelteKit options. + * + * @see https://svelte.dev/docs/kit/configuration + */ + kit?: KitConfig; + /** Any additional options required by tooling that integrates with Svelte. */ + [key: string]: any; +} + +export interface Cookies { + /** + * Gets a cookie that was previously set with `cookies.set`, or from the request headers. + * @param name the name of the cookie + * @param opts the options, passed directly to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options) + */ + get: (name: string, opts?: import('cookie').CookieParseOptions) => string | undefined; + + /** + * Gets all cookies that were previously set with `cookies.set`, or from the request headers. + * @param opts the options, passed directly to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options) + */ + getAll: (opts?: import('cookie').CookieParseOptions) => Array<{ name: string; value: string }>; + + /** + * Sets a cookie. This will add a `set-cookie` header to the response, but also make the cookie available via `cookies.get` or `cookies.getAll` during the current request. + * + * The `httpOnly` and `secure` options are `true` by default (except on http://localhost, where `secure` is `false`), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The `sameSite` option defaults to `lax`. + * + * You must specify a `path` for the cookie. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children + * @param name the name of the cookie + * @param value the cookie value + * @param opts the options, passed directly to `cookie.serialize`. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options) + */ + set: ( + name: string, + value: string, + opts: import('cookie').CookieSerializeOptions & { path: string } + ) => void; + + /** + * Deletes a cookie by setting its value to an empty string and setting the expiry date in the past. + * + * You must specify a `path` for the cookie. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children + * @param name the name of the cookie + * @param opts the options, passed directly to `cookie.serialize`. The `path` must match the path of the cookie you want to delete. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options) + */ + delete: (name: string, opts: import('cookie').CookieSerializeOptions & { path: string }) => void; + + /** + * Serialize a cookie name-value pair into a `Set-Cookie` header string, but don't apply it to the response. + * + * The `httpOnly` and `secure` options are `true` by default (except on http://localhost, where `secure` is `false`), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The `sameSite` option defaults to `lax`. + * + * You must specify a `path` for the cookie. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children + * + * @param name the name of the cookie + * @param value the cookie value + * @param opts the options, passed directly to `cookie.serialize`. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options) + */ + serialize: ( + name: string, + value: string, + opts: import('cookie').CookieSerializeOptions & { path: string } + ) => string; +} + +/** + * A collection of functions that influence the environment during dev, build and prerendering + */ +export interface Emulator { + /** + * A function that is called with the current route `config` and `prerender` option + * and returns an `App.Platform` object + */ + platform?(details: { config: any; prerender: PrerenderOption }): MaybePromise; +} + +export interface KitConfig { + /** + * Your [adapter](https://svelte.dev/docs/kit/adapters) is run when executing `vite build`. It determines how the output is converted for different platforms. + * @default undefined + */ + adapter?: Adapter; + /** + * An object containing zero or more aliases used to replace values in `import` statements. These aliases are automatically passed to Vite and TypeScript. + * + * ```js + * /// file: svelte.config.js + * /// type: import('@sveltejs/kit').Config + * const config = { + * kit: { + * alias: { + * // this will match a file + * 'my-file': 'path/to/my-file.js', + * + * // this will match a directory and its contents + * // (`my-directory/x` resolves to `path/to/my-directory/x`) + * 'my-directory': 'path/to/my-directory', + * + * // an alias ending /* will only match + * // the contents of a directory, not the directory itself + * 'my-directory/*': 'path/to/my-directory/*' + * } + * } + * }; + * ``` + * + * > [!NOTE] You will need to run `npm run dev` to have SvelteKit automatically generate the required alias configuration in `jsconfig.json` or `tsconfig.json`. + * @default {} + */ + alias?: Record; + /** + * The directory where SvelteKit keeps its stuff, including static assets (such as JS and CSS) and internally-used routes. + * + * If `paths.assets` is specified, there will be two app directories — `${paths.assets}/${appDir}` and `${paths.base}/${appDir}`. + * @default "_app" + */ + appDir?: string; + /** + * [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) configuration. CSP helps to protect your users against cross-site scripting (XSS) attacks, by limiting the places resources can be loaded from. For example, a configuration like this... + * + * ```js + * /// file: svelte.config.js + * /// type: import('@sveltejs/kit').Config + * const config = { + * kit: { + * csp: { + * directives: { + * 'script-src': ['self'] + * }, + * // must be specified with either the `report-uri` or `report-to` directives, or both + * reportOnly: { + * 'script-src': ['self'], + * 'report-uri': ['/'] + * } + * } + * } + * }; + * + * export default config; + * ``` + * + * ...would prevent scripts loading from external sites. SvelteKit will augment the specified directives with nonces or hashes (depending on `mode`) for any inline styles and scripts it generates. + * + * To add a nonce for scripts and links manually included in `src/app.html`, you may use the placeholder `%sveltekit.nonce%` (for example ` + * + * + * + * + * + * ``` + * @default 'split' + * @since 2.13.0 + */ + bundleStrategy?: 'split' | 'single' | 'inline'; + }; + paths?: { + /** + * An absolute path that your app's files are served from. This is useful if your files are served from a storage bucket of some kind. + * @default "" + */ + assets?: '' | `http://${string}` | `https://${string}`; + /** + * A root-relative path that must start, but not end with `/` (e.g. `/base-path`), unless it is the empty string. This specifies where your app is served from and allows the app to live on a non-root path. Note that you need to prepend all your root-relative links with the base value or they will point to the root of your domain, not your `base` (this is how the browser works). You can use [`base` from `$app/paths`](https://svelte.dev/docs/kit/$app-paths#base) for that: `Link`. If you find yourself writing this often, it may make sense to extract this into a reusable component. + * @default "" + */ + base?: '' | `/${string}`; + /** + * Whether to use relative asset paths. + * + * If `true`, `base` and `assets` imported from `$app/paths` will be replaced with relative asset paths during server-side rendering, resulting in more portable HTML. + * If `false`, `%sveltekit.assets%` and references to build artifacts will always be root-relative paths, unless `paths.assets` is an external URL + * + * [Single-page app](https://svelte.dev/docs/kit/single-page-apps) fallback pages will always use absolute paths, regardless of this setting. + * + * If your app uses a `` element, you should set this to `false`, otherwise asset URLs will incorrectly be resolved against the `` URL rather than the current page. + * + * In 1.0, `undefined` was a valid value, which was set by default. In that case, if `paths.assets` was not external, SvelteKit would replace `%sveltekit.assets%` with a relative path and use relative paths to reference build artifacts, but `base` and `assets` imported from `$app/paths` would be as specified in your config. + * + * @default true + * @since 1.9.0 + */ + relative?: boolean; + }; + /** + * See [Prerendering](https://svelte.dev/docs/kit/page-options#prerender). + */ + prerender?: { + /** + * How many pages can be prerendered simultaneously. JS is single-threaded, but in cases where prerendering performance is network-bound (for example loading content from a remote CMS) this can speed things up by processing other tasks while waiting on the network response. + * @default 1 + */ + concurrency?: number; + /** + * Whether SvelteKit should find pages to prerender by following links from `entries`. + * @default true + */ + crawl?: boolean; + /** + * An array of pages to prerender, or start crawling from (if `crawl: true`). The `*` string includes all routes containing no required `[parameters]` with optional parameters included as being empty (since SvelteKit doesn't know what value any parameters should have). + * @default ["*"] + */ + entries?: Array<'*' | `/${string}`>; + /** + * How to respond to HTTP errors encountered while prerendering the app. + * + * - `'fail'` — fail the build + * - `'ignore'` - silently ignore the failure and continue + * - `'warn'` — continue, but print a warning + * - `(details) => void` — a custom error handler that takes a `details` object with `status`, `path`, `referrer`, `referenceType` and `message` properties. If you `throw` from this function, the build will fail + * + * ```js + * /// file: svelte.config.js + * /// type: import('@sveltejs/kit').Config + * const config = { + * kit: { + * prerender: { + * handleHttpError: ({ path, referrer, message }) => { + * // ignore deliberate link to shiny 404 page + * if (path === '/not-found' && referrer === '/blog/how-we-built-our-404-page') { + * return; + * } + * + * // otherwise fail the build + * throw new Error(message); + * } + * } + * } + * }; + * ``` + * + * @default "fail" + * @since 1.15.7 + */ + handleHttpError?: PrerenderHttpErrorHandlerValue; + /** + * How to respond when hash links from one prerendered page to another don't correspond to an `id` on the destination page. + * + * - `'fail'` — fail the build + * - `'ignore'` - silently ignore the failure and continue + * - `'warn'` — continue, but print a warning + * - `(details) => void` — a custom error handler that takes a `details` object with `path`, `id`, `referrers` and `message` properties. If you `throw` from this function, the build will fail + * + * @default "fail" + * @since 1.15.7 + */ + handleMissingId?: PrerenderMissingIdHandlerValue; + /** + * How to respond when an entry generated by the `entries` export doesn't match the route it was generated from. + * + * - `'fail'` — fail the build + * - `'ignore'` - silently ignore the failure and continue + * - `'warn'` — continue, but print a warning + * - `(details) => void` — a custom error handler that takes a `details` object with `generatedFromId`, `entry`, `matchedId` and `message` properties. If you `throw` from this function, the build will fail + * + * @default "fail" + * @since 1.16.0 + */ + handleEntryGeneratorMismatch?: PrerenderEntryGeneratorMismatchHandlerValue; + /** + * How to respond when a route is marked as prerenderable but has not been prerendered. + * + * - `'fail'` — fail the build + * - `'ignore'` - silently ignore the failure and continue + * - `'warn'` — continue, but print a warning + * - `(details) => void` — a custom error handler that takes a `details` object with a `routes` property which contains all routes that haven't been prerendered. If you `throw` from this function, the build will fail + * + * The default behavior is to fail the build. This may be undesirable when you know that some of your routes may never be reached under certain + * circumstances such as a CMS not returning data for a specific area, resulting in certain routes never being reached. + * + * @default "fail" + * @since 2.16.0 + */ + handleUnseenRoutes?: PrerenderUnseenRoutesHandlerValue; + /** + * The value of `url.origin` during prerendering; useful if it is included in rendered content. + * @default "http://sveltekit-prerender" + */ + origin?: string; + }; + router?: { + /** + * What type of client-side router to use. + * - `'pathname'` is the default and means the current URL pathname determines the route + * - `'hash'` means the route is determined by `location.hash`. In this case, SSR and prerendering are disabled. This is only recommended if `pathname` is not an option, for example because you don't control the webserver where your app is deployed. + * It comes with some caveats: you can't use server-side rendering (or indeed any server logic), and you have to make sure that the links in your app all start with #/, or they won't work. Beyond that, everything works exactly like a normal SvelteKit app. + * + * @default "pathname" + * @since 2.14.0 + */ + type?: 'pathname' | 'hash'; + /** + * How to determine which route to load when navigating to a new page. + * + * By default, SvelteKit will serve a route manifest to the browser. + * When navigating, this manifest is used (along with the `reroute` hook, if it exists) to determine which components to load and which `load` functions to run. + * Because everything happens on the client, this decision can be made immediately. The drawback is that the manifest needs to be + * loaded and parsed before the first navigation can happen, which may have an impact if your app contains many routes. + * + * Alternatively, SvelteKit can determine the route on the server. This means that for every navigation to a path that has not yet been visited, the server will be asked to determine the route. + * This has several advantages: + * - The client does not need to load the routing manifest upfront, which can lead to faster initial page loads + * - The list of routes is hidden from public view + * - The server has an opportunity to intercept each navigation (for example through a middleware), enabling (for example) A/B testing opaque to SvelteKit + + * The drawback is that for unvisited paths, resolution will take slightly longer (though this is mitigated by [preloading](https://svelte.dev/docs/kit/link-options#data-sveltekit-preload-data)). + * + * > [!NOTE] When using server-side route resolution and prerendering, the resolution is prerendered along with the route itself. + * + * @default "client" + * @since 2.17.0 + */ + resolution?: 'client' | 'server'; + }; + serviceWorker?: { + /** + * Determine which files in your `static` directory will be available in `$service-worker.files`. + * @default (filename) => !/\.DS_Store/.test(filename) + */ + files?: (file: string) => boolean; + } & ( + | { + /** + * Whether to automatically register the service worker, if it exists. + * @default true + */ + register: true; + /** + * Options for serviceWorker.register("...", options); + */ + options?: RegistrationOptions; + } + | { + /** + * Whether to automatically register the service worker, if it exists. + * @default true + */ + register?: false; + } + ); + typescript?: { + /** + * A function that allows you to edit the generated `tsconfig.json`. You can mutate the config (recommended) or return a new one. + * This is useful for extending a shared `tsconfig.json` in a monorepo root, for example. + * + * Note that any paths configured here should be relative to the generated config file, which is written to `.svelte-kit/tsconfig.json`. + * + * @default (config) => config + * @since 1.3.0 + */ + config?: (config: Record) => Record | void; + }; + /** + * Client-side navigation can be buggy if you deploy a new version of your app while people are using it. If the code for the new page is already loaded, it may have stale content; if it isn't, the app's route manifest may point to a JavaScript file that no longer exists. + * SvelteKit helps you solve this problem through version management. + * If SvelteKit encounters an error while loading the page and detects that a new version has been deployed (using the `name` specified here, which defaults to a timestamp of the build) it will fall back to traditional full-page navigation. + * Not all navigations will result in an error though, for example if the JavaScript for the next page is already loaded. If you still want to force a full-page navigation in these cases, use techniques such as setting the `pollInterval` and then using `beforeNavigate`: + * ```html + * /// file: +layout.svelte + * + * ``` + * + * If you set `pollInterval` to a non-zero value, SvelteKit will poll for new versions in the background and set the value of [`updated.current`](https://svelte.dev/docs/kit/$app-state#updated) `true` when it detects one. + */ + version?: { + /** + * The current app version string. If specified, this must be deterministic (e.g. a commit ref rather than `Math.random()` or `Date.now().toString()`), otherwise defaults to a timestamp of the build. + * + * For example, to use the current commit hash, you could do use `git rev-parse HEAD`: + * + * ```js + * /// file: svelte.config.js + * import * as child_process from 'node:child_process'; + * + * export default { + * kit: { + * version: { + * name: child_process.execSync('git rev-parse HEAD').toString().trim() + * } + * } + * }; + * ``` + */ + name?: string; + /** + * The interval in milliseconds to poll for version changes. If this is `0`, no polling occurs. + * @default 0 + */ + pollInterval?: number; + }; +} + +/** + * The [`handle`](https://svelte.dev/docs/kit/hooks#Server-hooks-handle) hook runs every time the SvelteKit server receives a [request](https://svelte.dev/docs/kit/web-standards#Fetch-APIs-Request) and + * determines the [response](https://svelte.dev/docs/kit/web-standards#Fetch-APIs-Response). + * It receives an `event` object representing the request and a function called `resolve`, which renders the route and generates a `Response`. + * This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example). + */ +export type Handle = (input: { + event: RequestEvent; + resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise; +}) => MaybePromise; + +/** + * The server-side [`handleError`](https://svelte.dev/docs/kit/hooks#Shared-hooks-handleError) hook runs when an unexpected error is thrown while responding to a request. + * + * If an unexpected error is thrown during loading or rendering, this function will be called with the error and the event. + * Make sure that this function _never_ throws an error. + */ +export type HandleServerError = (input: { + error: unknown; + event: RequestEvent; + status: number; + message: string; +}) => MaybePromise; + +/** + * The [`handleValidationError`](https://svelte.dev/docs/kit/hooks#Server-hooks-handleValidationError) hook runs when the argument to a remote function fails validation. + * + * It will be called with the validation issues and the event, and must return an object shape that matches `App.Error`. + */ +export type HandleValidationError = + (input: { issues: Issue[]; event: RequestEvent }) => MaybePromise; + +/** + * The client-side [`handleError`](https://svelte.dev/docs/kit/hooks#Shared-hooks-handleError) hook runs when an unexpected error is thrown while navigating. + * + * If an unexpected error is thrown during loading or the following render, this function will be called with the error and the event. + * Make sure that this function _never_ throws an error. + */ +export type HandleClientError = (input: { + error: unknown; + event: NavigationEvent; + status: number; + message: string; +}) => MaybePromise; + +/** + * The [`handleFetch`](https://svelte.dev/docs/kit/hooks#Server-hooks-handleFetch) hook allows you to modify (or replace) the result of an [`event.fetch`](https://svelte.dev/docs/kit/load#Making-fetch-requests) call that runs on the server (or during prerendering) inside an endpoint, `load`, `action`, `handle`, `handleError` or `reroute`. + */ +export type HandleFetch = (input: { + event: RequestEvent; + request: Request; + fetch: typeof fetch; +}) => MaybePromise; + +/** + * The [`init`](https://svelte.dev/docs/kit/hooks#Shared-hooks-init) will be invoked before the server responds to its first request + * @since 2.10.0 + */ +export type ServerInit = () => MaybePromise; + +/** + * The [`init`](https://svelte.dev/docs/kit/hooks#Shared-hooks-init) will be invoked once the app starts in the browser + * @since 2.10.0 + */ +export type ClientInit = () => MaybePromise; + +/** + * The [`reroute`](https://svelte.dev/docs/kit/hooks#Universal-hooks-reroute) hook allows you to modify the URL before it is used to determine which route to render. + * @since 2.3.0 + */ +export type Reroute = (event: { url: URL; fetch: typeof fetch }) => MaybePromise; + +/** + * The [`transport`](https://svelte.dev/docs/kit/hooks#Universal-hooks-transport) hook allows you to transport custom types across the server/client boundary. + * + * Each transporter has a pair of `encode` and `decode` functions. On the server, `encode` determines whether a value is an instance of the custom type and, if so, returns a non-falsy encoding of the value which can be an object or an array (or `false` otherwise). + * + * In the browser, `decode` turns the encoding back into an instance of the custom type. + * + * ```ts + * import type { Transport } from '@sveltejs/kit'; + * + * declare class MyCustomType { + * data: any + * } + * + * // hooks.js + * export const transport: Transport = { + * MyCustomType: { + * encode: (value) => value instanceof MyCustomType && [value.data], + * decode: ([data]) => new MyCustomType(data) + * } + * }; + * ``` + * @since 2.11.0 + */ +export type Transport = Record; + +/** + * A member of the [`transport`](https://svelte.dev/docs/kit/hooks#Universal-hooks-transport) hook. + */ +export interface Transporter< + T = any, + U = Exclude +> { + encode: (value: T) => false | U; + decode: (data: U) => T; +} + +/** + * The generic form of `PageLoad` and `LayoutLoad`. You should import those from `./$types` (see [generated types](https://svelte.dev/docs/kit/types#Generated-types)) + * rather than using `Load` directly. + */ +export type Load< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + InputData extends Record | null = Record | null, + ParentData extends Record = Record, + OutputData extends Record | void = Record | void, + RouteId extends AppRouteId | null = AppRouteId | null +> = (event: LoadEvent) => MaybePromise; + +/** + * The generic form of `PageLoadEvent` and `LayoutLoadEvent`. You should import those from `./$types` (see [generated types](https://svelte.dev/docs/kit/types#Generated-types)) + * rather than using `LoadEvent` directly. + */ +export interface LoadEvent< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + Data extends Record | null = Record | null, + ParentData extends Record = Record, + RouteId extends AppRouteId | null = AppRouteId | null +> extends NavigationEvent { + /** + * `fetch` is equivalent to the [native `fetch` web API](https://developer.mozilla.org/en-US/docs/Web/API/fetch), with a few additional features: + * + * - It can be used to make credentialed requests on the server, as it inherits the `cookie` and `authorization` headers for the page request. + * - It can make relative requests on the server (ordinarily, `fetch` requires a URL with an origin when used in a server context). + * - Internal requests (e.g. for `+server.js` routes) go directly to the handler function when running on the server, without the overhead of an HTTP call. + * - During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the `text` and `json` methods of the `Response` object. Note that headers will _not_ be serialized, unless explicitly included via [`filterSerializedResponseHeaders`](https://svelte.dev/docs/kit/hooks#Server-hooks-handle) + * - During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request. + * + * You can learn more about making credentialed requests with cookies [here](https://svelte.dev/docs/kit/load#Cookies) + */ + fetch: typeof fetch; + /** + * Contains the data returned by the route's server `load` function (in `+layout.server.js` or `+page.server.js`), if any. + */ + data: Data; + /** + * If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example: + * + * ```js + * /// file: src/routes/blog/+page.js + * export async function load({ fetch, setHeaders }) { + * const url = `https://cms.example.com/articles.json`; + * const response = await fetch(url); + * + * setHeaders({ + * age: response.headers.get('age'), + * 'cache-control': response.headers.get('cache-control') + * }); + * + * return response.json(); + * } + * ``` + * + * Setting the same header multiple times (even in separate `load` functions) is an error — you can only set a given header once. + * + * You cannot add a `set-cookie` header with `setHeaders` — use the [`cookies`](https://svelte.dev/docs/kit/@sveltejs-kit#Cookies) API in a server-only `load` function instead. + * + * `setHeaders` has no effect when a `load` function runs in the browser. + */ + setHeaders: (headers: Record) => void; + /** + * `await parent()` returns data from parent `+layout.js` `load` functions. + * Implicitly, a missing `+layout.js` is treated as a `({ data }) => data` function, meaning that it will return and forward data from parent `+layout.server.js` files. + * + * Be careful not to introduce accidental waterfalls when using `await parent()`. If for example you only want to merge parent data into the returned output, call it _after_ fetching your other data. + */ + parent: () => Promise; + /** + * This function declares that the `load` function has a _dependency_ on one or more URLs or custom identifiers, which can subsequently be used with [`invalidate()`](https://svelte.dev/docs/kit/$app-navigation#invalidate) to cause `load` to rerun. + * + * Most of the time you won't need this, as `fetch` calls `depends` on your behalf — it's only necessary if you're using a custom API client that bypasses `fetch`. + * + * URLs can be absolute or relative to the page being loaded, and must be [encoded](https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding). + * + * Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the [URI specification](https://www.rfc-editor.org/rfc/rfc3986.html). + * + * The following example shows how to use `depends` to register a dependency on a custom identifier, which is `invalidate`d after a button click, making the `load` function rerun. + * + * ```js + * /// file: src/routes/+page.js + * let count = 0; + * export async function load({ depends }) { + * depends('increase:count'); + * + * return { count: count++ }; + * } + * ``` + * + * ```html + * /// file: src/routes/+page.svelte + * + * + *

{data.count}

+ * + * ``` + */ + depends: (...deps: Array<`${string}:${string}`>) => void; + /** + * Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example: + * + * ```js + * /// file: src/routes/+page.server.js + * export async function load({ untrack, url }) { + * // Untrack url.pathname so that path changes don't trigger a rerun + * if (untrack(() => url.pathname === '/')) { + * return { message: 'Welcome!' }; + * } + * } + * ``` + */ + untrack: (fn: () => T) => T; + + /** + * Access to spans for tracing. If tracing is not enabled or the function is being run in the browser, these spans will do nothing. + * @since 2.31.0 + */ + tracing: { + /** Whether tracing is enabled. */ + enabled: boolean; + /** The root span for the request. This span is named `sveltekit.handle.root`. */ + root: Span; + /** The span associated with the current `load` function. */ + current: Span; + }; +} + +export interface NavigationEvent< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + RouteId extends AppRouteId | null = AppRouteId | null +> { + /** + * The parameters of the current page - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object + */ + params: Params; + /** + * Info about the current route + */ + route: { + /** + * The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]`. It is `null` when no route is matched. + */ + id: RouteId; + }; + /** + * The URL of the current page + */ + url: URL; +} + +/** + * Information about the target of a specific navigation. + */ +export interface NavigationTarget< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + RouteId extends AppRouteId | null = AppRouteId | null +> { + /** + * Parameters of the target page - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object. + * Is `null` if the target is not part of the SvelteKit app (could not be resolved to a route). + */ + params: Params | null; + /** + * Info about the target route + */ + route: { + /** + * The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]`. It is `null` when no route is matched. + */ + id: RouteId | null; + }; + /** + * The URL that is navigated to + */ + url: URL; + /** + * The scroll position associated with this navigation. + * + * For the `from` target, this is the scroll position at the moment of navigation. + * + * For the `to` target, this represents the scroll position that will be or was restored: + * - In `beforeNavigate` and `onNavigate`, this is only available for `popstate` navigations (back/forward button) + * and will be `null` for other navigation types, since the final scroll position isn't known + * ahead of time. + * - In `afterNavigate`, this is always the scroll position that was applied after the navigation + * completed. + */ + scroll: { x: number; y: number } | null; +} + +/** + * - `enter`: The app has hydrated/started + * - `form`: The user submitted a `

` + * - `leave`: The app is being left either because the tab is being closed or a navigation to a different document is occurring + * - `link`: Navigation was triggered by a link click + * - `goto`: Navigation was triggered by a `goto(...)` call or a redirect + * - `popstate`: Navigation was triggered by back/forward navigation + */ +export type NavigationType = 'enter' | 'form' | 'leave' | 'link' | 'goto' | 'popstate'; + +export interface NavigationBase { + /** + * Where navigation was triggered from + */ + from: NavigationTarget | null; + /** + * Where navigation is going to/has gone to + */ + to: NavigationTarget | null; + /** + * Whether or not the navigation will result in the page being unloaded (i.e. not a client-side navigation). + */ + willUnload: boolean; + /** + * A promise that resolves once the navigation is complete, and rejects if the navigation + * fails or is aborted. In the case of a `willUnload` navigation, the promise will never resolve + */ + complete: Promise; +} + +export interface NavigationEnter extends NavigationBase { + /** + * The type of navigation: + * - `enter`: The app has hydrated/started + */ + type: 'enter'; + + /** + * In case of a history back/forward navigation, the number of steps to go back/forward + */ + delta?: undefined; + + /** + * Dispatched `Event` object when navigation occurred by `popstate` or `link`. + */ + event?: undefined; +} + +export type NavigationExternal = NavigationGoto | NavigationLeave; + +export interface NavigationGoto extends NavigationBase { + /** + * The type of navigation: + * - `goto`: Navigation was triggered by a `goto(...)` call or a redirect + */ + type: 'goto'; + + // TODO 3.0 remove this property, so that it only exists when type is 'popstate' + // (would possibly be a breaking change to do it prior to that) + /** + * In case of a history back/forward navigation, the number of steps to go back/forward + */ + delta?: undefined; +} + +export interface NavigationLeave extends NavigationBase { + /** + * The type of navigation: + * - `leave`: The app is being left either because the tab is being closed or a navigation to a different document is occurring + */ + type: 'leave'; + + // TODO 3.0 remove this property, so that it only exists when type is 'popstate' + // (would possibly be a breaking change to do it prior to that) + /** + * In case of a history back/forward navigation, the number of steps to go back/forward + */ + delta?: undefined; +} + +export interface NavigationFormSubmit extends NavigationBase { + /** + * The type of navigation: + * - `form`: The user submitted a `` + */ + type: 'form'; + + /** + * The `SubmitEvent` that caused the navigation + */ + event: SubmitEvent; + + // TODO 3.0 remove this property, so that it only exists when type is 'popstate' + // (would possibly be a breaking change to do it prior to that) + /** + * In case of a history back/forward navigation, the number of steps to go back/forward + */ + delta?: undefined; +} + +export interface NavigationPopState extends NavigationBase { + /** + * The type of navigation: + * - `popstate`: Navigation was triggered by back/forward navigation + */ + type: 'popstate'; + + /** + * In case of a history back/forward navigation, the number of steps to go back/forward + */ + delta: number; + + /** + * The `PopStateEvent` that caused the navigation + */ + event: PopStateEvent; +} + +export interface NavigationLink extends NavigationBase { + /** + * The type of navigation: + * - `link`: Navigation was triggered by a link click + */ + type: 'link'; + + /** + * The `PointerEvent` that caused the navigation + */ + event: PointerEvent; + + // TODO 3.0 remove this property, so that it only exists when type is 'popstate' + // (would possibly be a breaking change to do it prior to that) + /** + * In case of a history back/forward navigation, the number of steps to go back/forward + */ + delta?: undefined; +} + +export type Navigation = + | NavigationExternal + | NavigationFormSubmit + | NavigationPopState + | NavigationLink; + +/** + * The argument passed to [`beforeNavigate`](https://svelte.dev/docs/kit/$app-navigation#beforeNavigate) callbacks. + */ +export type BeforeNavigate = Navigation & { + /** + * Call this to prevent the navigation from starting. + */ + cancel: () => void; +}; + +/** + * The argument passed to [`onNavigate`](https://svelte.dev/docs/kit/$app-navigation#onNavigate) callbacks. + */ +export type OnNavigate = Navigation & { + type: Exclude; + /** + * Since `onNavigate` callbacks are called immediately before a client-side navigation, they will never be called with a navigation that unloads the page. + */ + willUnload: false; +}; + +/** + * The argument passed to [`afterNavigate`](https://svelte.dev/docs/kit/$app-navigation#afterNavigate) callbacks. + */ +export type AfterNavigate = (Navigation | NavigationEnter) & { + type: Exclude; + /** + * Since `afterNavigate` callbacks are called after a navigation completes, they will never be called with a navigation that unloads the page. + */ + willUnload: false; +}; + +/** + * The shape of the [`page`](https://svelte.dev/docs/kit/$app-state#page) reactive object and the [`$page`](https://svelte.dev/docs/kit/$app-stores) store. + */ +export interface Page< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + RouteId extends AppRouteId | null = AppRouteId | null +> { + /** + * The URL of the current page. + */ + url: URL & { pathname: ResolvedPathname }; + /** + * The parameters of the current page - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object. + */ + params: Params; + /** + * Info about the current route. + */ + route: { + /** + * The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]`. It is `null` when no route is matched. + */ + id: RouteId; + }; + /** + * HTTP status code of the current page. + */ + status: number; + /** + * The error object of the current page, if any. Filled from the `handleError` hooks. + */ + error: App.Error | null; + /** + * The merged result of all data from all `load` functions on the current page. You can type a common denominator through `App.PageData`. + */ + data: App.PageData & Record; + /** + * The page state, which can be manipulated using the [`pushState`](https://svelte.dev/docs/kit/$app-navigation#pushState) and [`replaceState`](https://svelte.dev/docs/kit/$app-navigation#replaceState) functions from `$app/navigation`. + */ + state: App.PageState; + /** + * Filled only after a form submission. See [form actions](https://svelte.dev/docs/kit/form-actions) for more info. + */ + form: any; +} + +/** + * The shape of a param matcher. See [matching](https://svelte.dev/docs/kit/advanced-routing#Matching) for more info. + */ +export type ParamMatcher = (param: string) => boolean; + +export interface RequestEvent< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + RouteId extends AppRouteId | null = AppRouteId | null +> { + /** + * Get or set cookies related to the current request + */ + cookies: Cookies; + /** + * `fetch` is equivalent to the [native `fetch` web API](https://developer.mozilla.org/en-US/docs/Web/API/fetch), with a few additional features: + * + * - It can be used to make credentialed requests on the server, as it inherits the `cookie` and `authorization` headers for the page request. + * - It can make relative requests on the server (ordinarily, `fetch` requires a URL with an origin when used in a server context). + * - Internal requests (e.g. for `+server.js` routes) go directly to the handler function when running on the server, without the overhead of an HTTP call. + * - During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the `text` and `json` methods of the `Response` object. Note that headers will _not_ be serialized, unless explicitly included via [`filterSerializedResponseHeaders`](https://svelte.dev/docs/kit/hooks#Server-hooks-handle) + * - During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request. + * + * You can learn more about making credentialed requests with cookies [here](https://svelte.dev/docs/kit/load#Cookies). + */ + fetch: typeof fetch; + /** + * The client's IP address, set by the adapter. + */ + getClientAddress: () => string; + /** + * Contains custom data that was added to the request within the [`server handle hook`](https://svelte.dev/docs/kit/hooks#Server-hooks-handle). + */ + locals: App.Locals; + /** + * The parameters of the current route - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object. + */ + params: Params; + /** + * Additional data made available through the adapter. + */ + platform: Readonly | undefined; + /** + * The original request object. + */ + request: Request; + /** + * Info about the current route. + */ + route: { + /** + * The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]`. It is `null` when no route is matched. + */ + id: RouteId; + }; + /** + * If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example: + * + * ```js + * /// file: src/routes/blog/+page.js + * export async function load({ fetch, setHeaders }) { + * const url = `https://cms.example.com/articles.json`; + * const response = await fetch(url); + * + * setHeaders({ + * age: response.headers.get('age'), + * 'cache-control': response.headers.get('cache-control') + * }); + * + * return response.json(); + * } + * ``` + * + * Setting the same header multiple times (even in separate `load` functions) is an error — you can only set a given header once. + * + * You cannot add a `set-cookie` header with `setHeaders` — use the [`cookies`](https://svelte.dev/docs/kit/@sveltejs-kit#Cookies) API instead. + */ + setHeaders: (headers: Record) => void; + /** + * The requested URL. + */ + url: URL; + /** + * `true` if the request comes from the client asking for `+page/layout.server.js` data. The `url` property will be stripped of the internal information + * related to the data request in this case. Use this property instead if the distinction is important to you. + */ + isDataRequest: boolean; + /** + * `true` for `+server.js` calls coming from SvelteKit without the overhead of actually making an HTTP request. This happens when you make same-origin `fetch` requests on the server. + */ + isSubRequest: boolean; + + /** + * Access to spans for tracing. If tracing is not enabled, these spans will do nothing. + * @since 2.31.0 + */ + tracing: { + /** Whether tracing is enabled. */ + enabled: boolean; + /** The root span for the request. This span is named `sveltekit.handle.root`. */ + root: Span; + /** The span associated with the current `handle` hook, `load` function, or form action. */ + current: Span; + }; + + /** + * `true` if the request comes from the client via a remote function. The `url` property will be stripped of the internal information + * related to the data request in this case. Use this property instead if the distinction is important to you. + */ + isRemoteRequest: boolean; +} + +/** + * A `(event: RequestEvent) => Response` function exported from a `+server.js` file that corresponds to an HTTP verb (`GET`, `PUT`, `PATCH`, etc) and handles requests with that method. + * + * It receives `Params` as the first generic argument, which you can skip by using [generated types](https://svelte.dev/docs/kit/types#Generated-types) instead. + */ +export type RequestHandler< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + RouteId extends AppRouteId | null = AppRouteId | null +> = (event: RequestEvent) => MaybePromise; + +export interface ResolveOptions { + /** + * Applies custom transforms to HTML. If `done` is true, it's the final chunk. Chunks are not guaranteed to be well-formed HTML + * (they could include an element's opening tag but not its closing tag, for example) + * but they will always be split at sensible boundaries such as `%sveltekit.head%` or layout/page components. + * @param input the html chunk and the info if this is the last chunk + */ + transformPageChunk?: (input: { html: string; done: boolean }) => MaybePromise; + /** + * Determines which headers should be included in serialized responses when a `load` function loads a resource with `fetch`. + * By default, none will be included. + * @param name header name + * @param value header value + */ + filterSerializedResponseHeaders?: (name: string, value: string) => boolean; + /** + * Determines what should be added to the `` tag to preload it. + * By default, `js` and `css` files will be preloaded. + * @param input the type of the file and its path + */ + preload?: (input: { type: 'font' | 'css' | 'js' | 'asset'; path: string }) => boolean; +} + +export interface RouteDefinition { + id: string; + api: { + methods: Array; + }; + page: { + methods: Array>; + }; + pattern: RegExp; + prerender: PrerenderOption; + segments: RouteSegment[]; + methods: Array; + config: Config; +} + +export class Server { + constructor(manifest: SSRManifest); + init(options: ServerInitOptions): Promise; + respond(request: Request, options: RequestOptions): Promise; +} + +export interface ServerInitOptions { + /** A map of environment variables. */ + env: Record; + /** A function that turns an asset filename into a `ReadableStream`. Required for the `read` export from `$app/server` to work. */ + read?: (file: string) => MaybePromise; +} + +export interface SSRManifest { + appDir: string; + appPath: string; + /** Static files from `kit.config.files.assets` and the service worker (if any). */ + assets: Set; + mimeTypes: Record; + + /** private fields */ + _: { + client: NonNullable; + nodes: SSRNodeLoader[]; + /** hashed filename -> import to that file */ + remotes: Record Promise>; + routes: SSRRoute[]; + prerendered_routes: Set; + matchers: () => Promise>; + /** A `[file]: size` map of all assets imported by server code. */ + server_assets: Record; + }; +} + +/** + * The generic form of `PageServerLoad` and `LayoutServerLoad`. You should import those from `./$types` (see [generated types](https://svelte.dev/docs/kit/types#Generated-types)) + * rather than using `ServerLoad` directly. + */ +export type ServerLoad< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + ParentData extends Record = Record, + OutputData extends Record | void = Record | void, + RouteId extends AppRouteId | null = AppRouteId | null +> = (event: ServerLoadEvent) => MaybePromise; + +export interface ServerLoadEvent< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + ParentData extends Record = Record, + RouteId extends AppRouteId | null = AppRouteId | null +> extends RequestEvent { + /** + * `await parent()` returns data from parent `+layout.server.js` `load` functions. + * + * Be careful not to introduce accidental waterfalls when using `await parent()`. If for example you only want to merge parent data into the returned output, call it _after_ fetching your other data. + */ + parent: () => Promise; + /** + * This function declares that the `load` function has a _dependency_ on one or more URLs or custom identifiers, which can subsequently be used with [`invalidate()`](https://svelte.dev/docs/kit/$app-navigation#invalidate) to cause `load` to rerun. + * + * Most of the time you won't need this, as `fetch` calls `depends` on your behalf — it's only necessary if you're using a custom API client that bypasses `fetch`. + * + * URLs can be absolute or relative to the page being loaded, and must be [encoded](https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding). + * + * Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the [URI specification](https://www.rfc-editor.org/rfc/rfc3986.html). + * + * The following example shows how to use `depends` to register a dependency on a custom identifier, which is `invalidate`d after a button click, making the `load` function rerun. + * + * ```js + * /// file: src/routes/+page.js + * let count = 0; + * export async function load({ depends }) { + * depends('increase:count'); + * + * return { count: count++ }; + * } + * ``` + * + * ```html + * /// file: src/routes/+page.svelte + * + * + *

{data.count}

+ * + * ``` + */ + depends: (...deps: string[]) => void; + /** + * Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example: + * + * ```js + * /// file: src/routes/+page.js + * export async function load({ untrack, url }) { + * // Untrack url.pathname so that path changes don't trigger a rerun + * if (untrack(() => url.pathname === '/')) { + * return { message: 'Welcome!' }; + * } + * } + * ``` + */ + untrack: (fn: () => T) => T; + + /** + * Access to spans for tracing. If tracing is not enabled, these spans will do nothing. + * @since 2.31.0 + */ + tracing: { + /** Whether tracing is enabled. */ + enabled: boolean; + /** The root span for the request. This span is named `sveltekit.handle.root`. */ + root: Span; + /** The span associated with the current server `load` function. */ + current: Span; + }; +} + +/** + * Shape of a form action method that is part of `export const actions = {...}` in `+page.server.js`. + * See [form actions](https://svelte.dev/docs/kit/form-actions) for more information. + */ +export type Action< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + OutputData extends Record | void = Record | void, + RouteId extends AppRouteId | null = AppRouteId | null +> = (event: RequestEvent) => MaybePromise; + +/** + * Shape of the `export const actions = {...}` object in `+page.server.js`. + * See [form actions](https://svelte.dev/docs/kit/form-actions) for more information. + */ +export type Actions< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + OutputData extends Record | void = Record | void, + RouteId extends AppRouteId | null = AppRouteId | null +> = Record>; + +/** + * When calling a form action via fetch, the response will be one of these shapes. + * ```svelte + * { + * return ({ result }) => { + * // result is of type ActionResult + * }; + * }} + * ``` + */ +export type ActionResult< + Success extends Record | undefined = Record, + Failure extends Record | undefined = Record +> = + | { type: 'success'; status: number; data?: Success } + | { type: 'failure'; status: number; data?: Failure } + | { type: 'redirect'; status: number; location: string } + | { type: 'error'; status?: number; error: any }; + +/** + * The object returned by the [`error`](https://svelte.dev/docs/kit/@sveltejs-kit#error) function. + */ +export interface HttpError { + /** The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses), in the range 400-599. */ + status: number; + /** The content of the error. */ + body: App.Error; +} + +/** + * The object returned by the [`redirect`](https://svelte.dev/docs/kit/@sveltejs-kit#redirect) function. + */ +export interface Redirect { + /** The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages), in the range 300-308. */ + status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308; + /** The location to redirect to. */ + location: string; +} + +export type SubmitFunction< + Success extends Record | undefined = Record, + Failure extends Record | undefined = Record +> = (input: { + action: URL; + formData: FormData; + formElement: HTMLFormElement; + controller: AbortController; + submitter: HTMLElement | null; + cancel: () => void; +}) => MaybePromise< + | void + | ((opts: { + formData: FormData; + formElement: HTMLFormElement; + action: URL; + result: ActionResult; + /** + * Call this to get the default behavior of a form submission response. + * @param options Set `reset: false` if you don't want the `` values to be reset after a successful submission. + * @param invalidateAll Set `invalidateAll: false` if you don't want the action to call `invalidateAll` after submission. + */ + update: (options?: { reset?: boolean; invalidateAll?: boolean }) => Promise; + }) => MaybePromise) +>; + +/** + * The type of `export const snapshot` exported from a page or layout component. + */ +export interface Snapshot { + capture: () => T; + restore: (snapshot: T) => void; +} + +// If T is unknown or has an index signature, the types below will recurse indefinitely and create giant unions that TS can't handle +type WillRecurseIndefinitely = unknown extends T ? true : string extends keyof T ? true : false; + +// Input type mappings for form fields +type InputTypeMap = { + text: string; + email: string; + password: string; + url: string; + tel: string; + search: string; + number: number; + range: number; + date: string; + 'datetime-local': string; + time: string; + month: string; + week: string; + color: string; + checkbox: boolean | string[]; + radio: string; + file: File; + hidden: string; + submit: string; + button: string; + reset: string; + image: string; + select: string; + 'select multiple': string[]; + 'file multiple': File[]; +}; + +// Valid input types for a given value type +export type RemoteFormFieldType = { + [K in keyof InputTypeMap]: T extends InputTypeMap[K] ? K : never; +}[keyof InputTypeMap]; + +// Input element properties based on type +type InputElementProps = T extends 'checkbox' | 'radio' + ? { + name: string; + type: T; + value?: string; + 'aria-invalid': boolean | 'false' | 'true' | undefined; + get checked(): boolean; + set checked(value: boolean); + } + : T extends 'file' + ? { + name: string; + type: 'file'; + 'aria-invalid': boolean | 'false' | 'true' | undefined; + get files(): FileList | null; + set files(v: FileList | null); + } + : T extends 'select' | 'select multiple' + ? { + name: string; + multiple: T extends 'select' ? false : true; + 'aria-invalid': boolean | 'false' | 'true' | undefined; + get value(): string | number; + set value(v: string | number); + } + : T extends 'text' + ? { + name: string; + 'aria-invalid': boolean | 'false' | 'true' | undefined; + get value(): string | number; + set value(v: string | number); + } + : { + name: string; + type: T; + 'aria-invalid': boolean | 'false' | 'true' | undefined; + get value(): string | number; + set value(v: string | number); + }; + +type RemoteFormFieldMethods = { + /** The values that will be submitted */ + value(): DeepPartial; + /** Set the values that will be submitted */ + set(input: DeepPartial): DeepPartial; + /** Validation issues, if any */ + issues(): RemoteFormIssue[] | undefined; +}; + +export type RemoteFormFieldValue = string | string[] | number | boolean | File | File[]; + +type AsArgs = Type extends 'checkbox' + ? Value extends string[] + ? [type: Type, value: Value[number] | (string & {})] + : [type: Type] + : Type extends 'radio' | 'submit' | 'hidden' + ? [type: Type, value: Value | (string & {})] + : [type: Type]; + +/** + * Form field accessor type that provides name(), value(), and issues() methods + */ +export type RemoteFormField = RemoteFormFieldMethods & { + /** + * Returns an object that can be spread onto an input element with the correct type attribute, + * aria-invalid attribute if the field is invalid, and appropriate value/checked property getters/setters. + * @example + * ```svelte + * + * + * + * ``` + */ + as>(...args: AsArgs): InputElementProps; +}; + +type RemoteFormFieldContainer = RemoteFormFieldMethods & { + /** Validation issues belonging to this or any of the fields that belong to it, if any */ + allIssues(): RemoteFormIssue[] | undefined; +}; + +type UnknownField = RemoteFormFieldMethods & { + /** Validation issues belonging to this or any of the fields that belong to it, if any */ + allIssues(): RemoteFormIssue[] | undefined; + /** + * Returns an object that can be spread onto an input element with the correct type attribute, + * aria-invalid attribute if the field is invalid, and appropriate value/checked property getters/setters. + * @example + * ```svelte + * + * + * + * ``` + */ + as>(...args: AsArgs): InputElementProps; +} & { + [key: string | number]: UnknownField; +}; + +type RemoteFormFieldsRoot = + IsAny extends true + ? RecursiveFormFields + : Input extends void + ? { + /** Validation issues, if any */ + issues(): RemoteFormIssue[] | undefined; + /** Validation issues belonging to this or any of the fields that belong to it, if any */ + allIssues(): RemoteFormIssue[] | undefined; + } + : RemoteFormFields; + +/** + * Recursive type to build form fields structure with proxy access + */ +export type RemoteFormFields = + WillRecurseIndefinitely extends true + ? RecursiveFormFields + : NonNullable extends string | number | boolean | File + ? RemoteFormField> + : T extends string[] | File[] + ? RemoteFormField & { [K in number]: RemoteFormField } + : T extends Array + ? RemoteFormFieldContainer & { + [K in number]: RemoteFormFields; + } + : RemoteFormFieldContainer & { + [K in keyof T]-?: RemoteFormFields; + }; + +// By breaking this out into its own type, we avoid the TS recursion depth limit +type RecursiveFormFields = RemoteFormFieldContainer & { + [key: string | number]: UnknownField; +}; + +type MaybeArray = T | T[]; + +export interface RemoteFormInput { + [key: string]: MaybeArray; +} + +export interface RemoteFormIssue { + message: string; + path: Array; +} + +// If the schema specifies `id` as a string or number, ensure that `for(...)` +// only accepts that type. Otherwise, accept `string | number` +type ExtractId = Input extends { id: infer Id } + ? Id extends string | number + ? Id + : string | number + : string | number; + +/** + * A function and proxy object used to imperatively create validation errors in form handlers. + * + * Access properties to create field-specific issues: `issue.fieldName('message')`. + * The type structure mirrors the input data structure for type-safe field access. + * Call `invalid(issue.foo(...), issue.nested.bar(...))` to throw a validation error. + */ +export type InvalidField = + WillRecurseIndefinitely extends true + ? Record + : NonNullable extends string | number | boolean | File + ? (message: string) => StandardSchemaV1.Issue + : NonNullable extends Array + ? { + [K in number]: InvalidField; + } & ((message: string) => StandardSchemaV1.Issue) + : NonNullable extends RemoteFormInput + ? { + [K in keyof T]-?: InvalidField; + } & ((message: string) => StandardSchemaV1.Issue) + : Record; + +/** + * A validation error thrown by `invalid`. + */ +export interface ValidationError { + /** The validation issues */ + issues: StandardSchemaV1.Issue[]; +} + +/** + * The return value of a remote `form` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#form) for full documentation. + */ +export type RemoteForm = { + /** Attachment that sets up an event handler that intercepts the form submission on the client to prevent a full page reload */ + [attachment: symbol]: (node: HTMLFormElement) => void; + method: 'POST'; + /** The URL to send the form to. */ + action: string; + /** Use the `enhance` method to influence what happens when the form is submitted. */ + enhance( + callback: (opts: { + form: HTMLFormElement; + data: Input; + submit: () => Promise & { + updates: (...queries: Array | RemoteQueryOverride>) => Promise; + }; + }) => void | Promise + ): { + method: 'POST'; + action: string; + [attachment: symbol]: (node: HTMLFormElement) => void; + }; + /** + * Create an instance of the form for the given `id`. + * The `id` is stringified and used for deduplication to potentially reuse existing instances. + * Useful when you have multiple forms that use the same remote form action, for example in a loop. + * ```svelte + * {#each todos as todo} + * {@const todoForm = updateTodo.for(todo.id)} + * + * {#if todoForm.result?.invalid}

Invalid data

{/if} + * ... + * + * {/each} + * ``` + */ + for(id: ExtractId): Omit, 'for'>; + /** Preflight checks */ + preflight(schema: StandardSchemaV1): RemoteForm; + /** Validate the form contents programmatically */ + validate(options?: { + /** Set this to `true` to also show validation issues of fields that haven't been touched yet. */ + includeUntouched?: boolean; + /** Set this to `true` to only run the `preflight` validation. */ + preflightOnly?: boolean; + }): Promise; + /** The result of the form submission */ + get result(): Output | undefined; + /** The number of pending submissions */ + get pending(): number; + /** Access form fields using object notation */ + fields: RemoteFormFieldsRoot; +}; + +/** + * The return value of a remote `command` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#command) for full documentation. + */ +export type RemoteCommand = { + (arg: undefined extends Input ? Input | void : Input): Promise> & { + updates(...queries: Array | RemoteQueryOverride>): Promise>; + }; + /** The number of pending command executions */ + get pending(): number; +}; + +export type RemoteResource = Promise> & { + /** The error in case the query fails. Most often this is a [`HttpError`](https://svelte.dev/docs/kit/@sveltejs-kit#HttpError) but it isn't guaranteed to be. */ + get error(): any; + /** `true` before the first result is available and during refreshes */ + get loading(): boolean; +} & ( + | { + /** The current value of the query. Undefined until `ready` is `true` */ + get current(): undefined; + ready: false; + } + | { + /** The current value of the query. Undefined until `ready` is `true` */ + get current(): Awaited; + ready: true; + } + ); + +export type RemoteQuery = RemoteResource & { + /** + * On the client, this function will update the value of the query without re-fetching it. + * + * On the server, this can be called in the context of a `command` or `form` and the specified data will accompany the action response back to the client. + * This prevents SvelteKit needing to refresh all queries on the page in a second server round-trip. + */ + set(value: T): void; + /** + * On the client, this function will re-fetch the query from the server. + * + * On the server, this can be called in the context of a `command` or `form` and the refreshed data will accompany the action response back to the client. + * This prevents SvelteKit needing to refresh all queries on the page in a second server round-trip. + */ + refresh(): Promise; + /** + * Temporarily override the value of a query. This is used with the `updates` method of a [command](https://svelte.dev/docs/kit/remote-functions#command-Updating-queries) or [enhanced form submission](https://svelte.dev/docs/kit/remote-functions#form-enhance) to provide optimistic updates. + * + * ```svelte + * + * + *
{ + * await submit().updates( + * todos.withOverride((todos) => [...todos, { text: data.get('text') }]) + * ); + * })}> + * + * + *
+ * ``` + */ + withOverride(update: (current: Awaited) => Awaited): RemoteQueryOverride; +}; + +export interface RemoteQueryOverride { + _key: string; + release(): void; +} + +/** + * The return value of a remote `prerender` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#prerender) for full documentation. + */ +export type RemotePrerenderFunction = ( + arg: undefined extends Input ? Input | void : Input +) => RemoteResource; + +/** + * The return value of a remote `query` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#query) for full documentation. + */ +export type RemoteQueryFunction = ( + arg: undefined extends Input ? Input | void : Input +) => RemoteQuery; + +export * from './index.js'; diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/vite/dev/index.js b/frontend/node_modules/@sveltejs/kit/src/exports/vite/dev/index.js new file mode 100644 index 0000000..031856f --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/vite/dev/index.js @@ -0,0 +1,669 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; +import { URL } from 'node:url'; +import { AsyncLocalStorage } from 'node:async_hooks'; +import colors from 'kleur'; +import sirv from 'sirv'; +import { isCSSRequest, loadEnv, buildErrorMessage } from 'vite'; +import { createReadableStream, getRequest, setResponse } from '../../../exports/node/index.js'; +import { installPolyfills } from '../../../exports/node/polyfills.js'; +import { coalesce_to_error } from '../../../utils/error.js'; +import { from_fs, posixify, resolve_entry, to_fs } from '../../../utils/filesystem.js'; +import { load_error_page } from '../../../core/config/index.js'; +import { SVELTE_KIT_ASSETS } from '../../../constants.js'; +import * as sync from '../../../core/sync/sync.js'; +import { get_mime_lookup, runtime_base } from '../../../core/utils.js'; +import { compact } from '../../../utils/array.js'; +import { not_found } from '../utils.js'; +import { SCHEME } from '../../../utils/url.js'; +import { check_feature } from '../../../utils/features.js'; +import { escape_html } from '../../../utils/escape.js'; + +const cwd = process.cwd(); +// vite-specifc queries that we should skip handling for css urls +const vite_css_query_regex = /(?:\?|&)(?:raw|url|inline)(?:&|$)/; + +/** + * @param {import('vite').ViteDevServer} vite + * @param {import('vite').ResolvedConfig} vite_config + * @param {import('types').ValidatedConfig} svelte_config + * @param {() => Array<{ hash: string, file: string }>} get_remotes + * @return {Promise void>>} + */ +export async function dev(vite, vite_config, svelte_config, get_remotes) { + installPolyfills(); + + const async_local_storage = new AsyncLocalStorage(); + + globalThis.__SVELTEKIT_TRACK__ = (label) => { + const context = async_local_storage.getStore(); + if (!context || context.prerender === true) return; + + check_feature(context.event.route.id, context.config, label, svelte_config.kit.adapter); + }; + + const fetch = globalThis.fetch; + globalThis.fetch = (info, init) => { + if (typeof info === 'string' && !SCHEME.test(info)) { + throw new Error( + `Cannot use relative URL (${info}) with global fetch — use \`event.fetch\` instead: https://svelte.dev/docs/kit/web-standards#fetch-apis` + ); + } + + return fetch(info, init); + }; + + sync.init(svelte_config, vite_config.mode); + + /** @type {import('types').ManifestData} */ + let manifest_data; + /** @type {import('@sveltejs/kit').SSRManifest} */ + let manifest; + + /** @type {Error | null} */ + let manifest_error = null; + + /** @param {string} url */ + async function loud_ssr_load_module(url) { + try { + return await vite.ssrLoadModule(url, { fixStacktrace: true }); + } catch (/** @type {any} */ err) { + const msg = buildErrorMessage(err, [colors.red(`Internal server error: ${err.message}`)]); + + if (!vite.config.logger.hasErrorLogged(err)) { + vite.config.logger.error(msg, { error: err }); + } + + vite.ws.send({ + type: 'error', + err: { + ...err, + // these properties are non-enumerable and will + // not be serialized unless we explicitly include them + message: err.message, + stack: err.stack + } + }); + + throw err; + } + } + + /** @param {string} id */ + async function resolve(id) { + const url = id.startsWith('..') ? to_fs(path.posix.resolve(id)) : `/${id}`; + + const module = await loud_ssr_load_module(url); + + const module_node = await vite.moduleGraph.getModuleByUrl(url); + if (!module_node) throw new Error(`Could not find node for ${url}`); + + return { module, module_node, url }; + } + + function update_manifest() { + try { + ({ manifest_data } = sync.create(svelte_config)); + + if (manifest_error) { + manifest_error = null; + vite.ws.send({ type: 'full-reload' }); + } + } catch (error) { + manifest_error = /** @type {Error} */ (error); + + console.error(colors.bold().red(manifest_error.message)); + vite.ws.send({ + type: 'error', + err: { + message: manifest_error.message ?? 'Invalid routes', + stack: '' + } + }); + + return; + } + + manifest = { + appDir: svelte_config.kit.appDir, + appPath: svelte_config.kit.appDir, + assets: new Set(manifest_data.assets.map((asset) => asset.file)), + mimeTypes: get_mime_lookup(manifest_data), + _: { + client: { + start: `${runtime_base}/client/entry.js`, + app: `${to_fs(svelte_config.kit.outDir)}/generated/client/app.js`, + imports: [], + stylesheets: [], + fonts: [], + uses_env_dynamic_public: true, + nodes: + svelte_config.kit.router.resolution === 'client' + ? undefined + : manifest_data.nodes.map((node, i) => { + if (node.component || node.universal) { + return `${svelte_config.kit.paths.base}${to_fs(svelte_config.kit.outDir)}/generated/client/nodes/${i}.js`; + } + }), + // `css` is not necessary in dev, as the JS file from `nodes` will reference the CSS file + routes: + svelte_config.kit.router.resolution === 'client' + ? undefined + : compact( + manifest_data.routes.map((route) => { + if (!route.page) return; + + return { + id: route.id, + pattern: route.pattern, + params: route.params, + layouts: route.page.layouts.map((l) => + l !== undefined ? [!!manifest_data.nodes[l].server, l] : undefined + ), + errors: route.page.errors, + leaf: [!!manifest_data.nodes[route.page.leaf].server, route.page.leaf] + }; + }) + ) + }, + server_assets: new Proxy( + {}, + { + has: (_, /** @type {string} */ file) => fs.existsSync(from_fs(file)), + get: (_, /** @type {string} */ file) => fs.statSync(from_fs(file)).size + } + ), + nodes: manifest_data.nodes.map((node, index) => { + return async () => { + /** @type {import('types').SSRNode} */ + const result = {}; + result.index = index; + result.universal_id = node.universal; + result.server_id = node.server; + + // these are unused in dev, but it's easier to include them + result.imports = []; + result.stylesheets = []; + result.fonts = []; + + /** @type {import('vite').ModuleNode[]} */ + const module_nodes = []; + + if (node.component) { + result.component = async () => { + const { module_node, module } = await resolve( + /** @type {string} */ (node.component) + ); + + module_nodes.push(module_node); + + return module.default; + }; + } + + if (node.universal) { + if (node.page_options?.ssr === false) { + result.universal = node.page_options; + } else { + // TODO: explain why the file was loaded on the server if we fail to load it + const { module, module_node } = await resolve(node.universal); + module_nodes.push(module_node); + result.universal = module; + } + } + + if (node.server) { + const { module } = await resolve(node.server); + result.server = module; + } + + // in dev we inline all styles to avoid FOUC. this gets populated lazily so that + // components/stylesheets loaded via import() during `load` are included + result.inline_styles = async () => { + /** @type {Set} */ + const deps = new Set(); + + for (const module_node of module_nodes) { + await find_deps(vite, module_node, deps); + } + + /** @type {Record} */ + const styles = {}; + + for (const dep of deps) { + if (isCSSRequest(dep.url) && !vite_css_query_regex.test(dep.url)) { + const inlineCssUrl = dep.url.includes('?') + ? dep.url.replace('?', '?inline&') + : dep.url + '?inline'; + try { + const mod = await vite.ssrLoadModule(inlineCssUrl); + styles[dep.url] = mod.default; + } catch { + // this can happen with dynamically imported modules, I think + // because the Vite module graph doesn't distinguish between + // static and dynamic imports? TODO investigate, submit fix + } + } + } + + return styles; + }; + + return result; + }; + }), + prerendered_routes: new Set(), + get remotes() { + return Object.fromEntries( + get_remotes().map((remote) => [ + remote.hash, + () => vite.ssrLoadModule(remote.file).then((module) => ({ default: module })) + ]) + ); + }, + routes: compact( + manifest_data.routes.map((route) => { + if (!route.page && !route.endpoint) return null; + + const endpoint = route.endpoint; + + return { + id: route.id, + pattern: route.pattern, + params: route.params, + page: route.page, + endpoint: endpoint + ? async () => { + const url = path.resolve(cwd, endpoint.file); + return await loud_ssr_load_module(url); + } + : null, + endpoint_id: endpoint?.file + }; + }) + ), + matchers: async () => { + /** @type {Record} */ + const matchers = {}; + + for (const key in manifest_data.matchers) { + const file = manifest_data.matchers[key]; + const url = path.resolve(cwd, file); + const module = await vite.ssrLoadModule(url, { fixStacktrace: true }); + + if (module.match) { + matchers[key] = module.match; + } else { + throw new Error(`${file} does not export a \`match\` function`); + } + } + + return matchers; + } + } + }; + } + + /** @param {Error} error */ + function fix_stack_trace(error) { + try { + vite.ssrFixStacktrace(error); + } catch { + // ssrFixStacktrace can fail on StackBlitz web containers and we don't know why + // by ignoring it the line numbers are wrong, but at least we can show the error + } + return error.stack; + } + + update_manifest(); + + /** + * @param {string} event + * @param {(file: string) => void} cb + */ + const watch = (event, cb) => { + vite.watcher.on(event, (file) => { + if ( + file.startsWith(svelte_config.kit.files.routes + path.sep) || + file.startsWith(svelte_config.kit.files.params + path.sep) || + svelte_config.kit.moduleExtensions.some((ext) => file.endsWith(`.remote${ext}`)) || + // in contrast to server hooks, client hooks are written to the client manifest + // and therefore need rebuilding when they are added/removed + file.startsWith(svelte_config.kit.files.hooks.client) + ) { + cb(file); + } + }); + }; + /** @type {NodeJS.Timeout | null } */ + let timeout = null; + /** @param {() => void} to_run */ + const debounce = (to_run) => { + timeout && clearTimeout(timeout); + timeout = setTimeout(() => { + timeout = null; + to_run(); + }, 100); + }; + + // flag to skip watchers if server is already restarting + let restarting = false; + + // Debounce add/unlink events because in case of folder deletion or moves + // they fire in rapid succession, causing needless invocations. + // These watchers only run for routes, param matchers, and client hooks. + watch('add', () => debounce(update_manifest)); + watch('unlink', () => debounce(update_manifest)); + watch('change', (file) => { + // Don't run for a single file if the whole manifest is about to get updated + // Unless it's a file where the trailing slash page option might have changed + if (timeout || restarting || !/\+(page|layout|server).*$/.test(file)) return; + sync.update(svelte_config, manifest_data, file); + }); + + const { appTemplate, errorTemplate, serviceWorker, hooks } = svelte_config.kit.files; + + // vite client only executes a full reload if the triggering html file path is index.html + // kit defaults to src/app.html, so unless user changed that to index.html + // send the vite client a full-reload event without path being set + if (appTemplate !== 'index.html') { + vite.watcher.on('change', (file) => { + if (file === appTemplate && !restarting) { + vite.ws.send({ type: 'full-reload' }); + } + }); + } + + vite.watcher.on('all', (_, file) => { + if ( + file === appTemplate || + file === errorTemplate || + file.startsWith(serviceWorker) || + file.startsWith(hooks.server) + ) { + sync.server(svelte_config); + } + }); + + vite.watcher.on('change', async (file) => { + // changing the svelte config requires restarting the dev server + // the config is only read on start and passed on to vite-plugin-svelte + // which needs up-to-date values to operate correctly + if (file.match(/[/\\]svelte\.config\.[jt]s$/)) { + console.log(`svelte config changed, restarting vite dev-server. changed file: ${file}`); + restarting = true; + await vite.restart(); + } + }); + + const assets = svelte_config.kit.paths.assets ? SVELTE_KIT_ASSETS : svelte_config.kit.paths.base; + const asset_server = sirv(svelte_config.kit.files.assets, { + dev: true, + etag: true, + maxAge: 0, + extensions: [], + setHeaders: (res) => { + res.setHeader('access-control-allow-origin', '*'); + } + }); + + vite.middlewares.use((req, res, next) => { + const base = `${vite.config.server.https ? 'https' : 'http'}://${ + req.headers[':authority'] || req.headers.host + }`; + + const decoded = decodeURI(new URL(base + req.url).pathname); + + if (decoded.startsWith(assets)) { + const pathname = decoded.slice(assets.length); + const file = svelte_config.kit.files.assets + pathname; + + if (fs.existsSync(file) && !fs.statSync(file).isDirectory()) { + if (has_correct_case(file, svelte_config.kit.files.assets)) { + req.url = encodeURI(pathname); // don't need query/hash + asset_server(req, res); + return; + } + } + } + + next(); + }); + + const env = loadEnv(vite_config.mode, svelte_config.kit.env.dir, ''); + const emulator = await svelte_config.kit.adapter?.emulate?.(); + + return () => { + const serve_static_middleware = vite.middlewares.stack.find( + (middleware) => + /** @type {function} */ (middleware.handle).name === 'viteServeStaticMiddleware' + ); + + // Vite will give a 403 on URLs like /test, /static, and /package.json preventing us from + // serving routes with those names. See https://github.com/vitejs/vite/issues/7363 + remove_static_middlewares(vite.middlewares); + + vite.middlewares.use(async (req, res) => { + // Vite's base middleware strips out the base path. Restore it + const original_url = req.url; + req.url = req.originalUrl; + try { + const base = `${vite.config.server.https ? 'https' : 'http'}://${ + req.headers[':authority'] || req.headers.host + }`; + + const decoded = decodeURI(new URL(base + req.url).pathname); + const file = posixify(path.resolve(decoded.slice(svelte_config.kit.paths.base.length + 1))); + const is_file = fs.existsSync(file) && !fs.statSync(file).isDirectory(); + const allowed = + !vite_config.server.fs.strict || + vite_config.server.fs.allow.some((dir) => file.startsWith(dir)); + + if (is_file && allowed) { + req.url = original_url; + // @ts-expect-error + serve_static_middleware.handle(req, res); + return; + } + + if (!decoded.startsWith(svelte_config.kit.paths.base)) { + return not_found(req, res, svelte_config.kit.paths.base); + } + + if (decoded === svelte_config.kit.paths.base + '/service-worker.js') { + const resolved = resolve_entry(svelte_config.kit.files.serviceWorker); + + if (resolved) { + res.writeHead(200, { + 'content-type': 'application/javascript' + }); + res.end(`import '${svelte_config.kit.paths.base}${to_fs(resolved)}';`); + } else { + res.writeHead(404); + res.end('not found'); + } + + return; + } + + const resolved_instrumentation = resolve_entry( + path.join(svelte_config.kit.files.src, 'instrumentation.server') + ); + + if (resolved_instrumentation) { + await vite.ssrLoadModule(resolved_instrumentation); + } + + // we have to import `Server` before calling `set_assets` + const { Server } = /** @type {import('types').ServerModule} */ ( + await vite.ssrLoadModule(`${runtime_base}/server/index.js`, { fixStacktrace: true }) + ); + + const { set_fix_stack_trace } = await vite.ssrLoadModule( + `${runtime_base}/shared-server.js` + ); + set_fix_stack_trace(fix_stack_trace); + + const { set_assets } = await vite.ssrLoadModule('$app/paths/internal/server'); + set_assets(assets); + + const server = new Server(manifest); + + await server.init({ + env, + read: (file) => createReadableStream(from_fs(file)) + }); + + const request = await getRequest({ + base, + request: req + }); + + if (manifest_error) { + console.error(colors.bold().red(manifest_error.message)); + + const error_page = load_error_page(svelte_config); + + /** @param {{ status: number; message: string }} opts */ + const error_template = ({ status, message }) => { + return error_page + .replace(/%sveltekit\.status%/g, String(status)) + .replace(/%sveltekit\.error\.message%/g, escape_html(message)); + }; + + res.writeHead(500, { + 'Content-Type': 'text/html; charset=utf-8' + }); + res.end( + error_template({ status: 500, message: manifest_error.message ?? 'Invalid routes' }) + ); + + return; + } + + const rendered = await server.respond(request, { + getClientAddress: () => { + const { remoteAddress } = req.socket; + if (remoteAddress) return remoteAddress; + throw new Error('Could not determine clientAddress'); + }, + read: (file) => { + if (file in manifest._.server_assets) { + return fs.readFileSync(from_fs(file)); + } + + return fs.readFileSync(path.join(svelte_config.kit.files.assets, file)); + }, + before_handle: (event, config, prerender) => { + async_local_storage.enterWith({ event, config, prerender }); + }, + emulator + }); + + if (rendered.status === 404) { + // @ts-expect-error + serve_static_middleware.handle(req, res, () => { + void setResponse(res, rendered); + }); + } else { + void setResponse(res, rendered); + } + } catch (e) { + const error = coalesce_to_error(e); + res.statusCode = 500; + res.end(fix_stack_trace(error)); + } + }); + }; +} + +/** + * @param {import('connect').Server} server + */ +function remove_static_middlewares(server) { + const static_middlewares = ['viteServeStaticMiddleware', 'viteServePublicMiddleware']; + for (let i = server.stack.length - 1; i > 0; i--) { + // @ts-expect-error using internals + if (static_middlewares.includes(server.stack[i].handle.name)) { + server.stack.splice(i, 1); + } + } +} + +/** + * @param {import('vite').ViteDevServer} vite + * @param {import('vite').ModuleNode | import('vite').EnvironmentModuleNode} node + * @param {Set} deps + */ +async function find_deps(vite, node, deps) { + // since `ssrTransformResult.deps` contains URLs instead of `ModuleNode`s, this process is asynchronous. + // instead of using `await`, we resolve all branches in parallel. + /** @type {Promise[]} */ + const branches = []; + + /** @param {import('vite').ModuleNode | import('vite').EnvironmentModuleNode} node */ + async function add(node) { + if (!deps.has(node)) { + deps.add(node); + await find_deps(vite, node, deps); + } + } + + /** @param {string} url */ + async function add_by_url(url) { + const node = await get_server_module_by_url(vite, url); + + if (node) { + await add(node); + } + } + + const transform_result = + /** @type {import('vite').ModuleNode} */ (node).ssrTransformResult || node.transformResult; + + if (transform_result) { + if (transform_result.deps) { + transform_result.deps.forEach((url) => branches.push(add_by_url(url))); + } + + if (transform_result.dynamicDeps) { + transform_result.dynamicDeps.forEach((url) => branches.push(add_by_url(url))); + } + } else { + node.importedModules.forEach((node) => branches.push(add(node))); + } + + await Promise.all(branches); +} + +/** + * @param {import('vite').ViteDevServer} vite + * @param {string} url + */ +function get_server_module_by_url(vite, url) { + return vite.environments + ? vite.environments.ssr.moduleGraph.getModuleByUrl(url) + : vite.moduleGraph.getModuleByUrl(url, true); +} + +/** + * Determine if a file is being requested with the correct case, + * to ensure consistent behaviour between dev and prod and across + * operating systems. Note that we can't use realpath here, + * because we don't want to follow symlinks + * @param {string} file + * @param {string} assets + * @returns {boolean} + */ +function has_correct_case(file, assets) { + if (file === assets) return true; + + const parent = path.dirname(file); + + if (fs.readdirSync(parent).includes(path.basename(file))) { + return has_correct_case(parent, assets); + } + + return false; +} diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/vite/index.js b/frontend/node_modules/@sveltejs/kit/src/exports/vite/index.js new file mode 100644 index 0000000..7e22d5e --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/vite/index.js @@ -0,0 +1,1464 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; + +import colors from 'kleur'; + +import { copy, mkdirp, posixify, read, resolve_entry, rimraf } from '../../utils/filesystem.js'; +import { create_static_module, create_dynamic_module } from '../../core/env.js'; +import * as sync from '../../core/sync/sync.js'; +import { create_assets } from '../../core/sync/create_manifest_data/index.js'; +import { runtime_directory, logger } from '../../core/utils.js'; +import { load_config } from '../../core/config/index.js'; +import { generate_manifest } from '../../core/generate_manifest/index.js'; +import { build_server_nodes } from './build/build_server.js'; +import { build_service_worker } from './build/build_service_worker.js'; +import { assets_base, find_deps, resolve_symlinks } from './build/utils.js'; +import { dev } from './dev/index.js'; +import { preview } from './preview/index.js'; +import { + error_for_missing_config, + get_config_aliases, + get_env, + normalize_id, + stackless +} from './utils.js'; +import { write_client_manifest } from '../../core/sync/write_client_manifest.js'; +import prerender from '../../core/postbuild/prerender.js'; +import analyse from '../../core/postbuild/analyse.js'; +import { s } from '../../utils/misc.js'; +import { hash } from '../../utils/hash.js'; +import { dedent, isSvelte5Plus } from '../../core/sync/utils.js'; +import { + env_dynamic_private, + env_dynamic_public, + env_static_private, + env_static_public, + service_worker, + sveltekit_environment, + sveltekit_server +} from './module_ids.js'; +import { import_peer } from '../../utils/import.js'; +import { compact } from '../../utils/array.js'; +import { should_ignore, has_children } from './static_analysis/utils.js'; + +const cwd = posixify(process.cwd()); + +/** @type {import('./types.js').EnforcedConfig} */ +const enforced_config = { + appType: true, + base: true, + build: { + cssCodeSplit: true, + emptyOutDir: true, + lib: { + entry: true, + name: true, + formats: true + }, + manifest: true, + outDir: true, + rollupOptions: { + input: true, + output: { + format: true, + entryFileNames: true, + chunkFileNames: true, + assetFileNames: true + }, + preserveEntrySignatures: true + }, + ssr: true + }, + publicDir: true, + resolve: { + alias: { + $app: true, + $lib: true, + '$service-worker': true + } + }, + root: true +}; + +const options_regex = /(export\s+const\s+(prerender|csr|ssr|trailingSlash))\s*=/s; + +/** @type {Set} */ +const warned = new Set(); + +/** @type {import('svelte/compiler').PreprocessorGroup} */ +const warning_preprocessor = { + script: ({ content, filename }) => { + if (!filename) return; + + const basename = path.basename(filename); + if (basename.startsWith('+page.') || basename.startsWith('+layout.')) { + const match = content.match(options_regex); + if (match && match.index !== undefined && !should_ignore(content, match.index)) { + const fixed = basename.replace('.svelte', '(.server).js/ts'); + + const message = + `\n${colors.bold().red(path.relative('.', filename))}\n` + + `\`${match[1]}\` will be ignored — move it to ${fixed} instead. See https://svelte.dev/docs/kit/page-options for more information.`; + + if (!warned.has(message)) { + console.log(message); + warned.add(message); + } + } + } + }, + markup: ({ content, filename }) => { + if (!filename) return; + + const basename = path.basename(filename); + + if (basename.startsWith('+layout.') && !has_children(content, isSvelte5Plus())) { + const message = + `\n${colors.bold().red(path.relative('.', filename))}\n` + + `\`\`${isSvelte5Plus() ? ' or `{@render ...}` tag' : ''}` + + ' missing — inner content will not be rendered'; + + if (!warned.has(message)) { + console.log(message); + warned.add(message); + } + } + } +}; + +/** + * Returns the SvelteKit Vite plugins. + * @returns {Promise} + */ +export async function sveltekit() { + const svelte_config = await load_config(); + + /** @type {import('@sveltejs/vite-plugin-svelte').Options['preprocess']} */ + let preprocess = svelte_config.preprocess; + if (Array.isArray(preprocess)) { + preprocess = [...preprocess, warning_preprocessor]; + } else if (preprocess) { + preprocess = [preprocess, warning_preprocessor]; + } else { + preprocess = warning_preprocessor; + } + + /** @type {import('@sveltejs/vite-plugin-svelte').Options} */ + const vite_plugin_svelte_options = { + configFile: false, + extensions: svelte_config.extensions, + preprocess, + onwarn: svelte_config.onwarn, + compilerOptions: { + // @ts-ignore - ignore this property when running `pnpm check` against Svelte 5 in the ecosystem CI + hydratable: isSvelte5Plus() ? undefined : true, + ...svelte_config.compilerOptions + }, + ...svelte_config.vitePlugin + }; + + const { svelte } = await import_peer('@sveltejs/vite-plugin-svelte'); + + return [...svelte(vite_plugin_svelte_options), ...(await kit({ svelte_config }))]; +} + +// These variables live outside the `kit()` function because it is re-invoked by each Vite build + +let secondary_build_started = false; + +/** @type {import('types').ManifestData} */ +let manifest_data; + +/** @type {import('types').ServerMetadata | undefined} only set at build time once analysis is finished */ +let build_metadata = undefined; + +/** + * Returns the SvelteKit Vite plugin. Vite executes Rollup hooks as well as some of its own. + * Background reading is available at: + * - https://vitejs.dev/guide/api-plugin.html + * - https://rollupjs.org/guide/en/#plugin-development + * + * You can get an idea of the lifecycle by looking at the flow charts here: + * - https://rollupjs.org/guide/en/#build-hooks + * - https://rollupjs.org/guide/en/#output-generation-hooks + * + * @param {{ svelte_config: import('types').ValidatedConfig }} options + * @return {Promise} + */ +async function kit({ svelte_config }) { + /** @type {import('vite')} */ + const vite = await import_peer('vite'); + + // @ts-ignore `vite.rolldownVersion` only exists in `vite 8` + const is_rolldown = !!vite.rolldownVersion; + + const { kit } = svelte_config; + const out = `${kit.outDir}/output`; + + const version_hash = hash(kit.version.name); + + /** @type {import('vite').ResolvedConfig} */ + let vite_config; + + /** @type {import('vite').ConfigEnv} */ + let vite_config_env; + + /** @type {boolean} */ + let is_build; + + /** @type {{ public: Record; private: Record }} */ + let env; + + /** @type {() => Promise} */ + let finalise; + + /** @type {import('vite').UserConfig} */ + let initial_config; + + const service_worker_entry_file = resolve_entry(kit.files.serviceWorker); + const parsed_service_worker = path.parse(kit.files.serviceWorker); + + const normalized_cwd = vite.normalizePath(cwd); + const normalized_lib = vite.normalizePath(kit.files.lib); + const normalized_node_modules = vite.normalizePath(path.resolve('node_modules')); + + /** + * A map showing which features (such as `$app/server:read`) are defined + * in which chunks, so that we can later determine which routes use which features + * @type {Record} + */ + const tracked_features = {}; + + const sourcemapIgnoreList = /** @param {string} relative_path */ (relative_path) => + relative_path.includes('node_modules') || relative_path.includes(kit.outDir); + + /** @type {import('vite').Plugin} */ + const plugin_setup = { + name: 'vite-plugin-sveltekit-setup', + + /** + * Build the SvelteKit-provided Vite config to be merged with the user's vite.config.js file. + * @see https://vitejs.dev/guide/api-plugin.html#config + */ + config(config, config_env) { + initial_config = config; + vite_config_env = config_env; + is_build = config_env.command === 'build'; + + env = get_env(kit.env, vite_config_env.mode); + + const allow = new Set([ + kit.files.lib, + kit.files.routes, + kit.outDir, + path.resolve('src'), // TODO this isn't correct if user changed all his files to sth else than src (like in test/options) + path.resolve('node_modules'), + path.resolve(vite.searchForWorkspaceRoot(cwd), 'node_modules') + ]); + + // We can only add directories to the allow list, so we find out + // if there's a client hooks file and pass its directory + const client_hooks = resolve_entry(kit.files.hooks.client); + if (client_hooks) allow.add(path.dirname(client_hooks)); + + const generated = path.posix.join(kit.outDir, 'generated'); + + // dev and preview config can be shared + /** @type {import('vite').UserConfig} */ + const new_config = { + resolve: { + alias: [ + { find: '__SERVER__', replacement: `${generated}/server` }, + { find: '$app', replacement: `${runtime_directory}/app` }, + ...get_config_aliases(kit) + ] + }, + root: cwd, + server: { + cors: { preflightContinue: true }, + fs: { + allow: [...allow] + }, + sourcemapIgnoreList, + watch: { + ignored: [ + // Ignore all siblings of config.kit.outDir/generated + `${posixify(kit.outDir)}/!(generated)` + ] + } + }, + preview: { + cors: { preflightContinue: true } + }, + optimizeDeps: { + entries: [ + `${kit.files.routes}/**/+*.{svelte,js,ts}`, + `!${kit.files.routes}/**/+*server.*` + ], + exclude: [ + // Without this SvelteKit will be prebundled on the client, which means we end up with two versions of Redirect etc. + // Also see https://github.com/sveltejs/kit/issues/5952#issuecomment-1218844057 + '@sveltejs/kit', + // exclude kit features so that libraries using them work even when they are prebundled + // this does not affect app code, just handling of imported libraries that use $app or $env + '$app', + '$env' + ] + }, + ssr: { + noExternal: [ + // This ensures that esm-env is inlined into the server output with the + // export conditions resolved correctly through Vite. This prevents adapters + // that bundle later on from resolving the export conditions incorrectly + // and for example include browser-only code in the server output + // because they for example use esbuild.build with `platform: 'browser'` + 'esm-env', + // This forces `$app/*` modules to be bundled, since they depend on + // virtual modules like `__sveltekit/environment` (this isn't a valid bare + // import, but it works with vite-node's externalization logic, which + // uses basic concatenation) + '@sveltejs/kit/src/runtime' + ] + } + }; + + if (kit.experimental.remoteFunctions) { + // treat .remote.js files as empty for the purposes of prebundling + // detects rolldown to avoid a warning message in vite 8 beta + const remote_id_filter = new RegExp( + `.remote(${kit.moduleExtensions.join('|')})$`.replaceAll('.', '\\.') + ); + new_config.optimizeDeps ??= {}; // for some reason ts says this could be undefined even though it was set above + if (is_rolldown) { + // @ts-ignore + new_config.optimizeDeps.rolldownOptions ??= {}; + // @ts-ignore + new_config.optimizeDeps.rolldownOptions.plugins ??= []; + // @ts-ignore + new_config.optimizeDeps.rolldownOptions.plugins.push({ + name: 'vite-plugin-sveltekit-setup:optimize-remote-functions', + load: { + filter: { id: remote_id_filter }, + handler() { + return ''; + } + } + }); + } else { + new_config.optimizeDeps.esbuildOptions ??= {}; + new_config.optimizeDeps.esbuildOptions.plugins ??= []; + new_config.optimizeDeps.esbuildOptions.plugins.push({ + name: 'vite-plugin-sveltekit-setup:optimize-remote-functions', + setup(build) { + build.onLoad({ filter: remote_id_filter }, () => ({ contents: '' })); + } + }); + } + } + + const define = { + __SVELTEKIT_APP_DIR__: s(kit.appDir), + __SVELTEKIT_EMBEDDED__: s(kit.embedded), + __SVELTEKIT_EXPERIMENTAL__REMOTE_FUNCTIONS__: s(kit.experimental.remoteFunctions), + __SVELTEKIT_FORK_PRELOADS__: s(kit.experimental.forkPreloads), + __SVELTEKIT_PATHS_ASSETS__: s(kit.paths.assets), + __SVELTEKIT_PATHS_BASE__: s(kit.paths.base), + __SVELTEKIT_PATHS_RELATIVE__: s(kit.paths.relative), + __SVELTEKIT_CLIENT_ROUTING__: s(kit.router.resolution === 'client'), + __SVELTEKIT_HASH_ROUTING__: s(kit.router.type === 'hash'), + __SVELTEKIT_SERVER_TRACING_ENABLED__: s(kit.experimental.tracing.server), + __SVELTEKIT_EXPERIMENTAL_USE_TRANSFORM_ERROR__: s(kit.experimental.handleRenderingErrors) + }; + + if (is_build) { + if (!new_config.build) new_config.build = {}; + new_config.build.ssr = !secondary_build_started; + + new_config.define = { + ...define, + __SVELTEKIT_ADAPTER_NAME__: s(kit.adapter?.name), + __SVELTEKIT_APP_VERSION_FILE__: s(`${kit.appDir}/version.json`), + __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: s(kit.version.pollInterval), + __SVELTEKIT_PAYLOAD__: new_config.build.ssr + ? '{}' + : `globalThis.__sveltekit_${version_hash}` + }; + + if (!secondary_build_started) { + manifest_data = sync.all(svelte_config, config_env.mode).manifest_data; + // During the initial server build we don't know yet + new_config.define.__SVELTEKIT_HAS_SERVER_LOAD__ = 'true'; + new_config.define.__SVELTEKIT_HAS_UNIVERSAL_LOAD__ = 'true'; + } else { + const nodes = Object.values( + /** @type {import('types').ServerMetadata} */ (build_metadata).nodes + ); + + // Through the finished analysis we can now check if any node has server or universal load functions + const has_server_load = nodes.some((node) => node.has_server_load); + const has_universal_load = nodes.some((node) => node.has_universal_load); + + new_config.define.__SVELTEKIT_HAS_SERVER_LOAD__ = s(has_server_load); + new_config.define.__SVELTEKIT_HAS_UNIVERSAL_LOAD__ = s(has_universal_load); + } + } else { + new_config.define = { + ...define, + __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: '0', + __SVELTEKIT_PAYLOAD__: 'globalThis.__sveltekit_dev', + __SVELTEKIT_HAS_SERVER_LOAD__: 'true', + __SVELTEKIT_HAS_UNIVERSAL_LOAD__: 'true' + }; + + // @ts-ignore this prevents a reference error if `client.js` is imported on the server + globalThis.__sveltekit_dev = {}; + + // These Kit dependencies are packaged as CommonJS, which means they must always be externalized. + // Without this, the tests will still pass but `pnpm dev` will fail in projects that link `@sveltejs/kit`. + /** @type {NonNullable} */ (new_config.ssr).external = [ + 'cookie', + 'set-cookie-parser' + ]; + } + + warn_overridden_config(config, new_config); + + return new_config; + }, + + /** + * Stores the final config. + */ + configResolved(config) { + vite_config = config; + } + }; + + /** @type {import('vite').Plugin} */ + const plugin_virtual_modules = { + name: 'vite-plugin-sveltekit-virtual-modules', + + resolveId(id, importer) { + if (id === '__sveltekit/manifest') { + return `${kit.outDir}/generated/client-optimized/app.js`; + } + + // If importing from a service-worker, only allow $service-worker & $env/static/public, but none of the other virtual modules. + // This check won't catch transitive imports, but it will warn when the import comes from a service-worker directly. + // Transitive imports will be caught during the build. + // TODO move this logic to plugin_guard + if (importer) { + const parsed_importer = path.parse(importer); + + const importer_is_service_worker = + parsed_importer.dir === parsed_service_worker.dir && + parsed_importer.name === parsed_service_worker.name; + + if (importer_is_service_worker && id !== '$service-worker' && id !== '$env/static/public') { + throw new Error( + `Cannot import ${normalize_id( + id, + normalized_lib, + normalized_cwd + )} into service-worker code. Only the modules $service-worker and $env/static/public are available in service workers.` + ); + } + } + + // treat $env/static/[public|private] as virtual + if (id.startsWith('$env/') || id === '$service-worker') { + // ids with :$ don't work with reverse proxies like nginx + return `\0virtual:${id.substring(1)}`; + } + + if (id === '__sveltekit/remote') { + return `${runtime_directory}/client/remote-functions/index.js`; + } + + if (id.startsWith('__sveltekit/')) { + return `\0virtual:${id}`; + } + }, + + load(id, options) { + const browser = !options?.ssr; + + const global = is_build + ? `globalThis.__sveltekit_${version_hash}` + : 'globalThis.__sveltekit_dev'; + + switch (id) { + case env_static_private: + return create_static_module('$env/static/private', env.private); + + case env_static_public: + return create_static_module('$env/static/public', env.public); + + case env_dynamic_private: + return create_dynamic_module( + 'private', + vite_config_env.command === 'serve' ? env.private : undefined + ); + + case env_dynamic_public: + // populate `$env/dynamic/public` from `window` + if (browser) { + return `export const env = ${global}.env;`; + } + + return create_dynamic_module( + 'public', + vite_config_env.command === 'serve' ? env.public : undefined + ); + + case service_worker: + return create_service_worker_module(svelte_config); + + case sveltekit_environment: { + const { version } = svelte_config.kit; + + return dedent` + export const version = ${s(version.name)}; + export let building = false; + export let prerendering = false; + + export function set_building() { + building = true; + } + + export function set_prerendering() { + prerendering = true; + } + `; + } + + case sveltekit_server: { + return dedent` + export let read_implementation = null; + + export let manifest = null; + + export function set_read_implementation(fn) { + read_implementation = fn; + } + + export function set_manifest(_) { + manifest = _; + } + `; + } + } + } + }; + + /** @type {Map>} */ + const import_map = new Map(); + const server_only_pattern = /.*\.server\..+/; + + /** + * Ensures that client-side code can't accidentally import server-side code, + * whether in `*.server.js` files, `$app/server`, `$lib/server`, or `$env/[static|dynamic]/private` + * @type {import('vite').Plugin} + */ + const plugin_guard = { + name: 'vite-plugin-sveltekit-guard', + + // Run this plugin before built-in resolution, so that relative imports + // are added to the module graph + enforce: 'pre', + + async resolveId(id, importer, options) { + if (importer && !importer.endsWith('index.html')) { + const resolved = await this.resolve(id, importer, { ...options, skipSelf: true }); + + if (resolved) { + const normalized = normalize_id(resolved.id, normalized_lib, normalized_cwd); + + let importers = import_map.get(normalized); + + if (!importers) { + importers = new Set(); + import_map.set(normalized, importers); + } + + importers.add(normalize_id(importer, normalized_lib, normalized_cwd)); + } + } + }, + + load(id, options) { + if (options?.ssr === true || process.env.TEST === 'true') { + return; + } + + // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context + const is_internal = id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules); + + const normalized = normalize_id(id, normalized_lib, normalized_cwd); + + const is_server_only = + normalized === '$env/static/private' || + normalized === '$env/dynamic/private' || + normalized === '$app/server' || + normalized.startsWith('$lib/server/') || + (is_internal && server_only_pattern.test(path.basename(id))); + + if (is_server_only) { + // in dev, this doesn't exist, so we need to create it + manifest_data ??= sync.all(svelte_config, vite_config_env.mode).manifest_data; + + /** @type {Set} */ + const entrypoints = new Set(); + for (const node of manifest_data.nodes) { + if (node.component) entrypoints.add(node.component); + if (node.universal) entrypoints.add(node.universal); + } + + if (manifest_data.hooks.client) entrypoints.add(manifest_data.hooks.client); + if (manifest_data.hooks.universal) entrypoints.add(manifest_data.hooks.universal); + + const normalized = normalize_id(id, normalized_lib, normalized_cwd); + const chain = [normalized]; + + let current = normalized; + let includes_remote_file = false; + + while (true) { + const importers = import_map.get(current); + if (!importers) break; + + const candidates = Array.from(importers).filter((importer) => !chain.includes(importer)); + if (candidates.length === 0) break; + + chain.push((current = candidates[0])); + + includes_remote_file ||= svelte_config.kit.moduleExtensions.some((ext) => { + return current.endsWith(`.remote${ext}`); + }); + + if (entrypoints.has(current)) { + const pyramid = chain + .reverse() + .map((id, i) => { + return `${' '.repeat(i + 1)}${id}`; + }) + .join(' imports\n'); + + if (includes_remote_file) { + error_for_missing_config( + 'remote functions', + 'kit.experimental.remoteFunctions', + 'true' + ); + } + + let message = `Cannot import ${normalized} into code that runs in the browser, as this could leak sensitive information.`; + message += `\n\n${pyramid}`; + message += `\n\nIf you're only using the import as a type, change it to \`import type\`.`; + + throw stackless(message); + } + } + + throw new Error('An impossible situation occurred'); + } + } + }; + + /** @type {import('vite').ViteDevServer} */ + let dev_server; + + /** @type {Array<{ hash: string, file: string }>} */ + const remotes = []; + + /** @type {Map} Maps remote hash -> original module id */ + const remote_original_by_hash = new Map(); + + /** @type {Set} Track which remote hashes have already been emitted */ + const emitted_remote_hashes = new Set(); + + /** @type {import('vite').Plugin} */ + const plugin_remote = { + name: 'vite-plugin-sveltekit-remote', + + resolveId(id) { + if (id.startsWith('\0sveltekit-remote:')) return id; + }, + + load(id) { + // On-the-fly generated entry point for remote file just forwards the original module + // We're not using manualChunks because it can cause problems with circular dependencies + // (e.g. https://github.com/sveltejs/kit/issues/14679) and module ordering in general + // (e.g. https://github.com/sveltejs/kit/issues/14590). + if (id.startsWith('\0sveltekit-remote:')) { + const hash_id = id.slice('\0sveltekit-remote:'.length); + const original = remote_original_by_hash.get(hash_id); + if (!original) throw new Error(`Expected to find metadata for remote file ${id}`); + return `import * as m from ${s(original)};\nexport default m;`; + } + }, + + configureServer(_dev_server) { + dev_server = _dev_server; + }, + + async transform(code, id, opts) { + const normalized = normalize_id(id, normalized_lib, normalized_cwd); + if (!svelte_config.kit.moduleExtensions.some((ext) => normalized.endsWith(`.remote${ext}`))) { + return; + } + + const file = posixify(path.relative(cwd, id)); + const remote = { + hash: hash(file), + file + }; + + remotes.push(remote); + + if (opts?.ssr) { + // we need to add an `await Promise.resolve()` because if the user imports this function + // on the client AND in a load function when loading the client module we will trigger + // an ssrLoadModule during dev. During a link preload, the module can be mistakenly + // loaded and transformed twice and the first time all its exports would be undefined + // triggering a dev server error. By adding a microtask we ensure that the module is fully loaded + + // Extra newlines to prevent syntax errors around missing semicolons or comments + code += + '\n\n' + + dedent` + import * as $$_self_$$ from './${path.basename(id)}'; + import { init_remote_functions as $$_init_$$ } from '@sveltejs/kit/internal'; + + ${dev_server ? 'await Promise.resolve()' : ''} + + $$_init_$$($$_self_$$, ${s(file)}, ${s(remote.hash)}); + + for (const [name, fn] of Object.entries($$_self_$$)) { + fn.__.id = ${s(remote.hash)} + '/' + name; + fn.__.name = name; + } + `; + + // Emit a dedicated entry chunk for this remote in SSR builds (prod only) + if (!dev_server) { + remote_original_by_hash.set(remote.hash, id); + if (!emitted_remote_hashes.has(remote.hash)) { + this.emitFile({ + type: 'chunk', + id: `\0sveltekit-remote:${remote.hash}`, + name: `remote-${remote.hash}` + }); + emitted_remote_hashes.add(remote.hash); + } + } + + return code; + } + + // For the client, read the exports and create a new module that only contains fetch functions with the correct metadata + + /** @type {Map} */ + const map = new Map(); + + // in dev, load the server module here (which will result in this hook + // being called again with `opts.ssr === true` if the module isn't + // already loaded) so we can determine what it exports + if (dev_server) { + const module = await dev_server.ssrLoadModule(id); + + for (const [name, value] of Object.entries(module)) { + const type = value?.__?.type; + if (type) { + map.set(name, type); + } + } + } + + // in prod, we already built and analysed the server code before + // building the client code, so `remote_exports` is populated + else if (build_metadata?.remotes) { + const exports = build_metadata?.remotes.get(remote.hash); + if (!exports) throw new Error('Expected to find metadata for remote file ' + id); + + for (const [name, value] of exports) { + map.set(name, value.type); + } + } + + let namespace = '__remote'; + let uid = 1; + while (map.has(namespace)) namespace = `__remote${uid++}`; + + const exports = Array.from(map).map(([name, type]) => { + return `export const ${name} = ${namespace}.${type}('${remote.hash}/${name}');`; + }); + + let result = `import * as ${namespace} from '__sveltekit/remote';\n\n${exports.join('\n')}\n`; + + if (dev_server) { + result += `\nimport.meta.hot?.accept();\n`; + } + + return { + code: result + }; + } + }; + + /** @type {import('vite').Plugin} */ + const plugin_compile = { + name: 'vite-plugin-sveltekit-compile', + + /** + * Build the SvelteKit-provided Vite config to be merged with the user's vite.config.js file. + * @see https://vitejs.dev/guide/api-plugin.html#config + */ + config(config) { + /** @type {import('vite').UserConfig} */ + let new_config; + + const kit_paths_base = kit.paths.base || '/'; + + if (is_build) { + const ssr = /** @type {boolean} */ (config.build?.ssr); + const prefix = `${kit.appDir}/immutable`; + + /** @type {Record} */ + const input = {}; + + if (ssr) { + input.index = `${runtime_directory}/server/index.js`; + input.internal = `${kit.outDir}/generated/server/internal.js`; + input['remote-entry'] = `${runtime_directory}/app/server/remote/index.js`; + + // add entry points for every endpoint... + manifest_data.routes.forEach((route) => { + if (route.endpoint) { + const resolved = path.resolve(route.endpoint.file); + const relative = decodeURIComponent(path.relative(kit.files.routes, resolved)); + const name = posixify(path.join('entries/endpoints', relative.replace(/\.js$/, ''))); + input[name] = resolved; + } + }); + + // ...and every component used by pages... + manifest_data.nodes.forEach((node) => { + for (const file of [node.component, node.universal, node.server]) { + if (file) { + const resolved = path.resolve(file); + const relative = decodeURIComponent(path.relative(kit.files.routes, resolved)); + + const name = relative.startsWith('..') + ? posixify(path.join('entries/fallbacks', path.basename(file))) + : posixify(path.join('entries/pages', relative.replace(/\.js$/, ''))); + input[name] = resolved; + } + } + }); + + // ...and every matcher + Object.entries(manifest_data.matchers).forEach(([key, file]) => { + const name = posixify(path.join('entries/matchers', key)); + input[name] = path.resolve(file); + }); + + // ...and the hooks files + if (manifest_data.hooks.server) { + input['entries/hooks.server'] = path.resolve(manifest_data.hooks.server); + } + if (manifest_data.hooks.universal) { + input['entries/hooks.universal'] = path.resolve(manifest_data.hooks.universal); + } + + // ...and the server instrumentation file + const server_instrumentation = resolve_entry( + path.join(kit.files.src, 'instrumentation.server') + ); + if (server_instrumentation) { + const { adapter } = kit; + if (adapter && !adapter.supports?.instrumentation?.()) { + throw new Error(`${server_instrumentation} is unsupported in ${adapter.name}.`); + } + if (!kit.experimental.instrumentation.server) { + error_for_missing_config( + '`instrumentation.server.js`', + 'kit.experimental.instrumentation.server', + 'true' + ); + } + input['instrumentation.server'] = server_instrumentation; + } + } else if (svelte_config.kit.output.bundleStrategy !== 'split') { + input['bundle'] = `${runtime_directory}/client/bundle.js`; + } else { + input['entry/start'] = `${runtime_directory}/client/entry.js`; + input['entry/app'] = `${kit.outDir}/generated/client-optimized/app.js`; + manifest_data.nodes.forEach((node, i) => { + if (node.component || node.universal) { + input[`nodes/${i}`] = `${kit.outDir}/generated/client-optimized/nodes/${i}.js`; + } + }); + } + + // see the kit.output.preloadStrategy option for details on why we have multiple options here + const ext = kit.output.preloadStrategy === 'preload-mjs' ? 'mjs' : 'js'; + + // We could always use a relative asset base path here, but it's better for performance not to. + // E.g. Vite generates `new URL('/asset.png', import.meta).href` for a relative path vs just '/asset.png'. + // That's larger and takes longer to run and also causes an HTML diff between SSR and client + // causing us to do a more expensive hydration check. + const client_base = + kit.paths.relative !== false || kit.paths.assets ? './' : kit_paths_base; + + const inline = !ssr && svelte_config.kit.output.bundleStrategy === 'inline'; + const split = ssr || svelte_config.kit.output.bundleStrategy === 'split'; + + new_config = { + base: ssr ? assets_base(kit) : client_base, + build: { + copyPublicDir: !ssr, + cssCodeSplit: svelte_config.kit.output.bundleStrategy !== 'inline', + cssMinify: initial_config.build?.minify == null ? true : !!initial_config.build.minify, + manifest: true, + outDir: `${out}/${ssr ? 'server' : 'client'}`, + rollupOptions: { + input: inline ? input['bundle'] : input, + output: { + format: inline ? 'iife' : 'esm', + name: `__sveltekit_${version_hash}.app`, + entryFileNames: ssr ? '[name].js' : `${prefix}/[name].[hash].${ext}`, + chunkFileNames: ssr ? 'chunks/[name].js' : `${prefix}/chunks/[hash].${ext}`, + assetFileNames: `${prefix}/assets/[name].[hash][extname]`, + hoistTransitiveImports: false, + sourcemapIgnoreList, + inlineDynamicImports: is_rolldown ? undefined : !split + }, + preserveEntrySignatures: 'strict', + onwarn(warning, handler) { + if ( + (is_rolldown + ? warning.code === 'IMPORT_IS_UNDEFINED' + : warning.code === 'MISSING_EXPORT') && + warning.id === `${kit.outDir}/generated/client-optimized/app.js` + ) { + // ignore e.g. undefined `handleError` hook when + // referencing `client_hooks.handleError` + return; + } + + handler(warning); + } + }, + ssrEmitAssets: true, + target: ssr ? 'node18.13' : undefined + }, + publicDir: kit.files.assets, + worker: { + rollupOptions: { + output: { + entryFileNames: `${prefix}/workers/[name]-[hash].js`, + chunkFileNames: `${prefix}/workers/chunks/[hash].js`, + assetFileNames: `${prefix}/workers/assets/[name]-[hash][extname]`, + hoistTransitiveImports: false + } + } + } + }; + + // we must reference Vite 8 options conditionally. Otherwise, older Vite + // versions throw an error about unknown config options + if (is_rolldown && new_config?.build?.rollupOptions?.output) { + // @ts-ignore only available in Vite 8 + new_config.build.rollupOptions.output.codeSplitting = split; + } + } else { + new_config = { + appType: 'custom', + base: kit_paths_base, + build: { + rollupOptions: { + // Vite dependency crawler needs an explicit JS entry point + // even though server otherwise works without it + input: `${runtime_directory}/client/entry.js` + } + }, + publicDir: kit.files.assets + }; + } + + warn_overridden_config(config, new_config); + + return new_config; + }, + + /** + * Adds the SvelteKit middleware to do SSR in dev mode. + * @see https://vitejs.dev/guide/api-plugin.html#configureserver + */ + async configureServer(vite) { + return await dev(vite, vite_config, svelte_config, () => remotes); + }, + + /** + * Adds the SvelteKit middleware to do SSR in preview mode. + * @see https://vitejs.dev/guide/api-plugin.html#configurepreviewserver + */ + configurePreviewServer(vite) { + return preview(vite, vite_config, svelte_config); + }, + + /** + * Clears the output directories. + */ + buildStart() { + if (secondary_build_started) return; + + if (is_build) { + if (!vite_config.build.watch) { + rimraf(out); + } + mkdirp(out); + } + }, + + renderChunk(code, chunk) { + if (code.includes('__SVELTEKIT_TRACK__')) { + return { + // Rolldown changes our single quotes to double quotes so we need it in the regex too + code: code.replace(/__SVELTEKIT_TRACK__\(['"](.+?)['"]\)/g, (_, label) => { + (tracked_features[chunk.name + '.js'] ??= []).push(label); + // put extra whitespace at the end of the comment to preserve the source size and avoid interfering with source maps + return `/* track ${label} */`; + }), + map: null // TODO we may need to generate a sourcemap in future + }; + } + }, + + generateBundle() { + if (vite_config.build.ssr) return; + + this.emitFile({ + type: 'asset', + fileName: `${kit.appDir}/version.json`, + source: s({ version: kit.version.name }) + }); + }, + + /** + * Vite builds a single bundle. We need three bundles: client, server, and service worker. + * The user's package.json scripts will invoke the Vite CLI to execute the server build. We + * then use this hook to kick off builds for the client and service worker. + */ + writeBundle: { + sequential: true, + async handler(_options) { + if (secondary_build_started) return; // only run this once + + const verbose = vite_config.logLevel === 'info'; + const log = logger({ verbose }); + + /** @type {import('vite').Manifest} */ + const server_manifest = JSON.parse(read(`${out}/server/.vite/manifest.json`)); + + /** @type {import('types').BuildData} */ + const build_data = { + app_dir: kit.appDir, + app_path: `${kit.paths.base.slice(1)}${kit.paths.base ? '/' : ''}${kit.appDir}`, + manifest_data, + out_dir: out, + service_worker: service_worker_entry_file ? 'service-worker.js' : null, // TODO make file configurable? + client: null, + server_manifest + }; + + const manifest_path = `${out}/server/manifest-full.js`; + fs.writeFileSync( + manifest_path, + `export const manifest = ${generate_manifest({ + build_data, + prerendered: [], + relative_path: '.', + routes: manifest_data.routes, + remotes + })};\n` + ); + + log.info('Analysing routes'); + + const { metadata } = await analyse({ + hash: kit.router.type === 'hash', + manifest_path, + manifest_data, + server_manifest, + tracked_features, + env: { ...env.private, ...env.public }, + out, + output_config: svelte_config.output, + remotes + }); + + build_metadata = metadata; + + log.info('Building app'); + + // create client build + write_client_manifest( + kit, + manifest_data, + `${kit.outDir}/generated/client-optimized`, + metadata.nodes + ); + + secondary_build_started = true; + + let client_chunks; + + try { + const bundle = /** @type {import('vite').Rollup.RollupOutput} */ ( + await vite.build({ + configFile: vite_config.configFile, + // CLI args + mode: vite_config_env.mode, + logLevel: vite_config.logLevel, + clearScreen: vite_config.clearScreen, + build: { + minify: initial_config.build?.minify, + assetsInlineLimit: vite_config.build.assetsInlineLimit, + sourcemap: vite_config.build.sourcemap + }, + optimizeDeps: { + force: vite_config.optimizeDeps.force + } + }) + ); + + client_chunks = bundle.output; + } catch (e) { + const error = + e instanceof Error ? e : new Error(/** @type {any} */ (e).message ?? e ?? ''); + + // without this, errors that occur during the secondary build + // will be logged twice + throw stackless(error.stack ?? error.message); + } + + // We use `build.ssrEmitAssets` so that asset URLs created from + // imports in server-only modules correspond to files in the build, + // but we don't want to copy over CSS imports as these are already + // accounted for in the client bundle. In most cases it would be + // a no-op, but for SSR builds `url(...)` paths are handled + // differently (relative for client, absolute for server) + // resulting in different hashes, and thus duplication + const ssr_stylesheets = new Set( + Object.values(server_manifest) + .map((chunk) => chunk.css ?? []) + .flat() + ); + + const assets_path = `${kit.appDir}/immutable/assets`; + const server_assets = `${out}/server/${assets_path}`; + const client_assets = `${out}/client/${assets_path}`; + + if (fs.existsSync(server_assets)) { + for (const file of fs.readdirSync(server_assets)) { + const src = `${server_assets}/${file}`; + const dest = `${client_assets}/${file}`; + + if (fs.existsSync(dest) || ssr_stylesheets.has(`${assets_path}/${file}`)) { + continue; + } + + if (file.endsWith('.css')) { + // make absolute paths in CSS relative, for portability + const content = fs + .readFileSync(src, 'utf-8') + .replaceAll(`${kit.paths.base}/${assets_path}`, '.'); + + fs.writeFileSync(src, content); + } + + copy(src, dest); + } + } + + /** @type {import('vite').Manifest} */ + const client_manifest = JSON.parse(read(`${out}/client/.vite/manifest.json`)); + + /** + * @param {string} entry + * @param {boolean} [add_dynamic_css] + */ + const deps_of = (entry, add_dynamic_css = false) => + find_deps(client_manifest, posixify(path.relative('.', entry)), add_dynamic_css); + + if (svelte_config.kit.output.bundleStrategy === 'split') { + const start = deps_of(`${runtime_directory}/client/entry.js`); + const app = deps_of(`${kit.outDir}/generated/client-optimized/app.js`); + + build_data.client = { + start: start.file, + app: app.file, + imports: [...start.imports, ...app.imports], + stylesheets: [...start.stylesheets, ...app.stylesheets], + fonts: [...start.fonts, ...app.fonts], + uses_env_dynamic_public: client_chunks.some( + (chunk) => chunk.type === 'chunk' && chunk.modules[env_dynamic_public] + ) + }; + + // In case of server-side route resolution, we create a purpose-built route manifest that is + // similar to that on the client, with as much information computed upfront so that we + // don't need to include any code of the actual routes in the server bundle. + if (svelte_config.kit.router.resolution === 'server') { + const nodes = manifest_data.nodes.map((node, i) => { + if (node.component || node.universal) { + const entry = `${kit.outDir}/generated/client-optimized/nodes/${i}.js`; + const deps = deps_of(entry, true); + const file = resolve_symlinks( + client_manifest, + `${kit.outDir}/generated/client-optimized/nodes/${i}.js` + ).chunk.file; + + return { file, css: deps.stylesheets }; + } + }); + build_data.client.nodes = nodes.map((node) => node?.file); + build_data.client.css = nodes.map((node) => node?.css); + + build_data.client.routes = compact( + manifest_data.routes.map((route) => { + if (!route.page) return; + + return { + id: route.id, + pattern: route.pattern, + params: route.params, + layouts: route.page.layouts.map((l) => + l !== undefined ? [metadata.nodes[l].has_server_load, l] : undefined + ), + errors: route.page.errors, + leaf: [metadata.nodes[route.page.leaf].has_server_load, route.page.leaf] + }; + }) + ); + } + } else { + const start = deps_of(`${runtime_directory}/client/bundle.js`); + + build_data.client = { + start: start.file, + imports: start.imports, + stylesheets: start.stylesheets, + fonts: start.fonts, + uses_env_dynamic_public: client_chunks.some( + (chunk) => chunk.type === 'chunk' && chunk.modules[env_dynamic_public] + ) + }; + + if (svelte_config.kit.output.bundleStrategy === 'inline') { + const style = /** @type {import('vite').Rollup.OutputAsset} */ ( + client_chunks.find( + (chunk) => + chunk.type === 'asset' && + chunk.names.length === 1 && + chunk.names[0] === 'style.css' + ) + ); + + build_data.client.inline = { + script: read(`${out}/client/${start.file}`), + style: /** @type {string | undefined} */ (style?.source) + }; + } + } + + // regenerate manifest now that we have client entry... + fs.writeFileSync( + manifest_path, + `export const manifest = ${generate_manifest({ + build_data, + prerendered: [], + relative_path: '.', + routes: manifest_data.routes, + remotes + })};\n` + ); + + // regenerate nodes with the client manifest... + build_server_nodes( + out, + kit, + manifest_data, + server_manifest, + client_manifest, + assets_path, + client_chunks, + svelte_config.kit.output + ); + + // ...and prerender + const { prerendered, prerender_map } = await prerender({ + hash: kit.router.type === 'hash', + out, + manifest_path, + metadata, + verbose, + env: { ...env.private, ...env.public } + }); + + // generate a new manifest that doesn't include prerendered pages + fs.writeFileSync( + `${out}/server/manifest.js`, + `export const manifest = ${generate_manifest({ + build_data, + prerendered: prerendered.paths, + relative_path: '.', + routes: manifest_data.routes.filter((route) => prerender_map.get(route.id) !== true), + remotes + })};\n` + ); + + if (service_worker_entry_file) { + if (kit.paths.assets) { + throw new Error('Cannot use service worker alongside config.kit.paths.assets'); + } + + log.info('Building service worker'); + + await build_service_worker( + out, + kit, + { + ...vite_config, + build: { + ...vite_config.build, + minify: initial_config.build?.minify ?? true + } + }, + manifest_data, + service_worker_entry_file, + prerendered, + client_manifest + ); + } + + // we need to defer this to closeBundle, so that adapters copy files + // created by other Vite plugins + finalise = async () => { + console.log( + `\nRun ${colors + .bold() + .cyan('npm run preview')} to preview your production build locally.` + ); + + if (kit.adapter) { + const { adapt } = await import('../../core/adapt/index.js'); + await adapt( + svelte_config, + build_data, + metadata, + prerendered, + prerender_map, + log, + remotes, + vite_config + ); + } else { + console.log(colors.bold().yellow('\nNo adapter specified')); + + const link = colors.bold().cyan('https://svelte.dev/docs/kit/adapters'); + console.log( + `See ${link} to learn how to configure your app to run on the platform of your choosing` + ); + } + + secondary_build_started = false; + }; + } + }, + + /** + * Runs the adapter. + */ + closeBundle: { + sequential: true, + async handler() { + if (!vite_config.build.ssr) return; + await finalise?.(); + } + } + }; + + return [ + plugin_setup, + kit.experimental.remoteFunctions && plugin_remote, + plugin_virtual_modules, + plugin_guard, + plugin_compile + ].filter((p) => !!p); +} + +/** + * @param {Record} config + * @param {Record} resolved_config + */ +function warn_overridden_config(config, resolved_config) { + const overridden = find_overridden_config(config, resolved_config, enforced_config, '', []); + + if (overridden.length > 0) { + console.error( + colors.bold().red('The following Vite config options will be overridden by SvelteKit:') + + overridden.map((key) => `\n - ${key}`).join('') + ); + } +} + +/** + * @param {Record} config + * @param {Record} resolved_config + * @param {import('./types.js').EnforcedConfig} enforced_config + * @param {string} path + * @param {string[]} out used locally to compute the return value + */ +function find_overridden_config(config, resolved_config, enforced_config, path, out) { + if (config == null || resolved_config == null) { + return out; + } + + for (const key in enforced_config) { + if (typeof config === 'object' && key in config && key in resolved_config) { + const enforced = enforced_config[key]; + + if (enforced === true) { + if (config[key] !== resolved_config[key]) { + out.push(path + key); + } + } else { + find_overridden_config(config[key], resolved_config[key], enforced, path + key + '.', out); + } + } + } + return out; +} + +/** + * @param {import('types').ValidatedConfig} config + */ +const create_service_worker_module = (config) => dedent` + if (typeof self === 'undefined' || self instanceof ServiceWorkerGlobalScope === false) { + throw new Error('This module can only be imported inside a service worker'); + } + + export const build = []; + export const files = [ + ${create_assets(config) + .filter((asset) => config.kit.serviceWorker.files(asset.file)) + .map((asset) => `${s(`${config.kit.paths.base}/${asset.file}`)}`) + .join(',\n')} + ]; + export const prerendered = []; + export const version = ${s(config.kit.version.name)}; +`; diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/vite/module_ids.js b/frontend/node_modules/@sveltejs/kit/src/exports/vite/module_ids.js new file mode 100644 index 0000000..69325f3 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/vite/module_ids.js @@ -0,0 +1,16 @@ +import { fileURLToPath } from 'node:url'; +import { posixify } from '../../utils/filesystem.js'; + +export const env_static_private = '\0virtual:env/static/private'; +export const env_static_public = '\0virtual:env/static/public'; +export const env_dynamic_private = '\0virtual:env/dynamic/private'; +export const env_dynamic_public = '\0virtual:env/dynamic/public'; + +export const service_worker = '\0virtual:service-worker'; + +export const sveltekit_environment = '\0virtual:__sveltekit/environment'; +export const sveltekit_server = '\0virtual:__sveltekit/server'; + +export const app_server = posixify( + fileURLToPath(new URL('../../runtime/app/server/index.js', import.meta.url)) +); diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/vite/preview/index.js b/frontend/node_modules/@sveltejs/kit/src/exports/vite/preview/index.js new file mode 100644 index 0000000..02a89e9 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/vite/preview/index.js @@ -0,0 +1,261 @@ +import fs from 'node:fs'; +import { join } from 'node:path'; +import { pathToFileURL } from 'node:url'; +import { lookup } from 'mrmime'; +import sirv from 'sirv'; +import { loadEnv, normalizePath } from 'vite'; +import { createReadableStream, getRequest, setResponse } from '../../../exports/node/index.js'; +import { installPolyfills } from '../../../exports/node/polyfills.js'; +import { SVELTE_KIT_ASSETS } from '../../../constants.js'; +import { not_found } from '../utils.js'; + +/** @typedef {import('http').IncomingMessage} Req */ +/** @typedef {import('http').ServerResponse} Res */ +/** @typedef {(req: Req, res: Res, next: () => void) => void} Handler */ + +/** + * @param {import('vite').PreviewServer} vite + * @param {import('vite').ResolvedConfig} vite_config + * @param {import('types').ValidatedConfig} svelte_config + */ +export async function preview(vite, vite_config, svelte_config) { + installPolyfills(); + + const { paths } = svelte_config.kit; + const base = paths.base; + const assets = paths.assets ? SVELTE_KIT_ASSETS : paths.base; + + const protocol = vite_config.preview.https ? 'https' : 'http'; + + const etag = `"${Date.now()}"`; + + const dir = join(svelte_config.kit.outDir, 'output/server'); + + if (!fs.existsSync(dir)) { + throw new Error(`Server files not found at ${dir}, did you run \`build\` first?`); + } + + const instrumentation = join(dir, 'instrumentation.server.js'); + if (fs.existsSync(instrumentation)) { + await import(pathToFileURL(instrumentation).href); + } + + /** @type {import('types').ServerInternalModule} */ + const { set_assets } = await import(pathToFileURL(join(dir, 'internal.js')).href); + + /** @type {import('types').ServerModule} */ + const { Server } = await import(pathToFileURL(join(dir, 'index.js')).href); + + const { manifest } = await import(pathToFileURL(join(dir, 'manifest.js')).href); + + set_assets(assets); + + const server = new Server(manifest); + await server.init({ + env: loadEnv(vite_config.mode, svelte_config.kit.env.dir, ''), + read: (file) => createReadableStream(`${dir}/${file}`) + }); + + const emulator = await svelte_config.kit.adapter?.emulate?.(); + + return () => { + // Remove the base middleware. It screws with the URL. + // It also only lets through requests beginning with the base path, so that requests beginning + // with the assets URL never reach us. We could serve assets separately before the base + // middleware, but we'd need that to occur after the compression and cors middlewares, so would + // need to insert it manually into the stack, which would be at least as bad as doing this. + for (let i = vite.middlewares.stack.length - 1; i > 0; i--) { + // @ts-expect-error using internals + if (vite.middlewares.stack[i].handle.name === 'viteBaseMiddleware') { + vite.middlewares.stack.splice(i, 1); + } + } + + // generated client assets and the contents of `static` + vite.middlewares.use( + scoped( + assets, + sirv(join(svelte_config.kit.outDir, 'output/client'), { + setHeaders: (res, pathname) => { + // only apply to immutable directory, not e.g. version.json + if (pathname.startsWith(`/${svelte_config.kit.appDir}/immutable`)) { + res.setHeader('cache-control', 'public,max-age=31536000,immutable'); + } + } + }) + ) + ); + + vite.middlewares.use((req, res, next) => { + const original_url = /** @type {string} */ (req.url); + const { pathname, search } = new URL(original_url, 'http://dummy'); + + // if `paths.base === '/a/b/c`, then the root route is `/a/b/c/`, + // regardless of the `trailingSlash` route option + if (base.length > 1 && pathname === base) { + let location = base + '/'; + if (search) location += search; + res.writeHead(307, { + location + }); + res.end(); + return; + } + + if (pathname.startsWith(base)) { + next(); + } else { + res.statusCode = 404; + not_found(req, res, base); + } + }); + + // prerendered dependencies + vite.middlewares.use( + scoped(base, mutable(join(svelte_config.kit.outDir, 'output/prerendered/dependencies'))) + ); + + // prerendered pages (we can't just use sirv because we need to + // preserve the correct trailingSlash behaviour) + vite.middlewares.use( + scoped(base, (req, res, next) => { + let if_none_match_value = req.headers['if-none-match']; + + if (if_none_match_value?.startsWith('W/"')) { + if_none_match_value = if_none_match_value.substring(2); + } + + if (if_none_match_value === etag) { + res.statusCode = 304; + res.end(); + return; + } + + const { pathname, search } = new URL(/** @type {string} */ (req.url), 'http://dummy'); + + const dir = pathname.startsWith(`/${svelte_config.kit.appDir}/remote/`) ? 'data' : 'pages'; + + let filename = normalizePath( + join(svelte_config.kit.outDir, `output/prerendered/${dir}` + pathname) + ); + + try { + filename = decodeURI(filename); + } catch { + // malformed URI + } + + let prerendered = is_file(filename); + + if (!prerendered) { + const has_trailing_slash = pathname.endsWith('/'); + const html_filename = `${filename}${has_trailing_slash ? 'index.html' : '.html'}`; + + /** @type {string | undefined} */ + let redirect; + + if (is_file(html_filename)) { + filename = html_filename; + prerendered = true; + } else if (has_trailing_slash) { + if (is_file(filename.slice(0, -1) + '.html')) { + redirect = pathname.slice(0, -1); + } + } else if (is_file(filename + '/index.html')) { + redirect = pathname + '/'; + } + + if (redirect) { + if (search) redirect += search; + res.writeHead(307, { + location: redirect + }); + + res.end(); + + return; + } + } + + if (prerendered) { + res.writeHead(200, { + 'content-type': lookup(pathname) || 'text/html', + etag + }); + + fs.createReadStream(filename).pipe(res); + } else { + next(); + } + }) + ); + + // SSR + vite.middlewares.use(async (req, res) => { + const host = req.headers[':authority'] || req.headers.host; + + const request = await getRequest({ + base: `${protocol}://${host}`, + request: req + }); + + await setResponse( + res, + await server.respond(request, { + getClientAddress: () => { + const { remoteAddress } = req.socket; + if (remoteAddress) return remoteAddress; + throw new Error('Could not determine clientAddress'); + }, + read: (file) => { + if (file in manifest._.server_assets) { + return fs.readFileSync(join(dir, file)); + } + + return fs.readFileSync(join(svelte_config.kit.files.assets, file)); + }, + emulator + }) + ); + }); + }; +} + +/** + * @param {string} dir + * @returns {Handler} + */ +const mutable = (dir) => + fs.existsSync(dir) + ? sirv(dir, { + etag: true, + maxAge: 0 + }) + : (_req, _res, next) => next(); + +/** + * @param {string} scope + * @param {Handler} handler + * @returns {Handler} + */ +function scoped(scope, handler) { + if (scope === '') return handler; + + return (req, res, next) => { + if (req.url?.startsWith(scope)) { + const original_url = req.url; + req.url = req.url.slice(scope.length); + handler(req, res, () => { + req.url = original_url; + next(); + }); + } else { + next(); + } + }; +} + +/** @param {string} path */ +function is_file(path) { + return fs.existsSync(path) && !fs.statSync(path).isDirectory(); +} diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/vite/static_analysis/index.js b/frontend/node_modules/@sveltejs/kit/src/exports/vite/static_analysis/index.js new file mode 100644 index 0000000..6d42480 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/vite/static_analysis/index.js @@ -0,0 +1,301 @@ +import { tsPlugin } from '@sveltejs/acorn-typescript'; +import { Parser } from 'acorn'; +import { read } from '../../../utils/filesystem.js'; + +const valid_page_options_array = /** @type {const} */ ([ + 'ssr', + 'prerender', + 'csr', + 'trailingSlash', + 'config', + 'entries', + 'load' +]); + +/** @type {Set} */ +const valid_page_options = new Set(valid_page_options_array); + +/** @typedef {typeof valid_page_options_array[number]} ValidPageOption */ +/** @typedef {Partial>} PageOptions */ + +const skip_parsing_regex = new RegExp( + `${Array.from(valid_page_options).join('|')}|(?:export[\\s\\n]+\\*[\\s\\n]+from)` +); + +const parser = Parser.extend(tsPlugin()); + +/** + * Collects page options from a +page.js/+layout.js file, ignoring reassignments + * and using the declared value (except for load functions, for which the value is `true`). + * Returns `null` if any export is too difficult to analyse. + * @param {string} filename The name of the file to report when an error occurs + * @param {string} input + * @returns {PageOptions | null} + */ +export function statically_analyse_page_options(filename, input) { + // if there's a chance there are no page exports or an unparseable + // export all declaration, then we can skip the AST parsing which is expensive + if (!skip_parsing_regex.test(input)) { + return {}; + } + + try { + const source = parser.parse(input, { + sourceType: 'module', + ecmaVersion: 'latest' + }); + + /** @type {Map} */ + const page_options = new Map(); + + for (const statement of source.body) { + // ignore export all declarations with aliases that are not page options + if ( + statement.type === 'ExportAllDeclaration' && + statement.exported && + !valid_page_options.has(get_name(statement.exported)) + ) { + continue; + } + + if ( + statement.type === 'ExportDefaultDeclaration' || + statement.type === 'ExportAllDeclaration' + ) { + return null; + } else if (statement.type !== 'ExportNamedDeclaration') { + continue; + } + + if (statement.specifiers.length) { + /** @type {Map} */ + const export_specifiers = new Map(); + for (const specifier of statement.specifiers) { + const exported_name = get_name(specifier.exported); + if (!valid_page_options.has(exported_name)) { + continue; + } + + if (statement.source) { + return null; + } + + export_specifiers.set(get_name(specifier.local), exported_name); + } + + for (const statement of source.body) { + switch (statement.type) { + case 'ImportDeclaration': { + for (const import_specifier of statement.specifiers) { + if (export_specifiers.has(import_specifier.local.name)) { + return null; + } + } + break; + } + case 'ExportNamedDeclaration': + case 'VariableDeclaration': + case 'FunctionDeclaration': + case 'ClassDeclaration': { + const declaration = + statement.type === 'ExportNamedDeclaration' ? statement.declaration : statement; + + if (!declaration) { + break; + } + + // class and function declarations + if (declaration.type !== 'VariableDeclaration') { + if (export_specifiers.has(declaration.id.name)) { + return null; + } + break; + } + + for (const variable_declarator of declaration.declarations) { + if ( + variable_declarator.id.type !== 'Identifier' || + !export_specifiers.has(variable_declarator.id.name) + ) { + continue; + } + + if (variable_declarator.init?.type === 'Literal') { + page_options.set( + /** @type {string} */ (export_specifiers.get(variable_declarator.id.name)), + variable_declarator.init.value + ); + export_specifiers.delete(variable_declarator.id.name); + continue; + } + + // Special case: We only want to know that 'load' is exported (in a way that doesn't cause truthy checks in other places to trigger) + if (variable_declarator.id.name === 'load') { + page_options.set('load', null); + export_specifiers.delete('load'); + continue; + } + + // references a declaration we can't easily evaluate statically + return null; + } + break; + } + } + } + + // there were some export specifiers that we couldn't resolve + if (export_specifiers.size) { + return null; + } + continue; + } + + if (!statement.declaration) { + continue; + } + + // class and function declarations + if (statement.declaration.type !== 'VariableDeclaration') { + if (valid_page_options.has(statement.declaration.id.name)) { + // Special case: We only want to know that 'load' is exported (in a way that doesn't cause truthy checks in other places to trigger) + if (statement.declaration.id.name === 'load') { + page_options.set('load', null); + } else { + return null; + } + } + continue; + } + + for (const declaration of statement.declaration.declarations) { + if (declaration.id.type !== 'Identifier') { + return null; + } + + if (!valid_page_options.has(declaration.id.name)) { + continue; + } + + if (declaration.init?.type === 'Literal') { + page_options.set(declaration.id.name, declaration.init.value); + continue; + } + + // Special case: We only want to know that 'load' is exported (in a way that doesn't cause truthy checks in other places to trigger) + if (declaration.id.name === 'load') { + page_options.set('load', null); + continue; + } + + // references a declaration we can't easily evaluate statically + return null; + } + } + + return Object.fromEntries(page_options); + } catch (error) { + if (error instanceof Error) { + error.message = `Failed to statically analyse page options for ${filename}. ${error.message}`; + } + throw error; + } +} + +/** + * @param {import('acorn').Identifier | import('acorn').Literal} node + * @returns {string} + */ +function get_name(node) { + return node.type === 'Identifier' ? node.name : /** @type {string} */ (node.value); +} + +/** + * Reads and statically analyses a file for page options + * @param {string} filepath + * @returns {PageOptions | null} Returns the page options for the file or `null` if unanalysable + */ +export function get_page_options(filepath) { + try { + const input = read(filepath); + const page_options = statically_analyse_page_options(filepath, input); + if (page_options === null) { + return null; + } + + return page_options; + } catch { + return null; + } +} + +export function create_node_analyser() { + const static_exports = new Map(); + + /** + * @param {string | undefined} key + * @param {PageOptions | null} page_options + */ + const cache = (key, page_options) => { + if (key) static_exports.set(key, { page_options, children: [] }); + }; + + /** + * Computes the final page options (may include load function as `load: null`; special case) for a node (if possible). Otherwise, returns `null`. + * @param {import('types').PageNode} node + * @returns {PageOptions | null} + */ + const crawl = (node) => { + const key = node.universal || node.server; + if (key && static_exports.has(key)) { + return { ...static_exports.get(key)?.page_options }; + } + + /** @type {PageOptions} */ + let page_options = {}; + + if (node.parent) { + const parent_options = crawl(node.parent); + + const parent_key = node.parent.universal || node.parent.server; + if (key && parent_key) { + static_exports.get(parent_key)?.children.push(key); + } + + if (parent_options === null) { + // if the parent cannot be analysed, we can't know what page options + // the child node inherits, so we also mark it as unanalysable + cache(key, null); + return null; + } + + page_options = { ...parent_options }; + } + + if (node.server) { + const server_page_options = get_page_options(node.server); + if (server_page_options === null) { + cache(key, null); + return null; + } + page_options = { ...page_options, ...server_page_options }; + } + + if (node.universal) { + const universal_page_options = get_page_options(node.universal); + if (universal_page_options === null) { + cache(key, null); + return null; + } + page_options = { ...page_options, ...universal_page_options }; + } + + cache(key, page_options); + + return page_options; + }; + + return { + get_page_options: crawl + }; +} diff --git a/frontend/node_modules/@sveltejs/kit/src/exports/vite/static_analysis/utils.js b/frontend/node_modules/@sveltejs/kit/src/exports/vite/static_analysis/utils.js new file mode 100644 index 0000000..c39cc06 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/exports/vite/static_analysis/utils.js @@ -0,0 +1,118 @@ +/** + * Check if content has children rendering (slot, @render, or children prop forwarding) + * @param {string} content - The markup content + * @param {boolean} is_svelte_5_plus - Whether the project uses Svelte 5+ + * @returns {boolean} + */ +export function has_children(content, is_svelte_5_plus) { + return ( + content.includes('') { + in_html_comment = false; + i += 2; // Skip the '-->' part + continue; + } + + // If we're in any comment, skip processing + if (in_single_line_comment || in_multi_line_comment || in_html_comment) { + continue; + } + + // Handle escape sequences in strings + if ((in_single_quote || in_double_quote || in_template_literal) && char === '\\') { + i++; // Skip the escaped character + continue; + } + + // Handle string boundaries + if (!in_double_quote && !in_template_literal && char === "'") { + in_single_quote = !in_single_quote; + continue; + } + + if (!in_single_quote && !in_template_literal && char === '"') { + in_double_quote = !in_double_quote; + continue; + } + + if (!in_single_quote && !in_double_quote && char === '`') { + in_template_literal = !in_template_literal; + continue; + } + + // If we're inside any string, don't process comment delimiters + if (in_single_quote || in_double_quote || in_template_literal) { + continue; + } + + // Check for comment starts + if (next_two === '//') { + in_single_line_comment = true; + i++; // Skip the second '/' + continue; + } + + if (next_two === '/*') { + in_multi_line_comment = true; + i++; // Skip the '*' + continue; + } + + if (next_four === ' + * + * + *

Currently at {page.url.pathname}

+ * + * {#if page.error} + * Problem detected + * {:else} + * All systems operational + * {/if} + * ``` + * + * Changes to `page` are available exclusively with runes. (The legacy reactivity syntax will not reflect any changes) + * + * ```svelte + * + * + * ``` + * + * On the server, values can only be read during rendering (in other words _not_ in e.g. `load` functions). In the browser, the values can be read at any time. + * + * @type {import('@sveltejs/kit').Page} + */ +export const page = BROWSER ? client_page : server_page; + +/** + * A read-only object representing an in-progress navigation, with `from`, `to`, `type` and (if `type === 'popstate'`) `delta` properties. + * Values are `null` when no navigation is occurring, or during server rendering. + * @type {import('@sveltejs/kit').Navigation | { from: null, to: null, type: null, willUnload: null, delta: null, complete: null }} + */ +// @ts-expect-error +export const navigating = BROWSER ? client_navigating : server_navigating; + +/** + * A read-only reactive value that's initially `false`. If [`version.pollInterval`](https://svelte.dev/docs/kit/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update `current` to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling. + * @type {{ get current(): boolean; check(): Promise; }} + */ +export const updated = BROWSER ? client_updated : server_updated; diff --git a/frontend/node_modules/@sveltejs/kit/src/runtime/app/state/server.js b/frontend/node_modules/@sveltejs/kit/src/runtime/app/state/server.js new file mode 100644 index 0000000..0be1693 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/runtime/app/state/server.js @@ -0,0 +1,63 @@ +import { DEV } from 'esm-env'; +import { getContext } from 'svelte'; + +function context() { + return getContext('__request__'); +} + +/** @param {string} name */ +function context_dev(name) { + try { + return context(); + } catch { + throw new Error( + `Can only read '${name}' on the server during rendering (not in e.g. \`load\` functions), as it is bound to the current request via component context. This prevents state from leaking between users. ` + + 'For more information, see https://svelte.dev/docs/kit/state-management#avoid-shared-state-on-the-server' + ); + } +} + +export const page = { + get data() { + return (DEV ? context_dev('page.data') : context()).page.data; + }, + get error() { + return (DEV ? context_dev('page.error') : context()).page.error; + }, + get form() { + return (DEV ? context_dev('page.form') : context()).page.form; + }, + get params() { + return (DEV ? context_dev('page.params') : context()).page.params; + }, + get route() { + return (DEV ? context_dev('page.route') : context()).page.route; + }, + get state() { + return (DEV ? context_dev('page.state') : context()).page.state; + }, + get status() { + return (DEV ? context_dev('page.status') : context()).page.status; + }, + get url() { + return (DEV ? context_dev('page.url') : context()).page.url; + } +}; + +export const navigating = { + from: null, + to: null, + type: null, + willUnload: null, + delta: null, + complete: null +}; + +export const updated = { + get current() { + return false; + }, + check: () => { + throw new Error('Can only call updated.check() in the browser'); + } +}; diff --git a/frontend/node_modules/@sveltejs/kit/src/runtime/app/stores.js b/frontend/node_modules/@sveltejs/kit/src/runtime/app/stores.js new file mode 100644 index 0000000..11e84fe --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/runtime/app/stores.js @@ -0,0 +1,101 @@ +import { getContext } from 'svelte'; +import { BROWSER, DEV } from 'esm-env'; +import { stores as browser_stores } from '../client/client.js'; + +/** + * A function that returns all of the contextual stores. On the server, this must be called during component initialization. + * Only use this if you need to defer store subscription until after the component has mounted, for some reason. + * + * @deprecated Use `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated)) + */ +export const getStores = () => { + const stores = BROWSER ? browser_stores : getContext('__svelte__'); + + return { + /** @type {typeof page} */ + page: { + subscribe: stores.page.subscribe + }, + /** @type {typeof navigating} */ + navigating: { + subscribe: stores.navigating.subscribe + }, + /** @type {typeof updated} */ + updated: stores.updated + }; +}; + +/** + * A readable store whose value contains page data. + * + * On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time. + * + * @deprecated Use `page` from `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated)) + * @type {import('svelte/store').Readable} + */ +export const page = { + subscribe(fn) { + const store = DEV ? get_store('page') : getStores().page; + return store.subscribe(fn); + } +}; + +/** + * A readable store. + * When navigating starts, its value is a `Navigation` object with `from`, `to`, `type` and (if `type === 'popstate'`) `delta` properties. + * When navigating finishes, its value reverts to `null`. + * + * On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time. + * + * @deprecated Use `navigating` from `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated)) + * @type {import('svelte/store').Readable} + */ +export const navigating = { + subscribe(fn) { + const store = DEV ? get_store('navigating') : getStores().navigating; + return store.subscribe(fn); + } +}; + +/** + * A readable store whose initial value is `false`. If [`version.pollInterval`](https://svelte.dev/docs/kit/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update the store value to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling. + * + * On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time. + * + * @deprecated Use `updated` from `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated)) + * @type {import('svelte/store').Readable & { check(): Promise }} + */ +export const updated = { + subscribe(fn) { + const store = DEV ? get_store('updated') : getStores().updated; + + if (BROWSER) { + updated.check = store.check; + } + + return store.subscribe(fn); + }, + check: () => { + throw new Error( + BROWSER + ? 'Cannot check updated store before subscribing' + : 'Can only check updated store in browser' + ); + } +}; + +/** + * @template {keyof ReturnType} Name + * @param {Name} name + * @returns {ReturnType[Name]} + */ +function get_store(name) { + try { + return getStores()[name]; + } catch { + throw new Error( + `Cannot subscribe to '${name}' store on the server outside of a Svelte component, as it is bound to the current request via component context. This prevents state from leaking between users.` + + 'For more information, see https://svelte.dev/docs/kit/state-management#avoid-shared-state-on-the-server' + ); + } +} diff --git a/frontend/node_modules/@sveltejs/kit/src/runtime/client/bundle.js b/frontend/node_modules/@sveltejs/kit/src/runtime/client/bundle.js new file mode 100644 index 0000000..f375d02 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/runtime/client/bundle.js @@ -0,0 +1,17 @@ +/* if `bundleStrategy` is 'single' or 'inline', this file is used as the entry point */ + +import * as kit from './entry.js'; + +// @ts-expect-error +import * as app from '__sveltekit/manifest'; + +/** + * + * @param {HTMLElement} element + * @param {import('./types.js').HydrateOptions} options + */ +export function start(element, options) { + void kit.start(app, element, options); +} + +export { app }; diff --git a/frontend/node_modules/@sveltejs/kit/src/runtime/client/client.js b/frontend/node_modules/@sveltejs/kit/src/runtime/client/client.js new file mode 100644 index 0000000..d6ece57 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/runtime/client/client.js @@ -0,0 +1,3309 @@ +import { BROWSER, DEV } from 'esm-env'; +import * as svelte from 'svelte'; +import { HttpError, Redirect, SvelteKitError } from '@sveltejs/kit/internal'; +const { onMount, tick } = svelte; +// Svelte 4 and under don't have `untrack`, so we have to fallback if `untrack` is not exported +const untrack = svelte.untrack ?? ((value) => value()); +import { + decode_params, + decode_pathname, + strip_hash, + make_trackable, + normalize_path +} from '../../utils/url.js'; +import { dev_fetch, initial_fetch, lock_fetch, subsequent_fetch, unlock_fetch } from './fetcher.js'; +import { parse, parse_server_route } from './parse.js'; +import * as storage from './session-storage.js'; +import { + find_anchor, + resolve_url, + get_link_info, + get_router_options, + is_external_url, + origin, + scroll_state, + notifiable_store, + create_updated_store, + load_css +} from './utils.js'; +import { base } from '$app/paths'; +import * as devalue from 'devalue'; +import { + HISTORY_INDEX, + NAVIGATION_INDEX, + PRELOAD_PRIORITIES, + SCROLL_KEY, + STATES_KEY, + SNAPSHOT_KEY, + PAGE_URL_KEY +} from './constants.js'; +import { validate_page_exports } from '../../utils/exports.js'; +import { compact } from '../../utils/array.js'; +import { + INVALIDATED_PARAM, + TRAILING_SLASH_PARAM, + validate_depends, + validate_load_response +} from '../shared.js'; +import { get_message, get_status } from '../../utils/error.js'; +import { writable } from 'svelte/store'; +import { page, update, navigating } from './state.svelte.js'; +import { add_data_suffix, add_resolution_suffix } from '../pathname.js'; +import { noop_span } from '../telemetry/noop.js'; +import { text_decoder } from '../utils.js'; + +export { load_css }; +const ICON_REL_ATTRIBUTES = new Set(['icon', 'shortcut icon', 'apple-touch-icon']); + +let errored = false; +/** + * Set via transformError, reset and read at the end of navigate. + * Necessary because a navigation might succeed loading but during rendering + * an error occurs, at which point the navigation result needs to be overridden with the error result. + * TODO this is all very hacky, rethink for SvelteKit 3 where we can assume Svelte 5 and do an overhaul of client.js + * @type {{ error: App.Error, status: number } | null} + */ +let rendering_error = null; + +// We track the scroll position associated with each history entry in sessionStorage, +// rather than on history.state itself, because when navigation is driven by +// popstate it's too late to update the scroll position associated with the +// state we're navigating from +/** + * history index -> { x, y } + * @type {Record} + */ +const scroll_positions = storage.get(SCROLL_KEY) ?? {}; + +/** + * navigation index -> any + * @type {Record} + */ +const snapshots = storage.get(SNAPSHOT_KEY) ?? {}; + +if (DEV && BROWSER) { + let warned = false; + + const current_module_url = import.meta.url.split('?')[0]; // remove query params that vite adds to the URL when it is loaded from node_modules + + const warn = () => { + if (warned) return; + + // Rather than saving a pointer to the original history methods, which would prevent monkeypatching by other libs, + // inspect the stack trace to see if we're being called from within SvelteKit. + let stack = new Error().stack?.split('\n'); + if (!stack) return; + if (!stack[0].includes('https:') && !stack[0].includes('http:')) stack = stack.slice(1); // Chrome includes the error message in the stack + stack = stack.slice(2); // remove `warn` and the place where `warn` was called + // Can be falsy if was called directly from an anonymous function + if (stack[0]?.includes(current_module_url)) return; + + warned = true; + + console.warn( + "Avoid using `history.pushState(...)` and `history.replaceState(...)` as these will conflict with SvelteKit's router. Use the `pushState` and `replaceState` imports from `$app/navigation` instead." + ); + }; + + const push_state = history.pushState; + history.pushState = (...args) => { + warn(); + return push_state.apply(history, args); + }; + + const replace_state = history.replaceState; + history.replaceState = (...args) => { + warn(); + return replace_state.apply(history, args); + }; +} + +export const stores = { + url: /* @__PURE__ */ notifiable_store({}), + page: /* @__PURE__ */ notifiable_store({}), + navigating: /* @__PURE__ */ writable( + /** @type {import('@sveltejs/kit').Navigation | null} */ (null) + ), + updated: /* @__PURE__ */ create_updated_store() +}; + +/** @param {number} index */ +function update_scroll_positions(index) { + scroll_positions[index] = scroll_state(); +} + +/** + * @param {number} current_history_index + * @param {number} current_navigation_index + */ +function clear_onward_history(current_history_index, current_navigation_index) { + // if we navigated back, then pushed a new state, we can + // release memory by pruning the scroll/snapshot lookup + let i = current_history_index + 1; + while (scroll_positions[i]) { + delete scroll_positions[i]; + i += 1; + } + + i = current_navigation_index + 1; + while (snapshots[i]) { + delete snapshots[i]; + i += 1; + } +} + +/** + * Loads `href` the old-fashioned way, with a full page reload. + * Returns a `Promise` that never resolves (to prevent any + * subsequent work, e.g. history manipulation, from happening) + * @param {URL} url + * @param {boolean} [replace] If `true`, will replace the current `history` entry rather than creating a new one with `pushState` + */ +function native_navigation(url, replace = false) { + if (replace) { + location.replace(url.href); + } else { + location.href = url.href; + } + return new Promise(() => {}); +} + +/** + * Checks whether a service worker is registered, and if it is, + * tries to update it. + */ +async function update_service_worker() { + if ('serviceWorker' in navigator) { + const registration = await navigator.serviceWorker.getRegistration(base || '/'); + if (registration) { + await registration.update(); + } + } +} + +function noop() {} + +/** @type {import('types').CSRRoute[]} All routes of the app. Only available when kit.router.resolution=client */ +let routes; +/** @type {import('types').CSRPageNodeLoader} */ +let default_layout_loader; +/** @type {import('types').CSRPageNodeLoader} */ +let default_error_loader; +/** @type {HTMLElement} */ +let container; +/** @type {HTMLElement} */ +let target; + +/** @type {import('./types.js').SvelteKitApp} */ +export let app; + +/** + * Data that was serialized during SSR. This is cleared when the user first navigates + * @type {Record} + */ +export let remote_responses = {}; + +/** @type {Array<((url: URL) => boolean)>} */ +const invalidated = []; + +/** + * An array of the `+layout.svelte` and `+page.svelte` component instances + * that currently live on the page — used for capturing and restoring snapshots. + * It's updated/manipulated through `bind:this` in `Root.svelte`. + * @type {import('svelte').SvelteComponent[]} + */ +const components = []; + +/** @type {{id: string, token: {}, promise: Promise, fork: Promise | null} | null} */ +let load_cache = null; + +function discard_load_cache() { + void load_cache?.fork?.then((f) => f?.discard()); + load_cache = null; +} + +/** + * @type {Map>} + * Cache for client-side rerouting, since it could contain async calls which we want to + * avoid running multiple times which would slow down navigations (e.g. else preloading + * wouldn't help because on navigation it would be called again). Since `reroute` should be + * a pure function (i.e. always return the same) value it's safe to cache across navigations. + * The server reroute calls don't need to be cached because they are called using `import(...)` + * which is cached per the JS spec. + */ +const reroute_cache = new Map(); + +/** + * Note on before_navigate_callbacks, on_navigate_callbacks and after_navigate_callbacks: + * do not re-assign as some closures keep references to these Sets + */ +/** @type {Set<(navigation: import('@sveltejs/kit').BeforeNavigate) => void>} */ +const before_navigate_callbacks = new Set(); + +/** @type {Set<(navigation: import('@sveltejs/kit').OnNavigate) => import('types').MaybePromise<(() => void) | void>>} */ +const on_navigate_callbacks = new Set(); + +/** @type {Set<(navigation: import('@sveltejs/kit').AfterNavigate) => void>} */ +const after_navigate_callbacks = new Set(); + +/** @type {import('./types.js').NavigationState & { nav: import('@sveltejs/kit').NavigationEvent }} */ +let current = { + branch: [], + error: null, + // @ts-ignore - we need the initial value to be null + url: null, + // @ts-ignore - we need the initial value to be null + nav: null +}; + +/** this being true means we SSR'd */ +let hydrated = false; +let started = false; +let autoscroll = true; +let updating = false; +let is_navigating = false; +let hash_navigating = false; +/** True as soon as there happened one client-side navigation (excluding the SvelteKit-initialized initial one when in SPA mode) */ +let has_navigated = false; + +let force_invalidation = false; + +/** @type {import('svelte').SvelteComponent} */ +let root; + +/** @type {number} keeping track of the history index in order to prevent popstate navigation events if needed */ +let current_history_index; + +/** @type {number} */ +let current_navigation_index; + +/** @type {{}} */ +let token; + +/** + * A set of tokens which are associated to current preloads. + * If a preload becomes a real navigation, it's removed from the set. + * If a preload token is in the set and the preload errors, the error + * handling logic (for example reloading) is skipped. + */ +const preload_tokens = new Set(); + +/** @type {Promise | null} */ +export let pending_invalidate; + +/** + * @type {Map} + * A map of id -> query info with all queries that currently exist in the app. + */ +export const query_map = new Map(); + +/** + * @param {import('./types.js').SvelteKitApp} _app + * @param {HTMLElement} _target + * @param {Parameters[1]} [hydrate] + */ +export async function start(_app, _target, hydrate) { + if (DEV && _target === document.body) { + console.warn( + 'Placing %sveltekit.body% directly inside is not recommended, as your app may break for users who have certain browser extensions installed.\n\nConsider wrapping it in an element:\n\n
\n %sveltekit.body%\n
' + ); + } + + if (__SVELTEKIT_PAYLOAD__?.data) { + remote_responses = __SVELTEKIT_PAYLOAD__.data; + } + + // detect basic auth credentials in the current URL + // https://github.com/sveltejs/kit/pull/11179 + // if so, refresh the page without credentials + if (document.URL !== location.href) { + // eslint-disable-next-line no-self-assign + location.href = location.href; + } + + app = _app; + + await _app.hooks.init?.(); + + routes = __SVELTEKIT_CLIENT_ROUTING__ ? parse(_app) : []; + container = __SVELTEKIT_EMBEDDED__ ? _target : document.documentElement; + target = _target; + + // we import the root layout/error nodes eagerly, so that + // connectivity errors after initialisation don't nuke the app + default_layout_loader = _app.nodes[0]; + default_error_loader = _app.nodes[1]; + void default_layout_loader(); + void default_error_loader(); + + current_history_index = history.state?.[HISTORY_INDEX]; + current_navigation_index = history.state?.[NAVIGATION_INDEX]; + + if (!current_history_index) { + // we use Date.now() as an offset so that cross-document navigations + // within the app don't result in data loss + current_history_index = current_navigation_index = Date.now(); + + // create initial history entry, so we can return here + history.replaceState( + { + ...history.state, + [HISTORY_INDEX]: current_history_index, + [NAVIGATION_INDEX]: current_navigation_index + }, + '' + ); + } + + // if we reload the page, or Cmd-Shift-T back to it, + // recover scroll position + const scroll = scroll_positions[current_history_index]; + function restore_scroll() { + if (scroll) { + history.scrollRestoration = 'manual'; + scrollTo(scroll.x, scroll.y); + } + } + + if (hydrate) { + restore_scroll(); + + await _hydrate(target, hydrate); + } else { + await navigate({ + type: 'enter', + url: resolve_url(app.hash ? decode_hash(new URL(location.href)) : location.href), + replace_state: true + }); + + restore_scroll(); + } + + _start_router(); +} + +async function _invalidate(include_load_functions = true, reset_page_state = true) { + // Accept all invalidations as they come, don't swallow any while another invalidation + // is running because subsequent invalidations may make earlier ones outdated, + // but batch multiple synchronous invalidations. + await (pending_invalidate ||= Promise.resolve()); + if (!pending_invalidate) return; + pending_invalidate = null; + + const nav_token = (token = {}); + const intent = await get_navigation_intent(current.url, true); + + // Clear preload, it might be affected by the invalidation. + // Also solves an edge case where a preload is triggered, the navigation for it + // was then triggered and is still running while the invalidation kicks in, + // at which point the invalidation should take over and "win". + discard_load_cache(); + + // Rerun queries + if (force_invalidation) { + query_map.forEach(({ resource }) => { + resource.refresh?.(); + }); + } + + if (include_load_functions) { + const prev_state = page.state; + const navigation_result = intent && (await load_route(intent)); + if (!navigation_result || nav_token !== token) return; + + if (navigation_result.type === 'redirect') { + return _goto( + new URL(navigation_result.location, current.url).href, + { replaceState: true }, + 1, + nav_token + ); + } + + // This is a bit hacky but allows us not having to pass that boolean around, making things harder to reason about + if (!reset_page_state) { + navigation_result.props.page.state = prev_state; + } + update(navigation_result.props.page); + current = { ...navigation_result.state, nav: current.nav }; + reset_invalidation(); + root.$set(navigation_result.props); + } else { + reset_invalidation(); + } + + // Don't use allSettled yet because it's too new + await Promise.all([...query_map.values()].map(({ resource }) => resource)).catch(noop); +} + +function reset_invalidation() { + invalidated.length = 0; + force_invalidation = false; +} + +/** @param {number} index */ +function capture_snapshot(index) { + if (components.some((c) => c?.snapshot)) { + snapshots[index] = components.map((c) => c?.snapshot?.capture()); + } +} + +/** @param {number} index */ +function restore_snapshot(index) { + snapshots[index]?.forEach((value, i) => { + components[i]?.snapshot?.restore(value); + }); +} + +function persist_state() { + update_scroll_positions(current_history_index); + storage.set(SCROLL_KEY, scroll_positions); + + capture_snapshot(current_navigation_index); + storage.set(SNAPSHOT_KEY, snapshots); +} + +/** + * @param {string | URL} url + * @param {{ replaceState?: boolean; noScroll?: boolean; keepFocus?: boolean; invalidateAll?: boolean; invalidate?: Array boolean)>; state?: Record }} options + * @param {number} redirect_count + * @param {{}} [nav_token] + */ +export async function _goto(url, options, redirect_count, nav_token) { + /** @type {string[]} */ + let query_keys; + + // Clear preload cache when invalidateAll is true to ensure fresh data + // after form submissions or explicit invalidations + if (options.invalidateAll) { + discard_load_cache(); + } + + await navigate({ + type: 'goto', + url: resolve_url(url), + keepfocus: options.keepFocus, + noscroll: options.noScroll, + replace_state: options.replaceState, + state: options.state, + redirect_count, + nav_token, + accept: () => { + if (options.invalidateAll) { + force_invalidation = true; + query_keys = [...query_map.keys()]; + } + + if (options.invalidate) { + options.invalidate.forEach(push_invalidated); + } + } + }); + + if (options.invalidateAll) { + // TODO the ticks shouldn't be necessary, something inside Svelte itself is buggy + // when a query in a layout that still exists after page change is refreshed earlier than this + void svelte + .tick() + .then(svelte.tick) + .then(() => { + query_map.forEach(({ resource }, key) => { + // Only refresh those that already existed on the old page + if (query_keys?.includes(key)) { + resource.refresh?.(); + } + }); + }); + } +} + +/** @param {import('./types.js').NavigationIntent} intent */ +async function _preload_data(intent) { + // Reuse the existing pending preload if it's for the same navigation. + // Prevents an edge case where same preload is triggered multiple times, + // then a later one is becoming the real navigation and the preload tokens + // get out of sync. + if (intent.id !== load_cache?.id) { + discard_load_cache(); + + const preload = {}; + preload_tokens.add(preload); + load_cache = { + id: intent.id, + token: preload, + promise: load_route({ ...intent, preload }).then((result) => { + preload_tokens.delete(preload); + if (result.type === 'loaded' && result.state.error) { + // Don't cache errors, because they might be transient + discard_load_cache(); + } + return result; + }), + fork: null + }; + + if (__SVELTEKIT_FORK_PRELOADS__ && svelte.fork) { + const lc = load_cache; + + lc.fork = lc.promise.then((result) => { + // if load_cache was discarded before load_cache.promise could + // resolve, bail rather than creating an orphan fork + if (lc === load_cache && result.type === 'loaded') { + try { + return svelte.fork(() => { + root.$set(result.props); + update(result.props.page); + }); + } catch { + // if it errors, it's because the experimental flag isn't enabled in Svelte + } + } + + return null; + }); + } + } + + return load_cache.promise; +} + +/** + * @param {URL} url + * @returns {Promise} + */ +async function _preload_code(url) { + const route = (await get_navigation_intent(url, false))?.route; + + if (route) { + await Promise.all( + /** @type {[has_server_load: boolean, node_loader: import('types').CSRPageNodeLoader][]} */ ( + [...route.layouts, route.leaf].filter(Boolean) + ).map((load) => load[1]()) + ); + } +} + +/** + * @param {import('./types.js').NavigationFinished} result + * @param {HTMLElement} target + * @param {boolean} hydrate + */ +async function initialize(result, target, hydrate) { + if (DEV && result.state.error && document.querySelector('vite-error-overlay')) return; + + /** @type {import('@sveltejs/kit').NavigationEvent} */ + const nav = { + params: current.params, + route: { id: current.route?.id ?? null }, + url: new URL(location.href) + }; + + current = { + ...result.state, + nav + }; + + const style = document.querySelector('style[data-sveltekit]'); + if (style) style.remove(); + + Object.assign(page, /** @type {import('@sveltejs/kit').Page} */ (result.props.page)); + + root = new app.root({ + target, + props: { ...result.props, stores, components }, + hydrate, + // @ts-ignore Svelte 5 specific: asynchronously instantiate the component, i.e. don't call flushSync + sync: false, + // @ts-ignore Svelte 5 specific: transformError allows to transform errors before they are passed to boundaries + transformError: __SVELTEKIT_EXPERIMENTAL_USE_TRANSFORM_ERROR__ + ? /** @param {unknown} e */ async (e) => { + const error = await handle_error(e, current.nav); + rendering_error = { error, status: get_status(e) }; + page.error = error; + page.status = rendering_error.status; + return error; + } + : undefined + }); + + // Wait for a microtask in case svelte experimental async is enabled, + // which causes component script blocks to run asynchronously + void (await Promise.resolve()); + + restore_snapshot(current_navigation_index); + + if (hydrate) { + /** @type {import('@sveltejs/kit').AfterNavigate} */ + const navigation = { + from: null, + to: { + ...nav, + scroll: scroll_positions[current_history_index] ?? scroll_state() + }, + willUnload: false, + type: 'enter', + complete: Promise.resolve() + }; + + after_navigate_callbacks.forEach((fn) => fn(navigation)); + } + + started = true; +} + +/** + * + * @param {{ + * url: URL; + * params: Record; + * branch: Array; + * errors?: Array; + * status: number; + * error: App.Error | null; + * route: import('types').CSRRoute | null; + * form?: Record | null; + * }} opts + */ +async function get_navigation_result_from_branch({ + url, + params, + branch, + errors, + status, + error, + route, + form +}) { + /** @type {import('types').TrailingSlash} */ + let slash = 'never'; + + // if `paths.base === '/a/b/c`, then the root route is always `/a/b/c/`, regardless of + // the `trailingSlash` route option, so that relative paths to JS and CSS work + if (base && (url.pathname === base || url.pathname === base + '/')) { + slash = 'always'; + } else { + for (const node of branch) { + if (node?.slash !== undefined) slash = node.slash; + } + } + + url.pathname = normalize_path(url.pathname, slash); + // eslint-disable-next-line no-self-assign + url.search = url.search; // turn `/?` into `/` + + /** @type {import('./types.js').NavigationFinished} */ + const result = { + type: 'loaded', + state: { + url, + params, + branch, + error, + route + }, + props: { + // @ts-ignore Somehow it's getting SvelteComponent and SvelteComponentDev mixed up + constructors: compact(branch).map((branch_node) => branch_node.node.component), + page: clone_page(page) + } + }; + + if (errors && __SVELTEKIT_EXPERIMENTAL_USE_TRANSFORM_ERROR__) { + let last_idx = -1; + result.props.errors = await Promise.all( + // eslint-disable-next-line @typescript-eslint/await-thenable + branch + .map((b, i) => { + if (i === 0) return undefined; // root layout wraps root error component, not the other way around + if (!b) return null; + + i--; + // Find the closest error component up to the previous branch + while (i > last_idx + 1 && !errors[i]) i -= 1; + last_idx = i; + return errors[i]?.() + .then((e) => e.component) + .catch(() => undefined); + }) + // filter out indexes where there was no branch, but keep indexes where there was a branch but no error component + .filter((e) => e !== null) + ); + } + + if (error && __SVELTEKIT_EXPERIMENTAL_USE_TRANSFORM_ERROR__) { + result.props.error = error; + } + + if (form !== undefined) { + result.props.form = form; + } + + let data = {}; + let data_changed = !page; + + let p = 0; + + for (let i = 0; i < Math.max(branch.length, current.branch.length); i += 1) { + const node = branch[i]; + const prev = current.branch[i]; + + if (node?.data !== prev?.data) data_changed = true; + if (!node) continue; + + data = { ...data, ...node.data }; + + // Only set props if the node actually updated. This prevents needless rerenders. + if (data_changed) { + result.props[`data_${p}`] = data; + } + + p += 1; + } + + const page_changed = + !current.url || + url.href !== current.url.href || + current.error !== error || + (form !== undefined && form !== page.form) || + data_changed; + + if (page_changed) { + result.props.page = { + error, + params, + route: { + id: route?.id ?? null + }, + state: {}, + status, + url: new URL(url), + form: form ?? null, + // The whole page store is updated, but this way the object reference stays the same + data: data_changed ? data : page.data + }; + } + + return result; +} + +/** + * Call the universal load function of the given node, if it exists. + * + * @param {{ + * loader: import('types').CSRPageNodeLoader; + * parent: () => Promise>; + * url: URL; + * params: Record; + * route: { id: string | null }; + * server_data_node: import('./types.js').DataNode | null; + * }} options + * @returns {Promise} + */ +async function load_node({ loader, parent, url, params, route, server_data_node }) { + /** @type {Record | null} */ + let data = null; + + let is_tracking = true; + + /** @type {import('types').Uses} */ + const uses = { + dependencies: new Set(), + params: new Set(), + parent: false, + route: false, + url: false, + search_params: new Set() + }; + + const node = await loader(); + + if (DEV) { + validate_page_exports(node.universal); + + if (node.universal && app.hash) { + const options = Object.keys(node.universal).filter((o) => o !== 'load'); + + if (options.length > 0) { + throw new Error( + `Page options are ignored when \`router.type === 'hash'\` (${route.id} has ${options + .filter((o) => o !== 'load') + .map((o) => `'${o}'`) + .join(', ')})` + ); + } + } + } + + if (__SVELTEKIT_HAS_UNIVERSAL_LOAD__ && node.universal?.load) { + /** @param {string[]} deps */ + function depends(...deps) { + for (const dep of deps) { + if (DEV) validate_depends(/** @type {string} */ (route.id), dep); + + const { href } = new URL(dep, url); + uses.dependencies.add(href); + } + } + + /** @type {import('@sveltejs/kit').LoadEvent} */ + const load_input = { + tracing: { enabled: false, root: noop_span, current: noop_span }, + route: new Proxy(route, { + get: (target, key) => { + if (is_tracking) { + uses.route = true; + } + return target[/** @type {'id'} */ (key)]; + } + }), + params: new Proxy(params, { + get: (target, key) => { + if (is_tracking) { + uses.params.add(/** @type {string} */ (key)); + } + return target[/** @type {string} */ (key)]; + } + }), + data: server_data_node?.data ?? null, + url: make_trackable( + url, + () => { + if (is_tracking) { + uses.url = true; + } + }, + (param) => { + if (is_tracking) { + uses.search_params.add(param); + } + }, + app.hash + ), + async fetch(resource, init) { + if (resource instanceof Request) { + // we're not allowed to modify the received `Request` object, so in order + // to fixup relative urls we create a new equivalent `init` object instead + init = { + // the request body must be consumed in memory until browsers + // implement streaming request bodies and/or the body getter + body: + resource.method === 'GET' || resource.method === 'HEAD' + ? undefined + : await resource.blob(), + cache: resource.cache, + credentials: resource.credentials, + // the server sets headers to `undefined` if there are no headers but + // the client defaults to an empty Headers object in the Request object. + // To keep the two values in sync, we explicitly set the headers to `undefined`. + // Also, not sure why, but sometimes 0 is evaluated as truthy so we need to + // explicitly compare the headers length to a number here + headers: [...resource.headers].length > 0 ? resource?.headers : undefined, + integrity: resource.integrity, + keepalive: resource.keepalive, + method: resource.method, + mode: resource.mode, + redirect: resource.redirect, + referrer: resource.referrer, + referrerPolicy: resource.referrerPolicy, + signal: resource.signal, + ...init + }; + } + + const { resolved, promise } = resolve_fetch_url(resource, init, url); + + if (is_tracking) { + depends(resolved.href); + } + + return promise; + }, + setHeaders: () => {}, // noop + depends, + parent() { + if (is_tracking) { + uses.parent = true; + } + return parent(); + }, + untrack(fn) { + is_tracking = false; + try { + return fn(); + } finally { + is_tracking = true; + } + } + }; + + if (DEV) { + try { + lock_fetch(); + data = (await node.universal.load.call(null, load_input)) ?? null; + validate_load_response(data, `related to route '${route.id}'`); + } finally { + unlock_fetch(); + } + } else { + data = (await node.universal.load.call(null, load_input)) ?? null; + } + } + + return { + node, + loader, + server: server_data_node, + universal: node.universal?.load ? { type: 'data', data, uses } : null, + data: data ?? server_data_node?.data ?? null, + slash: node.universal?.trailingSlash ?? server_data_node?.slash + }; +} + +/** + * @param {Request | string | URL} input + * @param {RequestInit | undefined} init + * @param {URL} url + */ +function resolve_fetch_url(input, init, url) { + let requested = input instanceof Request ? input.url : input; + + // we must fixup relative urls so they are resolved from the target page + const resolved = new URL(requested, url); + + // match ssr serialized data url, which is important to find cached responses + if (resolved.origin === url.origin) { + requested = resolved.href.slice(url.origin.length); + } + + // prerendered pages may be served from any origin, so `initial_fetch` urls shouldn't be resolved + const promise = started + ? subsequent_fetch(requested, resolved.href, init) + : initial_fetch(requested, init); + + return { resolved, promise }; +} + +/** + * @param {boolean} parent_changed + * @param {boolean} route_changed + * @param {boolean} url_changed + * @param {Set} search_params_changed + * @param {import('types').Uses | undefined} uses + * @param {Record} params + */ +function has_changed( + parent_changed, + route_changed, + url_changed, + search_params_changed, + uses, + params +) { + if (force_invalidation) return true; + + if (!uses) return false; + + if (uses.parent && parent_changed) return true; + if (uses.route && route_changed) return true; + if (uses.url && url_changed) return true; + + for (const tracked_params of uses.search_params) { + if (search_params_changed.has(tracked_params)) return true; + } + + for (const param of uses.params) { + if (params[param] !== current.params[param]) return true; + } + + for (const href of uses.dependencies) { + if (invalidated.some((fn) => fn(new URL(href)))) return true; + } + + return false; +} + +/** + * @param {import('types').ServerDataNode | import('types').ServerDataSkippedNode | null} node + * @param {import('./types.js').DataNode | null} [previous] + * @returns {import('./types.js').DataNode | null} + */ +function create_data_node(node, previous) { + if (node?.type === 'data') return node; + if (node?.type === 'skip') return previous ?? null; + return null; +} + +/** + * @param {URL | null} old_url + * @param {URL} new_url + */ +function diff_search_params(old_url, new_url) { + if (!old_url) return new Set(new_url.searchParams.keys()); + + const changed = new Set([...old_url.searchParams.keys(), ...new_url.searchParams.keys()]); + + for (const key of changed) { + const old_values = old_url.searchParams.getAll(key); + const new_values = new_url.searchParams.getAll(key); + + if ( + old_values.every((value) => new_values.includes(value)) && + new_values.every((value) => old_values.includes(value)) + ) { + changed.delete(key); + } + } + + return changed; +} + +/** + * @param {Omit & { error: App.Error }} opts + * @returns {import('./types.js').NavigationFinished} + */ +function preload_error({ error, url, route, params }) { + return { + type: 'loaded', + state: { + error, + url, + route, + params, + branch: [] + }, + props: { + page: clone_page(page), + constructors: [] + } + }; +} + +/** + * @param {import('./types.js').NavigationIntent & { preload?: {} }} intent + * @returns {Promise} + */ +async function load_route({ id, invalidating, url, params, route, preload }) { + if (load_cache?.id === id) { + // the preload becomes the real navigation + preload_tokens.delete(load_cache.token); + return load_cache.promise; + } + + const { errors, layouts, leaf } = route; + + const loaders = [...layouts, leaf]; + + // preload modules to avoid waterfall, but handle rejections + // so they don't get reported to Sentry et al (we don't need + // to act on the failures at this point) + errors.forEach((loader) => loader?.().catch(() => {})); + loaders.forEach((loader) => loader?.[1]().catch(() => {})); + + /** @type {import('types').ServerNodesResponse | import('types').ServerRedirectNode | null} */ + let server_data = null; + const url_changed = current.url ? id !== get_page_key(current.url) : false; + const route_changed = current.route ? route.id !== current.route.id : false; + const search_params_changed = diff_search_params(current.url, url); + + let parent_invalid = false; + + if (__SVELTEKIT_HAS_SERVER_LOAD__) { + const invalid_server_nodes = loaders.map((loader, i) => { + const previous = current.branch[i]; + + const invalid = + !!loader?.[0] && + (previous?.loader !== loader[1] || + has_changed( + parent_invalid, + route_changed, + url_changed, + search_params_changed, + previous.server?.uses, + params + )); + + if (invalid) { + // For the next one + parent_invalid = true; + } + + return invalid; + }); + + if (invalid_server_nodes.some(Boolean)) { + try { + server_data = await load_data(url, invalid_server_nodes); + } catch (error) { + const handled_error = await handle_error(error, { url, params, route: { id } }); + + if (preload_tokens.has(preload)) { + return preload_error({ error: handled_error, url, params, route }); + } + + return load_root_error_page({ + status: get_status(error), + error: handled_error, + url, + route + }); + } + + if (server_data.type === 'redirect') { + return server_data; + } + } + } + + const server_data_nodes = server_data?.nodes; + + let parent_changed = false; + + const branch_promises = loaders.map(async (loader, i) => { + if (!loader) return; + + /** @type {import('./types.js').BranchNode | undefined} */ + const previous = current.branch[i]; + + const server_data_node = server_data_nodes?.[i]; + + // re-use data from previous load if it's still valid + const valid = + (!server_data_node || server_data_node.type === 'skip') && + loader[1] === previous?.loader && + !has_changed( + parent_changed, + route_changed, + url_changed, + search_params_changed, + previous.universal?.uses, + params + ); + if (valid) return previous; + + parent_changed = true; + + if (server_data_node?.type === 'error') { + // rethrow and catch below + throw server_data_node; + } + + return load_node({ + loader: loader[1], + url, + params, + route, + parent: async () => { + const data = {}; + for (let j = 0; j < i; j += 1) { + Object.assign(data, (await branch_promises[j])?.data); + } + return data; + }, + server_data_node: create_data_node( + // server_data_node is undefined if it wasn't reloaded from the server; + // and if current loader uses server data, we want to reuse previous data. + server_data_node === undefined && loader[0] ? { type: 'skip' } : (server_data_node ?? null), + loader[0] ? previous?.server : undefined + ) + }); + }); + + // if we don't do this, rejections will be unhandled + for (const p of branch_promises) p.catch(() => {}); + + /** @type {Array} */ + const branch = []; + + for (let i = 0; i < loaders.length; i += 1) { + if (loaders[i]) { + try { + branch.push(await branch_promises[i]); + } catch (err) { + if (err instanceof Redirect) { + return { + type: 'redirect', + location: err.location + }; + } + + if (preload_tokens.has(preload)) { + return preload_error({ + error: await handle_error(err, { params, url, route: { id: route.id } }), + url, + params, + route + }); + } + + let status = get_status(err); + /** @type {App.Error} */ + let error; + + if (server_data_nodes?.includes(/** @type {import('types').ServerErrorNode} */ (err))) { + // this is the server error rethrown above, reconstruct but don't invoke + // the client error handler; it should've already been handled on the server + status = /** @type {import('types').ServerErrorNode} */ (err).status ?? status; + error = /** @type {import('types').ServerErrorNode} */ (err).error; + } else if (err instanceof HttpError) { + error = err.body; + } else { + // Referenced node could have been removed due to redeploy, check + const updated = await stores.updated.check(); + if (updated) { + // Before reloading, try to update the service worker if it exists + await update_service_worker(); + return await native_navigation(url); + } + + error = await handle_error(err, { params, url, route: { id: route.id } }); + } + + const error_load = await load_nearest_error_page(i, branch, errors); + if (error_load) { + return get_navigation_result_from_branch({ + url, + params, + branch: branch.slice(0, error_load.idx).concat(error_load.node), + errors, + status, + error, + route + }); + } else { + return await server_fallback(url, { id: route.id }, error, status); + } + } + } else { + // push an empty slot so we can rewind past gaps to the + // layout that corresponds with an +error.svelte page + branch.push(undefined); + } + } + + return get_navigation_result_from_branch({ + url, + params, + branch, + errors, + status: 200, + error: null, + route, + // Reset `form` on navigation, but not invalidation + form: invalidating ? undefined : null + }); +} + +/** + * @param {number} i Start index to backtrack from + * @param {Array} branch Branch to backtrack + * @param {Array} errors All error pages for this branch + * @returns {Promise<{idx: number; node: import('./types.js').BranchNode} | undefined>} + */ +async function load_nearest_error_page(i, branch, errors) { + while (i--) { + if (errors[i]) { + let j = i; + while (!branch[j]) j -= 1; + try { + return { + idx: j + 1, + node: { + node: await /** @type {import('types').CSRPageNodeLoader } */ (errors[i])(), + loader: /** @type {import('types').CSRPageNodeLoader } */ (errors[i]), + data: {}, + server: null, + universal: null + } + }; + } catch { + continue; + } + } + } +} + +/** + * @param {{ + * status: number; + * error: App.Error; + * url: URL; + * route: { id: string | null } + * }} opts + * @returns {Promise} + */ +async function load_root_error_page({ status, error, url, route }) { + /** @type {Record} */ + const params = {}; // error page does not have params + + /** @type {import('types').ServerDataNode | null} */ + let server_data_node = null; + + if (__SVELTEKIT_HAS_SERVER_LOAD__) { + const default_layout_has_server_load = app.server_loads[0] === 0; + + if (default_layout_has_server_load) { + // TODO post-https://github.com/sveltejs/kit/discussions/6124 we can use + // existing root layout data + try { + const server_data = await load_data(url, [true]); + + if ( + server_data.type !== 'data' || + (server_data.nodes[0] && server_data.nodes[0].type !== 'data') + ) { + throw 0; + } + + server_data_node = server_data.nodes[0] ?? null; + } catch { + // at this point we have no choice but to fall back to the server, if it wouldn't + // bring us right back here, turning this into an endless loop + if (url.origin !== origin || url.pathname !== location.pathname || hydrated) { + await native_navigation(url); + } + } + } + } + + try { + const root_layout = await load_node({ + loader: default_layout_loader, + url, + params, + route, + parent: () => Promise.resolve({}), + server_data_node: create_data_node(server_data_node) + }); + + /** @type {import('./types.js').BranchNode} */ + const root_error = { + node: await default_error_loader(), + loader: default_error_loader, + universal: null, + server: null, + data: null + }; + + return get_navigation_result_from_branch({ + url, + params, + branch: [root_layout, root_error], + status, + error, + errors: [], + route: null + }); + } catch (error) { + if (error instanceof Redirect) { + // @ts-expect-error TODO investigate this + return _goto(new URL(error.location, location.href), {}, 0); + } + + // TODO: this falls back to the server when a server exists, but what about SPA mode? + throw error; + } +} + +/** + * Resolve the relative rerouted URL for a client-side navigation + * @param {URL} url + * @returns {Promise} + */ +async function get_rerouted_url(url) { + const href = url.href; + + if (reroute_cache.has(href)) { + return reroute_cache.get(href); + } + + let rerouted; + + try { + const promise = (async () => { + // reroute could alter the given URL, so we pass a copy + let rerouted = + (await app.hooks.reroute({ + url: new URL(url), + fetch: async (input, init) => { + return resolve_fetch_url(input, init, url).promise; + } + })) ?? url; + + if (typeof rerouted === 'string') { + const tmp = new URL(url); // do not mutate the incoming URL + + if (app.hash) { + tmp.hash = rerouted; + } else { + tmp.pathname = rerouted; + } + + rerouted = tmp; + } + + return rerouted; + })(); + + reroute_cache.set(href, promise); + rerouted = await promise; + } catch (e) { + reroute_cache.delete(href); + if (DEV) { + // in development, print the error... + console.error(e); + + // ...and pause execution, since otherwise we will immediately reload the page + debugger; // eslint-disable-line + } + + // fall back to native navigation + return; + } + + return rerouted; +} + +/** + * Resolve the full info (which route, params, etc.) for a client-side navigation from the URL, + * taking the reroute hook into account. If this isn't a client-side-navigation (or the URL is undefined), + * returns undefined. + * @param {URL | undefined} url + * @param {boolean} invalidating + * @returns {Promise} + */ +export async function get_navigation_intent(url, invalidating) { + if (!url) return; + if (is_external_url(url, base, app.hash)) return; + + if (__SVELTEKIT_CLIENT_ROUTING__) { + const rerouted = await get_rerouted_url(url); + if (!rerouted) return; + + const path = get_url_path(rerouted); + + for (const route of routes) { + const params = route.exec(path); + + if (params) { + return { + id: get_page_key(url), + invalidating, + route, + params: decode_params(params), + url + }; + } + } + } else { + /** @type {{ route?: import('types').CSRRouteServer, params: Record}} */ + const { route, params } = await import( + /* @vite-ignore */ + add_resolution_suffix(url.pathname) + ); + + if (!route) return; + + return { + id: get_page_key(url), + invalidating, + route: parse_server_route(route, app.nodes), + params, + url + }; + } +} + +/** @param {URL} url */ +function get_url_path(url) { + return ( + decode_pathname( + app.hash ? url.hash.replace(/^#/, '').replace(/[?#].+/, '') : url.pathname.slice(base.length) + ) || '/' + ); +} + +/** @param {URL} url */ +function get_page_key(url) { + return (app.hash ? url.hash.replace(/^#/, '') : url.pathname) + url.search; +} + +/** + * @param {{ + * url: URL; + * type: import('@sveltejs/kit').Navigation["type"]; + * intent?: import('./types.js').NavigationIntent; + * delta?: number; + * event?: PopStateEvent | MouseEvent; + * scroll?: { x: number, y: number }; + * }} opts + */ +function _before_navigate({ url, type, intent, delta, event, scroll }) { + let should_block = false; + + const nav = create_navigation(current, intent, url, type, scroll ?? null); + + if (delta !== undefined) { + nav.navigation.delta = delta; + } + + if (event !== undefined) { + // @ts-ignore + nav.navigation.event = event; + } + + const cancellable = { + ...nav.navigation, + cancel: () => { + should_block = true; + nav.reject(new Error('navigation cancelled')); + } + }; + + if (!is_navigating) { + // Don't run the event during redirects + before_navigate_callbacks.forEach((fn) => fn(cancellable)); + } + + return should_block ? null : nav; +} + +/** + * @param {{ + * type: import('@sveltejs/kit').NavigationType; + * url: URL; + * popped?: { + * state: Record; + * scroll: { x: number, y: number }; + * delta: number; + * }; + * keepfocus?: boolean; + * noscroll?: boolean; + * replace_state?: boolean; + * state?: Record; + * redirect_count?: number; + * nav_token?: {}; + * accept?: () => void; + * block?: () => void; + * event?: Event + * }} opts + */ +async function navigate({ + type, + url, + popped, + keepfocus, + noscroll, + replace_state, + state = {}, + redirect_count = 0, + nav_token = {}, + accept = noop, + block = noop, + event +}) { + remote_responses = {}; + + const prev_token = token; + token = nav_token; + + const intent = await get_navigation_intent(url, false); + const nav = + type === 'enter' + ? create_navigation(current, intent, url, type) + : _before_navigate({ + url, + type, + delta: popped?.delta, + intent, + scroll: popped?.scroll, + // @ts-ignore + event + }); + + if (!nav) { + block(); + if (token === nav_token) token = prev_token; + return; + } + + // store this before calling `accept()`, which may change the index + const previous_history_index = current_history_index; + const previous_navigation_index = current_navigation_index; + + accept(); + + is_navigating = true; + + if (started && nav.navigation.type !== 'enter') { + stores.navigating.set((navigating.current = nav.navigation)); + } + + let navigation_result = intent && (await load_route(intent)); + + if (!navigation_result) { + if (is_external_url(url, base, app.hash)) { + if (DEV && app.hash) { + // Special case for hash mode during DEV: If someone accidentally forgets to use a hash for the link, + // they would end up here in an endless loop. Fall back to error page in that case + navigation_result = await server_fallback( + url, + { id: null }, + await handle_error( + new SvelteKitError( + 404, + 'Not Found', + `Not found: ${url.pathname} (did you forget the hash?)` + ), + { + url, + params: {}, + route: { id: null } + } + ), + 404, + replace_state + ); + } else { + return await native_navigation(url, replace_state); + } + } else { + navigation_result = await server_fallback( + url, + { id: null }, + await handle_error(new SvelteKitError(404, 'Not Found', `Not found: ${url.pathname}`), { + url, + params: {}, + route: { id: null } + }), + 404, + replace_state + ); + } + } + + // if this is an internal navigation intent, use the normalized + // URL for the rest of the function + url = intent?.url || url; + + // abort if user navigated during update + if (token !== nav_token) { + nav.reject(new Error('navigation aborted')); + return false; + } + + if (navigation_result.type === 'redirect') { + // whatwg fetch spec https://fetch.spec.whatwg.org/#http-redirect-fetch says to error after 20 redirects + if (redirect_count < 20) { + await navigate({ + type, + url: new URL(navigation_result.location, url), + popped, + keepfocus, + noscroll, + replace_state, + state, + redirect_count: redirect_count + 1, + nav_token + }); + + nav.fulfil(undefined); + return; + } + + navigation_result = await load_root_error_page({ + status: 500, + error: await handle_error(new Error('Redirect loop'), { + url, + params: {}, + route: { id: null } + }), + url, + route: { id: null } + }); + } else if (/** @type {number} */ (navigation_result.props.page.status) >= 400) { + const updated = await stores.updated.check(); + if (updated) { + // Before reloading, try to update the service worker if it exists + await update_service_worker(); + await native_navigation(url, replace_state); + } + } + + // reset invalidation only after a finished navigation. If there are redirects or + // additional invalidations, they should get the same invalidation treatment + reset_invalidation(); + + updating = true; + + update_scroll_positions(previous_history_index); + capture_snapshot(previous_navigation_index); + + // ensure the url pathname matches the page's trailing slash option + if (navigation_result.props.page.url.pathname !== url.pathname) { + url.pathname = navigation_result.props.page.url.pathname; + } + + state = popped ? popped.state : state; + + if (!popped) { + // this is a new navigation, rather than a popstate + const change = replace_state ? 0 : 1; + + const entry = { + [HISTORY_INDEX]: (current_history_index += change), + [NAVIGATION_INDEX]: (current_navigation_index += change), + [STATES_KEY]: state + }; + + const fn = replace_state ? history.replaceState : history.pushState; + fn.call(history, entry, '', url); + + if (!replace_state) { + clear_onward_history(current_history_index, current_navigation_index); + } + } + + // also compare ids to avoid using wrong fork (e.g. a new one could've been added while navigating) + const load_cache_fork = intent && load_cache?.id === intent.id ? load_cache.fork : null; + // reset preload synchronously after the history state has been set to avoid race conditions + load_cache = null; + + navigation_result.props.page.state = state; + + /** + * @type {Promise | undefined} + */ + let commit_promise; + if (started) { + const after_navigate = ( + await Promise.all( + // eslint-disable-next-line @typescript-eslint/await-thenable -- we need to await because they can be asynchronous + Array.from(on_navigate_callbacks, (fn) => + fn(/** @type {import('@sveltejs/kit').OnNavigate} */ (nav.navigation)) + ) + ) + ).filter(/** @returns {value is () => void} */ (value) => typeof value === 'function'); + + if (after_navigate.length > 0) { + function cleanup() { + after_navigate.forEach((fn) => { + after_navigate_callbacks.delete(fn); + }); + } + + after_navigate.push(cleanup); + + after_navigate.forEach((fn) => { + after_navigate_callbacks.add(fn); + }); + } + + // Type-casts are save because we know this resolved a proper SvelteKit route + const target = /** @type {import('@sveltejs/kit').NavigationTarget} */ (nav.navigation.to); + current = { + ...navigation_result.state, + nav: { + params: /** @type {Record} */ (target.params), + route: target.route, + url: target.url + } + }; + + // reset url before updating page store + if (navigation_result.props.page) { + navigation_result.props.page.url = url; + } + + const fork = load_cache_fork && (await load_cache_fork); + + if (fork) { + commit_promise = fork.commit(); + } else { + rendering_error = null; // TODO this can break with forks, rethink for SvelteKit 3 where we can assume Svelte 5 + root.$set(navigation_result.props); + // Check for sync rendering error + if (rendering_error) { + Object.assign(navigation_result.props.page, rendering_error); + } + update(navigation_result.props.page); + + commit_promise = svelte.settled?.(); + } + + has_navigated = true; + } else { + await initialize(navigation_result, target, false); + } + + const { activeElement } = document; + + await commit_promise; + + // TODO 3.0 remote — the double tick is probably necessary because + // of some store shenanigans. `settled()` and `f.commit()` + // should resolve after DOM updates in newer versions + await svelte.tick(); + await svelte.tick(); + + // we reset scroll before dealing with focus, to avoid a flash of unscrolled content + /** @type {Element | null | ''} */ + let deep_linked = null; + + if (autoscroll) { + const scroll = popped ? popped.scroll : noscroll ? scroll_state() : null; + if (scroll) { + scrollTo(scroll.x, scroll.y); + } else if ((deep_linked = url.hash && document.getElementById(get_id(url)))) { + // Here we use `scrollIntoView` on the element instead of `scrollTo` + // because it natively supports the `scroll-margin` and `scroll-behavior` + // CSS properties. + deep_linked.scrollIntoView(); + } else { + scrollTo(0, 0); + } + } + + const changed_focus = + // reset focus only if any manual focus management didn't override it + document.activeElement !== activeElement && + // also refocus when activeElement is body already because the + // focus event might not have been fired on it yet + document.activeElement !== document.body; + + if (!keepfocus && !changed_focus) { + // We don't need to manually restore the scroll position if we're navigating + // to a fragment identifier. It is automatically done for us when we set the + // sequential navigation starting point with `location.replace` + reset_focus(url, !deep_linked); + } + + autoscroll = true; + + if (navigation_result.props.page) { + // Check for async rendering error + if (rendering_error) { + Object.assign(navigation_result.props.page, rendering_error); + } + Object.assign(page, navigation_result.props.page); + } + + is_navigating = false; + + if (type === 'popstate') { + restore_snapshot(current_navigation_index); + } + + nav.fulfil(undefined); + + // Update to.scroll to the actual scroll position after navigation completed + if (nav.navigation.to) { + nav.navigation.to.scroll = scroll_state(); + } + + after_navigate_callbacks.forEach((fn) => + fn(/** @type {import('@sveltejs/kit').AfterNavigate} */ (nav.navigation)) + ); + + stores.navigating.set((navigating.current = null)); + + updating = false; +} + +/** + * Does a full page reload if it wouldn't result in an endless loop in the SPA case + * @param {URL} url + * @param {{ id: string | null }} route + * @param {App.Error} error + * @param {number} status + * @param {boolean} [replace_state] + * @returns {Promise} + */ +async function server_fallback(url, route, error, status, replace_state) { + if (url.origin === origin && url.pathname === location.pathname && !hydrated) { + // We would reload the same page we're currently on, which isn't hydrated, + // which means no SSR, which means we would end up in an endless loop + return await load_root_error_page({ + status, + error, + url, + route + }); + } + + if (DEV && status !== 404) { + console.error( + 'An error occurred while loading the page. This will cause a full page reload. (This message will only appear during development.)' + ); + + debugger; // eslint-disable-line + } + + return await native_navigation(url, replace_state); +} + +if (import.meta.hot) { + import.meta.hot.on('vite:beforeUpdate', () => { + if (current.error) location.reload(); + }); +} + +/** @typedef {(typeof PRELOAD_PRIORITIES)['hover'] | (typeof PRELOAD_PRIORITIES)['tap']} PreloadDataPriority */ + +function setup_preload() { + /** @type {NodeJS.Timeout} */ + let mousemove_timeout; + /** @type {{ element: Element | SVGAElement | undefined; href: string | SVGAnimatedString | undefined }} */ + let current_a = { element: undefined, href: undefined }; + /** @type {PreloadDataPriority} */ + let current_priority; + + container.addEventListener('mousemove', (event) => { + const target = /** @type {Element} */ (event.target); + + clearTimeout(mousemove_timeout); + mousemove_timeout = setTimeout(() => { + void preload(target, PRELOAD_PRIORITIES.hover); + }, 20); + }); + + /** @param {Event} event */ + function tap(event) { + if (event.defaultPrevented) return; + void preload(/** @type {Element} */ (event.composedPath()[0]), PRELOAD_PRIORITIES.tap); + } + + container.addEventListener('mousedown', tap); + container.addEventListener('touchstart', tap, { passive: true }); + + const observer = new IntersectionObserver( + (entries) => { + for (const entry of entries) { + if (entry.isIntersecting) { + void _preload_code(new URL(/** @type {HTMLAnchorElement} */ (entry.target).href)); + observer.unobserve(entry.target); + } + } + }, + { threshold: 0 } + ); + + /** + * @param {Element} element + * @param {PreloadDataPriority} priority + */ + async function preload(element, priority) { + const a = find_anchor(element, container); + + // we don't want to preload data again if the user has already hovered/tapped + const interacted = + a === current_a.element && a?.href === current_a.href && priority >= current_priority; + if (!a || interacted) return; + + const { url, external, download } = get_link_info(a, base, app.hash); + if (external || download) return; + + const options = get_router_options(a); + + // we don't want to preload data for a page we're already on + const same_url = url && get_page_key(current.url) === get_page_key(url); + if (options.reload || same_url) return; + + if (priority <= options.preload_data) { + current_a = { element: a, href: a.href }; + // we don't want to preload data again on tap if we've already preloaded it on hover + current_priority = PRELOAD_PRIORITIES.tap; + + const intent = await get_navigation_intent(url, false); + if (!intent) return; + + if (DEV) { + void _preload_data(intent).then((result) => { + if (result.type === 'loaded' && result.state.error) { + console.warn( + `Preloading data for ${intent.url.pathname} failed with the following error: ${result.state.error.message}\n` + + 'If this error is transient, you can ignore it. Otherwise, consider disabling preloading for this route. ' + + 'This route was preloaded due to a data-sveltekit-preload-data attribute. ' + + 'See https://svelte.dev/docs/kit/link-options for more info' + ); + } + }); + } else { + void _preload_data(intent); + } + } else if (priority <= options.preload_code) { + current_a = { element: a, href: a.href }; + current_priority = priority; + void _preload_code(/** @type {URL} */ (url)); + } + } + + function after_navigate() { + observer.disconnect(); + + for (const a of container.querySelectorAll('a')) { + const { url, external, download } = get_link_info(a, base, app.hash); + if (external || download) continue; + + const options = get_router_options(a); + if (options.reload) continue; + + if (options.preload_code === PRELOAD_PRIORITIES.viewport) { + observer.observe(a); + } + + if (options.preload_code === PRELOAD_PRIORITIES.eager) { + void _preload_code(/** @type {URL} */ (url)); + } + } + } + + after_navigate_callbacks.add(after_navigate); + after_navigate(); +} + +/** + * @param {unknown} error + * @param {import('@sveltejs/kit').NavigationEvent} event + * @returns {import('types').MaybePromise} + */ +function handle_error(error, event) { + if (error instanceof HttpError) { + return error.body; + } + + if (DEV) { + errored = true; + console.warn('The next HMR update will cause the page to reload'); + } + + const status = get_status(error); + const message = get_message(error); + + return ( + app.hooks.handleError({ error, event, status, message }) ?? /** @type {any} */ ({ message }) + ); +} + +/** + * @template {Function} T + * @param {Set} callbacks + * @param {T} callback + */ +function add_navigation_callback(callbacks, callback) { + onMount(() => { + callbacks.add(callback); + + return () => { + callbacks.delete(callback); + }; + }); +} + +/** + * A lifecycle function that runs the supplied `callback` when the current component mounts, and also whenever we navigate to a URL. + * + * `afterNavigate` must be called during a component initialization. It remains active as long as the component is mounted. + * @param {(navigation: import('@sveltejs/kit').AfterNavigate) => void} callback + * @returns {void} + */ +export function afterNavigate(callback) { + add_navigation_callback(after_navigate_callbacks, callback); +} + +/** + * A navigation interceptor that triggers before we navigate to a URL, whether by clicking a link, calling `goto(...)`, or using the browser back/forward controls. + * + * Calling `cancel()` will prevent the navigation from completing. If `navigation.type === 'leave'` — meaning the user is navigating away from the app (or closing the tab) — calling `cancel` will trigger the native browser unload confirmation dialog. In this case, the navigation may or may not be cancelled depending on the user's response. + * + * When a navigation isn't to a SvelteKit-owned route (and therefore controlled by SvelteKit's client-side router), `navigation.to.route.id` will be `null`. + * + * If the navigation will (if not cancelled) cause the document to unload — in other words `'leave'` navigations and `'link'` navigations where `navigation.to.route === null` — `navigation.willUnload` is `true`. + * + * `beforeNavigate` must be called during a component initialization. It remains active as long as the component is mounted. + * @param {(navigation: import('@sveltejs/kit').BeforeNavigate) => void} callback + * @returns {void} + */ +export function beforeNavigate(callback) { + add_navigation_callback(before_navigate_callbacks, callback); +} + +/** + * A lifecycle function that runs the supplied `callback` immediately before we navigate to a new URL except during full-page navigations. + * + * If you return a `Promise`, SvelteKit will wait for it to resolve before completing the navigation. This allows you to — for example — use `document.startViewTransition`. Avoid promises that are slow to resolve, since navigation will appear stalled to the user. + * + * If a function (or a `Promise` that resolves to a function) is returned from the callback, it will be called once the DOM has updated. + * + * `onNavigate` must be called during a component initialization. It remains active as long as the component is mounted. + * @param {(navigation: import('@sveltejs/kit').OnNavigate) => import('types').MaybePromise<(() => void) | void>} callback + * @returns {void} + */ +export function onNavigate(callback) { + add_navigation_callback(on_navigate_callbacks, callback); +} + +/** + * If called when the page is being updated following a navigation (in `onMount` or `afterNavigate` or an action, for example), this disables SvelteKit's built-in scroll handling. + * This is generally discouraged, since it breaks user expectations. + * @returns {void} + */ +export function disableScrollHandling() { + if (!BROWSER) { + throw new Error('Cannot call disableScrollHandling() on the server'); + } + + if (DEV && started && !updating) { + throw new Error('Can only disable scroll handling during navigation'); + } + + if (updating || !started) { + autoscroll = false; + } +} + +/** + * Allows you to navigate programmatically to a given route, with options such as keeping the current element focused. + * Returns a Promise that resolves when SvelteKit navigates (or fails to navigate, in which case the promise rejects) to the specified `url`. + * + * For external URLs, use `window.location = url` instead of calling `goto(url)`. + * + * @param {string | URL} url Where to navigate to. Note that if you've set [`config.kit.paths.base`](https://svelte.dev/docs/kit/configuration#paths) and the URL is root-relative, you need to prepend the base path if you want to navigate within the app. + * @param {Object} [opts] Options related to the navigation + * @param {boolean} [opts.replaceState] If `true`, will replace the current `history` entry rather than creating a new one with `pushState` + * @param {boolean} [opts.noScroll] If `true`, the browser will maintain its scroll position rather than scrolling to the top of the page after navigation + * @param {boolean} [opts.keepFocus] If `true`, the currently focused element will retain focus after navigation. Otherwise, focus will be reset to the body + * @param {boolean} [opts.invalidateAll] If `true`, all `load` functions of the page will be rerun. See https://svelte.dev/docs/kit/load#rerunning-load-functions for more info on invalidation. + * @param {Array boolean)>} [opts.invalidate] Causes any load functions to re-run if they depend on one of the urls + * @param {App.PageState} [opts.state] An optional object that will be available as `page.state` + * @returns {Promise} + */ +export function goto(url, opts = {}) { + if (!BROWSER) { + throw new Error('Cannot call goto(...) on the server'); + } + + url = new URL(resolve_url(url)); + + if (url.origin !== origin) { + return Promise.reject( + new Error( + DEV + ? `Cannot use \`goto\` with an external URL. Use \`window.location = "${url}"\` instead` + : 'goto: invalid URL' + ) + ); + } + + return _goto(url, opts, 0); +} + +/** + * Causes any `load` functions belonging to the currently active page to re-run if they depend on the `url` in question, via `fetch` or `depends`. Returns a `Promise` that resolves when the page is subsequently updated. + * + * If the argument is given as a `string` or `URL`, it must resolve to the same URL that was passed to `fetch` or `depends` (including query parameters). + * To create a custom identifier, use a string beginning with `[a-z]+:` (e.g. `custom:state`) — this is a valid URL. + * + * The `function` argument can be used define a custom predicate. It receives the full `URL` and causes `load` to rerun if `true` is returned. + * This can be useful if you want to invalidate based on a pattern instead of a exact match. + * + * ```ts + * // Example: Match '/path' regardless of the query parameters + * import { invalidate } from '$app/navigation'; + * + * invalidate((url) => url.pathname === '/path'); + * ``` + * @param {string | URL | ((url: URL) => boolean)} resource The invalidated URL + * @returns {Promise} + */ +export function invalidate(resource) { + if (!BROWSER) { + throw new Error('Cannot call invalidate(...) on the server'); + } + + push_invalidated(resource); + + return _invalidate(); +} + +/** + * @param {string | URL | ((url: URL) => boolean)} resource The invalidated URL + */ +function push_invalidated(resource) { + if (typeof resource === 'function') { + invalidated.push(resource); + } else { + const { href } = new URL(resource, location.href); + invalidated.push((url) => url.href === href); + } +} + +/** + * Causes all `load` and `query` functions belonging to the currently active page to re-run. Returns a `Promise` that resolves when the page is subsequently updated. + * @returns {Promise} + */ +export function invalidateAll() { + if (!BROWSER) { + throw new Error('Cannot call invalidateAll() on the server'); + } + + force_invalidation = true; + return _invalidate(); +} + +/** + * Causes all currently active remote functions to refresh, and all `load` functions belonging to the currently active page to re-run (unless disabled via the option argument). + * Returns a `Promise` that resolves when the page is subsequently updated. + * @param {{ includeLoadFunctions?: boolean }} [options] + * @returns {Promise} + */ +export function refreshAll({ includeLoadFunctions = true } = {}) { + if (!BROWSER) { + throw new Error('Cannot call refreshAll() on the server'); + } + + remote_responses = {}; + + force_invalidation = true; + return _invalidate(includeLoadFunctions, false); +} + +/** + * Programmatically preloads the given page, which means + * 1. ensuring that the code for the page is loaded, and + * 2. calling the page's load function with the appropriate options. + * + * This is the same behaviour that SvelteKit triggers when the user taps or mouses over an `` element with `data-sveltekit-preload-data`. + * If the next navigation is to `href`, the values returned from load will be used, making navigation instantaneous. + * Returns a Promise that resolves with the result of running the new route's `load` functions once the preload is complete. + * + * @param {string} href Page to preload + * @returns {Promise<{ type: 'loaded'; status: number; data: Record } | { type: 'redirect'; location: string }>} + */ +export async function preloadData(href) { + if (!BROWSER) { + throw new Error('Cannot call preloadData(...) on the server'); + } + + const url = resolve_url(href); + const intent = await get_navigation_intent(url, false); + + if (!intent) { + throw new Error(`Attempted to preload a URL that does not belong to this app: ${url}`); + } + + const result = await _preload_data(intent); + if (result.type === 'redirect') { + return { + type: result.type, + location: result.location + }; + } + + const { status, data } = result.props.page ?? page; + return { type: result.type, status, data }; +} + +/** + * Programmatically imports the code for routes that haven't yet been fetched. + * Typically, you might call this to speed up subsequent navigation. + * + * You can specify routes by any matching pathname such as `/about` (to match `src/routes/about/+page.svelte`) or `/blog/*` (to match `src/routes/blog/[slug]/+page.svelte`). + * + * Unlike `preloadData`, this won't call `load` functions. + * Returns a Promise that resolves when the modules have been imported. + * + * @param {string} pathname + * @returns {Promise} + */ +export async function preloadCode(pathname) { + if (!BROWSER) { + throw new Error('Cannot call preloadCode(...) on the server'); + } + + const url = new URL(pathname, current.url); + + if (DEV) { + if (!pathname.startsWith('/')) { + throw new Error( + 'argument passed to preloadCode must be a pathname (i.e. "/about" rather than "http://example.com/about"' + ); + } + + if (!pathname.startsWith(base)) { + throw new Error( + `pathname passed to preloadCode must start with \`paths.base\` (i.e. "${base}${pathname}" rather than "${pathname}")` + ); + } + + if (__SVELTEKIT_CLIENT_ROUTING__) { + const rerouted = await get_rerouted_url(url); + if (!rerouted || !routes.find((route) => route.exec(get_url_path(rerouted)))) { + throw new Error(`'${pathname}' did not match any routes`); + } + } + } + + return _preload_code(url); +} + +/** + * Programmatically create a new history entry with the given `page.state`. To use the current URL, you can pass `''` as the first argument. Used for [shallow routing](https://svelte.dev/docs/kit/shallow-routing). + * + * @param {string | URL} url + * @param {App.PageState} state + * @returns {void} + */ +export function pushState(url, state) { + if (!BROWSER) { + throw new Error('Cannot call pushState(...) on the server'); + } + + if (DEV) { + if (!started) { + throw new Error('Cannot call pushState(...) before router is initialized'); + } + + try { + // use `devalue.stringify` as a convenient way to ensure we exclude values that can't be properly rehydrated, such as custom class instances + devalue.stringify(state); + } catch (error) { + // @ts-expect-error + throw new Error(`Could not serialize state${error.path}`, { cause: error }); + } + } + + update_scroll_positions(current_history_index); + + const opts = { + [HISTORY_INDEX]: (current_history_index += 1), + [NAVIGATION_INDEX]: current_navigation_index, + [PAGE_URL_KEY]: page.url.href, + [STATES_KEY]: state + }; + + history.pushState(opts, '', resolve_url(url)); + has_navigated = true; + + page.state = state; + root.$set({ + // we need to assign a new page object so that subscribers are correctly notified + page: untrack(() => clone_page(page)) + }); + + clear_onward_history(current_history_index, current_navigation_index); +} + +/** + * Programmatically replace the current history entry with the given `page.state`. To use the current URL, you can pass `''` as the first argument. Used for [shallow routing](https://svelte.dev/docs/kit/shallow-routing). + * + * @param {string | URL} url + * @param {App.PageState} state + * @returns {void} + */ +export function replaceState(url, state) { + if (!BROWSER) { + throw new Error('Cannot call replaceState(...) on the server'); + } + + if (DEV) { + if (!started) { + throw new Error('Cannot call replaceState(...) before router is initialized'); + } + + try { + // use `devalue.stringify` as a convenient way to ensure we exclude values that can't be properly rehydrated, such as custom class instances + devalue.stringify(state); + } catch (error) { + // @ts-expect-error + throw new Error(`Could not serialize state${error.path}`, { cause: error }); + } + } + + const opts = { + [HISTORY_INDEX]: current_history_index, + [NAVIGATION_INDEX]: current_navigation_index, + [PAGE_URL_KEY]: page.url.href, + [STATES_KEY]: state + }; + + history.replaceState(opts, '', resolve_url(url)); + + page.state = state; + root.$set({ + page: untrack(() => clone_page(page)) + }); +} + +/** + * This action updates the `form` property of the current page with the given data and updates `page.status`. + * In case of an error, it redirects to the nearest error page. + * @template {Record | undefined} Success + * @template {Record | undefined} Failure + * @param {import('@sveltejs/kit').ActionResult} result + * @returns {Promise} + */ +export async function applyAction(result) { + if (!BROWSER) { + throw new Error('Cannot call applyAction(...) on the server'); + } + + if (result.type === 'error') { + await set_nearest_error_page(result.error, result.status); + } else if (result.type === 'redirect') { + await _goto(result.location, { invalidateAll: true }, 0); + } else { + page.form = result.data; + page.status = result.status; + + /** @type {Record} */ + root.$set({ + // this brings Svelte's view of the world in line with SvelteKit's + // after use:enhance reset the form.... + form: null, + page: clone_page(page) + }); + + // ...so that setting the `form` prop takes effect and isn't ignored + await tick(); + root.$set({ form: result.data }); + + if (result.type === 'success') { + reset_focus(page.url); + } + } +} + +/** + * @param {App.Error} error + * @param {number} status + */ +export async function set_nearest_error_page(error, status = 500) { + const url = new URL(location.href); + + const { branch, route } = current; + if (!route) return; + + const error_load = await load_nearest_error_page(current.branch.length, branch, route.errors); + if (error_load) { + const navigation_result = await get_navigation_result_from_branch({ + url, + params: current.params, + branch: branch.slice(0, error_load.idx).concat(error_load.node), + status, + error, + // do not set errors, we haven't changed the page so the previous ones are still current + route + }); + + current = { ...navigation_result.state, nav: current.nav }; + + root.$set(navigation_result.props); + update(navigation_result.props.page); + + void tick().then(() => reset_focus(current.url)); + } +} + +function _start_router() { + history.scrollRestoration = 'manual'; + + // Adopted from Nuxt.js + // Reset scrollRestoration to auto when leaving page, allowing page reload + // and back-navigation from other pages to use the browser to restore the + // scrolling position. + addEventListener('beforeunload', (e) => { + let should_block = false; + + persist_state(); + + if (!is_navigating) { + const nav = create_navigation(current, undefined, null, 'leave'); + + // If we're navigating, beforeNavigate was already called. If we end up in here during navigation, + // it's due to an external or full-page-reload link, for which we don't want to call the hook again. + /** @type {import('@sveltejs/kit').BeforeNavigate} */ + const navigation = { + ...nav.navigation, + cancel: () => { + should_block = true; + nav.reject(new Error('navigation cancelled')); + } + }; + + before_navigate_callbacks.forEach((fn) => fn(navigation)); + } + + if (should_block) { + e.preventDefault(); + e.returnValue = ''; + } else { + history.scrollRestoration = 'auto'; + } + }); + + addEventListener('visibilitychange', () => { + if (document.visibilityState === 'hidden') { + persist_state(); + } + }); + + // @ts-expect-error this isn't supported everywhere yet + if (!navigator.connection?.saveData) { + setup_preload(); + } + + /** @param {MouseEvent} event */ + container.addEventListener('click', async (event) => { + // Adapted from https://github.com/visionmedia/page.js + // MIT license https://github.com/visionmedia/page.js#license + if (event.button || event.which !== 1) return; + if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; + if (event.defaultPrevented) return; + + const a = find_anchor(/** @type {Element} */ (event.composedPath()[0]), container); + if (!a) return; + + const { url, external, target, download } = get_link_info(a, base, app.hash); + if (!url) return; + + // bail out before `beforeNavigate` if link opens in a different tab + if (target === '_parent' || target === '_top') { + if (window.parent !== window) return; + } else if (target && target !== '_self') { + return; + } + + const options = get_router_options(a); + const is_svg_a_element = a instanceof SVGAElement; + + // Ignore URL protocols that differ to the current one and are not http(s) (e.g. `mailto:`, `tel:`, `myapp:`, etc.) + // This may be wrong when the protocol is x: and the link goes to y:.. which should be treated as an external + // navigation, but it's not clear how to handle that case and it's not likely to come up in practice. + // MEMO: Without this condition, firefox will open mailer twice. + // See: + // - https://github.com/sveltejs/kit/issues/4045 + // - https://github.com/sveltejs/kit/issues/5725 + // - https://github.com/sveltejs/kit/issues/6496 + if ( + !is_svg_a_element && + url.protocol !== location.protocol && + !(url.protocol === 'https:' || url.protocol === 'http:') + ) + return; + + if (download) return; + + const [nonhash, hash] = (app.hash ? url.hash.replace(/^#/, '') : url.href).split('#'); + const same_pathname = nonhash === strip_hash(location); + + // Ignore the following but fire beforeNavigate + if (external || (options.reload && (!same_pathname || !hash))) { + if (_before_navigate({ url, type: 'link', event })) { + // set `navigating` to `true` to prevent `beforeNavigate` callbacks + // being called when the page unloads + is_navigating = true; + } else { + event.preventDefault(); + } + + return; + } + + // Check if new url only differs by hash and use the browser default behavior in that case + // This will ensure the `hashchange` event is fired + // Removing the hash does a full page navigation in the browser, so make sure a hash is present + if (hash !== undefined && same_pathname) { + // If we are trying to navigate to the same hash, we should only + // attempt to scroll to that element and avoid any history changes. + // Otherwise, this can cause Firefox to incorrectly assign a null + // history state value without any signal that we can detect. + const [, current_hash] = current.url.href.split('#'); + if (current_hash === hash) { + event.preventDefault(); + + // We're already on /# and click on a link that goes to /#, or we're on + // /#top and click on a link that goes to /#top. In those cases just go to + // the top of the page, and avoid a history change. + if (hash === '' || (hash === 'top' && a.ownerDocument.getElementById('top') === null)) { + scrollTo({ top: 0 }); + } else { + const element = a.ownerDocument.getElementById(decodeURIComponent(hash)); + if (element) { + element.scrollIntoView(); + element.focus(); + } + } + + return; + } + // set this flag to distinguish between navigations triggered by + // clicking a hash link and those triggered by popstate + hash_navigating = true; + + update_scroll_positions(current_history_index); + + update_url(url); + + if (!options.replace_state) return; + + // hashchange event shouldn't occur if the router is replacing state. + hash_navigating = false; + } + + event.preventDefault(); + + // allow the browser to repaint before navigating — + // this prevents INP scores being penalised + await new Promise((fulfil) => { + requestAnimationFrame(() => { + setTimeout(fulfil, 0); + }); + + setTimeout(fulfil, 100); // fallback for edge case where rAF doesn't fire because e.g. tab was backgrounded + }); + + await navigate({ + type: 'link', + url, + keepfocus: options.keepfocus, + noscroll: options.noscroll, + replace_state: options.replace_state ?? url.href === location.href, + event + }); + }); + + container.addEventListener('submit', (event) => { + if (event.defaultPrevented) return; + + const form = /** @type {HTMLFormElement} */ ( + HTMLFormElement.prototype.cloneNode.call(event.target) + ); + + const submitter = /** @type {HTMLButtonElement | HTMLInputElement | null} */ (event.submitter); + + const target = submitter?.formTarget || form.target; + + if (target === '_blank') return; + + const method = submitter?.formMethod || form.method; + + if (method !== 'get') return; + + // It is impossible to use form actions with hash router, so we just ignore handling them here + const url = new URL( + (submitter?.hasAttribute('formaction') && submitter?.formAction) || form.action + ); + + if (is_external_url(url, base, false)) return; + + const event_form = /** @type {HTMLFormElement} */ (event.target); + + const options = get_router_options(event_form); + if (options.reload) return; + + event.preventDefault(); + event.stopPropagation(); + + const data = new FormData(event_form, submitter); + + // @ts-expect-error `URLSearchParams(fd)` is kosher, but typescript doesn't know that + url.search = new URLSearchParams(data).toString(); + + void navigate({ + type: 'form', + url, + keepfocus: options.keepfocus, + noscroll: options.noscroll, + replace_state: options.replace_state ?? url.href === location.href, + event + }); + }); + + addEventListener('popstate', async (event) => { + if (resetting_focus) return; + + if (event.state?.[HISTORY_INDEX]) { + const history_index = event.state[HISTORY_INDEX]; + token = {}; + + // if a popstate-driven navigation is cancelled, we need to counteract it + // with history.go, which means we end up back here, hence this check + if (history_index === current_history_index) return; + + const scroll = scroll_positions[history_index]; + const state = event.state[STATES_KEY] ?? {}; + const url = new URL(event.state[PAGE_URL_KEY] ?? location.href); + const navigation_index = event.state[NAVIGATION_INDEX]; + const is_hash_change = current.url ? strip_hash(location) === strip_hash(current.url) : false; + const shallow = + navigation_index === current_navigation_index && (has_navigated || is_hash_change); + + if (shallow) { + // We don't need to navigate, we just need to update scroll and/or state. + // This happens with hash links and `pushState`/`replaceState`. The + // exception is if we haven't navigated yet, since we could have + // got here after a modal navigation then a reload + if (state !== page.state) { + page.state = state; + } + + update_url(url); + + scroll_positions[current_history_index] = scroll_state(); + if (scroll) scrollTo(scroll.x, scroll.y); + + current_history_index = history_index; + return; + } + + const delta = history_index - current_history_index; + + await navigate({ + type: 'popstate', + url, + popped: { + state, + scroll, + delta + }, + accept: () => { + current_history_index = history_index; + current_navigation_index = navigation_index; + }, + block: () => { + history.go(-delta); + }, + nav_token: token, + event + }); + } else { + // since popstate event is also emitted when an anchor referencing the same + // document is clicked, we have to check that the router isn't already handling + // the navigation. otherwise we would be updating the page store twice. + if (!hash_navigating) { + const url = new URL(location.href); + update_url(url); + + // if the user edits the hash via the browser URL bar, trigger a full-page + // reload to align with pathname router behavior + if (app.hash) { + location.reload(); + } + } + } + }); + + addEventListener('hashchange', () => { + // if the hashchange happened as a result of clicking on a link, + // we need to update history, otherwise we have to leave it alone + if (hash_navigating) { + hash_navigating = false; + history.replaceState( + { + ...history.state, + [HISTORY_INDEX]: ++current_history_index, + [NAVIGATION_INDEX]: current_navigation_index + }, + '', + location.href + ); + } + }); + + // fix link[rel=icon], because browsers will occasionally try to load relative + // URLs after a pushState/replaceState, resulting in a 404 — see + // https://github.com/sveltejs/kit/issues/3748#issuecomment-1125980897 + for (const link of document.querySelectorAll('link')) { + if (ICON_REL_ATTRIBUTES.has(link.rel)) { + link.href = link.href; // eslint-disable-line + } + } + + addEventListener('pageshow', (event) => { + // If the user navigates to another site and then uses the back button and + // bfcache hits, we need to set navigating to null, the site doesn't know + // the navigation away from it was successful. + // Info about bfcache here: https://web.dev/bfcache + if (event.persisted) { + stores.navigating.set((navigating.current = null)); + } + }); + + /** + * @param {URL} url + */ + function update_url(url) { + current.url = page.url = url; + stores.page.set(clone_page(page)); + stores.page.notify(); + } +} + +/** + * @param {HTMLElement} target + * @param {import('./types.js').HydrateOptions} opts + */ +async function _hydrate( + target, + { status = 200, error, node_ids, params, route, server_route, data: server_data_nodes, form } +) { + hydrated = true; + + const url = new URL(location.href); + + /** @type {import('types').CSRRoute | undefined} */ + let parsed_route; + + if (__SVELTEKIT_CLIENT_ROUTING__) { + if (!__SVELTEKIT_EMBEDDED__) { + // See https://github.com/sveltejs/kit/pull/4935#issuecomment-1328093358 for one motivation + // of determining the params on the client side. + ({ params = {}, route = { id: null } } = (await get_navigation_intent(url, false)) || {}); + } + + parsed_route = routes.find(({ id }) => id === route.id); + } else { + // undefined in case of 404 + if (server_route) { + parsed_route = route = parse_server_route(server_route, app.nodes); + } else { + route = { id: null }; + params = {}; + } + } + + /** @type {import('./types.js').NavigationFinished | undefined} */ + let result; + let hydrate = true; + + try { + const branch_promises = node_ids.map(async (n, i) => { + const server_data_node = server_data_nodes[i]; + // Type isn't completely accurate, we still need to deserialize uses + if (server_data_node?.uses) { + server_data_node.uses = deserialize_uses(server_data_node.uses); + } + + return load_node({ + loader: app.nodes[n], + url, + params, + route, + parent: async () => { + const data = {}; + for (let j = 0; j < i; j += 1) { + Object.assign(data, (await branch_promises[j]).data); + } + return data; + }, + server_data_node: create_data_node(server_data_node) + }); + }); + + /** @type {Array} */ + const branch = await Promise.all(branch_promises); + + // server-side will have compacted the branch, reinstate empty slots + // so that error boundaries can be lined up correctly + if (parsed_route) { + const layouts = parsed_route.layouts; + for (let i = 0; i < layouts.length; i++) { + if (!layouts[i]) { + branch.splice(i, 0, undefined); + } + } + } + + result = await get_navigation_result_from_branch({ + url, + params, + branch, + status, + error, + errors: parsed_route?.errors, // TODO load earlier? + form, + route: parsed_route ?? null + }); + } catch (error) { + if (error instanceof Redirect) { + // this is a real edge case — `load` would need to return + // a redirect but only in the browser + await native_navigation(new URL(error.location, location.href)); + return; + } + + result = await load_root_error_page({ + status: get_status(error), + error: await handle_error(error, { url, params, route }), + url, + route + }); + + target.textContent = ''; + hydrate = false; + } + + if (result.props.page) { + result.props.page.state = {}; + } + + await initialize(result, target, hydrate); +} + +/** + * @param {URL} url + * @param {boolean[]} invalid + * @returns {Promise} + */ +async function load_data(url, invalid) { + const data_url = new URL(url); + data_url.pathname = add_data_suffix(url.pathname); + if (url.pathname.endsWith('/')) { + data_url.searchParams.append(TRAILING_SLASH_PARAM, '1'); + } + if (DEV && url.searchParams.has(INVALIDATED_PARAM)) { + throw new Error(`Cannot used reserved query parameter "${INVALIDATED_PARAM}"`); + } + data_url.searchParams.append(INVALIDATED_PARAM, invalid.map((i) => (i ? '1' : '0')).join('')); + + // use window.fetch directly to allow using a 3rd party-patched fetch implementation + const fetcher = DEV ? dev_fetch : window.fetch; + const res = await fetcher(data_url.href, {}); + + if (!res.ok) { + // error message is a JSON-stringified string which devalue can't handle at the top level + // turn it into a HttpError to not call handleError on the client again (was already handled on the server) + // if `__data.json` doesn't exist or the server has an internal error, + // avoid parsing the HTML error page as a JSON + /** @type {string | undefined} */ + let message; + if (res.headers.get('content-type')?.includes('application/json')) { + message = await res.json(); + } else if (res.status === 404) { + message = 'Not Found'; + } else if (res.status === 500) { + message = 'Internal Error'; + } + throw new HttpError(res.status, message); + } + + // TODO: fix eslint error / figure out if it actually applies to our situation + // eslint-disable-next-line + return new Promise(async (resolve) => { + /** + * Map of deferred promises that will be resolved by a subsequent chunk of data + * @type {Map} + */ + const deferreds = new Map(); + const reader = /** @type {ReadableStream} */ (res.body).getReader(); + + /** + * @param {any} data + */ + function deserialize(data) { + return devalue.unflatten(data, { + ...app.decoders, + Promise: (id) => { + return new Promise((fulfil, reject) => { + deferreds.set(id, { fulfil, reject }); + }); + } + }); + } + + let text = ''; + + while (true) { + // Format follows ndjson (each line is a JSON object) or regular JSON spec + const { done, value } = await reader.read(); + if (done && !text) break; + + text += !value && text ? '\n' : text_decoder.decode(value, { stream: true }); // no value -> final chunk -> add a new line to trigger the last parse + + while (true) { + const split = text.indexOf('\n'); + if (split === -1) { + break; + } + + const node = JSON.parse(text.slice(0, split)); + text = text.slice(split + 1); + + if (node.type === 'redirect') { + return resolve(node); + } + + if (node.type === 'data') { + // This is the first (and possibly only, if no pending promises) chunk + node.nodes?.forEach((/** @type {any} */ node) => { + if (node?.type === 'data') { + node.uses = deserialize_uses(node.uses); + node.data = deserialize(node.data); + } + }); + + resolve(node); + } else if (node.type === 'chunk') { + // This is a subsequent chunk containing deferred data + const { id, data, error } = node; + const deferred = /** @type {import('types').Deferred} */ (deferreds.get(id)); + deferreds.delete(id); + + if (error) { + deferred.reject(deserialize(error)); + } else { + deferred.fulfil(deserialize(data)); + } + } + } + } + }); + + // TODO edge case handling necessary? stream() read fails? +} + +/** + * @param {any} uses + * @return {import('types').Uses} + */ +function deserialize_uses(uses) { + return { + dependencies: new Set(uses?.dependencies ?? []), + params: new Set(uses?.params ?? []), + parent: !!uses?.parent, + route: !!uses?.route, + url: !!uses?.url, + search_params: new Set(uses?.search_params ?? []) + }; +} + +/** + * This flag is used to avoid client-side navigation when we're only using + * `location.replace()` to set focus. + */ +let resetting_focus = false; + +/** + * @param {URL} url + * @param {boolean} [scroll] + */ +function reset_focus(url, scroll = true) { + const autofocus = document.querySelector('[autofocus]'); + if (autofocus) { + // @ts-ignore + autofocus.focus(); + } else { + // Reset page selection and focus + + // Mimic the browsers' behaviour and set the sequential focus navigation + // starting point to the fragment identifier. + const id = get_id(url); + if (id && document.getElementById(id)) { + const { x, y } = scroll_state(); + + // `element.focus()` doesn't work on Safari and Firefox Ubuntu so we need + // to use this hack with `location.replace()` instead. + setTimeout(() => { + const history_state = history.state; + + resetting_focus = true; + location.replace(new URL(`#${id}`, location.href)); + + // Firefox has a bug that sets the history state to `null` so we need to + // restore it after. See https://bugzilla.mozilla.org/show_bug.cgi?id=1199924 + // This is also needed to restore the original hash if we're using hash routing + history.replaceState(history_state, '', url); + + // If scroll management has already happened earlier, we need to restore + // the scroll position after setting the sequential focus navigation starting point + if (scroll) scrollTo(x, y); + resetting_focus = false; + }); + } else { + // If the ID doesn't exist, we try to mimic browsers' behaviour as closely + // as possible by targeting the first scrollable region. Unfortunately, it's + // not a perfect match — e.g. shift-tabbing won't immediately cycle up from + // the end of the page on Chromium + // See https://html.spec.whatwg.org/multipage/interaction.html#get-the-focusable-area + const root = document.body; + const tabindex = root.getAttribute('tabindex'); + + root.tabIndex = -1; + // @ts-expect-error options.focusVisible is only supported in Firefox + // See https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#browser_compatibility + root.focus({ preventScroll: true, focusVisible: false }); + + // restore `tabindex` as to prevent `root` from stealing input from elements + if (tabindex !== null) { + root.setAttribute('tabindex', tabindex); + } else { + root.removeAttribute('tabindex'); + } + } + + // capture current selection, so we can compare the state after + // snapshot restoration and afterNavigate callbacks have run + const selection = getSelection(); + + if (selection && selection.type !== 'None') { + /** @type {Range[]} */ + const ranges = []; + + for (let i = 0; i < selection.rangeCount; i += 1) { + ranges.push(selection.getRangeAt(i)); + } + + setTimeout(() => { + if (selection.rangeCount !== ranges.length) return; + + for (let i = 0; i < selection.rangeCount; i += 1) { + const a = ranges[i]; + const b = selection.getRangeAt(i); + + // we need to do a deep comparison rather than just `a !== b` because + // Safari behaves differently to other browsers + if ( + a.commonAncestorContainer !== b.commonAncestorContainer || + a.startContainer !== b.startContainer || + a.endContainer !== b.endContainer || + a.startOffset !== b.startOffset || + a.endOffset !== b.endOffset + ) { + return; + } + } + + // if the selection hasn't changed (as a result of an element being (auto)focused, + // or a programmatic selection, we reset everything as part of the navigation) + // fixes https://github.com/sveltejs/kit/issues/8439 + selection.removeAllRanges(); + }); + } + } +} + +/** + * @template {import('@sveltejs/kit').NavigationType} T + * @param {import('./types.js').NavigationState} current + * @param {import('./types.js').NavigationIntent | undefined} intent + * @param {URL | null} url + * @param {T} type + * @param {{ x: number, y: number } | null} [target_scroll] The scroll position for the target (for popstate navigations) + */ +function create_navigation(current, intent, url, type, target_scroll = null) { + /** @type {(value: any) => void} */ + let fulfil; + + /** @type {(error: any) => void} */ + let reject; + + const complete = new Promise((f, r) => { + fulfil = f; + reject = r; + }); + + // Handle any errors off-chain so that it doesn't show up as an unhandled rejection + complete.catch(() => {}); + + /** @type {(import('@sveltejs/kit').Navigation | import('@sveltejs/kit').AfterNavigate) & { type: T }} */ + const navigation = /** @type {any} */ ({ + from: { + params: current.params, + route: { id: current.route?.id ?? null }, + url: current.url, + scroll: scroll_state() + }, + to: url && { + params: intent?.params ?? null, + route: { id: intent?.route?.id ?? null }, + url, + scroll: target_scroll + }, + willUnload: !intent, + type, + complete + }); + + return { + navigation, + // @ts-expect-error + fulfil, + // @ts-expect-error + reject + }; +} + +/** + * TODO: remove this in 3.0 when the page store is also removed + * + * We need to assign a new page object so that subscribers are correctly notified. + * However, spreading `{ ...page }` returns an empty object so we manually + * assign to each property instead. + * + * @param {import('@sveltejs/kit').Page} page + */ +function clone_page(page) { + return { + data: page.data, + error: page.error, + form: page.form, + params: page.params, + route: page.route, + state: page.state, + status: page.status, + url: page.url + }; +} + +/** + * @param {URL} url + * @returns {URL} + */ +function decode_hash(url) { + const new_url = new URL(url); + // Safari, for some reason, does change # to %23, when entered through the address bar + new_url.hash = decodeURIComponent(url.hash); + return new_url; +} + +/** + * @param {URL} url + * @returns {string} + */ +function get_id(url) { + let id; + + if (app.hash) { + const [, , second] = url.hash.split('#', 3); + id = second ?? ''; + } else { + id = url.hash.slice(1); + } + + return decodeURIComponent(id); +} + +if (DEV) { + // Nasty hack to silence harmless warnings the user can do nothing about + const console_warn = console.warn; + console.warn = function warn(...args) { + if ( + args.length === 1 && + /<(Layout|Page|Error)(_[\w$]+)?> was created (with unknown|without expected) prop '(data|form)'/.test( + args[0] + ) + ) { + return; + } + console_warn(...args); + }; + + if (import.meta.hot) { + import.meta.hot.on('vite:beforeUpdate', () => { + if (errored) { + location.reload(); + } + }); + } +} diff --git a/frontend/node_modules/@sveltejs/kit/src/runtime/client/constants.js b/frontend/node_modules/@sveltejs/kit/src/runtime/client/constants.js new file mode 100644 index 0000000..982c25d --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/runtime/client/constants.js @@ -0,0 +1,16 @@ +export const SNAPSHOT_KEY = 'sveltekit:snapshot'; +export const SCROLL_KEY = 'sveltekit:scroll'; +export const STATES_KEY = 'sveltekit:states'; +export const PAGE_URL_KEY = 'sveltekit:pageurl'; + +export const HISTORY_INDEX = 'sveltekit:history'; +export const NAVIGATION_INDEX = 'sveltekit:navigation'; + +export const PRELOAD_PRIORITIES = /** @type {const} */ ({ + tap: 1, + hover: 2, + viewport: 3, + eager: 4, + off: -1, + false: -1 +}); diff --git a/frontend/node_modules/@sveltejs/kit/src/runtime/client/entry.js b/frontend/node_modules/@sveltejs/kit/src/runtime/client/entry.js new file mode 100644 index 0000000..74b0fb2 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/runtime/client/entry.js @@ -0,0 +1,3 @@ +// we expose this as a separate entry point (rather than treating client.js as the entry point) +// so that everything other than `start`/`load_css` can be treeshaken +export { start, load_css } from './client.js'; diff --git a/frontend/node_modules/@sveltejs/kit/src/runtime/client/fetcher.js b/frontend/node_modules/@sveltejs/kit/src/runtime/client/fetcher.js new file mode 100644 index 0000000..ae0b4dd --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/runtime/client/fetcher.js @@ -0,0 +1,178 @@ +import { BROWSER, DEV } from 'esm-env'; +import { hash } from '../../utils/hash.js'; +import { base64_decode } from '../utils.js'; + +let loading = 0; + +/** @type {typeof fetch} */ +const native_fetch = BROWSER ? window.fetch : /** @type {any} */ (() => {}); + +export function lock_fetch() { + loading += 1; +} + +export function unlock_fetch() { + loading -= 1; +} + +if (DEV && BROWSER) { + let can_inspect_stack_trace = false; + + // detect whether async stack traces work + // eslint-disable-next-line @typescript-eslint/require-await + const check_stack_trace = async () => { + const stack = /** @type {string} */ (new Error().stack); + can_inspect_stack_trace = stack.includes('check_stack_trace'); + }; + + void check_stack_trace(); + + /** + * @param {RequestInfo | URL} input + * @param {RequestInit & Record | undefined} init + */ + window.fetch = (input, init) => { + // Check if fetch was called via load_node. the lock method only checks if it was called at the + // same time, but not necessarily if it was called from `load`. + // We use just the filename as the method name sometimes does not appear on the CI. + const url = input instanceof Request ? input.url : input.toString(); + const stack_array = /** @type {string} */ (new Error().stack).split('\n'); + // We need to do a cutoff because Safari and Firefox maintain the stack + // across events and for example traces a `fetch` call triggered from a button + // back to the creation of the event listener and the element creation itself, + // where at some point client.js will show up, leading to false positives. + const cutoff = stack_array.findIndex((a) => a.includes('load@') || a.includes('at load')); + const stack = stack_array.slice(0, cutoff + 2).join('\n'); + + const in_load_heuristic = can_inspect_stack_trace + ? stack.includes('src/runtime/client/client.js') + : loading; + + // This flag is set in initial_fetch and subsequent_fetch + const used_kit_fetch = init?.__sveltekit_fetch__; + + if (in_load_heuristic && !used_kit_fetch) { + console.warn( + `Loading ${url} using \`window.fetch\`. For best results, use the \`fetch\` that is passed to your \`load\` function: https://svelte.dev/docs/kit/load#making-fetch-requests` + ); + } + + const method = input instanceof Request ? input.method : init?.method || 'GET'; + + if (method !== 'GET') { + cache.delete(build_selector(input)); + } + + return native_fetch(input, init); + }; +} else if (BROWSER) { + window.fetch = (input, init) => { + const method = input instanceof Request ? input.method : init?.method || 'GET'; + + if (method !== 'GET') { + cache.delete(build_selector(input)); + } + + return native_fetch(input, init); + }; +} + +const cache = new Map(); + +/** + * Should be called on the initial run of load functions that hydrate the page. + * Saves any requests with cache-control max-age to the cache. + * @param {URL | string} resource + * @param {RequestInit} [opts] + */ +export function initial_fetch(resource, opts) { + const selector = build_selector(resource, opts); + + const script = document.querySelector(selector); + if (script?.textContent) { + script.remove(); // In case multiple script tags match the same selector + let { body, ...init } = JSON.parse(script.textContent); + + const ttl = script.getAttribute('data-ttl'); + if (ttl) cache.set(selector, { body, init, ttl: 1000 * Number(ttl) }); + const b64 = script.getAttribute('data-b64'); + if (b64 !== null) { + // Can't use native_fetch('data:...;base64,${body}') + // csp can block the request + body = base64_decode(body); + } + + return Promise.resolve(new Response(body, init)); + } + + return DEV ? dev_fetch(resource, opts) : window.fetch(resource, opts); +} + +/** + * Tries to get the response from the cache, if max-age allows it, else does a fetch. + * @param {URL | string} resource + * @param {string} resolved + * @param {RequestInit} [opts] + */ +export function subsequent_fetch(resource, resolved, opts) { + if (cache.size > 0) { + const selector = build_selector(resource, opts); + const cached = cache.get(selector); + if (cached) { + // https://developer.mozilla.org/en-US/docs/Web/API/Request/cache#value + if ( + performance.now() < cached.ttl && + ['default', 'force-cache', 'only-if-cached', undefined].includes(opts?.cache) + ) { + return new Response(cached.body, cached.init); + } + + cache.delete(selector); + } + } + + return DEV ? dev_fetch(resolved, opts) : window.fetch(resolved, opts); +} + +/** + * @param {RequestInfo | URL} resource + * @param {RequestInit & Record | undefined} opts + */ +export function dev_fetch(resource, opts) { + const patched_opts = { ...opts }; + // This assigns the __sveltekit_fetch__ flag and makes it non-enumerable + Object.defineProperty(patched_opts, '__sveltekit_fetch__', { + value: true, + writable: true, + configurable: true + }); + return window.fetch(resource, patched_opts); +} + +/** + * Build the cache key for a given request + * @param {URL | RequestInfo} resource + * @param {RequestInit} [opts] + */ +function build_selector(resource, opts) { + const url = JSON.stringify(resource instanceof Request ? resource.url : resource); + + let selector = `script[data-sveltekit-fetched][data-url=${url}]`; + + if (opts?.headers || opts?.body) { + /** @type {import('types').StrictBody[]} */ + const values = []; + + if (opts.headers) { + values.push([...new Headers(opts.headers)].join(',')); + } + + if (opts.body && (typeof opts.body === 'string' || ArrayBuffer.isView(opts.body))) { + values.push(opts.body); + } + + selector += `[data-hash="${hash(...values)}"]`; + } + + return selector; +} diff --git a/frontend/node_modules/@sveltejs/kit/src/runtime/client/parse.js b/frontend/node_modules/@sveltejs/kit/src/runtime/client/parse.js new file mode 100644 index 0000000..20445fc --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/runtime/client/parse.js @@ -0,0 +1,77 @@ +import { exec, parse_route_id } from '../../utils/routing.js'; + +/** + * @param {import('./types.js').SvelteKitApp} app + * @returns {import('types').CSRRoute[]} + */ +export function parse({ nodes, server_loads, dictionary, matchers }) { + const layouts_with_server_load = new Set(server_loads); + + return Object.entries(dictionary).map(([id, [leaf, layouts, errors]]) => { + const { pattern, params } = parse_route_id(id); + + /** @type {import('types').CSRRoute} */ + const route = { + id, + /** @param {string} path */ + exec: (path) => { + const match = pattern.exec(path); + if (match) return exec(match, params, matchers); + }, + errors: [1, ...(errors || [])].map((n) => nodes[n]), + layouts: [0, ...(layouts || [])].map(create_layout_loader), + leaf: create_leaf_loader(leaf) + }; + + // bit of a hack, but ensures that layout/error node lists are the same + // length, without which the wrong data will be applied if the route + // manifest looks like `[[a, b], [c,], d]` + route.errors.length = route.layouts.length = Math.max( + route.errors.length, + route.layouts.length + ); + + return route; + }); + + /** + * @param {number} id + * @returns {[boolean, import('types').CSRPageNodeLoader]} + */ + function create_leaf_loader(id) { + // whether or not the route uses the server data is + // encoded using the ones' complement, to save space + const uses_server_data = id < 0; + if (uses_server_data) id = ~id; + return [uses_server_data, nodes[id]]; + } + + /** + * @param {number | undefined} id + * @returns {[boolean, import('types').CSRPageNodeLoader] | undefined} + */ + function create_layout_loader(id) { + // whether or not the layout uses the server data is + // encoded in the layouts array, to save space + return id === undefined ? id : [layouts_with_server_load.has(id), nodes[id]]; + } +} + +/** + * @param {import('types').CSRRouteServer} input + * @param {import('types').CSRPageNodeLoader[]} app_nodes Will be modified if a new node is loaded that's not already in the array + * @returns {import('types').CSRRoute} + */ +export function parse_server_route({ nodes, id, leaf, layouts, errors }, app_nodes) { + return { + id, + exec: () => ({}), // dummy function; exec already happened on the server + // By writing to app_nodes only when a loader at that index is not already defined, + // we ensure that loaders have referential equality when they load the same node. + // Code elsewhere in client.js relies on this referential equality to determine + // if a loader is different and should therefore (re-)run. + errors: errors.map((n) => (n ? (app_nodes[n] ||= nodes[n]) : undefined)), + layouts: layouts.map((n) => (n ? [n[0], (app_nodes[n[1]] ||= nodes[n[1]])] : undefined)), + leaf: [leaf[0], (app_nodes[leaf[1]] ||= nodes[leaf[1]])] + }; +} diff --git a/frontend/node_modules/@sveltejs/kit/src/runtime/client/remote-functions/command.svelte.js b/frontend/node_modules/@sveltejs/kit/src/runtime/client/remote-functions/command.svelte.js new file mode 100644 index 0000000..5838f40 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/runtime/client/remote-functions/command.svelte.js @@ -0,0 +1,96 @@ +/** @import { RemoteCommand, RemoteQueryOverride } from '@sveltejs/kit' */ +/** @import { RemoteFunctionResponse } from 'types' */ +/** @import { Query } from './query.svelte.js' */ +import { app_dir, base } from '$app/paths/internal/client'; +import * as devalue from 'devalue'; +import { HttpError } from '@sveltejs/kit/internal'; +import { app } from '../client.js'; +import { stringify_remote_arg } from '../../shared.js'; +import { get_remote_request_headers, refresh_queries, release_overrides } from './shared.svelte.js'; + +/** + * Client-version of the `command` function from `$app/server`. + * @param {string} id + * @returns {RemoteCommand} + */ +export function command(id) { + /** @type {number} */ + let pending_count = $state(0); + + // Careful: This function MUST be synchronous (can't use the async keyword) because the return type has to be a promise with an updates() method. + // If we make it async, the return type will be a promise that resolves to a promise with an updates() method, which is not what we want. + /** @type {RemoteCommand} */ + const command_function = (arg) => { + /** @type {Array | RemoteQueryOverride>} */ + let updates = []; + + // Increment pending count when command starts + pending_count++; + + // Noone should call commands during rendering but belts and braces. + // Do this here, after await Svelte' reactivity context is gone. + const headers = { + 'Content-Type': 'application/json', + ...get_remote_request_headers() + }; + + /** @type {Promise & { updates: (...args: any[]) => any }} */ + const promise = (async () => { + try { + // Wait a tick to give room for the `updates` method to be called + await Promise.resolve(); + + const response = await fetch(`${base}/${app_dir}/remote/${id}`, { + method: 'POST', + body: JSON.stringify({ + payload: stringify_remote_arg(arg, app.hooks.transport), + refreshes: updates.map((u) => u._key) + }), + headers + }); + + if (!response.ok) { + release_overrides(updates); + // We only end up here in case of a network error or if the server has an internal error + // (which shouldn't happen because we handle errors on the server and always send a 200 response) + throw new Error('Failed to execute remote function'); + } + + const result = /** @type {RemoteFunctionResponse} */ (await response.json()); + if (result.type === 'redirect') { + release_overrides(updates); + throw new Error( + 'Redirects are not allowed in commands. Return a result instead and use goto on the client' + ); + } else if (result.type === 'error') { + release_overrides(updates); + throw new HttpError(result.status ?? 500, result.error); + } else { + if (result.refreshes) { + refresh_queries(result.refreshes, updates); + } + + return devalue.parse(result.result, app.decoders); + } + } finally { + // Decrement pending count when command completes + pending_count--; + } + })(); + + promise.updates = (/** @type {any} */ ...args) => { + updates = args; + // @ts-expect-error Don't allow updates to be called multiple times + delete promise.updates; + return promise; + }; + + return promise; + }; + + Object.defineProperty(command_function, 'pending', { + get: () => pending_count + }); + + return command_function; +} diff --git a/frontend/node_modules/@sveltejs/kit/src/runtime/client/remote-functions/form.svelte.js b/frontend/node_modules/@sveltejs/kit/src/runtime/client/remote-functions/form.svelte.js new file mode 100644 index 0000000..090fd27 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/src/runtime/client/remote-functions/form.svelte.js @@ -0,0 +1,650 @@ +/** @import { StandardSchemaV1 } from '@standard-schema/spec' */ +/** @import { RemoteFormInput, RemoteForm, RemoteQueryOverride } from '@sveltejs/kit' */ +/** @import { InternalRemoteFormIssue, RemoteFunctionResponse } from 'types' */ +/** @import { Query } from './query.svelte.js' */ +import { app_dir, base } from '$app/paths/internal/client'; +import * as devalue from 'devalue'; +import { DEV } from 'esm-env'; +import { HttpError } from '@sveltejs/kit/internal'; +import { app, remote_responses, _goto, set_nearest_error_page, invalidateAll } from '../client.js'; +import { tick } from 'svelte'; +import { refresh_queries, release_overrides } from './shared.svelte.js'; +import { createAttachmentKey } from 'svelte/attachments'; +import { + convert_formdata, + flatten_issues, + create_field_proxy, + deep_set, + set_nested_value, + throw_on_old_property_access, + build_path_string, + normalize_issue, + serialize_binary_form, + BINARY_FORM_CONTENT_TYPE +} from '../../form-utils.js'; + +/** + * Merge client issues into server issues. Server issues are persisted unless + * a client-issue exists for the same path, in which case the client-issue overrides it. + * @param {FormData} form_data + * @param {InternalRemoteFormIssue[]} current_issues + * @param {InternalRemoteFormIssue[]} client_issues + * @returns {InternalRemoteFormIssue[]} + */ +function merge_with_server_issues(form_data, current_issues, client_issues) { + const merged = [ + ...current_issues.filter( + (issue) => issue.server && !client_issues.some((i) => i.name === issue.name) + ), + ...client_issues + ]; + + const keys = Array.from(form_data.keys()); + + return merged.sort((a, b) => keys.indexOf(a.name) - keys.indexOf(b.name)); +} + +/** + * Client-version of the `form` function from `$app/server`. + * @template {RemoteFormInput} T + * @template U + * @param {string} id + * @returns {RemoteForm} + */ +export function form(id) { + /** @type {Map }>} */ + // eslint-disable-next-line svelte/prefer-svelte-reactivity -- we don't need reactivity for this + const instances = new Map(); + + /** @param {string | number | boolean} [key] */ + function create_instance(key) { + const action_id_without_key = id; + const action_id = id + (key != undefined ? `/${JSON.stringify(key)}` : ''); + const action = '?/remote=' + encodeURIComponent(action_id); + + /** + * @type {Record} + */ + let input = $state({}); + + /** @type {InternalRemoteFormIssue[]} */ + let raw_issues = $state.raw([]); + + const issues = $derived(flatten_issues(raw_issues)); + + /** @type {any} */ + let result = $state.raw(remote_responses[action_id]); + + /** @type {number} */ + let pending_count = $state(0); + + /** @type {StandardSchemaV1 | undefined} */ + let preflight_schema = undefined; + + /** @type {HTMLFormElement | null} */ + let element = null; + + /** @type {Record} */ + let touched = {}; + + let submitted = false; + + /** + * @param {FormData} form_data + * @returns {Record} + */ + function convert(form_data) { + const data = convert_formdata(form_data); + if (key !== undefined && !form_data.has('id')) { + data.id = key; + } + return data; + } + + /** + * @param {HTMLFormElement} form + * @param {FormData} form_data + * @param {Parameters['enhance']>[0]} callback + */ + async function handle_submit(form, form_data, callback) { + const data = convert(form_data); + + submitted = true; + + // Increment pending count immediately so that `pending` reflects + // the in-progress state during async preflight validation + pending_count++; + + const validated = await preflight_schema?.['~standard'].validate(data); + + if (validated?.issues) { + raw_issues = merge_with_server_issues( + form_data, + raw_issues, + validated.issues.map((issue) => normalize_issue(issue, false)) + ); + pending_count--; + return; + } + + // Preflight passed - clear stale client-side preflight issues + if (preflight_schema) { + raw_issues = raw_issues.filter((issue) => issue.server); + } + + // TODO 3.0 remove this warning + if (DEV) { + const error = () => { + throw new Error( + 'Remote form functions no longer get passed a FormData object. The payload is now a POJO. See https://kit.svelte.dev/docs/remote-functions#form for details.' + ); + }; + for (const key of [ + 'append', + 'delete', + 'entries', + 'forEach', + 'get', + 'getAll', + 'has', + 'keys', + 'set', + 'values' + ]) { + if (!(key in data)) { + Object.defineProperty(data, key, { get: error }); + } + } + } + + try { + await callback({ + form, + data, + submit: () => submit(form_data) + }); + } catch (e) { + const error = e instanceof HttpError ? e.body : { message: /** @type {any} */ (e).message }; + const status = e instanceof HttpError ? e.status : 500; + void set_nearest_error_page(error, status); + } + } + + /** + * @param {FormData} data + * @returns {Promise & { updates: (...args: any[]) => any }} + */ + function submit(data) { + // Store a reference to the current instance and increment the usage count for the duration + // of the request. This ensures that the instance is not deleted in case of an optimistic update + // (e.g. when deleting an item in a list) that fails and wants to surface an error to the user afterwards. + // If the instance would be deleted in the meantime, the error property would be assigned to the old, + // no-longer-visible instance, so it would never be shown to the user. + const entry = instances.get(key); + if (entry) { + entry.count++; + } + + /** @type {Array | RemoteQueryOverride>} */ + let updates = []; + + /** @type {Promise & { updates: (...args: any[]) => any }} */ + const promise = (async () => { + try { + await Promise.resolve(); + + const { blob } = serialize_binary_form(convert(data), { + remote_refreshes: updates.map((u) => u._key) + }); + + const response = await fetch(`${base}/${app_dir}/remote/${action_id_without_key}`, { + method: 'POST', + headers: { + 'Content-Type': BINARY_FORM_CONTENT_TYPE, + // Forms cannot be called during rendering, so it's save to use location here + 'x-sveltekit-pathname': location.pathname, + 'x-sveltekit-search': location.search + }, + body: blob + }); + + if (!response.ok) { + // We only end up here in case of a network error or if the server has an internal error + // (which shouldn't happen because we handle errors on the server and always send a 200 response) + throw new Error('Failed to execute remote function'); + } + + const form_result = /** @type { RemoteFunctionResponse} */ (await response.json()); + + // reset issues in case it's a redirect or error (but issues passed in that case) + raw_issues = []; + + if (form_result.type === 'result') { + ({ issues: raw_issues = [], result } = devalue.parse(form_result.result, app.decoders)); + + if (issues.$) { + release_overrides(updates); + } else { + if (form_result.refreshes) { + refresh_queries(form_result.refreshes, updates); + } else { + void invalidateAll(); + } + } + } else if (form_result.type === 'redirect') { + const refreshes = form_result.refreshes ?? ''; + const invalidateAll = !refreshes && updates.length === 0; + if (!invalidateAll) { + refresh_queries(refreshes, updates); + } + // Use internal version to allow redirects to external URLs + void _goto(form_result.location, { invalidateAll }, 0); + } else { + throw new HttpError(form_result.status ?? 500, form_result.error); + } + } catch (e) { + result = undefined; + release_overrides(updates); + throw e; + } finally { + // Decrement pending count when submission completes + pending_count--; + + void tick().then(() => { + if (entry) { + entry.count--; + if (entry.count === 0) { + instances.delete(key); + } + } + }); + } + })(); + + promise.updates = (...args) => { + updates = args; + return promise; + }; + + return promise; + } + + /** @type {RemoteForm} */ + const instance = {}; + + instance.method = 'POST'; + instance.action = action; + + /** @param {Parameters['enhance']>[0]} callback */ + const form_onsubmit = (callback) => { + /** @param {SubmitEvent} event */ + return async (event) => { + const form = /** @type {HTMLFormElement} */ (event.target); + const method = event.submitter?.hasAttribute('formmethod') + ? /** @type {HTMLButtonElement | HTMLInputElement} */ (event.submitter).formMethod + : clone(form).method; + + if (method !== 'post') return; + + // eslint-disable-next-line svelte/prefer-svelte-reactivity + const action = new URL( + // We can't do submitter.formAction directly because that property is always set + event.submitter?.hasAttribute('formaction') + ? /** @type {HTMLButtonElement | HTMLInputElement} */ (event.submitter).formAction + : clone(form).action + ); + + if (action.searchParams.get('/remote') !== action_id) { + return; + } + + const target = event.submitter?.hasAttribute('formtarget') + ? /** @type {HTMLButtonElement | HTMLInputElement} */ (event.submitter).formTarget + : clone(form).target; + + if (target === '_blank') { + return; + } + + event.preventDefault(); + + const form_data = new FormData(form, event.submitter); + + if (DEV) { + validate_form_data(form_data, clone(form).enctype); + } + + await handle_submit(form, form_data, callback); + }; + }; + + /** @param {(event: SubmitEvent) => void} onsubmit */ + function create_attachment(onsubmit) { + return (/** @type {HTMLFormElement} */ form) => { + if (element) { + let message = `A form object can only be attached to a single \`
\` element`; + if (DEV && !key) { + const name = id.split('/').pop(); + message += `. To create multiple instances, use \`${name}.for(key)\``; + } + + throw new Error(message); + } + + element = form; + + touched = {}; + + form.addEventListener('submit', onsubmit); + + /** @param {Event} e */ + const handle_input = (e) => { + // strictly speaking it can be an HTMLTextAreaElement or HTMLSelectElement + // but that makes the types unnecessarily awkward + const element = /** @type {HTMLInputElement} */ (e.target); + + let name = element.name; + if (!name) return; + + const is_array = name.endsWith('[]'); + if (is_array) name = name.slice(0, -2); + + const is_file = element.type === 'file'; + + touched[name] = true; + + if (is_array) { + let value; + + if (element.tagName === 'SELECT') { + value = Array.from( + element.querySelectorAll('option:checked'), + (e) => /** @type {HTMLOptionElement} */ (e).value + ); + } else { + const elements = /** @type {HTMLInputElement[]} */ ( + Array.from(form.querySelectorAll(`[name="${name}[]"]`)) + ); + + if (DEV) { + for (const e of elements) { + if ((e.type === 'file') !== is_file) { + throw new Error( + `Cannot mix and match file and non-file inputs under the same name ("${element.name}")` + ); + } + } + } + + value = is_file + ? elements.map((input) => Array.from(input.files ?? [])).flat() + : elements.map((element) => element.value); + if (element.type === 'checkbox') { + value = /** @type {string[]} */ (value.filter((_, i) => elements[i].checked)); + } + } + + set_nested_value(input, name, value); + } else if (is_file) { + if (DEV && element.multiple) { + throw new Error( + `Can only use the \`multiple\` attribute when \`name\` includes a \`[]\` suffix — consider changing "${name}" to "${name}[]"` + ); + } + + const file = /** @type {HTMLInputElement & { files: FileList }} */ (element).files[0]; + + if (file) { + set_nested_value(input, name, file); + } else { + // Remove the property by setting to undefined and clean up + const path_parts = name.split(/\.|\[|\]/).filter(Boolean); + let current = /** @type {any} */ (input); + for (let i = 0; i < path_parts.length - 1; i++) { + if (current[path_parts[i]] == null) return; + current = current[path_parts[i]]; + } + delete current[path_parts[path_parts.length - 1]]; + } + } else { + set_nested_value( + input, + name, + element.type === 'checkbox' && !element.checked ? null : element.value + ); + } + + name = name.replace(/^[nb]:/, ''); + + touched[name] = true; + }; + + form.addEventListener('input', handle_input); + + const handle_reset = async () => { + // need to wait a moment, because the `reset` event occurs before + // the inputs are actually updated (so that it can be cancelled) + await tick(); + + input = convert_formdata(new FormData(form)); + }; + + form.addEventListener('reset', handle_reset); + + return () => { + form.removeEventListener('submit', onsubmit); + form.removeEventListener('input', handle_input); + form.removeEventListener('reset', handle_reset); + element = null; + preflight_schema = undefined; + }; + }; + } + + instance[createAttachmentKey()] = create_attachment( + form_onsubmit(({ submit, form }) => + submit().then(() => { + if (!issues.$) { + form.reset(); + } + }) + ) + ); + + let validate_id = 0; + + // TODO 3.0 remove + if (DEV) { + throw_on_old_property_access(instance); + + Object.defineProperty(instance, 'buttonProps', { + get() { + throw new Error( + '`form.buttonProps` has been removed: Instead of ` + * ``` + */ + depends: (...deps: Array<`${string}:${string}`>) => void; + /** + * Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example: + * + * ```js + * /// file: src/routes/+page.server.js + * export async function load({ untrack, url }) { + * // Untrack url.pathname so that path changes don't trigger a rerun + * if (untrack(() => url.pathname === '/')) { + * return { message: 'Welcome!' }; + * } + * } + * ``` + */ + untrack: (fn: () => T) => T; + + /** + * Access to spans for tracing. If tracing is not enabled or the function is being run in the browser, these spans will do nothing. + * @since 2.31.0 + */ + tracing: { + /** Whether tracing is enabled. */ + enabled: boolean; + /** The root span for the request. This span is named `sveltekit.handle.root`. */ + root: Span; + /** The span associated with the current `load` function. */ + current: Span; + }; + } + + export interface NavigationEvent< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + RouteId extends AppRouteId | null = AppRouteId | null + > { + /** + * The parameters of the current page - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object + */ + params: Params; + /** + * Info about the current route + */ + route: { + /** + * The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]`. It is `null` when no route is matched. + */ + id: RouteId; + }; + /** + * The URL of the current page + */ + url: URL; + } + + /** + * Information about the target of a specific navigation. + */ + export interface NavigationTarget< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + RouteId extends AppRouteId | null = AppRouteId | null + > { + /** + * Parameters of the target page - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object. + * Is `null` if the target is not part of the SvelteKit app (could not be resolved to a route). + */ + params: Params | null; + /** + * Info about the target route + */ + route: { + /** + * The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]`. It is `null` when no route is matched. + */ + id: RouteId | null; + }; + /** + * The URL that is navigated to + */ + url: URL; + /** + * The scroll position associated with this navigation. + * + * For the `from` target, this is the scroll position at the moment of navigation. + * + * For the `to` target, this represents the scroll position that will be or was restored: + * - In `beforeNavigate` and `onNavigate`, this is only available for `popstate` navigations (back/forward button) + * and will be `null` for other navigation types, since the final scroll position isn't known + * ahead of time. + * - In `afterNavigate`, this is always the scroll position that was applied after the navigation + * completed. + */ + scroll: { x: number; y: number } | null; + } + + /** + * - `enter`: The app has hydrated/started + * - `form`: The user submitted a `` + * - `leave`: The app is being left either because the tab is being closed or a navigation to a different document is occurring + * - `link`: Navigation was triggered by a link click + * - `goto`: Navigation was triggered by a `goto(...)` call or a redirect + * - `popstate`: Navigation was triggered by back/forward navigation + */ + export type NavigationType = 'enter' | 'form' | 'leave' | 'link' | 'goto' | 'popstate'; + + export interface NavigationBase { + /** + * Where navigation was triggered from + */ + from: NavigationTarget | null; + /** + * Where navigation is going to/has gone to + */ + to: NavigationTarget | null; + /** + * Whether or not the navigation will result in the page being unloaded (i.e. not a client-side navigation). + */ + willUnload: boolean; + /** + * A promise that resolves once the navigation is complete, and rejects if the navigation + * fails or is aborted. In the case of a `willUnload` navigation, the promise will never resolve + */ + complete: Promise; + } + + export interface NavigationEnter extends NavigationBase { + /** + * The type of navigation: + * - `enter`: The app has hydrated/started + */ + type: 'enter'; + + /** + * In case of a history back/forward navigation, the number of steps to go back/forward + */ + delta?: undefined; + + /** + * Dispatched `Event` object when navigation occurred by `popstate` or `link`. + */ + event?: undefined; + } + + export type NavigationExternal = NavigationGoto | NavigationLeave; + + export interface NavigationGoto extends NavigationBase { + /** + * The type of navigation: + * - `goto`: Navigation was triggered by a `goto(...)` call or a redirect + */ + type: 'goto'; + + // TODO 3.0 remove this property, so that it only exists when type is 'popstate' + // (would possibly be a breaking change to do it prior to that) + /** + * In case of a history back/forward navigation, the number of steps to go back/forward + */ + delta?: undefined; + } + + export interface NavigationLeave extends NavigationBase { + /** + * The type of navigation: + * - `leave`: The app is being left either because the tab is being closed or a navigation to a different document is occurring + */ + type: 'leave'; + + // TODO 3.0 remove this property, so that it only exists when type is 'popstate' + // (would possibly be a breaking change to do it prior to that) + /** + * In case of a history back/forward navigation, the number of steps to go back/forward + */ + delta?: undefined; + } + + export interface NavigationFormSubmit extends NavigationBase { + /** + * The type of navigation: + * - `form`: The user submitted a `` + */ + type: 'form'; + + /** + * The `SubmitEvent` that caused the navigation + */ + event: SubmitEvent; + + // TODO 3.0 remove this property, so that it only exists when type is 'popstate' + // (would possibly be a breaking change to do it prior to that) + /** + * In case of a history back/forward navigation, the number of steps to go back/forward + */ + delta?: undefined; + } + + export interface NavigationPopState extends NavigationBase { + /** + * The type of navigation: + * - `popstate`: Navigation was triggered by back/forward navigation + */ + type: 'popstate'; + + /** + * In case of a history back/forward navigation, the number of steps to go back/forward + */ + delta: number; + + /** + * The `PopStateEvent` that caused the navigation + */ + event: PopStateEvent; + } + + export interface NavigationLink extends NavigationBase { + /** + * The type of navigation: + * - `link`: Navigation was triggered by a link click + */ + type: 'link'; + + /** + * The `PointerEvent` that caused the navigation + */ + event: PointerEvent; + + // TODO 3.0 remove this property, so that it only exists when type is 'popstate' + // (would possibly be a breaking change to do it prior to that) + /** + * In case of a history back/forward navigation, the number of steps to go back/forward + */ + delta?: undefined; + } + + export type Navigation = + | NavigationExternal + | NavigationFormSubmit + | NavigationPopState + | NavigationLink; + + /** + * The argument passed to [`beforeNavigate`](https://svelte.dev/docs/kit/$app-navigation#beforeNavigate) callbacks. + */ + export type BeforeNavigate = Navigation & { + /** + * Call this to prevent the navigation from starting. + */ + cancel: () => void; + }; + + /** + * The argument passed to [`onNavigate`](https://svelte.dev/docs/kit/$app-navigation#onNavigate) callbacks. + */ + export type OnNavigate = Navigation & { + type: Exclude; + /** + * Since `onNavigate` callbacks are called immediately before a client-side navigation, they will never be called with a navigation that unloads the page. + */ + willUnload: false; + }; + + /** + * The argument passed to [`afterNavigate`](https://svelte.dev/docs/kit/$app-navigation#afterNavigate) callbacks. + */ + export type AfterNavigate = (Navigation | NavigationEnter) & { + type: Exclude; + /** + * Since `afterNavigate` callbacks are called after a navigation completes, they will never be called with a navigation that unloads the page. + */ + willUnload: false; + }; + + /** + * The shape of the [`page`](https://svelte.dev/docs/kit/$app-state#page) reactive object and the [`$page`](https://svelte.dev/docs/kit/$app-stores) store. + */ + export interface Page< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + RouteId extends AppRouteId | null = AppRouteId | null + > { + /** + * The URL of the current page. + */ + url: URL & { pathname: ResolvedPathname }; + /** + * The parameters of the current page - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object. + */ + params: Params; + /** + * Info about the current route. + */ + route: { + /** + * The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]`. It is `null` when no route is matched. + */ + id: RouteId; + }; + /** + * HTTP status code of the current page. + */ + status: number; + /** + * The error object of the current page, if any. Filled from the `handleError` hooks. + */ + error: App.Error | null; + /** + * The merged result of all data from all `load` functions on the current page. You can type a common denominator through `App.PageData`. + */ + data: App.PageData & Record; + /** + * The page state, which can be manipulated using the [`pushState`](https://svelte.dev/docs/kit/$app-navigation#pushState) and [`replaceState`](https://svelte.dev/docs/kit/$app-navigation#replaceState) functions from `$app/navigation`. + */ + state: App.PageState; + /** + * Filled only after a form submission. See [form actions](https://svelte.dev/docs/kit/form-actions) for more info. + */ + form: any; + } + + /** + * The shape of a param matcher. See [matching](https://svelte.dev/docs/kit/advanced-routing#Matching) for more info. + */ + export type ParamMatcher = (param: string) => boolean; + + export interface RequestEvent< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + RouteId extends AppRouteId | null = AppRouteId | null + > { + /** + * Get or set cookies related to the current request + */ + cookies: Cookies; + /** + * `fetch` is equivalent to the [native `fetch` web API](https://developer.mozilla.org/en-US/docs/Web/API/fetch), with a few additional features: + * + * - It can be used to make credentialed requests on the server, as it inherits the `cookie` and `authorization` headers for the page request. + * - It can make relative requests on the server (ordinarily, `fetch` requires a URL with an origin when used in a server context). + * - Internal requests (e.g. for `+server.js` routes) go directly to the handler function when running on the server, without the overhead of an HTTP call. + * - During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the `text` and `json` methods of the `Response` object. Note that headers will _not_ be serialized, unless explicitly included via [`filterSerializedResponseHeaders`](https://svelte.dev/docs/kit/hooks#Server-hooks-handle) + * - During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request. + * + * You can learn more about making credentialed requests with cookies [here](https://svelte.dev/docs/kit/load#Cookies). + */ + fetch: typeof fetch; + /** + * The client's IP address, set by the adapter. + */ + getClientAddress: () => string; + /** + * Contains custom data that was added to the request within the [`server handle hook`](https://svelte.dev/docs/kit/hooks#Server-hooks-handle). + */ + locals: App.Locals; + /** + * The parameters of the current route - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object. + */ + params: Params; + /** + * Additional data made available through the adapter. + */ + platform: Readonly | undefined; + /** + * The original request object. + */ + request: Request; + /** + * Info about the current route. + */ + route: { + /** + * The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]`. It is `null` when no route is matched. + */ + id: RouteId; + }; + /** + * If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example: + * + * ```js + * /// file: src/routes/blog/+page.js + * export async function load({ fetch, setHeaders }) { + * const url = `https://cms.example.com/articles.json`; + * const response = await fetch(url); + * + * setHeaders({ + * age: response.headers.get('age'), + * 'cache-control': response.headers.get('cache-control') + * }); + * + * return response.json(); + * } + * ``` + * + * Setting the same header multiple times (even in separate `load` functions) is an error — you can only set a given header once. + * + * You cannot add a `set-cookie` header with `setHeaders` — use the [`cookies`](https://svelte.dev/docs/kit/@sveltejs-kit#Cookies) API instead. + */ + setHeaders: (headers: Record) => void; + /** + * The requested URL. + */ + url: URL; + /** + * `true` if the request comes from the client asking for `+page/layout.server.js` data. The `url` property will be stripped of the internal information + * related to the data request in this case. Use this property instead if the distinction is important to you. + */ + isDataRequest: boolean; + /** + * `true` for `+server.js` calls coming from SvelteKit without the overhead of actually making an HTTP request. This happens when you make same-origin `fetch` requests on the server. + */ + isSubRequest: boolean; + + /** + * Access to spans for tracing. If tracing is not enabled, these spans will do nothing. + * @since 2.31.0 + */ + tracing: { + /** Whether tracing is enabled. */ + enabled: boolean; + /** The root span for the request. This span is named `sveltekit.handle.root`. */ + root: Span; + /** The span associated with the current `handle` hook, `load` function, or form action. */ + current: Span; + }; + + /** + * `true` if the request comes from the client via a remote function. The `url` property will be stripped of the internal information + * related to the data request in this case. Use this property instead if the distinction is important to you. + */ + isRemoteRequest: boolean; + } + + /** + * A `(event: RequestEvent) => Response` function exported from a `+server.js` file that corresponds to an HTTP verb (`GET`, `PUT`, `PATCH`, etc) and handles requests with that method. + * + * It receives `Params` as the first generic argument, which you can skip by using [generated types](https://svelte.dev/docs/kit/types#Generated-types) instead. + */ + export type RequestHandler< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + RouteId extends AppRouteId | null = AppRouteId | null + > = (event: RequestEvent) => MaybePromise; + + export interface ResolveOptions { + /** + * Applies custom transforms to HTML. If `done` is true, it's the final chunk. Chunks are not guaranteed to be well-formed HTML + * (they could include an element's opening tag but not its closing tag, for example) + * but they will always be split at sensible boundaries such as `%sveltekit.head%` or layout/page components. + * @param input the html chunk and the info if this is the last chunk + */ + transformPageChunk?: (input: { html: string; done: boolean }) => MaybePromise; + /** + * Determines which headers should be included in serialized responses when a `load` function loads a resource with `fetch`. + * By default, none will be included. + * @param name header name + * @param value header value + */ + filterSerializedResponseHeaders?: (name: string, value: string) => boolean; + /** + * Determines what should be added to the `` tag to preload it. + * By default, `js` and `css` files will be preloaded. + * @param input the type of the file and its path + */ + preload?: (input: { type: 'font' | 'css' | 'js' | 'asset'; path: string }) => boolean; + } + + export interface RouteDefinition { + id: string; + api: { + methods: Array; + }; + page: { + methods: Array>; + }; + pattern: RegExp; + prerender: PrerenderOption; + segments: RouteSegment[]; + methods: Array; + config: Config; + } + + export class Server { + constructor(manifest: SSRManifest); + init(options: ServerInitOptions): Promise; + respond(request: Request, options: RequestOptions): Promise; + } + + export interface ServerInitOptions { + /** A map of environment variables. */ + env: Record; + /** A function that turns an asset filename into a `ReadableStream`. Required for the `read` export from `$app/server` to work. */ + read?: (file: string) => MaybePromise; + } + + export interface SSRManifest { + appDir: string; + appPath: string; + /** Static files from `kit.config.files.assets` and the service worker (if any). */ + assets: Set; + mimeTypes: Record; + + /** private fields */ + _: { + client: NonNullable; + nodes: SSRNodeLoader[]; + /** hashed filename -> import to that file */ + remotes: Record Promise>; + routes: SSRRoute[]; + prerendered_routes: Set; + matchers: () => Promise>; + /** A `[file]: size` map of all assets imported by server code. */ + server_assets: Record; + }; + } + + /** + * The generic form of `PageServerLoad` and `LayoutServerLoad`. You should import those from `./$types` (see [generated types](https://svelte.dev/docs/kit/types#Generated-types)) + * rather than using `ServerLoad` directly. + */ + export type ServerLoad< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + ParentData extends Record = Record, + OutputData extends Record | void = Record | void, + RouteId extends AppRouteId | null = AppRouteId | null + > = (event: ServerLoadEvent) => MaybePromise; + + export interface ServerLoadEvent< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + ParentData extends Record = Record, + RouteId extends AppRouteId | null = AppRouteId | null + > extends RequestEvent { + /** + * `await parent()` returns data from parent `+layout.server.js` `load` functions. + * + * Be careful not to introduce accidental waterfalls when using `await parent()`. If for example you only want to merge parent data into the returned output, call it _after_ fetching your other data. + */ + parent: () => Promise; + /** + * This function declares that the `load` function has a _dependency_ on one or more URLs or custom identifiers, which can subsequently be used with [`invalidate()`](https://svelte.dev/docs/kit/$app-navigation#invalidate) to cause `load` to rerun. + * + * Most of the time you won't need this, as `fetch` calls `depends` on your behalf — it's only necessary if you're using a custom API client that bypasses `fetch`. + * + * URLs can be absolute or relative to the page being loaded, and must be [encoded](https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding). + * + * Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the [URI specification](https://www.rfc-editor.org/rfc/rfc3986.html). + * + * The following example shows how to use `depends` to register a dependency on a custom identifier, which is `invalidate`d after a button click, making the `load` function rerun. + * + * ```js + * /// file: src/routes/+page.js + * let count = 0; + * export async function load({ depends }) { + * depends('increase:count'); + * + * return { count: count++ }; + * } + * ``` + * + * ```html + * /// file: src/routes/+page.svelte + * + * + *

{data.count}

+ * + * ``` + */ + depends: (...deps: string[]) => void; + /** + * Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example: + * + * ```js + * /// file: src/routes/+page.js + * export async function load({ untrack, url }) { + * // Untrack url.pathname so that path changes don't trigger a rerun + * if (untrack(() => url.pathname === '/')) { + * return { message: 'Welcome!' }; + * } + * } + * ``` + */ + untrack: (fn: () => T) => T; + + /** + * Access to spans for tracing. If tracing is not enabled, these spans will do nothing. + * @since 2.31.0 + */ + tracing: { + /** Whether tracing is enabled. */ + enabled: boolean; + /** The root span for the request. This span is named `sveltekit.handle.root`. */ + root: Span; + /** The span associated with the current server `load` function. */ + current: Span; + }; + } + + /** + * Shape of a form action method that is part of `export const actions = {...}` in `+page.server.js`. + * See [form actions](https://svelte.dev/docs/kit/form-actions) for more information. + */ + export type Action< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + OutputData extends Record | void = Record | void, + RouteId extends AppRouteId | null = AppRouteId | null + > = (event: RequestEvent) => MaybePromise; + + /** + * Shape of the `export const actions = {...}` object in `+page.server.js`. + * See [form actions](https://svelte.dev/docs/kit/form-actions) for more information. + */ + export type Actions< + Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>, + OutputData extends Record | void = Record | void, + RouteId extends AppRouteId | null = AppRouteId | null + > = Record>; + + /** + * When calling a form action via fetch, the response will be one of these shapes. + * ```svelte + * { + * return ({ result }) => { + * // result is of type ActionResult + * }; + * }} + * ``` + */ + export type ActionResult< + Success extends Record | undefined = Record, + Failure extends Record | undefined = Record + > = + | { type: 'success'; status: number; data?: Success } + | { type: 'failure'; status: number; data?: Failure } + | { type: 'redirect'; status: number; location: string } + | { type: 'error'; status?: number; error: any }; + + /** + * The object returned by the [`error`](https://svelte.dev/docs/kit/@sveltejs-kit#error) function. + */ + export interface HttpError { + /** The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses), in the range 400-599. */ + status: number; + /** The content of the error. */ + body: App.Error; + } + + /** + * The object returned by the [`redirect`](https://svelte.dev/docs/kit/@sveltejs-kit#redirect) function. + */ + export interface Redirect { + /** The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages), in the range 300-308. */ + status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308; + /** The location to redirect to. */ + location: string; + } + + export type SubmitFunction< + Success extends Record | undefined = Record, + Failure extends Record | undefined = Record + > = (input: { + action: URL; + formData: FormData; + formElement: HTMLFormElement; + controller: AbortController; + submitter: HTMLElement | null; + cancel: () => void; + }) => MaybePromise< + | void + | ((opts: { + formData: FormData; + formElement: HTMLFormElement; + action: URL; + result: ActionResult; + /** + * Call this to get the default behavior of a form submission response. + * @param options Set `reset: false` if you don't want the `` values to be reset after a successful submission. + * @param invalidateAll Set `invalidateAll: false` if you don't want the action to call `invalidateAll` after submission. + */ + update: (options?: { reset?: boolean; invalidateAll?: boolean }) => Promise; + }) => MaybePromise) + >; + + /** + * The type of `export const snapshot` exported from a page or layout component. + */ + export interface Snapshot { + capture: () => T; + restore: (snapshot: T) => void; + } + + // If T is unknown or has an index signature, the types below will recurse indefinitely and create giant unions that TS can't handle + type WillRecurseIndefinitely = unknown extends T ? true : string extends keyof T ? true : false; + + // Input type mappings for form fields + type InputTypeMap = { + text: string; + email: string; + password: string; + url: string; + tel: string; + search: string; + number: number; + range: number; + date: string; + 'datetime-local': string; + time: string; + month: string; + week: string; + color: string; + checkbox: boolean | string[]; + radio: string; + file: File; + hidden: string; + submit: string; + button: string; + reset: string; + image: string; + select: string; + 'select multiple': string[]; + 'file multiple': File[]; + }; + + // Valid input types for a given value type + export type RemoteFormFieldType = { + [K in keyof InputTypeMap]: T extends InputTypeMap[K] ? K : never; + }[keyof InputTypeMap]; + + // Input element properties based on type + type InputElementProps = T extends 'checkbox' | 'radio' + ? { + name: string; + type: T; + value?: string; + 'aria-invalid': boolean | 'false' | 'true' | undefined; + get checked(): boolean; + set checked(value: boolean); + } + : T extends 'file' + ? { + name: string; + type: 'file'; + 'aria-invalid': boolean | 'false' | 'true' | undefined; + get files(): FileList | null; + set files(v: FileList | null); + } + : T extends 'select' | 'select multiple' + ? { + name: string; + multiple: T extends 'select' ? false : true; + 'aria-invalid': boolean | 'false' | 'true' | undefined; + get value(): string | number; + set value(v: string | number); + } + : T extends 'text' + ? { + name: string; + 'aria-invalid': boolean | 'false' | 'true' | undefined; + get value(): string | number; + set value(v: string | number); + } + : { + name: string; + type: T; + 'aria-invalid': boolean | 'false' | 'true' | undefined; + get value(): string | number; + set value(v: string | number); + }; + + type RemoteFormFieldMethods = { + /** The values that will be submitted */ + value(): DeepPartial; + /** Set the values that will be submitted */ + set(input: DeepPartial): DeepPartial; + /** Validation issues, if any */ + issues(): RemoteFormIssue[] | undefined; + }; + + export type RemoteFormFieldValue = string | string[] | number | boolean | File | File[]; + + type AsArgs = Type extends 'checkbox' + ? Value extends string[] + ? [type: Type, value: Value[number] | (string & {})] + : [type: Type] + : Type extends 'radio' | 'submit' | 'hidden' + ? [type: Type, value: Value | (string & {})] + : [type: Type]; + + /** + * Form field accessor type that provides name(), value(), and issues() methods + */ + export type RemoteFormField = RemoteFormFieldMethods & { + /** + * Returns an object that can be spread onto an input element with the correct type attribute, + * aria-invalid attribute if the field is invalid, and appropriate value/checked property getters/setters. + * @example + * ```svelte + * + * + * + * ``` + */ + as>(...args: AsArgs): InputElementProps; + }; + + type RemoteFormFieldContainer = RemoteFormFieldMethods & { + /** Validation issues belonging to this or any of the fields that belong to it, if any */ + allIssues(): RemoteFormIssue[] | undefined; + }; + + type UnknownField = RemoteFormFieldMethods & { + /** Validation issues belonging to this or any of the fields that belong to it, if any */ + allIssues(): RemoteFormIssue[] | undefined; + /** + * Returns an object that can be spread onto an input element with the correct type attribute, + * aria-invalid attribute if the field is invalid, and appropriate value/checked property getters/setters. + * @example + * ```svelte + * + * + * + * ``` + */ + as>(...args: AsArgs): InputElementProps; + } & { + [key: string | number]: UnknownField; + }; + + type RemoteFormFieldsRoot = + IsAny extends true + ? RecursiveFormFields + : Input extends void + ? { + /** Validation issues, if any */ + issues(): RemoteFormIssue[] | undefined; + /** Validation issues belonging to this or any of the fields that belong to it, if any */ + allIssues(): RemoteFormIssue[] | undefined; + } + : RemoteFormFields; + + /** + * Recursive type to build form fields structure with proxy access + */ + export type RemoteFormFields = + WillRecurseIndefinitely extends true + ? RecursiveFormFields + : NonNullable extends string | number | boolean | File + ? RemoteFormField> + : T extends string[] | File[] + ? RemoteFormField & { [K in number]: RemoteFormField } + : T extends Array + ? RemoteFormFieldContainer & { + [K in number]: RemoteFormFields; + } + : RemoteFormFieldContainer & { + [K in keyof T]-?: RemoteFormFields; + }; + + // By breaking this out into its own type, we avoid the TS recursion depth limit + type RecursiveFormFields = RemoteFormFieldContainer & { + [key: string | number]: UnknownField; + }; + + type MaybeArray = T | T[]; + + export interface RemoteFormInput { + [key: string]: MaybeArray; + } + + export interface RemoteFormIssue { + message: string; + path: Array; + } + + // If the schema specifies `id` as a string or number, ensure that `for(...)` + // only accepts that type. Otherwise, accept `string | number` + type ExtractId = Input extends { id: infer Id } + ? Id extends string | number + ? Id + : string | number + : string | number; + + /** + * A function and proxy object used to imperatively create validation errors in form handlers. + * + * Access properties to create field-specific issues: `issue.fieldName('message')`. + * The type structure mirrors the input data structure for type-safe field access. + * Call `invalid(issue.foo(...), issue.nested.bar(...))` to throw a validation error. + */ + export type InvalidField = + WillRecurseIndefinitely extends true + ? Record + : NonNullable extends string | number | boolean | File + ? (message: string) => StandardSchemaV1.Issue + : NonNullable extends Array + ? { + [K in number]: InvalidField; + } & ((message: string) => StandardSchemaV1.Issue) + : NonNullable extends RemoteFormInput + ? { + [K in keyof T]-?: InvalidField; + } & ((message: string) => StandardSchemaV1.Issue) + : Record; + + /** + * A validation error thrown by `invalid`. + */ + export interface ValidationError { + /** The validation issues */ + issues: StandardSchemaV1.Issue[]; + } + + /** + * The return value of a remote `form` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#form) for full documentation. + */ + export type RemoteForm = { + /** Attachment that sets up an event handler that intercepts the form submission on the client to prevent a full page reload */ + [attachment: symbol]: (node: HTMLFormElement) => void; + method: 'POST'; + /** The URL to send the form to. */ + action: string; + /** Use the `enhance` method to influence what happens when the form is submitted. */ + enhance( + callback: (opts: { + form: HTMLFormElement; + data: Input; + submit: () => Promise & { + updates: (...queries: Array | RemoteQueryOverride>) => Promise; + }; + }) => void | Promise + ): { + method: 'POST'; + action: string; + [attachment: symbol]: (node: HTMLFormElement) => void; + }; + /** + * Create an instance of the form for the given `id`. + * The `id` is stringified and used for deduplication to potentially reuse existing instances. + * Useful when you have multiple forms that use the same remote form action, for example in a loop. + * ```svelte + * {#each todos as todo} + * {@const todoForm = updateTodo.for(todo.id)} + * + * {#if todoForm.result?.invalid}

Invalid data

{/if} + * ... + * + * {/each} + * ``` + */ + for(id: ExtractId): Omit, 'for'>; + /** Preflight checks */ + preflight(schema: StandardSchemaV1): RemoteForm; + /** Validate the form contents programmatically */ + validate(options?: { + /** Set this to `true` to also show validation issues of fields that haven't been touched yet. */ + includeUntouched?: boolean; + /** Set this to `true` to only run the `preflight` validation. */ + preflightOnly?: boolean; + }): Promise; + /** The result of the form submission */ + get result(): Output | undefined; + /** The number of pending submissions */ + get pending(): number; + /** Access form fields using object notation */ + fields: RemoteFormFieldsRoot; + }; + + /** + * The return value of a remote `command` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#command) for full documentation. + */ + export type RemoteCommand = { + (arg: undefined extends Input ? Input | void : Input): Promise> & { + updates(...queries: Array | RemoteQueryOverride>): Promise>; + }; + /** The number of pending command executions */ + get pending(): number; + }; + + export type RemoteResource = Promise> & { + /** The error in case the query fails. Most often this is a [`HttpError`](https://svelte.dev/docs/kit/@sveltejs-kit#HttpError) but it isn't guaranteed to be. */ + get error(): any; + /** `true` before the first result is available and during refreshes */ + get loading(): boolean; + } & ( + | { + /** The current value of the query. Undefined until `ready` is `true` */ + get current(): undefined; + ready: false; + } + | { + /** The current value of the query. Undefined until `ready` is `true` */ + get current(): Awaited; + ready: true; + } + ); + + export type RemoteQuery = RemoteResource & { + /** + * On the client, this function will update the value of the query without re-fetching it. + * + * On the server, this can be called in the context of a `command` or `form` and the specified data will accompany the action response back to the client. + * This prevents SvelteKit needing to refresh all queries on the page in a second server round-trip. + */ + set(value: T): void; + /** + * On the client, this function will re-fetch the query from the server. + * + * On the server, this can be called in the context of a `command` or `form` and the refreshed data will accompany the action response back to the client. + * This prevents SvelteKit needing to refresh all queries on the page in a second server round-trip. + */ + refresh(): Promise; + /** + * Temporarily override the value of a query. This is used with the `updates` method of a [command](https://svelte.dev/docs/kit/remote-functions#command-Updating-queries) or [enhanced form submission](https://svelte.dev/docs/kit/remote-functions#form-enhance) to provide optimistic updates. + * + * ```svelte + * + * + *
{ + * await submit().updates( + * todos.withOverride((todos) => [...todos, { text: data.get('text') }]) + * ); + * })}> + * + * + *
+ * ``` + */ + withOverride(update: (current: Awaited) => Awaited): RemoteQueryOverride; + }; + + export interface RemoteQueryOverride { + _key: string; + release(): void; + } + + /** + * The return value of a remote `prerender` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#prerender) for full documentation. + */ + export type RemotePrerenderFunction = ( + arg: undefined extends Input ? Input | void : Input + ) => RemoteResource; + + /** + * The return value of a remote `query` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#query) for full documentation. + */ + export type RemoteQueryFunction = ( + arg: undefined extends Input ? Input | void : Input + ) => RemoteQuery; + interface AdapterEntry { + /** + * A string that uniquely identifies an HTTP service (e.g. serverless function) and is used for deduplication. + * For example, `/foo/a-[b]` and `/foo/[c]` are different routes, but would both + * be represented in a Netlify _redirects file as `/foo/:param`, so they share an ID + */ + id: string; + + /** + * A function that compares the candidate route with the current route to determine + * if it should be grouped with the current route. + * + * Use cases: + * - Fallback pages: `/foo/[c]` is a fallback for `/foo/a-[b]`, and `/[...catchall]` is a fallback for all routes + * - Grouping routes that share a common `config`: `/foo` should be deployed to the edge, `/bar` and `/baz` should be deployed to a serverless function + */ + filter(route: RouteDefinition): boolean; + + /** + * A function that is invoked once the entry has been created. This is where you + * should write the function to the filesystem and generate redirect manifests. + */ + complete(entry: { generateManifest(opts: { relativePath: string }): string }): MaybePromise; + } + + // Based on https://github.com/josh-hemphill/csp-typed-directives/blob/latest/src/csp.types.ts + // + // MIT License + // + // Copyright (c) 2021-present, Joshua Hemphill + // Copyright (c) 2021, Tecnico Corporation + // + // Permission is hereby granted, free of charge, to any person obtaining a copy + // of this software and associated documentation files (the "Software"), to deal + // in the Software without restriction, including without limitation the rights + // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + // copies of the Software, and to permit persons to whom the Software is + // furnished to do so, subject to the following conditions: + // + // The above copyright notice and this permission notice shall be included in all + // copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + // SOFTWARE. + + namespace Csp { + type ActionSource = 'strict-dynamic' | 'report-sample'; + type BaseSource = + | 'self' + | 'unsafe-eval' + | 'unsafe-hashes' + | 'unsafe-inline' + | 'wasm-unsafe-eval' + | 'none'; + type CryptoSource = `${'nonce' | 'sha256' | 'sha384' | 'sha512'}-${string}`; + type FrameSource = HostSource | SchemeSource | 'self' | 'none'; + type HostNameScheme = `${string}.${string}` | 'localhost'; + type HostSource = `${HostProtocolSchemes}${HostNameScheme}${PortScheme}`; + type HostProtocolSchemes = `${string}://` | ''; + type HttpDelineator = '/' | '?' | '#' | '\\'; + type PortScheme = `:${number}` | '' | ':*'; + type SchemeSource = 'http:' | 'https:' | 'data:' | 'mediastream:' | 'blob:' | 'filesystem:'; + type Source = HostSource | SchemeSource | CryptoSource | BaseSource; + type Sources = Source[]; + } + + interface CspDirectives { + 'child-src'?: Csp.Sources; + 'default-src'?: Array; + 'frame-src'?: Csp.Sources; + 'worker-src'?: Csp.Sources; + 'connect-src'?: Csp.Sources; + 'font-src'?: Csp.Sources; + 'img-src'?: Csp.Sources; + 'manifest-src'?: Csp.Sources; + 'media-src'?: Csp.Sources; + 'object-src'?: Csp.Sources; + 'prefetch-src'?: Csp.Sources; + 'script-src'?: Array; + 'script-src-elem'?: Csp.Sources; + 'script-src-attr'?: Csp.Sources; + 'style-src'?: Array; + 'style-src-elem'?: Csp.Sources; + 'style-src-attr'?: Csp.Sources; + 'base-uri'?: Array; + sandbox?: Array< + | 'allow-downloads-without-user-activation' + | 'allow-forms' + | 'allow-modals' + | 'allow-orientation-lock' + | 'allow-pointer-lock' + | 'allow-popups' + | 'allow-popups-to-escape-sandbox' + | 'allow-presentation' + | 'allow-same-origin' + | 'allow-scripts' + | 'allow-storage-access-by-user-activation' + | 'allow-top-navigation' + | 'allow-top-navigation-by-user-activation' + >; + 'form-action'?: Array; + 'frame-ancestors'?: Array; + 'navigate-to'?: Array; + 'report-uri'?: string[]; + 'report-to'?: string[]; + + 'require-trusted-types-for'?: Array<'script'>; + 'trusted-types'?: Array<'none' | 'allow-duplicates' | '*' | string>; + 'upgrade-insecure-requests'?: boolean; + + /** @deprecated */ + 'require-sri-for'?: Array<'script' | 'style' | 'script style'>; + + /** @deprecated */ + 'block-all-mixed-content'?: boolean; + + /** @deprecated */ + 'plugin-types'?: Array<`${string}/${string}` | 'none'>; + + /** @deprecated */ + referrer?: Array< + | 'no-referrer' + | 'no-referrer-when-downgrade' + | 'origin' + | 'origin-when-cross-origin' + | 'same-origin' + | 'strict-origin' + | 'strict-origin-when-cross-origin' + | 'unsafe-url' + | 'none' + >; + } + + type HttpMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS'; + + interface Logger { + (msg: string): void; + success(msg: string): void; + error(msg: string): void; + warn(msg: string): void; + minor(msg: string): void; + info(msg: string): void; + } + + type MaybePromise = T | Promise; + + interface Prerendered { + /** + * A map of `path` to `{ file }` objects, where a path like `/foo` corresponds to `foo.html` and a path like `/bar/` corresponds to `bar/index.html`. + */ + pages: Map< + string, + { + /** The location of the .html file relative to the output directory */ + file: string; + } + >; + /** + * A map of `path` to `{ type }` objects. + */ + assets: Map< + string, + { + /** The MIME type of the asset */ + type: string; + } + >; + /** + * A map of redirects encountered during prerendering. + */ + redirects: Map< + string, + { + status: number; + location: string; + } + >; + /** An array of prerendered paths (without trailing slashes, regardless of the trailingSlash config) */ + paths: string[]; + } + + interface PrerenderHttpErrorHandler { + (details: { + status: number; + path: string; + referrer: string | null; + referenceType: 'linked' | 'fetched'; + message: string; + }): void; + } + + interface PrerenderMissingIdHandler { + (details: { path: string; id: string; referrers: string[]; message: string }): void; + } + + interface PrerenderEntryGeneratorMismatchHandler { + (details: { generatedFromId: string; entry: string; matchedId: string; message: string }): void; + } + + interface PrerenderUnseenRoutesHandler { + (details: { routes: string[]; message: string }): void; + } + + type PrerenderHttpErrorHandlerValue = 'fail' | 'warn' | 'ignore' | PrerenderHttpErrorHandler; + type PrerenderMissingIdHandlerValue = 'fail' | 'warn' | 'ignore' | PrerenderMissingIdHandler; + type PrerenderUnseenRoutesHandlerValue = + | 'fail' + | 'warn' + | 'ignore' + | PrerenderUnseenRoutesHandler; + type PrerenderEntryGeneratorMismatchHandlerValue = + | 'fail' + | 'warn' + | 'ignore' + | PrerenderEntryGeneratorMismatchHandler; + + export type PrerenderOption = boolean | 'auto'; + + interface RequestOptions { + getClientAddress(): string; + platform?: App.Platform; + } + + interface RouteSegment { + content: string; + dynamic: boolean; + rest: boolean; + } + + /** @default 'never' */ + type TrailingSlash = 'never' | 'always' | 'ignore'; + + type DeepPartial = T extends Record | unknown[] + ? { + [K in keyof T]?: T[K] extends Record | unknown[] + ? DeepPartial + : T[K]; + } + : T | undefined; + + type IsAny = 0 extends 1 & T ? true : false; + interface Asset { + file: string; + size: number; + type: string | null; + } + + interface BuildData { + app_dir: string; + app_path: string; + manifest_data: ManifestData; + out_dir: string; + service_worker: string | null; + client: { + /** Path to the client entry point. */ + start: string; + /** Path to the generated `app.js` file that contains the client manifest. Only set in case of `bundleStrategy === 'split'`. */ + app?: string; + /** JS files that the client entry point relies on. */ + imports: string[]; + /** + * JS files that represent the entry points of the layouts/pages. + * An entry is undefined if the layout/page has no component or universal file (i.e. only has a `.server.js` file). + * Only set in case of `router.resolution === 'server'`. + */ + nodes?: Array; + /** + * CSS files referenced in the entry points of the layouts/pages. + * An entry is undefined if the layout/page has no component or universal file (i.e. only has a `.server.js` file) or if has no CSS. + * Only set in case of `router.resolution === 'server'`. + */ + css?: Array; + /** + * Contains the client route manifest in a form suitable for the server which is used for server-side route resolution. + * Notably, it contains all routes, regardless of whether they are prerendered or not (those are missing in the optimized server route manifest). + * Only set in case of `router.resolution === 'server'`. + */ + routes?: SSRClientRoute[]; + stylesheets: string[]; + fonts: string[]; + uses_env_dynamic_public: boolean; + /** Only set in case of `bundleStrategy === 'inline'`. */ + inline?: { + script: string; + style: string | undefined; + }; + } | null; + server_manifest: import('vite').Manifest; + } + + interface ManifestData { + /** Static files from `kit.config.files.assets`. */ + assets: Asset[]; + hooks: { + client: string | null; + server: string | null; + universal: string | null; + }; + nodes: PageNode[]; + routes: RouteData[]; + matchers: Record; + } + + interface PageNode { + depth: number; + /** The `+page/layout.svelte`. */ + component?: string; // TODO supply default component if it's missing (bit of an edge case) + /** The `+page/layout.js/.ts`. */ + universal?: string; + /** The `+page/layout.server.js/ts`. */ + server?: string; + parent_id?: string; + parent?: PageNode; + /** Filled with the pages that reference this layout (if this is a layout). */ + child_pages?: PageNode[]; + /** The final page options for a node if it was statically analysable */ + page_options?: PageOptions | null; + } + + type RecursiveRequired = { + // Recursive implementation of TypeScript's Required utility type. + // Will recursively continue until it reaches a primitive or Function + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type + [K in keyof T]-?: Extract extends never // If it does not have a Function type + ? RecursiveRequired // recursively continue through. + : T[K]; // Use the exact type for everything else + }; + + interface RouteParam { + name: string; + matcher: string; + optional: boolean; + rest: boolean; + chained: boolean; + } + + /** + * Represents a route segment in the app. It can either be an intermediate node + * with only layout/error pages, or a leaf, at which point either `page` and `leaf` + * or `endpoint` is set. + */ + interface RouteData { + id: string; + parent: RouteData | null; + + segment: string; + pattern: RegExp; + params: RouteParam[]; + + layout: PageNode | null; + error: PageNode | null; + leaf: PageNode | null; + + page: { + layouts: Array; + errors: Array; + leaf: number; + } | null; + + endpoint: { + file: string; + /** The final page options for the endpoint if it was statically analysable */ + page_options: PageOptions | null; + } | null; + } + + interface SSRComponent { + default: { + render( + props: Record, + opts: { context: Map; csp?: { nonce?: string; hash?: boolean } } + ): { + html: string; + head: string; + css: { + code: string; + map: any; // TODO + }; + /** Until we require all Svelte versions that support hashes, this might not be defined */ + hashes?: { + script: Array<`sha256-${string}`>; + }; + }; + }; + } + + type SSRComponentLoader = () => Promise; + + interface UniversalNode { + /** Is `null` in case static analysis succeeds but the node is ssr=false */ + load?: Load; + prerender?: PrerenderOption; + ssr?: boolean; + csr?: boolean; + trailingSlash?: TrailingSlash; + config?: any; + entries?: PrerenderEntryGenerator; + } + + interface ServerNode { + load?: ServerLoad; + prerender?: PrerenderOption; + ssr?: boolean; + csr?: boolean; + trailingSlash?: TrailingSlash; + actions?: Actions; + config?: any; + entries?: PrerenderEntryGenerator; + } + + interface SSRNode { + /** index into the `nodes` array in the generated `client/app.js`. */ + index: number; + /** external JS files that are loaded on the client. `imports[0]` is the entry point (e.g. `client/nodes/0.js`) */ + imports: string[]; + /** external CSS files that are loaded on the client */ + stylesheets: string[]; + /** external font files that are loaded on the client */ + fonts: string[]; + + universal_id?: string; + server_id?: string; + + /** inlined styles */ + inline_styles?(): MaybePromise< + Record string)> + >; + /** Svelte component */ + component?: SSRComponentLoader; + /** +page.js or +layout.js */ + universal?: UniversalNode; + /** +page.server.js, +layout.server.js, or +server.js */ + server?: ServerNode; + } + + type SSRNodeLoader = () => Promise; + + interface PageNodeIndexes { + errors: Array; + layouts: Array; + leaf: number; + } + + type PrerenderEntryGenerator = () => MaybePromise>>; + + type SSREndpoint = Partial> & { + prerender?: PrerenderOption; + trailingSlash?: TrailingSlash; + config?: any; + entries?: PrerenderEntryGenerator; + fallback?: RequestHandler; + }; + + interface SSRRoute { + id: string; + pattern: RegExp; + params: RouteParam[]; + page: PageNodeIndexes | null; + endpoint: (() => Promise) | null; + endpoint_id?: string; + } + + interface SSRClientRoute { + id: string; + pattern: RegExp; + params: RouteParam[]; + errors: Array; + layouts: Array<[has_server_load: boolean, node_id: number] | undefined>; + leaf: [has_server_load: boolean, node_id: number]; + } + + type ValidatedConfig = Config & { + kit: ValidatedKitConfig; + extensions: string[]; + }; + + type ValidatedKitConfig = Omit, 'adapter'> & { + adapter?: Adapter; + }; + /** + * Throws an error with a HTTP status code and an optional message. + * When called during request handling, this will cause SvelteKit to + * return an error response without invoking `handleError`. + * Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it. + * @param status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599. + * @param body An object that conforms to the App.Error type. If a string is passed, it will be used as the message property. + * @throws {HttpError} This error instructs SvelteKit to initiate HTTP error handling. + * @throws {Error} If the provided status is invalid (not between 400 and 599). + */ + export function error(status: number, body: App.Error): never; + /** + * Throws an error with a HTTP status code and an optional message. + * When called during request handling, this will cause SvelteKit to + * return an error response without invoking `handleError`. + * Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it. + * @param status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599. + * @param body An object that conforms to the App.Error type. If a string is passed, it will be used as the message property. + * @throws {HttpError} This error instructs SvelteKit to initiate HTTP error handling. + * @throws {Error} If the provided status is invalid (not between 400 and 599). + */ + export function error(status: number, body?: { + message: string; + } extends App.Error ? App.Error | string | undefined : never): never; + /** + * Checks whether this is an error thrown by {@link error}. + * @param status The status to filter for. + * */ + export function isHttpError(e: unknown, status?: T): e is (HttpError_1 & { + status: T extends undefined ? never : T; + }); + /** + * Redirect a request. When called during request handling, SvelteKit will return a redirect response. + * Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it. + * + * Most common status codes: + * * `303 See Other`: redirect as a GET request (often used after a form POST request) + * * `307 Temporary Redirect`: redirect will keep the request method + * * `308 Permanent Redirect`: redirect will keep the request method, SEO will be transferred to the new page + * + * [See all redirect status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages) + * + * @param status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308. + * @param location The location to redirect to. + * @throws {Redirect} This error instructs SvelteKit to redirect to the specified location. + * @throws {Error} If the provided status is invalid. + * */ + export function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never; + /** + * Checks whether this is a redirect thrown by {@link redirect}. + * @param e The object to check. + * */ + export function isRedirect(e: unknown): e is Redirect_1; + /** + * Create a JSON `Response` object from the supplied data. + * @param data The value that will be serialized as JSON. + * @param init Options such as `status` and `headers` that will be added to the response. `Content-Type: application/json` and `Content-Length` headers will be added automatically. + */ + export function json(data: any, init?: ResponseInit): Response; + /** + * Create a `Response` object from the supplied body. + * @param body The value that will be used as-is. + * @param init Options such as `status` and `headers` that will be added to the response. A `Content-Length` header will be added automatically. + */ + export function text(body: string, init?: ResponseInit): Response; + /** + * Create an `ActionFailure` object. Call when form submission fails. + * @param status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599. + * */ + export function fail(status: number): ActionFailure; + /** + * Create an `ActionFailure` object. Call when form submission fails. + * @param status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599. + * @param data Data associated with the failure (e.g. validation errors) + * */ + export function fail(status: number, data: T): ActionFailure; + /** + * Checks whether this is an action failure thrown by {@link fail}. + * @param e The object to check. + * */ + export function isActionFailure(e: unknown): e is ActionFailure; + /** + * Use this to throw a validation error to imperatively fail form validation. + * Can be used in combination with `issue` passed to form actions to create field-specific issues. + * + * @example + * ```ts + * import { invalid } from '@sveltejs/kit'; + * import { form } from '$app/server'; + * import { tryLogin } from '$lib/server/auth'; + * import * as v from 'valibot'; + * + * export const login = form( + * v.object({ name: v.string(), _password: v.string() }), + * async ({ name, _password }) => { + * const success = tryLogin(name, _password); + * if (!success) { + * invalid('Incorrect username or password'); + * } + * + * // ... + * } + * ); + * ``` + * @since 2.47.3 + */ + export function invalid(...issues: (StandardSchemaV1.Issue | string)[]): never; + /** + * Checks whether this is an validation error thrown by {@link invalid}. + * @param e The object to check. + * @since 2.47.3 + */ + export function isValidationError(e: unknown): e is ActionFailure; + /** + * Strips possible SvelteKit-internal suffixes and trailing slashes from the URL pathname. + * Returns the normalized URL as well as a method for adding the potential suffix back + * based on a new pathname (possibly including search) or URL. + * ```js + * import { normalizeUrl } from '@sveltejs/kit'; + * + * const { url, denormalize } = normalizeUrl('/blog/post/__data.json'); + * console.log(url.pathname); // /blog/post + * console.log(denormalize('/blog/post/a')); // /blog/post/a/__data.json + * ``` + * @since 2.18.0 + */ + export function normalizeUrl(url: URL | string): { + url: URL; + wasNormalized: boolean; + denormalize: (url?: string | URL) => URL; + }; + export type LessThan = TNumber extends TArray["length"] ? TArray[number] : LessThan; + export type NumericRange = Exclude, LessThan>; + type ValidPageOption = (typeof valid_page_options_array)[number]; + type PageOptions = Partial>; + const valid_page_options_array: readonly ["ssr", "prerender", "csr", "trailingSlash", "config", "entries", "load"]; + export const VERSION: string; + class HttpError_1 { + + constructor(status: number, body: { + message: string; + } extends App.Error ? (App.Error | string | undefined) : App.Error); + status: number; + body: App.Error; + toString(): string; + } + class Redirect_1 { + + constructor(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308, location: string); + status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308; + location: string; + } + + export {}; +} + +declare module '@sveltejs/kit/hooks' { + import type { Handle } from '@sveltejs/kit'; + /** + * A helper function for sequencing multiple `handle` calls in a middleware-like manner. + * The behavior for the `handle` options is as follows: + * - `transformPageChunk` is applied in reverse order and merged + * - `preload` is applied in forward order, the first option "wins" and no `preload` options after it are called + * - `filterSerializedResponseHeaders` behaves the same as `preload` + * + * ```js + * /// file: src/hooks.server.js + * import { sequence } from '@sveltejs/kit/hooks'; + * + * /// type: import('@sveltejs/kit').Handle + * async function first({ event, resolve }) { + * console.log('first pre-processing'); + * const result = await resolve(event, { + * transformPageChunk: ({ html }) => { + * // transforms are applied in reverse order + * console.log('first transform'); + * return html; + * }, + * preload: () => { + * // this one wins as it's the first defined in the chain + * console.log('first preload'); + * return true; + * } + * }); + * console.log('first post-processing'); + * return result; + * } + * + * /// type: import('@sveltejs/kit').Handle + * async function second({ event, resolve }) { + * console.log('second pre-processing'); + * const result = await resolve(event, { + * transformPageChunk: ({ html }) => { + * console.log('second transform'); + * return html; + * }, + * preload: () => { + * console.log('second preload'); + * return true; + * }, + * filterSerializedResponseHeaders: () => { + * // this one wins as it's the first defined in the chain + * console.log('second filterSerializedResponseHeaders'); + * return true; + * } + * }); + * console.log('second post-processing'); + * return result; + * } + * + * export const handle = sequence(first, second); + * ``` + * + * The example above would print: + * + * ``` + * first pre-processing + * first preload + * second pre-processing + * second filterSerializedResponseHeaders + * second transform + * first transform + * second post-processing + * first post-processing + * ``` + * + * @param handlers The chain of `handle` functions + * */ + export function sequence(...handlers: Handle[]): Handle; + + export {}; +} + +declare module '@sveltejs/kit/node' { + export function getRequest({ request, base, bodySizeLimit }: { + request: import("http").IncomingMessage; + base: string; + bodySizeLimit?: number; + }): Promise; + + export function setResponse(res: import("http").ServerResponse, response: Response): Promise; + /** + * Converts a file on disk to a readable stream + * @since 2.4.0 + */ + export function createReadableStream(file: string): ReadableStream; + + export {}; +} + +declare module '@sveltejs/kit/node/polyfills' { + /** + * Make various web APIs available as globals: + * - `crypto` + * - `File` + */ + export function installPolyfills(): void; + + export {}; +} + +declare module '@sveltejs/kit/vite' { + /** + * Returns the SvelteKit Vite plugins. + * */ + export function sveltekit(): Promise; + + export {}; +} + +declare module '$app/environment' { + /** + * `true` if the app is running in the browser. + */ + export const browser: boolean; + + /** + * Whether the dev server is running. This is not guaranteed to correspond to `NODE_ENV` or `MODE`. + */ + export const dev: boolean; + + /** + * SvelteKit analyses your app during the `build` step by running it. During this process, `building` is `true`. This also applies during prerendering. + */ + export const building: boolean; + + /** + * The value of `config.kit.version.name`. + */ + export const version: string; + + export {}; +} + +declare module '$app/forms' { + /** + * Use this function to deserialize the response from a form submission. + * Usage: + * + * ```js + * import { deserialize } from '$app/forms'; + * + * async function handleSubmit(event) { + * const response = await fetch('/form?/action', { + * method: 'POST', + * body: new FormData(event.target) + * }); + * + * const result = deserialize(await response.text()); + * // ... + * } + * ``` + * */ + export function deserialize | undefined, Failure extends Record | undefined>(result: string): import("@sveltejs/kit").ActionResult; + /** + * This action enhances a `
` element that otherwise would work without JavaScript. + * + * The `submit` function is called upon submission with the given FormData and the `action` that should be triggered. + * If `cancel` is called, the form will not be submitted. + * You can use the abort `controller` to cancel the submission in case another one starts. + * If a function is returned, that function is called with the response from the server. + * If nothing is returned, the fallback will be used. + * + * If this function or its return value isn't set, it + * - falls back to updating the `form` prop with the returned data if the action is on the same page as the form + * - updates `page.status` + * - resets the `` element and invalidates all data in case of successful submission with no redirect response + * - redirects in case of a redirect response + * - redirects to the nearest error page in case of an unexpected error + * + * If you provide a custom function with a callback and want to use the default behavior, invoke `update` in your callback. + * It accepts an options object + * - `reset: false` if you don't want the `` values to be reset after a successful submission + * - `invalidateAll: false` if you don't want the action to call `invalidateAll` after submission + * @param form_element The form element + * @param submit Submit callback + */ + export function enhance | undefined, Failure extends Record | undefined>(form_element: HTMLFormElement, submit?: import("@sveltejs/kit").SubmitFunction): { + destroy(): void; + }; + /** + * This action updates the `form` property of the current page with the given data and updates `page.status`. + * In case of an error, it redirects to the nearest error page. + * */ + export function applyAction | undefined, Failure extends Record | undefined>(result: import("@sveltejs/kit").ActionResult): Promise; + + export {}; +} + +declare module '$app/navigation' { + /** + * A lifecycle function that runs the supplied `callback` when the current component mounts, and also whenever we navigate to a URL. + * + * `afterNavigate` must be called during a component initialization. It remains active as long as the component is mounted. + * */ + export function afterNavigate(callback: (navigation: import("@sveltejs/kit").AfterNavigate) => void): void; + /** + * A navigation interceptor that triggers before we navigate to a URL, whether by clicking a link, calling `goto(...)`, or using the browser back/forward controls. + * + * Calling `cancel()` will prevent the navigation from completing. If `navigation.type === 'leave'` — meaning the user is navigating away from the app (or closing the tab) — calling `cancel` will trigger the native browser unload confirmation dialog. In this case, the navigation may or may not be cancelled depending on the user's response. + * + * When a navigation isn't to a SvelteKit-owned route (and therefore controlled by SvelteKit's client-side router), `navigation.to.route.id` will be `null`. + * + * If the navigation will (if not cancelled) cause the document to unload — in other words `'leave'` navigations and `'link'` navigations where `navigation.to.route === null` — `navigation.willUnload` is `true`. + * + * `beforeNavigate` must be called during a component initialization. It remains active as long as the component is mounted. + * */ + export function beforeNavigate(callback: (navigation: import("@sveltejs/kit").BeforeNavigate) => void): void; + /** + * A lifecycle function that runs the supplied `callback` immediately before we navigate to a new URL except during full-page navigations. + * + * If you return a `Promise`, SvelteKit will wait for it to resolve before completing the navigation. This allows you to — for example — use `document.startViewTransition`. Avoid promises that are slow to resolve, since navigation will appear stalled to the user. + * + * If a function (or a `Promise` that resolves to a function) is returned from the callback, it will be called once the DOM has updated. + * + * `onNavigate` must be called during a component initialization. It remains active as long as the component is mounted. + * */ + export function onNavigate(callback: (navigation: import("@sveltejs/kit").OnNavigate) => MaybePromise<(() => void) | void>): void; + /** + * If called when the page is being updated following a navigation (in `onMount` or `afterNavigate` or an action, for example), this disables SvelteKit's built-in scroll handling. + * This is generally discouraged, since it breaks user expectations. + * */ + export function disableScrollHandling(): void; + /** + * Allows you to navigate programmatically to a given route, with options such as keeping the current element focused. + * Returns a Promise that resolves when SvelteKit navigates (or fails to navigate, in which case the promise rejects) to the specified `url`. + * + * For external URLs, use `window.location = url` instead of calling `goto(url)`. + * + * @param url Where to navigate to. Note that if you've set [`config.kit.paths.base`](https://svelte.dev/docs/kit/configuration#paths) and the URL is root-relative, you need to prepend the base path if you want to navigate within the app. + * @param {Object} opts Options related to the navigation + * */ + export function goto(url: string | URL, opts?: { + replaceState?: boolean | undefined; + noScroll?: boolean | undefined; + keepFocus?: boolean | undefined; + invalidateAll?: boolean | undefined; + invalidate?: (string | URL | ((url: URL) => boolean))[] | undefined; + state?: App.PageState | undefined; + }): Promise; + /** + * Causes any `load` functions belonging to the currently active page to re-run if they depend on the `url` in question, via `fetch` or `depends`. Returns a `Promise` that resolves when the page is subsequently updated. + * + * If the argument is given as a `string` or `URL`, it must resolve to the same URL that was passed to `fetch` or `depends` (including query parameters). + * To create a custom identifier, use a string beginning with `[a-z]+:` (e.g. `custom:state`) — this is a valid URL. + * + * The `function` argument can be used define a custom predicate. It receives the full `URL` and causes `load` to rerun if `true` is returned. + * This can be useful if you want to invalidate based on a pattern instead of a exact match. + * + * ```ts + * // Example: Match '/path' regardless of the query parameters + * import { invalidate } from '$app/navigation'; + * + * invalidate((url) => url.pathname === '/path'); + * ``` + * @param resource The invalidated URL + * */ + export function invalidate(resource: string | URL | ((url: URL) => boolean)): Promise; + /** + * Causes all `load` and `query` functions belonging to the currently active page to re-run. Returns a `Promise` that resolves when the page is subsequently updated. + * */ + export function invalidateAll(): Promise; + /** + * Causes all currently active remote functions to refresh, and all `load` functions belonging to the currently active page to re-run (unless disabled via the option argument). + * Returns a `Promise` that resolves when the page is subsequently updated. + * */ + export function refreshAll({ includeLoadFunctions }?: { + includeLoadFunctions?: boolean; + }): Promise; + /** + * Programmatically preloads the given page, which means + * 1. ensuring that the code for the page is loaded, and + * 2. calling the page's load function with the appropriate options. + * + * This is the same behaviour that SvelteKit triggers when the user taps or mouses over an `` element with `data-sveltekit-preload-data`. + * If the next navigation is to `href`, the values returned from load will be used, making navigation instantaneous. + * Returns a Promise that resolves with the result of running the new route's `load` functions once the preload is complete. + * + * @param href Page to preload + * */ + export function preloadData(href: string): Promise<{ + type: "loaded"; + status: number; + data: Record; + } | { + type: "redirect"; + location: string; + }>; + /** + * Programmatically imports the code for routes that haven't yet been fetched. + * Typically, you might call this to speed up subsequent navigation. + * + * You can specify routes by any matching pathname such as `/about` (to match `src/routes/about/+page.svelte`) or `/blog/*` (to match `src/routes/blog/[slug]/+page.svelte`). + * + * Unlike `preloadData`, this won't call `load` functions. + * Returns a Promise that resolves when the modules have been imported. + * + * */ + export function preloadCode(pathname: string): Promise; + /** + * Programmatically create a new history entry with the given `page.state`. To use the current URL, you can pass `''` as the first argument. Used for [shallow routing](https://svelte.dev/docs/kit/shallow-routing). + * + * */ + export function pushState(url: string | URL, state: App.PageState): void; + /** + * Programmatically replace the current history entry with the given `page.state`. To use the current URL, you can pass `''` as the first argument. Used for [shallow routing](https://svelte.dev/docs/kit/shallow-routing). + * + * */ + export function replaceState(url: string | URL, state: App.PageState): void; + type MaybePromise = T | Promise; + + export {}; +} + +declare module '$app/paths' { + import type { RouteIdWithSearchOrHash, PathnameWithSearchOrHash, ResolvedPathname, RouteId, RouteParams, Asset, Pathname as Pathname_1 } from '$app/types'; + /** + * A string that matches [`config.kit.paths.base`](https://svelte.dev/docs/kit/configuration#paths). + * + * Example usage: `Link` + * + * @deprecated Use [`resolve(...)`](https://svelte.dev/docs/kit/$app-paths#resolve) instead + */ + export let base: '' | `/${string}`; + + /** + * An absolute path that matches [`config.kit.paths.assets`](https://svelte.dev/docs/kit/configuration#paths). + * + * > [!NOTE] If a value for `config.kit.paths.assets` is specified, it will be replaced with `'/_svelte_kit_assets'` during `vite dev` or `vite preview`, since the assets don't yet live at their eventual URL. + * + * @deprecated Use [`asset(...)`](https://svelte.dev/docs/kit/$app-paths#asset) instead + */ + export let assets: '' | `https://${string}` | `http://${string}` | '/_svelte_kit_assets'; + + /** + * @deprecated Use [`resolve(...)`](https://svelte.dev/docs/kit/$app-paths#resolve) instead + */ + export function resolveRoute( + ...args: ResolveArgs + ): ResolvedPathname; + type StripSearchOrHash = T extends `${infer Pathname}?${string}` + ? Pathname + : T extends `${infer Pathname}#${string}` + ? Pathname + : T; + + type ResolveArgs = + T extends RouteId + ? RouteParams extends Record + ? [route: T] + : [route: T, params: RouteParams] + : StripSearchOrHash extends infer U extends RouteId + ? RouteParams extends Record + ? [route: T] + : [route: T, params: RouteParams] + : [route: T]; + /** + * Resolve the URL of an asset in your `static` directory, by prefixing it with [`config.kit.paths.assets`](https://svelte.dev/docs/kit/configuration#paths) if configured, or otherwise by prefixing it with the base path. + * + * During server rendering, the base path is relative and depends on the page currently being rendered. + * + * @example + * ```svelte + * + * + * a potato + * ``` + * @since 2.26 + * + * */ + export function asset(file: Asset): string; + /** + * Resolve a pathname by prefixing it with the base path, if any, or resolve a route ID by populating dynamic segments with parameters. + * + * During server rendering, the base path is relative and depends on the page currently being rendered. + * + * @example + * ```js + * import { resolve } from '$app/paths'; + * + * // using a pathname + * const resolved = resolve(`/blog/hello-world`); + * + * // using a route ID plus parameters + * const resolved = resolve('/blog/[slug]', { + * slug: 'hello-world' + * }); + * ``` + * @since 2.26 + * + * */ + export function resolve(...args: ResolveArgs): ResolvedPathname; + /** + * Match a path or URL to a route ID and extracts any parameters. + * + * @example + * ```js + * import { match } from '$app/paths'; + * + * const route = await match('/blog/hello-world'); + * + * if (route?.id === '/blog/[slug]') { + * const slug = route.params.slug; + * const response = await fetch(`/api/posts/${slug}`); + * const post = await response.json(); + * } + * ``` + * @since 2.52.0 + * + * */ + export function match(url: Pathname_1 | URL | (string & {})): Promise<{ + id: RouteId; + params: Record; + } | null>; + + export {}; +} + +declare module '$app/server' { + import type { RequestEvent, RemoteCommand, RemoteForm, RemoteFormInput, InvalidField, RemotePrerenderFunction, RemoteQueryFunction } from '@sveltejs/kit'; + import type { StandardSchemaV1 } from '@standard-schema/spec'; + /** + * Read the contents of an imported asset from the filesystem + * @example + * ```js + * import { read } from '$app/server'; + * import somefile from './somefile.txt'; + * + * const asset = read(somefile); + * const text = await asset.text(); + * ``` + * @since 2.4.0 + */ + export function read(asset: string): Response; + /** + * Returns the current `RequestEvent`. Can be used inside server hooks, server `load` functions, actions, and endpoints (and functions called by them). + * + * In environments without [`AsyncLocalStorage`](https://nodejs.org/api/async_context.html#class-asynclocalstorage), this must be called synchronously (i.e. not after an `await`). + * @since 2.20.0 + * + * */ + export function getRequestEvent(): RequestEvent; + /** + * Creates a remote command. When called from the browser, the function will be invoked on the server via a `fetch` call. + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#command) for full documentation. + * + * @since 2.27 + */ + export function command(fn: () => Output): RemoteCommand; + /** + * Creates a remote command. When called from the browser, the function will be invoked on the server via a `fetch` call. + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#command) for full documentation. + * + * @since 2.27 + */ + export function command(validate: "unchecked", fn: (arg: Input) => Output): RemoteCommand; + /** + * Creates a remote command. When called from the browser, the function will be invoked on the server via a `fetch` call. + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#command) for full documentation. + * + * @since 2.27 + */ + export function command(validate: Schema, fn: (arg: StandardSchemaV1.InferOutput) => Output): RemoteCommand, Output>; + /** + * Creates a form object that can be spread onto a `` element. + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#form) for full documentation. + * + * @since 2.27 + */ + export function form(fn: () => MaybePromise): RemoteForm; + /** + * Creates a form object that can be spread onto a `` element. + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#form) for full documentation. + * + * @since 2.27 + */ + export function form(validate: "unchecked", fn: (data: Input, issue: InvalidField) => MaybePromise): RemoteForm; + /** + * Creates a form object that can be spread onto a `` element. + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#form) for full documentation. + * + * @since 2.27 + */ + export function form>, Output>(validate: Schema, fn: (data: StandardSchemaV1.InferOutput, issue: InvalidField>) => MaybePromise): RemoteForm, Output>; + /** + * Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a `fetch` call. + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#prerender) for full documentation. + * + * @since 2.27 + */ + export function prerender(fn: () => MaybePromise, options?: { + inputs?: RemotePrerenderInputsGenerator; + dynamic?: boolean; + } | undefined): RemotePrerenderFunction; + /** + * Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a `fetch` call. + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#prerender) for full documentation. + * + * @since 2.27 + */ + export function prerender(validate: "unchecked", fn: (arg: Input) => MaybePromise, options?: { + inputs?: RemotePrerenderInputsGenerator; + dynamic?: boolean; + } | undefined): RemotePrerenderFunction; + /** + * Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a `fetch` call. + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#prerender) for full documentation. + * + * @since 2.27 + */ + export function prerender(schema: Schema, fn: (arg: StandardSchemaV1.InferOutput) => MaybePromise, options?: { + inputs?: RemotePrerenderInputsGenerator>; + dynamic?: boolean; + } | undefined): RemotePrerenderFunction, Output>; + /** + * Creates a remote query. When called from the browser, the function will be invoked on the server via a `fetch` call. + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#query) for full documentation. + * + * @since 2.27 + */ + export function query(fn: () => MaybePromise): RemoteQueryFunction; + /** + * Creates a remote query. When called from the browser, the function will be invoked on the server via a `fetch` call. + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#query) for full documentation. + * + * @since 2.27 + */ + export function query(validate: "unchecked", fn: (arg: Input) => MaybePromise): RemoteQueryFunction; + /** + * Creates a remote query. When called from the browser, the function will be invoked on the server via a `fetch` call. + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#query) for full documentation. + * + * @since 2.27 + */ + export function query(schema: Schema, fn: (arg: StandardSchemaV1.InferOutput) => MaybePromise): RemoteQueryFunction, Output>; + export namespace query { + /** + * Creates a batch query function that collects multiple calls and executes them in a single request + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#query.batch) for full documentation. + * + * @since 2.35 + */ + function batch(validate: "unchecked", fn: (args: Input[]) => MaybePromise<(arg: Input, idx: number) => Output>): RemoteQueryFunction; + /** + * Creates a batch query function that collects multiple calls and executes them in a single request + * + * See [Remote functions](https://svelte.dev/docs/kit/remote-functions#query.batch) for full documentation. + * + * @since 2.35 + */ + function batch(schema: Schema, fn: (args: StandardSchemaV1.InferOutput[]) => MaybePromise<(arg: StandardSchemaV1.InferOutput, idx: number) => Output>): RemoteQueryFunction, Output>; + } + type RemotePrerenderInputsGenerator = () => MaybePromise; + type MaybePromise = T | Promise; + + export {}; +} + +declare module '$app/state' { + /** + * A read-only reactive object with information about the current page, serving several use cases: + * - retrieving the combined `data` of all pages/layouts anywhere in your component tree (also see [loading data](https://svelte.dev/docs/kit/load)) + * - retrieving the current value of the `form` prop anywhere in your component tree (also see [form actions](https://svelte.dev/docs/kit/form-actions)) + * - retrieving the page state that was set through `goto`, `pushState` or `replaceState` (also see [goto](https://svelte.dev/docs/kit/$app-navigation#goto) and [shallow routing](https://svelte.dev/docs/kit/shallow-routing)) + * - retrieving metadata such as the URL you're on, the current route and its parameters, and whether or not there was an error + * + * ```svelte + * + * + * + *

Currently at {page.url.pathname}

+ * + * {#if page.error} + * Problem detected + * {:else} + * All systems operational + * {/if} + * ``` + * + * Changes to `page` are available exclusively with runes. (The legacy reactivity syntax will not reflect any changes) + * + * ```svelte + * + * + * ``` + * + * On the server, values can only be read during rendering (in other words _not_ in e.g. `load` functions). In the browser, the values can be read at any time. + * + * */ + export const page: import("@sveltejs/kit").Page; + /** + * A read-only object representing an in-progress navigation, with `from`, `to`, `type` and (if `type === 'popstate'`) `delta` properties. + * Values are `null` when no navigation is occurring, or during server rendering. + * */ + export const navigating: import("@sveltejs/kit").Navigation | { + from: null; + to: null; + type: null; + willUnload: null; + delta: null; + complete: null; + }; + /** + * A read-only reactive value that's initially `false`. If [`version.pollInterval`](https://svelte.dev/docs/kit/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update `current` to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling. + * */ + export const updated: { + get current(): boolean; + check(): Promise; + }; + + export {}; +} + +declare module '$app/stores' { + export function getStores(): { + + page: typeof page; + + navigating: typeof navigating; + + updated: typeof updated; + }; + /** + * A readable store whose value contains page data. + * + * On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time. + * + * @deprecated Use `page` from `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated)) + * */ + export const page: import("svelte/store").Readable; + /** + * A readable store. + * When navigating starts, its value is a `Navigation` object with `from`, `to`, `type` and (if `type === 'popstate'`) `delta` properties. + * When navigating finishes, its value reverts to `null`. + * + * On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time. + * + * @deprecated Use `navigating` from `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated)) + * */ + export const navigating: import("svelte/store").Readable; + /** + * A readable store whose initial value is `false`. If [`version.pollInterval`](https://svelte.dev/docs/kit/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update the store value to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling. + * + * On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time. + * + * @deprecated Use `updated` from `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated)) + * */ + export const updated: import("svelte/store").Readable & { + check(): Promise; + }; + + export {}; +}/** + * It's possible to tell SvelteKit how to type objects inside your app by declaring the `App` namespace. By default, a new project will have a file called `src/app.d.ts` containing the following: + * + * ```ts + * declare global { + * namespace App { + * // interface Error {} + * // interface Locals {} + * // interface PageData {} + * // interface PageState {} + * // interface Platform {} + * } + * } + * + * export {}; + * ``` + * + * The `export {}` line exists because without it, the file would be treated as an _ambient module_ which prevents you from adding `import` declarations. + * If you need to add ambient `declare module` declarations, do so in a separate file like `src/ambient.d.ts`. + * + * By populating these interfaces, you will gain type safety when using `event.locals`, `event.platform`, and `data` from `load` functions. + */ +declare namespace App { + /** + * Defines the common shape of expected and unexpected errors. Expected errors are thrown using the `error` function. Unexpected errors are handled by the `handleError` hooks which should return this shape. + */ + export interface Error { + message: string; + } + + /** + * The interface that defines `event.locals`, which can be accessed in server [hooks](https://svelte.dev/docs/kit/hooks) (`handle`, and `handleError`), server-only `load` functions, and `+server.js` files. + */ + export interface Locals {} + + /** + * Defines the common shape of the [page.data state](https://svelte.dev/docs/kit/$app-state#page) and [$page.data store](https://svelte.dev/docs/kit/$app-stores#page) - that is, the data that is shared between all pages. + * The `Load` and `ServerLoad` functions in `./$types` will be narrowed accordingly. + * Use optional properties for data that is only present on specific pages. Do not add an index signature (`[key: string]: any`). + */ + export interface PageData {} + + /** + * The shape of the `page.state` object, which can be manipulated using the [`pushState`](https://svelte.dev/docs/kit/$app-navigation#pushState) and [`replaceState`](https://svelte.dev/docs/kit/$app-navigation#replaceState) functions from `$app/navigation`. + */ + export interface PageState {} + + /** + * If your adapter provides [platform-specific context](https://svelte.dev/docs/kit/adapters#Platform-specific-context) via `event.platform`, you can specify it here. + */ + export interface Platform {} +} + +/** + * This module is only available to [service workers](https://svelte.dev/docs/kit/service-workers). + */ +declare module '$service-worker' { + /** + * The `base` path of the deployment. Typically this is equivalent to `config.kit.paths.base`, but it is calculated from `location.pathname` meaning that it will continue to work correctly if the site is deployed to a subdirectory. + * Note that there is a `base` but no `assets`, since service workers cannot be used if `config.kit.paths.assets` is specified. + */ + export const base: string; + /** + * An array of URL strings representing the files generated by Vite, suitable for caching with `cache.addAll(build)`. + * During development, this is an empty array. + */ + export const build: string[]; + /** + * An array of URL strings representing the files in your static directory, or whatever directory is specified by `config.kit.files.assets`. You can customize which files are included from `static` directory using [`config.kit.serviceWorker.files`](https://svelte.dev/docs/kit/configuration#serviceWorker) + */ + export const files: string[]; + /** + * An array of pathnames corresponding to prerendered pages and endpoints. + * During development, this is an empty array. + */ + export const prerendered: string[]; + /** + * See [`config.kit.version`](https://svelte.dev/docs/kit/configuration#version). It's useful for generating unique cache names inside your service worker, so that a later deployment of your app can invalidate old caches. + */ + export const version: string; +} + +/** + * This module contains generated types for the routes in your app. + */ +declare module '$app/types' { + /** + * Interface for all generated app types. This gets extended via declaration merging. DO NOT USE THIS INTERFACE DIRECTLY. + */ + export interface AppTypes { + // These are all functions so that we can leverage function overloads to get the correct type. + // Using the return types directly would error with a "not the same type" error. + // https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces + RouteId(): string; + RouteParams(): Record>; + LayoutParams(): Record>; + Pathname(): string; + ResolvedPathname(): string; + Asset(): string; + } + + /** + * A union of all the route IDs in your app. Used for `page.route.id` and `event.route.id`. + */ + export type RouteId = ReturnType; + + /** + * `RouteId`, but possibly suffixed with a search string and/or hash. + */ + export type RouteIdWithSearchOrHash = RouteId | `${RouteId}?${string}` | `${RouteId}#${string}`; + + /** + * A utility for getting the parameters associated with a given route. + */ + export type RouteParams = T extends keyof ReturnType + ? ReturnType[T] + : Record; + + /** + * A utility for getting the parameters associated with a given layout, which is similar to `RouteParams` but also includes optional parameters for any child route. + */ + export type LayoutParams = T extends keyof ReturnType + ? ReturnType[T] + : Record; + + /** + * A union of all valid pathnames in your app. + */ + export type Pathname = ReturnType; + + /** + * `Pathname`, but possibly suffixed with a search string and/or hash. + */ + export type PathnameWithSearchOrHash = + | Pathname + | `${Pathname}?${string}` + | `${Pathname}#${string}`; + + /** + * `Pathname`, but possibly prefixed with a base path. Used for `page.url.pathname`. + */ + export type ResolvedPathname = ReturnType; + + /** + * A union of all the filenames of assets contained in your `static` directory. + */ + export type Asset = ReturnType; +} + +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/frontend/node_modules/@sveltejs/kit/types/index.d.ts.map b/frontend/node_modules/@sveltejs/kit/types/index.d.ts.map new file mode 100644 index 0000000..dab7982 --- /dev/null +++ b/frontend/node_modules/@sveltejs/kit/types/index.d.ts.map @@ -0,0 +1,232 @@ +{ + "version": 3, + "file": "index.d.ts", + "names": [ + "Span", + "Adapter", + "LoadProperties", + "AwaitedActions", + "OptionalUnion", + "uniqueSymbol", + "ActionFailure", + "UnpackValidationError", + "Builder", + "Config", + "Cookies", + "Emulator", + "KitConfig", + "Handle", + "HandleServerError", + "HandleValidationError", + "HandleClientError", + "HandleFetch", + "ServerInit", + "ClientInit", + "Reroute", + "Transport", + "Transporter", + "Load", + "LoadEvent", + "NavigationEvent", + "NavigationTarget", + "NavigationType", + "NavigationBase", + "NavigationEnter", + "NavigationExternal", + "NavigationGoto", + "NavigationLeave", + "NavigationFormSubmit", + "NavigationPopState", + "NavigationLink", + "Navigation", + "BeforeNavigate", + "OnNavigate", + "AfterNavigate", + "Page", + "ParamMatcher", + "RequestEvent", + "RequestHandler", + "ResolveOptions", + "RouteDefinition", + "Server", + "ServerInitOptions", + "SSRManifest", + "ServerLoad", + "ServerLoadEvent", + "Action", + "Actions", + "ActionResult", + "HttpError", + "Redirect", + "SubmitFunction", + "Snapshot", + "WillRecurseIndefinitely", + "InputTypeMap", + "RemoteFormFieldType", + "InputElementProps", + "RemoteFormFieldMethods", + "RemoteFormFieldValue", + "AsArgs", + "RemoteFormField", + "RemoteFormFieldContainer", + "UnknownField", + "RemoteFormFieldsRoot", + "RemoteFormFields", + "RecursiveFormFields", + "MaybeArray", + "RemoteFormInput", + "RemoteFormIssue", + "ExtractId", + "InvalidField", + "ValidationError", + "RemoteForm", + "RemoteCommand", + "RemoteResource", + "RemoteQuery", + "RemoteQueryOverride", + "RemotePrerenderFunction", + "RemoteQueryFunction", + "AdapterEntry", + "Csp", + "CspDirectives", + "HttpMethod", + "Logger", + "MaybePromise", + "Prerendered", + "PrerenderHttpErrorHandler", + "PrerenderMissingIdHandler", + "PrerenderEntryGeneratorMismatchHandler", + "PrerenderUnseenRoutesHandler", + "PrerenderHttpErrorHandlerValue", + "PrerenderMissingIdHandlerValue", + "PrerenderUnseenRoutesHandlerValue", + "PrerenderEntryGeneratorMismatchHandlerValue", + "PrerenderOption", + "RequestOptions", + "RouteSegment", + "TrailingSlash", + "DeepPartial", + "IsAny", + "Asset", + "BuildData", + "ManifestData", + "PageNode", + "RecursiveRequired", + "RouteParam", + "RouteData", + "SSRComponent", + "SSRComponentLoader", + "UniversalNode", + "ServerNode", + "SSRNode", + "SSRNodeLoader", + "PageNodeIndexes", + "PrerenderEntryGenerator", + "SSREndpoint", + "SSRRoute", + "SSRClientRoute", + "ValidatedConfig", + "ValidatedKitConfig", + "isHttpError", + "redirect", + "isRedirect", + "json", + "text", + "isActionFailure", + "invalid", + "isValidationError", + "normalizeUrl", + "ValidPageOption", + "PageOptions", + "valid_page_options_array", + "VERSION", + "sequence", + "getRequest", + "setResponse", + "createReadableStream", + "installPolyfills", + "sveltekit", + "browser", + "dev", + "building", + "version", + "deserialize", + "enhance", + "applyAction", + "afterNavigate", + "beforeNavigate", + "onNavigate", + "disableScrollHandling", + "goto", + "invalidate", + "invalidateAll", + "refreshAll", + "preloadData", + "preloadCode", + "pushState", + "replaceState", + "base", + "assets", + "resolveRoute", + "StripSearchOrHash", + "ResolveArgs", + "asset", + "resolve", + "match", + "read", + "getRequestEvent", + "RemotePrerenderInputsGenerator", + "page", + "navigating", + "updated", + "getStores" + ], + "sources": [ + "../src/exports/public.d.ts", + "../src/exports/internal/index.js", + "../src/types/private.d.ts", + "../src/types/internal.d.ts", + "../src/exports/index.js", + "../src/exports/vite/static_analysis/index.js", + "../src/version.js", + "../src/exports/hooks/sequence.js", + "../src/exports/node/index.js", + "../src/exports/node/polyfills.js", + "../src/exports/vite/index.js", + "../src/runtime/app/environment/types.d.ts", + "../src/runtime/app/forms.js", + "../src/runtime/client/client.js", + "../src/runtime/app/paths/public.d.ts", + "../src/runtime/app/paths/types.d.ts", + "../src/runtime/app/paths/client.js", + "../src/runtime/app/server/index.js", + "../src/exports/internal/event.js", + "../src/runtime/app/state/index.js", + "../src/runtime/app/stores.js" + ], + "sourcesContent": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "mappings": ";;;;;;;;MAiCKA,IAAIA;;;;;kBAKQC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAiCZC,cAAcA;;;;;;aAMdC,cAAcA;;;;;;;;MAQrBC,aAAaA;;;;;OAKJC,YAAYA;;kBAETC,aAAaA;;;;;;MAMzBC,qBAAqBA;;;;;;;;;;;kBAWTC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA8IPC,MAAMA;;;;;;;;;;;kBAWNC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA4DPC,QAAQA;;;;;;;;kBAQRC,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAklBdC,MAAMA;;;;;;;;;;;aAWNC,iBAAiBA;;;;;;;;;;;;aAYjBC,qBAAqBA;;;;;;;;;aASrBC,iBAAiBA;;;;;;;;;;aAUjBC,WAAWA;;;;;;;;;;aAUXC,UAAUA;;;;;;aAMVC,UAAUA;;;;;;aAMVC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;aA0BPC,SAASA;;;;;kBAKJC,WAAWA;;;;;;;;;;;;aAYhBC,IAAIA;;;;;;;;;;;;kBAYCC,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAyHTC,eAAeA;;;;;;;;;;;;;;;;;;;;;;;;;;kBA0BfC,gBAAgBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA6CrBC,cAAcA;;kBAETC,cAAcA;;;;;;;;;;;;;;;;;;;;kBAoBdC,eAAeA;;;;;;;;;;;;;;;;;;aAkBpBC,kBAAkBA;;kBAEbC,cAAcA;;;;;;;;;;;;;;;kBAedC,eAAeA;;;;;;;;;;;;;;;kBAefC,oBAAoBA;;;;;;;;;;;;;;;;;;;;kBAoBpBC,kBAAkBA;;;;;;;;;;;;;;;;;;kBAkBlBC,cAAcA;;;;;;;;;;;;;;;;;;;;aAoBnBC,UAAUA;;;;;;;;;aASVC,cAAcA;;;;;;;;;;aAUdC,UAAUA;;;;;;;;;;;aAWVC,aAAaA;;;;;;;;;;;kBAWRC,IAAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA8CTC,YAAYA;;kBAEPC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA+GjBC,cAAcA;;;;;kBAKTC,cAAcA;;;;;;;;;;;;;;;;;;;;;;;kBAuBdC,eAAeA;;;;;;;;;;;;;;;cAenBC,MAAMA;;;;;;kBAMFC,iBAAiBA;;;;;;;kBAOjBC,WAAWA;;;;;;;;;;;;;;;;;;;;;;;;;aAyBhBC,UAAUA;;;;;;;kBAOLC,eAAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAkFpBC,MAAMA;;;;;;;;;;aAUNC,OAAOA;;;;;;;;;;;;;;;;aAgBPC,YAAYA;;;;;;;;;;;;kBC/tDXC,SAASA;;;;;;;;;;kBAqBTC,QAAQA;;;;;;;aDuuDTC,cAAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA6BTC,QAAQA;;;;;;MAMpBC,uBAAuBA;;;MAGvBC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA6BLC,mBAAmBA;;;;;MAK1BC,iBAAiBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAwCjBC,sBAAsBA;;;;;;;;;aASfC,oBAAoBA;;MAE3BC,MAAMA;;;;;;;;;;;aAWCC,eAAeA;;;;;;;;;;;;;;MActBC,wBAAwBA;;;;;MAKxBC,YAAYA;;;;;;;;;;;;;;;;;;MAkBZC,oBAAoBA;;;;;;;;;;;;;;;aAebC,gBAAgBA;;;;;;;;;;;;;;;;MAgBvBC,mBAAmBA;;;;MAInBC,UAAUA;;kBAEEC,eAAeA;;;;kBAIfC,eAAeA;;;;;;;MAO3BC,SAASA;;;;;;;;;;;;;aAaFC,YAAYA;;;;;;;;;;;;;;;;;;kBAkBPC,eAAeA;;;;;;;;aAQpBC,UAAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAuDVC,aAAaA;;;;;;;;aAQbC,cAAcA;;;;;;;;;;;;;;;;;;aAkBdC,WAAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAqCNC,mBAAmBA;;;;;;;;aAQxBC,uBAAuBA;;;;;;;aAOvBC,mBAAmBA;;;WE/nEdC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAkDZC,GAAGA;;;;;;;;;;;;;;;;;;;;;WAqBHC,aAAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAmElBC,UAAUA;;WAELC,MAAMA;;;;;;;;;MASXC,YAAYA;;WAEPC,WAAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAmCXC,yBAAyBA;;;;;;;;;;WAUzBC,yBAAyBA;;;;WAIzBC,sCAAsCA;;;;WAItCC,4BAA4BA;;;;MAIjCC,8BAA8BA;MAC9BC,8BAA8BA;MAC9BC,iCAAiCA;;;;;MAKjCC,2CAA2CA;;;;;;aAM3CC,eAAeA;;WAIVC,cAAcA;;;;;WAKdC,YAAYA;;;;;;;MAOjBC,aAAaA;;MAEbC,WAAWA;;;;;;;;MAQXC,KAAKA;WCxMAC,KAAKA;;;;;;WAeLC,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAuHTC,YAAYA;;;;;;;;;;;;;WAkBZC,QAAQA;;;;;;;;;;;;;;;;MAkCbC,iBAAiBA;;;;;;;;;WAWZC,UAAUA;;;;;;;;;;;;;WAaVC,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;WAyHTC,YAAYA;;;;;;;;;;;;;;;;;;;;MAoBjBC,kBAAkBA;;WAEbC,aAAaA;;;;;;;;;;;WAWbC,UAAUA;;;;;;;;;;;WAWVC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;MAyBZC,aAAaA;;WA+BRC,eAAeA;;;;;;MAMpBC,uBAAuBA;;MAGvBC,WAAWA;;;;;;;;WAQNC,QAAQA;;;;;;;;;WASRC,cAAcA;;;;;;;;;MA+CnBC,eAAeA;;;;;MAKfC,kBAAkBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCzddC,WAAWA;;;;;;;;;;;;;;;;;;;iBAsBXC,QAAQA;;;;;iBAiBRC,UAAUA;;;;;;iBASVC,IAAIA;;;;;;iBA4BJC,IAAIA;;;;;;;;;;;;;;;;iBAkDJC,eAAeA;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+BfC,OAAOA;;;;;;iBAYPC,iBAAiBA;;;;;;;;;;;;;;iBAmBjBC,YAAYA;;;;;;;MCpQ2BC,eAAeA;MACjBC,WAAWA;OAd1DC,wBAAwBA;cCDjBC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBC4EJC,QAAQA;;;;;;iBC4BFC,UAAUA;;;;;;iBAgDVC,WAAWA;;;;;iBAgFjBC,oBAAoBA;;;;;;;;;;;iBCzNpBC,gBAAgBA;;;;;;;;;iBCmHVC,SAASA;;;;;;;;;cClIlBC,OAAOA;;;;;cAKPC,GAAGA;;;;;cAKHC,QAAQA;;;;;cAKRC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;iBCYJC,WAAWA;;;;;;;;;;;;;;;;;;;;;;;;iBAgDXC,OAAOA;;;;;;;iBC+zEDC,WAAWA;;;;;;;;;;;iBAhVjBC,aAAaA;;;;;;;;;;;;iBAiBbC,cAAcA;;;;;;;;;;iBAedC,UAAUA;;;;;iBASVC,qBAAqBA;;;;;;;;;;iBA8BrBC,IAAIA;;;;;;;;;;;;;;;;;;;;;;;;;iBAsCJC,UAAUA;;;;iBA0BVC,aAAaA;;;;;iBAebC,UAAUA;;;;;;;;;;;;;;iBAuBJC,WAAWA;;;;;;;;;;;;;;;;;;iBAoCXC,WAAWA;;;;;iBAsCjBC,SAASA;;;;;iBA+CTC,YAAYA;MXxsEhBzE,YAAYA;;;;;;;;;;;;;;YY/Ib0E,IAAIA;;;;;;;;;YASJC,MAAMA;;;;;iBAKDC,YAAYA;;;MCnBvBC,iBAAiBA;;;;;;MAMVC,WAAWA;;;;;;;;;;;;;;;;;;;;;;;;;;iBCWPC,KAAKA;;;;;;;;;;;;;;;;;;;;;iBA6BLC,OAAOA;;;;;;;;;;;;;;;;;;;iBA4BDC,KAAKA;;;;;;;;;;;;;;;;;;;;;;;iBC9DXC,IAAIA;;;;;;;;iBCSJC,eAAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Mf+cnBC,8BAA8BA;MDhV9BpF,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ciB1GXqF,IAAIA;;;;;cAQJC,UAAUA;;;;;;;;;;;cAMVC,OAAOA;;;;;;;;;iBCrDPC,SAASA;;;;;;;;;;;;;;;cAyBTH,IAAIA;;;;;;;;;;cAiBJC,UAAUA;;;;;;;;cAeVC,OAAOA", + "ignoreList": [] +} \ No newline at end of file diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/LICENSE b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/LICENSE new file mode 100644 index 0000000..c1a5d8f --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 [these people](https://github.com/sveltejs/vite-plugin-svelte/graphs/contributors) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/README.md b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/README.md new file mode 100644 index 0000000..bbdf50c --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/README.md @@ -0,0 +1,26 @@ +# @sveltejs/vite-plugin-svelte-inspector + +A [Svelte](https://svelte.dev) inspector plugin for [Vite](https://vitejs.dev). + +## Usage + +```js +// vite.config.js +import { defineConfig } from 'vite'; +import { svelte } from '@sveltejs/vite-plugin-svelte'; +import { svelteInspector } from '@sveltejs/vite-plugin-svelte-inspector'; + +export default defineConfig({ + plugins: [ + // the svelte plugin is required to work + svelte(), + svelteInspector({ + /* plugin options */ + }) + ] +}); +``` + +## License + +[MIT](./LICENSE) diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/package.json b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/package.json new file mode 100644 index 0000000..4551087 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/package.json @@ -0,0 +1,56 @@ +{ + "name": "@sveltejs/vite-plugin-svelte-inspector", + "version": "3.0.1", + "license": "MIT", + "author": "dominikg", + "files": [ + "src", + "types" + ], + "type": "module", + "types": "types/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./types/index.d.ts", + "default": "./src/index.js" + } + } + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/sveltejs/vite-plugin-svelte.git", + "directory": "packages/vite-plugin-svelte-inspector" + }, + "keywords": [ + "vite-plugin", + "vite plugin", + "vite", + "svelte" + ], + "bugs": { + "url": "https://github.com/sveltejs/vite-plugin-svelte/issues" + }, + "homepage": "https://github.com/sveltejs/vite-plugin-svelte#readme", + "dependencies": { + "debug": "^4.3.7" + }, + "peerDependencies": { + "@sveltejs/vite-plugin-svelte": "^4.0.0-next.0||^4.0.0", + "svelte": "^5.0.0-next.96 || ^5.0.0", + "vite": "^5.0.0" + }, + "devDependencies": { + "@types/debug": "^4.1.12", + "svelte": "^5.0.3", + "vite": "^5.4.9" + }, + "scripts": { + "check:publint": "publint --strict", + "check:types": "tsc --noEmit", + "generate:types": "dts-buddy -m \"@sveltejs/vite-plugin-svelte-inspector:src/public.d.ts\"" + } +} \ No newline at end of file diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/debug.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/debug.js new file mode 100644 index 0000000..0575a83 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/debug.js @@ -0,0 +1,3 @@ +import _debug from 'debug'; + +export const debug = _debug('vite-plugin-svelte-inspector'); diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/index.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/index.js new file mode 100644 index 0000000..3b69783 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/index.js @@ -0,0 +1,112 @@ +import { normalizePath } from 'vite'; +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { debug } from './debug.js'; +import { defaultInspectorOptions, parseEnvironmentOptions } from './options.js'; +import { cleanUrl } from './utils.js'; + +function getInspectorPath() { + const pluginPath = normalizePath(path.dirname(fileURLToPath(import.meta.url))); + return pluginPath.replace( + /\/vite-plugin-svelte-inspector\/src$/, + '/vite-plugin-svelte-inspector/src/runtime/' + ); +} + +/** + * @param {Partial} [options] + * @returns {import('vite').Plugin} + */ +export function svelteInspector(options) { + const inspectorPath = getInspectorPath(); + debug(`svelte inspector path: ${inspectorPath}`); + + /** @type {import('vite').ResolvedConfig} */ + let viteConfig; + /** @type {import('./public.d.ts').Options} */ + let inspectorOptions; + let disabled = false; + + return { + name: 'vite-plugin-svelte-inspector', + apply: 'serve', + enforce: 'pre', + + configResolved(config) { + viteConfig = config; + const environmentOptions = parseEnvironmentOptions(config); + if (environmentOptions === false) { + debug('environment options set to false, inspector disabled'); + disabled = true; + return; + } + + // Handle config from svelte.config.js through vite-plugin-svelte + const vps = config.plugins.find((p) => p.name === 'vite-plugin-svelte'); + const configFileOptions = vps?.api?.options?.inspector; + + // vite-plugin-svelte can only pass options through it's `api` instead of `options`. + // that means this plugin could be created but should be disabled, so we check this case here. + if (vps && !options && !configFileOptions && !environmentOptions) { + debug("vite-plugin-svelte didn't pass options, inspector disabled"); + disabled = true; + return; + } + + if (environmentOptions === true) { + inspectorOptions = defaultInspectorOptions; + } else { + inspectorOptions = { + ...defaultInspectorOptions, + ...configFileOptions, + ...options, + ...(environmentOptions || {}) + }; + } + + inspectorOptions.__internal = { + base: config.base?.replace(/\/$/, '') || '' + }; + }, + + async resolveId(importee, _, options) { + if (options?.ssr || disabled) { + return; + } + if (importee.startsWith('virtual:svelte-inspector-options')) { + return importee; + } else if (importee.startsWith('virtual:svelte-inspector-path:')) { + return importee.replace('virtual:svelte-inspector-path:', inspectorPath); + } + }, + + async load(id, options) { + if (options?.ssr || disabled) { + return; + } + if (id === 'virtual:svelte-inspector-options') { + return `export default ${JSON.stringify(inspectorOptions ?? {})}`; + } else if (id.startsWith(inspectorPath)) { + // read file ourselves to avoid getting shut out by vites fs.allow check + const file = cleanUrl(id); + if (fs.existsSync(id)) { + return await fs.promises.readFile(file, 'utf-8'); + } else { + viteConfig.logger.error( + `[vite-plugin-svelte-inspector] failed to find svelte-inspector: ${id}` + ); + } + } + }, + + transform(code, id, options) { + if (options?.ssr || disabled) { + return; + } + if (id.includes('vite/dist/client/client.mjs')) { + return { code: `${code}\nimport('virtual:svelte-inspector-path:load-inspector.js')` }; + } + } + }; +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/options.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/options.js new file mode 100644 index 0000000..15a2456 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/options.js @@ -0,0 +1,63 @@ +import process from 'node:process'; +import { loadEnv } from 'vite'; +import { debug } from './debug.js'; + +/** @type {import('./public.d.ts').Options} */ +export const defaultInspectorOptions = { + toggleKeyCombo: 'alt-x', + navKeys: { parent: 'ArrowUp', child: 'ArrowDown', next: 'ArrowRight', prev: 'ArrowLeft' }, + escapeKeys: ['Backspace', 'Escape'], + openKey: 'Enter', + holdMode: true, + showToggleButton: 'active', + toggleButtonPos: 'top-right', + customStyles: true +}; + +/** + * @param {import('vite').ResolvedConfig} config + * @returns {Partial | boolean | void} + */ +export function parseEnvironmentOptions(config) { + const env = loadEnv(config.mode, config.envDir ?? process.cwd(), 'SVELTE_INSPECTOR'); + const options = env?.SVELTE_INSPECTOR_OPTIONS; + const toggle = env?.SVELTE_INSPECTOR_TOGGLE; + if (options) { + try { + const parsed = JSON.parse(options); + const parsedType = typeof parsed; + if (parsedType === 'boolean') { + return parsed; + } else if (parsedType === 'object') { + if (Array.isArray(parsed)) { + throw new Error('invalid type, expected object map but got array'); + } + const parsedKeys = Object.keys(parsed); + const defaultKeys = Object.keys(defaultInspectorOptions); + const unknownKeys = parsedKeys.filter((k) => !defaultKeys.includes(k)); + if (unknownKeys.length) { + config.logger.warn( + `[vite-plugin-svelte-inspector] ignoring unknown options in environment SVELTE_INSPECTOR_OPTIONS: ${unknownKeys.join( + ', ' + )}` + ); + for (const key of unknownKeys) { + delete parsed[key]; + } + } + debug('loaded environment config', parsed); + return parsed; + } + } catch (e) { + config.logger.error( + `[vite-plugin-svelte-inspector] failed to parse inspector options from environment SVELTE_INSPECTOR_OPTIONS="${options}"\n${e}` + ); + } + } else if (toggle) { + const keyConfig = { + toggleKeyCombo: toggle + }; + debug('loaded environment config', keyConfig); + return keyConfig; + } +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/public.d.ts b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/public.d.ts new file mode 100644 index 0000000..6849623 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/public.d.ts @@ -0,0 +1,78 @@ +export interface Options { + /** + * define a key combo to toggle inspector, + * @default 'meta-shift' on mac, 'control-shift' on other os + * + * any number of modifiers `control` `shift` `alt` `meta` followed by zero or one regular key, separated by - + * examples: control-shift, control-o, control-alt-s meta-x control-meta + * Some keys have native behavior (e.g. alt-s opens history menu on firefox). + * To avoid conflicts or accidentally typing into inputs, modifier only combinations are recommended. + */ + toggleKeyCombo?: string; + + /** + * define keys to select elements with via keyboard + * @default {parent: 'ArrowUp', child: 'ArrowDown', next: 'ArrowRight', prev: 'ArrowLeft' } + * + * improves accessibility and also helps when you want to select elements that do not have a hoverable surface area + * due to tight wrapping + * + * A note for users of screen-readers: + * If you are using arrow keys to navigate the page itself, change the navKeys to avoid conflicts. + * e.g. navKeys: {parent: 'w', prev: 'a', child: 's', next: 'd'} + * + * + * parent: select closest parent + * child: select first child (or grandchild) + * next: next sibling (or parent if no next sibling exists) + * prev: previous sibling (or parent if no prev sibling exists) + */ + navKeys?: { parent: string; child: string; next: string; prev: string }; + + /** + * define key to open the editor for the currently selected dom node + * + * @default 'Enter' + */ + openKey?: string; + + /** + * define keys to close the inspector + * @default ['Backspace', 'Escape'] + */ + escapeKeys?: string[]; + + /** + * inspector is automatically disabled when releasing toggleKeyCombo after holding it for a longpress + * @default true + */ + holdMode?: boolean; + + /** + * when to show the toggle button + * @default 'active' + */ + showToggleButton?: 'always' | 'active' | 'never'; + + /** + * where to display the toggle button + * @default top-right + */ + toggleButtonPos?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'; + + /** + * inject custom styles when inspector is active + */ + customStyles?: boolean; + + /** + * internal options that are automatically set, not to be set or used by users + * @internal + */ + __internal?: { + // vite base url + base: string; + }; +} +// eslint-disable-next-line n/no-missing-import +export * from './index.js'; diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/runtime/Inspector.svelte b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/runtime/Inspector.svelte new file mode 100644 index 0000000..9a03c49 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/runtime/Inspector.svelte @@ -0,0 +1,411 @@ + + + + +{#if show_toggle} + +{/if} +{#if enabled && active_el && file_loc} + {@const loc = active_el.__svelte_meta.loc} +
+ <{active_el.tagName.toLowerCase()}> {file_loc} +
+
+ {active_el.tagName.toLowerCase()} in file {loc.file} on line {loc.line} column {loc.column} +
+{/if} + + diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/runtime/load-inspector.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/runtime/load-inspector.js new file mode 100644 index 0000000..5662f9f --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/runtime/load-inspector.js @@ -0,0 +1,14 @@ +// eslint-disable-next-line n/no-missing-import +import Inspector from 'virtual:svelte-inspector-path:Inspector.svelte'; +import { mount } from 'svelte'; +function create_inspector_host() { + const id = 'svelte-inspector-host'; + if (document.getElementById(id) != null) { + throw new Error('svelte-inspector-host element already exists'); + } + const el = document.createElement('div'); + el.setAttribute('id', id); + document.documentElement.appendChild(el); + return el; +} +mount(Inspector, { target: create_inspector_host() }); diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/utils.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/utils.js new file mode 100644 index 0000000..bcb43f9 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/src/utils.js @@ -0,0 +1,8 @@ +const postfixRE = /[?#].*$/s; + +/** + * @param {string} url + */ +export function cleanUrl(url) { + return url.replace(postfixRE, ''); +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/types/index.d.ts b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/types/index.d.ts new file mode 100644 index 0000000..3c88a1e --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/types/index.d.ts @@ -0,0 +1,82 @@ +declare module '@sveltejs/vite-plugin-svelte-inspector' { + export interface Options { + /** + * define a key combo to toggle inspector, + * @default 'meta-shift' on mac, 'control-shift' on other os + * + * any number of modifiers `control` `shift` `alt` `meta` followed by zero or one regular key, separated by - + * examples: control-shift, control-o, control-alt-s meta-x control-meta + * Some keys have native behavior (e.g. alt-s opens history menu on firefox). + * To avoid conflicts or accidentally typing into inputs, modifier only combinations are recommended. + */ + toggleKeyCombo?: string; + + /** + * define keys to select elements with via keyboard + * @default {parent: 'ArrowUp', child: 'ArrowDown', next: 'ArrowRight', prev: 'ArrowLeft' } + * + * improves accessibility and also helps when you want to select elements that do not have a hoverable surface area + * due to tight wrapping + * + * A note for users of screen-readers: + * If you are using arrow keys to navigate the page itself, change the navKeys to avoid conflicts. + * e.g. navKeys: {parent: 'w', prev: 'a', child: 's', next: 'd'} + * + * + * parent: select closest parent + * child: select first child (or grandchild) + * next: next sibling (or parent if no next sibling exists) + * prev: previous sibling (or parent if no prev sibling exists) + */ + navKeys?: { parent: string; child: string; next: string; prev: string }; + + /** + * define key to open the editor for the currently selected dom node + * + * @default 'Enter' + */ + openKey?: string; + + /** + * define keys to close the inspector + * @default ['Backspace', 'Escape'] + */ + escapeKeys?: string[]; + + /** + * inspector is automatically disabled when releasing toggleKeyCombo after holding it for a longpress + * @default true + */ + holdMode?: boolean; + + /** + * when to show the toggle button + * @default 'active' + */ + showToggleButton?: 'always' | 'active' | 'never'; + + /** + * where to display the toggle button + * @default top-right + */ + toggleButtonPos?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'; + + /** + * inject custom styles when inspector is active + */ + customStyles?: boolean; + + /** + * internal options that are automatically set, not to be set or used by users + * */ + __internal?: { + // vite base url + base: string; + }; + } + export function svelteInspector(options?: Partial | undefined): import("vite").Plugin; + + export {}; +} + +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/types/index.d.ts.map b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/types/index.d.ts.map new file mode 100644 index 0000000..08ac045 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte-inspector/types/index.d.ts.map @@ -0,0 +1,17 @@ +{ + "version": 3, + "file": "index.d.ts", + "names": [ + "Options", + "svelteInspector" + ], + "sources": [ + "../src/public.d.ts", + "../src/index.js" + ], + "sourcesContent": [ + null, + null + ], + "mappings": ";kBAAiBA,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCoBRC,eAAeA" +} \ No newline at end of file diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/LICENSE b/frontend/node_modules/@sveltejs/vite-plugin-svelte/LICENSE new file mode 100644 index 0000000..c1a5d8f --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 [these people](https://github.com/sveltejs/vite-plugin-svelte/graphs/contributors) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/README.md b/frontend/node_modules/@sveltejs/vite-plugin-svelte/README.md new file mode 100644 index 0000000..48798bc --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/README.md @@ -0,0 +1,28 @@ +# @sveltejs/vite-plugin-svelte + +The official [Svelte](https://svelte.dev) plugin for [Vite](https://vitejs.dev). + +## Usage + +```js +// vite.config.js +import { defineConfig } from 'vite'; +import { svelte } from '@sveltejs/vite-plugin-svelte'; + +export default defineConfig({ + plugins: [ + svelte({ + /* plugin options */ + }) + ] +}); +``` + +## Documentation + +- [Plugin options](../../docs/config.md) +- [FAQ](../../docs/faq.md) + +## License + +[MIT](./LICENSE) diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/package.json b/frontend/node_modules/@sveltejs/vite-plugin-svelte/package.json new file mode 100644 index 0000000..fe71997 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/package.json @@ -0,0 +1,62 @@ +{ + "name": "@sveltejs/vite-plugin-svelte", + "version": "4.0.4", + "license": "MIT", + "author": "dominikg", + "files": [ + "src", + "types" + ], + "type": "module", + "types": "types/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./types/index.d.ts", + "default": "./src/index.js" + } + } + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/sveltejs/vite-plugin-svelte.git", + "directory": "packages/vite-plugin-svelte" + }, + "keywords": [ + "vite-plugin", + "vite plugin", + "vite", + "svelte" + ], + "bugs": { + "url": "https://github.com/sveltejs/vite-plugin-svelte/issues" + }, + "homepage": "https://github.com/sveltejs/vite-plugin-svelte#readme", + "dependencies": { + "@sveltejs/vite-plugin-svelte-inspector": "^3.0.0-next.0||^3.0.0", + "debug": "^4.3.7", + "deepmerge": "^4.3.1", + "kleur": "^4.1.5", + "magic-string": "^0.30.12", + "vitefu": "^1.0.3" + }, + "peerDependencies": { + "svelte": "^5.0.0-next.96 || ^5.0.0", + "vite": "^5.0.0" + }, + "devDependencies": { + "@types/debug": "^4.1.12", + "esbuild": "^0.24.0", + "sass": "^1.81.0", + "svelte": "^5.2.0", + "vite": "^5.4.11" + }, + "scripts": { + "check:publint": "publint --strict", + "check:types": "tsc --noEmit", + "generate:types": "dts-buddy -m \"@sveltejs/vite-plugin-svelte:src/public.d.ts\"" + } +} \ No newline at end of file diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/handle-hot-update.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/handle-hot-update.js new file mode 100644 index 0000000..82758e5 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/handle-hot-update.js @@ -0,0 +1,145 @@ +import { log, logCompilerWarnings } from './utils/log.js'; +import { toRollupError } from './utils/error.js'; + +/** + * Vite-specific HMR handling + * + * @param {Function} compileSvelte + * @param {import('vite').HmrContext} ctx + * @param {import('./types/id.d.ts').SvelteRequest} svelteRequest + * @param {import('./utils/vite-plugin-svelte-cache.js').VitePluginSvelteCache} cache + * @param {import('./types/options.d.ts').ResolvedOptions} options + * @returns {Promise} + */ +export async function handleHotUpdate(compileSvelte, ctx, svelteRequest, cache, options) { + if (!cache.has(svelteRequest)) { + // file hasn't been requested yet (e.g. async component) + log.debug( + `handleHotUpdate called before initial transform for ${svelteRequest.id}`, + undefined, + 'hmr' + ); + return; + } + const { read, server, modules } = ctx; + + const cachedJS = cache.getJS(svelteRequest); + const cachedCss = cache.getCSS(svelteRequest); + + const content = await read(); + /** @type {import('./types/compile.d.ts').CompileData} */ + let compileData; + try { + compileData = await compileSvelte(svelteRequest, content, options); + cache.update(compileData); + } catch (e) { + cache.setError(svelteRequest, e); + throw toRollupError(e, options); + } + + const affectedModules = [...modules]; + + const cssIdx = modules.findIndex((m) => m.id === svelteRequest.cssId); + if (cssIdx > -1) { + const cssUpdated = cssChanged(cachedCss, compileData.compiled.css); + if (!cssUpdated) { + log.debug(`skipping unchanged css for ${svelteRequest.cssId}`, undefined, 'hmr'); + affectedModules.splice(cssIdx, 1); + } + } + const jsIdx = modules.findIndex((m) => m.id === svelteRequest.id); + if (jsIdx > -1) { + const jsUpdated = jsChanged(cachedJS, compileData.compiled.js, svelteRequest.filename); + if (!jsUpdated) { + log.debug(`skipping unchanged js for ${svelteRequest.id}`, undefined, 'hmr'); + affectedModules.splice(jsIdx, 1); + // transform won't be called, log warnings here + logCompilerWarnings(svelteRequest, compileData.compiled.warnings, options); + } + } + + // TODO is this enough? see also: https://github.com/vitejs/vite/issues/2274 + const ssrModulesToInvalidate = affectedModules.filter((m) => !!m.ssrTransformResult); + if (ssrModulesToInvalidate.length > 0) { + log.debug( + `invalidating modules ${ssrModulesToInvalidate.map((m) => m.id).join(', ')}`, + undefined, + 'hmr' + ); + ssrModulesToInvalidate.forEach((moduleNode) => server.moduleGraph.invalidateModule(moduleNode)); + } + if (affectedModules.length > 0) { + log.debug( + `handleHotUpdate for ${svelteRequest.id} result: ${affectedModules + .map((m) => m.id) + .join(', ')}`, + undefined, + 'hmr' + ); + } + return affectedModules; +} + +/** + * @param {import('./types/compile.d.ts').Code | null} [prev] + * @param {import('./types/compile.d.ts').Code | null} [next] + * @returns {boolean} + */ +function cssChanged(prev, next) { + return !isCodeEqual(prev?.code, next?.code); +} + +/** + * @param {import('./types/compile.d.ts').Code | null} [prev] + * @param {import('./types/compile.d.ts').Code | null} [next] + * @param {string} [filename] + * @returns {boolean} + */ +function jsChanged(prev, next, filename) { + const prevJs = prev?.code; + const nextJs = next?.code; + const isStrictEqual = isCodeEqual(prevJs, nextJs); + if (isStrictEqual) { + return false; + } + const isLooseEqual = isCodeEqual(normalizeJsCode(prevJs), normalizeJsCode(nextJs)); + if (!isStrictEqual && isLooseEqual) { + log.debug( + `ignoring compiler output js change for ${filename} as it is equal to previous output after normalization`, + undefined, + 'hmr' + ); + } + return !isLooseEqual; +} + +/** + * @param {string} [prev] + * @param {string} [next] + * @returns {boolean} + */ +function isCodeEqual(prev, next) { + if (!prev && !next) { + return true; + } + if ((!prev && next) || (prev && !next)) { + return false; + } + return prev === next; +} + +/** + * remove code that only changes metadata and does not require a js update for the component to keep working + * + * 1) add_location() calls. These add location metadata to elements, only used by some dev tools + * 2) ... maybe more (or less) in the future + * + * @param {string} [code] + * @returns {string | undefined} + */ +function normalizeJsCode(code) { + if (!code) { + return code; + } + return code.replace(/\s*\badd_location\s*\([^)]*\)\s*;?/g, ''); +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/index.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/index.js new file mode 100644 index 0000000..622a315 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/index.js @@ -0,0 +1,220 @@ +import fs from 'node:fs'; +import process from 'node:process'; +import { svelteInspector } from '@sveltejs/vite-plugin-svelte-inspector'; +import { handleHotUpdate } from './handle-hot-update.js'; +import { log, logCompilerWarnings } from './utils/log.js'; +import { createCompileSvelte } from './utils/compile.js'; +import { buildIdParser, buildModuleIdParser } from './utils/id.js'; +import { + buildExtraViteConfig, + validateInlineOptions, + resolveOptions, + patchResolvedViteConfig, + preResolveOptions +} from './utils/options.js'; +import { ensureWatchedFile, setupWatchers } from './utils/watch.js'; +import { toRollupError } from './utils/error.js'; +import { saveSvelteMetadata } from './utils/optimizer.js'; +import { VitePluginSvelteCache } from './utils/vite-plugin-svelte-cache.js'; +import { loadRaw } from './utils/load-raw.js'; +import * as svelteCompiler from 'svelte/compiler'; + +/** + * @param {Partial} [inlineOptions] + * @returns {import('vite').Plugin[]} + */ +export function svelte(inlineOptions) { + if (process.env.DEBUG != null) { + log.setLevel('debug'); + } + validateInlineOptions(inlineOptions); + const cache = new VitePluginSvelteCache(); + // updated in configResolved hook + /** @type {import('./types/id.d.ts').IdParser} */ + let requestParser; + /** @type {import('./types/id.d.ts').ModuleIdParser} */ + let moduleRequestParser; + /** @type {import('./types/options.d.ts').ResolvedOptions} */ + let options; + /** @type {import('vite').ResolvedConfig} */ + let viteConfig; + /** @type {import('./types/compile.d.ts').CompileSvelte} */ + let compileSvelte; + /** @type {import('./types/plugin-api.d.ts').PluginAPI} */ + const api = {}; + /** @type {import('vite').Plugin[]} */ + const plugins = [ + { + name: 'vite-plugin-svelte', + // make sure our resolver runs before vite internal resolver to resolve svelte field correctly + enforce: 'pre', + api, + async config(config, configEnv) { + // setup logger + if (process.env.DEBUG) { + log.setLevel('debug'); + } else if (config.logLevel) { + log.setLevel(config.logLevel); + } + // @ts-expect-error temporarily lend the options variable until fixed in configResolved + options = await preResolveOptions(inlineOptions, config, configEnv); + // extra vite config + const extraViteConfig = await buildExtraViteConfig(options, config); + log.debug('additional vite config', extraViteConfig, 'config'); + return extraViteConfig; + }, + + async configResolved(config) { + options = resolveOptions(options, config, cache); + patchResolvedViteConfig(config, options); + requestParser = buildIdParser(options); + compileSvelte = createCompileSvelte(); + viteConfig = config; + // TODO deep clone to avoid mutability from outside? + api.options = options; + log.debug('resolved options', options, 'config'); + }, + + async buildStart() { + if (!options.prebundleSvelteLibraries) return; + const isSvelteMetadataChanged = await saveSvelteMetadata(viteConfig.cacheDir, options); + if (isSvelteMetadataChanged) { + // Force Vite to optimize again. Although we mutate the config here, it works because + // Vite's optimizer runs after `buildStart()`. + viteConfig.optimizeDeps.force = true; + } + }, + + configureServer(server) { + options.server = server; + setupWatchers(options, cache, requestParser); + }, + + async load(id, opts) { + const ssr = !!opts?.ssr; + const svelteRequest = requestParser(id, !!ssr); + if (svelteRequest) { + const { filename, query, raw } = svelteRequest; + if (raw) { + const code = await loadRaw(svelteRequest, compileSvelte, options); + // prevent vite from injecting sourcemaps in the results. + return { + code, + map: { + mappings: '' + } + }; + } else { + if (query.svelte && query.type === 'style') { + const css = cache.getCSS(svelteRequest); + if (css) { + return css; + } + } + // prevent vite asset plugin from loading files as url that should be compiled in transform + if (viteConfig.assetsInclude(filename)) { + log.debug(`load returns raw content for ${filename}`, undefined, 'load'); + return fs.readFileSync(filename, 'utf-8'); + } + } + } + }, + + async resolveId(importee, importer, opts) { + const ssr = !!opts?.ssr; + const svelteRequest = requestParser(importee, ssr); + if (svelteRequest?.query.svelte) { + if (svelteRequest.query.type === 'style' && !svelteRequest.raw) { + // return cssId with root prefix so postcss pipeline of vite finds the directory correctly + // see https://github.com/sveltejs/vite-plugin-svelte/issues/14 + log.debug( + `resolveId resolved virtual css module ${svelteRequest.cssId}`, + undefined, + 'resolve' + ); + return svelteRequest.cssId; + } + } + }, + + async transform(code, id, opts) { + const ssr = !!opts?.ssr; + const svelteRequest = requestParser(id, ssr); + if (!svelteRequest || svelteRequest.query.type === 'style' || svelteRequest.raw) { + return; + } + let compileData; + try { + compileData = await compileSvelte(svelteRequest, code, options); + } catch (e) { + cache.setError(svelteRequest, e); + throw toRollupError(e, options); + } + logCompilerWarnings(svelteRequest, compileData.compiled.warnings, options); + cache.update(compileData); + if (compileData.dependencies?.length) { + if (options.server) { + for (const dep of compileData.dependencies) { + ensureWatchedFile(options.server.watcher, dep, options.root); + } + } else if (options.isBuild && viteConfig.build.watch) { + for (const dep of compileData.dependencies) { + this.addWatchFile(dep); + } + } + } + return { + ...compileData.compiled.js, + meta: { + vite: { + lang: compileData.lang + } + } + }; + }, + + handleHotUpdate(ctx) { + if (!options.compilerOptions.hmr || !options.emitCss) { + return; + } + const svelteRequest = requestParser(ctx.file, false, ctx.timestamp); + if (svelteRequest) { + return handleHotUpdate(compileSvelte, ctx, svelteRequest, cache, options); + } + }, + async buildEnd() { + await options.stats?.finishAll(); + } + }, + { + name: 'vite-plugin-svelte-module', + enforce: 'post', + async configResolved() { + moduleRequestParser = buildModuleIdParser(options); + }, + async transform(code, id, opts) { + const ssr = !!opts?.ssr; + const moduleRequest = moduleRequestParser(id, ssr); + if (!moduleRequest) { + return; + } + try { + const compileResult = svelteCompiler.compileModule(code, { + dev: !viteConfig.isProduction, + generate: ssr ? 'server' : 'client', + filename: moduleRequest.filename + }); + logCompilerWarnings(moduleRequest, compileResult.warnings, options); + return compileResult.js; + } catch (e) { + throw toRollupError(e, options); + } + } + }, + svelteInspector() + ]; + return plugins; +} + +export { vitePreprocess } from './preprocess.js'; +export { loadSvelteConfig } from './utils/load-svelte-config.js'; diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/preprocess.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/preprocess.js new file mode 100644 index 0000000..d63ea23 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/preprocess.js @@ -0,0 +1,124 @@ +import process from 'node:process'; +import { isCSSRequest, preprocessCSS, resolveConfig, transformWithEsbuild } from 'vite'; +import { mapToRelative, removeLangSuffix } from './utils/sourcemaps.js'; + +/** + * @typedef {(code: string, filename: string) => Promise<{ code: string; map?: any; deps?: Set }>} CssTransform + */ + +const supportedScriptLangs = ['ts']; + +export const lang_sep = '.vite-preprocess'; + +/** + * @param {import('./public.d.ts').VitePreprocessOptions} [opts] + * @returns {import('svelte/compiler').PreprocessorGroup} + */ +export function vitePreprocess(opts) { + /** @type {import('svelte/compiler').PreprocessorGroup} */ + const preprocessor = { name: 'vite-preprocess' }; + if (opts?.script === true) { + preprocessor.script = viteScript().script; + } + if (opts?.style !== false) { + const styleOpts = typeof opts?.style == 'object' ? opts?.style : undefined; + preprocessor.style = viteStyle(styleOpts).style; + } + return preprocessor; +} + +/** + * @returns {{ script: import('svelte/compiler').Preprocessor }} + */ +function viteScript() { + return { + async script({ attributes, content, filename = '' }) { + const lang = /** @type {string} */ (attributes.lang); + if (!supportedScriptLangs.includes(lang)) return; + const { code, map } = await transformWithEsbuild(content, filename, { + loader: /** @type {import('vite').ESBuildOptions['loader']} */ (lang), + target: 'esnext', + tsconfigRaw: { + compilerOptions: { + // svelte typescript needs this flag to work with type imports + importsNotUsedAsValues: 'preserve', + preserveValueImports: true + } + } + }); + + mapToRelative(map, filename); + + return { + code, + map + }; + } + }; +} + +/** + * @param {import('vite').ResolvedConfig | import('vite').InlineConfig} config + * @returns {{ style: import('svelte/compiler').Preprocessor }} + */ +function viteStyle(config = {}) { + /** @type {Promise | CssTransform} */ + let cssTransform; + /** @type {import('svelte/compiler').Preprocessor} */ + const style = async ({ attributes, content, filename = '' }) => { + const ext = attributes.lang ? `.${attributes.lang}` : '.css'; + if (attributes.lang && !isCSSRequest(ext)) return; + if (!cssTransform) { + cssTransform = createCssTransform(style, config).then((t) => (cssTransform = t)); + } + const transform = await cssTransform; + const suffix = `${lang_sep}${ext}`; + const moduleId = `${filename}${suffix}`; + const { code, map, deps } = await transform(content, moduleId); + removeLangSuffix(map, suffix); + mapToRelative(map, filename); + const dependencies = deps ? Array.from(deps).filter((d) => !d.endsWith(suffix)) : undefined; + return { + code, + map: map ?? undefined, + dependencies + }; + }; + // @ts-expect-error tag so can be found by v-p-s + style.__resolvedConfig = null; + return { style }; +} + +/** + * @param {import('svelte/compiler').Preprocessor} style + * @param {import('vite').ResolvedConfig | import('vite').InlineConfig} config + * @returns {Promise} + */ +async function createCssTransform(style, config) { + /** @type {import('vite').ResolvedConfig} */ + let resolvedConfig; + // @ts-expect-error special prop added if running in v-p-s + if (style.__resolvedConfig) { + // @ts-expect-error not typed + resolvedConfig = style.__resolvedConfig; + } else if (isResolvedConfig(config)) { + resolvedConfig = config; + } else { + // default to "build" if no NODE_ENV is set to avoid running in dev mode for svelte-check etc. + const useBuild = !process.env.NODE_ENV || process.env.NODE_ENV === 'production'; + const command = useBuild ? 'build' : 'serve'; + const defaultMode = useBuild ? 'production' : 'development'; + resolvedConfig = await resolveConfig(config, command, defaultMode, defaultMode, false); + } + return async (code, filename) => { + return preprocessCSS(code, filename, resolvedConfig); + }; +} + +/** + * @param {any} config + * @returns {config is import('vite').ResolvedConfig} + */ +function isResolvedConfig(config) { + return !!config.inlineConfig; +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/public.d.ts b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/public.d.ts new file mode 100644 index 0000000..6335e1a --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/public.d.ts @@ -0,0 +1,210 @@ +import type { InlineConfig, ResolvedConfig } from 'vite'; +import type { CompileOptions, Warning, PreprocessorGroup } from 'svelte/compiler'; +import type { Options as InspectorOptions } from '@sveltejs/vite-plugin-svelte-inspector'; + +export type Options = Omit & PluginOptionsInline; + +interface PluginOptionsInline extends PluginOptions { + /** + * Path to a svelte config file, either absolute or relative to Vite root + * + * set to `false` to ignore the svelte config file + * + * @see https://vitejs.dev/config/#root + */ + configFile?: string | false; +} + +export interface PluginOptions { + /** + * A `picomatch` pattern, or array of patterns, which specifies the files the plugin should + * operate on. By default, all svelte files are included. + * + * @see https://github.com/micromatch/picomatch + */ + include?: Arrayable; + /** + * A `picomatch` pattern, or array of patterns, which specifies the files to be ignored by the + * plugin. By default, no files are ignored. + * + * @see https://github.com/micromatch/picomatch + */ + exclude?: Arrayable; + /** + * Emit Svelte styles as virtual CSS files for Vite and other plugins to process + * + * @default true + */ + emitCss?: boolean; + /** + * Enable or disable Hot Module Replacement. + * Deprecated, use compilerOptions.hmr instead! + * + * @deprecated + * @default true for development, always false for production + */ + hot?: boolean; + + /** + * Some Vite plugins can contribute additional preprocessors by defining `api.sveltePreprocess`. + * If you don't want to use them, set this to true to ignore them all or use an array of strings + * with plugin names to specify which. + * + * @default false + */ + ignorePluginPreprocessors?: boolean | string[]; + /** + * vite-plugin-svelte automatically handles excluding svelte libraries and reinclusion of their dependencies + * in vite.optimizeDeps. + * + * `disableDependencyReinclusion: true` disables all reinclusions + * `disableDependencyReinclusion: ['foo','bar']` disables reinclusions for dependencies of foo and bar + * + * This should be used for hybrid packages that contain both node and browser dependencies, eg Routify + * + * @default false + */ + disableDependencyReinclusion?: boolean | string[]; + /** + * Enable support for Vite's dependency optimization to prebundle Svelte libraries. + * + * To disable prebundling for a specific library, add it to `optimizeDeps.exclude`. + * + * @default true for dev, false for build + */ + prebundleSvelteLibraries?: boolean; + /** + * toggle/configure Svelte Inspector + * + * @default unset for dev, always false for build + */ + inspector?: InspectorOptions | boolean; + + /** + * A function to update `compilerOptions` before compilation + * + * `data.filename` - The file to be compiled + * `data.code` - The preprocessed Svelte code + * `data.compileOptions` - The current compiler options + * + * To change part of the compiler options, return an object with the changes you need. + * + * @example + * ``` + * ({ filename, compileOptions }) => { + * // Dynamically set runes mode per Svelte file + * if (forceRunesMode(filename) && !compileOptions.runes) { + * return { runes: true }; + * } + * } + * ``` + */ + dynamicCompileOptions?: (data: { + filename: string; + code: string; + compileOptions: Partial; + }) => Promise | void> | Partial | void; + + /** + * These options are considered experimental and breaking changes to them can occur in any release + */ + experimental?: ExperimentalOptions; +} + +export interface SvelteConfig { + /** + * A list of file extensions to be compiled by Svelte + * + * @default ['.svelte'] + */ + extensions?: string[]; + /** + * An array of preprocessors to transform the Svelte source code before compilation + * + * @see https://svelte.dev/docs#svelte_preprocess + */ + preprocess?: Arrayable; + /** + * The options to be passed to the Svelte compiler. A few options are set by default, + * including `dev` and `css`. However, some options are non-configurable, like + * `filename`, `format`, `generate`, and `cssHash` (in dev). + * + * @see https://svelte.dev/docs#svelte_compile + */ + compilerOptions?: Omit; + + /** + * Handles warning emitted from the Svelte compiler + * + * warnings emitted for files in node_modules are logged at the debug level, to see them run + * `DEBUG=vite-plugin-svelte:node-modules-onwarn pnpm build` + * + * @example + * ``` + * (warning, defaultHandler) => { + * // ignore some warnings + * if (!['foo','bar'].includes(warning.code)) { + * defaultHandler(warning); + * } + * } + * ``` + * + */ + onwarn?: (warning: Warning, defaultHandler: (warning: Warning) => void) => void; + /** + * Options for vite-plugin-svelte + */ + vitePlugin?: PluginOptions; +} + +/** + * These options are considered experimental and breaking changes to them can occur in any release + */ +interface ExperimentalOptions { + /** + * send a websocket message with svelte compiler warnings during dev + * + */ + sendWarningsToBrowser?: boolean; + /** + * disable svelte field resolve warnings + * + * @default false + */ + disableSvelteResolveWarnings?: boolean; + + compileModule?: CompileModuleOptions; +} + +interface CompileModuleOptions { + /** + * infix that must be present in filename + * @default ['.svelte.'] + */ + infixes?: string[]; + /** + * module extensions + * @default ['.ts','.js'] + */ + extensions?: string[]; + include?: Arrayable; + exclude?: Arrayable; +} + +type Arrayable = T | T[]; + +export interface VitePreprocessOptions { + /** + * preprocess script block with vite pipeline. + * Since svelte5 this is not needed for typescript anymore + * + * @default false + */ + script?: boolean; + /** + * preprocess style blocks with vite pipeline + */ + style?: boolean | InlineConfig | ResolvedConfig; +} +// eslint-disable-next-line n/no-missing-import +export * from './index.js'; diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/compile.d.ts b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/compile.d.ts new file mode 100644 index 0000000..d6ba48e --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/compile.d.ts @@ -0,0 +1,25 @@ +import type { Processed, CompileResult } from 'svelte/compiler'; +import type { SvelteRequest } from './id.d.ts'; +import type { ResolvedOptions } from './options.d.ts'; + +export type CompileSvelte = ( + svelteRequest: SvelteRequest, + code: string, + options: Partial +) => Promise; + +export interface Code { + code: string; + map?: any; + dependencies?: any[]; +} + +export interface CompileData { + filename: string; + normalizedFilename: string; + lang: string; + compiled: CompileResult; + ssr: boolean | undefined; + dependencies: string[]; + preprocessed: Processed; +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/id.d.ts b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/id.d.ts new file mode 100644 index 0000000..25ff361 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/id.d.ts @@ -0,0 +1,45 @@ +import type { CompileOptions } from 'svelte/compiler'; + +export type SvelteQueryTypes = 'style' | 'script' | 'preprocessed' | 'all'; + +export interface RequestQuery { + // our own + svelte?: boolean; + type?: SvelteQueryTypes; + sourcemap?: boolean; + compilerOptions?: Pick< + CompileOptions, + 'generate' | 'dev' | 'css' | 'customElement' | 'immutable' + >; + // vite specific + url?: boolean; + raw?: boolean; + direct?: boolean; +} + +export interface SvelteRequest { + id: string; + cssId: string; + filename: string; + normalizedFilename: string; + query: RequestQuery; + timestamp: number; + ssr: boolean; + raw: boolean; +} + +export interface SvelteModuleRequest { + id: string; + filename: string; + normalizedFilename: string; + query: RequestQuery; + timestamp: number; + ssr: boolean; +} + +export type IdParser = (id: string, ssr: boolean, timestamp?: number) => SvelteRequest | undefined; +export type ModuleIdParser = ( + id: string, + ssr: boolean, + timestamp?: number +) => SvelteModuleRequest | undefined; diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/log.d.ts b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/log.d.ts new file mode 100644 index 0000000..fd4f13e --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/log.d.ts @@ -0,0 +1,24 @@ +import type { Warning } from 'svelte/compiler'; + +export interface LogFn extends SimpleLogFn { + (message: string, payload?: unknown, namespace?: string): void; + + enabled: boolean; + once: SimpleLogFn; +} + +export interface SimpleLogFn { + (message: string, payload?: unknown, namespace?: string): void; +} + +export type SvelteWarningsMessage = { + id: string; + filename: string; + normalizedFilename: string; + timestamp: number; + warnings: Warning[]; // allWarnings filtered by warnings where onwarn did not call the default handler + allWarnings: Warning[]; // includes warnings filtered by onwarn and our extra vite plugin svelte warnings + rawWarnings: Warning[]; // raw compiler output +}; + +export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'; diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/options.d.ts b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/options.d.ts new file mode 100644 index 0000000..5b4ca42 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/options.d.ts @@ -0,0 +1,21 @@ +import type { CompileOptions } from 'svelte/compiler'; +import type { ViteDevServer } from 'vite'; +// eslint-disable-next-line n/no-missing-import +import { VitePluginSvelteStats } from '../utils/vite-plugin-svelte-stats.js'; +import type { Options } from '../public.d.ts'; + +export interface PreResolvedOptions extends Options { + // these options are non-nullable after resolve + compilerOptions: CompileOptions; + // extra options + root: string; + isBuild: boolean; + isServe: boolean; + isDebug: boolean; +} + +export interface ResolvedOptions extends PreResolvedOptions { + isProduction: boolean; + server?: ViteDevServer; + stats?: VitePluginSvelteStats; +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/plugin-api.d.ts b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/plugin-api.d.ts new file mode 100644 index 0000000..36c42b6 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/plugin-api.d.ts @@ -0,0 +1,11 @@ +import type { ResolvedOptions } from './options.d.ts'; + +export interface PluginAPI { + /** + * must not be modified, should not be used outside of vite-plugin-svelte repo + * @internal + * @experimental + */ + options?: ResolvedOptions; + // TODO expose compile cache here so other utility plugins can use it +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/vite-plugin-svelte-stats.d.ts b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/vite-plugin-svelte-stats.d.ts new file mode 100644 index 0000000..1b69ebd --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/types/vite-plugin-svelte-stats.d.ts @@ -0,0 +1,30 @@ +export interface Stat { + file: string; + pkg?: string; + start: number; + end: number; +} + +export interface StatCollection { + name: string; + options: CollectionOptions; + + start: (file: string) => () => void; + stats: Stat[]; + packageStats?: PackageStats[]; + collectionStart: number; + duration?: number; + finish: () => Promise | void; + finished: boolean; +} + +export interface PackageStats { + pkg: string; + files: number; + duration: number; +} + +export interface CollectionOptions { + logInProgress: (collection: StatCollection, now: number) => boolean; + logResult: (collection: StatCollection) => boolean; +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/compile.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/compile.js new file mode 100644 index 0000000..4c0e524 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/compile.js @@ -0,0 +1,191 @@ +import * as svelte from 'svelte/compiler'; + +import { safeBase64Hash } from './hash.js'; +import { log } from './log.js'; + +import { + checkPreprocessDependencies, + createInjectScopeEverythingRulePreprocessorGroup +} from './preprocess.js'; +import { mapToRelative } from './sourcemaps.js'; +import { enhanceCompileError } from './error.js'; + +// TODO this is a patched version of https://github.com/sveltejs/vite-plugin-svelte/pull/796/files#diff-3bce0b33034aad4b35ca094893671f7e7ddf4d27254ae7b9b0f912027a001b15R10 +// which is closer to the other regexes in at least not falling into commented script +// but ideally would be shared exactly with svelte and other tools that use it +const scriptLangRE = + /|]*|(?:[^=>'"/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)\s+)*)lang=(["'])?([^"' >]+)\1[^>]*>/g; + +/** + * @returns {import('../types/compile.d.ts').CompileSvelte} + */ +export function createCompileSvelte() { + /** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection | undefined} */ + let stats; + const devStylePreprocessor = createInjectScopeEverythingRulePreprocessorGroup(); + /** @type {import('../types/compile.d.ts').CompileSvelte} */ + return async function compileSvelte(svelteRequest, code, options) { + const { filename, normalizedFilename, cssId, ssr, raw } = svelteRequest; + const { emitCss = true } = options; + /** @type {string[]} */ + const dependencies = []; + /** @type {import('svelte/compiler').Warning[]} */ + const warnings = []; + + if (options.stats) { + if (options.isBuild) { + if (!stats) { + // build is either completely ssr or csr, create stats collector on first compile + // it is then finished in the buildEnd hook. + stats = options.stats.startCollection(`${ssr ? 'ssr' : 'dom'} compile`, { + logInProgress: () => false + }); + } + } else { + // dev time ssr, it's a ssr request and there are no stats, assume new page load and start collecting + if (ssr && !stats) { + stats = options.stats.startCollection('ssr compile'); + } + // stats are being collected but this isn't an ssr request, assume page loaded and stop collecting + if (!ssr && stats) { + stats.finish(); + stats = undefined; + } + // TODO find a way to trace dom compile during dev + // problem: we need to call finish at some point but have no way to tell if page load finished + // also they for hmr updates too + } + } + /** @type {import('svelte/compiler').CompileOptions} */ + const compileOptions = { + ...options.compilerOptions, + filename, + generate: ssr ? 'server' : 'client' + }; + + if (compileOptions.hmr && options.emitCss) { + const hash = `s-${safeBase64Hash(normalizedFilename)}`; + compileOptions.cssHash = () => hash; + } + + let preprocessed; + let preprocessors = options.preprocess; + if (!options.isBuild && options.emitCss && compileOptions.hmr) { + // inject preprocessor that ensures css hmr works better + if (!Array.isArray(preprocessors)) { + preprocessors = preprocessors + ? [preprocessors, devStylePreprocessor] + : [devStylePreprocessor]; + } else { + preprocessors = preprocessors.concat(devStylePreprocessor); + } + } + if (preprocessors) { + try { + preprocessed = await svelte.preprocess(code, preprocessors, { filename }); // full filename here so postcss works + } catch (e) { + e.message = `Error while preprocessing ${filename}${e.message ? ` - ${e.message}` : ''}`; + throw e; + } + + if (preprocessed.dependencies?.length) { + const checked = checkPreprocessDependencies(filename, preprocessed.dependencies); + if (checked.warnings.length) { + warnings.push(...checked.warnings); + } + if (checked.dependencies.length) { + dependencies.push(...checked.dependencies); + } + } + + if (preprocessed.map) compileOptions.sourcemap = preprocessed.map; + } + if (typeof preprocessed?.map === 'object') { + mapToRelative(preprocessed?.map, filename); + } + if (raw && svelteRequest.query.type === 'preprocessed') { + // @ts-expect-error shortcut + return /** @type {import('../types/compile.d.ts').CompileData} */ { + preprocessed: preprocessed ?? { code } + }; + } + const finalCode = preprocessed ? preprocessed.code : code; + const dynamicCompileOptions = await options?.dynamicCompileOptions?.({ + filename, + code: finalCode, + compileOptions + }); + if (dynamicCompileOptions && log.debug.enabled) { + log.debug( + `dynamic compile options for ${filename}: ${JSON.stringify(dynamicCompileOptions)}`, + undefined, + 'compile' + ); + } + const finalCompileOptions = dynamicCompileOptions + ? { + ...compileOptions, + ...dynamicCompileOptions + } + : compileOptions; + const endStat = stats?.start(filename); + /** @type {import('svelte/compiler').CompileResult} */ + let compiled; + try { + compiled = svelte.compile(finalCode, { ...finalCompileOptions, filename }); + // patch output with partial accept until svelte does it + // TODO remove later + if ( + options.server?.config.experimental.hmrPartialAccept && + compiled.js.code.includes('import.meta.hot.accept(') + ) { + compiled.js.code = compiled.js.code.replaceAll( + 'import.meta.hot.accept(', + 'import.meta.hot.acceptExports(["default"],' + ); + } + } catch (e) { + enhanceCompileError(e, code, preprocessors); + throw e; + } + + if (endStat) { + endStat(); + } + mapToRelative(compiled.js?.map, filename); + mapToRelative(compiled.css?.map, filename); + if (warnings.length) { + if (!compiled.warnings) { + compiled.warnings = []; + } + compiled.warnings.push(...warnings); + } + if (!raw) { + // wire css import and code for hmr + const hasCss = compiled.css?.code?.trim()?.length ?? 0 > 0; + // compiler might not emit css with mode none or it may be empty + if (emitCss && hasCss) { + // TODO properly update sourcemap? + compiled.js.code += `\nimport ${JSON.stringify(cssId)};\n`; + } + } + + let lang = 'js'; + for (const match of code.matchAll(scriptLangRE)) { + if (match[2]) { + lang = match[2]; + break; + } + } + + return { + filename, + normalizedFilename, + lang, + compiled, + ssr, + dependencies, + preprocessed: preprocessed ?? { code } + }; + }; +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/constants.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/constants.js new file mode 100644 index 0000000..9e251ea --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/constants.js @@ -0,0 +1,30 @@ +import { createRequire } from 'node:module'; + +export const VITE_RESOLVE_MAIN_FIELDS = ['browser', 'module', 'jsnext:main', 'jsnext']; + +export const SVELTE_RESOLVE_MAIN_FIELDS = ['svelte']; + +export const SVELTE_IMPORTS = Object.entries( + createRequire(import.meta.url)('svelte/package.json').exports +) + .map(([name, config]) => { + // ignore type only + if (typeof config === 'object' && Object.keys(config).length === 1 && config.types) { + return ''; + } + // ignore names + if (name === './package.json' || name === './compiler') { + return ''; + } + return name.replace(/^\./, 'svelte'); + }) + .filter((s) => s.length > 0); + +export const SVELTE_EXPORT_CONDITIONS = ['svelte']; + +export const FAQ_LINK_MISSING_EXPORTS_CONDITION = + 'https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#missing-exports-condition'; + +export const DEFAULT_SVELTE_EXT = ['.svelte']; +export const DEFAULT_SVELTE_MODULE_INFIX = ['.svelte.']; +export const DEFAULT_SVELTE_MODULE_EXT = ['.js', '.ts']; diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/dependencies.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/dependencies.js new file mode 100644 index 0000000..30caf59 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/dependencies.js @@ -0,0 +1,89 @@ +import path from 'node:path'; +import fs from 'node:fs/promises'; +import { findDepPkgJsonPath } from 'vitefu'; + +/** + * @typedef {{ + * dir: string; + * pkg: Record; + * }} DependencyData + */ + +/** + * @param {string} dep + * @param {string} parent + * @returns {Promise} + */ +export async function resolveDependencyData(dep, parent) { + const depDataPath = await findDepPkgJsonPath(dep, parent); + if (!depDataPath) return undefined; + try { + return { + dir: path.dirname(depDataPath), + pkg: JSON.parse(await fs.readFile(depDataPath, 'utf-8')) + }; + } catch { + return undefined; + } +} + +const COMMON_DEPENDENCIES_WITHOUT_SVELTE_FIELD = [ + '@lukeed/uuid', + '@playwright/test', + '@sveltejs/kit', + '@sveltejs/package', + '@sveltejs/vite-plugin-svelte', + 'autoprefixer', + 'cookie', + 'dotenv', + 'esbuild', + 'eslint', + 'jest', + 'mdsvex', + 'playwright', + 'postcss', + 'prettier', + 'svelte', + 'svelte2tsx', + 'svelte-check', + 'svelte-preprocess', + 'tslib', + 'typescript', + 'vite', + 'vitest', + '__vite-browser-external' // see https://github.com/sveltejs/vite-plugin-svelte/issues/362 +]; +const COMMON_PREFIXES_WITHOUT_SVELTE_FIELD = [ + '@fontsource/', + '@postcss-plugins/', + '@rollup/', + '@sveltejs/adapter-', + '@types/', + '@typescript-eslint/', + 'eslint-', + 'jest-', + 'postcss-plugin-', + 'prettier-plugin-', + 'rollup-plugin-', + 'vite-plugin-' +]; + +/** + * Test for common dependency names that tell us it is not a package including a svelte field, eg. eslint + plugins. + * + * This speeds up the find process as we don't have to try and require the package.json for all of them + * + * @param {string} dependency + * @returns {boolean} true if it is a dependency without a svelte field + */ +export function isCommonDepWithoutSvelteField(dependency) { + return ( + COMMON_DEPENDENCIES_WITHOUT_SVELTE_FIELD.includes(dependency) || + COMMON_PREFIXES_WITHOUT_SVELTE_FIELD.some( + (prefix) => + prefix.startsWith('@') + ? dependency.startsWith(prefix) + : dependency.substring(dependency.lastIndexOf('/') + 1).startsWith(prefix) // check prefix omitting @scope/ + ) + ); +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/error.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/error.js new file mode 100644 index 0000000..31e3c5a --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/error.js @@ -0,0 +1,162 @@ +import { buildExtendedLogMessage } from './log.js'; + +/** + * convert an error thrown by svelte.compile to a RollupError so that vite displays it in a user friendly way + * @param {import('svelte/compiler').Warning & Error & {frame?: string}} error a svelte compiler error, which is a mix of Warning and an error + * @param {import('../types/options.d.ts').ResolvedOptions} options + * @returns {import('vite').Rollup.RollupError} the converted error + */ +export function toRollupError(error, options) { + const { filename, frame, start, code, name, stack } = error; + /** @type {import('vite').Rollup.RollupError} */ + const rollupError = { + name, // needed otherwise sveltekit coalesce_to_error turns it into a string + id: filename, + message: buildExtendedLogMessage(error), // include filename:line:column so that it's clickable + frame: formatFrameForVite(frame), + code, + stack: options.isBuild || options.isDebug || !frame ? stack : '' + }; + if (start) { + rollupError.loc = { + line: start.line, + column: start.column, + file: filename + }; + } + return rollupError; +} + +/** + * convert an error thrown by svelte.compile to an esbuild PartialMessage + * @param {import('svelte/compiler').Warning & Error & {frame?: string}} error a svelte compiler error, which is a mix of Warning and an error + * @param {import('../types/options.d.ts').ResolvedOptions} options + * @returns {import('esbuild').PartialMessage} the converted error + */ +export function toESBuildError(error, options) { + const { filename, frame, start, stack } = error; + /** @type {import('esbuild').PartialMessage} */ + const partialMessage = { + text: buildExtendedLogMessage(error) + }; + if (start) { + partialMessage.location = { + line: start.line, + column: start.column, + file: filename, + lineText: lineFromFrame(start.line, frame) // needed to get a meaningful error message on cli + }; + } + if (options.isBuild || options.isDebug || !frame) { + partialMessage.detail = stack; + } + return partialMessage; +} + +/** + * extract line with number from codeframe + * + * @param {number} lineNo + * @param {string} [frame] + * @returns {string} + */ +function lineFromFrame(lineNo, frame) { + if (!frame) { + return ''; + } + const lines = frame.split('\n'); + const errorLine = lines.find((line) => line.trimStart().startsWith(`${lineNo}: `)); + return errorLine ? errorLine.substring(errorLine.indexOf(': ') + 3) : ''; +} + +/** + * vite error overlay expects a specific format to show frames + * this reformats svelte frame (colon separated, less whitespace) + * to one that vite displays on overlay ( pipe separated, more whitespace) + * e.g. + * ``` + * 1: foo + * 2: bar; + * ^ + * 3: baz + * ``` + * to + * ``` + * 1 | foo + * 2 | bar; + * ^ + * 3 | baz + * ``` + * @see https://github.com/vitejs/vite/blob/96591bf9989529de839ba89958755eafe4c445ae/packages/vite/src/client/overlay.ts#L116 + * @param {string} [frame] + * @returns {string} + */ +function formatFrameForVite(frame) { + if (!frame) { + return ''; + } + return frame + .split('\n') + .map((line) => (line.match(/^\s+\^/) ? ' ' + line : ' ' + line.replace(':', ' | '))) + .join('\n'); +} + +/** + * + * @param {string} code the svelte error code + * @see https://github.com/sveltejs/svelte/blob/main/packages/svelte/src/compiler/errors.js + * @returns {boolean} + */ +function couldBeFixedByCssPreprocessor(code) { + return code === 'expected_token' || code === 'unexpected_eof' || code?.startsWith('css_'); +} + +/** + * @param {import('svelte/compiler').Warning & Error} err a svelte compiler error, which is a mix of Warning and an error + * @param {string} originalCode + * @param {import('../public.d.ts').Options['preprocess']} [preprocessors] + */ +export function enhanceCompileError(err, originalCode, preprocessors) { + preprocessors = arraify(preprocessors ?? []); + + /** @type {string[]} */ + const additionalMessages = []; + + // Handle incorrect CSS preprocessor usage + if (couldBeFixedByCssPreprocessor(err.code)) { + // Reference from Svelte: https://github.com/sveltejs/svelte/blob/9926347ad9dbdd0f3324d5538e25dcb7f5e442f8/packages/svelte/src/compiler/preprocess/index.js#L257 + const styleRe = + /|'"/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/]+)*\s*)(?:\/>|>([\S\s]*?)<\/style>)/g; + + let m; + while ((m = styleRe.exec(originalCode))) { + // Warn missing lang attribute + if (!m[1]?.includes('lang=')) { + additionalMessages.push('Did you forget to add a lang attribute to your style tag?'); + } + // Warn missing style preprocessor + if ( + preprocessors.every((p) => p.style == null || p.name === 'inject-scope-everything-rule') + ) { + const preprocessorType = m[1]?.match(/lang="(.+?)"/)?.[1] ?? 'style'; + additionalMessages.push( + `Did you forget to add a ${preprocessorType} preprocessor? See https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/preprocess.md for more information.` + ); + } + } + } + + if (additionalMessages.length) { + err.message += '\n\n- ' + additionalMessages.join('\n- '); + } + + return err; +} + +/** + * @param {T | T[]} value + * @template T + */ +function arraify(value) { + return Array.isArray(value) ? value : [value]; +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/esbuild.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/esbuild.js new file mode 100644 index 0000000..5a1ca89 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/esbuild.js @@ -0,0 +1,177 @@ +import { readFileSync } from 'node:fs'; +import * as svelte from 'svelte/compiler'; +import { log } from './log.js'; +import { toESBuildError } from './error.js'; +import { safeBase64Hash } from './hash.js'; +import { normalize } from './id.js'; + +/** + * @typedef {NonNullable} EsbuildOptions + * @typedef {NonNullable[number]} EsbuildPlugin + */ + +export const facadeEsbuildSveltePluginName = 'vite-plugin-svelte:facade'; +export const facadeEsbuildSvelteModulePluginName = 'vite-plugin-svelte-module:facade'; + +/** + * @param {import('../types/options.d.ts').ResolvedOptions} options + * @returns {EsbuildPlugin} + */ +export function esbuildSveltePlugin(options) { + return { + name: 'vite-plugin-svelte:optimize-svelte', + setup(build) { + // Skip in scanning phase as Vite already handles scanning Svelte files. + // Otherwise this would heavily slow down the scanning phase. + if (build.initialOptions.plugins?.some((v) => v.name === 'vite:dep-scan')) return; + + const filter = /\.svelte(?:\?.*)?$/; + /** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection | undefined} */ + let statsCollection; + build.onStart(() => { + statsCollection = options.stats?.startCollection('prebundle library components', { + logResult: (c) => c.stats.length > 1 + }); + }); + build.onLoad({ filter }, async ({ path: filename }) => { + const code = readFileSync(filename, 'utf8'); + try { + const contents = await compileSvelte(options, { filename, code }, statsCollection); + return { contents }; + } catch (e) { + return { errors: [toESBuildError(e, options)] }; + } + }); + build.onEnd(() => { + statsCollection?.finish(); + }); + } + }; +} + +/** + * @param {import('../types/options.d.ts').ResolvedOptions} options + * @param {{ filename: string, code: string }} input + * @param {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection} [statsCollection] + * @returns {Promise} + */ +async function compileSvelte(options, { filename, code }, statsCollection) { + let css = options.compilerOptions.css; + if (css !== 'injected') { + // TODO ideally we'd be able to externalize prebundled styles too, but for now always put them in the js + css = 'injected'; + } + /** @type {import('svelte/compiler').CompileOptions} */ + const compileOptions = { + dev: true, // default to dev: true because prebundling is only used in dev + ...options.compilerOptions, + css, + filename, + generate: 'client' + }; + + if (compileOptions.hmr && options.emitCss) { + const hash = `s-${safeBase64Hash(normalize(filename, options.root))}`; + compileOptions.cssHash = () => hash; + } + + let preprocessed; + + if (options.preprocess) { + try { + preprocessed = await svelte.preprocess(code, options.preprocess, { filename }); + } catch (e) { + e.message = `Error while preprocessing ${filename}${e.message ? ` - ${e.message}` : ''}`; + throw e; + } + if (preprocessed.map) compileOptions.sourcemap = preprocessed.map; + } + + const finalCode = preprocessed ? preprocessed.code : code; + + const dynamicCompileOptions = await options?.dynamicCompileOptions?.({ + filename, + code: finalCode, + compileOptions + }); + + if (dynamicCompileOptions && log.debug.enabled) { + log.debug( + `dynamic compile options for ${filename}: ${JSON.stringify(dynamicCompileOptions)}`, + undefined, + 'compile' + ); + } + + const finalCompileOptions = dynamicCompileOptions + ? { + ...compileOptions, + ...dynamicCompileOptions + } + : compileOptions; + const endStat = statsCollection?.start(filename); + const compiled = svelte.compile(finalCode, finalCompileOptions); + if (endStat) { + endStat(); + } + return compiled.js.map + ? compiled.js.code + '//# sourceMappingURL=' + compiled.js.map.toUrl() + : compiled.js.code; +} + +/** + * @param {import('../types/options.d.ts').ResolvedOptions} options + * @returns {EsbuildPlugin} + */ +export function esbuildSvelteModulePlugin(options) { + return { + name: 'vite-plugin-svelte-module:optimize-svelte', + setup(build) { + // Skip in scanning phase as Vite already handles scanning Svelte files. + // Otherwise this would heavily slow down the scanning phase. + if (build.initialOptions.plugins?.some((v) => v.name === 'vite:dep-scan')) return; + + const filter = /\.svelte\.[jt]s(?:\?.*)?$/; + /** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection | undefined} */ + let statsCollection; + build.onStart(() => { + statsCollection = options.stats?.startCollection('prebundle library modules', { + logResult: (c) => c.stats.length > 1 + }); + }); + build.onLoad({ filter }, async ({ path: filename }) => { + const code = readFileSync(filename, 'utf8'); + try { + const contents = await compileSvelteModule(options, { filename, code }, statsCollection); + return { contents }; + } catch (e) { + return { errors: [toESBuildError(e, options)] }; + } + }); + build.onEnd(() => { + statsCollection?.finish(); + }); + } + }; +} + +/** + * @param {import('../types/options.d.ts').ResolvedOptions} options + * @param {{ filename: string; code: string }} input + * @param {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection} [statsCollection] + * @returns {Promise} + */ +async function compileSvelteModule(options, { filename, code }, statsCollection) { + const endStat = statsCollection?.start(filename); + const compiled = svelte.compileModule(code, { + dev: options.compilerOptions?.dev ?? true, // default to dev: true because prebundling is only used in dev + filename, + generate: 'client' + }); + if (endStat) { + endStat(); + } + return compiled.js.map + ? compiled.js.code + '//# sourceMappingURL=' + compiled.js.map.toUrl() + : compiled.js.code; +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/hash.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/hash.js new file mode 100644 index 0000000..6d0dad2 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/hash.js @@ -0,0 +1,43 @@ +import crypto from 'node:crypto'; + +const hashes = Object.create(null); + +//TODO shorter? +const hash_length = 12; + +/** + * replaces +/= in base64 output so they don't interfere + * + * @param {string} input + * @returns {string} base64 hash safe to use in any context + */ +export function safeBase64Hash(input) { + if (hashes[input]) { + return hashes[input]; + } + //TODO if performance really matters, use a faster one like xx-hash etc. + // should be evenly distributed because short input length and similarities in paths could cause collisions otherwise + // OR DON'T USE A HASH AT ALL, what about a simple counter? + const md5 = crypto.createHash('md5'); + md5.update(input); + const hash = toSafe(md5.digest('base64')).slice(0, hash_length); + hashes[input] = hash; + return hash; +} + +/** @type {Record} */ +const replacements = { + '+': '-', + '/': '_', + '=': '' +}; + +const replaceRE = new RegExp(`[${Object.keys(replacements).join('')}]`, 'g'); + +/** + * @param {string} base64 + * @returns {string} + */ +function toSafe(base64) { + return base64.replace(replaceRE, (x) => replacements[x]); +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/id.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/id.js new file mode 100644 index 0000000..cb420dd --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/id.js @@ -0,0 +1,252 @@ +import { createFilter, normalizePath } from 'vite'; +import fs from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; +import { log } from './log.js'; +import { DEFAULT_SVELTE_MODULE_EXT, DEFAULT_SVELTE_MODULE_INFIX } from './constants.js'; + +const VITE_FS_PREFIX = '/@fs/'; +const IS_WINDOWS = process.platform === 'win32'; + +const SUPPORTED_COMPILER_OPTIONS = ['generate', 'dev', 'css', 'customElement', 'immutable']; +const TYPES_WITH_COMPILER_OPTIONS = ['style', 'script', 'all']; + +/** + * @param {string} id + * @returns {{ filename: string, rawQuery: string }} + */ +function splitId(id) { + const parts = id.split('?', 2); + const filename = parts[0]; + const rawQuery = parts[1]; + return { filename, rawQuery }; +} + +/** + * @param {string} id + * @param {string} filename + * @param {string} rawQuery + * @param {string} root + * @param {number} timestamp + * @param {boolean} ssr + * @returns {import('../types/id.d.ts').SvelteRequest | undefined} + */ +function parseToSvelteRequest(id, filename, rawQuery, root, timestamp, ssr) { + const query = parseRequestQuery(rawQuery); + const rawOrDirect = !!(query.raw || query.direct); + if (query.url || (!query.svelte && rawOrDirect)) { + // skip requests with special vite tags + return; + } + const raw = rawOrDirect; + const normalizedFilename = normalize(filename, root); + const cssId = createVirtualImportId(filename, root, 'style'); + + return { + id, + filename, + normalizedFilename, + cssId, + query, + timestamp, + ssr, + raw + }; +} + +/** + * @param {string} filename + * @param {string} root + * @param {import('../types/id.d.ts').SvelteQueryTypes} type + * @returns {string} + */ +function createVirtualImportId(filename, root, type) { + const parts = ['svelte', `type=${type}`]; + if (type === 'style') { + parts.push('lang.css'); + } + if (existsInRoot(filename, root)) { + filename = root + filename; + } else if (filename.startsWith(VITE_FS_PREFIX)) { + filename = IS_WINDOWS + ? filename.slice(VITE_FS_PREFIX.length) // remove /@fs/ from /@fs/C:/... + : filename.slice(VITE_FS_PREFIX.length - 1); // remove /@fs from /@fs/home/user + } + // return same virtual id format as vite-plugin-vue eg ...App.svelte?svelte&type=style&lang.css + return `${filename}?${parts.join('&')}`; +} + +/** + * @param {string} rawQuery + * @returns {import('../types/id.d.ts').RequestQuery} + */ +function parseRequestQuery(rawQuery) { + const query = Object.fromEntries(new URLSearchParams(rawQuery)); + for (const key in query) { + if (query[key] === '') { + // @ts-expect-error not boolean + query[key] = true; + } + } + const compilerOptions = query.compilerOptions; + if (compilerOptions) { + if (!((query.raw || query.direct) && TYPES_WITH_COMPILER_OPTIONS.includes(query.type))) { + throw new Error( + `Invalid compilerOptions in query ${rawQuery}. CompilerOptions are only supported for raw or direct queries with type in "${TYPES_WITH_COMPILER_OPTIONS.join( + ', ' + )}" e.g. '?svelte&raw&type=script&compilerOptions={"generate":"server","dev":false}` + ); + } + try { + const parsed = JSON.parse(compilerOptions); + const invalid = Object.keys(parsed).filter( + (key) => !SUPPORTED_COMPILER_OPTIONS.includes(key) + ); + if (invalid.length) { + throw new Error( + `Invalid compilerOptions in query ${rawQuery}: ${invalid.join( + ', ' + )}. Supported: ${SUPPORTED_COMPILER_OPTIONS.join(', ')}` + ); + } + query.compilerOptions = parsed; + } catch (e) { + log.error('failed to parse request query compilerOptions', e); + throw e; + } + } + + return /** @type {import('../types/id.d.ts').RequestQuery}*/ query; +} + +/** + * posixify and remove root at start + * + * @param {string} filename + * @param {string} normalizedRoot + * @returns {string} + */ +export function normalize(filename, normalizedRoot) { + return stripRoot(normalizePath(filename), normalizedRoot); +} + +/** + * @param {string} filename + * @param {string} root + * @returns {boolean} + */ +function existsInRoot(filename, root) { + if (filename.startsWith(VITE_FS_PREFIX)) { + return false; // vite already tagged it as out of root + } + return fs.existsSync(root + filename); +} + +/** + * @param {string} normalizedFilename + * @param {string} normalizedRoot + * @returns {string} + */ +function stripRoot(normalizedFilename, normalizedRoot) { + return normalizedFilename.startsWith(normalizedRoot + '/') + ? normalizedFilename.slice(normalizedRoot.length) + : normalizedFilename; +} + +/** + * @param {import('../public.d.ts').Options['include'] | undefined} include + * @param {import('../public.d.ts').Options['exclude'] | undefined} exclude + * @param {string[]} extensions + * @returns {(filename: string) => boolean} + */ +function buildFilter(include, exclude, extensions) { + const rollupFilter = createFilter(include, exclude); + return (filename) => rollupFilter(filename) && extensions.some((ext) => filename.endsWith(ext)); +} + +/** + * @param {import('../public.d.ts').Options['include'] | undefined} include + * @param {import('../public.d.ts').Options['exclude'] | undefined} exclude + * @param {string[]} infixes + * @param {string[]} extensions + * @returns {(filename: string) => boolean} + */ +function buildModuleFilter(include, exclude, infixes, extensions) { + const rollupFilter = createFilter(include, exclude); + return (filename) => { + const basename = path.basename(filename); + + return ( + rollupFilter(filename) && + infixes.some((infix) => basename.includes(infix)) && + extensions.some((ext) => basename.endsWith(ext)) + ); + }; +} + +/** + * @param {import('../types/options.d.ts').ResolvedOptions} options + * @returns {import('../types/id.d.ts').IdParser} + */ +export function buildIdParser(options) { + const { include, exclude, extensions, root } = options; + const normalizedRoot = normalizePath(root); + const filter = buildFilter(include, exclude, extensions ?? []); + return (id, ssr, timestamp = Date.now()) => { + const { filename, rawQuery } = splitId(id); + if (filter(filename)) { + return parseToSvelteRequest(id, filename, rawQuery, normalizedRoot, timestamp, ssr); + } + }; +} + +/** + * @param {import('../types/options.d.ts').ResolvedOptions} options + * @returns {import('../types/id.d.ts').ModuleIdParser} + */ +export function buildModuleIdParser(options) { + const { + include, + exclude, + infixes = DEFAULT_SVELTE_MODULE_INFIX, + extensions = DEFAULT_SVELTE_MODULE_EXT + } = options?.experimental?.compileModule ?? {}; + const root = options.root; + const normalizedRoot = normalizePath(root); + const filter = buildModuleFilter(include, exclude, infixes, extensions); + return (id, ssr, timestamp = Date.now()) => { + const { filename, rawQuery } = splitId(id); + if (filter(filename)) { + return parseToSvelteModuleRequest(id, filename, rawQuery, normalizedRoot, timestamp, ssr); + } + }; +} + +/** + * @param {string} id + * @param {string} filename + * @param {string} rawQuery + * @param {string} root + * @param {number} timestamp + * @param {boolean} ssr + * @returns {import('../types/id.d.ts').SvelteModuleRequest | undefined} + */ +function parseToSvelteModuleRequest(id, filename, rawQuery, root, timestamp, ssr) { + const query = parseRequestQuery(rawQuery); + + if (query.url || query.raw || query.direct) { + // skip requests with special vite tags + return; + } + + const normalizedFilename = normalize(filename, root); + + return { + id, + filename, + normalizedFilename, + query, + timestamp, + ssr + }; +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/load-raw.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/load-raw.js new file mode 100644 index 0000000..f800f1b --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/load-raw.js @@ -0,0 +1,125 @@ +import fs from 'node:fs'; +import { toRollupError } from './error.js'; +import { log } from './log.js'; + +/** + * utility function to compile ?raw and ?direct requests in load hook + * + * @param {import('../types/id.d.ts').SvelteRequest} svelteRequest + * @param {import('../types/compile.d.ts').CompileSvelte} compileSvelte + * @param {import('../types/options.d.ts').ResolvedOptions} options + * @returns {Promise} + */ +export async function loadRaw(svelteRequest, compileSvelte, options) { + const { id, filename, query } = svelteRequest; + + // raw svelte subrequest, compile on the fly and return requested subpart + let compileData; + const source = fs.readFileSync(filename, 'utf-8'); + try { + //avoid compileSvelte doing extra ssr stuff unless requested + svelteRequest.ssr = query.compilerOptions?.generate === 'server'; + compileData = await compileSvelte(svelteRequest, source, { + ...options, + // don't use dynamic vite-plugin-svelte defaults here to ensure stable result between ssr,dev and build + compilerOptions: { + dev: false, + css: 'external', + hmr: false, + ...svelteRequest.query.compilerOptions + }, + emitCss: true + }); + } catch (e) { + throw toRollupError(e, options); + } + let result; + if (query.type === 'style') { + result = compileData.compiled.css ?? { code: '', map: null }; + } else if (query.type === 'script') { + result = compileData.compiled.js; + } else if (query.type === 'preprocessed') { + result = compileData.preprocessed; + } else if (query.type === 'all' && query.raw) { + return allToRawExports(compileData, source); + } else { + throw new Error( + `invalid "type=${query.type}" in ${id}. supported are script, style, preprocessed, all` + ); + } + if (query.direct) { + const supportedDirectTypes = ['script', 'style']; + if (!supportedDirectTypes.includes(query.type)) { + throw new Error( + `invalid "type=${ + query.type + }" combined with direct in ${id}. supported are: ${supportedDirectTypes.join(', ')}` + ); + } + log.debug(`load returns direct result for ${id}`, undefined, 'load'); + let directOutput = result.code; + // @ts-expect-error might not be SourceMap but toUrl check should suffice + if (query.sourcemap && result.map?.toUrl) { + // @ts-expect-error toUrl might not exist + const map = `sourceMappingURL=${result.map.toUrl()}`; + if (query.type === 'style') { + directOutput += `\n\n/*# ${map} */\n`; + } else if (query.type === 'script') { + directOutput += `\n\n//# ${map}\n`; + } + } + return directOutput; + } else if (query.raw) { + log.debug(`load returns raw result for ${id}`, undefined, 'load'); + return toRawExports(result); + } else { + throw new Error(`invalid raw mode in ${id}, supported are raw, direct`); + } +} + +/** + * turn compileData and source into a flat list of raw exports + * + * @param {import('../types/compile.d.ts').CompileData} compileData + * @param {string} source + */ +function allToRawExports(compileData, source) { + // flatten CompileData + /** @type {Partial} */ + const exports = { + ...compileData, + ...compileData.compiled, + source + }; + delete exports.compiled; + delete exports.filename; // absolute path, remove to avoid it in output + return toRawExports(exports); +} + +/** + * turn object into raw exports. + * + * every prop is returned as a const export, and if prop 'code' exists it is additionally added as default export + * + * eg {'foo':'bar','code':'baz'} results in + * + * ```js + * export const code='baz' + * export const foo='bar' + * export default code + * ``` + * @param {object} object + * @returns {string} + */ +function toRawExports(object) { + let exports = + Object.entries(object) + .filter(([_key, value]) => typeof value !== 'function') // preprocess output has a toString function that's enumerable + .sort(([a], [b]) => (a < b ? -1 : a === b ? 0 : 1)) + .map(([key, value]) => `export const ${key}=${JSON.stringify(value)}`) + .join('\n') + '\n'; + if (Object.prototype.hasOwnProperty.call(object, 'code')) { + exports += 'export default code\n'; + } + return exports; +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/load-svelte-config.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/load-svelte-config.js new file mode 100644 index 0000000..1b32ba4 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/load-svelte-config.js @@ -0,0 +1,122 @@ +import { createRequire } from 'node:module'; +import path from 'node:path'; +import process from 'node:process'; +import fs from 'node:fs'; +import { pathToFileURL } from 'node:url'; +import { log } from './log.js'; + +// used to require cjs config in esm. +// NOTE dynamic import() cjs technically works, but timestamp query cache bust +// have no effect, likely because it has another internal cache? +/** @type {NodeRequire}*/ +let esmRequire; + +export const knownSvelteConfigNames = [ + 'svelte.config.js', + 'svelte.config.cjs', + 'svelte.config.mjs' +]; + +/** + * @param {string} filePath + * @param {number} timestamp + */ +async function dynamicImportDefault(filePath, timestamp) { + return await import(filePath + '?t=' + timestamp).then((m) => m.default); +} + +/** + * @param {import('vite').UserConfig} [viteConfig] + * @param {Partial} [inlineOptions] + * @returns {Promise | undefined>} + */ +export async function loadSvelteConfig(viteConfig, inlineOptions) { + if (inlineOptions?.configFile === false) { + return; + } + const configFile = findConfigToLoad(viteConfig, inlineOptions); + if (configFile) { + let err; + // try to use dynamic import for svelte.config.js first + if (configFile.endsWith('.js') || configFile.endsWith('.mjs')) { + try { + const result = await dynamicImportDefault( + pathToFileURL(configFile).href, + fs.statSync(configFile).mtimeMs + ); + if (result != null) { + return { + ...result, + configFile + }; + } else { + throw new Error(`invalid export in ${configFile}`); + } + } catch (e) { + log.error(`failed to import config ${configFile}`, e); + err = e; + } + } + // cjs or error with dynamic import + if (!configFile.endsWith('.mjs')) { + try { + // identify which require function to use (esm and cjs mode) + const _require = import.meta.url + ? (esmRequire ?? (esmRequire = createRequire(import.meta.url))) + : // eslint-disable-next-line no-undef + require; + + // avoid loading cached version on reload + delete _require.cache[_require.resolve(configFile)]; + const result = _require(configFile); + if (result != null) { + return { + ...result, + configFile + }; + } else { + throw new Error(`invalid export in ${configFile}`); + } + } catch (e) { + log.error(`failed to require config ${configFile}`, e); + if (!err) { + err = e; + } + } + } + // failed to load existing config file + throw err; + } +} + +/** + * @param {import('vite').UserConfig | undefined} viteConfig + * @param {Partial | undefined} inlineOptions + * @returns {string | undefined} + */ +function findConfigToLoad(viteConfig, inlineOptions) { + const root = viteConfig?.root || process.cwd(); + if (inlineOptions?.configFile) { + const abolutePath = path.isAbsolute(inlineOptions.configFile) + ? inlineOptions.configFile + : path.resolve(root, inlineOptions.configFile); + if (!fs.existsSync(abolutePath)) { + throw new Error(`failed to find svelte config file ${abolutePath}.`); + } + return abolutePath; + } else { + const existingKnownConfigFiles = knownSvelteConfigNames + .map((candidate) => path.resolve(root, candidate)) + .filter((file) => fs.existsSync(file)); + if (existingKnownConfigFiles.length === 0) { + log.debug(`no svelte config found at ${root}`, undefined, 'config'); + return; + } else if (existingKnownConfigFiles.length > 1) { + log.warn( + `found more than one svelte config file, using ${existingKnownConfigFiles[0]}. you should only have one!`, + existingKnownConfigFiles + ); + } + return existingKnownConfigFiles[0]; + } +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/log.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/log.js new file mode 100644 index 0000000..0b43cff --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/log.js @@ -0,0 +1,277 @@ +/* eslint-disable no-console */ +import { cyan, red, yellow } from 'kleur/colors'; +import debug from 'debug'; + +/** @type {import('../types/log.d.ts').LogLevel[]} */ +const levels = ['debug', 'info', 'warn', 'error', 'silent']; +const prefix = 'vite-plugin-svelte'; +/** @type {Record} */ +const loggers = { + debug: { + log: debug(`${prefix}`), + enabled: false, + isDebug: true + }, + info: { + color: cyan, + log: console.log, + enabled: true + }, + warn: { + color: yellow, + log: console.warn, + enabled: true + }, + error: { + color: red, + log: console.error, + enabled: true + }, + silent: { + enabled: false + } +}; + +/** @type {import('../types/log.d.ts').LogLevel} */ +let _level = 'info'; +/** + * @param {import('../types/log.d.ts').LogLevel} level + * @returns {void} + */ +function setLevel(level) { + if (level === _level) { + return; + } + const levelIndex = levels.indexOf(level); + if (levelIndex > -1) { + _level = level; + for (let i = 0; i < levels.length; i++) { + loggers[levels[i]].enabled = i >= levelIndex; + } + } else { + _log(loggers.error, `invalid log level: ${level} `); + } +} + +/** + * @param {any} logger + * @param {string} message + * @param {any} [payload] + * @param {string} [namespace] + * @returns + */ +function _log(logger, message, payload, namespace) { + if (!logger.enabled) { + return; + } + if (logger.isDebug) { + let log = logger.log; + if (namespace) { + if (!isDebugNamespaceEnabled(namespace)) { + return; + } + log = logger.log.extend(namespace); + } + if (payload !== undefined) { + log(message, payload); + } else { + log(message); + } + } else { + logger.log( + logger.color( + `${new Date().toLocaleTimeString()} [${prefix}${ + namespace ? `:${namespace}` : '' + }] ${message}` + ) + ); + if (payload) { + logger.log(payload); + } + } +} + +/** + * @param {import('../types/log.d.ts').LogLevel} level + * @returns {import('../types/log.d.ts').LogFn} + */ +function createLogger(level) { + const logger = loggers[level]; + const logFn = /** @type {import('../types/log.d.ts').LogFn} */ (_log.bind(null, logger)); + /** @type {Set} */ + const logged = new Set(); + /** @type {import('../types/log.d.ts').SimpleLogFn} */ + const once = function (message, payload, namespace) { + if (!logger.enabled || logged.has(message)) { + return; + } + logged.add(message); + logFn.apply(null, [message, payload, namespace]); + }; + Object.defineProperty(logFn, 'enabled', { + get() { + return logger.enabled; + } + }); + Object.defineProperty(logFn, 'once', { + get() { + return once; + } + }); + return logFn; +} + +export const log = { + debug: createLogger('debug'), + info: createLogger('info'), + warn: createLogger('warn'), + error: createLogger('error'), + setLevel +}; + +/** + * @param {import('../types/id.d.ts').SvelteRequest | import('../types/id.d.ts').SvelteModuleRequest} svelteRequest + * @param {import('svelte/compiler').Warning[]} warnings + * @param {import('../types/options.d.ts').ResolvedOptions} options + */ +export function logCompilerWarnings(svelteRequest, warnings, options) { + const { emitCss, onwarn, isBuild } = options; + const sendViaWS = !isBuild && options.experimental?.sendWarningsToBrowser; + let warn = isBuild ? warnBuild : warnDev; + /** @type {import('svelte/compiler').Warning[]} */ + const handledByDefaultWarn = []; + const notIgnored = warnings?.filter((w) => !ignoreCompilerWarning(w, isBuild, emitCss)); + const extra = buildExtraWarnings(warnings, isBuild); + const allWarnings = [...notIgnored, ...extra]; + if (sendViaWS) { + const _warn = warn; + /** @type {(w: import('svelte/compiler').Warning) => void} */ + warn = (w) => { + handledByDefaultWarn.push(w); + _warn(w); + }; + } + allWarnings.forEach((warning) => { + if (onwarn) { + onwarn(warning, warn); + } else { + warn(warning); + } + }); + if (sendViaWS) { + /** @type {import('../types/log.d.ts').SvelteWarningsMessage} */ + const message = { + id: svelteRequest.id, + filename: svelteRequest.filename, + normalizedFilename: svelteRequest.normalizedFilename, + timestamp: svelteRequest.timestamp, + warnings: handledByDefaultWarn, // allWarnings filtered by warnings where onwarn did not call the default handler + allWarnings, // includes warnings filtered by onwarn and our extra vite plugin svelte warnings + rawWarnings: warnings // raw compiler output + }; + log.debug(`sending svelte:warnings message for ${svelteRequest.normalizedFilename}`); + options.server?.ws?.send('svelte:warnings', message); + } +} + +/** + * @param {import('svelte/compiler').Warning} warning + * @param {boolean} isBuild + * @param {boolean} [emitCss] + * @returns {boolean} + */ +function ignoreCompilerWarning(warning, isBuild, emitCss) { + return ( + (!emitCss && warning.code === 'css_unused_selector') || // same as rollup-plugin-svelte + (!isBuild && isNoScopableElementWarning(warning)) + ); +} + +/** + * + * @param {import('svelte/compiler').Warning} warning + * @returns {boolean} + */ +function isNoScopableElementWarning(warning) { + // see https://github.com/sveltejs/vite-plugin-svelte/issues/153 + return warning.code === 'css_unused_selector' && warning.message.includes('"*"'); +} + +/** + * + * @param {import('svelte/compiler').Warning[]} warnings + * @param {boolean} isBuild + * @returns {import('svelte/compiler').Warning[]} + */ +function buildExtraWarnings(warnings, isBuild) { + const extraWarnings = []; + if (!isBuild) { + const noScopableElementWarnings = warnings.filter((w) => isNoScopableElementWarning(w)); + if (noScopableElementWarnings.length > 0) { + // in case there are multiple, use last one as that is the one caused by our *{} rule + const noScopableElementWarning = + noScopableElementWarnings[noScopableElementWarnings.length - 1]; + extraWarnings.push({ + ...noScopableElementWarning, + code: 'vite-plugin-svelte-css-no-scopable-elements', + message: + "No scopable elements found in template. If you're using global styles in the style tag, you should move it into an external stylesheet file and import it in JS. See https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#where-should-i-put-my-global-styles." + }); + } + } + return extraWarnings; +} + +/** + * @param {import('svelte/compiler').Warning} w + */ +function warnDev(w) { + if (w.filename?.includes('node_modules')) { + if (isDebugNamespaceEnabled('node-modules-onwarn')) { + log.debug(buildExtendedLogMessage(w), undefined, 'node-modules-onwarn'); + } + } else if (log.info.enabled) { + log.info(buildExtendedLogMessage(w)); + } +} + +/** + * @param {import('svelte/compiler').Warning & {frame?: string}} w + */ +function warnBuild(w) { + if (w.filename?.includes('node_modules')) { + if (isDebugNamespaceEnabled('node-modules-onwarn')) { + log.debug(buildExtendedLogMessage(w), w.frame, 'node-modules-onwarn'); + } + } else if (log.warn.enabled) { + log.warn(buildExtendedLogMessage(w), w.frame); + } +} + +/** + * @param {import('svelte/compiler').Warning} w + */ +export function buildExtendedLogMessage(w) { + const parts = []; + if (w.filename) { + parts.push(w.filename); + } + if (w.start) { + parts.push(':', w.start.line, ':', w.start.column); + } + if (w.message) { + if (parts.length > 0) { + parts.push(' '); + } + parts.push(w.message); + } + return parts.join(''); +} + +/** + * @param {string} namespace + * @returns {boolean} + */ +export function isDebugNamespaceEnabled(namespace) { + return debug.enabled(`${prefix}:${namespace}`); +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/optimizer.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/optimizer.js new file mode 100644 index 0000000..71aa571 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/optimizer.js @@ -0,0 +1,53 @@ +import { promises as fs } from 'node:fs'; +import path from 'node:path'; + +// List of options that changes the prebundling result +/** @type {(keyof import('../types/options.d.ts').ResolvedOptions)[]} */ +const PREBUNDLE_SENSITIVE_OPTIONS = [ + 'compilerOptions', + 'configFile', + 'experimental', + 'extensions', + 'ignorePluginPreprocessors', + 'preprocess' +]; + +/** + * @param {string} cacheDir + * @param {import('../types/options.d.ts').ResolvedOptions} options + * @returns {Promise} Whether the Svelte metadata has changed + */ +export async function saveSvelteMetadata(cacheDir, options) { + const svelteMetadata = generateSvelteMetadata(options); + const svelteMetadataPath = path.resolve(cacheDir, '_svelte_metadata.json'); + + const currentSvelteMetadata = JSON.stringify(svelteMetadata, (_, value) => { + // Handle preprocessors + return typeof value === 'function' ? value.toString() : value; + }); + + /** @type {string | undefined} */ + let existingSvelteMetadata; + try { + existingSvelteMetadata = await fs.readFile(svelteMetadataPath, 'utf8'); + } catch { + // ignore + } + + await fs.mkdir(cacheDir, { recursive: true }); + await fs.writeFile(svelteMetadataPath, currentSvelteMetadata); + return currentSvelteMetadata !== existingSvelteMetadata; +} + +/** + * @param {import('../types/options.d.ts').ResolvedOptions} options + * @returns {Partial} + */ +function generateSvelteMetadata(options) { + /** @type {Record} */ + const metadata = {}; + for (const key of PREBUNDLE_SENSITIVE_OPTIONS) { + metadata[key] = options[key]; + } + return metadata; +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/options.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/options.js new file mode 100644 index 0000000..dff6eb4 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/options.js @@ -0,0 +1,620 @@ +import process from 'node:process'; +import { normalizePath } from 'vite'; +import { isDebugNamespaceEnabled, log } from './log.js'; +import { loadSvelteConfig } from './load-svelte-config.js'; +import { + DEFAULT_SVELTE_EXT, + FAQ_LINK_MISSING_EXPORTS_CONDITION, + SVELTE_EXPORT_CONDITIONS, + SVELTE_IMPORTS, + SVELTE_RESOLVE_MAIN_FIELDS, + VITE_RESOLVE_MAIN_FIELDS +} from './constants.js'; + +import path from 'node:path'; +import { + esbuildSvelteModulePlugin, + esbuildSveltePlugin, + facadeEsbuildSvelteModulePluginName, + facadeEsbuildSveltePluginName +} from './esbuild.js'; +import { addExtraPreprocessors } from './preprocess.js'; +import deepmerge from 'deepmerge'; +import { + crawlFrameworkPkgs, + isDepExcluded, + isDepExternaled, + isDepIncluded, + isDepNoExternaled +} from 'vitefu'; + +import { isCommonDepWithoutSvelteField } from './dependencies.js'; +import { VitePluginSvelteStats } from './vite-plugin-svelte-stats.js'; + +const allowedPluginOptions = new Set([ + 'include', + 'exclude', + 'emitCss', + 'hot', + 'ignorePluginPreprocessors', + 'disableDependencyReinclusion', + 'prebundleSvelteLibraries', + 'inspector', + 'dynamicCompileOptions', + 'experimental' +]); + +const knownRootOptions = new Set(['extensions', 'compilerOptions', 'preprocess', 'onwarn']); + +const allowedInlineOptions = new Set(['configFile', ...allowedPluginOptions, ...knownRootOptions]); + +/** + * @param {Partial} [inlineOptions] + */ +export function validateInlineOptions(inlineOptions) { + const invalidKeys = Object.keys(inlineOptions || {}).filter( + (key) => !allowedInlineOptions.has(key) + ); + if (invalidKeys.length) { + log.warn(`invalid plugin options "${invalidKeys.join(', ')}" in inline config`, inlineOptions); + } +} + +/** + * @param {Partial} [config] + * @returns {Partial | undefined} + */ +function convertPluginOptions(config) { + if (!config) { + return; + } + const invalidRootOptions = Object.keys(config).filter((key) => allowedPluginOptions.has(key)); + if (invalidRootOptions.length > 0) { + throw new Error( + `Invalid options in svelte config. Move the following options into 'vitePlugin:{...}': ${invalidRootOptions.join( + ', ' + )}` + ); + } + if (!config.vitePlugin) { + return config; + } + const pluginOptions = config.vitePlugin; + const pluginOptionKeys = Object.keys(pluginOptions); + + const rootOptionsInPluginOptions = pluginOptionKeys.filter((key) => knownRootOptions.has(key)); + if (rootOptionsInPluginOptions.length > 0) { + throw new Error( + `Invalid options in svelte config under vitePlugin:{...}', move them to the config root : ${rootOptionsInPluginOptions.join( + ', ' + )}` + ); + } + const duplicateOptions = pluginOptionKeys.filter((key) => + Object.prototype.hasOwnProperty.call(config, key) + ); + if (duplicateOptions.length > 0) { + throw new Error( + `Invalid duplicate options in svelte config under vitePlugin:{...}', they are defined in root too and must only exist once: ${duplicateOptions.join( + ', ' + )}` + ); + } + const unknownPluginOptions = pluginOptionKeys.filter((key) => !allowedPluginOptions.has(key)); + if (unknownPluginOptions.length > 0) { + log.warn( + `ignoring unknown plugin options in svelte config under vitePlugin:{...}: ${unknownPluginOptions.join( + ', ' + )}` + ); + unknownPluginOptions.forEach((unkownOption) => { + // @ts-expect-error not typed + delete pluginOptions[unkownOption]; + }); + } + /** @type {import('../public.d.ts').Options} */ + const result = { + ...config, + ...pluginOptions + }; + // @ts-expect-error it exists + delete result.vitePlugin; + + return result; +} + +/** + * used in config phase, merges the default options, svelte config, and inline options + * @param {Partial | undefined} inlineOptions + * @param {import('vite').UserConfig} viteUserConfig + * @param {import('vite').ConfigEnv} viteEnv + * @returns {Promise} + */ +export async function preResolveOptions(inlineOptions, viteUserConfig, viteEnv) { + if (!inlineOptions) { + inlineOptions = {}; + } + /** @type {import('vite').UserConfig} */ + const viteConfigWithResolvedRoot = { + ...viteUserConfig, + root: resolveViteRoot(viteUserConfig) + }; + const isBuild = viteEnv.command === 'build'; + /** @type {Partial} */ + const defaultOptions = { + extensions: DEFAULT_SVELTE_EXT, + emitCss: true, + prebundleSvelteLibraries: !isBuild + }; + const svelteConfig = convertPluginOptions( + await loadSvelteConfig(viteConfigWithResolvedRoot, inlineOptions) + ); + /** @type {Partial} */ + const extraOptions = { + root: viteConfigWithResolvedRoot.root, + isBuild, + isServe: viteEnv.command === 'serve', + isDebug: process.env.DEBUG != null + }; + + const merged = /** @type {import('../types/options.d.ts').PreResolvedOptions} */ ( + mergeConfigs(defaultOptions, svelteConfig, inlineOptions, extraOptions) + ); + // configFile of svelteConfig contains the absolute path it was loaded from, + // prefer it over the possibly relative inline path + if (svelteConfig?.configFile) { + merged.configFile = svelteConfig.configFile; + } + return merged; +} + +/** + * @template T + * @param {(Partial | undefined)[]} configs + * @returns T + */ +function mergeConfigs(...configs) { + /** @type {Partial} */ + let result = {}; + for (const config of configs.filter((x) => x != null)) { + result = deepmerge(result, /** @type {Partial} */ (config), { + // replace arrays + arrayMerge: (target, source) => source ?? target + }); + } + return /** @type {T} */ result; +} + +/** + * used in configResolved phase, merges a contextual default config, pre-resolved options, and some preprocessors. also validates the final config. + * + * @param {import('../types/options.d.ts').PreResolvedOptions} preResolveOptions + * @param {import('vite').ResolvedConfig} viteConfig + * @param {import('./vite-plugin-svelte-cache.js').VitePluginSvelteCache} cache + * @returns {import('../types/options.d.ts').ResolvedOptions} + */ +export function resolveOptions(preResolveOptions, viteConfig, cache) { + const css = preResolveOptions.emitCss ? 'external' : 'injected'; + /** @type {Partial} */ + const defaultOptions = { + compilerOptions: { + css, + dev: !viteConfig.isProduction, + hmr: + !viteConfig.isProduction && + !preResolveOptions.isBuild && + viteConfig.server && + viteConfig.server.hmr !== false + } + }; + + /** @type {Partial} */ + const extraOptions = { + root: viteConfig.root, + isProduction: viteConfig.isProduction + }; + const merged = /** @type {import('../types/options.d.ts').ResolvedOptions}*/ ( + mergeConfigs(defaultOptions, preResolveOptions, extraOptions) + ); + + removeIgnoredOptions(merged); + handleDeprecatedOptions(merged); + addExtraPreprocessors(merged, viteConfig); + enforceOptionsForHmr(merged, viteConfig); + enforceOptionsForProduction(merged); + // mergeConfigs would mangle functions on the stats class, so do this afterwards + if (log.debug.enabled && isDebugNamespaceEnabled('stats')) { + merged.stats = new VitePluginSvelteStats(cache); + } + return merged; +} + +/** + * @param {import('../types/options.d.ts').ResolvedOptions} options + * @param {import('vite').ResolvedConfig} viteConfig + */ +function enforceOptionsForHmr(options, viteConfig) { + if (options.hot) { + log.warn( + 'svelte 5 has hmr integrated in core. Please remove the vitePlugin.hot option and use compilerOptions.hmr instead' + ); + delete options.hot; + options.compilerOptions.hmr = true; + } + if (options.compilerOptions.hmr && viteConfig.server?.hmr === false) { + log.warn( + 'vite config server.hmr is false but compilerOptions.hmr is true. Forcing compilerOptions.hmr to false as it would not work.' + ); + options.compilerOptions.hmr = false; + } +} + +/** + * @param {import('../types/options.d.ts').ResolvedOptions} options + */ +function enforceOptionsForProduction(options) { + if (options.isProduction) { + if (options.compilerOptions.hmr) { + log.warn( + 'you are building for production but compilerOptions.hmr is true, forcing it to false' + ); + options.compilerOptions.hmr = false; + } + if (options.compilerOptions.dev) { + log.warn( + 'you are building for production but compilerOptions.dev is true, forcing it to false' + ); + options.compilerOptions.dev = false; + } + } +} + +/** + * @param {import('../types/options.d.ts').ResolvedOptions} options + */ +function removeIgnoredOptions(options) { + const ignoredCompilerOptions = ['generate', 'format', 'filename']; + if (options.compilerOptions.hmr && options.emitCss) { + ignoredCompilerOptions.push('cssHash'); + } + const passedCompilerOptions = Object.keys(options.compilerOptions || {}); + const passedIgnored = passedCompilerOptions.filter((o) => ignoredCompilerOptions.includes(o)); + if (passedIgnored.length) { + log.warn( + `The following Svelte compilerOptions are controlled by vite-plugin-svelte and essential to its functionality. User-specified values are ignored. Please remove them from your configuration: ${passedIgnored.join( + ', ' + )}` + ); + passedIgnored.forEach((ignored) => { + // @ts-expect-error string access + delete options.compilerOptions[ignored]; + }); + } +} + +/** + * @param {import('../types/options.d.ts').ResolvedOptions} options + */ +function handleDeprecatedOptions(options) { + const experimental = /** @type {Record} */ (options.experimental); + if (experimental) { + for (const promoted of ['prebundleSvelteLibraries', 'inspector', 'dynamicCompileOptions']) { + if (experimental[promoted]) { + //@ts-expect-error untyped assign + options[promoted] = experimental[promoted]; + delete experimental[promoted]; + log.warn( + `Option "experimental.${promoted}" is no longer experimental and has moved to "${promoted}". Please update your Svelte or Vite config.` + ); + } + } + if (experimental.generateMissingPreprocessorSourcemaps) { + log.warn('experimental.generateMissingPreprocessorSourcemaps has been removed.'); + } + } +} + +/** + * vite passes unresolved `root`option to config hook but we need the resolved value, so do it here + * + * @see https://github.com/sveltejs/vite-plugin-svelte/issues/113 + * @see https://github.com/vitejs/vite/blob/43c957de8a99bb326afd732c962f42127b0a4d1e/packages/vite/src/node/config.ts#L293 + * + * @param {import('vite').UserConfig} viteConfig + * @returns {string | undefined} + */ +function resolveViteRoot(viteConfig) { + return normalizePath(viteConfig.root ? path.resolve(viteConfig.root) : process.cwd()); +} + +/** + * @param {import('../types/options.d.ts').PreResolvedOptions} options + * @param {import('vite').UserConfig} config + * @returns {Promise>} + */ +export async function buildExtraViteConfig(options, config) { + // make sure we only readd vite default mainFields when no other plugin has changed the config already + // see https://github.com/sveltejs/vite-plugin-svelte/issues/581 + if (!config.resolve) { + config.resolve = {}; + } + config.resolve.mainFields = [ + ...SVELTE_RESOLVE_MAIN_FIELDS, + ...(config.resolve.mainFields ?? VITE_RESOLVE_MAIN_FIELDS) + ]; + + /** @type {Partial} */ + const extraViteConfig = { + resolve: { + dedupe: [...SVELTE_IMPORTS], + conditions: [...SVELTE_EXPORT_CONDITIONS] + } + // this option is still awaiting a PR in vite to be supported + // see https://github.com/sveltejs/vite-plugin-svelte/issues/60 + // knownJsSrcExtensions: options.extensions + }; + + const extraSvelteConfig = buildExtraConfigForSvelte(config); + const extraDepsConfig = await buildExtraConfigForDependencies(options, config); + // merge extra svelte and deps config, but make sure dep values are not contradicting svelte + extraViteConfig.optimizeDeps = { + include: [ + ...extraSvelteConfig.optimizeDeps.include, + ...extraDepsConfig.optimizeDeps.include.filter( + (dep) => !isDepExcluded(dep, extraSvelteConfig.optimizeDeps.exclude) + ) + ], + exclude: [ + ...extraSvelteConfig.optimizeDeps.exclude, + ...extraDepsConfig.optimizeDeps.exclude.filter( + (dep) => !isDepIncluded(dep, extraSvelteConfig.optimizeDeps.include) + ) + ] + }; + + extraViteConfig.ssr = { + external: [ + ...extraSvelteConfig.ssr.external, + ...extraDepsConfig.ssr.external.filter( + (dep) => !isDepNoExternaled(dep, extraSvelteConfig.ssr.noExternal) + ) + ], + noExternal: [ + ...extraSvelteConfig.ssr.noExternal, + ...extraDepsConfig.ssr.noExternal.filter( + (dep) => !isDepExternaled(dep, extraSvelteConfig.ssr.external) + ) + ] + }; + + // handle prebundling for svelte files + if (options.prebundleSvelteLibraries) { + extraViteConfig.optimizeDeps = { + ...extraViteConfig.optimizeDeps, + // Experimental Vite API to allow these extensions to be scanned and prebundled + extensions: options.extensions ?? ['.svelte'], + // Add esbuild plugin to prebundle Svelte files. + // Currently a placeholder as more information is needed after Vite config is resolved, + // the real Svelte plugin is added in `patchResolvedViteConfig()` + esbuildOptions: { + plugins: [ + { name: facadeEsbuildSveltePluginName, setup: () => {} }, + { name: facadeEsbuildSvelteModulePluginName, setup: () => {} } + ] + } + }; + } + + // enable hmrPartialAccept if not explicitly disabled + if (config.experimental?.hmrPartialAccept !== false) { + log.debug('enabling "experimental.hmrPartialAccept" in vite config', undefined, 'config'); + extraViteConfig.experimental = { hmrPartialAccept: true }; + } + validateViteConfig(extraViteConfig, config, options); + return extraViteConfig; +} + +/** + * @param {Partial} extraViteConfig + * @param {import('vite').UserConfig} config + * @param {import('../types/options.d.ts').PreResolvedOptions} options + */ +function validateViteConfig(extraViteConfig, config, options) { + const { prebundleSvelteLibraries, isBuild } = options; + if (prebundleSvelteLibraries) { + /** @type {(option: 'dev' | 'build' | boolean)=> boolean} */ + const isEnabled = (option) => option !== true && option !== (isBuild ? 'build' : 'dev'); + /** @type {(name: string, value: 'dev' | 'build' | boolean, recommendation: string)=> void} */ + const logWarning = (name, value, recommendation) => + log.warn.once( + `Incompatible options: \`prebundleSvelteLibraries: true\` and vite \`${name}: ${JSON.stringify( + value + )}\` ${isBuild ? 'during build.' : '.'} ${recommendation}` + ); + const viteOptimizeDepsDisabled = config.optimizeDeps?.disabled ?? 'build'; // fall back to vite default + const isOptimizeDepsEnabled = isEnabled(viteOptimizeDepsDisabled); + if (!isBuild && !isOptimizeDepsEnabled) { + logWarning( + 'optimizeDeps.disabled', + viteOptimizeDepsDisabled, + 'Forcing `optimizeDeps.disabled: "build"`. Disable prebundleSvelteLibraries or update your vite config to enable optimizeDeps during dev.' + ); + if (!extraViteConfig.optimizeDeps) { + extraViteConfig.optimizeDeps = {}; + } + extraViteConfig.optimizeDeps.disabled = 'build'; + } else if (isBuild && isOptimizeDepsEnabled) { + logWarning( + 'optimizeDeps.disabled', + viteOptimizeDepsDisabled, + 'Disable optimizeDeps or prebundleSvelteLibraries for build if you experience errors.' + ); + } + } +} + +/** + * @param {import('../types/options.d.ts').PreResolvedOptions} options + * @param {import('vite').UserConfig} config + * @returns {Promise} + */ +async function buildExtraConfigForDependencies(options, config) { + // extra handling for svelte dependencies in the project + const packagesWithoutSvelteExportsCondition = new Set(); + const depsConfig = await crawlFrameworkPkgs({ + root: options.root, + isBuild: options.isBuild, + viteUserConfig: config, + isFrameworkPkgByJson(pkgJson) { + let hasSvelteCondition = false; + if (typeof pkgJson.exports === 'object') { + // use replacer as a simple way to iterate over nested keys + JSON.stringify(pkgJson.exports, (key, value) => { + if (SVELTE_EXPORT_CONDITIONS.includes(key)) { + hasSvelteCondition = true; + } + return value; + }); + } + const hasSvelteField = !!pkgJson.svelte; + if (hasSvelteField && !hasSvelteCondition) { + packagesWithoutSvelteExportsCondition.add(`${pkgJson.name}@${pkgJson.version}`); + } + return hasSvelteCondition || hasSvelteField; + }, + isSemiFrameworkPkgByJson(pkgJson) { + return !!pkgJson.dependencies?.svelte || !!pkgJson.peerDependencies?.svelte; + }, + isFrameworkPkgByName(pkgName) { + const isNotSveltePackage = isCommonDepWithoutSvelteField(pkgName); + if (isNotSveltePackage) { + return false; + } else { + return undefined; + } + } + }); + if ( + !options.experimental?.disableSvelteResolveWarnings && + packagesWithoutSvelteExportsCondition?.size > 0 + ) { + log.warn( + `WARNING: The following packages have a svelte field in their package.json but no exports condition for svelte.\n\n${[ + ...packagesWithoutSvelteExportsCondition + ].join('\n')}\n\nPlease see ${FAQ_LINK_MISSING_EXPORTS_CONDITION} for details.` + ); + } + log.debug('extra config for dependencies generated by vitefu', depsConfig, 'config'); + + if (options.prebundleSvelteLibraries) { + // prebundling enabled, so we don't need extra dependency excludes + depsConfig.optimizeDeps.exclude = []; + // but keep dependency reinclusions of explicit user excludes + const userExclude = config.optimizeDeps?.exclude; + depsConfig.optimizeDeps.include = !userExclude + ? [] + : depsConfig.optimizeDeps.include.filter((dep) => { + // reincludes look like this: foo > bar > baz + // in case foo or bar are excluded, we have to retain the reinclude even with prebundling + return ( + dep.includes('>') && + dep + .split('>') + .slice(0, -1) + .some((d) => isDepExcluded(d.trim(), userExclude)) + ); + }); + } + if (options.disableDependencyReinclusion === true) { + depsConfig.optimizeDeps.include = depsConfig.optimizeDeps.include.filter( + (dep) => !dep.includes('>') + ); + } else if (Array.isArray(options.disableDependencyReinclusion)) { + const disabledDeps = options.disableDependencyReinclusion; + depsConfig.optimizeDeps.include = depsConfig.optimizeDeps.include.filter((dep) => { + if (!dep.includes('>')) return true; + const trimDep = dep.replace(/\s+/g, ''); + return disabledDeps.some((disabled) => trimDep.includes(`${disabled}>`)); + }); + } + + log.debug('post-processed extra config for dependencies', depsConfig, 'config'); + + return depsConfig; +} + +/** + * @param {import('vite').UserConfig} config + * @returns {import('vite').UserConfig & { optimizeDeps: { include: string[], exclude:string[] }, ssr: { noExternal:(string|RegExp)[], external: string[] } } } + */ +function buildExtraConfigForSvelte(config) { + // include svelte imports for optimization unless explicitly excluded + /** @type {string[]} */ + const include = []; + /** @type {string[]} */ + const exclude = []; + if (!isDepExcluded('svelte', config.optimizeDeps?.exclude ?? [])) { + const svelteImportsToInclude = SVELTE_IMPORTS.filter( + (si) => !(si.endsWith('/server') || si.includes('/server/')) + ); + log.debug( + `adding bare svelte packages to optimizeDeps.include: ${svelteImportsToInclude.join(', ')} `, + undefined, + 'config' + ); + include.push(...svelteImportsToInclude); + } else { + log.debug( + '"svelte" is excluded in optimizeDeps.exclude, skipped adding it to include.', + undefined, + 'config' + ); + } + /** @type {(string | RegExp)[]} */ + const noExternal = []; + /** @type {string[]} */ + const external = []; + // add svelte to ssr.noExternal unless it is present in ssr.external + // so it is correctly resolving according to the conditions in sveltes exports map + if (!isDepExternaled('svelte', config.ssr?.external ?? [])) { + noExternal.push('svelte', /^svelte\//); + } + return { optimizeDeps: { include, exclude }, ssr: { noExternal, external } }; +} + +/** + * @param {import('vite').ResolvedConfig} viteConfig + * @param {import('../types/options.d.ts').ResolvedOptions} options + */ +export function patchResolvedViteConfig(viteConfig, options) { + if (options.preprocess) { + for (const preprocessor of arraify(options.preprocess)) { + if (preprocessor.style && '__resolvedConfig' in preprocessor.style) { + preprocessor.style.__resolvedConfig = viteConfig; + } + } + } + + // replace facade esbuild plugin with a real one + const facadeEsbuildSveltePlugin = viteConfig.optimizeDeps.esbuildOptions?.plugins?.find( + (plugin) => plugin.name === facadeEsbuildSveltePluginName + ); + if (facadeEsbuildSveltePlugin) { + Object.assign(facadeEsbuildSveltePlugin, esbuildSveltePlugin(options)); + } + const facadeEsbuildSvelteModulePlugin = viteConfig.optimizeDeps.esbuildOptions?.plugins?.find( + (plugin) => plugin.name === facadeEsbuildSvelteModulePluginName + ); + if (facadeEsbuildSvelteModulePlugin) { + Object.assign(facadeEsbuildSvelteModulePlugin, esbuildSvelteModulePlugin(options)); + } +} + +/** + * @template T + * @param {T | T[]} value + * @returns {T[]} + */ +function arraify(value) { + return Array.isArray(value) ? value : [value]; +} diff --git a/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/preprocess.js b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/preprocess.js new file mode 100644 index 0000000..602c649 --- /dev/null +++ b/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/utils/preprocess.js @@ -0,0 +1,173 @@ +import MagicString from 'magic-string'; +import { log } from './log.js'; +import path from 'node:path'; +import { normalizePath } from 'vite'; + +/** + * this appends a *{} rule to component styles to force the svelte compiler to add style classes to all nodes + * That means adding/removing class rules from ' + * ) + * document.type //=> 'document' + * document.nodes.length //=> 2 + * ``` + */ +declare class Document_ extends Container { + nodes: Root[] + parent: undefined + type: 'document' + + constructor(defaults?: Document.DocumentProps) + + assign(overrides: Document.DocumentProps | object): this + clone(overrides?: Partial): this + cloneAfter(overrides?: Partial): this + cloneBefore(overrides?: Partial): this + + /** + * Returns a `Result` instance representing the document’s CSS roots. + * + * ```js + * const root1 = postcss.parse(css1, { from: 'a.css' }) + * const root2 = postcss.parse(css2, { from: 'b.css' }) + * const document = postcss.document() + * document.append(root1) + * document.append(root2) + * const result = document.toResult({ to: 'all.css', map: true }) + * ``` + * + * @param opts Options. + * @return Result with current document’s CSS. + */ + toResult(options?: ProcessOptions): Result +} + +declare class Document extends Document_ {} + +export = Document diff --git a/frontend/node_modules/postcss/lib/document.js b/frontend/node_modules/postcss/lib/document.js new file mode 100644 index 0000000..4468991 --- /dev/null +++ b/frontend/node_modules/postcss/lib/document.js @@ -0,0 +1,33 @@ +'use strict' + +let Container = require('./container') + +let LazyResult, Processor + +class Document extends Container { + constructor(defaults) { + // type needs to be passed to super, otherwise child roots won't be normalized correctly + super({ type: 'document', ...defaults }) + + if (!this.nodes) { + this.nodes = [] + } + } + + toResult(opts = {}) { + let lazy = new LazyResult(new Processor(), this, opts) + + return lazy.stringify() + } +} + +Document.registerLazyResult = dependant => { + LazyResult = dependant +} + +Document.registerProcessor = dependant => { + Processor = dependant +} + +module.exports = Document +Document.default = Document diff --git a/frontend/node_modules/postcss/lib/fromJSON.d.ts b/frontend/node_modules/postcss/lib/fromJSON.d.ts new file mode 100644 index 0000000..e1deedb --- /dev/null +++ b/frontend/node_modules/postcss/lib/fromJSON.d.ts @@ -0,0 +1,9 @@ +import { JSONHydrator } from './postcss.js' + +interface FromJSON extends JSONHydrator { + default: FromJSON +} + +declare const fromJSON: FromJSON + +export = fromJSON diff --git a/frontend/node_modules/postcss/lib/fromJSON.js b/frontend/node_modules/postcss/lib/fromJSON.js new file mode 100644 index 0000000..c9ac1a8 --- /dev/null +++ b/frontend/node_modules/postcss/lib/fromJSON.js @@ -0,0 +1,54 @@ +'use strict' + +let AtRule = require('./at-rule') +let Comment = require('./comment') +let Declaration = require('./declaration') +let Input = require('./input') +let PreviousMap = require('./previous-map') +let Root = require('./root') +let Rule = require('./rule') + +function fromJSON(json, inputs) { + if (Array.isArray(json)) return json.map(n => fromJSON(n)) + + let { inputs: ownInputs, ...defaults } = json + if (ownInputs) { + inputs = [] + for (let input of ownInputs) { + let inputHydrated = { ...input, __proto__: Input.prototype } + if (inputHydrated.map) { + inputHydrated.map = { + ...inputHydrated.map, + __proto__: PreviousMap.prototype + } + } + inputs.push(inputHydrated) + } + } + if (defaults.nodes) { + defaults.nodes = json.nodes.map(n => fromJSON(n, inputs)) + } + if (defaults.source) { + let { inputId, ...source } = defaults.source + defaults.source = source + if (inputId != null) { + defaults.source.input = inputs[inputId] + } + } + if (defaults.type === 'root') { + return new Root(defaults) + } else if (defaults.type === 'decl') { + return new Declaration(defaults) + } else if (defaults.type === 'rule') { + return new Rule(defaults) + } else if (defaults.type === 'comment') { + return new Comment(defaults) + } else if (defaults.type === 'atrule') { + return new AtRule(defaults) + } else { + throw new Error('Unknown node type: ' + json.type) + } +} + +module.exports = fromJSON +fromJSON.default = fromJSON diff --git a/frontend/node_modules/postcss/lib/input.d.ts b/frontend/node_modules/postcss/lib/input.d.ts new file mode 100644 index 0000000..b788f55 --- /dev/null +++ b/frontend/node_modules/postcss/lib/input.d.ts @@ -0,0 +1,227 @@ +import { CssSyntaxError, ProcessOptions } from './postcss.js' +import PreviousMap from './previous-map.js' + +declare namespace Input { + export interface FilePosition { + /** + * Column of inclusive start position in source file. + */ + column: number + + /** + * Column of exclusive end position in source file. + */ + endColumn?: number + + /** + * Line of exclusive end position in source file. + */ + endLine?: number + + /** + * Offset of exclusive end position in source file. + */ + endOffset?: number + + /** + * Absolute path to the source file. + */ + file?: string + + /** + * Line of inclusive start position in source file. + */ + line: number + + /** + * Offset of inclusive start position in source file. + */ + offset: number + + /** + * Source code. + */ + source?: string + + /** + * URL for the source file. + */ + url: string + } + + + export { Input_ as default } +} + +/** + * Represents the source CSS. + * + * ```js + * const root = postcss.parse(css, { from: file }) + * const input = root.source.input + * ``` + */ +declare class Input_ { + /** + * Input CSS source. + * + * ```js + * const input = postcss.parse('a{}', { from: file }).input + * input.css //=> "a{}" + * ``` + */ + css: string + + /** + * Input source with support for non-CSS documents. + * + * ```js + * const input = postcss.parse('a{}', { from: file, document: '' }).input + * input.document //=> "" + * input.css //=> "a{}" + * ``` + */ + document: string + + /** + * The absolute path to the CSS source file defined + * with the `from` option. + * + * ```js + * const root = postcss.parse(css, { from: 'a.css' }) + * root.source.input.file //=> '/home/ai/a.css' + * ``` + */ + file?: string + + /** + * The flag to indicate whether or not the source code has Unicode BOM. + */ + hasBOM: boolean + + /** + * The unique ID of the CSS source. It will be created if `from` option + * is not provided (because PostCSS does not know the file path). + * + * ```js + * const root = postcss.parse(css) + * root.source.input.file //=> undefined + * root.source.input.id //=> "" + * ``` + */ + id?: string + + /** + * The input source map passed from a compilation step before PostCSS + * (for example, from Sass compiler). + * + * ```js + * root.source.input.map.consumer().sources //=> ['a.sass'] + * ``` + */ + map: PreviousMap + + /** + * The CSS source identifier. Contains `Input#file` if the user + * set the `from` option, or `Input#id` if they did not. + * + * ```js + * const root = postcss.parse(css, { from: 'a.css' }) + * root.source.input.from //=> "/home/ai/a.css" + * + * const root = postcss.parse(css) + * root.source.input.from //=> "" + * ``` + */ + get from(): string + + /** + * @param css Input CSS source. + * @param opts Process options. + */ + constructor(css: string, opts?: ProcessOptions) + + /** + * Returns `CssSyntaxError` with information about the error and its position. + */ + error( + message: string, + start: + | { + column: number + line: number + } + | { + offset: number + }, + end: + | { + column: number + line: number + } + | { + offset: number + }, + opts?: { plugin?: CssSyntaxError['plugin'] } + ): CssSyntaxError + error( + message: string, + line: number, + column: number, + opts?: { plugin?: CssSyntaxError['plugin'] } + ): CssSyntaxError + error( + message: string, + offset: number, + opts?: { plugin?: CssSyntaxError['plugin'] } + ): CssSyntaxError + + /** + * Converts source line and column to offset. + * + * @param line Source line. + * @param column Source column. + * @return Source offset. + */ + fromLineAndColumn(line: number, column: number): number + + /** + * Converts source offset to line and column. + * + * @param offset Source offset. + */ + fromOffset(offset: number): { col: number; line: number } | null + + /** + * Reads the input source map and returns a symbol position + * in the input source (e.g., in a Sass file that was compiled + * to CSS before being passed to PostCSS). Optionally takes an + * end position, exclusive. + * + * ```js + * root.source.input.origin(1, 1) //=> { file: 'a.css', line: 3, column: 1 } + * root.source.input.origin(1, 1, 1, 4) + * //=> { file: 'a.css', line: 3, column: 1, endLine: 3, endColumn: 4 } + * ``` + * + * @param line Line for inclusive start position in input CSS. + * @param column Column for inclusive start position in input CSS. + * @param endLine Line for exclusive end position in input CSS. + * @param endColumn Column for exclusive end position in input CSS. + * + * @return Position in input source. + */ + origin( + line: number, + column: number, + endLine?: number, + endColumn?: number + ): false | Input.FilePosition + + /** Converts this to a JSON-friendly object representation. */ + toJSON(): object +} + +declare class Input extends Input_ {} + +export = Input diff --git a/frontend/node_modules/postcss/lib/input.js b/frontend/node_modules/postcss/lib/input.js new file mode 100644 index 0000000..bb0ccf5 --- /dev/null +++ b/frontend/node_modules/postcss/lib/input.js @@ -0,0 +1,265 @@ +'use strict' + +let { nanoid } = require('nanoid/non-secure') +let { isAbsolute, resolve } = require('path') +let { SourceMapConsumer, SourceMapGenerator } = require('source-map-js') +let { fileURLToPath, pathToFileURL } = require('url') + +let CssSyntaxError = require('./css-syntax-error') +let PreviousMap = require('./previous-map') +let terminalHighlight = require('./terminal-highlight') + +let lineToIndexCache = Symbol('lineToIndexCache') + +let sourceMapAvailable = Boolean(SourceMapConsumer && SourceMapGenerator) +let pathAvailable = Boolean(resolve && isAbsolute) + +function getLineToIndex(input) { + if (input[lineToIndexCache]) return input[lineToIndexCache] + let lines = input.css.split('\n') + let lineToIndex = new Array(lines.length) + let prevIndex = 0 + + for (let i = 0, l = lines.length; i < l; i++) { + lineToIndex[i] = prevIndex + prevIndex += lines[i].length + 1 + } + + input[lineToIndexCache] = lineToIndex + return lineToIndex +} + +class Input { + get from() { + return this.file || this.id + } + + constructor(css, opts = {}) { + if ( + css === null || + typeof css === 'undefined' || + (typeof css === 'object' && !css.toString) + ) { + throw new Error(`PostCSS received ${css} instead of CSS string`) + } + + this.css = css.toString() + + if (this.css[0] === '\uFEFF' || this.css[0] === '\uFFFE') { + this.hasBOM = true + this.css = this.css.slice(1) + } else { + this.hasBOM = false + } + + this.document = this.css + if (opts.document) this.document = opts.document.toString() + + if (opts.from) { + if ( + !pathAvailable || + /^\w+:\/\//.test(opts.from) || + isAbsolute(opts.from) + ) { + this.file = opts.from + } else { + this.file = resolve(opts.from) + } + } + + if (pathAvailable && sourceMapAvailable) { + let map = new PreviousMap(this.css, opts) + if (map.text) { + this.map = map + let file = map.consumer().file + if (!this.file && file) this.file = this.mapResolve(file) + } + } + + if (!this.file) { + this.id = '' + } + if (this.map) this.map.file = this.from + } + + error(message, line, column, opts = {}) { + let endColumn, endLine, endOffset, offset, result + + if (line && typeof line === 'object') { + let start = line + let end = column + if (typeof start.offset === 'number') { + offset = start.offset + let pos = this.fromOffset(offset) + line = pos.line + column = pos.col + } else { + line = start.line + column = start.column + offset = this.fromLineAndColumn(line, column) + } + if (typeof end.offset === 'number') { + endOffset = end.offset + let pos = this.fromOffset(endOffset) + endLine = pos.line + endColumn = pos.col + } else { + endLine = end.line + endColumn = end.column + endOffset = this.fromLineAndColumn(end.line, end.column) + } + } else if (!column) { + offset = line + let pos = this.fromOffset(offset) + line = pos.line + column = pos.col + } else { + offset = this.fromLineAndColumn(line, column) + } + + let origin = this.origin(line, column, endLine, endColumn) + if (origin) { + result = new CssSyntaxError( + message, + origin.endLine === undefined + ? origin.line + : { column: origin.column, line: origin.line }, + origin.endLine === undefined + ? origin.column + : { column: origin.endColumn, line: origin.endLine }, + origin.source, + origin.file, + opts.plugin + ) + } else { + result = new CssSyntaxError( + message, + endLine === undefined ? line : { column, line }, + endLine === undefined ? column : { column: endColumn, line: endLine }, + this.css, + this.file, + opts.plugin + ) + } + + result.input = { column, endColumn, endLine, endOffset, line, offset, source: this.css } + if (this.file) { + if (pathToFileURL) { + result.input.url = pathToFileURL(this.file).toString() + } + result.input.file = this.file + } + + return result + } + + fromLineAndColumn(line, column) { + let lineToIndex = getLineToIndex(this) + let index = lineToIndex[line - 1] + return index + column - 1 + } + + fromOffset(offset) { + let lineToIndex = getLineToIndex(this) + let lastLine = lineToIndex[lineToIndex.length - 1] + + let min = 0 + if (offset >= lastLine) { + min = lineToIndex.length - 1 + } else { + let max = lineToIndex.length - 2 + let mid + while (min < max) { + mid = min + ((max - min) >> 1) + if (offset < lineToIndex[mid]) { + max = mid - 1 + } else if (offset >= lineToIndex[mid + 1]) { + min = mid + 1 + } else { + min = mid + break + } + } + } + return { + col: offset - lineToIndex[min] + 1, + line: min + 1 + } + } + + mapResolve(file) { + if (/^\w+:\/\//.test(file)) { + return file + } + return resolve(this.map.consumer().sourceRoot || this.map.root || '.', file) + } + + origin(line, column, endLine, endColumn) { + if (!this.map) return false + let consumer = this.map.consumer() + + let from = consumer.originalPositionFor({ column, line }) + if (!from.source) return false + + let to + if (typeof endLine === 'number') { + to = consumer.originalPositionFor({ column: endColumn, line: endLine }) + } + + let fromUrl + + if (isAbsolute(from.source)) { + fromUrl = pathToFileURL(from.source) + } else { + fromUrl = new URL( + from.source, + this.map.consumer().sourceRoot || pathToFileURL(this.map.mapFile) + ) + } + + let result = { + column: from.column, + endColumn: to && to.column, + endLine: to && to.line, + line: from.line, + url: fromUrl.toString() + } + + if (fromUrl.protocol === 'file:') { + if (fileURLToPath) { + result.file = fileURLToPath(fromUrl) + } else { + /* c8 ignore next 2 */ + throw new Error(`file: protocol is not available in this PostCSS build`) + } + } + + let source = consumer.sourceContentFor(from.source) + if (source) result.source = source + + return result + } + + toJSON() { + let json = {} + for (let name of ['hasBOM', 'css', 'file', 'id']) { + if (this[name] != null) { + json[name] = this[name] + } + } + if (this.map) { + json.map = { ...this.map } + if (json.map.consumerCache) { + json.map.consumerCache = undefined + } + } + return json + } +} + +module.exports = Input +Input.default = Input + +if (terminalHighlight && terminalHighlight.registerInput) { + terminalHighlight.registerInput(Input) +} diff --git a/frontend/node_modules/postcss/lib/lazy-result.d.ts b/frontend/node_modules/postcss/lib/lazy-result.d.ts new file mode 100644 index 0000000..393ab03 --- /dev/null +++ b/frontend/node_modules/postcss/lib/lazy-result.d.ts @@ -0,0 +1,190 @@ +import Document from './document.js' +import { SourceMap } from './postcss.js' +import Processor from './processor.js' +import Result, { Message, ResultOptions } from './result.js' +import Root from './root.js' +import Warning from './warning.js' + +declare namespace LazyResult { + + export { LazyResult_ as default } +} + +/** + * A Promise proxy for the result of PostCSS transformations. + * + * A `LazyResult` instance is returned by `Processor#process`. + * + * ```js + * const lazy = postcss([autoprefixer]).process(css) + * ``` + */ +declare class LazyResult_ + implements PromiseLike> +{ + /** + * Processes input CSS through synchronous and asynchronous plugins + * and calls onRejected for each error thrown in any plugin. + * + * It implements standard Promise API. + * + * ```js + * postcss([autoprefixer]).process(css).then(result => { + * console.log(result.css) + * }).catch(error => { + * console.error(error) + * }) + * ``` + */ + catch: Promise>['catch'] + + /** + * Processes input CSS through synchronous and asynchronous plugins + * and calls onFinally on any error or when all plugins will finish work. + * + * It implements standard Promise API. + * + * ```js + * postcss([autoprefixer]).process(css).finally(() => { + * console.log('processing ended') + * }) + * ``` + */ + finally: Promise>['finally'] + + /** + * Processes input CSS through synchronous and asynchronous plugins + * and calls `onFulfilled` with a Result instance. If a plugin throws + * an error, the `onRejected` callback will be executed. + * + * It implements standard Promise API. + * + * ```js + * postcss([autoprefixer]).process(css, { from: cssPath }).then(result => { + * console.log(result.css) + * }) + * ``` + */ + then: Promise>['then'] + + /** + * An alias for the `css` property. Use it with syntaxes + * that generate non-CSS output. + * + * This property will only work with synchronous plugins. + * If the processor contains any asynchronous plugins + * it will throw an error. + * + * PostCSS runners should always use `LazyResult#then`. + */ + get content(): string + + /** + * Processes input CSS through synchronous plugins, converts `Root` + * to a CSS string and returns `Result#css`. + * + * This property will only work with synchronous plugins. + * If the processor contains any asynchronous plugins + * it will throw an error. + * + * PostCSS runners should always use `LazyResult#then`. + */ + get css(): string + + /** + * Processes input CSS through synchronous plugins + * and returns `Result#map`. + * + * This property will only work with synchronous plugins. + * If the processor contains any asynchronous plugins + * it will throw an error. + * + * PostCSS runners should always use `LazyResult#then`. + */ + get map(): SourceMap + + /** + * Processes input CSS through synchronous plugins + * and returns `Result#messages`. + * + * This property will only work with synchronous plugins. If the processor + * contains any asynchronous plugins it will throw an error. + * + * PostCSS runners should always use `LazyResult#then`. + */ + get messages(): Message[] + + /** + * Options from the `Processor#process` call. + */ + get opts(): ResultOptions + + /** + * Returns a `Processor` instance, which will be used + * for CSS transformations. + */ + get processor(): Processor + + /** + * Processes input CSS through synchronous plugins + * and returns `Result#root`. + * + * This property will only work with synchronous plugins. If the processor + * contains any asynchronous plugins it will throw an error. + * + * PostCSS runners should always use `LazyResult#then`. + */ + get root(): RootNode + + /** + * Returns the default string description of an object. + * Required to implement the Promise interface. + */ + get [Symbol.toStringTag](): string + + /** + * @param processor Processor used for this transformation. + * @param css CSS to parse and transform. + * @param opts Options from the `Processor#process` or `Root#toResult`. + */ + constructor(processor: Processor, css: string, opts: ResultOptions) + + /** + * Run plugin in async way and return `Result`. + * + * @return Result with output content. + */ + async(): Promise> + + /** + * Run plugin in sync way and return `Result`. + * + * @return Result with output content. + */ + sync(): Result + + /** + * Alias for the `LazyResult#css` property. + * + * ```js + * lazy + '' === lazy.css + * ``` + * + * @return Output CSS. + */ + toString(): string + + /** + * Processes input CSS through synchronous plugins + * and calls `Result#warnings`. + * + * @return Warnings from plugins. + */ + warnings(): Warning[] +} + +declare class LazyResult< + RootNode = Document | Root +> extends LazyResult_ {} + +export = LazyResult diff --git a/frontend/node_modules/postcss/lib/lazy-result.js b/frontend/node_modules/postcss/lib/lazy-result.js new file mode 100644 index 0000000..1ea52b8 --- /dev/null +++ b/frontend/node_modules/postcss/lib/lazy-result.js @@ -0,0 +1,550 @@ +'use strict' + +let Container = require('./container') +let Document = require('./document') +let MapGenerator = require('./map-generator') +let parse = require('./parse') +let Result = require('./result') +let Root = require('./root') +let stringify = require('./stringify') +let { isClean, my } = require('./symbols') +let warnOnce = require('./warn-once') + +const TYPE_TO_CLASS_NAME = { + atrule: 'AtRule', + comment: 'Comment', + decl: 'Declaration', + document: 'Document', + root: 'Root', + rule: 'Rule' +} + +const PLUGIN_PROPS = { + AtRule: true, + AtRuleExit: true, + Comment: true, + CommentExit: true, + Declaration: true, + DeclarationExit: true, + Document: true, + DocumentExit: true, + Once: true, + OnceExit: true, + postcssPlugin: true, + prepare: true, + Root: true, + RootExit: true, + Rule: true, + RuleExit: true +} + +const NOT_VISITORS = { + Once: true, + postcssPlugin: true, + prepare: true +} + +const CHILDREN = 0 + +function isPromise(obj) { + return typeof obj === 'object' && typeof obj.then === 'function' +} + +function getEvents(node) { + let key = false + let type = TYPE_TO_CLASS_NAME[node.type] + if (node.type === 'decl') { + key = node.prop.toLowerCase() + } else if (node.type === 'atrule') { + key = node.name.toLowerCase() + } + + if (key && node.append) { + return [ + type, + type + '-' + key, + CHILDREN, + type + 'Exit', + type + 'Exit-' + key + ] + } else if (key) { + return [type, type + '-' + key, type + 'Exit', type + 'Exit-' + key] + } else if (node.append) { + return [type, CHILDREN, type + 'Exit'] + } else { + return [type, type + 'Exit'] + } +} + +function toStack(node) { + let events + if (node.type === 'document') { + events = ['Document', CHILDREN, 'DocumentExit'] + } else if (node.type === 'root') { + events = ['Root', CHILDREN, 'RootExit'] + } else { + events = getEvents(node) + } + + return { + eventIndex: 0, + events, + iterator: 0, + node, + visitorIndex: 0, + visitors: [] + } +} + +function cleanMarks(node) { + node[isClean] = false + if (node.nodes) node.nodes.forEach(i => cleanMarks(i)) + return node +} + +let postcss = {} + +class LazyResult { + get content() { + return this.stringify().content + } + + get css() { + return this.stringify().css + } + + get map() { + return this.stringify().map + } + + get messages() { + return this.sync().messages + } + + get opts() { + return this.result.opts + } + + get processor() { + return this.result.processor + } + + get root() { + return this.sync().root + } + + get [Symbol.toStringTag]() { + return 'LazyResult' + } + + constructor(processor, css, opts) { + this.stringified = false + this.processed = false + + let root + if ( + typeof css === 'object' && + css !== null && + (css.type === 'root' || css.type === 'document') + ) { + root = cleanMarks(css) + } else if (css instanceof LazyResult || css instanceof Result) { + root = cleanMarks(css.root) + if (css.map) { + if (typeof opts.map === 'undefined') opts.map = {} + if (!opts.map.inline) opts.map.inline = false + opts.map.prev = css.map + } + } else { + let parser = parse + if (opts.syntax) parser = opts.syntax.parse + if (opts.parser) parser = opts.parser + if (parser.parse) parser = parser.parse + + try { + root = parser(css, opts) + } catch (error) { + this.processed = true + this.error = error + } + + if (root && !root[my]) { + /* c8 ignore next 2 */ + Container.rebuild(root) + } + } + + this.result = new Result(processor, root, opts) + this.helpers = { ...postcss, postcss, result: this.result } + this.plugins = this.processor.plugins.map(plugin => { + if (typeof plugin === 'object' && plugin.prepare) { + return { ...plugin, ...plugin.prepare(this.result) } + } else { + return plugin + } + }) + } + + async() { + if (this.error) return Promise.reject(this.error) + if (this.processed) return Promise.resolve(this.result) + if (!this.processing) { + this.processing = this.runAsync() + } + return this.processing + } + + catch(onRejected) { + return this.async().catch(onRejected) + } + + finally(onFinally) { + return this.async().then(onFinally, onFinally) + } + + getAsyncError() { + throw new Error('Use process(css).then(cb) to work with async plugins') + } + + handleError(error, node) { + let plugin = this.result.lastPlugin + try { + if (node) node.addToError(error) + this.error = error + if (error.name === 'CssSyntaxError' && !error.plugin) { + error.plugin = plugin.postcssPlugin + error.setMessage() + } else if (plugin.postcssVersion) { + if (process.env.NODE_ENV !== 'production') { + let pluginName = plugin.postcssPlugin + let pluginVer = plugin.postcssVersion + let runtimeVer = this.result.processor.version + let a = pluginVer.split('.') + let b = runtimeVer.split('.') + + if (a[0] !== b[0] || parseInt(a[1]) > parseInt(b[1])) { + // eslint-disable-next-line no-console + console.error( + 'Unknown error from PostCSS plugin. Your current PostCSS ' + + 'version is ' + + runtimeVer + + ', but ' + + pluginName + + ' uses ' + + pluginVer + + '. Perhaps this is the source of the error below.' + ) + } + } + } + } catch (err) { + /* c8 ignore next 3 */ + // eslint-disable-next-line no-console + if (console && console.error) console.error(err) + } + return error + } + + prepareVisitors() { + this.listeners = {} + let add = (plugin, type, cb) => { + if (!this.listeners[type]) this.listeners[type] = [] + this.listeners[type].push([plugin, cb]) + } + for (let plugin of this.plugins) { + if (typeof plugin === 'object') { + for (let event in plugin) { + if (!PLUGIN_PROPS[event] && /^[A-Z]/.test(event)) { + throw new Error( + `Unknown event ${event} in ${plugin.postcssPlugin}. ` + + `Try to update PostCSS (${this.processor.version} now).` + ) + } + if (!NOT_VISITORS[event]) { + if (typeof plugin[event] === 'object') { + for (let filter in plugin[event]) { + if (filter === '*') { + add(plugin, event, plugin[event][filter]) + } else { + add( + plugin, + event + '-' + filter.toLowerCase(), + plugin[event][filter] + ) + } + } + } else if (typeof plugin[event] === 'function') { + add(plugin, event, plugin[event]) + } + } + } + } + } + this.hasListener = Object.keys(this.listeners).length > 0 + } + + async runAsync() { + this.plugin = 0 + for (let i = 0; i < this.plugins.length; i++) { + let plugin = this.plugins[i] + let promise = this.runOnRoot(plugin) + if (isPromise(promise)) { + try { + await promise + } catch (error) { + throw this.handleError(error) + } + } + } + + this.prepareVisitors() + if (this.hasListener) { + let root = this.result.root + while (!root[isClean]) { + root[isClean] = true + let stack = [toStack(root)] + while (stack.length > 0) { + let promise = this.visitTick(stack) + if (isPromise(promise)) { + try { + await promise + } catch (e) { + let node = stack[stack.length - 1].node + throw this.handleError(e, node) + } + } + } + } + + if (this.listeners.OnceExit) { + for (let [plugin, visitor] of this.listeners.OnceExit) { + this.result.lastPlugin = plugin + try { + if (root.type === 'document') { + let roots = root.nodes.map(subRoot => + visitor(subRoot, this.helpers) + ) + + await Promise.all(roots) + } else { + await visitor(root, this.helpers) + } + } catch (e) { + throw this.handleError(e) + } + } + } + } + + this.processed = true + return this.stringify() + } + + runOnRoot(plugin) { + this.result.lastPlugin = plugin + try { + if (typeof plugin === 'object' && plugin.Once) { + if (this.result.root.type === 'document') { + let roots = this.result.root.nodes.map(root => + plugin.Once(root, this.helpers) + ) + + if (isPromise(roots[0])) { + return Promise.all(roots) + } + + return roots + } + + return plugin.Once(this.result.root, this.helpers) + } else if (typeof plugin === 'function') { + return plugin(this.result.root, this.result) + } + } catch (error) { + throw this.handleError(error) + } + } + + stringify() { + if (this.error) throw this.error + if (this.stringified) return this.result + this.stringified = true + + this.sync() + + let opts = this.result.opts + let str = stringify + if (opts.syntax) str = opts.syntax.stringify + if (opts.stringifier) str = opts.stringifier + if (str.stringify) str = str.stringify + + let map = new MapGenerator(str, this.result.root, this.result.opts) + let data = map.generate() + this.result.css = data[0] + this.result.map = data[1] + + return this.result + } + + sync() { + if (this.error) throw this.error + if (this.processed) return this.result + this.processed = true + + if (this.processing) { + throw this.getAsyncError() + } + + for (let plugin of this.plugins) { + let promise = this.runOnRoot(plugin) + if (isPromise(promise)) { + throw this.getAsyncError() + } + } + + this.prepareVisitors() + if (this.hasListener) { + let root = this.result.root + while (!root[isClean]) { + root[isClean] = true + this.walkSync(root) + } + if (this.listeners.OnceExit) { + if (root.type === 'document') { + for (let subRoot of root.nodes) { + this.visitSync(this.listeners.OnceExit, subRoot) + } + } else { + this.visitSync(this.listeners.OnceExit, root) + } + } + } + + return this.result + } + + then(onFulfilled, onRejected) { + if (process.env.NODE_ENV !== 'production') { + if (!('from' in this.opts)) { + warnOnce( + 'Without `from` option PostCSS could generate wrong source map ' + + 'and will not find Browserslist config. Set it to CSS file path ' + + 'or to `undefined` to prevent this warning.' + ) + } + } + return this.async().then(onFulfilled, onRejected) + } + + toString() { + return this.css + } + + visitSync(visitors, node) { + for (let [plugin, visitor] of visitors) { + this.result.lastPlugin = plugin + let promise + try { + promise = visitor(node, this.helpers) + } catch (e) { + throw this.handleError(e, node.proxyOf) + } + if (node.type !== 'root' && node.type !== 'document' && !node.parent) { + return true + } + if (isPromise(promise)) { + throw this.getAsyncError() + } + } + } + + visitTick(stack) { + let visit = stack[stack.length - 1] + let { node, visitors } = visit + + if (node.type !== 'root' && node.type !== 'document' && !node.parent) { + stack.pop() + return + } + + if (visitors.length > 0 && visit.visitorIndex < visitors.length) { + let [plugin, visitor] = visitors[visit.visitorIndex] + visit.visitorIndex += 1 + if (visit.visitorIndex === visitors.length) { + visit.visitors = [] + visit.visitorIndex = 0 + } + this.result.lastPlugin = plugin + try { + return visitor(node.toProxy(), this.helpers) + } catch (e) { + throw this.handleError(e, node) + } + } + + if (visit.iterator !== 0) { + let iterator = visit.iterator + let child + while ((child = node.nodes[node.indexes[iterator]])) { + node.indexes[iterator] += 1 + if (!child[isClean]) { + child[isClean] = true + stack.push(toStack(child)) + return + } + } + visit.iterator = 0 + delete node.indexes[iterator] + } + + let events = visit.events + while (visit.eventIndex < events.length) { + let event = events[visit.eventIndex] + visit.eventIndex += 1 + if (event === CHILDREN) { + if (node.nodes && node.nodes.length) { + node[isClean] = true + visit.iterator = node.getIterator() + } + return + } else if (this.listeners[event]) { + visit.visitors = this.listeners[event] + return + } + } + stack.pop() + } + + walkSync(node) { + node[isClean] = true + let events = getEvents(node) + for (let event of events) { + if (event === CHILDREN) { + if (node.nodes) { + node.each(child => { + if (!child[isClean]) this.walkSync(child) + }) + } + } else { + let visitors = this.listeners[event] + if (visitors) { + if (this.visitSync(visitors, node.toProxy())) return + } + } + } + } + + warnings() { + return this.sync().warnings() + } +} + +LazyResult.registerPostcss = dependant => { + postcss = dependant +} + +module.exports = LazyResult +LazyResult.default = LazyResult + +Root.registerLazyResult(LazyResult) +Document.registerLazyResult(LazyResult) diff --git a/frontend/node_modules/postcss/lib/list.d.ts b/frontend/node_modules/postcss/lib/list.d.ts new file mode 100644 index 0000000..e262ad3 --- /dev/null +++ b/frontend/node_modules/postcss/lib/list.d.ts @@ -0,0 +1,60 @@ +declare namespace list { + type List = { + /** + * Safely splits comma-separated values (such as those for `transition-*` + * and `background` properties). + * + * ```js + * Once (root, { list }) { + * list.comma('black, linear-gradient(white, black)') + * //=> ['black', 'linear-gradient(white, black)'] + * } + * ``` + * + * @param str Comma-separated values. + * @return Split values. + */ + comma(str: string): string[] + + default: List + + /** + * Safely splits space-separated values (such as those for `background`, + * `border-radius`, and other shorthand properties). + * + * ```js + * Once (root, { list }) { + * list.space('1px calc(10% + 1px)') //=> ['1px', 'calc(10% + 1px)'] + * } + * ``` + * + * @param str Space-separated values. + * @return Split values. + */ + space(str: string): string[] + + /** + * Safely splits values. + * + * ```js + * Once (root, { list }) { + * list.split('1px calc(10% + 1px)', [' ', '\n', '\t']) //=> ['1px', 'calc(10% + 1px)'] + * } + * ``` + * + * @param string separated values. + * @param separators array of separators. + * @param last boolean indicator. + * @return Split values. + */ + split( + string: string, + separators: readonly string[], + last: boolean + ): string[] + } +} + +declare const list: list.List + +export = list diff --git a/frontend/node_modules/postcss/lib/list.js b/frontend/node_modules/postcss/lib/list.js new file mode 100644 index 0000000..1b31f98 --- /dev/null +++ b/frontend/node_modules/postcss/lib/list.js @@ -0,0 +1,58 @@ +'use strict' + +let list = { + comma(string) { + return list.split(string, [','], true) + }, + + space(string) { + let spaces = [' ', '\n', '\t'] + return list.split(string, spaces) + }, + + split(string, separators, last) { + let array = [] + let current = '' + let split = false + + let func = 0 + let inQuote = false + let prevQuote = '' + let escape = false + + for (let letter of string) { + if (escape) { + escape = false + } else if (letter === '\\') { + escape = true + } else if (inQuote) { + if (letter === prevQuote) { + inQuote = false + } + } else if (letter === '"' || letter === "'") { + inQuote = true + prevQuote = letter + } else if (letter === '(') { + func += 1 + } else if (letter === ')') { + if (func > 0) func -= 1 + } else if (func === 0) { + if (separators.includes(letter)) split = true + } + + if (split) { + if (current !== '') array.push(current.trim()) + current = '' + split = false + } else { + current += letter + } + } + + if (last || current !== '') array.push(current.trim()) + return array + } +} + +module.exports = list +list.default = list diff --git a/frontend/node_modules/postcss/lib/map-generator.js b/frontend/node_modules/postcss/lib/map-generator.js new file mode 100644 index 0000000..df880ac --- /dev/null +++ b/frontend/node_modules/postcss/lib/map-generator.js @@ -0,0 +1,376 @@ +'use strict' + +let { dirname, relative, resolve, sep } = require('path') +let { SourceMapConsumer, SourceMapGenerator } = require('source-map-js') +let { pathToFileURL } = require('url') + +let Input = require('./input') + +let sourceMapAvailable = Boolean(SourceMapConsumer && SourceMapGenerator) +let pathAvailable = Boolean(dirname && resolve && relative && sep) + +class MapGenerator { + constructor(stringify, root, opts, cssString) { + this.stringify = stringify + this.mapOpts = opts.map || {} + this.root = root + this.opts = opts + this.css = cssString + this.originalCSS = cssString + this.usesFileUrls = !this.mapOpts.from && this.mapOpts.absolute + + this.memoizedFileURLs = new Map() + this.memoizedPaths = new Map() + this.memoizedURLs = new Map() + } + + addAnnotation() { + let content + + if (this.isInline()) { + content = + 'data:application/json;base64,' + this.toBase64(this.map.toString()) + } else if (typeof this.mapOpts.annotation === 'string') { + content = this.mapOpts.annotation + } else if (typeof this.mapOpts.annotation === 'function') { + content = this.mapOpts.annotation(this.opts.to, this.root) + } else { + content = this.outputFile() + '.map' + } + let eol = '\n' + if (this.css.includes('\r\n')) eol = '\r\n' + + this.css += eol + '/*# sourceMappingURL=' + content + ' */' + } + + applyPrevMaps() { + for (let prev of this.previous()) { + let from = this.toUrl(this.path(prev.file)) + let root = prev.root || dirname(prev.file) + let map + + if (this.mapOpts.sourcesContent === false) { + map = new SourceMapConsumer(prev.text) + if (map.sourcesContent) { + map.sourcesContent = null + } + } else { + map = prev.consumer() + } + + this.map.applySourceMap(map, from, this.toUrl(this.path(root))) + } + } + + clearAnnotation() { + if (this.mapOpts.annotation === false) return + + if (this.root) { + let node + for (let i = this.root.nodes.length - 1; i >= 0; i--) { + node = this.root.nodes[i] + if (node.type !== 'comment') continue + if (node.text.startsWith('# sourceMappingURL=')) { + this.root.removeChild(i) + } + } + } else if (this.css) { + let startIndex + while ((startIndex = this.css.lastIndexOf('/*#')) !== -1) { + let endIndex = this.css.indexOf('*/', startIndex + 3) + if (endIndex === -1) break + while (startIndex > 0 && this.css[startIndex - 1] === '\n') { + startIndex-- + } + this.css = this.css.slice(0, startIndex) + this.css.slice(endIndex + 2) + } + } + } + + generate() { + this.clearAnnotation() + if (pathAvailable && sourceMapAvailable && this.isMap()) { + return this.generateMap() + } else { + let result = '' + this.stringify(this.root, i => { + result += i + }) + return [result] + } + } + + generateMap() { + if (this.root) { + this.generateString() + } else if (this.previous().length === 1) { + let prev = this.previous()[0].consumer() + prev.file = this.outputFile() + this.map = SourceMapGenerator.fromSourceMap(prev, { + ignoreInvalidMapping: true + }) + } else { + this.map = new SourceMapGenerator({ + file: this.outputFile(), + ignoreInvalidMapping: true + }) + this.map.addMapping({ + generated: { column: 0, line: 1 }, + original: { column: 0, line: 1 }, + source: this.opts.from + ? this.toUrl(this.path(this.opts.from)) + : '' + }) + } + + if (this.isSourcesContent()) this.setSourcesContent() + if (this.root && this.previous().length > 0) this.applyPrevMaps() + if (this.isAnnotation()) this.addAnnotation() + + if (this.isInline()) { + return [this.css] + } else { + return [this.css, this.map] + } + } + + generateString() { + this.css = '' + this.map = new SourceMapGenerator({ + file: this.outputFile(), + ignoreInvalidMapping: true + }) + + let line = 1 + let column = 1 + + let noSource = '' + let mapping = { + generated: { column: 0, line: 0 }, + original: { column: 0, line: 0 }, + source: '' + } + + let last, lines + this.stringify(this.root, (str, node, type) => { + this.css += str + + if (node && type !== 'end') { + mapping.generated.line = line + mapping.generated.column = column - 1 + if (node.source && node.source.start) { + mapping.source = this.sourcePath(node) + mapping.original.line = node.source.start.line + mapping.original.column = node.source.start.column - 1 + this.map.addMapping(mapping) + } else { + mapping.source = noSource + mapping.original.line = 1 + mapping.original.column = 0 + this.map.addMapping(mapping) + } + } + + lines = str.match(/\n/g) + if (lines) { + line += lines.length + last = str.lastIndexOf('\n') + column = str.length - last + } else { + column += str.length + } + + if (node && type !== 'start') { + let p = node.parent || { raws: {} } + let childless = + node.type === 'decl' || (node.type === 'atrule' && !node.nodes) + if (!childless || node !== p.last || p.raws.semicolon) { + if (node.source && node.source.end) { + mapping.source = this.sourcePath(node) + mapping.original.line = node.source.end.line + mapping.original.column = node.source.end.column - 1 + mapping.generated.line = line + mapping.generated.column = column - 2 + this.map.addMapping(mapping) + } else { + mapping.source = noSource + mapping.original.line = 1 + mapping.original.column = 0 + mapping.generated.line = line + mapping.generated.column = column - 1 + this.map.addMapping(mapping) + } + } + } + }) + } + + isAnnotation() { + if (this.isInline()) { + return true + } + if (typeof this.mapOpts.annotation !== 'undefined') { + return this.mapOpts.annotation + } + if (this.previous().length) { + return this.previous().some(i => i.annotation) + } + return true + } + + isInline() { + if (typeof this.mapOpts.inline !== 'undefined') { + return this.mapOpts.inline + } + + let annotation = this.mapOpts.annotation + if (typeof annotation !== 'undefined' && annotation !== true) { + return false + } + + if (this.previous().length) { + return this.previous().some(i => i.inline) + } + return true + } + + isMap() { + if (typeof this.opts.map !== 'undefined') { + return !!this.opts.map + } + return this.previous().length > 0 + } + + isSourcesContent() { + if (typeof this.mapOpts.sourcesContent !== 'undefined') { + return this.mapOpts.sourcesContent + } + if (this.previous().length) { + return this.previous().some(i => i.withContent()) + } + return true + } + + outputFile() { + if (this.opts.to) { + return this.path(this.opts.to) + } else if (this.opts.from) { + return this.path(this.opts.from) + } else { + return 'to.css' + } + } + + path(file) { + if (this.mapOpts.absolute) return file + if (file.charCodeAt(0) === 60 /* `<` */) return file + if (/^\w+:\/\//.test(file)) return file + let cached = this.memoizedPaths.get(file) + if (cached) return cached + + let from = this.opts.to ? dirname(this.opts.to) : '.' + + if (typeof this.mapOpts.annotation === 'string') { + from = dirname(resolve(from, this.mapOpts.annotation)) + } + + let path = relative(from, file) + this.memoizedPaths.set(file, path) + + return path + } + + previous() { + if (!this.previousMaps) { + this.previousMaps = [] + if (this.root) { + this.root.walk(node => { + if (node.source && node.source.input.map) { + let map = node.source.input.map + if (!this.previousMaps.includes(map)) { + this.previousMaps.push(map) + } + } + }) + } else { + let input = new Input(this.originalCSS, this.opts) + if (input.map) this.previousMaps.push(input.map) + } + } + + return this.previousMaps + } + + setSourcesContent() { + let already = {} + if (this.root) { + this.root.walk(node => { + if (node.source) { + let from = node.source.input.from + if (from && !already[from]) { + already[from] = true + let fromUrl = this.usesFileUrls + ? this.toFileUrl(from) + : this.toUrl(this.path(from)) + this.map.setSourceContent(fromUrl, node.source.input.css) + } + } + }) + } else if (this.css) { + let from = this.opts.from + ? this.toUrl(this.path(this.opts.from)) + : '' + this.map.setSourceContent(from, this.css) + } + } + + sourcePath(node) { + if (this.mapOpts.from) { + return this.toUrl(this.mapOpts.from) + } else if (this.usesFileUrls) { + return this.toFileUrl(node.source.input.from) + } else { + return this.toUrl(this.path(node.source.input.from)) + } + } + + toBase64(str) { + if (Buffer) { + return Buffer.from(str).toString('base64') + } else { + return window.btoa(unescape(encodeURIComponent(str))) + } + } + + toFileUrl(path) { + let cached = this.memoizedFileURLs.get(path) + if (cached) return cached + + if (pathToFileURL) { + let fileURL = pathToFileURL(path).toString() + this.memoizedFileURLs.set(path, fileURL) + + return fileURL + } else { + throw new Error( + '`map.absolute` option is not available in this PostCSS build' + ) + } + } + + toUrl(path) { + let cached = this.memoizedURLs.get(path) + if (cached) return cached + + if (sep === '\\') { + path = path.replace(/\\/g, '/') + } + + let url = encodeURI(path).replace(/[#?]/g, encodeURIComponent) + this.memoizedURLs.set(path, url) + + return url + } +} + +module.exports = MapGenerator diff --git a/frontend/node_modules/postcss/lib/no-work-result.d.ts b/frontend/node_modules/postcss/lib/no-work-result.d.ts new file mode 100644 index 0000000..747d705 --- /dev/null +++ b/frontend/node_modules/postcss/lib/no-work-result.d.ts @@ -0,0 +1,46 @@ +import LazyResult from './lazy-result.js' +import { SourceMap } from './postcss.js' +import Processor from './processor.js' +import Result, { Message, ResultOptions } from './result.js' +import Root from './root.js' +import Warning from './warning.js' + +declare namespace NoWorkResult { + + export { NoWorkResult_ as default } +} + +/** + * A Promise proxy for the result of PostCSS transformations. + * This lazy result instance doesn't parse css unless `NoWorkResult#root` or `Result#root` + * are accessed. See the example below for details. + * A `NoWork` instance is returned by `Processor#process` ONLY when no plugins defined. + * + * ```js + * const noWorkResult = postcss().process(css) // No plugins are defined. + * // CSS is not parsed + * let root = noWorkResult.root // now css is parsed because we accessed the root + * ``` + */ +declare class NoWorkResult_ implements LazyResult { + catch: Promise>['catch'] + finally: Promise>['finally'] + then: Promise>['then'] + get content(): string + get css(): string + get map(): SourceMap + get messages(): Message[] + get opts(): ResultOptions + get processor(): Processor + get root(): Root + get [Symbol.toStringTag](): string + constructor(processor: Processor, css: string, opts: ResultOptions) + async(): Promise> + sync(): Result + toString(): string + warnings(): Warning[] +} + +declare class NoWorkResult extends NoWorkResult_ {} + +export = NoWorkResult diff --git a/frontend/node_modules/postcss/lib/no-work-result.js b/frontend/node_modules/postcss/lib/no-work-result.js new file mode 100644 index 0000000..092fdc3 --- /dev/null +++ b/frontend/node_modules/postcss/lib/no-work-result.js @@ -0,0 +1,137 @@ +'use strict' + +let MapGenerator = require('./map-generator') +let parse = require('./parse') +const Result = require('./result') +let stringify = require('./stringify') +let warnOnce = require('./warn-once') + +class NoWorkResult { + get content() { + return this.result.css + } + + get css() { + return this.result.css + } + + get map() { + return this.result.map + } + + get messages() { + return [] + } + + get opts() { + return this.result.opts + } + + get processor() { + return this.result.processor + } + + get root() { + if (this._root) { + return this._root + } + + let root + let parser = parse + + try { + root = parser(this._css, this._opts) + } catch (error) { + this.error = error + } + + if (this.error) { + throw this.error + } else { + this._root = root + return root + } + } + + get [Symbol.toStringTag]() { + return 'NoWorkResult' + } + + constructor(processor, css, opts) { + css = css.toString() + this.stringified = false + + this._processor = processor + this._css = css + this._opts = opts + this._map = undefined + + let str = stringify + this.result = new Result(this._processor, undefined, this._opts) + this.result.css = css + + let self = this + Object.defineProperty(this.result, 'root', { + get() { + return self.root + } + }) + + let map = new MapGenerator(str, undefined, this._opts, css) + if (map.isMap()) { + let [generatedCSS, generatedMap] = map.generate() + if (generatedCSS) { + this.result.css = generatedCSS + } + if (generatedMap) { + this.result.map = generatedMap + } + } else { + map.clearAnnotation() + this.result.css = map.css + } + } + + async() { + if (this.error) return Promise.reject(this.error) + return Promise.resolve(this.result) + } + + catch(onRejected) { + return this.async().catch(onRejected) + } + + finally(onFinally) { + return this.async().then(onFinally, onFinally) + } + + sync() { + if (this.error) throw this.error + return this.result + } + + then(onFulfilled, onRejected) { + if (process.env.NODE_ENV !== 'production') { + if (!('from' in this._opts)) { + warnOnce( + 'Without `from` option PostCSS could generate wrong source map ' + + 'and will not find Browserslist config. Set it to CSS file path ' + + 'or to `undefined` to prevent this warning.' + ) + } + } + + return this.async().then(onFulfilled, onRejected) + } + + toString() { + return this._css + } + + warnings() { + return [] + } +} + +module.exports = NoWorkResult +NoWorkResult.default = NoWorkResult diff --git a/frontend/node_modules/postcss/lib/node.d.ts b/frontend/node_modules/postcss/lib/node.d.ts new file mode 100644 index 0000000..a48120e --- /dev/null +++ b/frontend/node_modules/postcss/lib/node.d.ts @@ -0,0 +1,556 @@ +import AtRule = require('./at-rule.js') +import { AtRuleProps } from './at-rule.js' +import Comment, { CommentProps } from './comment.js' +import Container, { NewChild } from './container.js' +import CssSyntaxError from './css-syntax-error.js' +import Declaration, { DeclarationProps } from './declaration.js' +import Document from './document.js' +import Input from './input.js' +import { Stringifier, Syntax } from './postcss.js' +import Result from './result.js' +import Root from './root.js' +import Rule, { RuleProps } from './rule.js' +import Warning, { WarningOptions } from './warning.js' + +declare namespace Node { + export type ChildNode = AtRule.default | Comment | Declaration | Rule + + export type AnyNode = + | AtRule.default + | Comment + | Declaration + | Document + | Root + | Rule + + export type ChildProps = + | AtRuleProps + | CommentProps + | DeclarationProps + | RuleProps + + export interface Position { + /** + * Source line in file. In contrast to `offset` it starts from 1. + */ + column: number + + /** + * Source column in file. + */ + line: number + + /** + * Source offset in file. It starts from 0. + */ + offset: number + } + + export interface Range { + /** + * End position, exclusive. + */ + end: Position + + /** + * Start position, inclusive. + */ + start: Position + } + + /** + * Source represents an interface for the {@link Node.source} property. + */ + export interface Source { + /** + * The inclusive ending position for the source + * code of a node. + * + * However, `end.offset` of a non `Root` node is the exclusive position. + * See https://github.com/postcss/postcss/pull/1879 for details. + * + * ```js + * const root = postcss.parse('a { color: black }') + * const a = root.first + * const color = a.first + * + * // The offset of `Root` node is the inclusive position + * css.source.end // { line: 1, column: 19, offset: 18 } + * + * // The offset of non `Root` node is the exclusive position + * a.source.end // { line: 1, column: 18, offset: 18 } + * color.source.end // { line: 1, column: 16, offset: 16 } + * ``` + */ + end?: Position + + /** + * The source file from where a node has originated. + */ + input: Input + + /** + * The inclusive starting position for the source + * code of a node. + */ + start?: Position + } + + /** + * Interface represents an interface for an object received + * as parameter by Node class constructor. + */ + export interface NodeProps { + source?: Source + } + + export interface NodeErrorOptions { + /** + * An ending index inside a node's string that should be highlighted as + * source of error. + */ + endIndex?: number + /** + * An index inside a node's string that should be highlighted as source + * of error. + */ + index?: number + /** + * Plugin name that created this error. PostCSS will set it automatically. + */ + plugin?: string + /** + * A word inside a node's string, that should be highlighted as source + * of error. + */ + word?: string + } + + + class Node extends Node_ {} + export { Node as default } +} + +/** + * It represents an abstract class that handles common + * methods for other CSS abstract syntax tree nodes. + * + * Any node that represents CSS selector or value should + * not extend the `Node` class. + */ +declare abstract class Node_ { + /** + * It represents parent of the current node. + * + * ```js + * root.nodes[0].parent === root //=> true + * ``` + */ + parent: Container | Document | undefined + + /** + * It represents unnecessary whitespace and characters present + * in the css source code. + * + * Information to generate byte-to-byte equal node string as it was + * in the origin input. + * + * The properties of the raws object are decided by parser, + * the default parser uses the following properties: + * + * * `before`: the space symbols before the node. It also stores `*` + * and `_` symbols before the declaration (IE hack). + * * `after`: the space symbols after the last child of the node + * to the end of the node. + * * `between`: the symbols between the property and value + * for declarations, selector and `{` for rules, or last parameter + * and `{` for at-rules. + * * `semicolon`: contains true if the last child has + * an (optional) semicolon. + * * `afterName`: the space between the at-rule name and its parameters. + * * `left`: the space symbols between `/*` and the comment’s text. + * * `right`: the space symbols between the comment’s text + * and */. + * - `important`: the content of the important statement, + * if it is not just `!important`. + * + * PostCSS filters out the comments inside selectors, declaration values + * and at-rule parameters but it stores the origin content in raws. + * + * ```js + * const root = postcss.parse('a {\n color:black\n}') + * root.first.first.raws //=> { before: '\n ', between: ':' } + * ``` + */ + raws: any + + /** + * It represents information related to origin of a node and is required + * for generating source maps. + * + * The nodes that are created manually using the public APIs + * provided by PostCSS will have `source` undefined and + * will be absent in the source map. + * + * For this reason, the plugin developer should consider + * duplicating nodes as the duplicate node will have the + * same source as the original node by default or assign + * source to a node created manually. + * + * ```js + * decl.source.input.from //=> '/home/ai/source.css' + * decl.source.start //=> { line: 10, column: 2 } + * decl.source.end //=> { line: 10, column: 12 } + * ``` + * + * ```js + * // Incorrect method, source not specified! + * const prefixed = postcss.decl({ + * prop: '-moz-' + decl.prop, + * value: decl.value + * }) + * + * // Correct method, source is inherited when duplicating. + * const prefixed = decl.clone({ + * prop: '-moz-' + decl.prop + * }) + * ``` + * + * ```js + * if (atrule.name === 'add-link') { + * const rule = postcss.rule({ + * selector: 'a', + * source: atrule.source + * }) + * + * atrule.parent.insertBefore(atrule, rule) + * } + * ``` + */ + source?: Node.Source + + /** + * It represents type of a node in + * an abstract syntax tree. + * + * A type of node helps in identification of a node + * and perform operation based on it's type. + * + * ```js + * const declaration = new Declaration({ + * prop: 'color', + * value: 'black' + * }) + * + * declaration.type //=> 'decl' + * ``` + */ + type: string + + constructor(defaults?: object) + + /** + * Insert new node after current node to current node’s parent. + * + * Just alias for `node.parent.insertAfter(node, add)`. + * + * ```js + * decl.after('color: black') + * ``` + * + * @param newNode New node. + * @return This node for methods chain. + */ + after( + newNode: Node | Node.ChildProps | readonly Node[] | string | undefined + ): this + + /** + * It assigns properties to an existing node instance. + * + * ```js + * decl.assign({ prop: 'word-wrap', value: 'break-word' }) + * ``` + * + * @param overrides New properties to override the node. + * + * @return `this` for method chaining. + */ + assign(overrides: object): this + + /** + * Insert new node before current node to current node’s parent. + * + * Just alias for `node.parent.insertBefore(node, add)`. + * + * ```js + * decl.before('content: ""') + * ``` + * + * @param newNode New node. + * @return This node for methods chain. + */ + before( + newNode: Node | Node.ChildProps | readonly Node[] | string | undefined + ): this + + /** + * Clear the code style properties for the node and its children. + * + * ```js + * node.raws.before //=> ' ' + * node.cleanRaws() + * node.raws.before //=> undefined + * ``` + * + * @param keepBetween Keep the `raws.between` symbols. + */ + cleanRaws(keepBetween?: boolean): void + + /** + * It creates clone of an existing node, which includes all the properties + * and their values, that includes `raws` but not `type`. + * + * ```js + * decl.raws.before //=> "\n " + * const cloned = decl.clone({ prop: '-moz-' + decl.prop }) + * cloned.raws.before //=> "\n " + * cloned.toString() //=> -moz-transform: scale(0) + * ``` + * + * @param overrides New properties to override in the clone. + * + * @return Duplicate of the node instance. + */ + clone(overrides?: object): this + + /** + * Shortcut to clone the node and insert the resulting cloned node + * after the current node. + * + * @param overrides New properties to override in the clone. + * @return New node. + */ + cloneAfter(overrides?: object): this + + /** + * Shortcut to clone the node and insert the resulting cloned node + * before the current node. + * + * ```js + * decl.cloneBefore({ prop: '-moz-' + decl.prop }) + * ``` + * + * @param overrides Mew properties to override in the clone. + * + * @return New node + */ + cloneBefore(overrides?: object): this + + /** + * It creates an instance of the class `CssSyntaxError` and parameters passed + * to this method are assigned to the error instance. + * + * The error instance will have description for the + * error, original position of the node in the + * source, showing line and column number. + * + * If any previous map is present, it would be used + * to get original position of the source. + * + * The Previous Map here is referred to the source map + * generated by previous compilation, example: Less, + * Stylus and Sass. + * + * This method returns the error instance instead of + * throwing it. + * + * ```js + * if (!variables[name]) { + * throw decl.error(`Unknown variable ${name}`, { word: name }) + * // CssSyntaxError: postcss-vars:a.sass:4:3: Unknown variable $black + * // color: $black + * // a + * // ^ + * // background: white + * } + * ``` + * + * @param message Description for the error instance. + * @param options Options for the error instance. + * + * @return Error instance is returned. + */ + error(message: string, options?: Node.NodeErrorOptions): CssSyntaxError + + /** + * Returns the next child of the node’s parent. + * Returns `undefined` if the current node is the last child. + * + * ```js + * if (comment.text === 'delete next') { + * const next = comment.next() + * if (next) { + * next.remove() + * } + * } + * ``` + * + * @return Next node. + */ + next(): Node.ChildNode | undefined + + /** + * Get the position for a word or an index inside the node. + * + * @param opts Options. + * @return Position. + */ + positionBy(opts?: Pick): Node.Position + + /** + * Convert string index to line/column. + * + * @param index The symbol number in the node’s string. + * @return Symbol position in file. + */ + positionInside(index: number): Node.Position + + /** + * Returns the previous child of the node’s parent. + * Returns `undefined` if the current node is the first child. + * + * ```js + * const annotation = decl.prev() + * if (annotation.type === 'comment') { + * readAnnotation(annotation.text) + * } + * ``` + * + * @return Previous node. + */ + prev(): Node.ChildNode | undefined + + /** + * Get the range for a word or start and end index inside the node. + * The start index is inclusive; the end index is exclusive. + * + * @param opts Options. + * @return Range. + */ + rangeBy( + opts?: Pick + ): Node.Range + + /** + * Returns a `raws` value. If the node is missing + * the code style property (because the node was manually built or cloned), + * PostCSS will try to autodetect the code style property by looking + * at other nodes in the tree. + * + * ```js + * const root = postcss.parse('a { background: white }') + * root.nodes[0].append({ prop: 'color', value: 'black' }) + * root.nodes[0].nodes[1].raws.before //=> undefined + * root.nodes[0].nodes[1].raw('before') //=> ' ' + * ``` + * + * @param prop Name of code style property. + * @param defaultType Name of default value, it can be missed + * if the value is the same as prop. + * @return {string} Code style value. + */ + raw(prop: string, defaultType?: string): string + + /** + * It removes the node from its parent and deletes its parent property. + * + * ```js + * if (decl.prop.match(/^-webkit-/)) { + * decl.remove() + * } + * ``` + * + * @return `this` for method chaining. + */ + remove(): this + + /** + * Inserts node(s) before the current node and removes the current node. + * + * ```js + * AtRule: { + * mixin: atrule => { + * atrule.replaceWith(mixinRules[atrule.params]) + * } + * } + * ``` + * + * @param nodes Mode(s) to replace current one. + * @return Current node to methods chain. + */ + replaceWith(...nodes: NewChild[]): this + + /** + * Finds the Root instance of the node’s tree. + * + * ```js + * root.nodes[0].nodes[0].root() === root + * ``` + * + * @return Root parent. + */ + root(): Root + + /** + * Fix circular links on `JSON.stringify()`. + * + * @return Cleaned object. + */ + toJSON(): object + + /** + * It compiles the node to browser readable cascading style sheets string + * depending on it's type. + * + * ```js + * new Rule({ selector: 'a' }).toString() //=> "a {}" + * ``` + * + * @param stringifier A syntax to use in string generation. + * @return CSS string of this node. + */ + toString(stringifier?: Stringifier | Syntax): string + + /** + * It is a wrapper for {@link Result#warn}, providing convenient + * way of generating warnings. + * + * ```js + * Declaration: { + * bad: (decl, { result }) => { + * decl.warn(result, 'Deprecated property: bad') + * } + * } + * ``` + * + * @param result The `Result` instance that will receive the warning. + * @param message Description for the warning. + * @param options Options for the warning. + * + * @return `Warning` instance is returned + */ + warn(result: Result, message: string, options?: WarningOptions): Warning + + /** + * If this node isn't already dirty, marks it and its ancestors as such. This + * indicates to the LazyResult processor that the {@link Root} has been + * modified by the current plugin and may need to be processed again by other + * plugins. + */ + protected markDirty(): void +} + +declare class Node extends Node_ {} + +export = Node diff --git a/frontend/node_modules/postcss/lib/node.js b/frontend/node_modules/postcss/lib/node.js new file mode 100644 index 0000000..b403b71 --- /dev/null +++ b/frontend/node_modules/postcss/lib/node.js @@ -0,0 +1,449 @@ +'use strict' + +let CssSyntaxError = require('./css-syntax-error') +let Stringifier = require('./stringifier') +let stringify = require('./stringify') +let { isClean, my } = require('./symbols') + +function cloneNode(obj, parent) { + let cloned = new obj.constructor() + + for (let i in obj) { + if (!Object.prototype.hasOwnProperty.call(obj, i)) { + /* c8 ignore next 2 */ + continue + } + if (i === 'proxyCache') continue + let value = obj[i] + let type = typeof value + + if (i === 'parent' && type === 'object') { + if (parent) cloned[i] = parent + } else if (i === 'source') { + cloned[i] = value + } else if (Array.isArray(value)) { + cloned[i] = value.map(j => cloneNode(j, cloned)) + } else { + if (type === 'object' && value !== null) value = cloneNode(value) + cloned[i] = value + } + } + + return cloned +} + +function sourceOffset(inputCSS, position) { + // Not all custom syntaxes support `offset` in `source.start` and `source.end` + if (position && typeof position.offset !== 'undefined') { + return position.offset + } + + let column = 1 + let line = 1 + let offset = 0 + + for (let i = 0; i < inputCSS.length; i++) { + if (line === position.line && column === position.column) { + offset = i + break + } + + if (inputCSS[i] === '\n') { + column = 1 + line += 1 + } else { + column += 1 + } + } + + return offset +} + +class Node { + get proxyOf() { + return this + } + + constructor(defaults = {}) { + this.raws = {} + this[isClean] = false + this[my] = true + + for (let name in defaults) { + if (name === 'nodes') { + this.nodes = [] + for (let node of defaults[name]) { + if (typeof node.clone === 'function') { + this.append(node.clone()) + } else { + this.append(node) + } + } + } else { + this[name] = defaults[name] + } + } + } + + addToError(error) { + error.postcssNode = this + if (error.stack && this.source && /\n\s{4}at /.test(error.stack)) { + let s = this.source + error.stack = error.stack.replace( + /\n\s{4}at /, + `$&${s.input.from}:${s.start.line}:${s.start.column}$&` + ) + } + return error + } + + after(add) { + this.parent.insertAfter(this, add) + return this + } + + assign(overrides = {}) { + for (let name in overrides) { + this[name] = overrides[name] + } + return this + } + + before(add) { + this.parent.insertBefore(this, add) + return this + } + + cleanRaws(keepBetween) { + delete this.raws.before + delete this.raws.after + if (!keepBetween) delete this.raws.between + } + + clone(overrides = {}) { + let cloned = cloneNode(this) + for (let name in overrides) { + cloned[name] = overrides[name] + } + return cloned + } + + cloneAfter(overrides = {}) { + let cloned = this.clone(overrides) + this.parent.insertAfter(this, cloned) + return cloned + } + + cloneBefore(overrides = {}) { + let cloned = this.clone(overrides) + this.parent.insertBefore(this, cloned) + return cloned + } + + error(message, opts = {}) { + if (this.source) { + let { end, start } = this.rangeBy(opts) + return this.source.input.error( + message, + { column: start.column, line: start.line }, + { column: end.column, line: end.line }, + opts + ) + } + return new CssSyntaxError(message) + } + + getProxyProcessor() { + return { + get(node, prop) { + if (prop === 'proxyOf') { + return node + } else if (prop === 'root') { + return () => node.root().toProxy() + } else { + return node[prop] + } + }, + + set(node, prop, value) { + if (node[prop] === value) return true + node[prop] = value + if ( + prop === 'prop' || + prop === 'value' || + prop === 'name' || + prop === 'params' || + prop === 'important' || + /* c8 ignore next */ + prop === 'text' + ) { + node.markDirty() + } + return true + } + } + } + + /* c8 ignore next 3 */ + markClean() { + this[isClean] = true + } + + markDirty() { + if (this[isClean]) { + this[isClean] = false + let next = this + while ((next = next.parent)) { + next[isClean] = false + } + } + } + + next() { + if (!this.parent) return undefined + let index = this.parent.index(this) + return this.parent.nodes[index + 1] + } + + positionBy(opts = {}) { + let pos = this.source.start + if (opts.index) { + pos = this.positionInside(opts.index) + } else if (opts.word) { + let inputString = + 'document' in this.source.input + ? this.source.input.document + : this.source.input.css + let stringRepresentation = inputString.slice( + sourceOffset(inputString, this.source.start), + sourceOffset(inputString, this.source.end) + ) + let index = stringRepresentation.indexOf(opts.word) + if (index !== -1) pos = this.positionInside(index) + } + return pos + } + + positionInside(index) { + let column = this.source.start.column + let line = this.source.start.line + let inputString = + 'document' in this.source.input + ? this.source.input.document + : this.source.input.css + let offset = sourceOffset(inputString, this.source.start) + let end = offset + index + + for (let i = offset; i < end; i++) { + if (inputString[i] === '\n') { + column = 1 + line += 1 + } else { + column += 1 + } + } + + return { column, line, offset: end } + } + + prev() { + if (!this.parent) return undefined + let index = this.parent.index(this) + return this.parent.nodes[index - 1] + } + + rangeBy(opts = {}) { + let inputString = + 'document' in this.source.input + ? this.source.input.document + : this.source.input.css + let start = { + column: this.source.start.column, + line: this.source.start.line, + offset: sourceOffset(inputString, this.source.start) + } + let end = this.source.end + ? { + column: this.source.end.column + 1, + line: this.source.end.line, + offset: + typeof this.source.end.offset === 'number' + ? // `source.end.offset` is exclusive, so we don't need to add 1 + this.source.end.offset + : // Since line/column in this.source.end is inclusive, + // the `sourceOffset(... , this.source.end)` returns an inclusive offset. + // So, we add 1 to convert it to exclusive. + sourceOffset(inputString, this.source.end) + 1 + } + : { + column: start.column + 1, + line: start.line, + offset: start.offset + 1 + } + + if (opts.word) { + let stringRepresentation = inputString.slice( + sourceOffset(inputString, this.source.start), + sourceOffset(inputString, this.source.end) + ) + let index = stringRepresentation.indexOf(opts.word) + if (index !== -1) { + start = this.positionInside(index) + end = this.positionInside(index + opts.word.length) + } + } else { + if (opts.start) { + start = { + column: opts.start.column, + line: opts.start.line, + offset: sourceOffset(inputString, opts.start) + } + } else if (opts.index) { + start = this.positionInside(opts.index) + } + + if (opts.end) { + end = { + column: opts.end.column, + line: opts.end.line, + offset: sourceOffset(inputString, opts.end) + } + } else if (typeof opts.endIndex === 'number') { + end = this.positionInside(opts.endIndex) + } else if (opts.index) { + end = this.positionInside(opts.index + 1) + } + } + + if ( + end.line < start.line || + (end.line === start.line && end.column <= start.column) + ) { + end = { + column: start.column + 1, + line: start.line, + offset: start.offset + 1 + } + } + + return { end, start } + } + + raw(prop, defaultType) { + let str = new Stringifier() + return str.raw(this, prop, defaultType) + } + + remove() { + if (this.parent) { + this.parent.removeChild(this) + } + this.parent = undefined + return this + } + + replaceWith(...nodes) { + if (this.parent) { + let bookmark = this + let foundSelf = false + for (let node of nodes) { + if (node === this) { + foundSelf = true + } else if (foundSelf) { + this.parent.insertAfter(bookmark, node) + bookmark = node + } else { + this.parent.insertBefore(bookmark, node) + } + } + + if (!foundSelf) { + this.remove() + } + } + + return this + } + + root() { + let result = this + while (result.parent && result.parent.type !== 'document') { + result = result.parent + } + return result + } + + toJSON(_, inputs) { + let fixed = {} + let emitInputs = inputs == null + inputs = inputs || new Map() + let inputsNextIndex = 0 + + for (let name in this) { + if (!Object.prototype.hasOwnProperty.call(this, name)) { + /* c8 ignore next 2 */ + continue + } + if (name === 'parent' || name === 'proxyCache') continue + let value = this[name] + + if (Array.isArray(value)) { + fixed[name] = value.map(i => { + if (typeof i === 'object' && i.toJSON) { + return i.toJSON(null, inputs) + } else { + return i + } + }) + } else if (typeof value === 'object' && value.toJSON) { + fixed[name] = value.toJSON(null, inputs) + } else if (name === 'source') { + if (value == null) continue + let inputId = inputs.get(value.input) + if (inputId == null) { + inputId = inputsNextIndex + inputs.set(value.input, inputsNextIndex) + inputsNextIndex++ + } + fixed[name] = { + end: value.end, + inputId, + start: value.start + } + } else { + fixed[name] = value + } + } + + if (emitInputs) { + fixed.inputs = [...inputs.keys()].map(input => input.toJSON()) + } + + return fixed + } + + toProxy() { + if (!this.proxyCache) { + this.proxyCache = new Proxy(this, this.getProxyProcessor()) + } + return this.proxyCache + } + + toString(stringifier = stringify) { + if (stringifier.stringify) stringifier = stringifier.stringify + let result = '' + stringifier(this, i => { + result += i + }) + return result + } + + warn(result, text, opts = {}) { + let data = { node: this } + for (let i in opts) data[i] = opts[i] + return result.warn(text, data) + } +} + +module.exports = Node +Node.default = Node diff --git a/frontend/node_modules/postcss/lib/parse.d.ts b/frontend/node_modules/postcss/lib/parse.d.ts new file mode 100644 index 0000000..4c943a4 --- /dev/null +++ b/frontend/node_modules/postcss/lib/parse.d.ts @@ -0,0 +1,9 @@ +import { Parser } from './postcss.js' + +interface Parse extends Parser { + default: Parse +} + +declare const parse: Parse + +export = parse diff --git a/frontend/node_modules/postcss/lib/parse.js b/frontend/node_modules/postcss/lib/parse.js new file mode 100644 index 0000000..00a1037 --- /dev/null +++ b/frontend/node_modules/postcss/lib/parse.js @@ -0,0 +1,42 @@ +'use strict' + +let Container = require('./container') +let Input = require('./input') +let Parser = require('./parser') + +function parse(css, opts) { + let input = new Input(css, opts) + let parser = new Parser(input) + try { + parser.parse() + } catch (e) { + if (process.env.NODE_ENV !== 'production') { + if (e.name === 'CssSyntaxError' && opts && opts.from) { + if (/\.scss$/i.test(opts.from)) { + e.message += + '\nYou tried to parse SCSS with ' + + 'the standard CSS parser; ' + + 'try again with the postcss-scss parser' + } else if (/\.sass/i.test(opts.from)) { + e.message += + '\nYou tried to parse Sass with ' + + 'the standard CSS parser; ' + + 'try again with the postcss-sass parser' + } else if (/\.less$/i.test(opts.from)) { + e.message += + '\nYou tried to parse Less with ' + + 'the standard CSS parser; ' + + 'try again with the postcss-less parser' + } + } + } + throw e + } + + return parser.root +} + +module.exports = parse +parse.default = parse + +Container.registerParse(parse) diff --git a/frontend/node_modules/postcss/lib/parser.js b/frontend/node_modules/postcss/lib/parser.js new file mode 100644 index 0000000..b29ff5b --- /dev/null +++ b/frontend/node_modules/postcss/lib/parser.js @@ -0,0 +1,611 @@ +'use strict' + +let AtRule = require('./at-rule') +let Comment = require('./comment') +let Declaration = require('./declaration') +let Root = require('./root') +let Rule = require('./rule') +let tokenizer = require('./tokenize') + +const SAFE_COMMENT_NEIGHBOR = { + empty: true, + space: true +} + +function findLastWithPosition(tokens) { + for (let i = tokens.length - 1; i >= 0; i--) { + let token = tokens[i] + let pos = token[3] || token[2] + if (pos) return pos + } +} + +class Parser { + constructor(input) { + this.input = input + + this.root = new Root() + this.current = this.root + this.spaces = '' + this.semicolon = false + + this.createTokenizer() + this.root.source = { input, start: { column: 1, line: 1, offset: 0 } } + } + + atrule(token) { + let node = new AtRule() + node.name = token[1].slice(1) + if (node.name === '') { + this.unnamedAtrule(node, token) + } + this.init(node, token[2]) + + let type + let prev + let shift + let last = false + let open = false + let params = [] + let brackets = [] + + while (!this.tokenizer.endOfFile()) { + token = this.tokenizer.nextToken() + type = token[0] + + if (type === '(' || type === '[') { + brackets.push(type === '(' ? ')' : ']') + } else if (type === '{' && brackets.length > 0) { + brackets.push('}') + } else if (type === brackets[brackets.length - 1]) { + brackets.pop() + } + + if (brackets.length === 0) { + if (type === ';') { + node.source.end = this.getPosition(token[2]) + node.source.end.offset++ + this.semicolon = true + break + } else if (type === '{') { + open = true + break + } else if (type === '}') { + if (params.length > 0) { + shift = params.length - 1 + prev = params[shift] + while (prev && prev[0] === 'space') { + prev = params[--shift] + } + if (prev) { + node.source.end = this.getPosition(prev[3] || prev[2]) + node.source.end.offset++ + } + } + this.end(token) + break + } else { + params.push(token) + } + } else { + params.push(token) + } + + if (this.tokenizer.endOfFile()) { + last = true + break + } + } + + node.raws.between = this.spacesAndCommentsFromEnd(params) + if (params.length) { + node.raws.afterName = this.spacesAndCommentsFromStart(params) + this.raw(node, 'params', params) + if (last) { + token = params[params.length - 1] + node.source.end = this.getPosition(token[3] || token[2]) + node.source.end.offset++ + this.spaces = node.raws.between + node.raws.between = '' + } + } else { + node.raws.afterName = '' + node.params = '' + } + + if (open) { + node.nodes = [] + this.current = node + } + } + + checkMissedSemicolon(tokens) { + let colon = this.colon(tokens) + if (colon === false) return + + let founded = 0 + let token + for (let j = colon - 1; j >= 0; j--) { + token = tokens[j] + if (token[0] !== 'space') { + founded += 1 + if (founded === 2) break + } + } + // If the token is a word, e.g. `!important`, `red` or any other valid property's value. + // Then we need to return the colon after that word token. [3] is the "end" colon of that word. + // And because we need it after that one we do +1 to get the next one. + throw this.input.error( + 'Missed semicolon', + token[0] === 'word' ? token[3] + 1 : token[2] + ) + } + + colon(tokens) { + let brackets = 0 + let prev, token, type + for (let [i, element] of tokens.entries()) { + token = element + type = token[0] + + if (type === '(') { + brackets += 1 + } + if (type === ')') { + brackets -= 1 + } + if (brackets === 0 && type === ':') { + if (!prev) { + this.doubleColon(token) + } else if (prev[0] === 'word' && prev[1] === 'progid') { + continue + } else { + return i + } + } + + prev = token + } + return false + } + + comment(token) { + let node = new Comment() + this.init(node, token[2]) + node.source.end = this.getPosition(token[3] || token[2]) + node.source.end.offset++ + + let text = token[1].slice(2, -2) + if (!text.trim()) { + node.text = '' + node.raws.left = text + node.raws.right = '' + } else { + let match = text.match(/^(\s*)([^]*\S)(\s*)$/) + node.text = match[2] + node.raws.left = match[1] + node.raws.right = match[3] + } + } + + createTokenizer() { + this.tokenizer = tokenizer(this.input) + } + + decl(tokens, customProperty) { + let node = new Declaration() + this.init(node, tokens[0][2]) + + let last = tokens[tokens.length - 1] + if (last[0] === ';') { + this.semicolon = true + tokens.pop() + } + + node.source.end = this.getPosition( + last[3] || last[2] || findLastWithPosition(tokens) + ) + node.source.end.offset++ + + while (tokens[0][0] !== 'word') { + if (tokens.length === 1) this.unknownWord(tokens) + node.raws.before += tokens.shift()[1] + } + node.source.start = this.getPosition(tokens[0][2]) + + node.prop = '' + while (tokens.length) { + let type = tokens[0][0] + if (type === ':' || type === 'space' || type === 'comment') { + break + } + node.prop += tokens.shift()[1] + } + + node.raws.between = '' + + let token + while (tokens.length) { + token = tokens.shift() + + if (token[0] === ':') { + node.raws.between += token[1] + break + } else { + if (token[0] === 'word' && /\w/.test(token[1])) { + this.unknownWord([token]) + } + node.raws.between += token[1] + } + } + + if (node.prop[0] === '_' || node.prop[0] === '*') { + node.raws.before += node.prop[0] + node.prop = node.prop.slice(1) + } + + let firstSpaces = [] + let next + while (tokens.length) { + next = tokens[0][0] + if (next !== 'space' && next !== 'comment') break + firstSpaces.push(tokens.shift()) + } + + this.precheckMissedSemicolon(tokens) + + for (let i = tokens.length - 1; i >= 0; i--) { + token = tokens[i] + if (token[1].toLowerCase() === '!important') { + node.important = true + let string = this.stringFrom(tokens, i) + string = this.spacesFromEnd(tokens) + string + if (string !== ' !important') node.raws.important = string + break + } else if (token[1].toLowerCase() === 'important') { + let cache = tokens.slice(0) + let str = '' + for (let j = i; j > 0; j--) { + let type = cache[j][0] + if (str.trim().startsWith('!') && type !== 'space') { + break + } + str = cache.pop()[1] + str + } + if (str.trim().startsWith('!')) { + node.important = true + node.raws.important = str + tokens = cache + } + } + + if (token[0] !== 'space' && token[0] !== 'comment') { + break + } + } + + let hasWord = tokens.some(i => i[0] !== 'space' && i[0] !== 'comment') + + if (hasWord) { + node.raws.between += firstSpaces.map(i => i[1]).join('') + firstSpaces = [] + } + this.raw(node, 'value', firstSpaces.concat(tokens), customProperty) + + if (node.value.includes(':') && !customProperty) { + this.checkMissedSemicolon(tokens) + } + } + + doubleColon(token) { + throw this.input.error( + 'Double colon', + { offset: token[2] }, + { offset: token[2] + token[1].length } + ) + } + + emptyRule(token) { + let node = new Rule() + this.init(node, token[2]) + node.selector = '' + node.raws.between = '' + this.current = node + } + + end(token) { + if (this.current.nodes && this.current.nodes.length) { + this.current.raws.semicolon = this.semicolon + } + this.semicolon = false + + this.current.raws.after = (this.current.raws.after || '') + this.spaces + this.spaces = '' + + if (this.current.parent) { + this.current.source.end = this.getPosition(token[2]) + this.current.source.end.offset++ + this.current = this.current.parent + } else { + this.unexpectedClose(token) + } + } + + endFile() { + if (this.current.parent) this.unclosedBlock() + if (this.current.nodes && this.current.nodes.length) { + this.current.raws.semicolon = this.semicolon + } + this.current.raws.after = (this.current.raws.after || '') + this.spaces + this.root.source.end = this.getPosition(this.tokenizer.position()) + } + + freeSemicolon(token) { + this.spaces += token[1] + if (this.current.nodes) { + let prev = this.current.nodes[this.current.nodes.length - 1] + if (prev && prev.type === 'rule' && !prev.raws.ownSemicolon) { + prev.raws.ownSemicolon = this.spaces + this.spaces = '' + prev.source.end = this.getPosition(token[2]) + prev.source.end.offset += prev.raws.ownSemicolon.length + } + } + } + + // Helpers + + getPosition(offset) { + let pos = this.input.fromOffset(offset) + return { + column: pos.col, + line: pos.line, + offset + } + } + + init(node, offset) { + this.current.push(node) + node.source = { + input: this.input, + start: this.getPosition(offset) + } + node.raws.before = this.spaces + this.spaces = '' + if (node.type !== 'comment') this.semicolon = false + } + + other(start) { + let end = false + let type = null + let colon = false + let bracket = null + let brackets = [] + let customProperty = start[1].startsWith('--') + + let tokens = [] + let token = start + while (token) { + type = token[0] + tokens.push(token) + + if (type === '(' || type === '[') { + if (!bracket) bracket = token + brackets.push(type === '(' ? ')' : ']') + } else if (customProperty && colon && type === '{') { + if (!bracket) bracket = token + brackets.push('}') + } else if (brackets.length === 0) { + if (type === ';') { + if (colon) { + this.decl(tokens, customProperty) + return + } else { + break + } + } else if (type === '{') { + this.rule(tokens) + return + } else if (type === '}') { + this.tokenizer.back(tokens.pop()) + end = true + break + } else if (type === ':') { + colon = true + } + } else if (type === brackets[brackets.length - 1]) { + brackets.pop() + if (brackets.length === 0) bracket = null + } + + token = this.tokenizer.nextToken() + } + + if (this.tokenizer.endOfFile()) end = true + if (brackets.length > 0) this.unclosedBracket(bracket) + + if (end && colon) { + if (!customProperty) { + while (tokens.length) { + token = tokens[tokens.length - 1][0] + if (token !== 'space' && token !== 'comment') break + this.tokenizer.back(tokens.pop()) + } + } + this.decl(tokens, customProperty) + } else { + this.unknownWord(tokens) + } + } + + parse() { + let token + while (!this.tokenizer.endOfFile()) { + token = this.tokenizer.nextToken() + + switch (token[0]) { + case 'space': + this.spaces += token[1] + break + + case ';': + this.freeSemicolon(token) + break + + case '}': + this.end(token) + break + + case 'comment': + this.comment(token) + break + + case 'at-word': + this.atrule(token) + break + + case '{': + this.emptyRule(token) + break + + default: + this.other(token) + break + } + } + this.endFile() + } + + precheckMissedSemicolon(/* tokens */) { + // Hook for Safe Parser + } + + raw(node, prop, tokens, customProperty) { + let token, type + let length = tokens.length + let value = '' + let clean = true + let next, prev + + for (let i = 0; i < length; i += 1) { + token = tokens[i] + type = token[0] + if (type === 'space' && i === length - 1 && !customProperty) { + clean = false + } else if (type === 'comment') { + prev = tokens[i - 1] ? tokens[i - 1][0] : 'empty' + next = tokens[i + 1] ? tokens[i + 1][0] : 'empty' + if (!SAFE_COMMENT_NEIGHBOR[prev] && !SAFE_COMMENT_NEIGHBOR[next]) { + if (value.slice(-1) === ',') { + clean = false + } else { + value += token[1] + } + } else { + clean = false + } + } else { + value += token[1] + } + } + if (!clean) { + let raw = tokens.reduce((all, i) => all + i[1], '') + node.raws[prop] = { raw, value } + } + node[prop] = value + } + + rule(tokens) { + tokens.pop() + + let node = new Rule() + this.init(node, tokens[0][2]) + + node.raws.between = this.spacesAndCommentsFromEnd(tokens) + this.raw(node, 'selector', tokens) + this.current = node + } + + spacesAndCommentsFromEnd(tokens) { + let lastTokenType + let spaces = '' + while (tokens.length) { + lastTokenType = tokens[tokens.length - 1][0] + if (lastTokenType !== 'space' && lastTokenType !== 'comment') break + spaces = tokens.pop()[1] + spaces + } + return spaces + } + + // Errors + + spacesAndCommentsFromStart(tokens) { + let next + let spaces = '' + while (tokens.length) { + next = tokens[0][0] + if (next !== 'space' && next !== 'comment') break + spaces += tokens.shift()[1] + } + return spaces + } + + spacesFromEnd(tokens) { + let lastTokenType + let spaces = '' + while (tokens.length) { + lastTokenType = tokens[tokens.length - 1][0] + if (lastTokenType !== 'space') break + spaces = tokens.pop()[1] + spaces + } + return spaces + } + + stringFrom(tokens, from) { + let result = '' + for (let i = from; i < tokens.length; i++) { + result += tokens[i][1] + } + tokens.splice(from, tokens.length - from) + return result + } + + unclosedBlock() { + let pos = this.current.source.start + throw this.input.error('Unclosed block', pos.line, pos.column) + } + + unclosedBracket(bracket) { + throw this.input.error( + 'Unclosed bracket', + { offset: bracket[2] }, + { offset: bracket[2] + 1 } + ) + } + + unexpectedClose(token) { + throw this.input.error( + 'Unexpected }', + { offset: token[2] }, + { offset: token[2] + 1 } + ) + } + + unknownWord(tokens) { + throw this.input.error( + 'Unknown word ' + tokens[0][1], + { offset: tokens[0][2] }, + { offset: tokens[0][2] + tokens[0][1].length } + ) + } + + unnamedAtrule(node, token) { + throw this.input.error( + 'At-rule without name', + { offset: token[2] }, + { offset: token[2] + token[1].length } + ) + } +} + +module.exports = Parser diff --git a/frontend/node_modules/postcss/lib/postcss.d.mts b/frontend/node_modules/postcss/lib/postcss.d.mts new file mode 100644 index 0000000..d343f3c --- /dev/null +++ b/frontend/node_modules/postcss/lib/postcss.d.mts @@ -0,0 +1,69 @@ +export { + // Type-only exports + AcceptedPlugin, + + AnyNode, + atRule, + AtRule, + AtRuleProps, + Builder, + ChildNode, + ChildProps, + comment, + Comment, + CommentProps, + Container, + ContainerProps, + CssSyntaxError, + decl, + Declaration, + DeclarationProps, + // postcss function / namespace + default, + document, + Document, + DocumentProps, + FilePosition, + fromJSON, + Helpers, + Input, + + JSONHydrator, + // This is a class, but it’s not re-exported. That’s why it’s exported as type-only here. + type LazyResult, + list, + Message, + Node, + NodeErrorOptions, + NodeProps, + OldPlugin, + parse, + Parser, + // @ts-expect-error This value exists, but it’s untyped. + plugin, + Plugin, + PluginCreator, + Position, + Postcss, + ProcessOptions, + Processor, + Result, + root, + Root, + RootProps, + rule, + Rule, + RuleProps, + Source, + SourceMap, + SourceMapOptions, + Stringifier, + // Value exports from postcss.mjs + stringify, + Syntax, + TransformCallback, + Transformer, + Warning, + + WarningOptions +} from './postcss.js' diff --git a/frontend/node_modules/postcss/lib/postcss.d.ts b/frontend/node_modules/postcss/lib/postcss.d.ts new file mode 100644 index 0000000..c5e3605 --- /dev/null +++ b/frontend/node_modules/postcss/lib/postcss.d.ts @@ -0,0 +1,458 @@ +import { RawSourceMap, SourceMapGenerator } from 'source-map-js' + +import AtRule, { AtRuleProps } from './at-rule.js' +import Comment, { CommentProps } from './comment.js' +import Container, { ContainerProps, NewChild } from './container.js' +import CssSyntaxError from './css-syntax-error.js' +import Declaration, { DeclarationProps } from './declaration.js' +import Document, { DocumentProps } from './document.js' +import Input, { FilePosition } from './input.js' +import LazyResult from './lazy-result.js' +import list from './list.js' +import Node, { + AnyNode, + ChildNode, + ChildProps, + NodeErrorOptions, + NodeProps, + Position, + Source +} from './node.js' +import Processor from './processor.js' +import Result, { Message } from './result.js' +import Root, { RootProps } from './root.js' +import Rule, { RuleProps } from './rule.js' +import Warning, { WarningOptions } from './warning.js' + +type DocumentProcessor = ( + document: Document, + helper: postcss.Helpers +) => Promise | void +type RootProcessor = ( + root: Root, + helper: postcss.Helpers +) => Promise | void +type DeclarationProcessor = ( + decl: Declaration, + helper: postcss.Helpers +) => Promise | void +type RuleProcessor = ( + rule: Rule, + helper: postcss.Helpers +) => Promise | void +type AtRuleProcessor = ( + atRule: AtRule, + helper: postcss.Helpers +) => Promise | void +type CommentProcessor = ( + comment: Comment, + helper: postcss.Helpers +) => Promise | void + +interface Processors { + /** + * Will be called on all`AtRule` nodes. + * + * Will be called again on node or children changes. + */ + AtRule?: { [name: string]: AtRuleProcessor } | AtRuleProcessor + + /** + * Will be called on all `AtRule` nodes, when all children will be processed. + * + * Will be called again on node or children changes. + */ + AtRuleExit?: { [name: string]: AtRuleProcessor } | AtRuleProcessor + + /** + * Will be called on all `Comment` nodes. + * + * Will be called again on node or children changes. + */ + Comment?: CommentProcessor + + /** + * Will be called on all `Comment` nodes after listeners + * for `Comment` event. + * + * Will be called again on node or children changes. + */ + CommentExit?: CommentProcessor + + /** + * Will be called on all `Declaration` nodes after listeners + * for `Declaration` event. + * + * Will be called again on node or children changes. + */ + Declaration?: { [prop: string]: DeclarationProcessor } | DeclarationProcessor + + /** + * Will be called on all `Declaration` nodes. + * + * Will be called again on node or children changes. + */ + DeclarationExit?: + | { [prop: string]: DeclarationProcessor } + | DeclarationProcessor + + /** + * Will be called on `Document` node. + * + * Will be called again on children changes. + */ + Document?: DocumentProcessor + + /** + * Will be called on `Document` node, when all children will be processed. + * + * Will be called again on children changes. + */ + DocumentExit?: DocumentProcessor + + /** + * Will be called on `Root` node once. + */ + Once?: RootProcessor + + /** + * Will be called on `Root` node once, when all children will be processed. + */ + OnceExit?: RootProcessor + + /** + * Will be called on `Root` node. + * + * Will be called again on children changes. + */ + Root?: RootProcessor + + /** + * Will be called on `Root` node, when all children will be processed. + * + * Will be called again on children changes. + */ + RootExit?: RootProcessor + + /** + * Will be called on all `Rule` nodes. + * + * Will be called again on node or children changes. + */ + Rule?: RuleProcessor + + /** + * Will be called on all `Rule` nodes, when all children will be processed. + * + * Will be called again on node or children changes. + */ + RuleExit?: RuleProcessor +} + +declare namespace postcss { + export { + AnyNode, + AtRule, + AtRuleProps, + ChildNode, + ChildProps, + Comment, + CommentProps, + Container, + ContainerProps, + CssSyntaxError, + Declaration, + DeclarationProps, + Document, + DocumentProps, + FilePosition, + Input, + LazyResult, + list, + Message, + NewChild, + Node, + NodeErrorOptions, + NodeProps, + Position, + Processor, + Result, + Root, + RootProps, + Rule, + RuleProps, + Source, + Warning, + WarningOptions + } + + export type SourceMap = { + toJSON(): RawSourceMap + } & SourceMapGenerator + + export type Helpers = { postcss: Postcss; result: Result } & Postcss + + export interface Plugin extends Processors { + postcssPlugin: string + prepare?: (result: Result) => Processors + } + + export interface PluginCreator { + (opts?: PluginOptions): Plugin | Processor + postcss: true + } + + export interface Transformer extends TransformCallback { + postcssPlugin: string + postcssVersion: string + } + + export interface TransformCallback { + (root: Root, result: Result): Promise | void + } + + export interface OldPlugin extends Transformer { + (opts?: T): Transformer + postcss: Transformer + } + + export type AcceptedPlugin = + | { + postcss: Processor | TransformCallback + } + | OldPlugin + | Plugin + | PluginCreator + | Processor + | TransformCallback + + export interface Parser { + ( + css: { toString(): string } | string, + opts?: Pick + ): RootNode + } + + export interface Builder { + (part: string, node?: AnyNode, type?: 'end' | 'start'): void + } + + export interface Stringifier { + (node: AnyNode, builder: Builder): void + } + + export interface JSONHydrator { + (data: object): Node + (data: object[]): Node[] + } + + export interface Syntax { + /** + * Function to generate AST by string. + */ + parse?: Parser + + /** + * Class to generate string by AST. + */ + stringify?: Stringifier + } + + export interface SourceMapOptions { + /** + * Use absolute path in generated source map. + */ + absolute?: boolean + + /** + * Indicates that PostCSS should add annotation comments to the CSS. + * By default, PostCSS will always add a comment with a path + * to the source map. PostCSS will not add annotations to CSS files + * that do not contain any comments. + * + * By default, PostCSS presumes that you want to save the source map as + * `opts.to + '.map'` and will use this path in the annotation comment. + * A different path can be set by providing a string value for annotation. + * + * If you have set `inline: true`, annotation cannot be disabled. + */ + annotation?: ((file: string, root: Root) => string) | boolean | string + + /** + * Override `from` in map’s sources. + */ + from?: string + + /** + * Indicates that the source map should be embedded in the output CSS + * as a Base64-encoded comment. By default, it is `true`. + * But if all previous maps are external, not inline, PostCSS will not embed + * the map even if you do not set this option. + * + * If you have an inline source map, the result.map property will be empty, + * as the source map will be contained within the text of `result.css`. + */ + inline?: boolean + + /** + * Source map content from a previous processing step (e.g., Sass). + * + * PostCSS will try to read the previous source map + * automatically (based on comments within the source CSS), but you can use + * this option to identify it manually. + * + * If desired, you can omit the previous map with prev: `false`. + */ + prev?: ((file: string) => string) | boolean | object | string + + /** + * Indicates that PostCSS should set the origin content (e.g., Sass source) + * of the source map. By default, it is true. But if all previous maps do not + * contain sources content, PostCSS will also leave it out even if you + * do not set this option. + */ + sourcesContent?: boolean + } + + export interface ProcessOptions { + /** + * Input file if it is not simple CSS file, but HTML with ")},SvelteBoundary(t,n){qP(t,n,e)},SvelteComponent(t,n){n.write("0?(n.write(">"),IP(n,t.fragment,!0),n.write("")):n.write(" />")},SvelteDocument(t,n){qP(t,n,e)},SvelteElement(t,n){n.write("0?(n.write(">"),IP(n,t.fragment),n.write("")):n.write(" />")},SvelteFragment(t,n){qP(t,n,e)},SvelteHead(t,n){qP(t,n,e)},SvelteSelf(t,n){qP(t,n,e)},SvelteWindow(t,n){qP(t,n,e)},Text(e,t){t.write(e.data)},TitleElement(t,n){qP(t,n,e)},TransitionDirective(e,t){const n=e.intro&&e.outro?"transition":e.intro?"in":"out";t.write(`${n}:${e.name}`);for(const n of e.modifiers)t.write(`|${n}`);null===e.expression||"Identifier"===e.expression.type&&e.expression.name===e.name||(t.write("={"),t.visit(e.expression),t.write("}"))},UseDirective(e,t){t.write(`use:${e.name}`),null===e.expression||"Identifier"===e.expression.type&&e.expression.name===e.name||(t.write("={"),t.visit(e.expression),t.write("}"))}}),NP=/(]+>)([\S\s]*?)(<\/style>)/g,DP="/*$$__STYLE_CONTENT__$$*/";let jP=!1;class BP extends Error{constructor(e){super(e)}}function FP(e,t){let n=1,s=e,r=t[s];for(;0!==n&&r;)"("===r&&n++,")"===r&&n--,s++,r=t[s];return s}const VP={_(e,{state:t,next:n}){const s=e.leadingComments;if(s)for(const e of s)if("Line"===e.type){const n=kt(e.value);n!==e.value&&t.str.overwrite(e.start+2,e.end,n)}n()},Identifier(e,{state:t,path:n}){QP(e,t,n)},ImportDeclaration(e,{state:t}){if(t.props_insertion_point=e.end??t.props_insertion_point,"svelte"===e.source.value){let n=[],s=0;for(let r of e.specifiers)if("ImportSpecifier"===r.type&&"Identifier"===r.imported.type&&["beforeUpdate","afterUpdate"].includes(r.imported.name)){if(!t.scope.references.get(r.local.name)){let e=-1!==t.str.original.indexOf(",",r.end)&&t.str.original.indexOf(",",r.end)0)throw new BP(`Can't migrate code with ${n.join(" and ")}. Please migrate by hand.`)}},ExportNamedDeclaration(e,{state:t,next:n}){if(e.declaration)return void n();let s=0;for(const n of e.specifiers){if("Identifier"!==n.local.type)continue;const e=t.scope.get(n.local.name);"bindable_prop"===e?.kind&&(t.str.remove(n.start,n.end),s++)}s===e.specifiers.length&&t.str.remove(e.start,e.end)},VariableDeclaration(e,{state:t,path:n,visit:s,next:r}){if(t.scope!==t.analysis.instance.scope)return;let a=0;for(let i=0;i"state"===e.kind)),p=l.some((e=>"bindable_prop"===e.kind));if(c||p)if(p){if(a++,"Identifier"!==o.id.type)throw new BP("Encountered an export declaration pattern that is not supported for automigration.");const h=o.id.name,m=t.scope.get(h);if(t.analysis.uses_props&&(o.init||m.updated))throw new BP("$$props is used together with named props in a way that cannot be automatically migrated.");const f=t.props.find((e=>e.exported===(m.prop_alias||h)));f?(r(),f.init=o.init?t.str.snip(o.init.start,o.init.end).toString():"",f.bindable=m.updated,f.exported=m.prop_alias||h,f.type_only=!1):(r(),t.props.push({local:h,exported:m.prop_alias?m.prop_alias:h,init:o.init?t.str.snip(o.init.start,o.init.end).toString():"",optional:!!o.init,bindable:m.updated,...WP(o,t,n)}));let y=o.start,v=o.end;e.declarations.length>1?(t.props_insertion_point=e.end,0!==i&&(y=t.str.original.indexOf(",",e.declarations[i-1].end)),i!==e.declarations.length-1&&(v=0===i?e.declarations[i+1].start:t.str.original.lastIndexOf(",",e.declarations[i+1].start))):t.props_insertion_point=o.end,t.str.update(y,v,"")}else if(o.init){let{start:g,end:b}=o.init;if("SequenceExpression"===o.init.type){for(;"("!==t.str.original[g];)g-=1;for(;")"!==t.str.original[b-1];)b+=1}u("state"),t.str.prependLeft(g,"$state("),t.str.appendRight(b,")")}else{let _,x;const w=l.every((e=>e.references.every((t=>{const n=t.path.find((e=>"VariableDeclaration"===e.type)),s=t.path.find((e=>"AssignmentExpression"===e.type)),r=t.path.find((e=>"UpdateExpression"===e.type)),a=t.path.find((e=>"LabeledStatement"===e.type&&"$"===e.label.name));if(s&&a&&("ExpressionStatement"!==a.body.type||a.body.expression!==s||"Identifier"===s.left.type&&s.left.name===e.node.name)){if(_)return!1;_=s,x=a}return!r&&(n&&e.initial||a&&s||!a&&!s)})))),k="BlockStatement"===x?.body.type&&1===x.body.body.length&&"ExpressionStatement"===x.body.body[0].type,C="ExpressionStatement"===x?.body.type&&"AssignmentExpression"===x.body.expression.type;let S=!1;if(C){const P=x?.body,E=P.expression,[,T]=ao(E.right);0===T.length&&(S=!0,t.derived_labeled_statements.add(x))}if(!S&&w&&_&&x&&(k||C)){const A=t.str.original.substring(t.str.original.lastIndexOf("\n",e.start)+1,e.start);if("BlockStatement"===x.body.type&&x.body.body[0].leadingComments)for(let $ of x.body.body[0].leadingComments)t.str.prependLeft(e.start,"Block"===$.type?`/*${$.value}*/\n${A}`:`// ${$.value}\n${A}`);if(u("derived"),t.str.appendRight(o.id.typeAnnotation?.end??o.id.end," = $derived("),s(_.right),t.str.appendRight(o.id.typeAnnotation?.end??o.id.end,t.str.snip(_.right.start,_.right.end).toString()),t.str.remove(x.start,x.end),t.str.appendRight(o.id.typeAnnotation?.end??o.id.end,")"),t.derived_labeled_statements.add(x),"BlockStatement"===x.body.type&&x.body.body[0].trailingComments)for(let R of x.body.body[0].trailingComments)t.str.appendRight(o.id.typeAnnotation?.end??o.id.end,"Block"===R.type?`\n${A}/*${R.value}*/`:`\n${A}// ${R.value}`)}else u("state"),t.str.prependLeft(o.id.typeAnnotation?.end??o.id.end," = $state("),S&&(t.str.appendRight(o.id.typeAnnotation?.end??o.id.end,t.str.snip(_.right.start,_.right.end).toString()),t.str.remove(x.start,x.end)),t.str.appendRight(o.id.typeAnnotation?.end??o.id.end,")")}else r();function u(n){if(!!t.scope.get(n))throw new BP(`can't migrate \`${t.str.original.substring(e.start,e.end)}\` to \`$${n}\` because there's a variable named ${n}.\n Rename the variable and try again or migrate by hand.`)}}if(a===e.declarations.length){let I=e.start,M=e.end;const q=n.at(-1);for("ExportNamedDeclaration"===q?.type&&(I=q.start,M=q.end);"\n"!==t.str.original[I];)I--;for(;"\n"!==t.str.original[M];)M++;t.str.update(I,M,"")}},BreakStatement(e,{state:t,path:n}){"LabeledStatement"===n[1].type&&"$"===e.label?.name&&t.str.update(e.start,e.end,"return;")},LabeledStatement(e,{path:t,state:n,next:s}){if(n.analysis.runes)return;if(t.length>1)return;if("$"!==e.label.name)return;if(n.derived_labeled_statements.has(e))return;function r(t){if(n.scope.get(t))throw new BP(`can't migrate \`$: ${n.str.original.substring(e.body.start,e.body.end)}\` to \`$${t}\` because there's a variable named ${t}.\n Rename the variable and try again or migrate by hand.`)}if(s(),"ExpressionStatement"===e.body.type&&"AssignmentExpression"===e.body.expression.type){const{left:t,right:s}=e.body.expression,a=ro(t),[,i]=ao(s),o=a.map((e=>n.scope.get(e.name)));if(o.every((e=>"legacy_reactive"===e.kind))){if("Literal"!==s.type&&o.every((e=>"store_sub"!==e.kind))&&"MemberExpression"!==t.type){let{start:t,end:a}=s;if(r("derived"),n.str.update(e.start,e.body.expression.start,"let "),"SequenceExpression"===s.type){for(;"("!==n.str.original[t];)t-=1;for(;")"!==n.str.original[a-1];)a+=1}return n.str.prependRight(t,"$derived("),void("("!==n.str.original[e.body.start]&&n.str.appendLeft(a,")"))}for(const t of o)if(t.reassigned&&(a.includes(t.node)||0===i.length)){r("state");const a="state"===t.kind?" = $state()":0===i.length?` = $state(${n.str.original.substring(s.start,s.end)})`:"";n.str.prependLeft(e.start,`let ${t.node.name}${a};\n${n.indent}`)}if(0===i.length&&o.every((e=>"store_sub"!==e.kind)))return void n.str.remove(e.start,e.end)}}n.legacy_imports.add("run");const a="BlockStatement"===e.body.type,i=e.body.start;if(a){n.str.update(e.start,i+1,`${n.names.run}(() => {`);const t=e.body.end;n.str.update(t-1,t,"});")}else n.str.update(e.start,i,`${n.names.run}(() => {\n${n.indent}`),n.str.indent(n.indent,{exclude:[[0,e.body.start],[e.body.end,n.end]]}),n.str.appendLeft(e.end,`\n${n.indent}});`)}};function HP(e,t,n){const s=e.str.snip(t,n).toString(),r=s.substring(1,s.length-1);r.trim().length!==r.length&&e.str.update(t+1,n-1,r.trim())}const UP={Identifier(e,{state:t,path:n}){QP(e,t,n)},RegularElement(e,{state:t,path:n,next:s}){const r=e.name.replace(/[a-zA-Z-]*:/g,"");if("/"===t.analysis.source[e.end-2]&&!z(r)&&!oe(r)){let n=e.end-2;for(;" "===t.str.original.charAt(n-1);)n--;t.str.remove(n,e.end-1),t.str.appendLeft(e.end,``)}zP(e,n,t),KP(e,t),s()},SvelteSelf(e,{state:t,next:n}){const s=t.str.original.substring(e.start,e.end);if(!t.filename){const r=YP(s);return jP=!0,t.str.prependRight(e.start,`\x3c!-- @migration-task: svelte:self is deprecated, import this Svelte file into itself instead --\x3e\n${r}`),void n()}t.str.overwrite(e.start+1,e.start+1+11,`${t.analysis.name}`),e.fragment.nodes.length>0?t.str.overwrite(t.str.original.lastIndexOf("<",e.end)+2,e.end-1,`${t.analysis.name}`):s.endsWith("/>")||t.str.overwrite(e.start+s.lastIndexOf("=0;i--){const o=s[i];if("EachBlock"===o.type||"AwaitBlock"===o.type||"IfBlock"===o.type||"SnippetBlock"===o.type||"Component"===o.type||"SvelteComponent"===o.type){let o=e.start;if(i!==s.length-1)for(let e=1;e("RegularElement"===e.type||"SvelteElement"===e.type||"Component"===e.type||"SvelteComponent"===e.type||"SvelteFragment"===e.type)&&e.attributes.some((e=>"Attribute"===e.type&&"slot"===e.name&&Ji(e)&&e.value[0].data===o))))||e.attributes.some((e=>"Attribute"===e.type&&"slot"===e.name&&Ji(e)&&e.value[0].data===o)))&&(a=`${o}_render`,t.derived_conflicting_slots.set(a,o));else{const e=!0===s.value||Array.isArray(s.value)?s.value:[s.value];let n="true";if(!0!==e){const s=e[0],a=e[e.length-1];for(const t of e)r(t);n=t.str.snip("Text"===s.type?s.start-1:s.expression.start,"Text"===a.type?a.end+1:a.expression.end).toString()}l+=n===s.name?`${n}, `:`${s.name}: ${n}, `}}l+="}","{ }"===l&&(l="");const c=t.props.find((e=>e.slot_name===o));if(c)i=c.local;else if("default"!==o&&(i=t.scope.generate(o),i!==o))throw new BP(`This migration would change the name of a slot (${o} to ${i}) making the component unusable`);c?c.needs_refine_type&&(c.type="import('svelte')."+(l?"Snippet<[any]>":"Snippet"),c.needs_refine_type=!1):t.props.push({local:i,exported:i,init:"",bindable:!1,optional:!0,slot_name:o,type:"import('svelte')."+(l?"Snippet<[any]>":"Snippet")}),"default"===o&&n.some((e=>("SvelteComponent"===e.type||"Component"===e.type||"RegularElement"===e.type||"SvelteElement"===e.type||"SvelteFragment"===e.type)&&e.attributes.some((e=>"LetDirective"===e.type))))&&(a=`${i}_render`,t.derived_conflicting_slots.set(a,i)),i=a??i,e.fragment.nodes.length>0?(s(),t.str.update(e.start,e.fragment.nodes[0].start,`{#if ${i}}{@render ${t.analysis.uses_props?`${t.names.props}.`:""}${i}(${l})}{:else}`),t.str.update(e.fragment.nodes[e.fragment.nodes.length-1].end,e.end,"{/if}")):t.str.update(e.start,e.end,`{@render ${t.analysis.uses_props?`${t.names.props}.`:""}${i}?.(${l})}`)},Comment(e,{state:t}){const n=kt(e.data);n!==e.data&&t.str.overwrite(e.start+4,e.end-3,n)},HtmlTag(e,{state:t,next:n}){HP(t,e.start,e.end),n()},ConstTag(e,{state:t,next:n}){HP(t,e.start,e.end),n()},IfBlock(e,{state:t,next:n}){const s=e.start,r=t.str.original.indexOf("}",e.test.end)+1;HP(t,s,r),n()},AwaitBlock(e,{state:t,next:n}){const s=e.start,r=t.str.original.indexOf("}",null!==e.pending?e.expression.end:e.value?.end)+1;if(HP(t,s,r),null!==e.pending){const n=t.str.original.lastIndexOf("{",e.value?.start),s=t.str.original.indexOf("}",e.value?.end)+1;HP(t,n,s)}if(null!==e.catch){const n=t.str.original.lastIndexOf("{",e.error?.start),s=t.str.original.indexOf("}",e.error?.end)+1;HP(t,n,s)}n()},KeyBlock(e,{state:t,next:n}){const s=e.start,r=t.str.original.indexOf("}",e.expression.end)+1;HP(t,s,r),n()}};function zP(e,t,n){const s=t.at(-2);if("Component"!==s?.type&&"SvelteComponent"!==s?.type&&"Component"!==e.type&&"SvelteComponent"!==e.type)return;let r="children",a=[],i=[];for(let t of e.attributes){if("Attribute"===t.type&&"slot"===t.name&&Ji(t)){if(r=t.value[0].data,"default"===r&&(r="children"),!m.test(r)||G(r))return jP=!0,void n.str.appendLeft(e.start,`\x3c!-- @migration-task: migrate this slot by hand, \`${r}\` is an invalid identifier --\x3e\n${n.indent}`);if("Component"===s?.type||"SvelteComponent"===s?.type)for(let t of s.attributes)if(("Attribute"===t.type||"BindDirective"===t.type)&&t.name===r)return void n.str.appendLeft(e.start,`\x3c!-- @migration-task: migrate this slot by hand, \`${r}\` would shadow a prop on the parent component --\x3e\n${n.indent}`);for(let e of i)e();n.str.remove(t.start,t.end)}"LetDirective"===t.type&&(a.push(t.name+(t.expression?`: ${n.str.original.substring(t.expression.start,t.expression.end)}`:"")),i.push((()=>n.str.remove(t.start,t.end))))}if(i.length>0)for(let e of i)e();"SvelteFragment"===e.type&&e.fragment.nodes.length>0&&(n.str.remove(e.start,e.fragment.nodes[0].start),n.str.remove(e.fragment.nodes[e.fragment.nodes.length-1].end,e.end));const o=a.length>0?`{ ${a.join(", ")} }`:"";if("children"===r&&"SvelteFragment"!==e.type){if(0===a.length)return;let s=0,i=0;for(let t=0;t"Attribute"===e.type&&"slot"===e.name))?s||a?i&&!a&&(n.str.update(i-1,i,""),n.str.prependLeft(i-1,n.str.original[i-1]),n.str.move(r.start,r.end,i-1)):s=r.start:s&&!i&&(i=r.start)}i||(i=e.fragment.nodes[e.fragment.nodes.length-1].end),n.str.appendLeft(s,`{#snippet ${r}(${o})}\n${n.indent.repeat(t.length)}`),n.str.indent(n.indent,{exclude:[[0,s],[i,n.str.original.length]]}),ie.trim().replace(/^\/\/\s*/g,"").replace(/^\/\*\*?\s*/g,"").replace(/\s*\*\/$/g,"").replace(/^\*\s*/g,""))).filter(Boolean);const m=h?.findIndex((e=>e.startsWith("@")));let f=h?.slice(0,-1!==m?m:h.length).join("\n"),y=d?.split("\n").map((e=>e.trim().replace(/^\/\/\s*/g,"").replace(/^\/\*\*?\s*/g,"").replace(/\s*\*\/$/g,"").replace(/^\*\s*/g,""))).filter(Boolean);const v=y?.findIndex((e=>e.startsWith("@")));let g=y?.slice(0,-1!==v?v:y.length).join("\n");if("ExportNamedDeclaration"===r?.type&&a){t.has_type_or_fallback=!0;const e=/@type {(.+)}/.exec(a.value);if(e){const t=/@type {.+} (?:\w+|\[.*?\]) - (.+)/.exec(a.value);return t&&(f+=t[1]?.trim()),{type:e[1],comment:f,trailing_comment:g}}}if("Literal"===e.init?.type){t.has_type_or_fallback=!0;const n=typeof e.init.value;if("string"===n||"number"===n||"boolean"===n)return{type:n,comment:t.uses_ts?l:f,trailing_comment:t.uses_ts?d:g}}return{type:"any",comment:t.uses_ts?l:f,trailing_comment:t.uses_ts?d:g}}const GP=["preventDefault","stopPropagation","stopImmediatePropagation","self","trusted","once"];function KP(e,t){const n=new Map;for(const t of e.attributes){if("OnDirective"!==t.type)continue;let e=`on${t.name}`;t.modifiers.includes("capture")&&(e+="capture");const s=n.get(e)||[];s.push(t),n.set(e,s)}for(const[e,s]of n){const n=[];let r=null;for(const e of s){let s;e.expression?s=t.str.original.substring(e.expression.start,e.expression.end):(s=`${t.names.bubble}('${e.name}')`,t.legacy_imports.add("createBubbler"),t.script_insertions.add(`const ${t.names.bubble} = ${t.names.createBubbler}();`));const a=e.modifiers.includes("passive"),i=e.modifiers.includes("nonpassive"),o=GP.filter((t=>e.modifiers.includes(t)));for(const e of o)t.legacy_imports.add(e),s=`${t.names[e]}(${s})`;if(a||i){const n=a?"passive":"nonpassive";t.legacy_imports.add(n),t.str.overwrite(e.start,e.end,`use:${t.names[n]}={['${e.name}', () => ${s}]}`)}else{if(r){let n=e.start,s=e.end;for(;/[\s\n]/.test(t.str.original[n-1]);)n-=1;t.str.remove(n,s)}else r=e;n.push(s)}}if(r){let s;if(n.length>1)t.legacy_imports.add("handlers"),s=`${e}={${t.names.handlers}(${n.join(", ")})}`;else{const t=n[0];s=t===e?`{${t}}`:`${e}={${t}}`}t.str.overwrite(r.start,r.end,s)}}}function XP(e,t){const n=t.leadingComments?.[0],s=t.trailingComments?.[t.trailingComments.length-1];let r=n?.start??t.start,a=s?.end??t.end,i=r;for(;"\n"!==e[i-1]&&"\r"!==e[i-1];)if(i--," "!==e[i]&&"\t"!==e[i]){i=r;break}return r=i,{start:r,end:a}}function QP(e,t,n){const s=n.at(-1);if("MemberExpression"!==s?.type||s.property!==e)if(t.analysis.uses_props&&"$$slots"!==e.name)if("$$props"===e.name||"$$restProps"===e.name)t.str.update(e.start,e.end,t.names.props);else{const n=t.scope.get(e.name);"bindable_prop"===n?.kind&&n.node!==e&&t.str.prependLeft(e.start,`${t.names.props}.`)}else if("$$restProps"===e.name&&t.analysis.uses_rest_props)t.str.update(e.start,e.end,t.names.rest);else if("$$slots"===e.name&&t.analysis.uses_slots){if("MemberExpression"===s?.type){if(t.analysis.custom_element)return;let n="Literal"===s.property.type?s.property.value:s.property.name,r=n;const a=t.props.find((e=>e.slot_name===n));if(a)n=a.local;else if("default"!==n){let e=t.scope.generate(n);if(e!==n)throw new BP(`This migration would change the name of a slot (${n} to ${e}) making the component unusable`)}n="default"===n?"children":n,a||t.props.push({local:n,exported:n,init:"",bindable:!1,optional:!0,slot_name:r,type:"import('svelte').Snippet<[any]>",needs_refine_type:!0}),t.str.update(e.start,s.property.start,t.analysis.uses_props?`${t.names.props}.`:""),t.str.update(s.property.start,s.end,n)}}else if("TSInterfaceDeclaration"===s?.type||"TSTypeAliasDeclaration"===s?.type){const n="TSInterfaceDeclaration"===s.type?s.body.body:s.typeAnnotation?.members;if(Array.isArray(n)&&"$$Props"===e.name){t.has_type_or_fallback=!0;for(const e of n){const n=t.props.find((t=>t.exported===e.key.name)),s=t.str.original.substring(e.typeAnnotation.typeAnnotation.start,e.typeAnnotation.typeAnnotation.end);let r;const a=e.leadingComments?.at(-1);"Block"===a?.type&&(r=t.str.original.substring(a.start,a.end));const i=e.trailingComments?.at(0)?.value;n?(n.type=s,n.optional=e.optional,n.comment=r??n.comment,n.trailing_comment=i??n.trailing_comment):t.props.push({local:e.key.name,exported:e.key.name,init:"",bindable:!1,optional:e.optional,type:s,comment:r,trailing_comment:i,type_only:!0})}t.str.remove(s.start,s.end)}}}function YP(e){const t=e.split("\n"),n=t.filter((e=>/^\t+/.test(e))),s=t.filter((e=>/^ {2,}/.test(e)));if(0===n.length&&0===s.length)return"\t";if(n.length>=s.length)return"\t";const r=s.reduce(((e,t)=>{const n=/^ +/.exec(t)?.[0].length??0;return Math.min(n,e)}),1/0);return" ".repeat(r)}function JP(e,n,s){if(s){const e=e=>{delete e.metadata};return n.options?.attributes.forEach((t=>{e(t),e(t.value),Array.isArray(t.value)&&t.value.forEach(e)})),t(n,null,{_(t,{next:n}){e(t),n()}})}return function(e,n){return t(n,null,{_(e,{next:t}){delete e.metadata,t()},Root(t,{visit:s}){const{instance:r,module:a,options:i}=t;if(i?.__raw__){let e=t.fragment.nodes.findIndex((e=>i.end<=e.start));-1===e&&(e=t.fragment.nodes.length),t.fragment.nodes.splice(e,0,i.__raw__)}let o=null,l=null;if(t.fragment.nodes.length>0){const n=t.fragment.nodes.at(0),s=t.fragment.nodes.at(-1);for(o=n.start,l=s.end;/\s/.test(e[o]);)o+=1;for(;/\s/.test(e[l-1]);)l-=1}return r&&delete r.attributes,a&&delete a.attributes,{html:{type:"Fragment",start:o,end:l,children:t.fragment.nodes.map((e=>s(e)))},instance:r,module:a,css:n.css?s(n.css):void 0,_comments:n.comments?.length>0?n.comments:void 0}},AnimateDirective:e=>({...e,type:"Animation"}),AwaitBlock(t,{visit:n}){let s={type:"PendingBlock",start:null,end:null,children:t.pending?.nodes.map((e=>n(e)))??[],skip:!0},r={type:"ThenBlock",start:null,end:null,children:t.then?.nodes.map((e=>n(e)))??[],skip:!0},a={type:"CatchBlock",start:null,end:null,children:t.catch?.nodes.map((e=>n(e)))??[],skip:!0};if(t.pending){const n=t.pending.nodes.at(0),r=t.pending.nodes.at(-1);s.start=n?.start??e.indexOf("}",t.expression.end)+1,s.end=r?.end??s.start,s.skip=!1}if(t.then){const n=t.then.nodes.at(0),a=t.then.nodes.at(-1);r.start=s.end??n?.start??e.indexOf("}",t.expression.end)+1,r.end=a?.end??e.lastIndexOf("}",s.end??t.expression.end)+1,r.skip=!1}if(t.catch){const n=t.catch.nodes.at(0),i=t.catch.nodes.at(-1);a.start=r.end??s.end??n?.start??e.indexOf("}",t.expression.end)+1,a.end=i?.end??e.lastIndexOf("}",r.end??s.end??t.expression.end)+1,a.skip=!1}return{type:"AwaitBlock",start:t.start,end:t.end,expression:t.expression,value:t.value,error:t.error,pending:s,then:r,catch:a}},BindDirective:e=>({...e,type:"Binding"}),ClassDirective:e=>({...e,type:"Class"}),Comment:e=>({...e,ignores:wt(e.start,e.data,!1)}),ComplexSelector(e,{next:t}){t();const n=[];for(const t of e.children)t.combinator&&n.push(t.combinator),n.push(...t.selectors);return{type:"Selector",start:e.start,end:e.end,children:n}},Component:(e,{visit:t})=>({type:"InlineComponent",start:e.start,end:e.end,name:e.name,attributes:e.attributes.map((e=>t(e))),children:e.fragment.nodes.map((e=>t(e)))}),ConstTag(e){if(void 0!==e.expression)return e;const t=e,{id:n}={...t.declaration.declarations[0]};return delete n.typeAnnotation,{type:"ConstTag",start:t.start,end:e.end,expression:{type:"AssignmentExpression",start:(t.declaration.start??0)+6,end:t.declaration.end??0,operator:"=",left:n,right:t.declaration.declarations[0].init}}},KeyBlock:(e,{visit:t})=>(Ct(e.fragment.nodes),{type:"KeyBlock",start:e.start,end:e.end,expression:e.expression,children:e.fragment.nodes.map((e=>t(e)))}),EachBlock(t,{visit:n}){let s;if(t.fallback){const r=t.fallback.nodes.at(0),a=e.lastIndexOf("{",t.end-1),i=r?.start??a;Ct(t.fallback.nodes),s={type:"ElseBlock",start:i,end:a,children:t.fallback.nodes.map((e=>n(e)))}}return Ct(t.body.nodes),{type:"EachBlock",start:t.start,end:t.end,children:t.body.nodes.map((e=>n(e))),context:t.context,expression:t.expression,index:t.index,key:t.key,else:s}},ExpressionTag(t,{path:n}){const s=n.at(-1);return"Attribute"===s?.type&&"{"===e[s.start]?{type:"AttributeShorthand",start:t.start,end:t.end,expression:t.expression}:{type:"MustacheTag",start:t.start,end:t.end,expression:t.expression}},HtmlTag:e=>({...e,type:"RawMustacheTag"}),IfBlock(t,{visit:n}){let s;if(t.alternate){let r=t.alternate.nodes;1===r.length&&"IfBlock"===r[0].type&&r[0].elseif&&(r=r[0].consequent.nodes);const a=e.lastIndexOf("{",t.end-1),i=r.at(0)?.start??a;Ct(t.alternate.nodes),s={type:"ElseBlock",start:i,end:a,children:t.alternate.nodes.map((e=>n(e)))}}const r=t.elseif?t.consequent.nodes[0]?.start??e.lastIndexOf("{",t.end-1):t.start;return Ct(t.consequent.nodes),{type:"IfBlock",start:r,end:t.end,expression:t.test,children:t.consequent.nodes.map((e=>n(e))),else:s,elseif:!!t.elseif||void 0}},OnDirective:e=>({...e,type:"EventHandler"}),SnippetBlock:(e,{visit:t})=>(Ct(e.body.nodes),{type:"SnippetBlock",start:e.start,end:e.end,expression:e.expression,parameters:e.parameters,children:e.body.nodes.map((e=>t(e))),typeParams:e.typeParams}),SvelteBoundary:(e,{visit:t})=>(Ct(e.fragment.nodes),{type:"SvelteBoundary",name:"svelte:boundary",start:e.start,end:e.end,attributes:e.attributes.map((e=>t(e))),children:e.fragment.nodes.map((e=>t(e)))}),RegularElement:(e,{visit:t})=>({type:"Element",start:e.start,end:e.end,name:e.name,attributes:e.attributes.map((e=>t(e))),children:e.fragment.nodes.map((e=>t(e)))}),SlotElement:(e,{visit:t})=>({type:"Slot",start:e.start,end:e.end,name:e.name,attributes:e.attributes.map((e=>t(e))),children:e.fragment.nodes.map((e=>t(e)))}),Attribute(e,{visit:t,next:n,path:s}){if(!0===e.value||Array.isArray(e.value))return n();{s.push(e);const n=[t(e.value)];return s.pop(),{...e,value:n}}},StyleDirective(e,{visit:t,next:n,path:s}){if(!0===e.value||Array.isArray(e.value))return n();{s.push(e);const n=[t(e.value)];return s.pop(),{...e,value:n}}},SpreadAttribute:e=>({...e,type:"Spread"}),StyleSheet:(e,t)=>({...e,...t.next(),type:"Style"}),SvelteBody:(e,{visit:t})=>({type:"Body",name:"svelte:body",start:e.start,end:e.end,attributes:e.attributes.map((e=>t(e))),children:e.fragment.nodes.map((e=>t(e)))}),SvelteComponent:(e,{visit:t})=>({type:"InlineComponent",name:"svelte:component",start:e.start,end:e.end,expression:e.expression,attributes:e.attributes.map((e=>t(e))),children:e.fragment.nodes.map((e=>t(e)))}),SvelteDocument:(e,{visit:t})=>({type:"Document",name:"svelte:document",start:e.start,end:e.end,attributes:e.attributes.map((e=>t(e))),children:e.fragment.nodes.map((e=>t(e)))}),SvelteElement(t,{visit:n}){let s=t.tag;return"Literal"===s.type&&"string"==typeof s.value&&"{"!==e[t.tag.start-1]&&(s=s.value),{type:"Element",name:"svelte:element",start:t.start,end:t.end,tag:s,attributes:t.attributes.map((e=>n(e))),children:t.fragment.nodes.map((e=>n(e)))}},SvelteFragment:(e,{visit:t})=>({type:"SlotTemplate",name:"svelte:fragment",start:e.start,end:e.end,attributes:e.attributes.map((e=>t(e))),children:e.fragment.nodes.map((e=>t(e)))}),SvelteHead:(e,{visit:t})=>({type:"Head",name:"svelte:head",start:e.start,end:e.end,attributes:e.attributes.map((e=>t(e))),children:e.fragment.nodes.map((e=>t(e)))}),SvelteOptions:(e,{visit:t})=>({type:"Options",name:"svelte:options",start:e.start,end:e.end,attributes:e.attributes.map((e=>t(e)))}),SvelteSelf:(e,{visit:t})=>({type:"InlineComponent",name:"svelte:self",start:e.start,end:e.end,attributes:e.attributes.map((e=>t(e))),children:e.fragment.nodes.map((e=>t(e)))}),SvelteWindow:(e,{visit:t})=>({type:"Window",name:"svelte:window",start:e.start,end:e.end,attributes:e.attributes.map((e=>t(e))),children:e.fragment.nodes.map((e=>t(e)))}),Text(e,{path:t}){const n=t.at(-1);if("RegularElement"===n?.type&&"style"===n.name)return{type:"Text",start:e.start,end:e.end,data:e.data}},TitleElement:(e,{visit:t})=>({type:"Title",name:"title",start:e.start,end:e.end,attributes:e.attributes.map((e=>t(e))),children:e.fragment.nodes.map((e=>t(e)))}),TransitionDirective:e=>({...e,type:"Transition"}),UseDirective:e=>({...e,type:"Action"}),LetDirective:e=>({...e,type:"Let"})})}(e,n)}function ZP(e){return 65279===e.charCodeAt(0)?e.slice(1):e}e.VERSION=sk,e.compile=function(e,t){e=ZP(e),$e({warning:t.warningFilter,filename:t.filename});const n=iP(t,"");let s=Yl(e);const{customElement:r,...a}=s.options||{},i={...n,...a,customElementOptions:r,css:"css"in a?()=>a.css??"external":n.css,runes:"runes"in a?()=>a.runes:n.runes};s.metadata.ts&&(s={...s,fragment:s.fragment&&ec(s.fragment),instance:s.instance&&ec(s.instance),module:s.module&&ec(s.module)},i.customElementOptions?.extend&&(i.customElementOptions.extend=ec(i.customElementOptions?.extend)));const o=tP(kw(s,e,i),e,i);return o.ast=JP(e,s,t.modernAst),o},e.compileModule=function(e,n){e=ZP(e),$e({warning:n.warningFilter,filename:n.filename});const s=aP(n,""),r=function(e,n){const s=[];Ce(e);const r=Hs(e,s,!1,!1),{scope:a,scopes:i,has_await:o}=Sc(r,new Cc,!1,null);for(const[e,t]of a.references)"$"!==e[0]||ww.includes(e)||("$"!==e&&"$"!==e[1]||er(t[0].node,e),null===a.get(e.slice(1))||de(e)||Gs(t[0].node,"store_invalid_subscription_module","Cannot reference store value outside a `.svelte` file\nhttps://svelte.dev/e/store_invalid_subscription_module"));const l={module:{ast:r,scope:a,scopes:i,has_await:o},name:n.filename,accessors:!1,runes:!0,immutable:!0,tracing:!1,async_deriveds:new Set,comments:s,classes:new Map,pickled_awaits:new Set};return Re({dev:n.dev,rootDir:n.rootDir,runes:!0}),t(r,{scope:a,scopes:i,analysis:l,state_fields:new Map,ast_type:null,component_slots:new Set,expression:null,function_depth:0,has_props_rune:!1,options:n,fragment:null,parent_element:null,reactive_statement:null,derived_function_depth:-1},_w),l}(e,s);return nP(r,e,s)},e.migrate=function(e,{filename:n,use_ts:s}={}){let r=e;try{jP=!1;const a=[];e=e.replace(NP,((e,t,n,s,r)=>(a.push([r+t.length,n]),t+DP+s))),$e({warning:()=>!1,filename:n});let i=Yl(e);const{customElement:o,...l}=i.options||{},c={...iP({},""),...l,customElementOptions:o,filename:n??ye,css:"css"in l?()=>l.css??"external":()=>"external",runes:"runes"in l?()=>l.runes:()=>{},experimental:{async:!0}},p=new yk(e),u=kw(i,e,c),d=YP(e);p.replaceAll(/(t));for(const _ of a)p.overwrite(_[0],_[0]+25,_[1]);let h={scope:u.instance.scope,analysis:u,filename:n,str:p,indent:d,props:[],props_insertion_point:i.instance?.content.start??0,has_props_rune:!1,has_type_or_fallback:!1,end:e.length,names:{props:u.root.unique("props").name,rest:u.root.unique("rest").name,run:u.root.unique("run").name,handlers:u.root.unique("handlers").name,stopImmediatePropagation:u.root.unique("stopImmediatePropagation").name,preventDefault:u.root.unique("preventDefault").name,stopPropagation:u.root.unique("stopPropagation").name,once:u.root.unique("once").name,self:u.root.unique("self").name,trusted:u.root.unique("trusted").name,createBubbler:u.root.unique("createBubbler").name,bubble:u.root.unique("bubble").name,passive:u.root.unique("passive").name,nonpassive:u.root.unique("nonpassive").name},legacy_imports:new Set,script_insertions:new Set,derived_components:new Map,derived_conflicting_slots:new Map,derived_labeled_statements:new Set,has_svelte_self:!1,uses_ts:s&&!e.includes("@type {")||!!i.instance?.attributes.some((e=>"lang"===e.name&&"ts"===e.value[0].data))};if(i.module){const x=i.module.attributes.find((e=>"context"===e.name));x&&h.str.update(x.start,x.end,"module")}i.instance&&t(i.instance.content,h,VP),h={...h,scope:u.template.scope},t(i.fragment,h,UP);let m=i.instance?i.instance.content.start:0;const f=h.legacy_imports.size>0||h.derived_components.size>0||h.derived_conflicting_slots.size>0||h.script_insertions.size>0||h.props.length>0||u.uses_rest_props||u.uses_props||h.has_svelte_self,y=h.uses_ts&&(!i.instance||!i.instance.attributes.some((e=>"lang"===e.name)));if(!i.instance&&f&&p.appendRight(0,y?' + * + * + * ``` + * @since 5.29 + */ +export function createAttachmentKey() { + return Symbol(ATTACHMENT_KEY); +} + +/** + * Converts an [action](https://svelte.dev/docs/svelte/use) into an [attachment](https://svelte.dev/docs/svelte/@attach) keeping the same behavior. + * It's useful if you want to start using attachments on components but you have actions provided by a library. + * + * Note that the second argument, if provided, must be a function that _returns_ the argument to the + * action function, not the argument itself. + * + * ```svelte + * + *
...
+ * + * + *
bar)}>...
+ * ``` + * @template {EventTarget} E + * @template {unknown} T + * @overload + * @param {Action | ((element: E, arg: T) => void | ActionReturn)} action The action function + * @param {() => T} fn A function that returns the argument for the action + * @returns {Attachment} + */ +/** + * Converts an [action](https://svelte.dev/docs/svelte/use) into an [attachment](https://svelte.dev/docs/svelte/@attach) keeping the same behavior. + * It's useful if you want to start using attachments on components but you have actions provided by a library. + * + * Note that the second argument, if provided, must be a function that _returns_ the argument to the + * action function, not the argument itself. + * + * ```svelte + * + *
...
+ * + * + *
bar)}>...
+ * ``` + * @template {EventTarget} E + * @overload + * @param {Action | ((element: E) => void | ActionReturn)} action The action function + * @returns {Attachment} + */ +/** + * Converts an [action](https://svelte.dev/docs/svelte/use) into an [attachment](https://svelte.dev/docs/svelte/@attach) keeping the same behavior. + * It's useful if you want to start using attachments on components but you have actions provided by a library. + * + * Note that the second argument, if provided, must be a function that _returns_ the argument to the + * action function, not the argument itself. + * + * ```svelte + * + *
...
+ * + * + *
bar)}>...
+ * ``` + * + * @template {EventTarget} E + * @template {unknown} T + * @param {Action | ((element: E, arg: T) => void | ActionReturn)} action The action function + * @param {() => T} fn A function that returns the argument for the action + * @returns {Attachment} + * @since 5.32 + */ +export function fromAction(action, fn = /** @type {() => T} */ (noop)) { + return (element) => { + const { update, destroy } = untrack(() => action(element, fn()) ?? {}); + + if (update) { + var ran = false; + render_effect(() => { + const arg = fn(); + if (ran) update(arg); + }); + ran = true; + } + + if (destroy) { + teardown(destroy); + } + }; +} diff --git a/frontend/node_modules/svelte/src/compiler/errors.js b/frontend/node_modules/svelte/src/compiler/errors.js new file mode 100644 index 0000000..c28c737 --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/errors.js @@ -0,0 +1,1719 @@ +/* This file is generated by scripts/process-messages/index.js. Do not edit! */ + +import { CompileDiagnostic } from './utils/compile_diagnostic.js'; + +/** @typedef {{ start?: number, end?: number }} NodeLike */ +class InternalCompileError extends Error { + message = ''; // ensure this property is enumerable + #diagnostic; + + /** + * @param {string} code + * @param {string} message + * @param {[number, number] | undefined} position + */ + constructor(code, message, position) { + super(message); + this.stack = ''; // avoid unnecessary noise; don't set it as a class property or it becomes enumerable + + // We want to extend from Error so that various bundler plugins properly handle it. + // But we also want to share the same object shape with that of warnings, therefore + // we create an instance of the shared class an copy over its properties. + this.#diagnostic = new CompileDiagnostic(code, message, position); + + Object.assign(this, this.#diagnostic); + this.name = 'CompileError'; + } + + toString() { + return this.#diagnostic.toString(); + } + + toJSON() { + return this.#diagnostic.toJSON(); + } +} + +/** + * @param {null | number | NodeLike} node + * @param {string} code + * @param {string} message + * @returns {never} + */ +function e(node, code, message) { + const start = typeof node === 'number' ? node : node?.start; + const end = typeof node === 'number' ? node : node?.end; + + throw new InternalCompileError(code, message, start !== undefined ? [start, end ?? start] : undefined); +} + +/** + * Invalid compiler option: %details% + * @param {null | number | NodeLike} node + * @param {string} details + * @returns {never} + */ +export function options_invalid_value(node, details) { + e(node, 'options_invalid_value', `Invalid compiler option: ${details}\nhttps://svelte.dev/e/options_invalid_value`); +} + +/** + * Invalid compiler option: %details% + * @param {null | number | NodeLike} node + * @param {string} details + * @returns {never} + */ +export function options_removed(node, details) { + e(node, 'options_removed', `Invalid compiler option: ${details}\nhttps://svelte.dev/e/options_removed`); +} + +/** + * Unrecognised compiler option %keypath% + * @param {null | number | NodeLike} node + * @param {string} keypath + * @returns {never} + */ +export function options_unrecognised(node, keypath) { + e(node, 'options_unrecognised', `Unrecognised compiler option ${keypath}\nhttps://svelte.dev/e/options_unrecognised`); +} + +/** + * `$bindable()` can only be used inside a `$props()` declaration + * @param {null | number | NodeLike} node + * @returns {never} + */ +export function bindable_invalid_location(node) { + e(node, 'bindable_invalid_location', `\`$bindable()\` can only be used inside a \`$props()\` declaration\nhttps://svelte.dev/e/bindable_invalid_location`); +} + +/** + * Cannot assign to %thing% + * @param {null | number | NodeLike} node + * @param {string} thing + * @returns {never} + */ +export function constant_assignment(node, thing) { + e(node, 'constant_assignment', `Cannot assign to ${thing}\nhttps://svelte.dev/e/constant_assignment`); +} + +/** + * Cannot bind to %thing% + * @param {null | number | NodeLike} node + * @param {string} thing + * @returns {never} + */ +export function constant_binding(node, thing) { + e(node, 'constant_binding', `Cannot bind to ${thing}\nhttps://svelte.dev/e/constant_binding`); +} + +/** + * `%name%` has already been declared + * @param {null | number | NodeLike} node + * @param {string} name + * @returns {never} + */ +export function declaration_duplicate(node, name) { + e(node, 'declaration_duplicate', `\`${name}\` has already been declared\nhttps://svelte.dev/e/declaration_duplicate`); +} + +/** + * Cannot declare a variable with the same name as an import inside `\n\n'); + } + migrate_css(state); + return { + code: str.toString() + }; + } catch (e) { + if (!(e instanceof MigrationError)) { + // eslint-disable-next-line no-console + console.error('Error while migrating Svelte code', e); + } + has_migration_task = true; + return { + code: `\n${og_source}` + }; + } finally { + if (has_migration_task) { + // eslint-disable-next-line no-console + console.log( + `One or more \`@migration-task\` comments were added to ${filename ? `\`${filename}\`` : "a file (unfortunately we don't know the name)"}, please check them and complete the migration manually.` + ); + } + } +} + +/** + * @typedef {{ + * scope: Scope; + * str: MagicString; + * analysis: ComponentAnalysis; + * filename?: string; + * indent: string; + * props: Array<{ local: string; exported: string; init: string; bindable: boolean; slot_name?: string; optional: boolean; type: string; comment?: string; trailing_comment?: string; type_only?: boolean; needs_refine_type?: boolean; }>; + * props_insertion_point: number; + * has_props_rune: boolean; + * has_type_or_fallback: boolean; + * end: number; + * names: Record; + * legacy_imports: Set; + * script_insertions: Set; + * derived_components: Map; + * derived_conflicting_slots: Map; + * derived_labeled_statements: Set; + * has_svelte_self: boolean; + * uses_ts: boolean; + * }} State + */ + +/** @type {Visitors} */ +const instance_script = { + _(node, { state, next }) { + // @ts-expect-error + const comments = node.leadingComments; + if (comments) { + for (const comment of comments) { + if (comment.type === 'Line') { + const migrated = migrate_svelte_ignore(comment.value); + if (migrated !== comment.value) { + state.str.overwrite(comment.start + '//'.length, comment.end, migrated); + } + } + } + } + next(); + }, + Identifier(node, { state, path }) { + handle_identifier(node, state, path); + }, + ImportDeclaration(node, { state }) { + state.props_insertion_point = node.end ?? state.props_insertion_point; + if (node.source.value === 'svelte') { + let illegal_specifiers = []; + let removed_specifiers = 0; + for (let specifier of node.specifiers) { + if ( + specifier.type === 'ImportSpecifier' && + specifier.imported.type === 'Identifier' && + ['beforeUpdate', 'afterUpdate'].includes(specifier.imported.name) + ) { + const references = state.scope.references.get(specifier.local.name); + if (!references) { + let end = /** @type {number} */ ( + state.str.original.indexOf(',', specifier.end) !== -1 && + state.str.original.indexOf(',', specifier.end) < + state.str.original.indexOf('}', specifier.end) + ? state.str.original.indexOf(',', specifier.end) + 1 + : specifier.end + ); + while (state.str.original[end].trim() === '') end++; + state.str.remove(/** @type {number} */ (specifier.start), end); + removed_specifiers++; + continue; + } + illegal_specifiers.push(specifier.imported.name); + } + } + if (removed_specifiers === node.specifiers.length) { + state.str.remove(/** @type {number} */ (node.start), /** @type {number} */ (node.end)); + } + if (illegal_specifiers.length > 0) { + throw new MigrationError( + `Can't migrate code with ${illegal_specifiers.join(' and ')}. Please migrate by hand.` + ); + } + } + }, + ExportNamedDeclaration(node, { state, next }) { + if (node.declaration) { + next(); + return; + } + + let count_removed = 0; + for (const specifier of node.specifiers) { + if (specifier.local.type !== 'Identifier') continue; + + const binding = state.scope.get(specifier.local.name); + if (binding?.kind === 'bindable_prop') { + state.str.remove( + /** @type {number} */ (specifier.start), + /** @type {number} */ (specifier.end) + ); + count_removed++; + } + } + if (count_removed === node.specifiers.length) { + state.str.remove(/** @type {number} */ (node.start), /** @type {number} */ (node.end)); + } + }, + VariableDeclaration(node, { state, path, visit, next }) { + if (state.scope !== state.analysis.instance.scope) { + return; + } + + let nr_of_props = 0; + + for (let i = 0; i < node.declarations.length; i++) { + const declarator = node.declarations[i]; + if (state.analysis.runes) { + if (get_rune(declarator.init, state.scope) === '$props') { + state.props_insertion_point = /** @type {number} */ (declarator.id.start) + 1; + state.has_props_rune = true; + } + continue; + } + + let bindings; + try { + bindings = state.scope.get_bindings(declarator); + } catch (e) { + // no bindings, so we can skip this + next(); + continue; + } + const has_state = bindings.some((binding) => binding.kind === 'state'); + const has_props = bindings.some((binding) => binding.kind === 'bindable_prop'); + + if (!has_state && !has_props) { + next(); + continue; + } + + if (has_props) { + nr_of_props++; + + if (declarator.id.type !== 'Identifier') { + // TODO invest time in this? + throw new MigrationError( + 'Encountered an export declaration pattern that is not supported for automigration.' + ); + // Turn export let into props. It's really really weird because export let { x: foo, z: [bar]} = .. + // means that foo and bar are the props (i.e. the leaves are the prop names), not x and z. + // const tmp = b.id(state.scope.generate('tmp')); + // const paths = extract_paths(declarator.id, tmp); + // state.props_pre.push( + // b.declaration('const', tmp, visit(declarator.init!) as Expression) + // ); + // for (const path of paths) { + // const name = (path.node as Identifier).name; + // const binding = state.scope.get(name)!; + // const value = path.expression; + // if (binding.kind === 'bindable_prop' || binding.kind === 'rest_prop') { + // state.props.push({ + // local: name, + // exported: binding.prop_alias ? binding.prop_alias : name, + // init: value + // }); + // state.props_insertion_point = /** @type {number} */(declarator.end); + // } else { + // declarations.push(b.declarator(path.node, value)); + // } + // } + } + + const name = declarator.id.name; + const binding = /** @type {Binding} */ (state.scope.get(name)); + + if (state.analysis.uses_props && (declarator.init || binding.updated)) { + throw new MigrationError( + '$$props is used together with named props in a way that cannot be automatically migrated.' + ); + } + + const prop = state.props.find((prop) => prop.exported === (binding.prop_alias || name)); + if (prop) { + next(); + // $$Props type was used + prop.init = declarator.init + ? state.str + .snip( + /** @type {number} */ (declarator.init.start), + /** @type {number} */ (declarator.init.end) + ) + .toString() + : ''; + prop.bindable = binding.updated; + prop.exported = binding.prop_alias || name; + prop.type_only = false; + } else { + next(); + state.props.push({ + local: name, + exported: binding.prop_alias ? binding.prop_alias : name, + init: declarator.init + ? state.str + .snip( + /** @type {number} */ (declarator.init.start), + /** @type {number} */ (declarator.init.end) + ) + .toString() + : '', + optional: !!declarator.init, + bindable: binding.updated, + ...extract_type_and_comment(declarator, state, path) + }); + } + + let start = /** @type {number} */ (declarator.start); + let end = /** @type {number} */ (declarator.end); + + // handle cases like let a,b,c; where only some are exported + if (node.declarations.length > 1) { + // move the insertion point after the node itself; + state.props_insertion_point = /** @type {number} */ (node.end); + // if it's not the first declaration remove from the , of the previous declaration + if (i !== 0) { + start = state.str.original.indexOf( + ',', + /** @type {number} */ (node.declarations[i - 1].end) + ); + } + // if it's not the last declaration remove either from up until the + // start of the next declaration (if it's the first declaration) or + // up until the last index of , from the next declaration + if (i !== node.declarations.length - 1) { + if (i === 0) { + end = /** @type {number} */ (node.declarations[i + 1].start); + } else { + end = state.str.original.lastIndexOf( + ',', + /** @type {number} */ (node.declarations[i + 1].start) + ); + } + } + } else { + state.props_insertion_point = /** @type {number} */ (declarator.end); + } + + state.str.update(start, end, ''); + + continue; + } + + /** + * @param {"state"|"derived"} rune + */ + function check_rune_binding(rune) { + const has_rune_binding = !!state.scope.get(rune); + if (has_rune_binding) { + throw new MigrationError( + `can't migrate \`${state.str.original.substring(/** @type {number} */ (node.start), node.end)}\` to \`$${rune}\` because there's a variable named ${rune}.\n Rename the variable and try again or migrate by hand.` + ); + } + } + + // state + if (declarator.init) { + let { start, end } = /** @type {{ start: number, end: number }} */ (declarator.init); + + if (declarator.init.type === 'SequenceExpression') { + while (state.str.original[start] !== '(') start -= 1; + while (state.str.original[end - 1] !== ')') end += 1; + } + + check_rune_binding('state'); + + state.str.prependLeft(start, '$state('); + state.str.appendRight(end, ')'); + } else { + /** + * @type {AssignmentExpression | undefined} + */ + let assignment_in_labeled; + /** + * @type {LabeledStatement | undefined} + */ + let labeled_statement; + + // Analyze declaration bindings to see if they're exclusively updated within a single reactive statement + const possible_derived = bindings.every((binding) => + binding.references.every((reference) => { + const declaration = reference.path.find((el) => el.type === 'VariableDeclaration'); + const assignment = reference.path.find((el) => el.type === 'AssignmentExpression'); + const update = reference.path.find((el) => el.type === 'UpdateExpression'); + const labeled = /** @type {LabeledStatement | undefined} */ ( + reference.path.find((el) => el.type === 'LabeledStatement' && el.label.name === '$') + ); + + if ( + assignment && + labeled && + // ensure that $: foo = bar * 2 is not counted as a reassignment of bar + (labeled.body.type !== 'ExpressionStatement' || + labeled.body.expression !== assignment || + (assignment.left.type === 'Identifier' && + assignment.left.name === binding.node.name)) + ) { + if (assignment_in_labeled) return false; + assignment_in_labeled = /** @type {AssignmentExpression} */ (assignment); + labeled_statement = labeled; + } + + return ( + !update && + ((declaration && binding.initial) || + (labeled && assignment) || + (!labeled && !assignment)) + ); + }) + ); + + const labeled_has_single_assignment = + labeled_statement?.body.type === 'BlockStatement' && + labeled_statement.body.body.length === 1 && + labeled_statement.body.body[0].type === 'ExpressionStatement'; + + const is_expression_assignment = + labeled_statement?.body.type === 'ExpressionStatement' && + labeled_statement.body.expression.type === 'AssignmentExpression'; + + let should_be_state = false; + + if (is_expression_assignment) { + const body = /**@type {ExpressionStatement}*/ (labeled_statement?.body); + const expression = /**@type {AssignmentExpression}*/ (body.expression); + const [, ids] = extract_all_identifiers_from_expression(expression.right); + if (ids.length === 0) { + should_be_state = true; + state.derived_labeled_statements.add( + /** @type {LabeledStatement} */ (labeled_statement) + ); + } + } + + if ( + !should_be_state && + possible_derived && + assignment_in_labeled && + labeled_statement && + (labeled_has_single_assignment || is_expression_assignment) + ) { + const indent = state.str.original.substring( + state.str.original.lastIndexOf('\n', /** @type {number} */ (node.start)) + 1, + /** @type {number} */ (node.start) + ); + // transfer all the leading comments + if ( + labeled_statement.body.type === 'BlockStatement' && + labeled_statement.body.body[0].leadingComments + ) { + for (let comment of labeled_statement.body.body[0].leadingComments) { + state.str.prependLeft( + /** @type {number} */ (node.start), + comment.type === 'Block' + ? `/*${comment.value}*/\n${indent}` + : `// ${comment.value}\n${indent}` + ); + } + } + + check_rune_binding('derived'); + + // Someone wrote a `$: { ... }` statement which we can turn into a `$derived` + state.str.appendRight( + /** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), + ' = $derived(' + ); + visit(assignment_in_labeled.right); + state.str.appendRight( + /** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), + state.str + .snip( + /** @type {number} */ (assignment_in_labeled.right.start), + /** @type {number} */ (assignment_in_labeled.right.end) + ) + .toString() + ); + state.str.remove( + /** @type {number} */ (labeled_statement.start), + /** @type {number} */ (labeled_statement.end) + ); + state.str.appendRight( + /** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), + ')' + ); + state.derived_labeled_statements.add(labeled_statement); + + // transfer all the trailing comments + if ( + labeled_statement.body.type === 'BlockStatement' && + labeled_statement.body.body[0].trailingComments + ) { + for (let comment of labeled_statement.body.body[0].trailingComments) { + state.str.appendRight( + /** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), + comment.type === 'Block' + ? `\n${indent}/*${comment.value}*/` + : `\n${indent}// ${comment.value}` + ); + } + } + } else { + check_rune_binding('state'); + + state.str.prependLeft( + /** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), + ' = $state(' + ); + if (should_be_state) { + // someone wrote a `$: foo = ...` statement which we can turn into `let foo = $state(...)` + state.str.appendRight( + /** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), + state.str + .snip( + /** @type {number} */ ( + /** @type {AssignmentExpression} */ (assignment_in_labeled).right.start + ), + /** @type {number} */ ( + /** @type {AssignmentExpression} */ (assignment_in_labeled).right.end + ) + ) + .toString() + ); + state.str.remove( + /** @type {number} */ (/** @type {LabeledStatement} */ (labeled_statement).start), + /** @type {number} */ (/** @type {LabeledStatement} */ (labeled_statement).end) + ); + } + state.str.appendRight( + /** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), + ')' + ); + } + } + } + + if (nr_of_props === node.declarations.length) { + let start = /** @type {number} */ (node.start); + let end = /** @type {number} */ (node.end); + + const parent = path.at(-1); + if (parent?.type === 'ExportNamedDeclaration') { + start = /** @type {number} */ (parent.start); + end = /** @type {number} */ (parent.end); + } + while (state.str.original[start] !== '\n') start--; + while (state.str.original[end] !== '\n') end++; + state.str.update(start, end, ''); + } + }, + BreakStatement(node, { state, path }) { + if (path[1].type !== 'LabeledStatement') return; + if (node.label?.name !== '$') return; + state.str.update( + /** @type {number} */ (node.start), + /** @type {number} */ (node.end), + 'return;' + ); + }, + LabeledStatement(node, { path, state, next }) { + if (state.analysis.runes) return; + if (path.length > 1) return; + if (node.label.name !== '$') return; + if (state.derived_labeled_statements.has(node)) return; + + next(); + + /** + * @param {"state"|"derived"} rune + */ + function check_rune_binding(rune) { + const has_rune_binding = state.scope.get(rune); + if (has_rune_binding) { + throw new MigrationError( + `can't migrate \`$: ${state.str.original.substring(/** @type {number} */ (node.body.start), node.body.end)}\` to \`$${rune}\` because there's a variable named ${rune}.\n Rename the variable and try again or migrate by hand.` + ); + } + } + + if ( + node.body.type === 'ExpressionStatement' && + node.body.expression.type === 'AssignmentExpression' + ) { + const { left, right } = node.body.expression; + + const ids = extract_identifiers(left); + const [, expression_ids] = extract_all_identifiers_from_expression(right); + const bindings = ids.map((id) => /** @type {Binding} */ (state.scope.get(id.name))); + + if (bindings.every((b) => b.kind === 'legacy_reactive')) { + if ( + right.type !== 'Literal' && + bindings.every((b) => b.kind !== 'store_sub') && + left.type !== 'MemberExpression' + ) { + let { start, end } = /** @type {{ start: number, end: number }} */ (right); + + check_rune_binding('derived'); + + // $derived + state.str.update( + /** @type {number} */ (node.start), + /** @type {number} */ (node.body.expression.start), + 'let ' + ); + + if (right.type === 'SequenceExpression') { + while (state.str.original[start] !== '(') start -= 1; + while (state.str.original[end - 1] !== ')') end += 1; + } + + state.str.prependRight(start, `$derived(`); + + // in a case like `$: ({ a } = b())`, there's already a trailing parenthesis. + // otherwise, we need to add one + if (state.str.original[/** @type {number} */ (node.body.start)] !== '(') { + state.str.appendLeft(end, `)`); + } + + return; + } + + for (const binding of bindings) { + if (binding.reassigned && (ids.includes(binding.node) || expression_ids.length === 0)) { + check_rune_binding('state'); + const init = + binding.kind === 'state' + ? ' = $state()' + : expression_ids.length === 0 + ? ` = $state(${state.str.original.substring(/** @type {number} */ (right.start), right.end)})` + : ''; + // implicitly-declared variable which we need to make explicit + state.str.prependLeft( + /** @type {number} */ (node.start), + `let ${binding.node.name}${init};\n${state.indent}` + ); + } + } + + if (expression_ids.length === 0 && bindings.every((b) => b.kind !== 'store_sub')) { + state.str.remove(/** @type {number} */ (node.start), /** @type {number} */ (node.end)); + return; + } + } + } + + state.legacy_imports.add('run'); + const is_block_stmt = node.body.type === 'BlockStatement'; + const start_end = /** @type {number} */ (node.body.start); + // TODO try to find out if we can use $derived.by instead? + if (is_block_stmt) { + state.str.update( + /** @type {number} */ (node.start), + start_end + 1, + `${state.names.run}(() => {` + ); + const end = /** @type {number} */ (node.body.end); + state.str.update(end - 1, end, '});'); + } else { + state.str.update( + /** @type {number} */ (node.start), + start_end, + `${state.names.run}(() => {\n${state.indent}` + ); + state.str.indent(state.indent, { + exclude: [ + [0, /** @type {number} */ (node.body.start)], + [/** @type {number} */ (node.body.end), state.end] + ] + }); + state.str.appendLeft(/** @type {number} */ (node.end), `\n${state.indent}});`); + } + } +}; + +/** + * + * @param {State} state + * @param {number} start + * @param {number} end + */ +function trim_block(state, start, end) { + const original = state.str.snip(start, end).toString(); + const without_parens = original.substring(1, original.length - 1); + if (without_parens.trim().length !== without_parens.length) { + state.str.update(start + 1, end - 1, without_parens.trim()); + } +} + +/** @type {Visitors} */ +const template = { + Identifier(node, { state, path }) { + handle_identifier(node, state, path); + }, + RegularElement(node, { state, path, next }) { + // Strip off any namespace from the beginning of the node name. + const node_name = node.name.replace(/[a-zA-Z-]*:/g, ''); + + if (state.analysis.source[node.end - 2] === '/' && !is_void(node_name) && !is_svg(node_name)) { + let trimmed_position = node.end - 2; + while (state.str.original.charAt(trimmed_position - 1) === ' ') trimmed_position--; + state.str.remove(trimmed_position, node.end - 1); + state.str.appendLeft(node.end, ``); + } + + migrate_slot_usage(node, path, state); + handle_events(node, state); + + next(); + }, + SvelteSelf(node, { state, next }) { + const source = state.str.original.substring(node.start, node.end); + if (!state.filename) { + const indent = guess_indent(source); + has_migration_task = true; + state.str.prependRight( + node.start, + `\n${indent}` + ); + next(); + return; + } + // overwrite the open tag + state.str.overwrite( + node.start + 1, + node.start + 1 + 'svelte:self'.length, + `${state.analysis.name}` + ); + // if it has a fragment we need to overwrite the closing tag too + if (node.fragment.nodes.length > 0) { + state.str.overwrite( + state.str.original.lastIndexOf('<', node.end) + 2, + node.end - 1, + `${state.analysis.name}` + ); + } else if (!source.endsWith('/>')) { + // special case for case `` it has no fragment but + // we still need to overwrite the end tag + state.str.overwrite( + node.start + source.lastIndexOf('= 0; i--) { + const part = path[i]; + if ( + part.type === 'EachBlock' || + part.type === 'AwaitBlock' || + part.type === 'IfBlock' || + part.type === 'SnippetBlock' || + part.type === 'Component' || + part.type === 'SvelteComponent' + ) { + let position = node.start; + if (i !== path.length - 1) { + for (let modifier = 1; modifier < path.length - i; modifier++) { + const path_part = path[i + modifier]; + if ('start' in path_part) { + position = /** @type {number} */ (path_part.start); + break; + } + } + } + const indent = state.str.original.substring( + state.str.original.lastIndexOf('\n', position) + 1, + position + ); + state.str.appendRight( + position, + `{@const ${expression} = ${current_expression}}\n${indent}` + ); + needs_derived = false; + break; + } + } + if (needs_derived) { + if (state.derived_components.has(current_expression)) { + expression = /** @type {string} */ (state.derived_components.get(current_expression)); + } else { + state.derived_components.set(current_expression, expression); + } + } + } + + state.str.overwrite(node.start + 1, node.start + node.name.length + 1, expression); + + if (state.str.original.substring(node.end - node.name.length - 1, node.end - 1) === node.name) { + state.str.overwrite(node.end - node.name.length - 1, node.end - 1, expression); + } + let this_pos = state.str.original.lastIndexOf('this', node.expression.start); + while (!state.str.original.charAt(this_pos - 1).trim()) this_pos--; + const end_pos = state.str.original.indexOf('}', node.expression.end) + 1; + state.str.remove(this_pos, end_pos); + }, + SvelteFragment(node, { state, path, next }) { + migrate_slot_usage(node, path, state); + next(); + }, + SvelteWindow(node, { state, next }) { + handle_events(node, state); + next(); + }, + SvelteBody(node, { state, next }) { + handle_events(node, state); + next(); + }, + SvelteDocument(node, { state, next }) { + handle_events(node, state); + next(); + }, + SlotElement(node, { state, path, next, visit }) { + migrate_slot_usage(node, path, state); + + if (state.analysis.custom_element) return; + let name = 'children'; + let slot_name = 'default'; + let slot_props = '{ '; + let aliased_slot_name; + + for (const attr of node.attributes) { + if (attr.type === 'SpreadAttribute') { + slot_props += `...${state.str.original.substring(/** @type {number} */ (attr.expression.start), attr.expression.end)}, `; + } else if (attr.type === 'Attribute') { + if (attr.name === 'slot') { + continue; + } + + if (attr.name === 'name') { + slot_name = /** @type {any} */ (attr.value)[0].data; + // if some of the parents or this node itself har a slot + // attribute with the sane name of this slot + // we want to create a derived or the migrated snippet + // will shadow the slot prop + if ( + path.some( + (parent) => + (parent.type === 'RegularElement' || + parent.type === 'SvelteElement' || + parent.type === 'Component' || + parent.type === 'SvelteComponent' || + parent.type === 'SvelteFragment') && + parent.attributes.some( + (attribute) => + attribute.type === 'Attribute' && + attribute.name === 'slot' && + is_text_attribute(attribute) && + attribute.value[0].data === slot_name + ) + ) || + node.attributes.some( + (attribute) => + attribute.type === 'Attribute' && + attribute.name === 'slot' && + is_text_attribute(attribute) && + attribute.value[0].data === slot_name + ) + ) { + aliased_slot_name = `${slot_name}_render`; + state.derived_conflicting_slots.set(aliased_slot_name, slot_name); + } + } else { + const attr_value = + attr.value === true || Array.isArray(attr.value) ? attr.value : [attr.value]; + let value = 'true'; + if (attr_value !== true) { + const first = attr_value[0]; + const last = attr_value[attr_value.length - 1]; + for (const attr of attr_value) { + visit(attr); + } + value = state.str + .snip( + first.type === 'Text' + ? first.start - 1 + : /** @type {number} */ (first.expression.start), + last.type === 'Text' ? last.end + 1 : /** @type {number} */ (last.expression.end) + ) + .toString(); + } + slot_props += value === attr.name ? `${value}, ` : `${attr.name}: ${value}, `; + } + } + } + + slot_props += '}'; + if (slot_props === '{ }') { + slot_props = ''; + } + + const existing_prop = state.props.find((prop) => prop.slot_name === slot_name); + if (existing_prop) { + name = existing_prop.local; + } else if (slot_name !== 'default') { + name = state.scope.generate(slot_name); + if (name !== slot_name) { + throw new MigrationError( + `This migration would change the name of a slot (${slot_name} to ${name}) making the component unusable` + ); + } + } + + if (!existing_prop) { + state.props.push({ + local: name, + exported: name, + init: '', + bindable: false, + optional: true, + slot_name, + type: `import('svelte').${slot_props ? 'Snippet<[any]>' : 'Snippet'}` + }); + } else if (existing_prop.needs_refine_type) { + existing_prop.type = `import('svelte').${slot_props ? 'Snippet<[any]>' : 'Snippet'}`; + existing_prop.needs_refine_type = false; + } + + if ( + slot_name === 'default' && + path.some( + (parent) => + (parent.type === 'SvelteComponent' || + parent.type === 'Component' || + parent.type === 'RegularElement' || + parent.type === 'SvelteElement' || + parent.type === 'SvelteFragment') && + parent.attributes.some((attr) => attr.type === 'LetDirective') + ) + ) { + aliased_slot_name = `${name}_render`; + state.derived_conflicting_slots.set(aliased_slot_name, name); + } + name = aliased_slot_name ?? name; + + if (node.fragment.nodes.length > 0) { + next(); + state.str.update( + node.start, + node.fragment.nodes[0].start, + `{#if ${name}}{@render ${state.analysis.uses_props ? `${state.names.props}.` : ''}${name}(${slot_props})}{:else}` + ); + state.str.update(node.fragment.nodes[node.fragment.nodes.length - 1].end, node.end, '{/if}'); + } else { + state.str.update( + node.start, + node.end, + `{@render ${state.analysis.uses_props ? `${state.names.props}.` : ''}${name}?.(${slot_props})}` + ); + } + }, + Comment(node, { state }) { + const migrated = migrate_svelte_ignore(node.data); + if (migrated !== node.data) { + state.str.overwrite(node.start + ''.length, migrated); + } + }, + HtmlTag(node, { state, next }) { + trim_block(state, node.start, node.end); + next(); + }, + ConstTag(node, { state, next }) { + trim_block(state, node.start, node.end); + next(); + }, + IfBlock(node, { state, next }) { + const start = node.start; + const end = state.str.original.indexOf('}', node.test.end) + 1; + trim_block(state, start, end); + next(); + }, + AwaitBlock(node, { state, next }) { + const start = node.start; + const end = + state.str.original.indexOf( + '}', + node.pending !== null ? node.expression.end : node.value?.end + ) + 1; + trim_block(state, start, end); + if (node.pending !== null) { + const start = state.str.original.lastIndexOf('{', node.value?.start); + const end = state.str.original.indexOf('}', node.value?.end) + 1; + trim_block(state, start, end); + } + if (node.catch !== null) { + const start = state.str.original.lastIndexOf('{', node.error?.start); + const end = state.str.original.indexOf('}', node.error?.end) + 1; + trim_block(state, start, end); + } + next(); + }, + KeyBlock(node, { state, next }) { + const start = node.start; + const end = state.str.original.indexOf('}', node.expression.end) + 1; + trim_block(state, start, end); + next(); + } +}; + +/** + * @param {AST.RegularElement | AST.SvelteElement | AST.SvelteComponent | AST.Component | AST.SlotElement | AST.SvelteFragment} node + * @param {AST.SvelteNode[]} path + * @param {State} state + */ +function migrate_slot_usage(node, path, state) { + const parent = path.at(-2); + // Bail on custom element slot usage + if ( + parent?.type !== 'Component' && + parent?.type !== 'SvelteComponent' && + node.type !== 'Component' && + node.type !== 'SvelteComponent' + ) { + return; + } + + let snippet_name = 'children'; + let snippet_props = []; + + // if we stop the transform because the name is not correct we don't want to + // remove the let directive and they could come before the name + let removal_queue = []; + + for (let attribute of node.attributes) { + if ( + attribute.type === 'Attribute' && + attribute.name === 'slot' && + is_text_attribute(attribute) + ) { + snippet_name = attribute.value[0].data; + // the default slot in svelte 4 if what the children slot is for svelte 5 + if (snippet_name === 'default') { + snippet_name = 'children'; + } + if (!regex_is_valid_identifier.test(snippet_name) || is_reserved(snippet_name)) { + has_migration_task = true; + state.str.appendLeft( + node.start, + `\n${state.indent}` + ); + return; + } + if (parent?.type === 'Component' || parent?.type === 'SvelteComponent') { + for (let attribute of parent.attributes) { + if (attribute.type === 'Attribute' || attribute.type === 'BindDirective') { + if (attribute.name === snippet_name) { + state.str.appendLeft( + node.start, + `\n${state.indent}` + ); + return; + } + } + } + } + // flush the queue after we found the name + for (let remove_let of removal_queue) { + remove_let(); + } + state.str.remove(attribute.start, attribute.end); + } + if (attribute.type === 'LetDirective') { + snippet_props.push( + attribute.name + + (attribute.expression + ? `: ${state.str.original.substring(/** @type {number} */ (attribute.expression.start), /** @type {number} */ (attribute.expression.end))}` + : '') + ); + // we just add to the queue to remove them after we found if we need to migrate or we bail + removal_queue.push(() => state.str.remove(attribute.start, attribute.end)); + } + } + + if (removal_queue.length > 0) { + for (let remove_let of removal_queue) { + remove_let(); + } + } + + if (node.type === 'SvelteFragment' && node.fragment.nodes.length > 0) { + // remove node itself, keep content + state.str.remove(node.start, node.fragment.nodes[0].start); + state.str.remove(node.fragment.nodes[node.fragment.nodes.length - 1].end, node.end); + } + + const props = snippet_props.length > 0 ? `{ ${snippet_props.join(', ')} }` : ''; + + if (snippet_name === 'children' && node.type !== 'SvelteFragment') { + if (snippet_props.length === 0) return; // nothing to do + + let inner_start = 0; + let inner_end = 0; + for (let i = 0; i < node.fragment.nodes.length; i++) { + const inner = node.fragment.nodes[i]; + const is_empty_text = inner.type === 'Text' && !inner.data.trim(); + + if ( + (inner.type === 'RegularElement' || + inner.type === 'SvelteElement' || + inner.type === 'Component' || + inner.type === 'SvelteComponent' || + inner.type === 'SlotElement' || + inner.type === 'SvelteFragment') && + inner.attributes.some((attr) => attr.type === 'Attribute' && attr.name === 'slot') + ) { + if (inner_start && !inner_end) { + // End of default slot content + inner_end = inner.start; + } + } else if (!inner_start && !is_empty_text) { + // Start of default slot content + inner_start = inner.start; + } else if (inner_end && !is_empty_text) { + // There was default slot content before, then some named slot content, now some default slot content again. + // We're moving the last character back by one to avoid the closing {/snippet} tag inserted afterwards + // to come before the opening {#snippet} tag of the named slot. + state.str.update(inner_end - 1, inner_end, ''); + state.str.prependLeft(inner_end - 1, state.str.original[inner_end - 1]); + state.str.move(inner.start, inner.end, inner_end - 1); + } + } + + if (!inner_end) { + inner_end = node.fragment.nodes[node.fragment.nodes.length - 1].end; + } + + state.str.appendLeft( + inner_start, + `{#snippet ${snippet_name}(${props})}\n${state.indent.repeat(path.length)}` + ); + state.str.indent(state.indent, { + exclude: [ + [0, inner_start], + [inner_end, state.str.original.length] + ] + }); + if (inner_end < node.fragment.nodes[node.fragment.nodes.length - 1].end) { + // Named slots coming afterwards + state.str.prependLeft(inner_end, `{/snippet}\n${state.indent.repeat(path.length)}`); + } else { + // No named slots coming afterwards + state.str.prependLeft( + inner_end, + `${state.indent.repeat(path.length)}{/snippet}\n${state.indent.repeat(path.length - 1)}` + ); + } + } else { + // Named slot or `svelte:fragment`: wrap element itself in a snippet + state.str.prependLeft( + node.start, + `{#snippet ${snippet_name}(${props})}\n${state.indent.repeat(path.length - 2)}` + ); + state.str.indent(state.indent, { + exclude: [ + [0, node.start], + [node.end, state.str.original.length] + ] + }); + const str = `\n${state.indent.repeat(path.length - 2)}{/snippet}`; + + if (node.type === 'SlotElement') { + state.str.appendRight(node.end, str); + } else { + state.str.appendLeft(node.end, str); + } + } +} + +/** + * @param {VariableDeclarator} declarator + * @param {State} state + * @param {AST.SvelteNode[]} path + */ +function extract_type_and_comment(declarator, state, path) { + const str = state.str; + const parent = path.at(-1); + + // Try to find jsdoc above the declaration + let comment_node = /** @type {Node} */ (parent)?.leadingComments?.at(-1); + + const comment_start = /** @type {any} */ (comment_node)?.start; + const comment_end = /** @type {any} */ (comment_node)?.end; + let comment = comment_node && str.original.substring(comment_start, comment_end); + if (comment_node) { + str.update(comment_start, comment_end, ''); + } + + // Find trailing comments + const trailing_comment_node = /** @type {Node} */ (parent)?.trailingComments?.at(0); + const trailing_comment_start = /** @type {any} */ (trailing_comment_node)?.start; + const trailing_comment_end = /** @type {any} */ (trailing_comment_node)?.end; + let trailing_comment = + trailing_comment_node && str.original.substring(trailing_comment_start, trailing_comment_end); + + if (trailing_comment_node) { + str.update(trailing_comment_start, trailing_comment_end, ''); + } + + if (declarator.id.typeAnnotation) { + state.has_type_or_fallback = true; + let start = declarator.id.typeAnnotation.start + 1; // skip the colon + while (str.original[start] === ' ') { + start++; + } + return { + type: str.original.substring(start, declarator.id.typeAnnotation.end), + comment, + trailing_comment + }; + } + + let cleaned_comment_arr = comment + ?.split('\n') + .map((line) => + line + .trim() + // replace `// ` for one liners + .replace(/^\/\/\s*/g, '') + // replace `\**` for the initial JSDoc + .replace(/^\/\*\*?\s*/g, '') + // migrate `*/` for the end of JSDoc + .replace(/\s*\*\/$/g, '') + // remove any initial `* ` to clean the comment + .replace(/^\*\s*/g, '') + ) + .filter(Boolean); + const first_at_comment = cleaned_comment_arr?.findIndex((line) => line.startsWith('@')); + let cleaned_comment = cleaned_comment_arr + ?.slice(0, first_at_comment !== -1 ? first_at_comment : cleaned_comment_arr.length) + .join('\n'); + + let cleaned_comment_arr_trailing = trailing_comment + ?.split('\n') + .map((line) => + line + .trim() + // replace `// ` for one liners + .replace(/^\/\/\s*/g, '') + // replace `\**` for the initial JSDoc + .replace(/^\/\*\*?\s*/g, '') + // migrate `*/` for the end of JSDoc + .replace(/\s*\*\/$/g, '') + // remove any initial `* ` to clean the comment + .replace(/^\*\s*/g, '') + ) + .filter(Boolean); + const first_at_comment_trailing = cleaned_comment_arr_trailing?.findIndex((line) => + line.startsWith('@') + ); + let cleaned_comment_trailing = cleaned_comment_arr_trailing + ?.slice( + 0, + first_at_comment_trailing !== -1 + ? first_at_comment_trailing + : cleaned_comment_arr_trailing.length + ) + .join('\n'); + + // try to find a comment with a type annotation, hinting at jsdoc + if (parent?.type === 'ExportNamedDeclaration' && comment_node) { + state.has_type_or_fallback = true; + const match = /@type {(.+)}/.exec(comment_node.value); + if (match) { + // try to find JSDoc comments after a hyphen `-` + const jsdoc_comment = /@type {.+} (?:\w+|\[.*?\]) - (.+)/.exec(comment_node.value); + if (jsdoc_comment) { + cleaned_comment += jsdoc_comment[1]?.trim(); + } + return { + type: match[1], + comment: cleaned_comment, + trailing_comment: cleaned_comment_trailing + }; + } + } + + // try to infer it from the init + if (declarator.init?.type === 'Literal') { + state.has_type_or_fallback = true; // only assume type if it's trivial to infer - else someone would've added a type annotation + const type = typeof declarator.init.value; + if (type === 'string' || type === 'number' || type === 'boolean') { + return { + type, + comment: state.uses_ts ? comment : cleaned_comment, + trailing_comment: state.uses_ts ? trailing_comment : cleaned_comment_trailing + }; + } + } + return { + type: 'any', + comment: state.uses_ts ? comment : cleaned_comment, + trailing_comment: state.uses_ts ? trailing_comment : cleaned_comment_trailing + }; +} + +// Ensure modifiers are applied in the same order as Svelte 4 +const modifier_order = /** @type {const} */ ([ + 'preventDefault', + 'stopPropagation', + 'stopImmediatePropagation', + 'self', + 'trusted', + 'once' +]); + +/** + * @param {AST.RegularElement | AST.SvelteElement | AST.SvelteWindow | AST.SvelteDocument | AST.SvelteBody} element + * @param {State} state + */ +function handle_events(element, state) { + /** @type {Map} */ + const handlers = new Map(); + for (const attribute of element.attributes) { + if (attribute.type !== 'OnDirective') continue; + + let name = `on${attribute.name}`; + if (attribute.modifiers.includes('capture')) { + name += 'capture'; + } + + const nodes = handlers.get(name) || []; + nodes.push(attribute); + handlers.set(name, nodes); + } + + for (const [name, nodes] of handlers) { + const handlers = []; + + let first = null; + + for (const node of nodes) { + /** @type {string} */ + let body; + + if (node.expression) { + body = state.str.original.substring( + /** @type {number} */ (node.expression.start), + /** @type {number} */ (node.expression.end) + ); + } else { + body = `${state.names.bubble}('${node.name}')`; + state.legacy_imports.add('createBubbler'); + state.script_insertions.add( + `const ${state.names.bubble} = ${state.names.createBubbler}();` + ); + } + + const has_passive = node.modifiers.includes('passive'); + const has_nonpassive = node.modifiers.includes('nonpassive'); + + const modifiers = modifier_order.filter((modifier) => node.modifiers.includes(modifier)); + + for (const modifier of modifiers) { + state.legacy_imports.add(modifier); + body = `${state.names[modifier]}(${body})`; + } + + if (has_passive || has_nonpassive) { + const action = has_passive ? 'passive' : 'nonpassive'; + state.legacy_imports.add(action); + + state.str.overwrite( + node.start, + node.end, + `use:${state.names[action]}={['${node.name}', () => ${body}]}` + ); + } else { + if (first) { + let start = node.start; + let end = node.end; + + while (/[\s\n]/.test(state.str.original[start - 1])) start -= 1; + state.str.remove(start, end); + } else { + first = node; + } + + handlers.push(body); + } + } + + if (first) { + /** @type {string} */ + let replacement; + + if (handlers.length > 1) { + state.legacy_imports.add('handlers'); + replacement = `${name}={${state.names.handlers}(${handlers.join(', ')})}`; + } else { + const handler = handlers[0]; + replacement = handler === name ? `{${handler}}` : `${name}={${handler}}`; + } + + state.str.overwrite(first.start, first.end, replacement); + } + } +} + +/** + * Returns start and end of the node. If the start is preceded with white-space-only before a line break, + * the start will be the start of the line. + * @param {string} source + * @param {LabeledStatement} node + */ +function get_node_range(source, node) { + const first_leading_comment = node.leadingComments?.[0]; + const last_trailing_comment = node.trailingComments?.[node.trailingComments.length - 1]; + + // @ts-expect-error the type of `Comment` seems to be wrong...the node actually contains + // start and end but the type seems to only contain a `range` (which doesn't actually exists) + let start = /** @type {number} */ (first_leading_comment?.start ?? node.start); + // @ts-expect-error the type of `Comment` seems to be wrong...the node actually contains + // start and end but the type seems to only contain a `range` (which doesn't actually exists) + let end = /** @type {number} */ (last_trailing_comment?.end ?? node.end); + + let idx = start; + while (source[idx - 1] !== '\n' && source[idx - 1] !== '\r') { + idx--; + if (source[idx] !== ' ' && source[idx] !== '\t') { + idx = start; + break; + } + } + + start = idx; + + return { start, end }; +} + +/** + * @param {Identifier} node + * @param {State} state + * @param {any[]} path + */ +function handle_identifier(node, state, path) { + const parent = path.at(-1); + if (parent?.type === 'MemberExpression' && parent.property === node) return; + + if (state.analysis.uses_props && node.name !== '$$slots') { + if (node.name === '$$props' || node.name === '$$restProps') { + // not 100% correct for $$restProps but it'll do + state.str.update( + /** @type {number} */ (node.start), + /** @type {number} */ (node.end), + state.names.props + ); + } else { + const binding = state.scope.get(node.name); + if (binding?.kind === 'bindable_prop' && binding.node !== node) { + state.str.prependLeft(/** @type {number} */ (node.start), `${state.names.props}.`); + } + } + } else if (node.name === '$$restProps' && state.analysis.uses_rest_props) { + state.str.update( + /** @type {number} */ (node.start), + /** @type {number} */ (node.end), + state.names.rest + ); + } else if (node.name === '$$slots' && state.analysis.uses_slots) { + if (parent?.type === 'MemberExpression') { + if (state.analysis.custom_element) return; + + let name = parent.property.type === 'Literal' ? parent.property.value : parent.property.name; + let slot_name = name; + const existing_prop = state.props.find((prop) => prop.slot_name === name); + if (existing_prop) { + name = existing_prop.local; + } else if (name !== 'default') { + let new_name = state.scope.generate(name); + if (new_name !== name) { + throw new MigrationError( + `This migration would change the name of a slot (${name} to ${new_name}) making the component unusable` + ); + } + } + + name = name === 'default' ? 'children' : name; + + if (!existing_prop) { + state.props.push({ + local: name, + exported: name, + init: '', + bindable: false, + optional: true, + slot_name, + // if it's the first time we encounter this slot + // we start with any and delegate to when the slot + // is actually rendered (it might not happen in that case) + // any is still a safe bet + type: `import('svelte').Snippet<[any]>`, + needs_refine_type: true + }); + } + + state.str.update( + /** @type {number} */ (node.start), + parent.property.start, + state.analysis.uses_props ? `${state.names.props}.` : '' + ); + state.str.update(parent.property.start, parent.end, name); + } + // else passed as identifier, we don't know what to do here, so let it error + } else if ( + parent?.type === 'TSInterfaceDeclaration' || + parent?.type === 'TSTypeAliasDeclaration' + ) { + const members = + parent.type === 'TSInterfaceDeclaration' ? parent.body.body : parent.typeAnnotation?.members; + if (Array.isArray(members)) { + if (node.name === '$$Props') { + state.has_type_or_fallback = true; + + for (const member of members) { + const prop = state.props.find((prop) => prop.exported === member.key.name); + + const type = state.str.original.substring( + member.typeAnnotation.typeAnnotation.start, + member.typeAnnotation.typeAnnotation.end + ); + + let comment; + const comment_node = member.leadingComments?.at(-1); + if (comment_node?.type === 'Block') { + comment = state.str.original.substring(comment_node.start, comment_node.end); + } + + const trailing_comment = member.trailingComments?.at(0)?.value; + + if (prop) { + prop.type = type; + prop.optional = member.optional; + prop.comment = comment ?? prop.comment; + prop.trailing_comment = trailing_comment ?? prop.trailing_comment; + } else { + state.props.push({ + local: member.key.name, + exported: member.key.name, + init: '', + bindable: false, + optional: member.optional, + type, + comment, + trailing_comment, + type_only: true + }); + } + } + + state.str.remove(parent.start, parent.end); + } + } + } +} + +/** @param {string} content */ +function guess_indent(content) { + const lines = content.split('\n'); + + const tabbed = lines.filter((line) => /^\t+/.test(line)); + const spaced = lines.filter((line) => /^ {2,}/.test(line)); + + if (tabbed.length === 0 && spaced.length === 0) { + return '\t'; + } + + // More lines tabbed than spaced? Assume tabs, and + // default to tabs in the case of a tie (or nothing + // to go on) + if (tabbed.length >= spaced.length) { + return '\t'; + } + + // Otherwise, we need to guess the multiple + const min = spaced.reduce((previous, current) => { + const count = /^ +/.exec(current)?.[0].length ?? 0; + return Math.min(count, previous); + }, Infinity); + + return ' '.repeat(min); +} diff --git a/frontend/node_modules/svelte/src/compiler/phases/1-parse/acorn.js b/frontend/node_modules/svelte/src/compiler/phases/1-parse/acorn.js new file mode 100644 index 0000000..77ce4a4 --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/phases/1-parse/acorn.js @@ -0,0 +1,198 @@ +/** @import { Comment, Program } from 'estree' */ +/** @import { AST } from '#compiler' */ +import * as acorn from 'acorn'; +import { walk } from 'zimmerframe'; +import { tsPlugin } from '@sveltejs/acorn-typescript'; + +const ParserWithTS = acorn.Parser.extend(tsPlugin()); + +/** + * @typedef {Comment & { + * start: number; + * end: number; + * }} CommentWithLocation + */ + +/** + * @param {string} source + * @param {AST.JSComment[]} comments + * @param {boolean} typescript + * @param {boolean} [is_script] + */ +export function parse(source, comments, typescript, is_script) { + const parser = typescript ? ParserWithTS : acorn.Parser; + + const { onComment, add_comments } = get_comment_handlers( + source, + /** @type {CommentWithLocation[]} */ (comments) + ); + + // @ts-ignore + const parse_statement = parser.prototype.parseStatement; + + // If we're dealing with a '); + }, + + Fragment(node, context) { + /** @type {AST.SvelteNode[][]} */ + const items = []; + + /** @type {AST.SvelteNode[]} */ + let sequence = []; + + const flush = () => { + items.push(sequence); + sequence = []; + }; + + for (let i = 0; i < node.nodes.length; i += 1) { + let child_node = node.nodes[i]; + + const prev = node.nodes[i - 1]; + const next = node.nodes[i + 1]; + + if (child_node.type === 'Text') { + child_node = { ...child_node }; // always clone, so we can safely mutate + + child_node.data = child_node.data.replace(/[^\S]+/g, ' '); + + // trim fragment + if (i === 0) { + child_node.data = child_node.data.trimStart(); + } + + if (i === node.nodes.length - 1) { + child_node.data = child_node.data.trimEnd(); + } + + if (child_node.data === '') { + continue; + } + + if (child_node.data.startsWith(' ') && prev && prev.type !== 'ExpressionTag') { + flush(); + child_node.data = child_node.data.trimStart(); + } + + if (child_node.data !== '') { + sequence.push({ ...child_node, data: child_node.data }); + + if (child_node.data.endsWith(' ') && next && next.type !== 'ExpressionTag') { + flush(); + child_node.data = child_node.data.trimStart(); + } + } + } else { + const is_block_element = + child_node.type === 'RegularElement' || + child_node.type === 'Component' || + child_node.type === 'SvelteHead' || + child_node.type === 'SvelteFragment' || + child_node.type === 'SvelteBoundary' || + child_node.type === 'SvelteDocument' || + child_node.type === 'SvelteSelf' || + child_node.type === 'SvelteWindow' || + child_node.type === 'SvelteComponent' || + child_node.type === 'SvelteElement' || + child_node.type === 'SlotElement' || + child_node.type === 'TitleElement'; + + if (is_block_element && sequence.length > 0) flush(); + sequence.push(child_node); + if (is_block_element) flush(); + } + } + + flush(); + + let multiline = false; + let width = 0; + + const child_contexts = items + .filter((x) => x.length > 0) + .map((sequence) => { + const child_context = context.new(); + + for (const node of sequence) { + child_context.visit(node); + multiline ||= child_context.multiline; + } + + width += child_context.measure(); + + return child_context; + }); + + multiline ||= width > LINE_BREAK_THRESHOLD; + + for (let i = 0; i < child_contexts.length; i += 1) { + const prev = child_contexts[i]; + const next = child_contexts[i + 1]; + + context.append(prev); + + if (next) { + if (prev.multiline || next.multiline) { + context.margin(); + context.newline(); + } else if (multiline) { + context.newline(); + } + } + } + }, + + AnimateDirective(node, context) { + context.write(`animate:${node.name}`); + if ( + node.expression !== null && + !(node.expression.type === 'Identifier' && node.expression.name === node.name) + ) { + context.write('={'); + context.visit(node.expression); + context.write('}'); + } + }, + + AttachTag(node, context) { + context.write('{@attach '); + context.visit(node.expression); + context.write('}'); + }, + + Attribute(node, context) { + context.write(node.name); + + if (node.value === true) return; + + context.write('='); + + if (Array.isArray(node.value)) { + if (node.value.length > 1 || node.value[0].type === 'Text') { + context.write('"'); + } + + for (const chunk of node.value) { + context.visit(chunk); + } + + if (node.value.length > 1 || node.value[0].type === 'Text') { + context.write('"'); + } + } else { + context.visit(node.value); + } + }, + + AwaitBlock(node, context) { + context.write(`{#await `); + context.visit(node.expression); + + if (node.pending) { + context.write('}'); + block(context, node.pending); + context.write('{:'); + } else { + context.write(' '); + } + + if (node.then) { + context.write(node.value ? 'then ' : 'then'); + if (node.value) context.visit(node.value); + context.write('}'); + + block(context, node.then); + + if (node.catch) { + context.write('{:'); + } + } + + if (node.catch) { + context.write(node.value ? 'catch ' : 'catch'); + if (node.error) context.visit(node.error); + context.write('}'); + + block(context, node.catch); + } + + context.write('{/await}'); + }, + + BindDirective(node, context) { + context.write(`bind:${node.name}`); + + if (node.expression.type === 'Identifier' && node.expression.name === node.name) { + // shorthand + return; + } + + context.write('={'); + + if (node.expression.type === 'SequenceExpression') { + context.visit(node.expression.expressions[0]); + context.write(', '); + context.visit(node.expression.expressions[1]); + } else { + context.visit(node.expression); + } + + context.write('}'); + }, + + ClassDirective(node, context) { + context.write(`class:${node.name}`); + if ( + node.expression !== null && + !(node.expression.type === 'Identifier' && node.expression.name === node.name) + ) { + context.write('={'); + context.visit(node.expression); + context.write('}'); + } + }, + + Comment(node, context) { + context.write(''); + }, + + Component(node, context) { + base_element(node, context, comments); + }, + + ConstTag(node, context) { + context.write('{@'); + context.visit(node.declaration); + context.write('}'); + }, + + DebugTag(node, context) { + context.write('{@debug '); + let started = false; + for (const identifier of node.identifiers) { + if (started) { + context.write(', '); + } + context.visit(identifier); + started = true; + } + context.write('}'); + }, + + EachBlock(node, context) { + context.write('{#each '); + context.visit(node.expression); + + if (node.context) { + context.write(' as '); + context.visit(node.context); + } + + if (node.index) { + context.write(`, ${node.index}`); + } + + if (node.key) { + context.write(' ('); + context.visit(node.key); + context.write(')'); + } + + context.write('}'); + + block(context, node.body); + + if (node.fallback) { + context.write('{:else}'); + block(context, node.fallback); + } + + context.write('{/each}'); + }, + + ExpressionTag(node, context) { + context.write('{'); + context.visit(node.expression); + context.write('}'); + }, + + HtmlTag(node, context) { + context.write('{@html '); + context.visit(node.expression); + context.write('}'); + }, + + IfBlock(node, context) { + if (node.elseif) { + context.write('{:else if '); + context.visit(node.test); + context.write('}'); + + block(context, node.consequent); + } else { + context.write('{#if '); + context.visit(node.test); + context.write('}'); + + block(context, node.consequent); + } + + if (node.alternate !== null) { + if ( + !( + node.alternate.nodes.length === 1 && + node.alternate.nodes[0].type === 'IfBlock' && + node.alternate.nodes[0].elseif + ) + ) { + context.write('{:else}'); + block(context, node.alternate); + } else { + context.visit(node.alternate); + } + } + + if (!node.elseif) { + context.write('{/if}'); + } + }, + + KeyBlock(node, context) { + context.write('{#key '); + context.visit(node.expression); + context.write('}'); + block(context, node.fragment); + context.write('{/key}'); + }, + + LetDirective(node, context) { + context.write(`let:${node.name}`); + if ( + node.expression !== null && + !(node.expression.type === 'Identifier' && node.expression.name === node.name) + ) { + context.write('={'); + context.visit(node.expression); + context.write('}'); + } + }, + + OnDirective(node, context) { + context.write(`on:${node.name}`); + for (const modifier of node.modifiers) { + context.write(`|${modifier}`); + } + if ( + node.expression !== null && + !(node.expression.type === 'Identifier' && node.expression.name === node.name) + ) { + context.write('={'); + context.visit(node.expression); + context.write('}'); + } + }, + + RegularElement(node, context) { + base_element(node, context, comments); + }, + + RenderTag(node, context) { + context.write('{@render '); + context.visit(node.expression); + context.write('}'); + }, + + SlotElement(node, context) { + base_element(node, context, comments); + }, + + SnippetBlock(node, context) { + context.write('{#snippet '); + context.visit(node.expression); + + if (node.typeParams) { + context.write(`<${node.typeParams}>`); + } + + context.write('('); + + for (let i = 0; i < node.parameters.length; i += 1) { + if (i > 0) context.write(', '); + context.visit(node.parameters[i]); + } + + context.write(')}'); + block(context, node.body); + context.write('{/snippet}'); + }, + + SpreadAttribute(node, context) { + context.write('{...'); + context.visit(node.expression); + context.write('}'); + }, + + StyleDirective(node, context) { + context.write(`style:${node.name}`); + for (const modifier of node.modifiers) { + context.write(`|${modifier}`); + } + + if (node.value === true) { + return; + } + + context.write('='); + + if (Array.isArray(node.value)) { + context.write('"'); + + for (const tag of node.value) { + context.visit(tag); + } + + context.write('"'); + } else { + context.visit(node.value); + } + }, + + StyleSheet(node, context) { + context.write(''); + + if (node.children.length > 0) { + context.indent(); + context.newline(); + + let started = false; + + for (const child of node.children) { + if (started) { + context.margin(); + context.newline(); + } + + context.visit(child); + started = true; + } + + context.dedent(); + context.newline(); + } + + context.write(''); + }, + + SvelteBoundary(node, context) { + base_element(node, context, comments); + }, + + SvelteComponent(node, context) { + context.write(' 0) { + context.write('>'); + block(context, node.fragment, true); + context.write(``); + } else { + context.write(' />'); + } + }, + + SvelteDocument(node, context) { + base_element(node, context, comments); + }, + + SvelteElement(node, context) { + context.write(' 0) { + context.write('>'); + block(context, node.fragment); + context.write(``); + } else { + context.write(' />'); + } + }, + + SvelteFragment(node, context) { + base_element(node, context, comments); + }, + + SvelteHead(node, context) { + base_element(node, context, comments); + }, + + SvelteSelf(node, context) { + base_element(node, context, comments); + }, + + SvelteWindow(node, context) { + base_element(node, context, comments); + }, + + Text(node, context) { + context.write(node.data); + }, + + TitleElement(node, context) { + base_element(node, context, comments); + }, + + TransitionDirective(node, context) { + const directive = node.intro && node.outro ? 'transition' : node.intro ? 'in' : 'out'; + context.write(`${directive}:${node.name}`); + for (const modifier of node.modifiers) { + context.write(`|${modifier}`); + } + if ( + node.expression !== null && + !(node.expression.type === 'Identifier' && node.expression.name === node.name) + ) { + context.write('={'); + context.visit(node.expression); + context.write('}'); + } + }, + + UseDirective(node, context) { + context.write(`use:${node.name}`); + if ( + node.expression !== null && + !(node.expression.type === 'Identifier' && node.expression.name === node.name) + ) { + context.write('={'); + context.visit(node.expression); + context.write('}'); + } + } +}); diff --git a/frontend/node_modules/svelte/src/compiler/state.js b/frontend/node_modules/svelte/src/compiler/state.js new file mode 100644 index 0000000..5ae001e --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/state.js @@ -0,0 +1,175 @@ +/** @import { Location } from 'locate-character' */ +/** @import { CompileOptions } from './types' */ +/** @import { AST, Warning } from '#compiler' */ +import { getLocator } from 'locate-character'; +import { sanitize_location } from '../utils.js'; + +/** @typedef {{ start?: number, end?: number }} NodeLike */ + +/** @type {Warning[]} */ +export let warnings = []; + +/** + * The filename relative to the rootDir (if specified). + * This should not be used in the compiler output except in dev mode + * @type {string} + */ +export let filename; + +/** + * This is the fallback used when no filename is specified. + */ +export const UNKNOWN_FILENAME = '(unknown)'; + +/** + * The name of the component that is used in the `export default function ...` statement. + */ +export let component_name = ''; + +/** + * The original source code + * @type {string} + */ +export let source; + +/** + * The source code split into lines (set by `set_source`) + * @type {string[]} + */ +export let source_lines = []; + +/** + * True if compiling with `dev: true` + * @type {boolean} + */ +export let dev; + +export let runes = false; + +/** @type {(index: number) => Location} */ +export let locator; + +/** @param {string} value */ +export function set_source(value) { + source = value; + source_lines = source.split('\n'); + + const l = getLocator(source, { offsetLine: 1 }); + + locator = (i) => { + const loc = l(i); + if (!loc) throw new Error('An impossible situation occurred'); + + return loc; + }; +} + +/** + * @param {AST.SvelteNode & { start?: number | undefined }} node + */ +export function locate_node(node) { + const loc = locator(/** @type {number} */ (node.start)); + return `${sanitize_location(filename)}:${loc?.line}:${loc.column}`; +} + +/** @type {NonNullable} */ +export let warning_filter; + +/** + * The current stack of ignored warnings + * @type {Set[]} + */ +export let ignore_stack = []; + +/** + * For each node the list of warnings that should be ignored for that node. + * Exists in addition to `ignore_stack` because not all warnings are emitted + * while the stack is being built. + * @type {Map[]>} + */ +export let ignore_map = new Map(); + +/** + * Cached snapshot of the ignore_stack. Only re-created when the stack changes + * (i.e. when push_ignore or pop_ignore is called), avoiding a structuredClone + * on every node visit during analysis. + * @type {Set[] | null} + */ +let cached_ignore_snapshot = null; + +/** + * Returns a snapshot of the current ignore_stack, reusing a cached copy + * when the stack hasn't changed since the last call. + * @returns {Set[]} + */ +export function get_ignore_snapshot() { + if (cached_ignore_snapshot === null) { + cached_ignore_snapshot = ignore_stack.map((s) => new Set(s)); + } + return cached_ignore_snapshot; +} + +/** + * @param {string[]} ignores + */ +export function push_ignore(ignores) { + const next = new Set([...(ignore_stack.at(-1) || []), ...ignores]); + ignore_stack.push(next); + cached_ignore_snapshot = null; +} + +export function pop_ignore() { + ignore_stack.pop(); + cached_ignore_snapshot = null; +} + +/** + * @param {AST.SvelteNode | NodeLike} node + * @param {typeof import('../constants.js').IGNORABLE_RUNTIME_WARNINGS[number]} code + * @returns + */ +export function is_ignored(node, code) { + return dev && !!ignore_map.get(node)?.some((codes) => codes.has(code)); +} + +/** + * Call this to reset the compiler state. Should be called before each compilation. + * @param {{ warning?: (warning: Warning) => boolean; filename: string | undefined }} state + */ +export function reset(state) { + dev = false; + runes = false; + component_name = UNKNOWN_FILENAME; + source = ''; + source_lines = []; + filename = (state.filename ?? UNKNOWN_FILENAME).replace(/\\/g, '/'); + warning_filter = state.warning ?? (() => true); + warnings = []; +} + +/** + * Adjust the compiler state based on the provided state object. + * Call this after parsing and basic analysis happened. + * @param {{ + * dev: boolean; + * component_name?: string; + * rootDir?: string; + * runes: boolean; + * }} state + */ +export function adjust(state) { + const root_dir = state.rootDir?.replace(/\\/g, '/'); + + dev = state.dev; + runes = state.runes; + component_name = state.component_name ?? UNKNOWN_FILENAME; + + if (typeof root_dir === 'string' && filename.startsWith(root_dir)) { + // make filename relative to rootDir + filename = filename.replace(root_dir, '').replace(/^[/\\]/, ''); + } + + ignore_stack = []; + ignore_map.clear(); + cached_ignore_snapshot = null; +} diff --git a/frontend/node_modules/svelte/src/compiler/utils/assert.js b/frontend/node_modules/svelte/src/compiler/utils/assert.js new file mode 100644 index 0000000..6434e4d --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/utils/assert.js @@ -0,0 +1,9 @@ +/** + * @template T + * @param {any} actual + * @param {T} expected + * @returns {asserts actual is T} + */ +export function equal(actual, expected) { + if (actual !== expected) throw new Error('Assertion failed'); +} diff --git a/frontend/node_modules/svelte/src/compiler/utils/ast.js b/frontend/node_modules/svelte/src/compiler/utils/ast.js new file mode 100644 index 0000000..75aadd9 --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/utils/ast.js @@ -0,0 +1,639 @@ +/** @import { AST, Scope } from '#compiler' */ +/** @import * as ESTree from 'estree' */ +import { walk } from 'zimmerframe'; +import * as b from '#compiler/builders'; + +/** + * Gets the left-most identifier of a member expression or identifier. + * @param {ESTree.MemberExpression | ESTree.Identifier} expression + * @returns {ESTree.Identifier | null} + */ +export function object(expression) { + while (expression.type === 'MemberExpression') { + expression = /** @type {ESTree.MemberExpression | ESTree.Identifier} */ (expression.object); + } + + if (expression.type !== 'Identifier') { + return null; + } + + return expression; +} + +/** + * Returns true if the attribute contains a single static text node. + * @param {AST.Attribute} attribute + * @returns {attribute is AST.Attribute & { value: [AST.Text] }} + */ +export function is_text_attribute(attribute) { + return ( + Array.isArray(attribute.value) && + attribute.value.length === 1 && + attribute.value[0].type === 'Text' + ); +} + +/** + * Returns true if the attribute contains a single expression node. + * In Svelte 5, this also includes a single expression node wrapped in an array. + * TODO change that in a future version + * @param {AST.Attribute} attribute + * @returns {attribute is AST.Attribute & { value: [AST.ExpressionTag] | AST.ExpressionTag }} + */ +export function is_expression_attribute(attribute) { + return ( + (attribute.value !== true && !Array.isArray(attribute.value)) || + (Array.isArray(attribute.value) && + attribute.value.length === 1 && + attribute.value[0].type === 'ExpressionTag') + ); +} + +/** + * Returns the single attribute expression node. + * In Svelte 5, this also includes a single expression node wrapped in an array. + * TODO change that in a future version + * @param { AST.Attribute & { value: [AST.ExpressionTag] | AST.ExpressionTag }} attribute + * @returns {ESTree.Expression} + */ +export function get_attribute_expression(attribute) { + return Array.isArray(attribute.value) + ? /** @type {AST.ExpressionTag} */ (attribute.value[0]).expression + : attribute.value.expression; +} + +/** + * Returns the expression chunks of an attribute value + * @param {AST.Attribute['value']} value + * @returns {Array} + */ +export function get_attribute_chunks(value) { + return Array.isArray(value) ? value : typeof value === 'boolean' ? [] : [value]; +} + +/** + * Returns true if the attribute starts with `on` and contains a single expression node. + * @param {AST.Attribute} attribute + * @returns {attribute is AST.Attribute & { value: [AST.ExpressionTag] | AST.ExpressionTag }} + */ +export function is_event_attribute(attribute) { + return is_expression_attribute(attribute) && attribute.name.startsWith('on'); +} + +/** + * Extracts all identifiers and member expressions from a pattern. + * @param {ESTree.Pattern} pattern + * @param {Array} [nodes] + * @returns {Array} + */ +export function unwrap_pattern(pattern, nodes = []) { + switch (pattern.type) { + case 'Identifier': + nodes.push(pattern); + break; + + case 'MemberExpression': + // member expressions can be part of an assignment pattern, but not a binding pattern + // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#binding_and_assignment + nodes.push(pattern); + break; + + case 'ObjectPattern': + for (const prop of pattern.properties) { + if (prop.type === 'RestElement') { + unwrap_pattern(prop.argument, nodes); + } else { + unwrap_pattern(prop.value, nodes); + } + } + + break; + + case 'ArrayPattern': + for (const element of pattern.elements) { + if (element) unwrap_pattern(element, nodes); + } + + break; + + case 'RestElement': + unwrap_pattern(pattern.argument, nodes); + break; + + case 'AssignmentPattern': + unwrap_pattern(pattern.left, nodes); + break; + } + + return nodes; +} + +/** + * Extracts all identifiers from a pattern. + * @param {ESTree.Pattern} pattern + * @returns {ESTree.Identifier[]} + */ +export function extract_identifiers(pattern) { + return unwrap_pattern(pattern, []).filter((node) => node.type === 'Identifier'); +} + +/** + * Extracts all identifiers and a stringified keypath from an expression. + * TODO replace this with `expression.dependencies` + * @param {ESTree.Expression} expr + * @returns {[keypath: string, ids: ESTree.Identifier[]]} + */ +export function extract_all_identifiers_from_expression(expr) { + /** @type {ESTree.Identifier[]} */ + let nodes = []; + /** @type {string[]} */ + let keypath = []; + + walk( + expr, + {}, + { + Identifier(node, { path }) { + const parent = path.at(-1); + if (parent?.type !== 'MemberExpression' || parent.property !== node || parent.computed) { + nodes.push(node); + } + + if (parent?.type === 'MemberExpression' && parent.computed && parent.property === node) { + keypath.push(`[${node.name}]`); + } else { + keypath.push(node.name); + } + }, + Literal(node, { path }) { + const value = typeof node.value === 'string' ? `"${node.value}"` : String(node.value); + const parent = path.at(-1); + if (parent?.type === 'MemberExpression' && parent.computed && parent.property === node) { + keypath.push(`[${value}]`); + } else { + keypath.push(value); + } + }, + ThisExpression(_, { next }) { + keypath.push('this'); + next(); + } + } + ); + + return [keypath.join('.'), nodes]; +} + +/** + * Extracts all leaf identifiers from a destructuring expression. + * @param {ESTree.Identifier | ESTree.ObjectExpression | ESTree.ArrayExpression} node + * @param {ESTree.Identifier[]} [nodes] + * @returns + */ +export function extract_identifiers_from_destructuring(node, nodes = []) { + // TODO This isn't complete, but it should be enough for our purposes + switch (node.type) { + case 'Identifier': + nodes.push(node); + break; + + case 'ObjectExpression': + for (const prop of node.properties) { + if (prop.type === 'Property') { + extract_identifiers_from_destructuring(/** @type {any} */ (prop.value), nodes); + } else { + extract_identifiers_from_destructuring(/** @type {any} */ (prop.argument), nodes); + } + } + + break; + + case 'ArrayExpression': + for (const element of node.elements) { + if (element) extract_identifiers_from_destructuring(/** @type {any} */ (element), nodes); + } + + break; + } + + return nodes; +} + +/** + * Represents the path of a destructured assignment from either a declaration + * or assignment expression. For example, given `const { foo: { bar: baz } } = quux`, + * the path of `baz` is `foo.bar` + * @typedef {Object} DestructuredAssignment + * @property {ESTree.Identifier | ESTree.MemberExpression} node The node the destructuring path end in. Can be a member expression only for assignment expressions + * @property {boolean} is_rest `true` if this is a `...rest` destructuring + * @property {boolean} has_default_value `true` if this has a fallback value like `const { foo = 'bar } = ..` + * @property {ESTree.Expression} expression The value of the current path + * This will be a call expression if a rest element or default is involved — e.g. `const { foo: { bar: baz = 42 }, ...rest } = quux` — since we can't represent `baz` or `rest` purely as a path + * Will be an await expression in case of an async default value (`const { foo = await bar } = ...`) + * @property {ESTree.Expression} update_expression Like `expression` but without default values. + */ + +/** + * Extracts all destructured assignments from a pattern. + * For each `id` in the returned `inserts`, make sure to adjust the `name`. + * @param {ESTree.Node} param + * @param {ESTree.Expression} initial + * @returns {{ inserts: Array<{ id: ESTree.Identifier, value: ESTree.Expression }>, paths: DestructuredAssignment[] }} + */ +export function extract_paths(param, initial) { + /** + * When dealing with array destructuring patterns (`let [a, b, c] = $derived(blah())`) + * we need an intermediate declaration that creates an array, since `blah()` could + * return a non-array-like iterator + * @type {Array<{ id: ESTree.Identifier, value: ESTree.Expression }>} + */ + const inserts = []; + + /** @type {DestructuredAssignment[]} */ + const paths = []; + + _extract_paths(paths, inserts, param, initial, initial, false); + + return { inserts, paths }; +} + +/** + * @param {DestructuredAssignment[]} paths + * @param {Array<{ id: ESTree.Identifier, value: ESTree.Expression }>} inserts + * @param {ESTree.Node} param + * @param {ESTree.Expression} expression + * @param {ESTree.Expression} update_expression + * @param {boolean} has_default_value + * @returns {DestructuredAssignment[]} + */ +function _extract_paths(paths, inserts, param, expression, update_expression, has_default_value) { + switch (param.type) { + case 'Identifier': + case 'MemberExpression': + paths.push({ + node: param, + is_rest: false, + has_default_value, + expression, + update_expression + }); + break; + + case 'ObjectPattern': + for (const prop of param.properties) { + if (prop.type === 'RestElement') { + /** @type {ESTree.Expression[]} */ + const props = []; + + for (const p of param.properties) { + if (p.type === 'Property' && p.key.type !== 'PrivateIdentifier') { + if (p.key.type === 'Identifier' && !p.computed) { + props.push(b.literal(p.key.name)); + } else if (p.key.type === 'Literal') { + props.push(b.literal(String(p.key.value))); + } else { + props.push(b.call('String', p.key)); + } + } + } + + const rest_expression = b.call('$.exclude_from_object', expression, b.array(props)); + + if (prop.argument.type === 'Identifier') { + paths.push({ + node: prop.argument, + is_rest: true, + has_default_value, + expression: rest_expression, + update_expression: rest_expression + }); + } else { + _extract_paths( + paths, + inserts, + prop.argument, + rest_expression, + rest_expression, + has_default_value + ); + } + } else { + const object_expression = b.member( + expression, + prop.key, + prop.computed || prop.key.type !== 'Identifier' + ); + + _extract_paths( + paths, + inserts, + prop.value, + object_expression, + object_expression, + has_default_value + ); + } + } + + break; + + case 'ArrayPattern': { + // we create an intermediate declaration to convert iterables to arrays if necessary. + // the consumer is responsible for setting the name of the identifier + const id = b.id('#'); + + const value = b.call( + '$.to_array', + expression, + param.elements.at(-1)?.type === 'RestElement' ? undefined : b.literal(param.elements.length) + ); + + inserts.push({ id, value }); + + for (let i = 0; i < param.elements.length; i += 1) { + const element = param.elements[i]; + if (element) { + if (element.type === 'RestElement') { + const rest_expression = b.call(b.member(id, 'slice'), b.literal(i)); + + if (element.argument.type === 'Identifier') { + paths.push({ + node: element.argument, + is_rest: true, + has_default_value, + expression: rest_expression, + update_expression: rest_expression + }); + } else { + _extract_paths( + paths, + inserts, + element.argument, + rest_expression, + rest_expression, + has_default_value + ); + } + } else { + const array_expression = b.member(id, b.literal(i), true); + + _extract_paths( + paths, + inserts, + element, + array_expression, + array_expression, + has_default_value + ); + } + } + } + + break; + } + + case 'AssignmentPattern': { + const fallback_expression = build_fallback(expression, param.right); + + if (param.left.type === 'Identifier') { + paths.push({ + node: param.left, + is_rest: false, + has_default_value: true, + expression: fallback_expression, + update_expression + }); + } else { + _extract_paths(paths, inserts, param.left, fallback_expression, update_expression, true); + } + + break; + } + } + + return paths; +} + +/** + * Like `path.at(x)`, but skips over `TSNonNullExpression` and `TSAsExpression` nodes and eases assertions a bit + * by removing the `| undefined` from the resulting type. + * + * @template {AST.SvelteNode} T + * @param {T[]} path + * @param {number} at + */ +export function get_parent(path, at) { + let node = path.at(at); + // @ts-expect-error + if (node.type === 'TSNonNullExpression' || node.type === 'TSAsExpression') { + return /** @type {T} */ (path.at(at < 0 ? at - 1 : at + 1)); + } + return /** @type {T} */ (node); +} + +/** + * Returns `true` if the expression is an identifier, a literal, a function expression, + * or a logical expression that only contains simple expressions. Used to determine whether + * something needs to be treated as though accessing it could have side-effects (i.e. + * reading signals prematurely) + * @param {ESTree.Expression} node + * @returns {boolean} + */ +export function is_simple_expression(node) { + if ( + node.type === 'Literal' || + node.type === 'Identifier' || + node.type === 'ArrowFunctionExpression' || + node.type === 'FunctionExpression' + ) { + return true; + } + + if (node.type === 'ConditionalExpression') { + return ( + is_simple_expression(node.test) && + is_simple_expression(node.consequent) && + is_simple_expression(node.alternate) + ); + } + + if (node.type === 'BinaryExpression' || node.type === 'LogicalExpression') { + return ( + node.left.type !== 'PrivateIdentifier' && + is_simple_expression(node.left) && + is_simple_expression(node.right) + ); + } + + return false; +} + +/** + * @template {ESTree.SimpleCallExpression | ESTree.MemberExpression} T + * @param {ESTree.ChainExpression & { expression : T } | T} node + * @returns {T} + */ +export function unwrap_optional(node) { + return node.type === 'ChainExpression' ? node.expression : node; +} + +/** + * @param {ESTree.Expression | ESTree.Pattern} expression + * @returns {boolean} + */ +export function is_expression_async(expression) { + switch (expression.type) { + case 'AwaitExpression': { + return true; + } + case 'ArrayPattern': { + return expression.elements.some((element) => element && is_expression_async(element)); + } + case 'ArrayExpression': { + return expression.elements.some((element) => { + if (!element) { + return false; + } else if (element.type === 'SpreadElement') { + return is_expression_async(element.argument); + } else { + return is_expression_async(element); + } + }); + } + case 'AssignmentPattern': + case 'AssignmentExpression': + case 'BinaryExpression': + case 'LogicalExpression': { + return ( + (expression.left.type !== 'PrivateIdentifier' && is_expression_async(expression.left)) || + is_expression_async(expression.right) + ); + } + case 'CallExpression': + case 'NewExpression': { + return ( + (expression.callee.type !== 'Super' && is_expression_async(expression.callee)) || + expression.arguments.some((element) => { + if (element.type === 'SpreadElement') { + return is_expression_async(element.argument); + } else { + return is_expression_async(element); + } + }) + ); + } + case 'ChainExpression': { + return is_expression_async(expression.expression); + } + case 'ConditionalExpression': { + return ( + is_expression_async(expression.test) || + is_expression_async(expression.alternate) || + is_expression_async(expression.consequent) + ); + } + case 'ImportExpression': { + return is_expression_async(expression.source); + } + case 'MemberExpression': { + return ( + (expression.object.type !== 'Super' && is_expression_async(expression.object)) || + (expression.property.type !== 'PrivateIdentifier' && + is_expression_async(expression.property)) + ); + } + case 'ObjectPattern': + case 'ObjectExpression': { + return expression.properties.some((property) => { + if (property.type === 'SpreadElement') { + return is_expression_async(property.argument); + } else if (property.type === 'Property') { + return ( + (property.key.type !== 'PrivateIdentifier' && is_expression_async(property.key)) || + is_expression_async(property.value) + ); + } + }); + } + case 'RestElement': { + return is_expression_async(expression.argument); + } + case 'SequenceExpression': + case 'TemplateLiteral': { + return expression.expressions.some((subexpression) => is_expression_async(subexpression)); + } + case 'TaggedTemplateExpression': { + return is_expression_async(expression.tag) || is_expression_async(expression.quasi); + } + case 'UnaryExpression': + case 'UpdateExpression': { + return is_expression_async(expression.argument); + } + case 'YieldExpression': { + return expression.argument ? is_expression_async(expression.argument) : false; + } + default: + return false; + } +} + +/** + * + * @param {ESTree.Expression} expression + * @param {ESTree.Expression} fallback + */ +export function build_fallback(expression, fallback) { + if (is_simple_expression(fallback)) { + return b.call('$.fallback', expression, fallback); + } + + if (fallback.type === 'AwaitExpression' && is_simple_expression(fallback.argument)) { + return b.await(b.call('$.fallback', expression, fallback.argument)); + } + + return is_expression_async(fallback) + ? b.await(b.call('$.fallback', expression, b.thunk(fallback, true), b.true)) + : b.call('$.fallback', expression, b.thunk(fallback), b.true); +} + +/** + * @param {ESTree.AssignmentOperator} operator + * @param {ESTree.Identifier | ESTree.MemberExpression} left + * @param {ESTree.Expression} right + */ +export function build_assignment_value(operator, left, right) { + return operator === '=' + ? right + : // turn something like x += 1 into x = x + 1 + ['||=', '&&=', '??='].includes(operator) + ? b.logical(/** @type {ESTree.LogicalOperator} */ (operator.slice(0, -1)), left, right) + : b.binary(/** @type {ESTree.BinaryOperator} */ (operator.slice(0, -1)), left, right); +} + +/** + * @param {ESTree.Node} node + */ +export function has_await_expression(node) { + let has_await = false; + + walk(node, null, { + AwaitExpression(_node, context) { + has_await = true; + context.stop(); + }, + // don't traverse into these + FunctionDeclaration() {}, + FunctionExpression() {}, + ArrowFunctionExpression() {} + }); + + return has_await; +} + +/** + * Turns `await ...` to `(await $.save(...))()` + * @param {ESTree.Expression} expression + */ +export function save(expression) { + return b.call(b.await(b.call('$.save', expression))); +} diff --git a/frontend/node_modules/svelte/src/compiler/utils/builders.js b/frontend/node_modules/svelte/src/compiler/utils/builders.js new file mode 100644 index 0000000..7508caf --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/utils/builders.js @@ -0,0 +1,698 @@ +/** @import * as ESTree from 'estree' */ +import { walk } from 'zimmerframe'; +import { regex_is_valid_identifier } from '../phases/patterns.js'; +import { sanitize_template_string } from './sanitize_template_string.js'; +import { has_await_expression } from './ast.js'; + +/** + * @param {Array} elements + * @returns {ESTree.ArrayExpression} + */ +export function array(elements = []) { + return { type: 'ArrayExpression', elements }; +} + +/** + * @param {Array} elements + * @returns {ESTree.ArrayPattern} + */ +export function array_pattern(elements) { + return { type: 'ArrayPattern', elements }; +} + +/** + * @param {ESTree.Pattern} left + * @param {ESTree.Expression} right + * @returns {ESTree.AssignmentPattern} + */ +export function assignment_pattern(left, right) { + return { type: 'AssignmentPattern', left, right }; +} + +/** + * @param {Array} params + * @param {ESTree.BlockStatement | ESTree.Expression} body + * @param {boolean} async + * @returns {ESTree.ArrowFunctionExpression} + */ +export function arrow(params, body, async = false) { + // optimize `async () => await x()`, but not `async () => await x(await y)` + if (async && body.type === 'AwaitExpression') { + if (!has_await_expression(body.argument)) { + return arrow(params, body.argument); + } + } + + return { + type: 'ArrowFunctionExpression', + params, + body, + expression: body.type !== 'BlockStatement', + generator: false, + async + }; +} + +/** + * @param {ESTree.AssignmentOperator} operator + * @param {ESTree.Pattern} left + * @param {ESTree.Expression} right + * @returns {ESTree.AssignmentExpression} + */ +export function assignment(operator, left, right) { + return { type: 'AssignmentExpression', operator, left, right }; +} + +/** + * @param {ESTree.Expression} argument + * @returns {ESTree.AwaitExpression} + */ +function await_builder(argument) { + return { type: 'AwaitExpression', argument }; +} + +/** + * @param {ESTree.BinaryOperator} operator + * @param {ESTree.Expression} left + * @param {ESTree.Expression} right + * @returns {ESTree.BinaryExpression} + */ +export function binary(operator, left, right) { + return { type: 'BinaryExpression', operator, left, right }; +} + +/** + * @param {ESTree.Statement[]} body + * @returns {ESTree.BlockStatement} + */ +export function block(body) { + return { type: 'BlockStatement', body }; +} + +/** + * @param {ESTree.Identifier | null} id + * @param {ESTree.ClassBody} body + * @param {ESTree.Expression | null} [superClass] + * @param {ESTree.Decorator[]} [decorators] + * @returns {ESTree.ClassExpression} + */ +export function class_expression(id, body, superClass, decorators = []) { + return { type: 'ClassExpression', body, superClass, decorators }; +} + +/** + * @param {string} name + * @param {ESTree.Statement} body + * @returns {ESTree.LabeledStatement} + */ +export function labeled(name, body) { + return { type: 'LabeledStatement', label: id(name), body }; +} + +/** + * @param {string | ESTree.Expression} callee + * @param {...(ESTree.Expression | ESTree.SpreadElement | false | undefined | null)} args + * @returns {ESTree.CallExpression} + */ +export function call(callee, ...args) { + if (typeof callee === 'string') callee = id(callee); + args = args.slice(); + + // replacing missing arguments with `void(0)`, unless they're at the end in which case remove them + let i = args.length; + let popping = true; + while (i--) { + if (!args[i]) { + if (popping) { + args.pop(); + } else { + args[i] = void0; + } + } else { + popping = false; + } + } + + return { + type: 'CallExpression', + callee, + arguments: /** @type {Array} */ (args), + optional: false + }; +} + +/** + * @param {string | ESTree.Expression} callee + * @param {...ESTree.Expression} args + * @returns {ESTree.ChainExpression} + */ +export function maybe_call(callee, ...args) { + const expression = /** @type {ESTree.SimpleCallExpression} */ (call(callee, ...args)); + expression.optional = true; + + return { + type: 'ChainExpression', + expression + }; +} + +/** + * @param {ESTree.UnaryOperator} operator + * @param {ESTree.Expression} argument + * @returns {ESTree.UnaryExpression} + */ +export function unary(operator, argument) { + return { type: 'UnaryExpression', argument, operator, prefix: true }; +} + +export const void0 = unary('void', literal(0)); + +/** + * @param {ESTree.Expression} test + * @param {ESTree.Expression} consequent + * @param {ESTree.Expression} alternate + * @returns {ESTree.ConditionalExpression} + */ +export function conditional(test, consequent, alternate) { + return { type: 'ConditionalExpression', test, consequent, alternate }; +} + +/** + * @param {ESTree.LogicalOperator} operator + * @param {ESTree.Expression} left + * @param {ESTree.Expression} right + * @returns {ESTree.LogicalExpression} + */ +export function logical(operator, left, right) { + return { type: 'LogicalExpression', operator, left, right }; +} + +/** + * @param {ESTree.VariableDeclaration['kind']} kind + * @param {ESTree.VariableDeclarator[]} declarations + * @returns {ESTree.VariableDeclaration} + */ +export function declaration(kind, declarations) { + return { + type: 'VariableDeclaration', + kind, + declarations + }; +} + +/** + * @param {ESTree.Pattern | string} pattern + * @param {ESTree.Expression | null} [init] + * @returns {ESTree.VariableDeclarator} + */ +export function declarator(pattern, init) { + if (typeof pattern === 'string') pattern = id(pattern); + return { type: 'VariableDeclarator', id: pattern, init }; +} + +/** @type {ESTree.EmptyStatement} */ +export const empty = { + type: 'EmptyStatement' +}; + +/** + * @param {ESTree.Expression | ESTree.MaybeNamedClassDeclaration | ESTree.MaybeNamedFunctionDeclaration} declaration + * @returns {ESTree.ExportDefaultDeclaration} + */ +export function export_default(declaration) { + return { type: 'ExportDefaultDeclaration', declaration }; +} + +/** + * @param {ESTree.VariableDeclaration | ESTree.Pattern} left + * @param {ESTree.Expression} right + * @param {ESTree.Statement} body + * @param {boolean} [_await] + * @returns {ESTree.ForOfStatement} + */ +export function for_of(left, right, body, _await = false) { + return { + type: 'ForOfStatement', + left, + right, + body, + await: _await + }; +} + +/** + * @param {ESTree.Identifier} id + * @param {ESTree.Pattern[]} params + * @param {ESTree.BlockStatement} body + * @param {boolean} async + * @returns {ESTree.FunctionDeclaration} + */ +export function function_declaration(id, params, body, async = false) { + return { + type: 'FunctionDeclaration', + id, + params, + body, + generator: false, + async + }; +} + +/** + * @param {string} name + * @param {ESTree.Statement[]} body + * @returns {ESTree.Property & { value: ESTree.FunctionExpression}}} + */ +export function get(name, body) { + return prop('get', key(name), function_builder(null, [], block(body))); +} + +/** + * @param {string} name + * @param {ESTree.SourceLocation | null} [loc] + * @returns {ESTree.Identifier} + */ +export function id(name, loc) { + const node = /** @type {ESTree.Identifier} */ ({ type: 'Identifier', name }); + if (loc) node.loc = loc; + + return node; +} + +/** + * @param {string} name + * @returns {ESTree.PrivateIdentifier} + */ +export function private_id(name) { + return { type: 'PrivateIdentifier', name }; +} + +/** + * @param {string} local + * @returns {ESTree.ImportNamespaceSpecifier} + */ +function import_namespace(local) { + return { + type: 'ImportNamespaceSpecifier', + local: id(local) + }; +} + +/** + * @param {string} name + * @param {ESTree.Expression} value + * @returns {ESTree.Property} + */ +export function init(name, value) { + return prop('init', key(name), value); +} + +/** + * @param {string | boolean | null | number | RegExp} value + * @returns {ESTree.Literal} + */ +export function literal(value) { + // @ts-expect-error we don't want to muck around with bigint here + return { type: 'Literal', value }; +} + +/** + * @param {ESTree.Expression | ESTree.Super} object + * @param {string | ESTree.Expression | ESTree.PrivateIdentifier} property + * @param {boolean} computed + * @param {boolean} optional + * @returns {ESTree.MemberExpression} + */ +export function member(object, property, computed = false, optional = false) { + if (typeof property === 'string') { + property = id(property); + } + + return { type: 'MemberExpression', object, property, computed, optional }; +} + +/** + * @param {string} path + * @returns {ESTree.Identifier | ESTree.MemberExpression} + */ +export function member_id(path) { + const parts = path.split('.'); + + /** @type {ESTree.Identifier | ESTree.MemberExpression} */ + let expression = id(parts[0]); + + for (let i = 1; i < parts.length; i += 1) { + expression = member(expression, id(parts[i])); + } + return expression; +} + +/** + * @param {Array} properties + * @returns {ESTree.ObjectExpression} + */ +export function object(properties) { + return { type: 'ObjectExpression', properties }; +} + +/** + * @param {Array} properties + * @returns {ESTree.ObjectPattern} + */ +export function object_pattern(properties) { + // @ts-expect-error the types appear to be wrong + return { type: 'ObjectPattern', properties }; +} + +/** + * @template {ESTree.Expression} Value + * @param {'init' | 'get' | 'set'} kind + * @param {ESTree.Expression} key + * @param {Value} value + * @param {boolean} computed + * @returns {ESTree.Property & { value: Value }} + */ +export function prop(kind, key, value, computed = false) { + return { type: 'Property', kind, key, value, method: false, shorthand: false, computed }; +} + +/** + * @param {ESTree.Expression | ESTree.PrivateIdentifier} key + * @param {ESTree.Expression | null | undefined} value + * @param {boolean} computed + * @param {boolean} is_static + * @returns {ESTree.PropertyDefinition} + */ +export function prop_def(key, value, computed = false, is_static = false) { + return { + type: 'PropertyDefinition', + decorators: [], + key, + value, + computed, + static: is_static + }; +} + +/** + * @param {string} cooked + * @param {boolean} tail + * @returns {ESTree.TemplateElement} + */ +export function quasi(cooked, tail = false) { + const raw = sanitize_template_string(cooked); + return { type: 'TemplateElement', value: { raw, cooked }, tail }; +} + +/** + * @param {ESTree.Pattern} argument + * @returns {ESTree.RestElement} + */ +export function rest(argument) { + return { type: 'RestElement', argument }; +} + +/** + * @param {ESTree.Expression[]} expressions + * @returns {ESTree.SequenceExpression} + */ +export function sequence(expressions) { + return { type: 'SequenceExpression', expressions }; +} + +/** + * @param {string} name + * @param {ESTree.Statement[]} body + * @returns {ESTree.Property & { value: ESTree.FunctionExpression}} + */ +export function set(name, body) { + return prop('set', key(name), function_builder(null, [id('$$value')], block(body))); +} + +/** + * @param {ESTree.Expression} argument + * @returns {ESTree.SpreadElement} + */ +export function spread(argument) { + return { type: 'SpreadElement', argument }; +} + +/** + * @param {ESTree.Expression} expression + * @returns {ESTree.ExpressionStatement} + */ +export function stmt(expression) { + return { type: 'ExpressionStatement', expression }; +} + +/** + * @param {ESTree.TemplateElement[]} elements + * @param {ESTree.Expression[]} expressions + * @returns {ESTree.TemplateLiteral} + */ +export function template(elements, expressions) { + return { type: 'TemplateLiteral', quasis: elements, expressions }; +} + +/** + * @param {ESTree.Expression | ESTree.BlockStatement} expression + * @param {boolean} [async] + * @returns {ESTree.Expression} + */ +export function thunk(expression, async = false) { + return unthunk(arrow([], expression, async)); +} + +/** + * Replace "(arg) => func(arg)" to "func" + * @param {ESTree.ArrowFunctionExpression} expression + * @returns {ESTree.Expression} + */ +export function unthunk(expression) { + if ( + expression.async === false && + expression.body.type === 'CallExpression' && + expression.body.callee.type === 'Identifier' && + expression.params.length === expression.body.arguments.length && + expression.params.every((param, index) => { + const arg = /** @type {ESTree.SimpleCallExpression} */ (expression.body).arguments[index]; + return param.type === 'Identifier' && arg.type === 'Identifier' && param.name === arg.name; + }) + ) { + return expression.body.callee; + } + return expression; +} + +/** + * + * @param {string | ESTree.Expression} expression + * @param {...ESTree.Expression} args + * @returns {ESTree.NewExpression} + */ +function new_builder(expression, ...args) { + if (typeof expression === 'string') expression = id(expression); + + return { + callee: expression, + arguments: args, + type: 'NewExpression' + }; +} + +/** + * @param {ESTree.UpdateOperator} operator + * @param {ESTree.Expression} argument + * @param {boolean} prefix + * @returns {ESTree.UpdateExpression} + */ +export function update(operator, argument, prefix = false) { + return { type: 'UpdateExpression', operator, argument, prefix }; +} + +/** + * @param {ESTree.Expression} test + * @param {ESTree.Statement} body + * @returns {ESTree.DoWhileStatement} + */ +export function do_while(test, body) { + return { type: 'DoWhileStatement', test, body }; +} + +const true_instance = literal(true); +const false_instance = literal(false); +const null_instance = literal(null); + +/** @type {ESTree.DebuggerStatement} */ +const debugger_builder = { + type: 'DebuggerStatement' +}; + +/** @type {ESTree.ThisExpression} */ +const this_instance = { + type: 'ThisExpression' +}; + +/** + * @param {string | ESTree.Pattern} pattern + * @param {ESTree.Expression | null} [init] + * @returns {ESTree.VariableDeclaration} + */ +function let_builder(pattern, init) { + return declaration('let', [declarator(pattern, init)]); +} + +/** + * @param {string | ESTree.Pattern} pattern + * @param {ESTree.Expression | null} init + * @returns {ESTree.VariableDeclaration} + */ +function const_builder(pattern, init) { + return declaration('const', [declarator(pattern, init)]); +} + +/** + * @param {string | ESTree.Pattern} pattern + * @param {ESTree.Expression | null} [init] + * @returns {ESTree.VariableDeclaration} + */ +function var_builder(pattern, init) { + return declaration('var', [declarator(pattern, init)]); +} + +/** + * + * @param {ESTree.VariableDeclaration | ESTree.Expression | null} init + * @param {ESTree.Expression} test + * @param {ESTree.Expression} update + * @param {ESTree.Statement} body + * @returns {ESTree.ForStatement} + */ +function for_builder(init, test, update, body) { + return { type: 'ForStatement', init, test, update, body }; +} + +/** + * + * @param {'constructor' | 'method' | 'get' | 'set'} kind + * @param {ESTree.Expression | ESTree.PrivateIdentifier} key + * @param {ESTree.Pattern[]} params + * @param {ESTree.Statement[]} body + * @param {boolean} computed + * @param {boolean} is_static + * @returns {ESTree.MethodDefinition} + */ +export function method(kind, key, params, body, computed = false, is_static = false) { + return { + type: 'MethodDefinition', + decorators: [], + key, + kind, + value: function_builder(null, params, block(body)), + computed, + static: is_static + }; +} + +/** + * + * @param {ESTree.Identifier | null} id + * @param {ESTree.Pattern[]} params + * @param {ESTree.BlockStatement} body + * @returns {ESTree.FunctionExpression} + */ +function function_builder(id, params, body, async = false) { + return { + type: 'FunctionExpression', + id, + params, + body, + generator: false, + async + }; +} + +/** + * @param {ESTree.Expression} test + * @param {ESTree.Statement} consequent + * @param {ESTree.Statement} [alternate] + * @returns {ESTree.IfStatement} + */ +function if_builder(test, consequent, alternate) { + return { type: 'IfStatement', test, consequent, alternate }; +} + +/** + * @param {string} as + * @param {string} source + * @returns {ESTree.ImportDeclaration} + */ +export function import_all(as, source) { + return { + type: 'ImportDeclaration', + attributes: [], + source: literal(source), + specifiers: [import_namespace(as)] + }; +} + +/** + * @param {Array<[string, string]>} parts + * @param {string} source + * @returns {ESTree.ImportDeclaration} + */ +export function imports(parts, source) { + return { + type: 'ImportDeclaration', + attributes: [], + source: literal(source), + specifiers: parts.map((p) => ({ + type: 'ImportSpecifier', + imported: id(p[0]), + local: id(p[1]) + })) + }; +} + +/** + * @param {ESTree.Expression | null} argument + * @returns {ESTree.ReturnStatement} + */ +function return_builder(argument = null) { + return { type: 'ReturnStatement', argument }; +} + +/** + * @param {string} str + * @returns {ESTree.ThrowStatement} + */ +export function throw_error(str) { + return { + type: 'ThrowStatement', + argument: new_builder('Error', literal(str)) + }; +} + +export { + await_builder as await, + let_builder as let, + const_builder as const, + var_builder as var, + true_instance as true, + false_instance as false, + for_builder as for, + function_builder as function, + return_builder as return, + if_builder as if, + this_instance as this, + null_instance as null, + debugger_builder as debugger +}; + +/** + * @param {string} name + * @returns {ESTree.Expression} + */ +export function key(name) { + return regex_is_valid_identifier.test(name) ? id(name) : literal(name); +} diff --git a/frontend/node_modules/svelte/src/compiler/utils/compile_diagnostic.js b/frontend/node_modules/svelte/src/compiler/utils/compile_diagnostic.js new file mode 100644 index 0000000..95d028e --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/utils/compile_diagnostic.js @@ -0,0 +1,106 @@ +/** @import { Location } from 'locate-character' */ +import * as state from '../state.js'; + +const regex_tabs = /^\t+/; + +/** + * @param {string} str + */ +function tabs_to_spaces(str) { + return str.replace(regex_tabs, (match) => match.split('\t').join(' ')); +} + +/** + * @param {number} line + * @param {number} column + */ +function get_code_frame(line, column) { + const lines = state.source_lines; + const frame_start = Math.max(0, line - 2); + const frame_end = Math.min(line + 3, lines.length); + const digits = String(frame_end + 1).length; + return lines + .slice(frame_start, frame_end) + .map((str, i) => { + const is_error_line = frame_start + i === line; + const line_num = String(i + frame_start + 1).padStart(digits, ' '); + if (is_error_line) { + const indicator = + ' '.repeat(digits + 2 + tabs_to_spaces(str.slice(0, column)).length) + '^'; + return `${line_num}: ${tabs_to_spaces(str)}\n${indicator}`; + } + return `${line_num}: ${tabs_to_spaces(str)}`; + }) + .join('\n'); +} + +/** + * @typedef {{ + * code: string; + * message: string; + * stack?: string; + * filename?: string; + * start?: Location; + * end?: Location; + * position?: [number, number]; + * frame?: string; + * }} ICompileDiagnostic + */ + +/** @implements {ICompileDiagnostic} */ +export class CompileDiagnostic { + name = 'CompileDiagnostic'; + + /** + * @param {string} code + * @param {string} message + * @param {[number, number] | undefined} position + */ + constructor(code, message, position) { + this.code = code; + this.message = message; + + if (state.filename !== state.UNKNOWN_FILENAME) { + this.filename = state.filename; + } + + if (position) { + this.position = position; + this.start = state.locator(position[0]); + this.end = state.locator(position[1]); + if (this.start && this.end) { + this.frame = get_code_frame(this.start.line - 1, this.end.column); + } + } + } + + toString() { + let out = `${this.code}: ${this.message}`; + + if (this.filename) { + out += `\n${this.filename}`; + + if (this.start) { + out += `:${this.start.line}:${this.start.column}`; + } + } + + if (this.frame) { + out += `\n${this.frame}`; + } + + return out; + } + + toJSON() { + return { + code: this.code, + message: this.message, + filename: this.filename, + start: this.start, + end: this.end, + position: this.position, + frame: this.frame + }; + } +} diff --git a/frontend/node_modules/svelte/src/compiler/utils/extract_svelte_ignore.js b/frontend/node_modules/svelte/src/compiler/utils/extract_svelte_ignore.js new file mode 100644 index 0000000..2f0d387 --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/utils/extract_svelte_ignore.js @@ -0,0 +1,104 @@ +import { IGNORABLE_RUNTIME_WARNINGS } from '../../constants.js'; +import fuzzymatch from '../phases/1-parse/utils/fuzzymatch.js'; +import * as w from '../warnings.js'; + +const regex_svelte_ignore = /^\s*svelte-ignore\s/; + +/** @type {Record} Map of legacy code -> new code */ +const replacements = { + 'non-top-level-reactive-declaration': 'reactive_declaration_invalid_placement', + 'module-script-reactive-declaration': 'reactive_declaration_module_script', + 'empty-block': 'block_empty', + 'avoid-is': 'attribute_avoid_is', + 'invalid-html-attribute': 'attribute_invalid_property_name', + 'a11y-structure': 'a11y_figcaption_parent', + 'illegal-attribute-character': 'attribute_illegal_colon', + 'invalid-rest-eachblock-binding': 'bind_invalid_each_rest', + 'unused-export-let': 'export_let_unused' +}; + +const codes = w.codes.concat(IGNORABLE_RUNTIME_WARNINGS); + +/** + * @param {number} offset + * @param {string} text + * @param {boolean} runes + * @returns {string[]} + */ +export function extract_svelte_ignore(offset, text, runes) { + const match = regex_svelte_ignore.exec(text); + if (!match) return []; + + let length = match[0].length; + offset += length; + + /** @type {string[]} */ + const ignores = []; + + if (runes) { + // Warnings have to be separated by commas, everything after is interpreted as prose + for (const match of text.slice(length).matchAll(/([\w$-]+)(,)?/gm)) { + const code = match[1]; + + if (codes.includes(code)) { + ignores.push(code); + } else { + const replacement = replacements[code] ?? code.replace(/-/g, '_'); + + // The type cast is for some reason necessary to pass the type check in CI + const start = offset + /** @type {number} */ (match.index); + const end = start + code.length; + + if (codes.includes(replacement)) { + w.legacy_code({ start, end }, code, replacement); + } else { + const suggestion = fuzzymatch(code, codes); + w.unknown_code({ start, end }, code, suggestion); + } + } + + if (!match[2]) { + break; + } + } + } else { + // Non-runes mode: lax parsing, backwards compat with old codes + for (const match of text.slice(length).matchAll(/[\w$-]+/gm)) { + const code = match[0]; + + ignores.push(code); + + if (!codes.includes(code)) { + const replacement = replacements[code] ?? code.replace(/-/g, '_'); + + if (codes.includes(replacement)) { + ignores.push(replacement); + } + } + } + } + + return ignores; +} + +/** + * Replaces legacy svelte-ignore codes with new codes. + * @param {string} text + * @returns {string} + */ +export function migrate_svelte_ignore(text) { + const match = regex_svelte_ignore.exec(text); + if (!match) return text; + + const length = match[0].length; + return ( + text.substring(0, length) + + text.substring(length).replace(/\w+-\w+(-\w+)*/g, (code, _, idx) => { + let replacement = replacements[code] ?? code.replace(/-/g, '_'); + if (/\w+-\w+/.test(text.substring(length + idx + code.length))) { + replacement += ','; + } + return replacement; + }) + ); +} diff --git a/frontend/node_modules/svelte/src/compiler/utils/mapped_code.js b/frontend/node_modules/svelte/src/compiler/utils/mapped_code.js new file mode 100644 index 0000000..7686ba5 --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/utils/mapped_code.js @@ -0,0 +1,454 @@ +/** @import { ValidatedCompileOptions } from '#compiler' */ +/** @import { Processed } from '../preprocess/public.js' */ +/** @import { SourceMap } from 'magic-string' */ +/** @import { Source } from '../preprocess/private.js' */ +/** @import { DecodedSourceMap, SourceMapSegment, RawSourceMap } from '@jridgewell/remapping' */ +import remapping from '@jridgewell/remapping'; +import { push_array } from './push_array.js'; + +/** + * @param {string} s + */ +function last_line_length(s) { + return s.length - s.lastIndexOf('\n') - 1; +} +// mutate map in-place + +/** + * @param {DecodedSourceMap} map + * @param {{ line: number; column: number; }} offset + * @param {number} source_index + */ +export function sourcemap_add_offset(map, offset, source_index) { + if (map.mappings.length == 0) return; + for (let line = 0; line < map.mappings.length; line++) { + const segment_list = map.mappings[line]; + for (let segment = 0; segment < segment_list.length; segment++) { + const seg = segment_list[segment]; + // shift only segments that belong to component source file + if (seg[1] === source_index) { + // also ensures that seg.length >= 4 + // shift column if it points at the first line + if (seg[2] === 0) { + /** @type {any} */ (seg[3]) += offset.column; + } + // shift line + /** @type {any} */ (seg[2]) += offset.line; + } + } + } +} + +/** + * @template T + * @param {T[]} this_table + * @param {T[]} other_table + * @returns {[T[], number[], boolean, boolean]} + */ +function merge_tables(this_table, other_table) { + const new_table = this_table.slice(); + const idx_map = []; + other_table = other_table || []; + let val_changed = false; + for (const [other_idx, other_val] of other_table.entries()) { + const this_idx = this_table.indexOf(other_val); + if (this_idx >= 0) { + idx_map[other_idx] = this_idx; + } else { + const new_idx = new_table.length; + new_table[new_idx] = other_val; + idx_map[other_idx] = new_idx; + val_changed = true; + } + } + let idx_changed = val_changed; + if (val_changed) { + if (idx_map.find((val, idx) => val != idx) === undefined) { + // idx_map is identity map [0, 1, 2, 3, 4, ....] + idx_changed = false; + } + } + return [new_table, idx_map, val_changed, idx_changed]; +} +const regex_line_token = /([^\w\s]|\s+)/g; +/** */ +export class MappedCode { + /** + * @type {string} + */ + string = /** @type {any} */ (undefined); + + /** + * @type {DecodedSourceMap} + */ + map = /** @type {any} */ (undefined); + + /** + * @param {string} string + * @param {DecodedSourceMap | null} map + */ + constructor(string = '', map = null) { + this.string = string; + if (map) { + this.map = map; + } else { + this.map = { + version: 3, + mappings: [], + sources: [], + names: [] + }; + } + } + /** + * concat in-place (mutable), return this (chainable) + * will also mutate the `other` object + * @param {MappedCode} other + * @returns {MappedCode} + */ + concat(other) { + // noop: if one is empty, return the other + if (other.string == '') return this; + if (this.string == '') { + this.string = other.string; + this.map = other.map; + return this; + } + // compute last line length before mutating + const column_offset = last_line_length(this.string); + this.string += other.string; + const m1 = this.map; + const m2 = other.map; + if (m2.mappings.length == 0) return this; + // combine sources and names + const [sources, new_source_idx, sources_changed, sources_idx_changed] = merge_tables( + m1.sources, + m2.sources + ); + const [names, new_name_idx, names_changed, names_idx_changed] = merge_tables( + m1.names, + m2.names + ); + if (sources_changed) m1.sources = sources; + if (names_changed) m1.names = names; + // unswitched loops are faster + if (sources_idx_changed && names_idx_changed) { + for (let line = 0; line < m2.mappings.length; line++) { + const segment_list = m2.mappings[line]; + for (let segment = 0; segment < segment_list.length; segment++) { + const seg = segment_list[segment]; + // @ts-ignore + if (seg[1] >= 0) seg[1] = new_source_idx[seg[1]]; + // @ts-ignore + if (seg[4] >= 0) seg[4] = new_name_idx[seg[4]]; + } + } + } else if (sources_idx_changed) { + for (let line = 0; line < m2.mappings.length; line++) { + const segment_list = m2.mappings[line]; + for (let segment = 0; segment < segment_list.length; segment++) { + const seg = segment_list[segment]; + // @ts-ignore + if (seg[1] >= 0) seg[1] = new_source_idx[seg[1]]; + } + } + } else if (names_idx_changed) { + for (let line = 0; line < m2.mappings.length; line++) { + const segment_list = m2.mappings[line]; + for (let segment = 0; segment < segment_list.length; segment++) { + const seg = segment_list[segment]; + // @ts-ignore + if (seg[4] >= 0) seg[4] = new_name_idx[seg[4]]; + } + } + } + // combine the mappings + // combine + // 1. last line of first map + // 2. first line of second map + // columns of 2 must be shifted + if (m2.mappings.length > 0 && column_offset > 0) { + const first_line = m2.mappings[0]; + for (let i = 0; i < first_line.length; i++) { + first_line[i][0] += column_offset; + } + } + // combine last line + first line + push_array( + m1.mappings[m1.mappings.length - 1], + /** @type {SourceMapSegment[]} */ (m2.mappings.shift()) + ); + // append other lines + push_array(m1.mappings, m2.mappings); + return this; + } + + /** + * @static + * @param {string} string + * @param {DecodedSourceMap} [map] + * @returns {MappedCode} + */ + static from_processed(string, map) { + const line_count = string.split('\n').length; + if (map) { + // ensure that count of source map mappings lines + // is equal to count of generated code lines + // (some tools may produce less) + const missing_lines = line_count - map.mappings.length; + for (let i = 0; i < missing_lines; i++) { + map.mappings.push([]); + } + return new MappedCode(string, map); + } + if (string == '') return new MappedCode(); + map = { version: 3, names: [], sources: [], mappings: [] }; + // add empty SourceMapSegment[] for every line + for (let i = 0; i < line_count; i++) map.mappings.push([]); + return new MappedCode(string, map); + } + + /** + * @static + * @param {Source} opts + * @returns {MappedCode} + */ + static from_source({ source, file_basename, get_location }) { + /** + * @type {{ line: number; column: number; }} + */ + let offset = get_location(0); + if (!offset) offset = { line: 0, column: 0 }; + + /** + * @type {DecodedSourceMap} + */ + const map = { version: 3, names: [], sources: [file_basename], mappings: [] }; + if (source == '') return new MappedCode(source, map); + // we create a high resolution identity map here, + // we know that it will eventually be merged with svelte's map, + // at which stage the resolution will decrease. + const line_list = source.split('\n'); + for (let line = 0; line < line_list.length; line++) { + map.mappings.push([]); + const token_list = line_list[line].split(regex_line_token); + for (let token = 0, column = 0; token < token_list.length; token++) { + if (token_list[token] == '') continue; + map.mappings[line].push([column, 0, offset.line + line, column]); + column += token_list[token].length; + } + } + // shift columns in first line + const segment_list = map.mappings[0]; + for (let segment = 0; segment < segment_list.length; segment++) { + // @ts-ignore + segment_list[segment][3] += offset.column; + } + return new MappedCode(source, map); + } +} + +// browser vs node.js +const b64enc = + typeof window !== 'undefined' && typeof btoa === 'function' + ? /** @param {string} str */ (str) => btoa(unescape(encodeURIComponent(str))) + : /** @param {string} str */ (str) => Buffer.from(str).toString('base64'); +const b64dec = + typeof window !== 'undefined' && typeof atob === 'function' + ? atob + : /** @param {any} a */ (a) => Buffer.from(a, 'base64').toString(); + +/** + * @param {string} filename Basename of the input file + * @param {Array} sourcemap_list + */ +export function combine_sourcemaps(filename, sourcemap_list) { + if (sourcemap_list.length == 0) return null; + let map_idx = 1; + const map = + sourcemap_list.slice(0, -1).find((m) => m.sources.length !== 1) === undefined + ? remapping( + // use array interface + // only the oldest sourcemap can have multiple sources + sourcemap_list, + () => null, + true // skip optional field `sourcesContent` + ) + : remapping( + // use loader interface + sourcemap_list[0], // last map + (sourcefile) => { + // TODO the equality check assumes that the preprocessor map has the input file as a relative path in sources, + // e.g. when the input file is `src/foo/bar.svelte`, then sources is expected to contain just `bar.svelte`. + // Therefore filename also needs to be the basename of the path. This feels brittle, investigate how we can + // harden this (without breaking other tooling that assumes this behavior). + if (sourcefile === filename && sourcemap_list[map_idx]) { + return sourcemap_list[map_idx++]; // idx 1, 2, ... + // bundle file = branch node + } else { + return null; // source file = leaf node + } + }, + true + ); + if (!map.file) delete map.file; // skip optional field `file` + // When source maps are combined and the leading map is empty, sources is not set. + // Add the filename to the empty array in this case. + // Further improvements to remapping may help address this as well https://github.com/ampproject/remapping/issues/116 + if (!map.sources.length) map.sources = [filename]; + return map; +} + +/** + * @param {string} filename + * @param {SourceMap} svelte_map + * @param {string | DecodedSourceMap | RawSourceMap} preprocessor_map_input + * @returns {SourceMap} + */ +function apply_preprocessor_sourcemap(filename, svelte_map, preprocessor_map_input) { + if (!svelte_map || !preprocessor_map_input) return svelte_map; + const preprocessor_map = + typeof preprocessor_map_input === 'string' + ? JSON.parse(preprocessor_map_input) + : preprocessor_map_input; + const result_map = combine_sourcemaps(filename, [svelte_map, preprocessor_map]); + // Svelte expects a SourceMap which includes toUrl and toString. Instead of wrapping our output in a class, + // we just tack on the extra properties. + Object.defineProperties(result_map, { + toString: { + enumerable: false, + value: function toString() { + return JSON.stringify(this); + } + }, + toUrl: { + enumerable: false, + value: function toUrl() { + return 'data:application/json;charset=utf-8;base64,' + b64enc(this.toString()); + } + } + }); + return /** @type {any} */ (result_map); +} +const regex_data_uri = /data:(?:application|text)\/json;(?:charset[:=]\S+?;)?base64,(\S*)/; +// parse attached sourcemap in processed.code + +/** + * @param {Processed} processed + * @param {'script' | 'style'} tag_name + * @returns {void} + */ +export function parse_attached_sourcemap(processed, tag_name) { + const r_in = '[#@]\\s*sourceMappingURL\\s*=\\s*(\\S*)'; + const regex = + tag_name == 'script' + ? new RegExp('(?://' + r_in + ')|(?:/\\*' + r_in + '\\s*\\*/)$') + : new RegExp('/\\*' + r_in + '\\s*\\*/$'); + + /** + * @param {any} message + */ + function log_warning(message) { + // code_start: help to find preprocessor + const code_start = + processed.code.length < 100 ? processed.code : processed.code.slice(0, 100) + ' [...]'; + // eslint-disable-next-line no-console + console.warn(`warning: ${message}. processed.code = ${JSON.stringify(code_start)}`); + } + processed.code = processed.code.replace(regex, (_, match1, match2) => { + const map_url = tag_name == 'script' ? match1 || match2 : match1; + const map_data = (map_url.match(regex_data_uri) || [])[1]; + if (map_data) { + // sourceMappingURL is data URL + if (processed.map) { + log_warning( + 'Not implemented. ' + + 'Found sourcemap in both processed.code and processed.map. ' + + 'Please update your preprocessor to return only one sourcemap.' + ); + // ignore attached sourcemap + return ''; + } + processed.map = b64dec(map_data); // use attached sourcemap + return ''; // remove from processed.code + } + // sourceMappingURL is path or URL + if (!processed.map) { + log_warning( + `Found sourcemap path ${JSON.stringify( + map_url + )} in processed.code, but no sourcemap data. ` + + 'Please update your preprocessor to return sourcemap data directly.' + ); + } + // ignore sourcemap path + return ''; // remove from processed.code + }); +} + +/** + * @param {{ code: string, map: SourceMap}} result + * @param {ValidatedCompileOptions} options + * @param {string} source_name + */ +export function merge_with_preprocessor_map(result, options, source_name) { + if (options.sourcemap) { + const file_basename = get_basename(options.filename); + // The preprocessor map is expected to contain `sources: [basename_of_filename]`, but our own + // map may contain a different file name. Patch our map beforehand to align sources so merging + // with the preprocessor map works correctly. + result.map.sources = [file_basename]; + Object.assign( + result.map, + apply_preprocessor_sourcemap( + file_basename, + result.map, + /** @type {any} */ (options.sourcemap) + ) + ); + // After applying the preprocessor map, we need to do the inverse and make the sources + // relative to the input file again in case the output code is in a different directory. + if (file_basename !== source_name) { + result.map.sources = result.map.sources.map( + /** @param {string} source */ (source) => get_relative_path(source_name, source) + ); + } + } +} + +/** + * @param {string} from + * @param {string} to + */ +function get_relative_path(from, to) { + // Don't use node's utils here to ensure the compiler is usable in a browser environment + const from_parts = from.split(/[/\\]/); + const to_parts = to.split(/[/\\]/); + from_parts.pop(); // get dirname + while (from_parts[0] === to_parts[0]) { + from_parts.shift(); + to_parts.shift(); + } + if (from_parts.length) { + let i = from_parts.length; + while (i--) from_parts[i] = '..'; + } + return from_parts.concat(to_parts).join('/'); +} + +/** + * Like node's `basename`, but doesn't use it to ensure the compiler is usable in a browser environment + * @param {string} filename + */ +export function get_basename(filename) { + return /** @type {string} */ (filename.split(/[/\\]/).pop()); +} + +/** + * @param {string} filename + * @param {string | undefined} output_filename + * @param {string} fallback + */ +export function get_source_name(filename, output_filename, fallback) { + return output_filename ? get_relative_path(output_filename, filename) : get_basename(filename); +} diff --git a/frontend/node_modules/svelte/src/compiler/utils/push_array.js b/frontend/node_modules/svelte/src/compiler/utils/push_array.js new file mode 100644 index 0000000..ee6a9f7 --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/utils/push_array.js @@ -0,0 +1,13 @@ +/** + * Pushes all `items` into `array` using `push`, therefore mutating the array. + * We do this for memory and perf reasons, and because `array.push(...items)` would + * run into a "max call stack size exceeded" error with too many items (~65k). + * @template T + * @param {T[]} array + * @param {T[]} items + */ +export function push_array(array, items) { + for (let i = 0; i < items.length; i++) { + array.push(items[i]); + } +} diff --git a/frontend/node_modules/svelte/src/compiler/utils/sanitize_template_string.js b/frontend/node_modules/svelte/src/compiler/utils/sanitize_template_string.js new file mode 100644 index 0000000..80357d9 --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/utils/sanitize_template_string.js @@ -0,0 +1,7 @@ +/** + * @param {string} str + * @returns {string} + */ +export function sanitize_template_string(str) { + return str.replace(/(`|\${|\\)/g, '\\$1'); +} diff --git a/frontend/node_modules/svelte/src/compiler/utils/slot.js b/frontend/node_modules/svelte/src/compiler/utils/slot.js new file mode 100644 index 0000000..078bf58 --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/utils/slot.js @@ -0,0 +1,20 @@ +/** @import { AST } from '#compiler' */ +import { is_element_node } from '../phases/nodes.js'; +import { is_text_attribute } from './ast.js'; + +/** + * @param {AST.SvelteNode} node + */ +export function determine_slot(node) { + if (!is_element_node(node)) return null; + + for (const attribute of node.attributes) { + if (attribute.type !== 'Attribute') continue; + if (attribute.name !== 'slot') continue; + if (!is_text_attribute(attribute)) continue; + + return /** @type {string} */ (attribute.value[0].data); + } + + return null; +} diff --git a/frontend/node_modules/svelte/src/compiler/utils/string.js b/frontend/node_modules/svelte/src/compiler/utils/string.js new file mode 100644 index 0000000..42eefa9 --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/utils/string.js @@ -0,0 +1,9 @@ +/** + * @param {string[]} strings + * @param {string} conjunction + */ +export function list(strings, conjunction = 'or') { + if (strings.length === 1) return strings[0]; + if (strings.length === 2) return `${strings[0]} ${conjunction} ${strings[1]}`; + return `${strings.slice(0, -1).join(', ')} ${conjunction} ${strings[strings.length - 1]}`; +} diff --git a/frontend/node_modules/svelte/src/compiler/validate-options.js b/frontend/node_modules/svelte/src/compiler/validate-options.js new file mode 100644 index 0000000..f7c56aa --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/validate-options.js @@ -0,0 +1,361 @@ +/** @import { ModuleCompileOptions, ValidatedModuleCompileOptions, CompileOptions, ValidatedCompileOptions } from '#compiler' */ +import * as e from './errors.js'; +import * as w from './warnings.js'; + +/** + * @template [Input=any] + * @template [Output=Input] + * @typedef {(input: Input, keypath: string) => Required} Validator + */ + +const common_options = { + filename: string('(unknown)'), + + // default to process.cwd() where it exists to replicate svelte4 behavior (and make Deno work with this as well) + // see https://github.com/sveltejs/svelte/blob/b62fc8c8fd2640c9b99168f01b9d958cb2f7574f/packages/svelte/src/compiler/compile/Component.js#L211 + /* eslint-disable */ + rootDir: string( + typeof process !== 'undefined' + ? process.cwd?.() + : // @ts-expect-error + typeof Deno !== 'undefined' + ? // @ts-expect-error + Deno.cwd() + : undefined + ), + /* eslint-enable */ + + dev: boolean(false), + + generate: validator('client', (input, keypath) => { + if (input === 'dom' || input === 'ssr') { + warn_once(w.options_renamed_ssr_dom); + return input === 'dom' ? 'client' : 'server'; + } + + // TODO deprecate `false` in favour of `analyze`/`analyzeModule` https://github.com/sveltejs/svelte-octane/issues/655 + if (input !== 'client' && input !== 'server' && input !== false) { + throw_error(`${keypath} must be "client", "server" or false`); + } + + return input; + }), + + warningFilter: fun(() => true), + + experimental: object({ + async: boolean(false) + }) +}; + +const component_options = { + accessors: deprecate(w.options_deprecated_accessors, boolean(false)), + + /** @type {Validator<'injected' | 'external' | ((options: { filename: string }) => 'injected' | 'external'), (options: { filename: string }) => 'injected' | 'external'>} */ + css: parametric( + /** @type {(options: { filename: string }) => 'injected' | 'external'} */ (() => 'external'), + (input) => { + if (input === true || input === false) { + throw_error( + 'The boolean options have been removed from the css option. Use "external" instead of false and "injected" instead of true' + ); + } + if (input === 'none') { + throw_error( + 'css: "none" is no longer a valid option. If this was crucial for you, please open an issue on GitHub with your use case.' + ); + } + + if (input !== 'external' && input !== 'injected') { + throw_error(`css should be either "external" (default, recommended) or "injected"`); + } + + return /** @type {'external' | 'injected'} */ (input); + } + ), + + cssHash: fun(({ css, filename, hash }) => { + return `svelte-${hash(filename === '(unknown)' ? css : filename ?? css)}`; + }), + + // TODO this is a sourcemap option, would be good to put under a sourcemap namespace + cssOutputFilename: string(undefined), + + /** @type {Validator boolean), (options: { filename: string }) => boolean>} */ + customElement: parametric( + /** @type {(options: { filename: string }) => boolean} */ (() => false), + (input, keypath) => { + if (typeof input !== 'boolean') { + throw_error(`${keypath} should be true or false`); + } + + return /** @type {boolean} */ (input); + } + ), + + discloseVersion: boolean(true), + + immutable: deprecate(w.options_deprecated_immutable, boolean(false)), + + legacy: removed( + 'The legacy option has been removed. If you are using this because of legacy.componentApi, use compatibility.componentApi instead' + ), + + compatibility: object({ + componentApi: list([4, 5], 5) + }), + + loopGuardTimeout: warn_removed(w.options_removed_loop_guard_timeout), + + name: string(undefined), + + namespace: list(['html', 'mathml', 'svg']), + + modernAst: boolean(false), + + outputFilename: string(undefined), + + preserveComments: boolean(false), + + fragments: list(['html', 'tree']), + + preserveWhitespace: boolean(false), + + /** @type {Validator boolean | undefined), () => boolean | undefined>} */ + runes: parametric(() => /** @type {boolean | undefined} */ (undefined)), + + hmr: boolean(false), + + sourcemap: validator(undefined, (input) => { + // Source maps can take on a variety of values, including string, JSON, map objects from magic-string and source-map, + // so there's no good way to check type validity here + return input; + }), + + enableSourcemap: warn_removed(w.options_removed_enable_sourcemap), + + hydratable: warn_removed(w.options_removed_hydratable), + + format: removed( + 'The format option has been removed in Svelte 4, the compiler only outputs ESM now. Remove "format" from your compiler options. ' + + 'If you did not set this yourself, bump the version of your bundler plugin (vite-plugin-svelte/rollup-plugin-svelte/svelte-loader)' + ), + + tag: removed( + 'The tag option has been removed in Svelte 5. Use `` inside the component instead. ' + + 'If that does not solve your use case, please open an issue on GitHub with details.' + ), + + sveltePath: removed( + 'The sveltePath option has been removed in Svelte 5. ' + + 'If this option was crucial for you, please open an issue on GitHub with your use case.' + ), + + // These two were primarily created for svelte-preprocess (https://github.com/sveltejs/svelte/pull/6194), + // but with new TypeScript compilation modes strictly separating types it's not necessary anymore + errorMode: removed( + 'The errorMode option has been removed. If you are using this through svelte-preprocess with TypeScript, ' + + 'use the https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax setting instead' + ), + + varsReport: removed( + 'The vars option has been removed. If you are using this through svelte-preprocess with TypeScript, ' + + 'use the https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax setting instead' + ) +}; + +export const validate_module_options = + /** @type {Validator} */ ( + object({ + ...common_options, + ...Object.fromEntries(Object.keys(component_options).map((key) => [key, () => {}])) + }) + ); + +export const validate_component_options = + /** @type {Validator} */ ( + object({ + ...common_options, + ...component_options + }) + ); + +/** + * @param {string} msg + * @returns {Validator} + */ +function removed(msg) { + return (input) => { + if (input !== undefined) { + e.options_removed(null, msg); + } + return /** @type {any} */ (undefined); + }; +} + +const warned = new Set(); + +/** @param {(node: null) => void} fn */ +function warn_once(fn) { + if (!warned.has(fn)) { + warned.add(fn); + fn(null); + } +} + +/** + * @param {(node: null) => void} fn + * @returns {Validator} + */ +function warn_removed(fn) { + return (input) => { + if (input !== undefined) warn_once(fn); + return /** @type {any} */ (undefined); + }; +} + +/** + * @param {(node: null) => void} fn + * @param {Validator} validator + * @returns {Validator} + */ +function deprecate(fn, validator) { + return (input, keypath) => { + if (input !== undefined) warn_once(fn); + return validator(input, keypath); + }; +} + +/** + * @param {Record} children + * @param {boolean} [allow_unknown] + * @returns {Validator} + */ +function object(children, allow_unknown = false) { + return (input, keypath) => { + /** @type {Record} */ + const output = {}; + + if ((input && typeof input !== 'object') || Array.isArray(input)) { + throw_error(`${keypath} should be an object`); + } + + for (const key in input) { + if (!(key in children)) { + if (allow_unknown) { + output[key] = input[key]; + } else { + e.options_unrecognised(null, `${keypath ? `${keypath}.${key}` : key}`); + } + } + } + + for (const key in children) { + const validator = children[key]; + output[key] = validator(input && input[key], keypath ? `${keypath}.${key}` : key); + } + + return output; + }; +} + +/** + * @param {any} fallback + * @param {(value: any, keypath: string) => any} fn + * @returns {Validator} + */ +function validator(fallback, fn) { + return (input, keypath) => { + return input === undefined ? fallback : fn(input, keypath); + }; +} + +/** + * @param {string | undefined} fallback + * @param {boolean} allow_empty + * @returns {Validator} + */ +function string(fallback, allow_empty = true) { + return validator(fallback, (input, keypath) => { + if (typeof input !== 'string') { + throw_error(`${keypath} should be a string, if specified`); + } + + if (!allow_empty && input === '') { + throw_error(`${keypath} cannot be empty`); + } + + return input; + }); +} + +/** + * @param {boolean | undefined} fallback + * @returns {Validator} + */ +function boolean(fallback) { + return validator(fallback, (input, keypath) => { + if (typeof input !== 'boolean') { + throw_error(`${keypath} should be true or false, if specified`); + } + return input; + }); +} + +/** + * @param {Array} options + * @returns {Validator} + */ +function list(options, fallback = options[0]) { + return validator(fallback, (input, keypath) => { + if (!options.includes(input)) { + // prettier-ignore + const msg = options.length > 2 + ? `${keypath} should be one of ${options.slice(0, -1).map(input => `"${input}"`).join(', ')} or "${options[options.length - 1]}"` + : `${keypath} should be either "${options[0]}" or "${options[1]}"`; + + throw_error(msg); + } + return input; + }); +} + +/** + * @param {(...args: any) => any} fallback + * @returns {Validator} + */ +function fun(fallback) { + return validator(fallback, (input, keypath) => { + if (typeof input !== 'function') { + throw_error(`${keypath} should be a function, if specified`); + } + return input; + }); +} + +/** + * @template {(...args: any[]) => any} F + * @param {F} fallback + * @param {(value: unknown, keypath: string) => ReturnType} [normalize] + * @returns {Validator} + */ +function parametric(fallback, normalize = (value) => /** @type {ReturnType} */ (value)) { + return validator(fallback, (input, keypath) => { + if (typeof input === 'function') { + /** @type {(...args: Parameters) => ReturnType} */ + const normalized = (...args) => normalize(input(...args), keypath); + + return /** @type {F} */ (/** @type {unknown} */ (normalized)); + } + + /** @type {(...args: Parameters) => ReturnType} */ + const normalized = (..._args) => normalize(input, keypath); + + return /** @type {F} */ (/** @type {unknown} */ (normalized)); + }); +} + +/** @param {string} msg */ +function throw_error(msg) { + e.options_invalid_value(null, msg); +} diff --git a/frontend/node_modules/svelte/src/compiler/warnings.js b/frontend/node_modules/svelte/src/compiler/warnings.js new file mode 100644 index 0000000..089cb1e --- /dev/null +++ b/frontend/node_modules/svelte/src/compiler/warnings.js @@ -0,0 +1,845 @@ +/* This file is generated by scripts/process-messages/index.js. Do not edit! */ + +import { warnings, ignore_stack, ignore_map, warning_filter } from './state.js'; +import { CompileDiagnostic } from './utils/compile_diagnostic.js'; + +/** @typedef {{ start?: number, end?: number }} NodeLike */ +class InternalCompileWarning extends CompileDiagnostic { + name = 'CompileWarning'; + + /** + * @param {string} code + * @param {string} message + * @param {[number, number] | undefined} position + */ + constructor(code, message, position) { + super(code, message, position); + } +} + +/** + * @param {null | NodeLike} node + * @param {string} code + * @param {string} message + */ +function w(node, code, message) { + let stack = ignore_stack; + + if (node) { + stack = ignore_map.get(node) ?? ignore_stack; + } + + if (stack && stack.at(-1)?.has(code)) return; + + const warning = new InternalCompileWarning(code, message, node && node.start !== undefined ? [node.start, node.end ?? node.start] : undefined); + + if (!warning_filter(warning)) return; + + warnings.push(warning); +} + +export const codes = [ + 'a11y_accesskey', + 'a11y_aria_activedescendant_has_tabindex', + 'a11y_aria_attributes', + 'a11y_autocomplete_valid', + 'a11y_autofocus', + 'a11y_click_events_have_key_events', + 'a11y_consider_explicit_label', + 'a11y_distracting_elements', + 'a11y_figcaption_index', + 'a11y_figcaption_parent', + 'a11y_hidden', + 'a11y_img_redundant_alt', + 'a11y_incorrect_aria_attribute_type', + 'a11y_incorrect_aria_attribute_type_boolean', + 'a11y_incorrect_aria_attribute_type_id', + 'a11y_incorrect_aria_attribute_type_idlist', + 'a11y_incorrect_aria_attribute_type_integer', + 'a11y_incorrect_aria_attribute_type_token', + 'a11y_incorrect_aria_attribute_type_tokenlist', + 'a11y_incorrect_aria_attribute_type_tristate', + 'a11y_interactive_supports_focus', + 'a11y_invalid_attribute', + 'a11y_label_has_associated_control', + 'a11y_media_has_caption', + 'a11y_misplaced_role', + 'a11y_misplaced_scope', + 'a11y_missing_attribute', + 'a11y_missing_content', + 'a11y_mouse_events_have_key_events', + 'a11y_no_abstract_role', + 'a11y_no_interactive_element_to_noninteractive_role', + 'a11y_no_noninteractive_element_interactions', + 'a11y_no_noninteractive_element_to_interactive_role', + 'a11y_no_noninteractive_tabindex', + 'a11y_no_redundant_roles', + 'a11y_no_static_element_interactions', + 'a11y_positive_tabindex', + 'a11y_role_has_required_aria_props', + 'a11y_role_supports_aria_props', + 'a11y_role_supports_aria_props_implicit', + 'a11y_unknown_aria_attribute', + 'a11y_unknown_role', + 'bidirectional_control_characters', + 'legacy_code', + 'unknown_code', + 'options_deprecated_accessors', + 'options_deprecated_immutable', + 'options_missing_custom_element', + 'options_removed_enable_sourcemap', + 'options_removed_hydratable', + 'options_removed_loop_guard_timeout', + 'options_renamed_ssr_dom', + 'custom_element_props_identifier', + 'export_let_unused', + 'legacy_component_creation', + 'non_reactive_update', + 'perf_avoid_inline_class', + 'perf_avoid_nested_class', + 'reactive_declaration_invalid_placement', + 'reactive_declaration_module_script_dependency', + 'state_referenced_locally', + 'store_rune_conflict', + 'css_unused_selector', + 'attribute_avoid_is', + 'attribute_global_event_reference', + 'attribute_illegal_colon', + 'attribute_invalid_property_name', + 'attribute_quoted', + 'bind_invalid_each_rest', + 'block_empty', + 'component_name_lowercase', + 'element_implicitly_closed', + 'element_invalid_self_closing_tag', + 'event_directive_deprecated', + 'node_invalid_placement_ssr', + 'script_context_deprecated', + 'script_unknown_attribute', + 'slot_element_deprecated', + 'svelte_component_deprecated', + 'svelte_element_invalid_this', + 'svelte_self_deprecated' +]; + +/** + * Avoid using accesskey + * @param {null | NodeLike} node + */ +export function a11y_accesskey(node) { + w(node, 'a11y_accesskey', `Avoid using accesskey\nhttps://svelte.dev/e/a11y_accesskey`); +} + +/** + * An element with an aria-activedescendant attribute should have a tabindex value + * @param {null | NodeLike} node + */ +export function a11y_aria_activedescendant_has_tabindex(node) { + w(node, 'a11y_aria_activedescendant_has_tabindex', `An element with an aria-activedescendant attribute should have a tabindex value\nhttps://svelte.dev/e/a11y_aria_activedescendant_has_tabindex`); +} + +/** + * `<%name%>` should not have aria-* attributes + * @param {null | NodeLike} node + * @param {string} name + */ +export function a11y_aria_attributes(node, name) { + w(node, 'a11y_aria_attributes', `\`<${name}>\` should not have aria-* attributes\nhttps://svelte.dev/e/a11y_aria_attributes`); +} + +/** + * '%value%' is an invalid value for 'autocomplete' on `` + * @param {null | NodeLike} node + * @param {string} value + * @param {string} type + */ +export function a11y_autocomplete_valid(node, value, type) { + w(node, 'a11y_autocomplete_valid', `'${value}' is an invalid value for 'autocomplete' on \`\`\nhttps://svelte.dev/e/a11y_autocomplete_valid`); +} + +/** + * Avoid using autofocus + * @param {null | NodeLike} node + */ +export function a11y_autofocus(node) { + w(node, 'a11y_autofocus', `Avoid using autofocus\nhttps://svelte.dev/e/a11y_autofocus`); +} + +/** + * Visible, non-interactive elements with a click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as `