diff --git a/backend/.gitattributes b/backend/.gitattributes deleted file mode 100644 index 8af972c..0000000 --- a/backend/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/gradlew text eol=lf -*.bat text eol=crlf -*.jar binary diff --git a/backend/.gitignore b/backend/.gitignore index 9279e3c..0de1db4 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1,40 +1,46 @@ -HELP.md -.gradle -build/ -!gradle/wrapper/gradle-wrapper.jar -!**/src/main/**/build/ -!**/src/test/**/build/ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache -bin/ -!**/src/main/**/bin/ -!**/src/test/**/bin/ +# dependencies +/node_modules +/.pnp +.pnp.js -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr -out/ -!**/src/main/**/out/ -!**/src/test/**/out/ +# testing +/coverage -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ +# next.js +/.next/ +/out/ -### VS Code ### -.vscode/ +# production +/build -### Direnv ### -.direnv/ \ No newline at end of file +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel + +**/*.trace +**/*.zip +**/*.tar.gz +**/*.tgz +**/*.log +package-lock.json +**/*.bun + +# Nix +.direnv +/src/generated/prisma diff --git a/backend/README.md b/backend/README.md new file mode 100644 index 0000000..688c87e --- /dev/null +++ b/backend/README.md @@ -0,0 +1,15 @@ +# Elysia with Bun runtime + +## Getting Started +To get started with this template, simply paste this command into your terminal: +```bash +bun create elysia ./elysia-example +``` + +## Development +To start the development server run: +```bash +bun run dev +``` + +Open http://localhost:3000/ with your browser to see the result. \ No newline at end of file diff --git a/backend/build.gradle b/backend/build.gradle deleted file mode 100644 index 136d23d..0000000 --- a/backend/build.gradle +++ /dev/null @@ -1,49 +0,0 @@ -plugins { - id 'java' - id 'org.springframework.boot' version '4.0.5' - id 'io.spring.dependency-management' version '1.1.7' -} - -group = 'net.kpuig.shoebill' -version = '0.0.1-SNAPSHOT' -description = 'Shoebill REST Server' - -java { - toolchain { - languageVersion = JavaLanguageVersion.of(25) - } -} - -configurations { - compileOnly { - extendsFrom annotationProcessor - } -} - -repositories { - mavenCentral() -} - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-actuator' - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-webmvc' - implementation 'org.springframework.boot:spring-boot-starter-websocket' - implementation 'org.springframework.boot:spring-boot-h2console' - implementation 'org.springframework.boot:spring-boot-autoconfigure-processor' - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:3.0.3' - //implementation 'org.springframework.boot:spring-boot-starter-security' - //implementation 'org.springframework.boot:spring-boot-starter-security-oauth2-resource-server' - compileOnly 'org.projectlombok:lombok' - runtimeOnly 'org.postgresql:postgresql' - runtimeOnly 'com.h2database:h2:2.4.240' - annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa-test' - testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test' - testImplementation 'org.springframework.boot:spring-boot-starter-websocket-test' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' -} - -tasks.named('test') { - useJUnitPlatform() -} diff --git a/backend/bun.lock b/backend/bun.lock new file mode 100644 index 0000000..e9dcd6a --- /dev/null +++ b/backend/bun.lock @@ -0,0 +1,295 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "app", + "dependencies": { + "@prisma/adapter-pg": "^7.8.0", + "@prisma/client": "^7.8.0", + "dotenv": "^17.4.2", + "elysia": "latest", + "pg": "^8.20.0", + "zod": "^4.3.6", + }, + "devDependencies": { + "@types/pg": "^8.20.0", + "bun-types": "latest", + "prisma": "^7.8.0", + }, + }, + }, + "packages": { + "@borewit/text-codec": ["@borewit/text-codec@0.2.2", "", {}, "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ=="], + + "@electric-sql/pglite": ["@electric-sql/pglite@0.4.1", "", {}, "sha512-mZ9NzzUSYPOCnxHH1oAHPRzoMFJHY472raDKwXl/+6oPbpdJ7g8LsCN4FSaIIfkiCKHhb3iF/Zqo3NYxaIhU7Q=="], + + "@electric-sql/pglite-socket": ["@electric-sql/pglite-socket@0.1.1", "", { "peerDependencies": { "@electric-sql/pglite": "0.4.1" }, "bin": { "pglite-server": "dist/scripts/server.js" } }, "sha512-p2hoXw3Z3LQHwTeikdZNsFBOvXGqKY2hk51BBw+8NKND8eoH+8LFOtW9Z8CQKmTJ2qqGYu82ipqiyFZOTTXNfw=="], + + "@electric-sql/pglite-tools": ["@electric-sql/pglite-tools@0.3.1", "", { "peerDependencies": { "@electric-sql/pglite": "0.4.1" } }, "sha512-C+T3oivmy9bpQvSxVqXA1UDY8cB9Eb9vZHL9zxWwEUfDixbXv4G3r2LjoTdR33LD8aomR3O9ZXEO3XEwr/cUCA=="], + + "@hono/node-server": ["@hono/node-server@1.19.11", "", { "peerDependencies": { "hono": "^4" } }, "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g=="], + + "@kurkle/color": ["@kurkle/color@0.3.4", "", {}, "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w=="], + + "@prisma/adapter-pg": ["@prisma/adapter-pg@7.8.0", "", { "dependencies": { "@prisma/driver-adapter-utils": "7.8.0", "@types/pg": "^8.16.0", "pg": "^8.16.3", "postgres-array": "3.0.4" } }, "sha512-ygb3UkerK3v8MDpXVgCISdRNDozpxh6+JVJgiIGbSr5KBgz10LLf5ejUskPGoXlsIjxsOu6nuy1JVQr2EKGSlg=="], + + "@prisma/client": ["@prisma/client@7.8.0", "", { "dependencies": { "@prisma/client-runtime-utils": "7.8.0" }, "peerDependencies": { "prisma": "*", "typescript": ">=5.4.0" }, "optionalPeers": ["prisma", "typescript"] }, "sha512-HFp3Dawv/3sU3JtlPha90IB+48lS7zHiH4LKZPjmcE8YH5P9DOXGPvo8dqOtO7MqLDd1p2hOWMcFlRT1DMblHw=="], + + "@prisma/client-runtime-utils": ["@prisma/client-runtime-utils@7.8.0", "", {}, "sha512-5NQZztQ0oY/ADFkmd9gPuweH5A1/CCY8YQPorLLO0Mu6a87mY5gsnDkzmFmIHs9NFaLnZojzgddFVN4RpKYrdw=="], + + "@prisma/config": ["@prisma/config@7.8.0", "", { "dependencies": { "c12": "3.3.4", "deepmerge-ts": "7.1.5", "effect": "3.20.0", "empathic": "2.0.0" } }, "sha512-HFESzd9rx2ZQxlK+TL7tu1HPvCqrHiL6LCxYykI2c34mvaUuIVVl3lYuicJD/MNnzgPnyeBEMlK4WTomJCV5jw=="], + + "@prisma/debug": ["@prisma/debug@7.8.0", "", {}, "sha512-p+QZReysDUqXC+mk17q9a+Y/qzh4c2KYliDK30buYUyfrGeTGSyfmc0AIrJRhZJrLHhRiJa9Au/J72h3C+szvA=="], + + "@prisma/dev": ["@prisma/dev@0.24.3", "", { "dependencies": { "@electric-sql/pglite": "0.4.1", "@electric-sql/pglite-socket": "0.1.1", "@electric-sql/pglite-tools": "0.3.1", "@hono/node-server": "1.19.11", "@prisma/get-platform": "7.2.0", "@prisma/query-plan-executor": "7.2.0", "@prisma/streams-local": "0.1.2", "foreground-child": "3.3.1", "get-port-please": "3.2.0", "hono": "^4.12.8", "http-status-codes": "2.3.0", "pathe": "2.0.3", "proper-lockfile": "4.1.2", "remeda": "2.33.4", "std-env": "3.10.0", "valibot": "1.2.0", "zeptomatch": "2.1.0" } }, "sha512-ffHlQuKXZiaDt9Go0OnCTdJZrHxK0k7omJKNV86/VjpsXu5EIHZLK0T7JSWgvNlJwh56kW9JFu9v0qJciFzepg=="], + + "@prisma/driver-adapter-utils": ["@prisma/driver-adapter-utils@7.8.0", "", { "dependencies": { "@prisma/debug": "7.8.0" } }, "sha512-/Q13o0ZT0rjc1Xk0Q9KhZYwuq2EW/vSbWUBKfgEKkaCuB/Sg6bqnjmTZqC5cD4d6y1vfFAEwBRzfzoSMIVJ55A=="], + + "@prisma/engines": ["@prisma/engines@7.8.0", "", { "dependencies": { "@prisma/debug": "7.8.0", "@prisma/engines-version": "7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a", "@prisma/fetch-engine": "7.8.0", "@prisma/get-platform": "7.8.0" } }, "sha512-jx3rCnNNrt5uzbkKlegtQ2GZHxSlihMCzutgT/BP6UIDF1r9tDI39hV/0T/cHZgzJ3ELbuQPXlVZy+Y1n0pcgw=="], + + "@prisma/engines-version": ["@prisma/engines-version@7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a", "", {}, "sha512-fJPQxCkLgA5EayWaW8eArgCvjJ+N+Kz3VyeNKMEeYiQC4alNkxRKFVAGxv/ZUzuJISKqdw+zGeDbS6mn6RCPOA=="], + + "@prisma/fetch-engine": ["@prisma/fetch-engine@7.8.0", "", { "dependencies": { "@prisma/debug": "7.8.0", "@prisma/engines-version": "7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a", "@prisma/get-platform": "7.8.0" } }, "sha512-gwB0Euiz/DDRyxFRpLXYlK3RfaZUj1c5dAYMuhZYfApg7arknJlcb9bIsOHDppJmbqYaVA+yBIiFMDBfprsNPQ=="], + + "@prisma/get-platform": ["@prisma/get-platform@7.2.0", "", { "dependencies": { "@prisma/debug": "7.2.0" } }, "sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA=="], + + "@prisma/query-plan-executor": ["@prisma/query-plan-executor@7.2.0", "", {}, "sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ=="], + + "@prisma/streams-local": ["@prisma/streams-local@0.1.2", "", { "dependencies": { "ajv": "^8.12.0", "better-result": "^2.7.0", "env-paths": "^3.0.0", "proper-lockfile": "^4.1.2" } }, "sha512-l49yTxKKF2odFxaAXTmwmkBKL3+bVQ1tFOooGifu4xkdb9NMNLxHj27XAhTylWZod8I+ISGM5erU1xcl/oBCtg=="], + + "@prisma/studio-core": ["@prisma/studio-core@0.27.3", "", { "dependencies": { "@radix-ui/react-toggle": "1.1.10", "chart.js": "4.5.1" }, "peerDependencies": { "@types/react": "^18.0.0 || ^19.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-AADjNFPdsrglxHQVTmHFqv6DuKQZ5WY4p5/gVFY017twvNrSwpLJ9lqUbYYxEu2W7nbvVxTZA8deJ8LseNALsw=="], + + "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="], + + "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="], + + "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], + + "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], + + "@radix-ui/react-toggle": ["@radix-ui/react-toggle@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ=="], + + "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="], + + "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="], + + "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="], + + "@sinclair/typebox": ["@sinclair/typebox@0.34.49", "", {}, "sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A=="], + + "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + + "@tokenizer/inflate": ["@tokenizer/inflate@0.4.1", "", { "dependencies": { "debug": "^4.4.3", "token-types": "^6.1.1" } }, "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA=="], + + "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], + + "@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + + "@types/pg": ["@types/pg@8.20.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow=="], + + "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="], + + "ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], + + "aws-ssl-profiles": ["aws-ssl-profiles@1.1.2", "", {}, "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g=="], + + "better-result": ["better-result@2.8.2", "", {}, "sha512-YOf0VSj5nUPI27doTtXF+BBnsiRq3qY7avHqfIWnppxTLGyvkLq1QV2RTxkwoZwJ60ywLfZ0raFF4J/G886i7A=="], + + "bun-types": ["bun-types@1.3.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-QXKeHLlOLqQX9LgYaHJfzdBaV21T63HhFJnvuRCcjZiaUDpbs5ED1MgxbMra71CsryN/1dAoXuJJJwIv/2drVA=="], + + "c12": ["c12@3.3.4", "", { "dependencies": { "chokidar": "^5.0.0", "confbox": "^0.2.4", "defu": "^6.1.6", "dotenv": "^17.3.1", "exsolve": "^1.0.8", "giget": "^3.2.0", "jiti": "^2.6.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.1.0", "pkg-types": "^2.3.0", "rc9": "^3.0.1" }, "peerDependencies": { "magicast": "*" }, "optionalPeers": ["magicast"] }, "sha512-cM0ApFQSBXuourJejzwv/AuPRvAxordTyParRVcHjjtXirtkzM0uK2L9TTn9s0cXZbG7E55jCivRQzoxYmRAlA=="], + + "chart.js": ["chart.js@4.5.1", "", { "dependencies": { "@kurkle/color": "^0.3.0" } }, "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw=="], + + "chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], + + "confbox": ["confbox@0.2.4", "", {}, "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ=="], + + "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "deepmerge-ts": ["deepmerge-ts@7.1.5", "", {}, "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw=="], + + "defu": ["defu@6.1.7", "", {}, "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ=="], + + "denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="], + + "destr": ["destr@2.0.5", "", {}, "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="], + + "dotenv": ["dotenv@17.4.2", "", {}, "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw=="], + + "effect": ["effect@3.20.0", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-qMLfDJscrNG8p/aw+IkT9W7fgj50Z4wG5bLBy0Txsxz8iUHjDIkOgO3SV0WZfnQbNG2VJYb0b+rDLMrhM4+Krw=="], + + "elysia": ["elysia@1.4.28", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.7", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-Vrx8sBnvq8squS/3yNBzR1jBXI+SgmnmvwawPjNuEHndUe5l1jV2Gp6JJ4ulDkEB8On6bWmmuyPpA+bq4t+WYg=="], + + "empathic": ["empathic@2.0.0", "", {}, "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA=="], + + "env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="], + + "exact-mirror": ["exact-mirror@0.2.7", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-+MeEmDcLA4o/vjK2zujgk+1VTxPR4hdp23qLqkWfStbECtAq9gmsvQa3LW6z/0GXZyHJobrCnmy1cdeE7BjsYg=="], + + "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="], + + "fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="], + + "fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], + + "file-type": ["file-type@22.0.1", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.5", "token-types": "^6.1.2", "uint8array-extras": "^1.5.0" } }, "sha512-ww5Mhre0EE+jmBvOXTmXAbEMuZE7uX4a3+oRCQFNj8w++g3ev913N6tXQz0XTXbueQ5TWQfm6BdaViEHHn8bhA=="], + + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], + + "generate-function": ["generate-function@2.3.1", "", { "dependencies": { "is-property": "^1.0.2" } }, "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ=="], + + "get-port-please": ["get-port-please@3.2.0", "", {}, "sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A=="], + + "giget": ["giget@3.2.0", "", { "bin": { "giget": "dist/cli.mjs" } }, "sha512-GvHTWcykIR/fP8cj8dMpuMMkvaeJfPvYnhq0oW+chSeIr+ldX21ifU2Ms6KBoyKZQZmVaUAAhQ2EZ68KJF8a7A=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "grammex": ["grammex@3.1.12", "", {}, "sha512-6ufJOsSA7LcQehIJNCO7HIBykfM7DXQual0Ny780/DEcJIpBlHRvcqEBWGPYd7hrXL2GJ3oJI1MIhaXjWmLQOQ=="], + + "graphmatch": ["graphmatch@1.1.1", "", {}, "sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg=="], + + "hono": ["hono@4.12.14", "", {}, "sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w=="], + + "http-status-codes": ["http-status-codes@2.3.0", "", {}, "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA=="], + + "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], + + "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + + "is-property": ["is-property@1.0.2", "", {}, "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], + + "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], + + "lru.min": ["lru.min@1.1.4", "", {}, "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA=="], + + "memoirist": ["memoirist@0.4.0", "", {}, "sha512-zxTgA0mSYELa66DimuNQDvyLq36AwDlTuVRbnQtB+VuTcKWm5Qc4z3WkSpgsFWHNhexqkIooqpv4hdcqrX5Nmg=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "mysql2": ["mysql2@3.15.3", "", { "dependencies": { "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", "generate-function": "^2.3.1", "iconv-lite": "^0.7.0", "long": "^5.2.1", "lru.min": "^1.0.0", "named-placeholders": "^1.1.3", "seq-queue": "^0.0.5", "sqlstring": "^2.3.2" } }, "sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg=="], + + "named-placeholders": ["named-placeholders@1.1.6", "", { "dependencies": { "lru.min": "^1.1.0" } }, "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w=="], + + "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], + + "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "perfect-debounce": ["perfect-debounce@2.1.0", "", {}, "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g=="], + + "pg": ["pg@8.20.0", "", { "dependencies": { "pg-connection-string": "^2.12.0", "pg-pool": "^3.13.0", "pg-protocol": "^1.13.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.3.0" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA=="], + + "pg-cloudflare": ["pg-cloudflare@1.3.0", "", {}, "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ=="], + + "pg-connection-string": ["pg-connection-string@2.12.0", "", {}, "sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ=="], + + "pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="], + + "pg-pool": ["pg-pool@3.13.0", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA=="], + + "pg-protocol": ["pg-protocol@1.13.0", "", {}, "sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w=="], + + "pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="], + + "pgpass": ["pgpass@1.0.5", "", { "dependencies": { "split2": "^4.1.0" } }, "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug=="], + + "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], + + "postgres": ["postgres@3.4.7", "", {}, "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw=="], + + "postgres-array": ["postgres-array@3.0.4", "", {}, "sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ=="], + + "postgres-bytea": ["postgres-bytea@1.0.1", "", {}, "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ=="], + + "postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="], + + "postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="], + + "prisma": ["prisma@7.8.0", "", { "dependencies": { "@prisma/config": "7.8.0", "@prisma/dev": "0.24.3", "@prisma/engines": "7.8.0", "@prisma/studio-core": "0.27.3", "mysql2": "3.15.3", "postgres": "3.4.7" }, "peerDependencies": { "better-sqlite3": ">=9.0.0", "typescript": ">=5.4.0" }, "optionalPeers": ["better-sqlite3", "typescript"], "bin": { "prisma": "build/index.js" } }, "sha512-yfN4yrw7HV9kEJhoy1+jgah0jafEIQsf7uWouSsM8MvJtlubsk+kM7AIBWZ8+GJl74Yj3c+nbYqBkMOxtsZ3Lw=="], + + "proper-lockfile": ["proper-lockfile@4.1.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", "signal-exit": "^3.0.2" } }, "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA=="], + + "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="], + + "rc9": ["rc9@3.0.1", "", { "dependencies": { "defu": "^6.1.6", "destr": "^2.0.5" } }, "sha512-gMDyleLWVE+i6Sgtc0QbbY6pEKqYs97NGi6isHQPqYlLemPoO8dxQ3uGi0f4NiP98c+jMW6cG1Kx9dDwfvqARQ=="], + + "react": ["react@19.2.5", "", {}, "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA=="], + + "react-dom": ["react-dom@19.2.5", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.5" } }, "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag=="], + + "readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], + + "remeda": ["remeda@2.33.4", "", {}, "sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ=="], + + "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + + "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], + + "seq-queue": ["seq-queue@0.0.5", "", {}, "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], + + "sqlstring": ["sqlstring@2.3.3", "", {}, "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg=="], + + "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="], + + "strtok3": ["strtok3@10.3.5", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA=="], + + "token-types": ["token-types@6.1.2", "", { "dependencies": { "@borewit/text-codec": "^0.2.1", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww=="], + + "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="], + + "undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], + + "valibot": ["valibot@1.2.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], + + "zeptomatch": ["zeptomatch@2.1.0", "", { "dependencies": { "grammex": "^3.1.11", "graphmatch": "^1.1.0" } }, "sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA=="], + + "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], + + "@prisma/engines/@prisma/get-platform": ["@prisma/get-platform@7.8.0", "", { "dependencies": { "@prisma/debug": "7.8.0" } }, "sha512-WlxgRGnolL8VH2EmkH1R/DkKNr/mVdS3G2h42IZFFZ3eUrH9OT6t73kIOSlkkrv50wG123Iq8d96ufv5LlZktw=="], + + "@prisma/fetch-engine/@prisma/get-platform": ["@prisma/get-platform@7.8.0", "", { "dependencies": { "@prisma/debug": "7.8.0" } }, "sha512-WlxgRGnolL8VH2EmkH1R/DkKNr/mVdS3G2h42IZFFZ3eUrH9OT6t73kIOSlkkrv50wG123Iq8d96ufv5LlZktw=="], + + "@prisma/get-platform/@prisma/debug": ["@prisma/debug@7.2.0", "", {}, "sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw=="], + + "pg-types/postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="], + + "proper-lockfile/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + } +} diff --git a/backend/flake.nix b/backend/flake.nix index 86a1407..d65fefe 100644 --- a/backend/flake.nix +++ b/backend/flake.nix @@ -10,25 +10,11 @@ in { devShell = pkgs.mkShell { buildInputs = with pkgs; [ - jdk25 - gradle - keycloak + bun + prisma_7 ]; shellHook = '' - mkdir -p .vscode - - cat < .vscode/settings.json - { - "java.compile.nullAnalysis.mode": "disabled", - "gradle.reuseTerminals": "all", - "java.import.gradle.java.home": "${pkgs.jdk25}/lib/openjdk", - "java.import.gradle.home": "${pkgs.gradle}/libexec/gradle", - "java.import.gradle.wrapper.enabled": false - } - EOF - - - echo Java Flake development environment ready! + echo Bun development environment ready! ''; }; } diff --git a/backend/gradle/wrapper/gradle-wrapper.jar b/backend/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 61285a6..0000000 Binary files a/backend/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/backend/gradle/wrapper/gradle-wrapper.properties b/backend/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 19a6bde..0000000 --- a/backend/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/backend/gradlew b/backend/gradlew deleted file mode 100755 index adff685..0000000 --- a/backend/gradlew +++ /dev/null @@ -1,248 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/backend/gradlew.bat b/backend/gradlew.bat deleted file mode 100644 index c4bdd3a..0000000 --- a/backend/gradlew.bat +++ /dev/null @@ -1,93 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 0000000..b477902 --- /dev/null +++ b/backend/package.json @@ -0,0 +1,22 @@ +{ + "name": "app", + "version": "1.0.50", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "dev": "bun run --watch src/index.ts" + }, + "dependencies": { + "@prisma/adapter-pg": "^7.8.0", + "@prisma/client": "^7.8.0", + "dotenv": "^17.4.2", + "elysia": "latest", + "pg": "^8.20.0", + "zod": "^4.3.6" + }, + "devDependencies": { + "@types/pg": "^8.20.0", + "bun-types": "latest", + "prisma": "^7.8.0" + }, + "module": "src/index.js" +} diff --git a/backend/prisma.config.ts b/backend/prisma.config.ts new file mode 100644 index 0000000..831a20f --- /dev/null +++ b/backend/prisma.config.ts @@ -0,0 +1,14 @@ +// This file was generated by Prisma, and assumes you have installed the following: +// npm install --save-dev prisma dotenv +import "dotenv/config"; +import { defineConfig } from "prisma/config"; + +export default defineConfig({ + schema: "prisma/schema.prisma", + migrations: { + path: "prisma/migrations", + }, + datasource: { + url: process.env["DATABASE_URL"], + }, +}); diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma new file mode 100644 index 0000000..10c4de8 --- /dev/null +++ b/backend/prisma/schema.prisma @@ -0,0 +1,13 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +// Get a free hosted Postgres database in seconds: `npx create-db` + +generator client { + provider = "prisma-client" + output = "../src/generated/prisma" +} + +datasource db { + provider = "postgresql" +} diff --git a/backend/settings.gradle b/backend/settings.gradle deleted file mode 100644 index 0f5036d..0000000 --- a/backend/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'backend' diff --git a/backend/src/index.ts b/backend/src/index.ts new file mode 100644 index 0000000..9c1f7a1 --- /dev/null +++ b/backend/src/index.ts @@ -0,0 +1,7 @@ +import { Elysia } from "elysia"; + +const app = new Elysia().get("/", () => "Hello Elysia").listen(3000); + +console.log( + `🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}` +); diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/BackendApplication.java b/backend/src/main/java/net/kpuig/shoebill/backend/BackendApplication.java deleted file mode 100644 index 5fcdd83..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/BackendApplication.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.kpuig.shoebill.backend; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.properties.EnableConfigurationProperties; - -import net.kpuig.shoebill.backend.config.ShoebillConfiguration; - -@EnableConfigurationProperties(ShoebillConfiguration.class) -@SpringBootApplication -public class BackendApplication { - - public static void main(String[] args) { - SpringApplication.run(BackendApplication.class, args); - } - -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/config/ShoebillConfiguration.java b/backend/src/main/java/net/kpuig/shoebill/backend/config/ShoebillConfiguration.java deleted file mode 100644 index 50097bf..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/config/ShoebillConfiguration.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.kpuig.shoebill.backend.config; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.bind.DefaultValue; -import org.springframework.validation.annotation.Validated; - -@ConfigurationProperties(prefix = "shoebill") -@Validated -public record ShoebillConfiguration ( - @DefaultValue("false") - boolean relativePicturesOnly -) { - -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/controllers/ChannelController.java b/backend/src/main/java/net/kpuig/shoebill/backend/controllers/ChannelController.java deleted file mode 100644 index 8ee6cb5..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/controllers/ChannelController.java +++ /dev/null @@ -1,82 +0,0 @@ -package net.kpuig.shoebill.backend.controllers; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.util.UriComponentsBuilder; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import net.kpuig.shoebill.backend.datamodels.channel.GetAllChannelsFromServerResponse; -import net.kpuig.shoebill.backend.datamodels.channel.GetChannelResponse; -import net.kpuig.shoebill.backend.datamodels.channel.PostChannelRequest; -import net.kpuig.shoebill.backend.datamodels.channel.PostChannelResponse; -import net.kpuig.shoebill.backend.services.ChannelService; -import net.kpuig.shoebill.backend.services.exceptions.NotFoundException; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; - - -@RestController -@RequestMapping("/api") -public class ChannelController { - @Autowired private ChannelService channelService; - - @Operation(summary = "Get all channels from a server", description = "Retrieves a list of all channels from a server by the server's ID") - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "Channels retrieved"), - @ApiResponse(responseCode = "404", description = "Server not found") - }) - @GetMapping("/server/{serverId}/channel/") - public ResponseEntity getAllChannelsFromServer(@PathVariable(name = "serverId") Long serverId) { - try { - var response = channelService.getAllChannelsFromServer(serverId); - return ResponseEntity.ok(response); - } catch (NotFoundException notFoundException) { - return ResponseEntity.notFound().build(); - } - } - - @Operation(summary = "Get a channel by ID", description = "Retrieves a channel by its ID") - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "Channel retrieved"), - @ApiResponse(responseCode = "404", description = "Channel not found") - }) - @GetMapping("/channel/{channelId}") - public ResponseEntity getChannelById(@PathVariable(name = "channelId") Long channelId) { - try { - var response = channelService.getChannelById(channelId); - return ResponseEntity.ok(response); - } catch (NotFoundException notFoundException) { - return ResponseEntity.notFound().build(); - } - } - - @Operation(summary = "Create a new channel", description = "Creates a new channel with the provided name, position, type, and server ID") - @ApiResponses({ - @ApiResponse(responseCode = "201", description = "Channel created"), - @ApiResponse(responseCode = "400", description = "Invalid request") - }) - @PostMapping("/server/{serverId}/channel") - public ResponseEntity createChannel( - @PathVariable(name = "serverId") Long serverId, - @RequestBody PostChannelRequest request) { - - try { - var response = channelService.createChannel(serverId, request); - return ResponseEntity - .created(UriComponentsBuilder.fromPath("/api/channel/{id}") - .buildAndExpand(response.getId()) - .toUri()) - .body(response); - } catch (RuntimeException e) { - return ResponseEntity.badRequest().build(); - } - } - -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/controllers/ServerController.java b/backend/src/main/java/net/kpuig/shoebill/backend/controllers/ServerController.java deleted file mode 100644 index d7b3556..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/controllers/ServerController.java +++ /dev/null @@ -1,69 +0,0 @@ -package net.kpuig.shoebill.backend.controllers; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import jakarta.validation.Valid; -import net.kpuig.shoebill.backend.datamodels.server.GetAllServersResponse; -import net.kpuig.shoebill.backend.datamodels.server.GetServerResponse; -import net.kpuig.shoebill.backend.datamodels.server.PostServerRequest; -import net.kpuig.shoebill.backend.datamodels.server.PostServerResponse; -import net.kpuig.shoebill.backend.services.ServerService; -import net.kpuig.shoebill.backend.services.exceptions.BadRequestException; -import net.kpuig.shoebill.backend.services.exceptions.NotFoundException; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; - - - -@RestController -@RequestMapping("/api") -public class ServerController { - @Autowired private ServerService serverService; - - @Operation(summary = "Get all servers", description = "Retrieves a list of all servers") - @ApiResponse(responseCode = "200", description = "Servers retrieved") - @GetMapping("/server") - public ResponseEntity getAllServers() { - return ResponseEntity.ok(serverService.getAllServers()); - } - - @Operation(summary = "Get server by ID", description = "Retrieves a server by its ID") - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "Server retrieved"), - @ApiResponse(responseCode = "404", description = "Server not found") - }) - @GetMapping("/server/{id}") - public ResponseEntity getServerById(@PathVariable(name = "id") Long id) { - try { - return ResponseEntity.ok(serverService.getServerById(id)); - } catch (NotFoundException e) { - return ResponseEntity.notFound().build(); - } - } - - @Operation(summary = "Create a new server", description = "Creates a new server with the provided name and image") - @ApiResponses({ - @ApiResponse(responseCode = "201", description = "Server created"), - @ApiResponse(responseCode = "400", description = "Invalid request") - }) - @PostMapping("/server") - public ResponseEntity createNewServer(@Valid @RequestBody PostServerRequest request) { - try { - var response = serverService.createServer(request); - return ResponseEntity.ok(response); - } catch (BadRequestException e) { - return ResponseEntity.badRequest().build(); - } - } - -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/controllers/UserProfileController.java b/backend/src/main/java/net/kpuig/shoebill/backend/controllers/UserProfileController.java deleted file mode 100644 index 1d9e698..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/controllers/UserProfileController.java +++ /dev/null @@ -1,91 +0,0 @@ -package net.kpuig.shoebill.backend.controllers; - -import java.net.URI; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.util.UriComponentsBuilder; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import jakarta.validation.Valid; -import net.kpuig.shoebill.backend.datamodels.userprofile.GetAllUserProfilesResponse; -import net.kpuig.shoebill.backend.datamodels.userprofile.GetUserProfileResponse; -import net.kpuig.shoebill.backend.datamodels.userprofile.PostUserProfileRequest; -import net.kpuig.shoebill.backend.datamodels.userprofile.PostUserProfileResponse; -import net.kpuig.shoebill.backend.services.UserProfileService; -import net.kpuig.shoebill.backend.services.exceptions.BadRequestException; -import net.kpuig.shoebill.backend.services.exceptions.NotFoundException; - -@RestController -@RequestMapping("/api") -public class UserProfileController { - @Autowired - private UserProfileService userProfileService; - - @Operation(summary = "Get all user profiles", description = "Retrieves a list of all user profiles") - @ApiResponse(responseCode = "200", description = "User profiles retrieved", - content = { @Content(mediaType = "application/json") }) - @GetMapping("/user-profile") - public ResponseEntity getAllUserProfiles() { - return ResponseEntity.ok(userProfileService.getAllUserProfiles()); - } - - @Operation(summary = "Get user profile by ID", description = "Retrieves a user profile by its ID") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "User profile retrieved", - content = { @Content(mediaType = "application/json") }), - @ApiResponse(responseCode = "404", description = "User profile not found") - }) - @GetMapping("/user-profile/{id}") - public ResponseEntity getUserProfileById(@PathVariable(name = "id") Long id) { - try { - return ResponseEntity.ok(userProfileService.getUserProfileById(id)); - } catch (NotFoundException e) { - return ResponseEntity.notFound().build(); - } - } - - @Operation(summary = "Get user profile by username", description = "Retrieves a user profile by its username") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "User profile retrieved", - content = { @Content(mediaType = "application/json") }), - @ApiResponse(responseCode = "404", description = "User profile not found") - }) - @GetMapping("/user-profile/") - public ResponseEntity getUserProfileByUsername(@RequestParam(name = "username") String username) { - try { - return ResponseEntity.ok(userProfileService.getUserProfileByUsername(username)); - } catch (NotFoundException e) { - return ResponseEntity.notFound().build(); - } - } - - @Operation(summary = "Create user profile", description = "Creates a new user profile") - @ApiResponse(responseCode = "201", description = "User profile created", - content = { @Content(mediaType = "application/json") }) - @PostMapping("/user-profile") - public ResponseEntity createUserProfile(@RequestBody @Valid PostUserProfileRequest request) { - try { - var response = userProfileService.createUserProfile(request.getUsername()); - URI location = UriComponentsBuilder - .fromPath("/user-profile") - .queryParam("username", response.getUsername()) - .build() - .encode() - .toUri(); - return ResponseEntity.created(location).body(response); - } catch (BadRequestException e) { - return ResponseEntity.badRequest().build(); - } - } -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/Channel.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/Channel.java deleted file mode 100644 index e022113..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/Channel.java +++ /dev/null @@ -1,26 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.channel; - -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; -import lombok.Data; -import net.kpuig.shoebill.backend.datamodels.server.Server; - -@Data -@Entity(name = "channel") -public class Channel { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - private Long position; - - private ChannelType type; - - private String name; - - @ManyToOne - private Server server; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/ChannelType.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/ChannelType.java deleted file mode 100644 index 9827c8d..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/ChannelType.java +++ /dev/null @@ -1,6 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.channel; - -public enum ChannelType { - TEXT_CHANNEL, - VOICE_CHANNEL -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/GetAllChannelsFromServerResponse.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/GetAllChannelsFromServerResponse.java deleted file mode 100644 index b624523..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/GetAllChannelsFromServerResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.channel; - -import java.util.List; - -import lombok.Data; - -@Data -public class GetAllChannelsFromServerResponse { - private List channels; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/GetChannelResponse.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/GetChannelResponse.java deleted file mode 100644 index 4a0e8fb..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/GetChannelResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.channel; - -import lombok.Data; - -@Data -public class GetChannelResponse { - private Long id; - private Long position; - private ChannelType type; - private String name; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/PostChannelRequest.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/PostChannelRequest.java deleted file mode 100644 index eeb0387..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/PostChannelRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.channel; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Data -public class PostChannelRequest { - @NotNull - private Long position; - - @NotNull - private ChannelType type; - - @NotBlank - private String name; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/PostChannelResponse.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/PostChannelResponse.java deleted file mode 100644 index 4bae950..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/PostChannelResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.channel; - -import lombok.Data; - -@Data -public class PostChannelResponse { - private Long id; - private Long position; - private ChannelType type; - private String name; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/message/Message.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/message/Message.java deleted file mode 100644 index 4a7de14..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/message/Message.java +++ /dev/null @@ -1,32 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.message; - -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToOne; -import lombok.Data; -import net.kpuig.shoebill.backend.datamodels.channel.Channel; -import net.kpuig.shoebill.backend.datamodels.userprofile.UserProfile; - -@Data -@Entity(name = "message") -public class Message { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - private String content; - - private Long timestamp; - - @OneToOne - private Message replyTo; - - @ManyToOne - private UserProfile userProfile; - - @ManyToOne - private Channel channel; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/GetAllServersResponse.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/GetAllServersResponse.java deleted file mode 100644 index b29f9c0..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/GetAllServersResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.server; - -import java.util.List; - -import lombok.Data; - -@Data -public class GetAllServersResponse { - private List servers; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/GetServerResponse.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/GetServerResponse.java deleted file mode 100644 index 6575842..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/GetServerResponse.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.server; - -import java.net.URI; - -import lombok.Data; - -@Data -public class GetServerResponse { - private Long id; - private String name; - private URI image; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/PostServerRequest.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/PostServerRequest.java deleted file mode 100644 index bebb987..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/PostServerRequest.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.server; - -import java.net.URI; - -import jakarta.validation.constraints.NotBlank; -import lombok.Data; - -@Data -public class PostServerRequest { - @NotBlank - private String name; - - private URI image; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/PostServerResponse.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/PostServerResponse.java deleted file mode 100644 index e5aadfe..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/PostServerResponse.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.server; - -import java.net.URI; - -import lombok.Data; - -@Data -public class PostServerResponse { - private Long id; - private String name; - private URI image; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/Server.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/Server.java deleted file mode 100644 index 03f6871..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/server/Server.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.server; - -import java.net.URI; - -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import lombok.Data; - -@Data -@Entity(name = "server") -public class Server { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - private String name; - - private URI image; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/GetAllUserProfilesResponse.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/GetAllUserProfilesResponse.java deleted file mode 100644 index ee06565..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/GetAllUserProfilesResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.userprofile; - -import java.util.List; - -import lombok.Data; - -@Data -public class GetAllUserProfilesResponse { - private List userProfiles; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/GetUserProfileResponse.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/GetUserProfileResponse.java deleted file mode 100644 index 58f9b3c..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/GetUserProfileResponse.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.userprofile; - -import lombok.Data; - -@Data -public class GetUserProfileResponse { - private Long id; - private String username; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/PostUserProfileRequest.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/PostUserProfileRequest.java deleted file mode 100644 index 979e360..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/PostUserProfileRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.userprofile; - -import jakarta.validation.constraints.NotBlank; -import lombok.Data; - -@Data -public class PostUserProfileRequest { - @NotBlank - private String username; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/PostUserProfileResponse.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/PostUserProfileResponse.java deleted file mode 100644 index 2bfa942..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/PostUserProfileResponse.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.userprofile; - -import lombok.Data; - -@Data -public class PostUserProfileResponse { - private Long id; - private String username; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/UserProfile.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/UserProfile.java deleted file mode 100644 index da680e4..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/userprofile/UserProfile.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.kpuig.shoebill.backend.datamodels.userprofile; - -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import lombok.Data; - -@Data -@Entity(name = "user_profile") -public class UserProfile { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - private String username; -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/repositories/ChannelRepository.java b/backend/src/main/java/net/kpuig/shoebill/backend/repositories/ChannelRepository.java deleted file mode 100644 index cb651c7..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/repositories/ChannelRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.kpuig.shoebill.backend.repositories; - -import java.util.List; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import net.kpuig.shoebill.backend.datamodels.channel.Channel; - -@Repository -public interface ChannelRepository extends JpaRepository { - - List findAllByServerId(Long serverId); - -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/repositories/MessageRepository.java b/backend/src/main/java/net/kpuig/shoebill/backend/repositories/MessageRepository.java deleted file mode 100644 index 4739319..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/repositories/MessageRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.kpuig.shoebill.backend.repositories; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import net.kpuig.shoebill.backend.datamodels.message.Message; - -@Repository -public interface MessageRepository extends JpaRepository { - -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/repositories/ServerRepository.java b/backend/src/main/java/net/kpuig/shoebill/backend/repositories/ServerRepository.java deleted file mode 100644 index 0ed48f7..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/repositories/ServerRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.kpuig.shoebill.backend.repositories; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import net.kpuig.shoebill.backend.datamodels.server.Server; - -@Repository -public interface ServerRepository extends JpaRepository { - -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/repositories/UserProfileRepository.java b/backend/src/main/java/net/kpuig/shoebill/backend/repositories/UserProfileRepository.java deleted file mode 100644 index 21da66a..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/repositories/UserProfileRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package net.kpuig.shoebill.backend.repositories; - -import java.util.Optional; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import net.kpuig.shoebill.backend.datamodels.userprofile.UserProfile; - -@Repository -public interface UserProfileRepository extends JpaRepository { - Optional findByUsername(String username); -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/services/ChannelService.java b/backend/src/main/java/net/kpuig/shoebill/backend/services/ChannelService.java deleted file mode 100644 index c165865..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/services/ChannelService.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.kpuig.shoebill.backend.services; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import net.kpuig.shoebill.backend.datamodels.channel.Channel; -import net.kpuig.shoebill.backend.datamodels.channel.GetAllChannelsFromServerResponse; -import net.kpuig.shoebill.backend.datamodels.channel.GetChannelResponse; -import net.kpuig.shoebill.backend.datamodels.channel.PostChannelRequest; -import net.kpuig.shoebill.backend.datamodels.channel.PostChannelResponse; -import net.kpuig.shoebill.backend.datamodels.server.Server; -import net.kpuig.shoebill.backend.repositories.ChannelRepository; -import net.kpuig.shoebill.backend.repositories.ServerRepository; -import net.kpuig.shoebill.backend.services.exceptions.NotFoundException; - -@Service -public class ChannelService { - @Autowired private ChannelRepository channelRepository; - @Autowired private ServerRepository serverRepository; - - public GetAllChannelsFromServerResponse getAllChannelsFromServer(Long serverId) { - if (!serverRepository.existsById(serverId)) { - throw new NotFoundException("Server not found"); - } - var channels = channelRepository.findAllByServerId(serverId); - var response = new GetAllChannelsFromServerResponse(); - response.setChannels(channels.stream().map(channel -> { - var channelResponse = new GetChannelResponse(); - channelResponse.setId(channel.getId()); - channelResponse.setName(channel.getName()); - channelResponse.setPosition(channel.getPosition()); - channelResponse.setType(channel.getType()); - return channelResponse; - }).toList()); - return response; - } - - public GetChannelResponse getChannelById(Long channelId) { - var channel = channelRepository.findById(channelId).orElseThrow(); - var response = new GetChannelResponse(); - response.setId(channel.getId()); - response.setName(channel.getName()); - response.setPosition(channel.getPosition()); - response.setType(channel.getType()); - return response; - } - - public PostChannelResponse createChannel(Long serverId, PostChannelRequest request) { - Server server; - try { - server = serverRepository.findById(serverId).orElseThrow(); - } catch (Exception e) { - throw new RuntimeException("Server not found"); - } - - var channel = new Channel(); - channel.setName(request.getName()); - channel.setPosition(request.getPosition()); - channel.setType(request.getType()); - channel.setServer(server); - channel = channelRepository.save(channel); - - var response = new PostChannelResponse(); - response.setId(channel.getId()); - response.setName(channel.getName()); - response.setPosition(channel.getPosition()); - response.setType(channel.getType()); - return response; - } -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/services/ServerService.java b/backend/src/main/java/net/kpuig/shoebill/backend/services/ServerService.java deleted file mode 100644 index 99e1afc..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/services/ServerService.java +++ /dev/null @@ -1,79 +0,0 @@ -package net.kpuig.shoebill.backend.services; - -import java.net.URI; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import net.kpuig.shoebill.backend.config.ShoebillConfiguration; -import net.kpuig.shoebill.backend.datamodels.server.GetAllServersResponse; -import net.kpuig.shoebill.backend.datamodels.server.GetServerResponse; -import net.kpuig.shoebill.backend.datamodels.server.PostServerRequest; -import net.kpuig.shoebill.backend.datamodels.server.PostServerResponse; -import net.kpuig.shoebill.backend.datamodels.server.Server; -import net.kpuig.shoebill.backend.repositories.ServerRepository; -import net.kpuig.shoebill.backend.services.exceptions.BadRequestException; -import net.kpuig.shoebill.backend.services.exceptions.NotFoundException; - -@Service -public class ServerService { - @Autowired private ShoebillConfiguration shoebillConfiguration; - @Autowired private ServerRepository serverRepository; - - public GetAllServersResponse getAllServers() { - GetAllServersResponse response = new GetAllServersResponse(); - response.setServers(serverRepository.findAll().stream().map(server -> { - GetServerResponse serverResponse = new GetServerResponse(); - serverResponse.setId(server.getId()); - serverResponse.setName(server.getName()); - serverResponse.setImage(server.getImage()); - return serverResponse; - }).toList()); - return response; - } - - public GetServerResponse getServerById(Long id) { - GetServerResponse response = new GetServerResponse(); - serverRepository.findById(id).ifPresentOrElse(server -> { - response.setId(server.getId()); - response.setName(server.getName()); - response.setImage(server.getImage()); - }, () -> { - throw new NotFoundException("Server not found with id: " + id); - }); - return response; - } - - public PostServerResponse createServer(PostServerRequest request) { - Server server = new Server(); - server.setName(request.getName()); - server.setImage(request.getImage()); - - try { - server = serverRepository.save(server); - var uri = new URI(request.getImage().toString()); - - // Make sure it's either relative with no injections or a complete HTTP/HTTPS URL - if (uri.isAbsolute()) { - if (shoebillConfiguration.relativePicturesOnly()) { - throw new BadRequestException("Only relative image URLs are allowed"); - } - if (!uri.getScheme().equals("http") && !uri.getScheme().equals("https")) { - throw new BadRequestException("Image URL must be HTTP or HTTPS"); - } - } else { - if (request.getImage().toString().contains("..") || request.getImage().toString().contains("//") || request.getImage().toString().contains("\\")) { - throw new BadRequestException("Relative image URL cannot contain '..', '//', or '\\'"); - } - } - } catch (Exception e) { - throw new BadRequestException("Invalid image URL"); - } - - PostServerResponse response = new PostServerResponse(); - response.setId(server.getId()); - response.setName(server.getName()); - response.setImage(server.getImage()); - return response; - } -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/services/UserProfileService.java b/backend/src/main/java/net/kpuig/shoebill/backend/services/UserProfileService.java deleted file mode 100644 index 5ba11b7..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/services/UserProfileService.java +++ /dev/null @@ -1,68 +0,0 @@ -package net.kpuig.shoebill.backend.services; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import net.kpuig.shoebill.backend.datamodels.userprofile.GetAllUserProfilesResponse; -import net.kpuig.shoebill.backend.datamodels.userprofile.GetUserProfileResponse; -import net.kpuig.shoebill.backend.datamodels.userprofile.PostUserProfileResponse; -import net.kpuig.shoebill.backend.datamodels.userprofile.UserProfile; -import net.kpuig.shoebill.backend.repositories.UserProfileRepository; -import net.kpuig.shoebill.backend.services.exceptions.BadRequestException; -import net.kpuig.shoebill.backend.services.exceptions.NotFoundException; - -@Service -public class UserProfileService { - @Autowired - private UserProfileRepository userProfileRepository; - - public GetAllUserProfilesResponse getAllUserProfiles() { - GetAllUserProfilesResponse response = new GetAllUserProfilesResponse(); - response.setUserProfiles(userProfileRepository.findAll().stream().map(userProfile -> { - GetUserProfileResponse userProfileResponse = new GetUserProfileResponse(); - userProfileResponse.setId(userProfile.getId()); - userProfileResponse.setUsername(userProfile.getUsername()); - return userProfileResponse; - }).toList()); - return response; - } - - public GetUserProfileResponse getUserProfileById(Long id) { - GetUserProfileResponse response = new GetUserProfileResponse(); - userProfileRepository.findById(id).ifPresentOrElse(userProfile -> { - response.setId(userProfile.getId()); - response.setUsername(userProfile.getUsername()); - }, () -> { - throw new NotFoundException("User profile not found"); - }); - return response; - } - - public GetUserProfileResponse getUserProfileByUsername(String username) { - GetUserProfileResponse response = new GetUserProfileResponse(); - userProfileRepository.findByUsername(username).ifPresentOrElse(userProfile -> { - response.setId(userProfile.getId()); - response.setUsername(userProfile.getUsername()); - }, () -> { - throw new NotFoundException("User profile not found"); - }); - return response; - } - - public PostUserProfileResponse createUserProfile(String username) { - if (userProfileRepository.findByUsername(username).isPresent()) { - throw new BadRequestException("Username is already taken"); - } - - UserProfile userProfile = new UserProfile(); - userProfile.setUsername(username); - userProfile = userProfileRepository.save(userProfile); - - PostUserProfileResponse response = new PostUserProfileResponse(); - response.setId(userProfile.getId()); - response.setUsername(userProfile.getUsername()); - - return response; - } - -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/services/exceptions/BadRequestException.java b/backend/src/main/java/net/kpuig/shoebill/backend/services/exceptions/BadRequestException.java deleted file mode 100644 index d6ce748..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/services/exceptions/BadRequestException.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.kpuig.shoebill.backend.services.exceptions; - -public class BadRequestException extends RuntimeException { - public BadRequestException(String message) { - super(message); - } -} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/services/exceptions/NotFoundException.java b/backend/src/main/java/net/kpuig/shoebill/backend/services/exceptions/NotFoundException.java deleted file mode 100644 index 14754bf..0000000 --- a/backend/src/main/java/net/kpuig/shoebill/backend/services/exceptions/NotFoundException.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.kpuig.shoebill.backend.services.exceptions; - -public class NotFoundException extends RuntimeException { - public NotFoundException(String message) { - super(message); - } -} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties deleted file mode 100644 index 0a45475..0000000 --- a/backend/src/main/resources/application.properties +++ /dev/null @@ -1,16 +0,0 @@ -spring.application.name=backend -spring.h2.console.enabled=true -spring.h2.console.path=/h2-console -spring.datasource.url=jdbc:h2:mem:testdb -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=sa -spring.datasource.password=password -spring.jpa.hibernate.ddl-auto=update -logging.level.org.springframework=INFO -logging.level.com.example=DEBUG -server.port=8080 -springdoc.api-docs.enabled=true -springdoc.api-docs.path=/v3/api-docs -springdoc.swagger-ui.enabled=true -springdoc.swagger-ui.path=/swag -shoebill.relative-pictures-only=true \ No newline at end of file diff --git a/backend/src/test/java/net/kpuig/backend/BackendApplicationTests.java b/backend/src/test/java/net/kpuig/backend/BackendApplicationTests.java deleted file mode 100644 index ad56ac2..0000000 --- a/backend/src/test/java/net/kpuig/backend/BackendApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package net.kpuig.backend; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class BackendApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/backend/tsconfig.json b/backend/tsconfig.json new file mode 100644 index 0000000..36adf8e --- /dev/null +++ b/backend/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "ES2021", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "ES2022", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "bundler", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + "types": ["bun-types"], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +}