diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 0000000..54f5dc4 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,2 @@ +.build/ +tests/ diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..a3efe22 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,13 @@ +FROM golang:1.24-alpine AS build + +WORKDIR /app + +COPY . . +RUN go build -o nuchat fergus.molloy.xyz/nuchat + +FROM scratch +WORKDIR /app + +COPY --from=build /app/nuchat . + +ENTRYPOINT ["/app/nuchat"] diff --git a/backend/Justfile b/backend/Justfile index 0ec473c..1724716 100644 --- a/backend/Justfile +++ b/backend/Justfile @@ -1,6 +1,21 @@ -build: - go build -o .build/nuchat fergus.molloy.xyz/nuchat +GO_TEST := "gotestsum --format=testname --" + +dirs: + @mkdir -p .build/tests + +build: dirs + go build -o .build/nuchat fergus.molloy.xyz/nuchat run: build ./.build/nuchat +test: unit integration coverage + +integration: + {{GO_TEST}} ./tests/... | tee .build/tests/integration.log + +unit: + {{GO_TEST}} -race $(go list ./... | grep -v "/tests") | tee .build/tests/unit.log + +coverage: + {{GO_TEST}} $(go list ./... | grep -v "/tests") -coverprofile .build/tests/coverprofile.txt | tee .build/tests/coverage.log diff --git a/backend/main.go b/backend/main.go index c048119..375bbe9 100644 --- a/backend/main.go +++ b/backend/main.go @@ -3,5 +3,5 @@ package main import "fmt" func main() { - fmt.Println("hello world") + fmt.Println("hello world 3") } diff --git a/backend/tests/hello_test.go b/backend/tests/hello_test.go new file mode 100644 index 0000000..01ceef3 --- /dev/null +++ b/backend/tests/hello_test.go @@ -0,0 +1,7 @@ +package tests + +import "testing" + +func TestHello(t *testing.T) { + +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..9fa0222 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,22 @@ +services: + ui: + build: ./ui + ports: + - "5173:5173" + backend: + build: ./backend + #ports: + #- "7000:7000" + db: + image: postgres:17-alpine + ports: + - "5432:5432" + environment: + POSTGRES_DB: nuchat + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + volumes: + - db-data:/var/lib/postgresql/data + +volumes: + db-data: diff --git a/ui/.dockerignore b/ui/.dockerignore new file mode 100644 index 0000000..b38db2f --- /dev/null +++ b/ui/.dockerignore @@ -0,0 +1,2 @@ +node_modules/ +build/ diff --git a/ui/Dockerfile b/ui/Dockerfile new file mode 100644 index 0000000..b7ad638 --- /dev/null +++ b/ui/Dockerfile @@ -0,0 +1,31 @@ +FROM node:24-slim AS base + +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable + +FROM base AS prod +WORKDIR /app + +COPY pnpm-lock.yaml . +RUN pnpm fetch --prod + +FROM base AS build +WORKDIR /app + +COPY pnpm-lock.yaml . +COPY package.json . +RUN pnpm install + +COPY . . +RUN pnpm run build + +FROM base AS runner +COPY --from=prod /app/node_modules /app/node_modules +COPY --from=build /app/build build/ + +EXPOSE 3000 + +ENV NODE_ENV=production + +CMD ["node", "build"] diff --git a/ui/package.json b/ui/package.json index ad0082f..8b505f4 100644 --- a/ui/package.json +++ b/ui/package.json @@ -21,6 +21,7 @@ "@eslint/js": "^9.18.0", "@playwright/test": "^1.49.1", "@sveltejs/adapter-auto": "^6.0.0", + "@sveltejs/adapter-node": "^5.2.13", "@sveltejs/kit": "^2.22.0", "@sveltejs/vite-plugin-svelte": "^6.0.0", "@tailwindcss/vite": "^4.0.0", @@ -44,6 +45,7 @@ }, "pnpm": { "onlyBuiltDependencies": [ + "@tailwindcss/oxide", "esbuild" ] } diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml index 9ebc8d2..52a8963 100644 --- a/ui/pnpm-lock.yaml +++ b/ui/pnpm-lock.yaml @@ -20,6 +20,9 @@ importers: '@sveltejs/adapter-auto': specifier: ^6.0.0 version: 6.0.1(@sveltejs/kit@2.24.0(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1)))(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1))) + '@sveltejs/adapter-node': + specifier: ^5.2.13 + version: 5.2.13(@sveltejs/kit@2.24.0(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1)))(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1))) '@sveltejs/kit': specifier: ^2.22.0 version: 2.24.0(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1)))(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1)) @@ -359,6 +362,42 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@rollup/plugin-commonjs@28.0.6': + resolution: {integrity: sha512-XSQB1K7FUU5QP+3lOQmVCE3I0FcbbNvmNT4VJSj93iUjayaARrTQeoRdiYQoftAJBLrR9t2agwAd3ekaTgHNlw==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-json@6.1.0': + resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-node-resolve@16.0.1': + resolution: {integrity: sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/pluginutils@5.2.0': + resolution: {integrity: sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/rollup-android-arm-eabi@4.45.1': resolution: {integrity: sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==} cpu: [arm] @@ -469,6 +508,11 @@ packages: peerDependencies: '@sveltejs/kit': ^2.0.0 + '@sveltejs/adapter-node@5.2.13': + resolution: {integrity: sha512-yS2TVFmIrxjGhYaV5/iIUrJ3mJl6zjaYn0lBD70vTLnYvJeqf3cjvLXeXCUCuYinhSBoyF4DpfGla49BnIy7sQ==} + peerDependencies: + '@sveltejs/kit': ^2.4.0 + '@sveltejs/kit@2.24.0': resolution: {integrity: sha512-6aCsU6PwxB4CQBJEvLnOoSv8hoviZWDVTKDTzQoERG6vpIHeXJufVWQlyaOXrdSlqBiwknHm0nQT/S/Nn3518A==} engines: {node: '>=18.13'} @@ -611,6 +655,9 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + '@typescript-eslint/eslint-plugin@8.37.0': resolution: {integrity: sha512-jsuVWeIkb6ggzB+wPCsR4e6loj+rM72ohW6IBn2C+5NCvfUVY8s33iFPySSVXqtm5Hu29Ne/9bnA0JmyLmgenA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -809,6 +856,9 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -935,6 +985,9 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -999,6 +1052,9 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1025,6 +1081,10 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1041,6 +1101,10 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -1049,10 +1113,16 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + is-reference@3.0.3: resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} @@ -1255,6 +1325,9 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -1413,6 +1486,11 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -1473,6 +1551,10 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + svelte-check@4.2.2: resolution: {integrity: sha512-1+31EOYZ7NKN0YDMKusav2hhEoA51GD9Ws6o//0SphMT0ve9mBTsTUEX7OmDMadUP3KjNHsSKtJrqdSaD8CrGQ==} engines: {node: '>= 18.0.0'} @@ -1885,6 +1967,42 @@ snapshots: '@polka/url@1.0.0-next.29': {} + '@rollup/plugin-commonjs@28.0.6(rollup@4.45.1)': + dependencies: + '@rollup/pluginutils': 5.2.0(rollup@4.45.1) + commondir: 1.0.1 + estree-walker: 2.0.2 + fdir: 6.4.6(picomatch@4.0.3) + is-reference: 1.2.1 + magic-string: 0.30.17 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.45.1 + + '@rollup/plugin-json@6.1.0(rollup@4.45.1)': + dependencies: + '@rollup/pluginutils': 5.2.0(rollup@4.45.1) + optionalDependencies: + rollup: 4.45.1 + + '@rollup/plugin-node-resolve@16.0.1(rollup@4.45.1)': + dependencies: + '@rollup/pluginutils': 5.2.0(rollup@4.45.1) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.10 + optionalDependencies: + rollup: 4.45.1 + + '@rollup/pluginutils@5.2.0(rollup@4.45.1)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.45.1 + '@rollup/rollup-android-arm-eabi@4.45.1': optional: true @@ -1953,6 +2071,14 @@ snapshots: dependencies: '@sveltejs/kit': 2.24.0(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1)))(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1)) + '@sveltejs/adapter-node@5.2.13(@sveltejs/kit@2.24.0(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1)))(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1)))': + dependencies: + '@rollup/plugin-commonjs': 28.0.6(rollup@4.45.1) + '@rollup/plugin-json': 6.1.0(rollup@4.45.1) + '@rollup/plugin-node-resolve': 16.0.1(rollup@4.45.1) + '@sveltejs/kit': 2.24.0(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1)))(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1)) + rollup: 4.45.1 + '@sveltejs/kit@2.24.0(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1)))(svelte@5.36.2)(vite@7.0.4(jiti@2.4.2)(lightningcss@1.30.1))': dependencies: '@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0) @@ -2093,6 +2219,8 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/resolve@1.20.2': {} + '@typescript-eslint/eslint-plugin@8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -2328,6 +2456,8 @@ snapshots: color-name@1.1.4: {} + commondir@1.0.1: {} + concat-map@0.0.1: {} cookie@0.6.0: {} @@ -2491,6 +2621,8 @@ snapshots: estraverse@5.3.0: {} + estree-walker@2.0.2: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.8 @@ -2547,6 +2679,8 @@ snapshots: fsevents@2.3.3: optional: true + function-bind@1.1.2: {} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -2565,6 +2699,10 @@ snapshots: has-flag@4.0.0: {} + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + ignore@5.3.2: {} ignore@7.0.5: {} @@ -2576,14 +2714,24 @@ snapshots: imurmurhash@0.1.4: {} + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + is-extglob@2.1.1: {} is-glob@4.0.3: dependencies: is-extglob: 2.1.1 + is-module@1.0.0: {} + is-number@7.0.0: {} + is-reference@1.2.1: + dependencies: + '@types/estree': 1.0.8 + is-reference@3.0.3: dependencies: '@types/estree': 1.0.8 @@ -2740,6 +2888,8 @@ snapshots: path-key@3.1.1: {} + path-parse@1.0.7: {} + pathe@2.0.3: {} pathval@2.0.1: {} @@ -2815,6 +2965,12 @@ snapshots: resolve-from@4.0.0: {} + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + reusify@1.1.0: {} rollup@4.45.1: @@ -2885,6 +3041,8 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} + svelte-check@4.2.2(picomatch@4.0.3)(svelte@5.36.2)(typescript@5.8.3): dependencies: '@jridgewell/trace-mapping': 0.3.29 diff --git a/ui/svelte.config.js b/ui/svelte.config.js index 1295460..e0a641e 100644 --- a/ui/svelte.config.js +++ b/ui/svelte.config.js @@ -1,4 +1,4 @@ -import adapter from '@sveltejs/adapter-auto'; +import adapter from '@sveltejs/adapter-node'; import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; /** @type {import('@sveltejs/kit').Config} */