diff --git a/packages/server/package.json b/packages/server/package.json index 9e02fd3..d6f7a2d 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -16,6 +16,8 @@ "dependencies": { "@elysiajs/cors": "^1.3.3", "@elysiajs/html": "^1.3.1", + "@elysiajs/node": "^1.4.1", + "@elysiajs/openapi": "^1.4.11", "@elysiajs/static": "^1.3.0", "@std/async": "npm:@jsr/std__async@^1.0.13", "@zip.js/zip.js": "^2.7.62", @@ -23,7 +25,7 @@ "chokidar": "^3.6.0", "dbtype": "workspace:dbtype", "dotenv": "^16.5.0", - "elysia": "^1.3.20", + "elysia": "^1.4.9", "jose": "^5.10.0", "kysely": "^0.27.6", "natural-orderby": "^2.0.3", diff --git a/packages/server/src/SettingConfig.ts b/packages/server/src/SettingConfig.ts index 77611fc..637d489 100644 --- a/packages/server/src/SettingConfig.ts +++ b/packages/server/src/SettingConfig.ts @@ -86,7 +86,7 @@ const loadEnvSetting = (): EnvSetting => { throw new Error("SERVER_HOST environment variable is required"); } - const portString = process.env.SERVER_PORT; + const portString = process.env.SERVER_PORT ?? process.env.PORT; if (!portString) { throw new Error("SERVER_PORT environment variable is required"); } diff --git a/packages/server/src/app.ts b/packages/server/src/app.ts index e1158bb..547a5d7 100644 --- a/packages/server/src/app.ts +++ b/packages/server/src/app.ts @@ -1,5 +1,6 @@ import { create_server } from "./server.ts"; -create_server().catch((err) => { +create_server() +.catch((err) => { console.error(err); }); \ No newline at end of file diff --git a/packages/server/src/route/contents.ts b/packages/server/src/route/contents.ts index df1b67d..072fb31 100644 --- a/packages/server/src/route/contents.ts +++ b/packages/server/src/route/contents.ts @@ -8,28 +8,31 @@ import { oshash } from "src/util/oshash.ts"; import { renderComicPage } from "./comic.ts"; export const getContentRouter = (controller: DocumentAccessor) => { - return new Elysia({ name: "content-router" }) + return new Elysia({ name: "content-router", + prefix: "/doc", + }) .get("/search", async ({ query }) => { const limit = Math.min(Number(query.limit ?? 20), 100); const option: QueryListOption = { limit: limit, allow_tag: query.allow_tag?.split(",") ?? [], word: query.word, - cursor: Number(query.cursor), + cursor: query.cursor, eager_loading: true, offset: Number(query.offset), use_offset: query.use_offset === 'true', content_type: query.content_type, }; + console.log(option); return await controller.findList(option); }, { beforeHandle: createPermissionCheck(Per.QueryContent), query: t.Object({ limit: t.Optional(t.String()), - cursor: t.Optional(t.String()), + cursor: t.Optional(t.Number()), word: t.Optional(t.String()), content_type: t.Optional(t.String()), - offset: t.Optional(t.String()), + offset: t.Optional(t.Number()), use_offset: t.Optional(t.String()), allow_tag: t.Optional(t.String()), }) diff --git a/packages/server/src/route/settings.ts b/packages/server/src/route/settings.ts index 6bee557..6e1ce2e 100644 --- a/packages/server/src/route/settings.ts +++ b/packages/server/src/route/settings.ts @@ -50,7 +50,8 @@ const buildResponse = (): SettingResponse => { export const createSettingsRouter = (db: Kysely) => new Elysia({ name: "settings-router" }) - .get("/settings", () => buildResponse(), { + .get("/settings", () => { + return buildResponse()}, { beforeHandle: AdminOnly, }) .patch("/settings", async ({ body }) => { diff --git a/packages/server/src/route/tags.ts b/packages/server/src/route/tags.ts index d8fef1a..03212ac 100644 --- a/packages/server/src/route/tags.ts +++ b/packages/server/src/route/tags.ts @@ -4,7 +4,9 @@ import { createPermissionCheck, Permission } from "../permission/permission.ts"; import { sendError } from "./error_handler.ts"; export function getTagRounter(tagController: TagAccessor) { - return new Elysia({ name: "tags-router" }) + return new Elysia({ name: "tags-router", + prefix: "/tags", + }) .get("/", async ({ query }) => { if (query.withCount !== undefined) { return await tagController.getAllTagCount(); diff --git a/packages/server/src/server.ts b/packages/server/src/server.ts index 63786e8..d51bcd3 100644 --- a/packages/server/src/server.ts +++ b/packages/server/src/server.ts @@ -19,6 +19,8 @@ import { createComicWatcher } from "./diff/watcher/comic_watcher.ts"; import { loadComicConfig } from "./diff/watcher/ComicConfig.ts"; import type { DocumentAccessor, TagAccessor, UserAccessor } from "./model/mod.ts"; import { getTagRounter } from "./route/tags.ts"; +import { node } from "@elysiajs/node"; +import { openapi } from "@elysiajs/openapi"; import { config } from "dotenv"; config(); @@ -90,7 +92,9 @@ export async function create_server() { const index_html = readFileSync("dist/index.html", "utf-8"); - const app = new Elysia() + const app = new Elysia({ + adapter: node(), + }) .use(cors()) .use(staticPlugin({ assets: "dist/assets", @@ -100,6 +104,7 @@ export async function create_server() { "Cache-Control": setting.mode === "development" ? "no-cache" : "public, max-age=3600", } })) + .use(openapi()) .use(html()) .onError((context) => error_handler({ code: typeof context.code === "number" ? String(context.code) : context.code, @@ -141,12 +146,13 @@ export async function create_server() { .get("/difference", () => index_html) .get("/setting", () => index_html) .get("/tags", () => index_html) - .listen({ - hostname: setting.hostname, - port: setting.port, - }); - console.log(`🦊 Elysia is running at http://${app.server?.hostname}:${app.server?.port}`); + app.listen({ + port: setting.port, + hostname: setting.hostname, + }); + + console.log(`Server started at http://${setting.hostname}:${setting.port}/`); return app; } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index df6b7ac..dd65b32 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -171,13 +171,19 @@ importers: dependencies: '@elysiajs/cors': specifier: ^1.3.3 - version: 1.3.3(elysia@1.3.20(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(typescript@5.8.3)) + version: 1.3.3(elysia@1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3)) '@elysiajs/html': specifier: ^1.3.1 - version: 1.3.1(elysia@1.3.20(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(typescript@5.8.3))(typescript@5.8.3) + version: 1.3.1(elysia@1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3))(typescript@5.8.3) + '@elysiajs/node': + specifier: ^1.4.1 + version: 1.4.1(elysia@1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3)) + '@elysiajs/openapi': + specifier: ^1.4.11 + version: 1.4.11(elysia@1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3)) '@elysiajs/static': specifier: ^1.3.0 - version: 1.3.0(elysia@1.3.20(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(typescript@5.8.3)) + version: 1.3.0(elysia@1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3)) '@std/async': specifier: npm:@jsr/std__async@^1.0.13 version: '@jsr/std__async@1.0.13' @@ -197,8 +203,8 @@ importers: specifier: ^16.5.0 version: 16.5.0 elysia: - specifier: ^1.3.20 - version: 1.3.20(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(typescript@5.8.3) + specifier: ^1.4.9 + version: 1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3) jose: specifier: ^5.10.0 version: 5.10.0 @@ -422,6 +428,16 @@ packages: peerDependencies: elysia: '>= 1.3.0' + '@elysiajs/node@1.4.1': + resolution: {integrity: sha512-2wAALwHK3IYi1XJPnxfp1xJsvps5FqqcQqe+QXjYlGQvsmSG+vI5wNDIuvIlB+6p9NE/laLbqV0aFromf3X7yg==} + peerDependencies: + elysia: '>= 1.4.0' + + '@elysiajs/openapi@1.4.11': + resolution: {integrity: sha512-d75bMxYJpN6qSDi/z9L1S7SLk1S/8Px+cTb3W2lrYzU8uQ5E0kXdy1oOMJEfTyVsz3OA19NP9KNxE7ztSbLBLg==} + peerDependencies: + elysia: '>= 1.4.0' + '@elysiajs/static@1.3.0': resolution: {integrity: sha512-7mWlj2U/AZvH27IfRKqpUjDP1W9ZRldF9NmdnatFEtx0AOy7YYgyk0rt5hXrH6wPcR//2gO2Qy+k5rwswpEhJA==} peerDependencies: @@ -1805,6 +1821,9 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie-es@2.0.0: + resolution: {integrity: sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg==} + cookie@1.0.2: resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} engines: {node: '>=18'} @@ -1822,6 +1841,14 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + crossws@0.4.1: + resolution: {integrity: sha512-E7WKBcHVhAVrY6JYD5kteNqVq1GSZxqGrdSiwXR9at+XHi43HJoCQKXcCczR5LBnBquFZPsB3o7HklulKoBU5w==} + peerDependencies: + srvx: '>=0.7.1' + peerDependenciesMeta: + srvx: + optional: true + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -1887,6 +1914,15 @@ packages: supports-color: optional: true + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decimal.js-light@2.5.1: resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} @@ -1962,12 +1998,19 @@ packages: electron-to-chromium@1.5.165: resolution: {integrity: sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==} - elysia@1.3.20: - resolution: {integrity: sha512-7j2w/1NALKu1KOPDFEIKaSLZ2gcL92Ij/POssDOglZO04rFFQ3unvBjUVYTrMMKbDn+/tLd5OXuSUztK+pcEtQ==} + elysia@1.4.9: + resolution: {integrity: sha512-BWNhA8DoKQvlQTjAUkMAmNeso24U+ibZxY/8LN96qSDK/6eevaX59r3GISow699JPxSnFY3gLMUzJzCLYVtbvg==} peerDependencies: + '@sinclair/typebox': '>= 0.34.0 < 1' exact-mirror: '>= 0.0.9' file-type: '>= 20.0.0' + openapi-types: '>= 12.0.0' typescript: '>= 5.0.0' + peerDependenciesMeta: + file-type: + optional: true + typescript: + optional: true emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2991,6 +3034,11 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + srvx@0.8.9: + resolution: {integrity: sha512-wYc3VLZHRzwYrWJhkEqkhLb31TI0SOkfYZDkUhXdp3NoCnNS0FqajiQszZZjfow/VYEuc6Q5sZh9nM6kPy2NBQ==} + engines: {node: '>=20.16.0'} + hasBin: true + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -3568,23 +3616,34 @@ snapshots: '@biomejs/cli-win32-x64@1.6.3': optional: true - '@borewit/text-codec@0.1.1': {} + '@borewit/text-codec@0.1.1': + optional: true - '@elysiajs/cors@1.3.3(elysia@1.3.20(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(typescript@5.8.3))': + '@elysiajs/cors@1.3.3(elysia@1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3))': dependencies: - elysia: 1.3.20(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(typescript@5.8.3) + elysia: 1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3) - '@elysiajs/html@1.3.1(elysia@1.3.20(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(typescript@5.8.3))(typescript@5.8.3)': + '@elysiajs/html@1.3.1(elysia@1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3))(typescript@5.8.3)': dependencies: '@kitajs/html': 4.2.9 '@kitajs/ts-html-plugin': 4.1.2(@kitajs/html@4.2.9)(typescript@5.8.3) - elysia: 1.3.20(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(typescript@5.8.3) + elysia: 1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3) transitivePeerDependencies: - typescript - '@elysiajs/static@1.3.0(elysia@1.3.20(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(typescript@5.8.3))': + '@elysiajs/node@1.4.1(elysia@1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3))': dependencies: - elysia: 1.3.20(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(typescript@5.8.3) + crossws: 0.4.1(srvx@0.8.9) + elysia: 1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3) + srvx: 0.8.9 + + '@elysiajs/openapi@1.4.11(elysia@1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3))': + dependencies: + elysia: 1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3) + + '@elysiajs/static@1.3.0(elysia@1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3))': + dependencies: + elysia: 1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3) node-cache: 5.1.2 '@esbuild/aix-ppc64@0.21.5': @@ -4312,8 +4371,7 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.42.0': optional: true - '@sinclair/typebox@0.34.41': - optional: true + '@sinclair/typebox@0.34.41': {} '@swc/core-darwin-arm64@1.11.31': optional: true @@ -4377,13 +4435,15 @@ snapshots: '@tokenizer/inflate@0.2.7': dependencies: - debug: 4.4.1 + debug: 4.4.3 fflate: 0.8.2 token-types: 6.1.1 transitivePeerDependencies: - supports-color + optional: true - '@tokenizer/token@0.3.0': {} + '@tokenizer/token@0.3.0': + optional: true '@ts-morph/common@0.19.0': dependencies: @@ -4807,6 +4867,8 @@ snapshots: convert-source-map@2.0.0: {} + cookie-es@2.0.0: {} + cookie@1.0.2: {} cosmiconfig@8.3.6(typescript@5.8.3): @@ -4824,6 +4886,10 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + crossws@0.4.1(srvx@0.8.9): + optionalDependencies: + srvx: 0.8.9 + cssesc@3.0.0: {} csstype@3.1.3: {} @@ -4872,6 +4938,11 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.4.3: + dependencies: + ms: 2.1.3 + optional: true + decimal.js-light@2.5.1: {} decompress-response@6.0.0: @@ -4927,16 +4998,16 @@ snapshots: electron-to-chromium@1.5.165: {} - elysia@1.3.20(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(typescript@5.8.3): + elysia@1.4.9(@sinclair/typebox@0.34.41)(exact-mirror@0.2.0(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.8.3): dependencies: + '@sinclair/typebox': 0.34.41 cookie: 1.0.2 exact-mirror: 0.2.0(@sinclair/typebox@0.34.41) fast-decode-uri-component: 1.0.1 + openapi-types: 12.1.3 + optionalDependencies: file-type: 21.0.0 typescript: 5.8.3 - optionalDependencies: - '@sinclair/typebox': 0.34.41 - openapi-types: 12.1.3 emoji-regex@8.0.0: {} @@ -5147,7 +5218,8 @@ snapshots: node-domexception: 1.0.0 web-streams-polyfill: 3.3.3 - fflate@0.8.2: {} + fflate@0.8.2: + optional: true file-entry-cache@6.0.1: dependencies: @@ -5161,6 +5233,7 @@ snapshots: uint8array-extras: 1.5.0 transitivePeerDependencies: - supports-color + optional: true file-uri-to-path@1.0.0: {} @@ -5569,8 +5642,7 @@ snapshots: dependencies: mimic-fn: 4.0.0 - openapi-types@12.1.3: - optional: true + openapi-types@12.1.3: {} optionator@0.9.4: dependencies: @@ -5981,6 +6053,10 @@ snapshots: source-map@0.6.1: {} + srvx@0.8.9: + dependencies: + cookie-es: 2.0.0 + stackback@0.0.2: {} std-env@3.9.0: {} @@ -6024,6 +6100,7 @@ snapshots: strtok3@10.3.4: dependencies: '@tokenizer/token': 0.3.0 + optional: true sucrase@3.35.0: dependencies: @@ -6141,6 +6218,7 @@ snapshots: '@borewit/text-codec': 0.1.1 '@tokenizer/token': 0.3.0 ieee754: 1.2.1 + optional: true ts-api-utils@1.4.3(typescript@5.8.3): dependencies: @@ -6182,7 +6260,8 @@ snapshots: typescript@5.8.3: {} - uint8array-extras@1.5.0: {} + uint8array-extras@1.5.0: + optional: true undici-types@6.21.0: {}