diff --git a/.gitignore b/.gitignore index 3b462cb..84dc360 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,9 @@ node_modules /.svelte-kit /build +# Application +/temp + # OS .DS_Store Thumbs.db diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a8787c6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "css.lint.unknownAtRules": "ignore" +} diff --git a/deno.json b/deno.json index 9285094..7e96665 100644 --- a/deno.json +++ b/deno.json @@ -1,29 +1,28 @@ { - "tasks": { - "dev": "vite dev", - "build": "vite build", - "preview": "vite preview", - "prepare": "svelte-kit sync || echo ''", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "format": "prettier --write .", - "lint": "prettier --check . && eslint ." - }, - "compilerOptions": { - "lib": ["deno.window", "dom"], - "strict": true - }, - "exclude": [ - "build/", - ".svelte-kit/", - "node_modules/" - ], - "fmt": { - "exclude": ["build/", ".svelte-kit/", "node_modules/"], - "indentWidth": 2, - "useTabs": false - }, - "lint": { - "exclude": ["build/", ".svelte-kit/", "node_modules/"] - } -} \ No newline at end of file + "imports": { + "$config": "./src/utils/config/config.ts" + }, + "tasks": { + "dev": "APP_BASE_PATH=./temp vite dev", + "build": "vite build", + "preview": "vite preview", + "prepare": "svelte-kit sync || echo ''", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "format": "prettier --write .", + "lint": "prettier --check . && eslint ." + }, + "compilerOptions": { + "lib": ["deno.window", "dom"], + "strict": true + }, + "exclude": ["build/", ".svelte-kit/", "node_modules/"], + "fmt": { + "exclude": ["build/", ".svelte-kit/", "node_modules/"], + "indentWidth": 2, + "useTabs": false + }, + "lint": { + "exclude": ["build/", ".svelte-kit/", "node_modules/"] + } +} diff --git a/deno.lock b/deno.lock index f7d686b..2c9a3e3 100644 --- a/deno.lock +++ b/deno.lock @@ -1,10 +1,8 @@ { "version": "5", "specifiers": { - "npm:@deno/svelte-adapter@0.1": "0.1.0_@sveltejs+kit@2.47.1__@sveltejs+vite-plugin-svelte@6.2.1___svelte@5.40.2____acorn@8.15.0___vite@7.1.10____@types+node@22.18.11____picomatch@4.0.3___@types+node@22.18.11__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__acorn@8.15.0__@types+node@22.18.11_@sveltejs+vite-plugin-svelte@6.2.1__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__@types+node@22.18.11_svelte@5.40.2__acorn@8.15.0_vite@7.1.10__@types+node@22.18.11__picomatch@4.0.3_@types+node@22.18.11", "npm:@eslint/compat@^1.4.0": "1.4.0_eslint@9.37.0", "npm:@eslint/js@^9.36.0": "9.37.0", - "npm:@sveltejs/adapter-auto@^6.1.0": "6.1.1_@sveltejs+kit@2.47.1__@sveltejs+vite-plugin-svelte@6.2.1___svelte@5.40.2____acorn@8.15.0___vite@7.1.10____@types+node@22.18.11____picomatch@4.0.3___@types+node@22.18.11__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__acorn@8.15.0__@types+node@22.18.11_@sveltejs+vite-plugin-svelte@6.2.1__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__@types+node@22.18.11_svelte@5.40.2__acorn@8.15.0_vite@7.1.10__@types+node@22.18.11__picomatch@4.0.3_@types+node@22.18.11", "npm:@sveltejs/kit@^2.43.2": "2.47.1_@sveltejs+vite-plugin-svelte@6.2.1__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__@types+node@22.18.11_svelte@5.40.2__acorn@8.15.0_vite@7.1.10__@types+node@22.18.11__picomatch@4.0.3_acorn@8.15.0_@types+node@22.18.11", "npm:@sveltejs/vite-plugin-svelte@^6.2.0": "6.2.1_svelte@5.40.2__acorn@8.15.0_vite@7.1.10__@types+node@22.18.11__picomatch@4.0.3_@types+node@22.18.11", "npm:@tailwindcss/forms@~0.5.10": "0.5.10_tailwindcss@4.1.14", @@ -19,125 +17,218 @@ "npm:prettier@^3.6.2": "3.6.2", "npm:svelte-check@^4.3.2": "4.3.3_svelte@5.40.2__acorn@8.15.0_typescript@5.9.3", "npm:svelte@^5.39.5": "5.40.2_acorn@8.15.0", + "npm:sveltekit-adapter-deno@~0.16.1": "0.16.1_@sveltejs+kit@2.47.1__@sveltejs+vite-plugin-svelte@6.2.1___svelte@5.40.2____acorn@8.15.0___vite@7.1.10____@types+node@22.18.11____picomatch@4.0.3___@types+node@22.18.11__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__acorn@8.15.0__@types+node@22.18.11_@sveltejs+vite-plugin-svelte@6.2.1__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__@types+node@22.18.11_svelte@5.40.2__acorn@8.15.0_vite@7.1.10__@types+node@22.18.11__picomatch@4.0.3_@types+node@22.18.11", "npm:tailwindcss@^4.1.13": "4.1.14", "npm:typescript-eslint@^8.44.1": "8.46.1_eslint@9.37.0_typescript@5.9.3_@typescript-eslint+parser@8.46.1__eslint@9.37.0__typescript@5.9.3", "npm:typescript@^5.9.2": "5.9.3", "npm:vite@^7.1.7": "7.1.10_@types+node@22.18.11_picomatch@4.0.3" }, "npm": { - "@deno/experimental-route-config@0.0.5": { - "integrity": "sha512-0PN4qij3sC3Qm8WbiOBGlOQz8WtB0AENGkzsTHOYyPenf40iW7OGFid8QT3L8lGApnz3t6ufET0c2XgagV8Jjw==", - "dependencies": [ - "urlpattern-polyfill" - ] - }, - "@deno/svelte-adapter@0.1.0_@sveltejs+kit@2.47.1__@sveltejs+vite-plugin-svelte@6.2.1___svelte@5.40.2____acorn@8.15.0___vite@7.1.10____@types+node@22.18.11____picomatch@4.0.3___@types+node@22.18.11__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__acorn@8.15.0__@types+node@22.18.11_@sveltejs+vite-plugin-svelte@6.2.1__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__@types+node@22.18.11_svelte@5.40.2__acorn@8.15.0_vite@7.1.10__@types+node@22.18.11__picomatch@4.0.3_@types+node@22.18.11": { - "integrity": "sha512-fx4Kj1lSx1rJvjtPr3cXO7qKveI1vUyGW8jX+clJHQEqEeIDnEcBW0FpMZEVORPlay2SGydQWSGbwh4j2iENzg==", - "dependencies": [ - "@deno/experimental-route-config", - "@sveltejs/kit" - ] + "@esbuild/aix-ppc64@0.24.2": { + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "os": ["aix"], + "cpu": ["ppc64"] }, "@esbuild/aix-ppc64@0.25.11": { "integrity": "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==", "os": ["aix"], "cpu": ["ppc64"] }, + "@esbuild/android-arm64@0.24.2": { + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "os": ["android"], + "cpu": ["arm64"] + }, "@esbuild/android-arm64@0.25.11": { "integrity": "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==", "os": ["android"], "cpu": ["arm64"] }, + "@esbuild/android-arm@0.24.2": { + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "os": ["android"], + "cpu": ["arm"] + }, "@esbuild/android-arm@0.25.11": { "integrity": "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==", "os": ["android"], "cpu": ["arm"] }, + "@esbuild/android-x64@0.24.2": { + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "os": ["android"], + "cpu": ["x64"] + }, "@esbuild/android-x64@0.25.11": { "integrity": "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==", "os": ["android"], "cpu": ["x64"] }, + "@esbuild/darwin-arm64@0.24.2": { + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "os": ["darwin"], + "cpu": ["arm64"] + }, "@esbuild/darwin-arm64@0.25.11": { "integrity": "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==", "os": ["darwin"], "cpu": ["arm64"] }, + "@esbuild/darwin-x64@0.24.2": { + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "os": ["darwin"], + "cpu": ["x64"] + }, "@esbuild/darwin-x64@0.25.11": { "integrity": "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==", "os": ["darwin"], "cpu": ["x64"] }, + "@esbuild/freebsd-arm64@0.24.2": { + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "os": ["freebsd"], + "cpu": ["arm64"] + }, "@esbuild/freebsd-arm64@0.25.11": { "integrity": "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==", "os": ["freebsd"], "cpu": ["arm64"] }, + "@esbuild/freebsd-x64@0.24.2": { + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "os": ["freebsd"], + "cpu": ["x64"] + }, "@esbuild/freebsd-x64@0.25.11": { "integrity": "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==", "os": ["freebsd"], "cpu": ["x64"] }, + "@esbuild/linux-arm64@0.24.2": { + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "os": ["linux"], + "cpu": ["arm64"] + }, "@esbuild/linux-arm64@0.25.11": { "integrity": "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==", "os": ["linux"], "cpu": ["arm64"] }, + "@esbuild/linux-arm@0.24.2": { + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "os": ["linux"], + "cpu": ["arm"] + }, "@esbuild/linux-arm@0.25.11": { "integrity": "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==", "os": ["linux"], "cpu": ["arm"] }, + "@esbuild/linux-ia32@0.24.2": { + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "os": ["linux"], + "cpu": ["ia32"] + }, "@esbuild/linux-ia32@0.25.11": { "integrity": "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==", "os": ["linux"], "cpu": ["ia32"] }, + "@esbuild/linux-loong64@0.24.2": { + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "os": ["linux"], + "cpu": ["loong64"] + }, "@esbuild/linux-loong64@0.25.11": { "integrity": "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==", "os": ["linux"], "cpu": ["loong64"] }, + "@esbuild/linux-mips64el@0.24.2": { + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "os": ["linux"], + "cpu": ["mips64el"] + }, "@esbuild/linux-mips64el@0.25.11": { "integrity": "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==", "os": ["linux"], "cpu": ["mips64el"] }, + "@esbuild/linux-ppc64@0.24.2": { + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "os": ["linux"], + "cpu": ["ppc64"] + }, "@esbuild/linux-ppc64@0.25.11": { "integrity": "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==", "os": ["linux"], "cpu": ["ppc64"] }, + "@esbuild/linux-riscv64@0.24.2": { + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "os": ["linux"], + "cpu": ["riscv64"] + }, "@esbuild/linux-riscv64@0.25.11": { "integrity": "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==", "os": ["linux"], "cpu": ["riscv64"] }, + "@esbuild/linux-s390x@0.24.2": { + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "os": ["linux"], + "cpu": ["s390x"] + }, "@esbuild/linux-s390x@0.25.11": { "integrity": "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==", "os": ["linux"], "cpu": ["s390x"] }, + "@esbuild/linux-x64@0.24.2": { + "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "os": ["linux"], + "cpu": ["x64"] + }, "@esbuild/linux-x64@0.25.11": { "integrity": "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==", "os": ["linux"], "cpu": ["x64"] }, + "@esbuild/netbsd-arm64@0.24.2": { + "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "os": ["netbsd"], + "cpu": ["arm64"] + }, "@esbuild/netbsd-arm64@0.25.11": { "integrity": "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==", "os": ["netbsd"], "cpu": ["arm64"] }, + "@esbuild/netbsd-x64@0.24.2": { + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "os": ["netbsd"], + "cpu": ["x64"] + }, "@esbuild/netbsd-x64@0.25.11": { "integrity": "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==", "os": ["netbsd"], "cpu": ["x64"] }, + "@esbuild/openbsd-arm64@0.24.2": { + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "os": ["openbsd"], + "cpu": ["arm64"] + }, "@esbuild/openbsd-arm64@0.25.11": { "integrity": "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==", "os": ["openbsd"], "cpu": ["arm64"] }, + "@esbuild/openbsd-x64@0.24.2": { + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "os": ["openbsd"], + "cpu": ["x64"] + }, "@esbuild/openbsd-x64@0.25.11": { "integrity": "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==", "os": ["openbsd"], @@ -148,21 +239,41 @@ "os": ["openharmony"], "cpu": ["arm64"] }, + "@esbuild/sunos-x64@0.24.2": { + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "os": ["sunos"], + "cpu": ["x64"] + }, "@esbuild/sunos-x64@0.25.11": { "integrity": "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==", "os": ["sunos"], "cpu": ["x64"] }, + "@esbuild/win32-arm64@0.24.2": { + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "os": ["win32"], + "cpu": ["arm64"] + }, "@esbuild/win32-arm64@0.25.11": { "integrity": "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==", "os": ["win32"], "cpu": ["arm64"] }, + "@esbuild/win32-ia32@0.24.2": { + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "os": ["win32"], + "cpu": ["ia32"] + }, "@esbuild/win32-ia32@0.25.11": { "integrity": "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==", "os": ["win32"], "cpu": ["ia32"] }, + "@esbuild/win32-x64@0.24.2": { + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "os": ["win32"], + "cpu": ["x64"] + }, "@esbuild/win32-x64@0.25.11": { "integrity": "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==", "os": ["win32"], @@ -423,12 +534,6 @@ "acorn" ] }, - "@sveltejs/adapter-auto@6.1.1_@sveltejs+kit@2.47.1__@sveltejs+vite-plugin-svelte@6.2.1___svelte@5.40.2____acorn@8.15.0___vite@7.1.10____@types+node@22.18.11____picomatch@4.0.3___@types+node@22.18.11__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__acorn@8.15.0__@types+node@22.18.11_@sveltejs+vite-plugin-svelte@6.2.1__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__@types+node@22.18.11_svelte@5.40.2__acorn@8.15.0_vite@7.1.10__@types+node@22.18.11__picomatch@4.0.3_@types+node@22.18.11": { - "integrity": "sha512-cBNt4jgH4KuaNO5gRSB2CZKkGtz+OCZ8lPjRQGjhvVUD4akotnj2weUia6imLl2v07K3IgsQRyM36909miSwoQ==", - "dependencies": [ - "@sveltejs/kit" - ] - }, "@sveltejs/kit@2.47.1_@sveltejs+vite-plugin-svelte@6.2.1__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__@types+node@22.18.11_svelte@5.40.2__acorn@8.15.0_vite@7.1.10__@types+node@22.18.11__picomatch@4.0.3_acorn@8.15.0_@types+node@22.18.11": { "integrity": "sha512-1v+MbMHxTi6ctQyxmz3owLKqZGaBHyx4EQqTdq/PvDswPFzw3WlqhrOKOh2ZzH23+XpQGEF9G+KDIgYJE+byvg==", "dependencies": [ @@ -826,35 +931,67 @@ "tapable" ] }, + "esbuild@0.24.2": { + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "optionalDependencies": [ + "@esbuild/aix-ppc64@0.24.2", + "@esbuild/android-arm@0.24.2", + "@esbuild/android-arm64@0.24.2", + "@esbuild/android-x64@0.24.2", + "@esbuild/darwin-arm64@0.24.2", + "@esbuild/darwin-x64@0.24.2", + "@esbuild/freebsd-arm64@0.24.2", + "@esbuild/freebsd-x64@0.24.2", + "@esbuild/linux-arm@0.24.2", + "@esbuild/linux-arm64@0.24.2", + "@esbuild/linux-ia32@0.24.2", + "@esbuild/linux-loong64@0.24.2", + "@esbuild/linux-mips64el@0.24.2", + "@esbuild/linux-ppc64@0.24.2", + "@esbuild/linux-riscv64@0.24.2", + "@esbuild/linux-s390x@0.24.2", + "@esbuild/linux-x64@0.24.2", + "@esbuild/netbsd-arm64@0.24.2", + "@esbuild/netbsd-x64@0.24.2", + "@esbuild/openbsd-arm64@0.24.2", + "@esbuild/openbsd-x64@0.24.2", + "@esbuild/sunos-x64@0.24.2", + "@esbuild/win32-arm64@0.24.2", + "@esbuild/win32-ia32@0.24.2", + "@esbuild/win32-x64@0.24.2" + ], + "scripts": true, + "bin": true + }, "esbuild@0.25.11": { "integrity": "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==", "optionalDependencies": [ - "@esbuild/aix-ppc64", - "@esbuild/android-arm", - "@esbuild/android-arm64", - "@esbuild/android-x64", - "@esbuild/darwin-arm64", - "@esbuild/darwin-x64", - "@esbuild/freebsd-arm64", - "@esbuild/freebsd-x64", - "@esbuild/linux-arm", - "@esbuild/linux-arm64", - "@esbuild/linux-ia32", - "@esbuild/linux-loong64", - "@esbuild/linux-mips64el", - "@esbuild/linux-ppc64", - "@esbuild/linux-riscv64", - "@esbuild/linux-s390x", - "@esbuild/linux-x64", - "@esbuild/netbsd-arm64", - "@esbuild/netbsd-x64", - "@esbuild/openbsd-arm64", - "@esbuild/openbsd-x64", + "@esbuild/aix-ppc64@0.25.11", + "@esbuild/android-arm@0.25.11", + "@esbuild/android-arm64@0.25.11", + "@esbuild/android-x64@0.25.11", + "@esbuild/darwin-arm64@0.25.11", + "@esbuild/darwin-x64@0.25.11", + "@esbuild/freebsd-arm64@0.25.11", + "@esbuild/freebsd-x64@0.25.11", + "@esbuild/linux-arm@0.25.11", + "@esbuild/linux-arm64@0.25.11", + "@esbuild/linux-ia32@0.25.11", + "@esbuild/linux-loong64@0.25.11", + "@esbuild/linux-mips64el@0.25.11", + "@esbuild/linux-ppc64@0.25.11", + "@esbuild/linux-riscv64@0.25.11", + "@esbuild/linux-s390x@0.25.11", + "@esbuild/linux-x64@0.25.11", + "@esbuild/netbsd-arm64@0.25.11", + "@esbuild/netbsd-x64@0.25.11", + "@esbuild/openbsd-arm64@0.25.11", + "@esbuild/openbsd-x64@0.25.11", "@esbuild/openharmony-arm64", - "@esbuild/sunos-x64", - "@esbuild/win32-arm64", - "@esbuild/win32-ia32", - "@esbuild/win32-x64" + "@esbuild/sunos-x64@0.25.11", + "@esbuild/win32-arm64@0.25.11", + "@esbuild/win32-ia32@0.25.11", + "@esbuild/win32-x64@0.25.11" ], "scripts": true, "bin": true @@ -1537,6 +1674,13 @@ "zimmerframe" ] }, + "sveltekit-adapter-deno@0.16.1_@sveltejs+kit@2.47.1__@sveltejs+vite-plugin-svelte@6.2.1___svelte@5.40.2____acorn@8.15.0___vite@7.1.10____@types+node@22.18.11____picomatch@4.0.3___@types+node@22.18.11__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__acorn@8.15.0__@types+node@22.18.11_@sveltejs+vite-plugin-svelte@6.2.1__svelte@5.40.2___acorn@8.15.0__vite@7.1.10___@types+node@22.18.11___picomatch@4.0.3__@types+node@22.18.11_svelte@5.40.2__acorn@8.15.0_vite@7.1.10__@types+node@22.18.11__picomatch@4.0.3_@types+node@22.18.11": { + "integrity": "sha512-AwJj5Y9yoJ5BQVhfFURrVex5GrQmU/v06pW8vs6tyWaJxEYrnF6o3gbELVtCOI/YRl4G02I7n8fBDMY+/cgBdg==", + "dependencies": [ + "@sveltejs/kit", + "esbuild@0.24.2" + ] + }, "tailwindcss@4.1.14": { "integrity": "sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA==" }, @@ -1605,9 +1749,6 @@ "punycode" ] }, - "urlpattern-polyfill@10.1.0": { - "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==" - }, "util-deprecate@1.0.2": { "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, @@ -1615,7 +1756,7 @@ "integrity": "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==", "dependencies": [ "@types/node", - "esbuild", + "esbuild@0.25.11", "fdir", "picomatch@4.0.3", "postcss", @@ -1665,10 +1806,8 @@ "workspace": { "packageJson": { "dependencies": [ - "npm:@deno/svelte-adapter@0.1", "npm:@eslint/compat@^1.4.0", "npm:@eslint/js@^9.36.0", - "npm:@sveltejs/adapter-auto@^6.1.0", "npm:@sveltejs/kit@^2.43.2", "npm:@sveltejs/vite-plugin-svelte@^6.2.0", "npm:@tailwindcss/forms@~0.5.10", @@ -1683,6 +1822,7 @@ "npm:prettier@^3.6.2", "npm:svelte-check@^4.3.2", "npm:svelte@^5.39.5", + "npm:sveltekit-adapter-deno@~0.16.1", "npm:tailwindcss@^4.1.13", "npm:typescript-eslint@^8.44.1", "npm:typescript@^5.9.2", diff --git a/package.json b/package.json index 12e038d..f51f097 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,12 @@ "private": true, "version": "2.0.0", "type": "module", + "dependencies": { + "sveltekit-adapter-deno": "^0.16.1" + }, "devDependencies": { - "@deno/svelte-adapter": "^0.1.0", "@eslint/compat": "^1.4.0", "@eslint/js": "^9.36.0", - "@sveltejs/adapter-auto": "^6.1.0", "@sveltejs/kit": "^2.43.2", "@sveltejs/vite-plugin-svelte": "^6.2.0", "@tailwindcss/forms": "^0.5.10", diff --git a/src/deno.d.ts b/src/deno.d.ts new file mode 100644 index 0000000..aa03b52 --- /dev/null +++ b/src/deno.d.ts @@ -0,0 +1,20 @@ +/** + * Deno global type declarations for SvelteKit project + */ + +declare namespace Deno { + export const env: { + get(key: string): string | undefined; + }; + + export function mkdir( + path: string, + options?: { recursive?: boolean } + ): Promise; + + export function writeTextFile( + path: string, + data: string, + options?: { append?: boolean } + ): Promise; +} diff --git a/src/hooks.server.ts b/src/hooks.server.ts new file mode 100644 index 0000000..bf86cfd --- /dev/null +++ b/src/hooks.server.ts @@ -0,0 +1,8 @@ +import { config } from '$config'; +import { logStartup } from './utils/logger/startup.ts'; + +// Initialize configuration on server startup +await config.init(); + +// Log startup banner +await logStartup(); diff --git a/src/lib/assets/favicon.svg b/src/lib/assets/favicon.svg deleted file mode 100644 index cc5dc66..0000000 --- a/src/lib/assets/favicon.svg +++ /dev/null @@ -1 +0,0 @@ -svelte-logo \ No newline at end of file diff --git a/src/lib/index.ts b/src/lib/index.ts deleted file mode 100644 index 856f2b6..0000000 --- a/src/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -// place files you want to import through the `$lib` alias in this folder. diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 8c56a3c..850ac50 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,12 +1,13 @@ - + + Profilarr {@render children?.()} diff --git a/src/static/logo.svg b/src/static/logo.svg new file mode 100644 index 0000000..8c4acd5 --- /dev/null +++ b/src/static/logo.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/utils/config/config.ts b/src/utils/config/config.ts new file mode 100644 index 0000000..03bb605 --- /dev/null +++ b/src/utils/config/config.ts @@ -0,0 +1,46 @@ +/** + * Application configuration singleton + */ + +class Config { + private basePath: string; + + constructor() { + // Default base path logic: + // 1. Check environment variable + // 2. Fall back to /app (Docker default) + this.basePath = Deno.env.get('APP_BASE_PATH') || '/app'; + } + + /** + * Initialize the configuration (create directories) + * Must be called before using the config + */ + async init(): Promise { + await Deno.mkdir(this.paths.logs, { recursive: true }); + } + + /** + * Set the base path for the application + */ + setBasePath(path: string): void { + this.basePath = path; + } + + /** + * Application paths (relative to base) + */ + readonly paths = { + get base(): string { + return config.basePath; + }, + get logs(): string { + return `${config.basePath}/logs`; + }, + get logFile(): string { + return `${config.basePath}/logs/app.log`; + } + }; +} + +export const config = new Config(); diff --git a/src/utils/logger/colors.ts b/src/utils/logger/colors.ts new file mode 100644 index 0000000..81e09ee --- /dev/null +++ b/src/utils/logger/colors.ts @@ -0,0 +1,12 @@ +/** + * ANSI color codes for terminal output + */ + +export const colors = { + reset: '\x1b[0m', + grey: '\x1b[90m', + cyan: '\x1b[36m', + green: '\x1b[32m', + yellow: '\x1b[33m', + red: '\x1b[31m' +}; diff --git a/src/utils/logger/logger.ts b/src/utils/logger/logger.ts new file mode 100644 index 0000000..2426082 --- /dev/null +++ b/src/utils/logger/logger.ts @@ -0,0 +1,111 @@ +/** + * Logger singleton with console and file output + */ + +import { config } from '$config'; +import { colors } from './colors.ts'; +import type { LogOptions, LogEntry } from './types.ts'; + +class Logger { + private formatTimestamp(): string { + const timestamp = new Date().toISOString(); + return `${colors.grey}${timestamp}${colors.reset}`; + } + + private formatLevel(level: string, color: string): string { + return `${color}${level.padEnd(5)}${colors.reset}`; + } + + private formatSource(source?: string): string { + if (!source) return ''; + return `${colors.grey}[${source}]${colors.reset}`; + } + + private formatMeta(meta?: unknown): string { + if (!meta) return ''; + return `${colors.grey}${JSON.stringify(meta)}${colors.reset}`; + } + + private async log( + level: string, + color: string, + message: string, + options?: LogOptions + ): Promise { + const timestamp = new Date().toISOString(); + + // Console output (colored) + const consoleParts = [ + this.formatTimestamp(), + this.formatLevel(level, color), + message, + options?.source ? this.formatSource(options.source) : '', + options?.meta ? this.formatMeta(options.meta) : '' + ].filter(Boolean); + + console.log(consoleParts.join(' | ')); + + // File output (JSON) + const logEntry: LogEntry = { + timestamp, + level, + message, + ...(options?.source ? { source: options.source } : {}), + ...(options?.meta ? { meta: options.meta } : {}) + }; + + try { + await Deno.writeTextFile(config.paths.logFile, JSON.stringify(logEntry) + '\n', { + append: true + }); + } catch (error) { + // If file write fails, at least we have console output + console.error('Failed to write to log file:', error); + } + } + + async debug(message: string, options?: LogOptions): Promise { + await this.log('DEBUG', colors.cyan, message, options); + } + + async info(message: string, options?: LogOptions): Promise { + await this.log('INFO', colors.green, message, options); + } + + async warn(message: string, options?: LogOptions): Promise { + await this.log('WARN', colors.yellow, message, options); + } + + async error(message: string, options?: LogOptions): Promise { + await this.log('ERROR', colors.red, message, options); + } + + async errorWithTrace(message: string, error?: Error, options?: LogOptions): Promise { + await this.log('ERROR', colors.red, message, options); + + // Print stack trace to console + if (error?.stack) { + console.log(`${colors.grey}${error.stack}${colors.reset}`); + } + + // Write stack trace to file + if (error?.stack) { + const traceEntry: LogEntry = { + timestamp: new Date().toISOString(), + level: 'ERROR', + message: 'Stack trace', + meta: { stack: error.stack } + }; + + try { + await Deno.writeTextFile(config.paths.logFile, JSON.stringify(traceEntry) + '\n', { + append: true + }); + } catch (writeError) { + console.error('Failed to write stack trace to log file:', writeError); + } + } + } +} + +export const logger = new Logger(); diff --git a/src/utils/logger/startup.ts b/src/utils/logger/startup.ts new file mode 100644 index 0000000..d101dd1 --- /dev/null +++ b/src/utils/logger/startup.ts @@ -0,0 +1,26 @@ +/** + * Startup banner and logging + */ + +import { logger } from './logger.ts'; + +const BANNER = String.raw` + _____.__.__ +_____________ _____/ ____\__| | _____ ______________ +\____ \_ __ \/ _ \ __\| | | \__ \\_ __ \_ __ \ +| |_> > | \( <_> ) | | | |__/ __ \| | \/| | \/ +| __/|__| \____/|__| |__|____(____ /__| |__| +|__| \/ +`; + +export async function logStartup(): Promise { + // Print banner (not logged to file, just console) + console.log(BANNER); + + // Log startup info + await logger.info('Server started'); + + // Log environment + const env = Deno.env.get('NODE_ENV') || Deno.env.get('DENO_ENV') || 'development'; + await logger.info(`Environment: ${env}`); +} diff --git a/src/utils/logger/types.ts b/src/utils/logger/types.ts new file mode 100644 index 0000000..4af54c0 --- /dev/null +++ b/src/utils/logger/types.ts @@ -0,0 +1,18 @@ +/** + * Logger types and interfaces + */ + +export interface LogOptions { + /** Optional metadata to include with the log */ + meta?: unknown; + /** Optional source/context tag (e.g., "database", "api") */ + source?: string; +} + +export interface LogEntry { + timestamp: string; + level: string; + message: string; + source?: string; + meta?: unknown; +} diff --git a/static/robots.txt b/static/robots.txt deleted file mode 100644 index b6dd667..0000000 --- a/static/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# allow crawling everything by default -User-agent: * -Disallow: diff --git a/svelte.config.js b/svelte.config.js index 9aa6df6..c8ba8db 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,13 +1,18 @@ -import adapter from '@deno/svelte-adapter'; +import adapter from 'sveltekit-adapter-deno'; import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; /** @type {import('@sveltejs/kit').Config} */ const config = { - preprocess: vitePreprocess(), - - kit: { - adapter: adapter() - } + preprocess: vitePreprocess(), + + kit: { + adapter: adapter({ + usage: 'deno-compile' + }), + alias: { + $config: './src/utils/config/config.ts' + } + } }; -export default config; \ No newline at end of file +export default config; diff --git a/tsconfig.json b/tsconfig.json index a5567ee..f83ac33 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,10 @@ "skipLibCheck": true, "sourceMap": true, "strict": true, - "moduleResolution": "bundler" + "moduleResolution": "bundler", + "lib": ["ES2022", "DOM"], + "allowImportingTsExtensions": true, + "noEmit": true } // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files diff --git a/vite.config.ts b/vite.config.ts index 2d35c4f..28c5bf7 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -3,5 +3,8 @@ import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vite'; export default defineConfig({ - plugins: [tailwindcss(), sveltekit()] + plugins: [tailwindcss(), sveltekit()], + server: { + port: 6969 + } });