mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 00:18:19 +01:00
refactor: ⬆️ Upgrade to Zod v4 and hono-openapi 0.5.0
This commit is contained in:
parent
add2429606
commit
24d4150da4
|
|
@ -5,7 +5,7 @@ import {
|
|||
getTestUsers,
|
||||
} from "@versia-server/tests";
|
||||
import { bench, run } from "mitata";
|
||||
import type { z } from "zod";
|
||||
import type { z } from "zod/v4";
|
||||
|
||||
const { users, tokens, deleteUsers } = await getTestUsers(5);
|
||||
await getTestStatuses(40, users[0]);
|
||||
|
|
|
|||
44
bun.lock
44
bun.lock
|
|
@ -12,7 +12,7 @@
|
|||
"@clerc/plugin-not-found": "catalog:",
|
||||
"@clerc/plugin-version": "catalog:",
|
||||
"@hackmd/markdown-it-task-lists": "catalog:",
|
||||
"@hono/zod-validator": "catalog:",
|
||||
"@hono/standard-validator": "catalog:",
|
||||
"@inquirer/confirm": "catalog:",
|
||||
"@scalar/hono-api-reference": "catalog:",
|
||||
"@sentry/bun": "catalog:",
|
||||
|
|
@ -84,14 +84,13 @@
|
|||
"vitepress-plugin-tabs": "catalog:",
|
||||
"vitepress-sidebar": "catalog:",
|
||||
"vue": "catalog:",
|
||||
"zod-to-json-schema": "catalog:",
|
||||
},
|
||||
},
|
||||
"packages/api": {
|
||||
"name": "@versia-server/api",
|
||||
"version": "0.9.0-alpha.0",
|
||||
"dependencies": {
|
||||
"@hono/zod-validator": "catalog:",
|
||||
"@hono/standard-validator": "catalog:",
|
||||
"@scalar/hono-api-reference": "catalog:",
|
||||
"@versia-server/config": "workspace:*",
|
||||
"@versia-server/kit": "workspace:*",
|
||||
|
|
@ -143,7 +142,6 @@
|
|||
"mime-types": "catalog:",
|
||||
"web-push": "catalog:",
|
||||
"zod": "catalog:",
|
||||
"zod-to-json-schema": "catalog:",
|
||||
"zod-validation-error": "catalog:",
|
||||
},
|
||||
},
|
||||
|
|
@ -152,7 +150,7 @@
|
|||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@hackmd/markdown-it-task-lists": "catalog:",
|
||||
"@hono/zod-validator": "catalog:",
|
||||
"@hono/standard-validator": "catalog:",
|
||||
"@versia-server/config": "workspace:*",
|
||||
"@versia-server/logging": "workspace:*",
|
||||
"@versia/client": "workspace:*",
|
||||
|
|
@ -177,7 +175,6 @@
|
|||
"sonic-channel": "catalog:",
|
||||
"web-push": "catalog:",
|
||||
"zod": "catalog:",
|
||||
"zod-to-json-schema": "catalog:",
|
||||
"zod-validation-error": "catalog:",
|
||||
},
|
||||
},
|
||||
|
|
@ -242,7 +239,7 @@
|
|||
"@clerc/plugin-not-found": "^0.44.0",
|
||||
"@clerc/plugin-version": "^0.44.0",
|
||||
"@hackmd/markdown-it-task-lists": "^2.1.4",
|
||||
"@hono/zod-validator": "^0.7.0",
|
||||
"@hono/standard-validator": "^0.1.2",
|
||||
"@inquirer/confirm": "^5.1.13",
|
||||
"@logtape/file": "^1.0.0",
|
||||
"@logtape/logtape": "^1.0.0",
|
||||
|
|
@ -267,7 +264,7 @@
|
|||
"drizzle-orm": "^0.44.2",
|
||||
"feed": "^5.1.0",
|
||||
"hono": "^4.8.4",
|
||||
"hono-openapi": "^0.4.8",
|
||||
"hono-openapi": "npm:@cpluspatch/hono-openapi@0.5.1",
|
||||
"hono-rate-limiter": "^0.4.2",
|
||||
"html-to-text": "^9.0.5",
|
||||
"ioredis": "^5.6.1",
|
||||
|
|
@ -306,9 +303,8 @@
|
|||
"xss": "^1.0.15",
|
||||
"youch": "^4.1.0-beta.7",
|
||||
"zod": "^3.25.74",
|
||||
"zod-openapi": "^4.2.4",
|
||||
"zod-to-json-schema": "^3.24.6",
|
||||
"zod-validation-error": "^3.5.2",
|
||||
"zod-openapi": "^5.0.0",
|
||||
"zod-validation-error": "^4.0.0-beta.1",
|
||||
},
|
||||
"packages": {
|
||||
"@algolia/autocomplete-core": ["@algolia/autocomplete-core@1.17.7", "", { "dependencies": { "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", "@algolia/autocomplete-shared": "1.17.7" } }, "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q=="],
|
||||
|
|
@ -345,8 +341,6 @@
|
|||
|
||||
"@algolia/requester-node-http": ["@algolia/requester-node-http@5.30.0", "", { "dependencies": { "@algolia/client-common": "5.30.0" } }, "sha512-uSTUh9fxeHde1c7KhvZKUrivk90sdiDftC+rSKNFKKEU9TiIKAGA7B2oKC+AoMCqMymot1vW9SGbeESQPTZd0w=="],
|
||||
|
||||
"@apidevtools/json-schema-ref-parser": ["@apidevtools/json-schema-ref-parser@11.9.3", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.0" } }, "sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ=="],
|
||||
|
||||
"@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
|
||||
|
||||
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
|
||||
|
|
@ -467,7 +461,7 @@
|
|||
|
||||
"@hackmd/markdown-it-task-lists": ["@hackmd/markdown-it-task-lists@2.1.4", "", {}, "sha512-njMloWVihC7a7N4zxczv547bgNxPVG3GBzh6Z6f2xnO8/92JaxTmQuMV7YvaKKkOyhh2RW4RT84uSgax8u4qfQ=="],
|
||||
|
||||
"@hono/zod-validator": ["@hono/zod-validator@0.7.0", "", { "peerDependencies": { "hono": ">=3.9.0", "zod": "^3.25.0" } }, "sha512-qe2ZE6sHFE98dcUrbYMtS3bAV8hqcCOflykvZga2S7XhmNSZzT+dIz4OuMILsjLHkJw9JMn912/dB7dQOmuPvg=="],
|
||||
"@hono/standard-validator": ["@hono/standard-validator@0.1.2", "", { "peerDependencies": { "@standard-schema/spec": "1.0.0", "hono": ">=3.9.0" } }, "sha512-mVyv2fpx/o0MNAEhjXhvuVbW3BWTGnf8F4w8ZifztE+TWXjUAKr7KAOZfcDhVrurgVhKw7RbTnEog2beZM6QtQ=="],
|
||||
|
||||
"@iconify-json/simple-icons": ["@iconify-json/simple-icons@1.2.41", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-4tt29cKzNsxvt6rjAOVhEgpZV0L8jleTDTMdtvIJjF14Afp9aH8peuwGYyX35l6idfFwuzbvjSVfVyVjJtfmYA=="],
|
||||
|
||||
|
|
@ -529,8 +523,6 @@
|
|||
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.4", "", {}, "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw=="],
|
||||
|
||||
"@jsdevtools/ono": ["@jsdevtools/ono@7.1.3", "", {}, "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="],
|
||||
|
||||
"@logtape/file": ["@logtape/file@1.0.2", "", { "peerDependencies": { "@logtape/logtape": "1.0.2" } }, "sha512-V5fiudPkjz0+R5+eVNceYwn65oZ/XrUXlRqbn0xFaHZ/XBPgVRTPf2fReFeyzcl3d3hcPBGk2K6smsJQBSJavw=="],
|
||||
|
||||
"@logtape/logtape": ["@logtape/logtape@1.0.2", "", {}, "sha512-6EWfs4KyTAVsiAnXXSFpzEmUYI2k7qLJogqPv3JqwFd8S8Zr2iUBPv3pbIC+70cW4P6Zpq1l1hnX/jDVZwvc+Q=="],
|
||||
|
|
@ -739,6 +731,12 @@
|
|||
|
||||
"@speed-highlight/core": ["@speed-highlight/core@1.2.7", "", {}, "sha512-0dxmVj4gxg3Jg879kvFS/msl4s9F3T9UXC1InxgOf7t5NvcPD97u/WTA5vL/IxWHMn7qSxBozqrnnE2wvl1m8g=="],
|
||||
|
||||
"@standard-community/standard-json": ["@standard-community/standard-json@0.3.0-rc.1", "", { "peerDependencies": { "@standard-schema/spec": "^1.0.0", "@types/json-schema": "^7.0.15", "@valibot/to-json-schema": "^1.3.0", "arktype": "^2.1.20", "effect": "^3.16.8", "valibot": "^1.1.0", "zod": "^3.25.67", "zod-to-json-schema": "^3.24.5" }, "optionalPeers": ["@valibot/to-json-schema", "arktype", "effect", "valibot", "zod", "zod-to-json-schema"] }, "sha512-WF0OkR3cbKwtUxis8HFDRzkwPVbmk4WFhrZa35gFslIOKKLKlkh/ejjIeW6nGVoCxVQOQg5AayuggJo8bhn0Cg=="],
|
||||
|
||||
"@standard-community/standard-openapi": ["@standard-community/standard-openapi@0.2.0-rc.0", "", { "dependencies": { "zod-openapi": "^4.2.4" }, "peerDependencies": { "@standard-community/standard-json": "^0.3.0-rc.1", "@standard-schema/spec": "^1.0.0", "arktype": "^2.1.20", "openapi-types": "^12.1.3", "valibot": "^1.1.0", "zod": "^3.25.67" }, "optionalPeers": ["arktype", "valibot", "zod"] }, "sha512-UFN2H9aB7rCbvY4z072IikQMQ6PYrCAushiBrjgpGmhHww2Q8NDa8wwY1vPc5tJTTufjGAtMUZnVe2rskdD8/w=="],
|
||||
|
||||
"@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="],
|
||||
|
||||
"@ts-morph/common": ["@ts-morph/common@0.12.3", "", { "dependencies": { "fast-glob": "^3.2.7", "minimatch": "^3.0.4", "mkdirp": "^1.0.4", "path-browserify": "^1.0.1" } }, "sha512-4tUmeLyXJnJWvTFOKtcNJ1yh0a3SsTLi2MUoyj8iUNznFRN1ZquaNe7Oukqrnki2FzZkm0J9adCNLDZxUzvj+w=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
|
||||
|
|
@ -921,8 +919,6 @@
|
|||
|
||||
"cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="],
|
||||
|
||||
"clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="],
|
||||
|
||||
"cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="],
|
||||
|
||||
"code-block-writer": ["code-block-writer@11.0.3", "", {}, "sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw=="],
|
||||
|
|
@ -1081,7 +1077,7 @@
|
|||
|
||||
"hono": ["hono@4.8.4", "", {}, "sha512-KOIBp1+iUs0HrKztM4EHiB2UtzZDTBihDtOF5K6+WaJjCPeaW4Q92R8j63jOhvJI5+tZSMuKD9REVEXXY9illg=="],
|
||||
|
||||
"hono-openapi": ["hono-openapi@0.4.8", "", { "dependencies": { "json-schema-walker": "^2.0.0" }, "peerDependencies": { "@hono/arktype-validator": "^2.0.0", "@hono/effect-validator": "^1.2.0", "@hono/typebox-validator": "^0.2.0 || ^0.3.0", "@hono/valibot-validator": "^0.5.1", "@hono/zod-validator": "^0.4.1", "@sinclair/typebox": "^0.34.9", "@valibot/to-json-schema": "^1.0.0-beta.3", "arktype": "^2.0.0", "effect": "^3.11.3", "hono": "^4.6.13", "openapi-types": "^12.1.3", "valibot": "^1.0.0-beta.9", "zod": "^3.23.8", "zod-openapi": "^4.0.0" }, "optionalPeers": ["@hono/arktype-validator", "@hono/effect-validator", "@hono/typebox-validator", "@hono/valibot-validator", "@hono/zod-validator", "@sinclair/typebox", "@valibot/to-json-schema", "arktype", "effect", "hono", "valibot", "zod", "zod-openapi"] }, "sha512-LYr5xdtD49M7hEAduV1PftOMzuT8ZNvkyWfh1DThkLsIr4RkvDb12UxgIiFbwrJB6FLtFXLoOZL9x4IeDk2+VA=="],
|
||||
"hono-openapi": ["@cpluspatch/hono-openapi@0.5.1", "", { "peerDependencies": { "@hono/standard-validator": "^0.1.2", "@sinclair/typebox": "^0.34.9", "@standard-community/standard-json": "^0.3.0-rc.1", "@standard-community/standard-openapi": "^0.2.0-rc.0", "arktype": "^2.0.0", "effect": "^3.16.12", "hono": "^4.8.3", "openapi-types": "^12.1.3", "valibot": "^1.0.0-beta.9", "zod": "^3.23.8" }, "optionalPeers": ["@hono/standard-validator", "@sinclair/typebox", "arktype", "effect", "hono", "valibot", "zod"] }, "sha512-lecsN4jEzIwDb1HfArk5BuaR1O1AG2i6Dmtkc+K9BCs0LWRMZ0iWqPvo5LOwTTPttR4oG+mg50vepYQ5imV5Pg=="],
|
||||
|
||||
"hono-rate-limiter": ["hono-rate-limiter@0.4.2", "", { "peerDependencies": { "hono": "^4.1.1" } }, "sha512-AAtFqgADyrmbDijcRTT/HJfwqfvhalya2Zo+MgfdrMPas3zSMD8SU03cv+ZsYwRU1swv7zgVt0shwN059yzhjw=="],
|
||||
|
||||
|
|
@ -1145,8 +1141,6 @@
|
|||
|
||||
"json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
|
||||
|
||||
"json-schema-walker": ["json-schema-walker@2.0.0", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "^11.1.0", "clone": "^2.1.2" } }, "sha512-nXN2cMky0Iw7Af28w061hmxaPDaML5/bQD9nwm1lOoIKEGjHcRGxqWe4MfrkYThYAPjSUhmsp4bJNoLAyVn9Xw=="],
|
||||
|
||||
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
|
||||
|
||||
"juice": ["juice@8.1.0", "", { "dependencies": { "cheerio": "1.0.0-rc.10", "commander": "^6.1.0", "mensch": "^0.3.4", "slick": "^1.12.2", "web-resource-inliner": "^6.0.1" }, "bin": { "juice": "bin/juice" } }, "sha512-FLzurJrx5Iv1e7CfBSZH68dC04EEvXvvVvPYB7Vx1WAuhCp1ZPIMtqxc+WTWxVkpTIC2Ach/GAv0rQbtGf6YMA=="],
|
||||
|
|
@ -1571,16 +1565,14 @@
|
|||
|
||||
"zod": ["zod@3.25.74", "", {}, "sha512-J8poo92VuhKjNknViHRAIuuN6li/EwFbAC8OedzI8uxpEPGiXHGQu9wemIAioIpqgfB4SySaJhdk0mH5Y4ICBg=="],
|
||||
|
||||
"zod-openapi": ["zod-openapi@4.2.4", "", { "peerDependencies": { "zod": "^3.21.4" } }, "sha512-tsrQpbpqFCXqVXUzi3TPwFhuMtLN3oNZobOtYnK6/5VkXsNdnIgyNr4r8no4wmYluaxzN3F7iS+8xCW8BmMQ8g=="],
|
||||
"zod-openapi": ["zod-openapi@5.0.0", "", { "peerDependencies": { "zod": "^3.25.74" } }, "sha512-fNwuOsflpILVVsx+3e8ODA0AnI60xGtMVWcvzv733ggEj7fVvE4NQMoOlQGbqIleyOdFQuc5N6cpO1BevApQig=="],
|
||||
|
||||
"zod-to-json-schema": ["zod-to-json-schema@3.24.6", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg=="],
|
||||
|
||||
"zod-validation-error": ["zod-validation-error@3.5.2", "", { "peerDependencies": { "zod": "^3.25.0" } }, "sha512-mdi7YOLtram5dzJ5aDtm1AG9+mxRma1iaMrZdYIpFO7epdKBUwLHIxTF8CPDeCQ828zAXYtizrKlEJAtzgfgrw=="],
|
||||
"zod-validation-error": ["zod-validation-error@4.0.0-beta.1", "", { "peerDependencies": { "zod": "^3.25.0" } }, "sha512-42DSXwZyDKeLHrug+luXt6RMaoYsgMXc68bCz9kOyk66k7XBG35cAxsu2Lg42uVrJ1kEem2RyHxMBAv25SeZzQ=="],
|
||||
|
||||
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
|
||||
|
||||
"@apidevtools/json-schema-ref-parser/js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
|
||||
|
||||
"@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
|
||||
|
|
@ -1619,6 +1611,8 @@
|
|||
|
||||
"@sentry/node/@opentelemetry/resources": ["@opentelemetry/resources@1.30.1", "", { "dependencies": { "@opentelemetry/core": "1.30.1", "@opentelemetry/semantic-conventions": "1.28.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA=="],
|
||||
|
||||
"@standard-community/standard-openapi/zod-openapi": ["zod-openapi@4.2.4", "", { "peerDependencies": { "zod": "^3.21.4" } }, "sha512-tsrQpbpqFCXqVXUzi3TPwFhuMtLN3oNZobOtYnK6/5VkXsNdnIgyNr4r8no4wmYluaxzN3F7iS+8xCW8BmMQ8g=="],
|
||||
|
||||
"@ts-morph/common/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||
|
||||
"@vue/compiler-core/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||
|
|
|
|||
18
package.json
18
package.json
|
|
@ -42,7 +42,6 @@
|
|||
"vitepress-plugin-tabs": "^0.7.1",
|
||||
"vitepress-sidebar": "^1.32.1",
|
||||
"vue": "^3.5.17",
|
||||
"zod-to-json-schema": "^3.24.6",
|
||||
"@bull-board/api": "^6.11.0",
|
||||
"@bull-board/hono": "^6.11.0",
|
||||
"@clerc/plugin-completions": "^0.44.0",
|
||||
|
|
@ -51,7 +50,7 @@
|
|||
"@clerc/plugin-not-found": "^0.44.0",
|
||||
"@clerc/plugin-version": "^0.44.0",
|
||||
"@hackmd/markdown-it-task-lists": "^2.1.4",
|
||||
"@hono/zod-validator": "^0.7.0",
|
||||
"@hono/standard-validator": "^0.1.2",
|
||||
"@inquirer/confirm": "^5.1.13",
|
||||
"@logtape/file": "^1.0.0",
|
||||
"@logtape/logtape": "^1.0.0",
|
||||
|
|
@ -68,7 +67,7 @@
|
|||
"drizzle-orm": "^0.44.2",
|
||||
"feed": "^5.1.0",
|
||||
"hono": "^4.8.4",
|
||||
"hono-openapi": "^0.4.8",
|
||||
"hono-openapi": "npm:@cpluspatch/hono-openapi@0.5.1",
|
||||
"hono-rate-limiter": "^0.4.2",
|
||||
"html-to-text": "^9.0.5",
|
||||
"ioredis": "^5.6.1",
|
||||
|
|
@ -99,8 +98,8 @@
|
|||
"xss": "^1.0.15",
|
||||
"youch": "^4.1.0-beta.7",
|
||||
"zod": "^3.25.74",
|
||||
"zod-openapi": "^4.2.4",
|
||||
"zod-validation-error": "^3.5.2"
|
||||
"zod-openapi": "^5.0.0",
|
||||
"zod-validation-error": "^4.0.0-beta.1"
|
||||
}
|
||||
},
|
||||
"maintainers": [
|
||||
|
|
@ -153,8 +152,7 @@
|
|||
"vitepress": "catalog:",
|
||||
"vitepress-plugin-tabs": "catalog:",
|
||||
"vitepress-sidebar": "catalog:",
|
||||
"vue": "catalog:",
|
||||
"zod-to-json-schema": "catalog:"
|
||||
"vue": "catalog:"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bull-board/api": "catalog:",
|
||||
|
|
@ -165,15 +163,15 @@
|
|||
"@clerc/plugin-not-found": "catalog:",
|
||||
"@clerc/plugin-version": "catalog:",
|
||||
"@hackmd/markdown-it-task-lists": "catalog:",
|
||||
"@hono/zod-validator": "catalog:",
|
||||
"@hono/standard-validator": "catalog:",
|
||||
"@inquirer/confirm": "catalog:",
|
||||
"@scalar/hono-api-reference": "catalog:",
|
||||
"@sentry/bun": "catalog:",
|
||||
"@versia-server/api": "workspace:*",
|
||||
"@versia-server/config": "workspace:*",
|
||||
"@versia-server/kit": "workspace:*",
|
||||
"@versia-server/tests": "workspace:*",
|
||||
"@versia-server/logging": "workspace:*",
|
||||
"@versia-server/api": "workspace:*",
|
||||
"@versia-server/tests": "workspace:*",
|
||||
"@versia-server/worker": "workspace:*",
|
||||
"@versia/client": "workspace:*",
|
||||
"@versia/sdk": "workspace:*",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { cors } from "hono/cors";
|
|||
import { createMiddleware } from "hono/factory";
|
||||
import { prettyJSON } from "hono/pretty-json";
|
||||
import { secureHeaders } from "hono/secure-headers";
|
||||
import { openAPISpecs } from "hono-openapi";
|
||||
import { generateSpecs } from "hono-openapi";
|
||||
import { Youch } from "youch";
|
||||
import { applyToHono } from "@/bull-board.ts";
|
||||
import pkg from "../../package.json" with { type: "application/json" };
|
||||
|
|
@ -22,8 +22,6 @@ import { logger } from "./middlewares/logger.ts";
|
|||
import { rateLimit } from "./middlewares/rate-limit.ts";
|
||||
import { PluginLoader } from "./plugin-loader.ts";
|
||||
import { routes } from "./routes.ts";
|
||||
// Extends Zod with OpenAPI schema generation
|
||||
import "zod-openapi/extend";
|
||||
|
||||
export const appFactory = async (): Promise<Hono<HonoEnv>> => {
|
||||
const app = new Hono<HonoEnv>({
|
||||
|
|
@ -127,22 +125,23 @@ export const appFactory = async (): Promise<Hono<HonoEnv>> => {
|
|||
(time2 - time1).toFixed(2),
|
||||
)}ms`}`;
|
||||
|
||||
app.get(
|
||||
"/openapi.json",
|
||||
openAPISpecs(app, {
|
||||
documentation: {
|
||||
info: {
|
||||
title: "Versia Server API",
|
||||
version: pkg.version,
|
||||
license: {
|
||||
name: "AGPL-3.0",
|
||||
url: "https://www.gnu.org/licenses/agpl-3.0.html",
|
||||
},
|
||||
contact: pkg.author,
|
||||
const openApiSpecs = await generateSpecs(app, {
|
||||
documentation: {
|
||||
info: {
|
||||
title: "Versia Server API",
|
||||
version: pkg.version,
|
||||
license: {
|
||||
name: "AGPL-3.0",
|
||||
url: "https://www.gnu.org/licenses/agpl-3.0.html",
|
||||
},
|
||||
contact: pkg.author,
|
||||
},
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
app.get("/openapi.json", (context) => {
|
||||
return context.json(openApiSpecs, 200);
|
||||
});
|
||||
|
||||
app.get(
|
||||
"/docs",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import type { ApiError } from "@versia-server/kit";
|
|||
import { env } from "bun";
|
||||
import type { MiddlewareHandler } from "hono";
|
||||
import { rateLimiter } from "hono-rate-limiter";
|
||||
import type { z } from "zod";
|
||||
import type { z } from "zod/v4";
|
||||
import type { HonoEnv } from "~/types/api";
|
||||
|
||||
// Not exported by hono-rate-limiter
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@
|
|||
"ip-matching": "catalog:",
|
||||
"qs": "catalog:",
|
||||
"altcha-lib": "catalog:",
|
||||
"@hono/zod-validator": "catalog:",
|
||||
"@hono/standard-validator": "catalog:",
|
||||
"zod-validation-error": "catalog:",
|
||||
"confbox": "catalog:",
|
||||
"oauth4webapi": "catalog:"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { file, sleep } from "bun";
|
|||
import chalk from "chalk";
|
||||
import { parseJSON5, parseJSONC } from "confbox";
|
||||
import type { Hono } from "hono";
|
||||
import type { ZodTypeAny } from "zod";
|
||||
import type { ZodTypeAny } from "zod/v4";
|
||||
import { fromZodError, type ValidationError } from "zod-validation-error";
|
||||
import type { HonoEnv } from "~/types/api";
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { User } from "@versia-server/kit/db";
|
|||
import { getCookie } from "hono/cookie";
|
||||
import { jwtVerify } from "jose";
|
||||
import { JOSEError, JWTExpired } from "jose/errors";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import authorizeRoute from "./routes/authorize.ts";
|
||||
import jwksRoute from "./routes/jwks.ts";
|
||||
import ssoLoginCallbackRoute from "./routes/oauth/callback.ts";
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@ import { RolePermission } from "@versia/client/schemas";
|
|||
import { auth, handleZodError, jsonOrForm } from "@versia-server/kit/api";
|
||||
import { Application, Token, User } from "@versia-server/kit/db";
|
||||
import { randomUUIDv7 } from "bun";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { validator } from "hono-openapi/zod";
|
||||
import { describeRoute, validator } from "hono-openapi";
|
||||
import { type JWTPayload, jwtVerify, SignJWT } from "jose";
|
||||
import { JOSEError } from "jose/errors";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import { randomString } from "@/math";
|
||||
import { errorRedirect, errors } from "../errors.ts";
|
||||
import type { PluginType } from "../index.ts";
|
||||
|
|
@ -50,7 +49,6 @@ export default (plugin: PluginType): void =>
|
|||
.object({
|
||||
scope: z.string().optional(),
|
||||
redirect_uri: z
|
||||
.string()
|
||||
.url()
|
||||
.optional()
|
||||
.or(z.literal("urn:ietf:wg:oauth:2.0:oob")),
|
||||
|
|
@ -141,7 +139,7 @@ export default (plugin: PluginType): void =>
|
|||
);
|
||||
}
|
||||
|
||||
if (!z.string().uuid().safeParse(sub).success) {
|
||||
if (!z.uuid().safeParse(sub).success) {
|
||||
return errorRedirect(
|
||||
context,
|
||||
errors.InvalidSub,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { auth } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
import { exportJWK } from "jose";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import type { PluginType } from "../index.ts";
|
||||
|
||||
export default (plugin: PluginType): void => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
Account as AccountSchema,
|
||||
RolePermission,
|
||||
zBoolean,
|
||||
} from "@versia/client/schemas";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { handleZodError } from "@versia-server/kit/api";
|
||||
|
|
@ -10,10 +11,9 @@ import { OpenIdAccounts, Users } from "@versia-server/kit/tables";
|
|||
import { randomUUIDv7 } from "bun";
|
||||
import { and, eq, isNull, type SQL } from "drizzle-orm";
|
||||
import { setCookie } from "hono/cookie";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { validator } from "hono-openapi/zod";
|
||||
import { describeRoute, validator } from "hono-openapi";
|
||||
import { SignJWT } from "jose";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import { randomString } from "@/math.ts";
|
||||
import type { PluginType } from "../../index.ts";
|
||||
import { automaticOidcFlow } from "../../utils.ts";
|
||||
|
|
@ -47,13 +47,8 @@ export default (plugin: PluginType): void => {
|
|||
z.object({
|
||||
client_id: z.string().optional(),
|
||||
flow: z.string(),
|
||||
link: z
|
||||
.string()
|
||||
.transform((v) =>
|
||||
["true", "1", "on"].includes(v.toLowerCase()),
|
||||
)
|
||||
.optional(),
|
||||
user_id: z.string().uuid().optional(),
|
||||
link: zBoolean.optional(),
|
||||
user_id: z.uuid().optional(),
|
||||
}),
|
||||
handleZodError,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@ import { handleZodError, jsonOrForm } from "@versia-server/kit/api";
|
|||
import { db, Token } from "@versia-server/kit/db";
|
||||
import { Tokens } from "@versia-server/kit/tables";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import type { PluginType } from "../../index.ts";
|
||||
|
||||
export default (plugin: PluginType): void => {
|
||||
|
|
|
|||
|
|
@ -2,15 +2,14 @@ import { handleZodError } from "@versia-server/kit/api";
|
|||
import { Application, db } from "@versia-server/kit/db";
|
||||
import { OpenIdLoginFlows } from "@versia-server/kit/tables";
|
||||
import { randomUUIDv7 } from "bun";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { validator } from "hono-openapi/zod";
|
||||
import { describeRoute, validator } from "hono-openapi";
|
||||
import {
|
||||
calculatePKCECodeChallenge,
|
||||
discoveryRequest,
|
||||
generateRandomCodeVerifier,
|
||||
processDiscoveryResponse,
|
||||
} from "oauth4webapi";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import type { PluginType } from "../../index.ts";
|
||||
import { oauthRedirectUri } from "../../utils.ts";
|
||||
|
||||
|
|
@ -34,7 +33,7 @@ export default (plugin: PluginType): void => {
|
|||
z.object({
|
||||
issuer: z.string(),
|
||||
client_id: z.string().optional(),
|
||||
redirect_uri: z.string().url().optional(),
|
||||
redirect_uri: z.url().optional(),
|
||||
scope: z.string().optional(),
|
||||
response_type: z.enum(["code"]).optional(),
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@ import { handleZodError, jsonOrForm } from "@versia-server/kit/api";
|
|||
import { Application, Token } from "@versia-server/kit/db";
|
||||
import { Tokens } from "@versia-server/kit/tables";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import type { PluginType } from "../../index.ts";
|
||||
|
||||
export default (plugin: PluginType): void => {
|
||||
|
|
@ -80,7 +79,7 @@ export default (plugin: PluginType): void => {
|
|||
client_secret: z.string().optional(),
|
||||
username: z.string().trim().optional(),
|
||||
password: z.string().trim().optional(),
|
||||
redirect_uri: z.string().url().optional(),
|
||||
redirect_uri: z.url().optional(),
|
||||
refresh_token: z.string().optional(),
|
||||
scope: z.string().optional(),
|
||||
assertion: z.string().optional(),
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@ import { auth, handleZodError } from "@versia-server/kit/api";
|
|||
import { db } from "@versia-server/kit/db";
|
||||
import { OpenIdAccounts } from "@versia-server/kit/tables";
|
||||
import { and, eq, type SQL } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import type { PluginType } from "../../../index.ts";
|
||||
|
||||
export default (plugin: PluginType): void => {
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@ import { auth, handleZodError } from "@versia-server/kit/api";
|
|||
import { Application, db } from "@versia-server/kit/db";
|
||||
import { OpenIdLoginFlows } from "@versia-server/kit/tables";
|
||||
import { randomUUIDv7 } from "bun";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import {
|
||||
calculatePKCECodeChallenge,
|
||||
generateRandomCodeVerifier,
|
||||
} from "oauth4webapi";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import type { PluginType } from "../../index.ts";
|
||||
import { oauthDiscoveryRequest, oauthRedirectUri } from "../../utils.ts";
|
||||
|
||||
|
|
|
|||
|
|
@ -7,10 +7,9 @@ import { password as bunPassword } from "bun";
|
|||
import { eq, or } from "drizzle-orm";
|
||||
import type { Context } from "hono";
|
||||
import { setCookie } from "hono/cookie";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { validator } from "hono-openapi/zod";
|
||||
import { describeRoute, validator } from "hono-openapi";
|
||||
import { SignJWT } from "jose";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
const returnError = (
|
||||
context: Context,
|
||||
|
|
@ -59,7 +58,7 @@ export default apiRoute((app) =>
|
|||
"query",
|
||||
z.object({
|
||||
scope: z.string().optional(),
|
||||
redirect_uri: z.string().url().optional(),
|
||||
redirect_uri: z.url().optional(),
|
||||
response_type: z.enum([
|
||||
"code",
|
||||
"token",
|
||||
|
|
@ -90,7 +89,6 @@ export default apiRoute((app) =>
|
|||
"form",
|
||||
z.object({
|
||||
identifier: z
|
||||
.string()
|
||||
.email()
|
||||
.toLowerCase()
|
||||
.or(z.string().toLowerCase()),
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@ import { apiRoute, handleZodError } from "@versia-server/kit/api";
|
|||
import { db } from "@versia-server/kit/db";
|
||||
import { Applications, Tokens } from "@versia-server/kit/tables";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
/**
|
||||
* OAuth Code flow
|
||||
|
|
@ -28,7 +27,7 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
redirect_uri: z.string().url(),
|
||||
redirect_uri: z.url(),
|
||||
client_id: z.string(),
|
||||
code: z.string(),
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ import { Users } from "@versia-server/kit/tables";
|
|||
import { password as bunPassword } from "bun";
|
||||
import { eq } from "drizzle-orm";
|
||||
import type { Context } from "hono";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
const returnError = (
|
||||
context: Context,
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import {
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withUserParam } from "@versia-server/kit/api";
|
||||
import { Relationship } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ import {
|
|||
handleZodError,
|
||||
withUserParam,
|
||||
} from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import { getFeed } from "@/rss";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
|
|
@ -39,12 +38,13 @@ export default apiRoute((app) =>
|
|||
RolePermission.ViewNotes,
|
||||
RolePermission.ViewAccounts,
|
||||
],
|
||||
|
||||
scopes: ["read:statuses"],
|
||||
}),
|
||||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
page: z.coerce.number().default(0).openapi({
|
||||
page: z.coerce.number().default(0).meta({
|
||||
description: "Page number to fetch. Defaults to 0.",
|
||||
example: 2,
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ import {
|
|||
handleZodError,
|
||||
withUserParam,
|
||||
} from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import { getFeed } from "@/rss";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
|
|
@ -38,12 +37,13 @@ export default apiRoute((app) =>
|
|||
RolePermission.ViewNotes,
|
||||
RolePermission.ViewAccounts,
|
||||
],
|
||||
|
||||
scopes: ["read:statuses"],
|
||||
}),
|
||||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
page: z.coerce.number().default(0).openapi({
|
||||
page: z.coerce.number().default(0).meta({
|
||||
description: "Page number to fetch. Defaults to 0.",
|
||||
example: 2,
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -11,9 +11,8 @@ import {
|
|||
withUserParam,
|
||||
} from "@versia-server/kit/api";
|
||||
import { Relationship } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
@ -62,12 +61,12 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"json",
|
||||
z.object({
|
||||
reblogs: z.boolean().default(true).openapi({
|
||||
reblogs: z.boolean().default(true).meta({
|
||||
description:
|
||||
"Receive this account’s reblogs in home timeline?",
|
||||
example: true,
|
||||
}),
|
||||
notify: z.boolean().default(false).openapi({
|
||||
notify: z.boolean().default(false).meta({
|
||||
description:
|
||||
"Receive notifications when this account posts a status?",
|
||||
example: false,
|
||||
|
|
@ -75,7 +74,7 @@ export default apiRoute((app) =>
|
|||
languages: z
|
||||
.array(iso631)
|
||||
.default([])
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Array of String (ISO 639-1 language two-letter code). Filter received statuses for these languages. If not provided, you will receive this account’s posts in all languages.",
|
||||
example: ["en", "fr"],
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@ import {
|
|||
import { Timeline } from "@versia-server/kit/db";
|
||||
import { Users } from "@versia-server/kit/tables";
|
||||
import { and, gt, gte, lt, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
@ -39,7 +38,7 @@ export default apiRoute((app) =>
|
|||
link: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Links to the next and previous pages",
|
||||
example:
|
||||
|
|
@ -66,22 +65,22 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
max_id: AccountSchema.shape.id.optional().openapi({
|
||||
max_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be lesser than this ID. In effect, sets an upper bound on results.",
|
||||
example: "8d35243d-b959-43e2-8bac-1a9d4eaea2aa",
|
||||
}),
|
||||
since_id: AccountSchema.shape.id.optional().openapi({
|
||||
since_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be greater than this ID. In effect, sets a lower bound on results.",
|
||||
example: undefined,
|
||||
}),
|
||||
min_id: AccountSchema.shape.id.optional().openapi({
|
||||
min_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.",
|
||||
example: undefined,
|
||||
}),
|
||||
limit: z.number().int().min(1).max(40).default(20).openapi({
|
||||
limit: z.number().int().min(1).max(40).default(20).meta({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@ import {
|
|||
import { Timeline } from "@versia-server/kit/db";
|
||||
import { Users } from "@versia-server/kit/tables";
|
||||
import { and, gt, gte, lt, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
@ -40,7 +39,7 @@ export default apiRoute((app) =>
|
|||
link: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Links to the next and previous pages",
|
||||
example:
|
||||
|
|
@ -67,22 +66,22 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
max_id: AccountSchema.shape.id.optional().openapi({
|
||||
max_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be lesser than this ID. In effect, sets an upper bound on results.",
|
||||
example: "8d35243d-b959-43e2-8bac-1a9d4eaea2aa",
|
||||
}),
|
||||
since_id: AccountSchema.shape.id.optional().openapi({
|
||||
since_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be greater than this ID. In effect, sets a lower bound on results.",
|
||||
example: undefined,
|
||||
}),
|
||||
min_id: AccountSchema.shape.id.optional().openapi({
|
||||
min_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.",
|
||||
example: undefined,
|
||||
}),
|
||||
limit: z.number().int().min(1).max(40).default(20).openapi({
|
||||
limit: z.number().int().min(1).max(40).default(20).meta({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ import {
|
|||
} from "@versia/client/schemas";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withUserParam } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@ import {
|
|||
RelationshipJobType,
|
||||
relationshipQueue,
|
||||
} from "@versia-server/kit/queues/relationships";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
@ -56,7 +55,7 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"json",
|
||||
z.object({
|
||||
notifications: z.boolean().default(true).openapi({
|
||||
notifications: z.boolean().default(true).meta({
|
||||
description: "Mute notifications in addition to statuses?",
|
||||
}),
|
||||
duration: z
|
||||
|
|
@ -65,7 +64,7 @@ export default apiRoute((app) =>
|
|||
.min(0)
|
||||
.max(60 * 60 * 24 * 365 * 5)
|
||||
.default(0)
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"How long the mute should last, in seconds. 0 means indefinite.",
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -10,9 +10,8 @@ import {
|
|||
withUserParam,
|
||||
} from "@versia-server/kit/api";
|
||||
import { Relationship } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
@ -50,7 +49,7 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"json",
|
||||
z.object({
|
||||
comment: RelationshipSchema.shape.note.optional().openapi({
|
||||
comment: RelationshipSchema.shape.note.optional().meta({
|
||||
description:
|
||||
"The comment to be set on that user. Provide an empty string or leave out this parameter to clear the currently set note.",
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ import {
|
|||
} from "@versia/client/schemas";
|
||||
import { apiRoute, auth, withUserParam } from "@versia-server/kit/api";
|
||||
import { Relationship } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import {
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withUserParam } from "@versia-server/kit/api";
|
||||
import { User } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import {
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withUserParam } from "@versia-server/kit/api";
|
||||
import { Relationship } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -11,9 +11,8 @@ import {
|
|||
withUserParam,
|
||||
} from "@versia-server/kit/api";
|
||||
import { Role } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) => {
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import { Role as RoleSchema } from "@versia/client/schemas";
|
||||
import { apiRoute, auth, withUserParam } from "@versia-server/kit/api";
|
||||
import { Role } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) => {
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -13,9 +13,8 @@ import {
|
|||
import { Timeline } from "@versia-server/kit/db";
|
||||
import { Notes } from "@versia-server/kit/tables";
|
||||
import { and, eq, gt, gte, inArray, isNull, lt, or, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
@ -47,50 +46,45 @@ export default apiRoute((app) =>
|
|||
RolePermission.ViewNotes,
|
||||
RolePermission.ViewAccounts,
|
||||
],
|
||||
|
||||
scopes: ["read:statuses"],
|
||||
}),
|
||||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
max_id: StatusSchema.shape.id.optional().openapi({
|
||||
max_id: StatusSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be lesser than this ID. In effect, sets an upper bound on results.",
|
||||
example: "8d35243d-b959-43e2-8bac-1a9d4eaea2aa",
|
||||
}),
|
||||
since_id: StatusSchema.shape.id.optional().openapi({
|
||||
since_id: StatusSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be greater than this ID. In effect, sets a lower bound on results.",
|
||||
example: undefined,
|
||||
}),
|
||||
min_id: StatusSchema.shape.id.optional().openapi({
|
||||
min_id: StatusSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.",
|
||||
example: undefined,
|
||||
}),
|
||||
limit: z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.max(40)
|
||||
.default(20)
|
||||
.openapi({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
only_media: zBoolean.default(false).openapi({
|
||||
limit: z.coerce.number().int().min(1).max(40).default(20).meta({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
only_media: zBoolean.default(false).meta({
|
||||
description: "Filter out statuses without attachments.",
|
||||
}),
|
||||
exclude_replies: zBoolean.default(false).openapi({
|
||||
exclude_replies: zBoolean.default(false).meta({
|
||||
description:
|
||||
"Filter out statuses in reply to a different account.",
|
||||
}),
|
||||
exclude_reblogs: zBoolean.default(false).openapi({
|
||||
exclude_reblogs: zBoolean.default(false).meta({
|
||||
description: "Filter out boosts from the response.",
|
||||
}),
|
||||
pinned: zBoolean.default(false).openapi({
|
||||
pinned: zBoolean.default(false).meta({
|
||||
description:
|
||||
"Filter for pinned statuses only. Pinned statuses do not receive special priority in the order of the returned results.",
|
||||
}),
|
||||
tagged: z.string().optional().openapi({
|
||||
tagged: z.string().optional().meta({
|
||||
description:
|
||||
"Filter for statuses using a specific hashtag.",
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import {
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withUserParam } from "@versia-server/kit/api";
|
||||
import { Relationship } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import {
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withUserParam } from "@versia-server/kit/api";
|
||||
import { Relationship } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import {
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withUserParam } from "@versia-server/kit/api";
|
||||
import { Relationship } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import {
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withUserParam } from "@versia-server/kit/api";
|
||||
import { Relationship } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -13,9 +13,8 @@ import {
|
|||
import { db, User } from "@versia-server/kit/db";
|
||||
import type { Users } from "@versia-server/kit/tables";
|
||||
import { type InferSelectModel, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import { rateLimit } from "../../../../../middlewares/rate-limit.ts";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
|
|
@ -56,8 +55,8 @@ export default apiRoute((app) =>
|
|||
.array(AccountSchema.shape.id)
|
||||
.min(1)
|
||||
.max(10)
|
||||
.or(AccountSchema.shape.id.transform((v) => [v]))
|
||||
.openapi({
|
||||
.or(AccountSchema.shape.id)
|
||||
.meta({
|
||||
description:
|
||||
"Find familiar followers for the provided account IDs.",
|
||||
example: [
|
||||
|
|
@ -70,11 +69,11 @@ export default apiRoute((app) =>
|
|||
),
|
||||
async (context) => {
|
||||
const { user } = context.get("auth");
|
||||
const { id: ids } = context.req.valid("query");
|
||||
const { id } = context.req.valid("query");
|
||||
|
||||
// Find followers of the accounts in "ids", that you also follow
|
||||
const finalUsers = await Promise.all(
|
||||
ids.map(async (id) => ({
|
||||
(Array.isArray(id) ? id : [id]).map(async (id) => ({
|
||||
id,
|
||||
accounts: await User.fromIds(
|
||||
(
|
||||
|
|
|
|||
|
|
@ -12,38 +12,37 @@ import { User } from "@versia-server/kit/db";
|
|||
import { searchManager } from "@versia-server/kit/search";
|
||||
import { Users } from "@versia-server/kit/tables";
|
||||
import { and, eq, isNull } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import ISO6391 from "iso-639-1";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import { tempmailDomains } from "@/tempmail";
|
||||
import { rateLimit } from "../../../../middlewares/rate-limit.ts";
|
||||
|
||||
const schema = z.object({
|
||||
username: z.string().openapi({
|
||||
username: z.string().meta({
|
||||
description: "The desired username for the account",
|
||||
example: "alice",
|
||||
}),
|
||||
email: z.string().toLowerCase().openapi({
|
||||
email: z.string().toLowerCase().meta({
|
||||
description:
|
||||
"The email address to be used for login. Transformed to lowercase.",
|
||||
example: "alice@gmail.com",
|
||||
}),
|
||||
password: z.string().openapi({
|
||||
password: z.string().meta({
|
||||
description: "The password to be used for login",
|
||||
example: "hunter2",
|
||||
}),
|
||||
agreement: zBoolean.openapi({
|
||||
agreement: zBoolean.meta({
|
||||
description:
|
||||
"Whether the user agrees to the local rules, terms, and policies. These should be presented to the user in order to allow them to consent before setting this parameter to TRUE.",
|
||||
example: true,
|
||||
}),
|
||||
locale: z.string().openapi({
|
||||
locale: z.string().meta({
|
||||
description:
|
||||
"The language of the confirmation email that will be sent. ISO 639-1 code.",
|
||||
example: "en",
|
||||
}),
|
||||
reason: z.string().optional().openapi({
|
||||
reason: z.string().optional().meta({
|
||||
description:
|
||||
"If registrations require manual approval, this text will be reviewed by moderators.",
|
||||
}),
|
||||
|
|
@ -86,8 +85,8 @@ export default apiRoute((app) => {
|
|||
.array(AccountSchema.shape.id)
|
||||
.min(1)
|
||||
.max(40)
|
||||
.or(AccountSchema.shape.id.transform((v) => [v]))
|
||||
.openapi({
|
||||
.or(AccountSchema.shape.id)
|
||||
.meta({
|
||||
description: "The IDs of the Accounts in the database.",
|
||||
example: [
|
||||
"f137ce6f-ff5e-4998-b20f-0361ba9be007",
|
||||
|
|
@ -98,10 +97,10 @@ export default apiRoute((app) => {
|
|||
handleZodError,
|
||||
),
|
||||
async (context) => {
|
||||
const { id: ids } = context.req.valid("query");
|
||||
const { id } = context.req.valid("query");
|
||||
|
||||
// Find accounts by IDs
|
||||
const accounts = await User.fromIds(ids);
|
||||
const accounts = await User.fromIds(Array.isArray(id) ? id : [id]);
|
||||
|
||||
return context.json(
|
||||
accounts.map((account) => account.toApi()),
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@ import { Instance, User } from "@versia-server/kit/db";
|
|||
import { parseUserAddress } from "@versia-server/kit/parsers";
|
||||
import { Users } from "@versia-server/kit/tables";
|
||||
import { and, eq, isNull } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import { rateLimit } from "../../../../../middlewares/rate-limit.ts";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
|
|
@ -43,7 +42,7 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
acct: AccountSchema.shape.acct.openapi({
|
||||
acct: AccountSchema.shape.acct.meta({
|
||||
description: "The username or Webfinger address to lookup.",
|
||||
example: "lexi@beta.versia.social",
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@ import {
|
|||
qsQuery,
|
||||
} from "@versia-server/kit/api";
|
||||
import { Relationship } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import { rateLimit } from "../../../../../middlewares/rate-limit.ts";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
|
|
@ -55,8 +54,8 @@ export default apiRoute((app) =>
|
|||
.array(AccountSchema.shape.id)
|
||||
.min(1)
|
||||
.max(10)
|
||||
.or(AccountSchema.shape.id.transform((v) => [v]))
|
||||
.openapi({
|
||||
.or(AccountSchema.shape.id)
|
||||
.meta({
|
||||
description:
|
||||
"Check relationships for the provided account IDs.",
|
||||
example: [
|
||||
|
|
@ -64,7 +63,7 @@ export default apiRoute((app) =>
|
|||
"8424c654-5d03-4a1b-bec8-4e87db811b5d",
|
||||
],
|
||||
}),
|
||||
with_suspended: zBoolean.default(false).openapi({
|
||||
with_suspended: zBoolean.default(false).meta({
|
||||
description:
|
||||
"Whether relationships should be returned for suspended users",
|
||||
example: false,
|
||||
|
|
@ -76,17 +75,16 @@ export default apiRoute((app) =>
|
|||
const { user } = context.get("auth");
|
||||
|
||||
// TODO: Implement with_suspended
|
||||
const { id: ids } = context.req.valid("query");
|
||||
const { id } = context.req.valid("query");
|
||||
|
||||
const relationships = await Relationship.fromOwnerAndSubjects(
|
||||
user,
|
||||
ids,
|
||||
Array.isArray(id) ? id : [id],
|
||||
);
|
||||
|
||||
relationships.sort(
|
||||
(a, b) =>
|
||||
ids.indexOf(a.data.subjectId) -
|
||||
ids.indexOf(b.data.subjectId),
|
||||
id.indexOf(a.data.subjectId) - id.indexOf(b.data.subjectId),
|
||||
);
|
||||
|
||||
return context.json(
|
||||
|
|
|
|||
|
|
@ -9,10 +9,9 @@ import { User } from "@versia-server/kit/db";
|
|||
import { parseUserAddress } from "@versia-server/kit/parsers";
|
||||
import { Users } from "@versia-server/kit/tables";
|
||||
import { eq, ilike, not, or, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import stringComparison from "string-comparison";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
import { rateLimit } from "../../../../../middlewares/rate-limit.ts";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
|
|
@ -48,30 +47,24 @@ export default apiRoute((app) =>
|
|||
z.object({
|
||||
q: AccountSchema.shape.username
|
||||
.or(AccountSchema.shape.acct)
|
||||
.openapi({
|
||||
.meta({
|
||||
description: "Search query for accounts.",
|
||||
example: "username",
|
||||
}),
|
||||
limit: z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.max(80)
|
||||
.default(40)
|
||||
.openapi({
|
||||
description: "Maximum number of results.",
|
||||
example: 40,
|
||||
}),
|
||||
offset: z.coerce.number().int().default(0).openapi({
|
||||
limit: z.coerce.number().int().min(1).max(80).default(40).meta({
|
||||
description: "Maximum number of results.",
|
||||
example: 40,
|
||||
}),
|
||||
offset: z.coerce.number().int().default(0).meta({
|
||||
description: "Skip the first n results.",
|
||||
example: 0,
|
||||
}),
|
||||
resolve: zBoolean.default(false).openapi({
|
||||
resolve: zBoolean.default(false).meta({
|
||||
description:
|
||||
"Attempt WebFinger lookup. Use this when q is an exact address.",
|
||||
example: false,
|
||||
}),
|
||||
following: zBoolean.default(false).openapi({
|
||||
following: zBoolean.default(false).meta({
|
||||
description: "Limit the search to users you are following.",
|
||||
example: false,
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -16,9 +16,8 @@ import { Emoji, Media, User } from "@versia-server/kit/db";
|
|||
import { versiaTextToHtml } from "@versia-server/kit/parsers";
|
||||
import { Users } from "@versia-server/kit/tables";
|
||||
import { and, eq, isNull } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import { mergeAndDeduplicate } from "@/lib";
|
||||
import { sanitizedHtmlStrip } from "@/sanitization";
|
||||
import { rateLimit } from "../../../../../middlewares/rate-limit.ts";
|
||||
|
|
@ -58,7 +57,7 @@ export default apiRoute((app) =>
|
|||
z
|
||||
.object({
|
||||
display_name: AccountSchema.shape.display_name
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"The display name to use for the profile.",
|
||||
example: "Lexi",
|
||||
|
|
@ -75,7 +74,7 @@ export default apiRoute((app) =>
|
|||
"Display name contains blocked words",
|
||||
),
|
||||
username: AccountSchema.shape.username
|
||||
.openapi({
|
||||
.meta({
|
||||
description: "The username to use for the profile.",
|
||||
example: "lexi",
|
||||
})
|
||||
|
|
@ -95,7 +94,7 @@ export default apiRoute((app) =>
|
|||
"Username is disallowed",
|
||||
),
|
||||
note: AccountSchema.shape.note
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"The account bio. Markdown is supported.",
|
||||
})
|
||||
|
|
@ -108,72 +107,60 @@ export default apiRoute((app) =>
|
|||
"Bio contains blocked words",
|
||||
),
|
||||
avatar: z
|
||||
.string()
|
||||
.url()
|
||||
.transform((a) => new URL(a))
|
||||
.openapi({
|
||||
.meta({
|
||||
description: "Avatar image URL",
|
||||
})
|
||||
.or(
|
||||
z
|
||||
.instanceof(File)
|
||||
.refine(
|
||||
(v) =>
|
||||
v.size <=
|
||||
config.validation.accounts
|
||||
.max_avatar_bytes,
|
||||
`Avatar must be less than ${config.validation.accounts.max_avatar_bytes} bytes`,
|
||||
.file()
|
||||
.max(
|
||||
config.validation.accounts.max_avatar_bytes,
|
||||
)
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Avatar image encoded using multipart/form-data",
|
||||
}),
|
||||
),
|
||||
header: z
|
||||
.string()
|
||||
.url()
|
||||
.transform((v) => new URL(v))
|
||||
.openapi({
|
||||
.meta({
|
||||
description: "Header image URL",
|
||||
})
|
||||
.or(
|
||||
z
|
||||
.instanceof(File)
|
||||
.refine(
|
||||
(v) =>
|
||||
v.size <=
|
||||
config.validation.accounts
|
||||
.max_header_bytes,
|
||||
`Header must be less than ${config.validation.accounts.max_header_bytes} bytes`,
|
||||
.file()
|
||||
.max(
|
||||
config.validation.accounts.max_header_bytes,
|
||||
)
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Header image encoded using multipart/form-data",
|
||||
}),
|
||||
),
|
||||
locked: AccountSchema.shape.locked.openapi({
|
||||
locked: AccountSchema.shape.locked.meta({
|
||||
description:
|
||||
"Whether manual approval of follow requests is required.",
|
||||
}),
|
||||
bot: AccountSchema.shape.bot.openapi({
|
||||
bot: AccountSchema.shape.bot.meta({
|
||||
description: "Whether the account has a bot flag.",
|
||||
}),
|
||||
discoverable: AccountSchema.shape.discoverable
|
||||
.unwrap()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Whether the account should be shown in the profile directory.",
|
||||
}),
|
||||
hide_collections: zBoolean.openapi({
|
||||
hide_collections: zBoolean.meta({
|
||||
description:
|
||||
"Whether to hide followers and followed accounts.",
|
||||
}),
|
||||
indexable: zBoolean.openapi({
|
||||
indexable: zBoolean.meta({
|
||||
description:
|
||||
"Whether public posts should be searchable to anyone.",
|
||||
}),
|
||||
// TODO: Implement :(
|
||||
attribution_domains: z.array(z.string()).openapi({
|
||||
attribution_domains: z.array(z.string()).meta({
|
||||
description:
|
||||
"Domains of websites allowed to credit the account.",
|
||||
example: ["cnn.com", "myblog.com"],
|
||||
|
|
@ -287,9 +274,9 @@ export default apiRoute((app) =>
|
|||
user.avatar = await Media.fromFile(avatar);
|
||||
}
|
||||
} else if (user.avatar) {
|
||||
await user.avatar.updateFromUrl(avatar);
|
||||
await user.avatar.updateFromUrl(new URL(avatar));
|
||||
} else {
|
||||
user.avatar = await Media.fromUrl(avatar);
|
||||
user.avatar = await Media.fromUrl(new URL(avatar));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -301,9 +288,9 @@ export default apiRoute((app) =>
|
|||
user.header = await Media.fromFile(header);
|
||||
}
|
||||
} else if (user.header) {
|
||||
await user.header.updateFromUrl(header);
|
||||
await user.header.updateFromUrl(new URL(header));
|
||||
} else {
|
||||
user.header = await Media.fromUrl(header);
|
||||
user.header = await Media.fromUrl(new URL(header));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { Account } from "@versia/client/schemas";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ import { ApiError } from "@versia-server/kit";
|
|||
import { apiRoute, handleZodError, jsonOrForm } from "@versia-server/kit/api";
|
||||
import { Application } from "@versia-server/kit/db";
|
||||
import { randomUUIDv7 } from "bun";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import { randomString } from "@/math";
|
||||
import { rateLimit } from "../../../../middlewares/rate-limit.ts";
|
||||
|
||||
|
|
@ -43,22 +42,20 @@ export default apiRoute((app) =>
|
|||
z.object({
|
||||
client_name: ApplicationSchema.shape.name,
|
||||
redirect_uris: ApplicationSchema.shape.redirect_uris.or(
|
||||
ApplicationSchema.shape.redirect_uri.transform((u) =>
|
||||
u.split("\n"),
|
||||
),
|
||||
ApplicationSchema.shape.redirect_uri,
|
||||
),
|
||||
scopes: z
|
||||
.string()
|
||||
.default("read")
|
||||
.transform((s) => s.split(" "))
|
||||
.openapi({
|
||||
description: "Space separated list of scopes.",
|
||||
}),
|
||||
scopes: z.string().default("read").meta({
|
||||
description: "Space separated list of scopes.",
|
||||
type: "string",
|
||||
}),
|
||||
// Allow empty websites because Traewelling decides to give an empty
|
||||
// value instead of not providing anything at all
|
||||
website: ApplicationSchema.shape.website
|
||||
.optional()
|
||||
.or(z.literal("").transform(() => undefined)),
|
||||
.or(z.literal(""))
|
||||
.meta({
|
||||
type: "string",
|
||||
}),
|
||||
}),
|
||||
handleZodError,
|
||||
),
|
||||
|
|
@ -69,9 +66,11 @@ export default apiRoute((app) =>
|
|||
const app = await Application.insert({
|
||||
id: randomUUIDv7(),
|
||||
name: client_name,
|
||||
redirectUri: redirect_uris.join("\n"),
|
||||
scopes: scopes.join(" "),
|
||||
website,
|
||||
redirectUri: Array.isArray(redirect_uris)
|
||||
? redirect_uris.join("\n")
|
||||
: redirect_uris,
|
||||
scopes,
|
||||
website: website || undefined,
|
||||
clientId: randomString(32, "base64url"),
|
||||
secret: randomString(64, "base64url"),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import {
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth } from "@versia-server/kit/api";
|
||||
import { Application } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@ import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
|||
import { Timeline } from "@versia-server/kit/db";
|
||||
import { Users } from "@versia-server/kit/tables";
|
||||
import { and, gt, gte, lt, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
@ -33,7 +32,7 @@ export default apiRoute((app) =>
|
|||
link: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Links to the next and previous pages",
|
||||
example:
|
||||
|
|
@ -56,30 +55,24 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
max_id: AccountSchema.shape.id.optional().openapi({
|
||||
max_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be lesser than this ID. In effect, sets an upper bound on results.",
|
||||
example: "8d35243d-b959-43e2-8bac-1a9d4eaea2aa",
|
||||
}),
|
||||
since_id: AccountSchema.shape.id.optional().openapi({
|
||||
since_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be greater than this ID. In effect, sets a lower bound on results.",
|
||||
example: undefined,
|
||||
}),
|
||||
min_id: AccountSchema.shape.id.optional().openapi({
|
||||
min_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.",
|
||||
example: undefined,
|
||||
}),
|
||||
limit: z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.max(80)
|
||||
.default(40)
|
||||
.openapi({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
limit: z.coerce.number().int().min(1).max(80).default(40).meta({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
}),
|
||||
handleZodError,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import { Challenge } from "@versia/client/schemas";
|
|||
import { config } from "@versia-server/config";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
import { generateChallenge } from "@/challenges";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@ import { apiRoute, auth } from "@versia-server/kit/api";
|
|||
import { Emoji } from "@versia-server/kit/db";
|
||||
import { Emojis } from "@versia-server/kit/tables";
|
||||
import { and, eq, isNull, or } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -11,9 +11,8 @@ import {
|
|||
jsonOrForm,
|
||||
withEmojiParam,
|
||||
} from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import { mimeLookup } from "@/content_types";
|
||||
|
||||
export default apiRoute((app) => {
|
||||
|
|
@ -123,25 +122,18 @@ export default apiRoute((app) => {
|
|||
"Shortcode contains blocked words",
|
||||
),
|
||||
element: z
|
||||
.string()
|
||||
.url()
|
||||
.transform((a) => new URL(a))
|
||||
.openapi({
|
||||
.meta({
|
||||
description: "Emoji image URL",
|
||||
})
|
||||
.or(
|
||||
z
|
||||
.instanceof(File)
|
||||
.openapi({
|
||||
.file()
|
||||
.max(config.validation.emojis.max_bytes)
|
||||
.meta({
|
||||
description:
|
||||
"Emoji image encoded using multipart/form-data",
|
||||
})
|
||||
.refine(
|
||||
(v) =>
|
||||
v.size <=
|
||||
config.validation.emojis.max_bytes,
|
||||
`Emoji must be less than ${config.validation.emojis.max_bytes} bytes`,
|
||||
),
|
||||
}),
|
||||
),
|
||||
category: CustomEmojiSchema.shape.category.optional(),
|
||||
alt: CustomEmojiSchema.shape.description
|
||||
|
|
@ -195,7 +187,7 @@ export default apiRoute((app) => {
|
|||
const contentType =
|
||||
element instanceof File
|
||||
? element.type
|
||||
: await mimeLookup(element);
|
||||
: await mimeLookup(new URL(element));
|
||||
|
||||
if (!contentType.startsWith("image/")) {
|
||||
throw new ApiError(
|
||||
|
|
@ -208,7 +200,7 @@ export default apiRoute((app) => {
|
|||
if (element instanceof File) {
|
||||
await emoji.media.updateFromFile(element);
|
||||
} else {
|
||||
await emoji.media.updateFromUrl(element);
|
||||
await emoji.media.updateFromUrl(new URL(element));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@ import { Emoji, Media } from "@versia-server/kit/db";
|
|||
import { Emojis } from "@versia-server/kit/tables";
|
||||
import { randomUUIDv7 } from "bun";
|
||||
import { and, eq, isNull, or } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import { mimeLookup } from "@/content_types";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
|
|
@ -60,25 +59,15 @@ export default apiRoute((app) =>
|
|||
"Shortcode contains blocked words",
|
||||
),
|
||||
element: z
|
||||
.string()
|
||||
.url()
|
||||
.transform((a) => new URL(a))
|
||||
.openapi({
|
||||
.meta({
|
||||
description: "Emoji image URL",
|
||||
})
|
||||
.or(
|
||||
z
|
||||
.instanceof(File)
|
||||
.openapi({
|
||||
description:
|
||||
"Emoji image encoded using multipart/form-data",
|
||||
})
|
||||
.refine(
|
||||
(v) =>
|
||||
v.size <=
|
||||
config.validation.emojis.max_bytes,
|
||||
`Emoji must be less than ${config.validation.emojis.max_bytes} bytes`,
|
||||
),
|
||||
z.file().max(config.validation.emojis.max_bytes).meta({
|
||||
description:
|
||||
"Emoji image encoded using multipart/form-data",
|
||||
}),
|
||||
),
|
||||
category: CustomEmojiSchema.shape.category.optional(),
|
||||
alt: CustomEmojiSchema.shape.description
|
||||
|
|
@ -123,7 +112,7 @@ export default apiRoute((app) =>
|
|||
const contentType =
|
||||
element instanceof File
|
||||
? element.type
|
||||
: await mimeLookup(element);
|
||||
: await mimeLookup(new URL(element));
|
||||
|
||||
if (!contentType.startsWith("image/")) {
|
||||
throw new ApiError(
|
||||
|
|
@ -138,7 +127,7 @@ export default apiRoute((app) =>
|
|||
? await Media.fromFile(element, {
|
||||
description: alt ?? undefined,
|
||||
})
|
||||
: await Media.fromUrl(element, {
|
||||
: await Media.fromUrl(new URL(element), {
|
||||
description: alt ?? undefined,
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@ import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
|||
import { Timeline } from "@versia-server/kit/db";
|
||||
import { Notes } from "@versia-server/kit/tables";
|
||||
import { and, gt, gte, lt, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
@ -30,7 +29,7 @@ export default apiRoute((app) =>
|
|||
link: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Links to the next and previous pages",
|
||||
example:
|
||||
|
|
@ -52,30 +51,24 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
max_id: StatusSchema.shape.id.optional().openapi({
|
||||
max_id: StatusSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be lesser than this ID. In effect, sets an upper bound on results.",
|
||||
example: "8d35243d-b959-43e2-8bac-1a9d4eaea2aa",
|
||||
}),
|
||||
since_id: StatusSchema.shape.id.optional().openapi({
|
||||
since_id: StatusSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be greater than this ID. In effect, sets a lower bound on results.",
|
||||
example: undefined,
|
||||
}),
|
||||
min_id: StatusSchema.shape.id.optional().openapi({
|
||||
min_id: StatusSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.",
|
||||
example: undefined,
|
||||
}),
|
||||
limit: z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.max(80)
|
||||
.default(40)
|
||||
.openapi({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
limit: z.coerce.number().int().min(1).max(80).default(40).meta({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
}),
|
||||
handleZodError,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ import {
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
||||
import { Relationship, User } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ import {
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
||||
import { Relationship, User } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@ import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
|||
import { Timeline } from "@versia-server/kit/db";
|
||||
import { Users } from "@versia-server/kit/tables";
|
||||
import { and, gt, gte, lt, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
@ -35,7 +34,7 @@ export default apiRoute((app) =>
|
|||
link: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Links to the next and previous pages",
|
||||
example:
|
||||
|
|
@ -57,30 +56,24 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
max_id: AccountSchema.shape.id.optional().openapi({
|
||||
max_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be lesser than this ID. In effect, sets an upper bound on results.",
|
||||
example: "8d35243d-b959-43e2-8bac-1a9d4eaea2aa",
|
||||
}),
|
||||
since_id: AccountSchema.shape.id.optional().openapi({
|
||||
since_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be greater than this ID. In effect, sets a lower bound on results.",
|
||||
example: undefined,
|
||||
}),
|
||||
min_id: AccountSchema.shape.id.optional().openapi({
|
||||
min_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.",
|
||||
example: undefined,
|
||||
}),
|
||||
limit: z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.max(80)
|
||||
.default(40)
|
||||
.openapi({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
limit: z.coerce.number().int().min(1).max(80).default(40).meta({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
}),
|
||||
handleZodError,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { config } from "@versia-server/config";
|
||||
import { apiRoute } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import { ExtendedDescription as ExtendedDescriptionSchema } from "@versia/client
|
|||
import { config } from "@versia-server/config";
|
||||
import { apiRoute } from "@versia-server/kit/api";
|
||||
import { markdownToHtml } from "@versia-server/kit/markdown";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ import { Instance, Note, User } from "@versia-server/kit/db";
|
|||
import { markdownToHtml } from "@versia-server/kit/markdown";
|
||||
import { Users } from "@versia-server/kit/tables";
|
||||
import { and, eq, isNull } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import type { z } from "zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
import type { z } from "zod/v4";
|
||||
import manifest from "../../../../../../package.json" with { type: "json" };
|
||||
|
||||
export default apiRoute((app) =>
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import { PrivacyPolicy as PrivacyPolicySchema } from "@versia/client/schemas";
|
|||
import { config } from "@versia-server/config";
|
||||
import { apiRoute } from "@versia-server/kit/api";
|
||||
import { markdownToHtml } from "@versia-server/kit/markdown";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import { Rule as RuleSchema } from "@versia/client/schemas";
|
||||
import { config } from "@versia-server/config";
|
||||
import { apiRoute } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import { TermsOfService as TermsOfServiceSchema } from "@versia/client/schemas";
|
|||
import { config } from "@versia-server/config";
|
||||
import { apiRoute } from "@versia-server/kit/api";
|
||||
import { markdownToHtml } from "@versia-server/kit/markdown";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -10,9 +10,8 @@ import { db } from "@versia-server/kit/db";
|
|||
import { Markers } from "@versia-server/kit/tables";
|
||||
import { randomUUIDv7 } from "bun";
|
||||
import { and, eq, type SQL } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
const MarkerResponseSchema = z.object({
|
||||
notifications: MarkerSchema.optional(),
|
||||
|
|
@ -52,9 +51,9 @@ export default apiRoute((app) => {
|
|||
"timeline[]": z
|
||||
.array(z.enum(["home", "notifications"]))
|
||||
.max(2)
|
||||
.or(z.enum(["home", "notifications"]).transform((t) => [t]))
|
||||
.or(z.enum(["home", "notifications"]))
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Specify the timeline(s) for which markers should be fetched. Possible values: home, notifications. If not provided, an empty object will be returned.",
|
||||
}),
|
||||
|
|
@ -62,13 +61,17 @@ export default apiRoute((app) => {
|
|||
handleZodError,
|
||||
),
|
||||
async (context) => {
|
||||
const { "timeline[]": timeline } = context.req.valid("query");
|
||||
const { "timeline[]": queryTimeline } = context.req.valid("query");
|
||||
const { user } = context.get("auth");
|
||||
|
||||
if (!timeline) {
|
||||
if (!queryTimeline) {
|
||||
return context.json({}, 200);
|
||||
}
|
||||
|
||||
const timeline = Array.isArray(queryTimeline)
|
||||
? queryTimeline
|
||||
: [queryTimeline];
|
||||
|
||||
const markers: z.infer<typeof MarkerResponseSchema> = {
|
||||
home: undefined,
|
||||
notifications: undefined,
|
||||
|
|
@ -160,13 +163,13 @@ export default apiRoute((app) => {
|
|||
"query",
|
||||
z
|
||||
.object({
|
||||
"home[last_read_id]": StatusSchema.shape.id.openapi({
|
||||
"home[last_read_id]": StatusSchema.shape.id.meta({
|
||||
description:
|
||||
"ID of the last status read in the home timeline.",
|
||||
example: "c62aa212-8198-4ce5-a388-2cc8344a84ef",
|
||||
}),
|
||||
"notifications[last_read_id]":
|
||||
NotificationSchema.shape.id.openapi({
|
||||
NotificationSchema.shape.id.meta({
|
||||
description: "ID of the last notification read.",
|
||||
}),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ import { config } from "@versia-server/config";
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
||||
import { Media } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) => {
|
||||
app.get(
|
||||
|
|
@ -106,7 +105,7 @@ export default apiRoute((app) => {
|
|||
"form",
|
||||
z
|
||||
.object({
|
||||
thumbnail: z.instanceof(File).openapi({
|
||||
thumbnail: z.file().meta({
|
||||
description:
|
||||
"The custom thumbnail of the media to be attached, encoded using multipart form data.",
|
||||
}),
|
||||
|
|
@ -114,7 +113,7 @@ export default apiRoute((app) => {
|
|||
.unwrap()
|
||||
.max(config.validation.media.max_description_characters)
|
||||
.optional(),
|
||||
focus: z.string().openapi({
|
||||
focus: z.string().meta({
|
||||
description:
|
||||
"Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0. Used for media cropping on clients.",
|
||||
externalDocs: {
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ import { config } from "@versia-server/config";
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
||||
import { Media } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
@ -60,11 +59,11 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"form",
|
||||
z.object({
|
||||
file: z.instanceof(File).openapi({
|
||||
file: z.file().meta({
|
||||
description:
|
||||
"The file to be attached, encoded using multipart form data. The file must have a MIME type.",
|
||||
}),
|
||||
thumbnail: z.instanceof(File).optional().openapi({
|
||||
thumbnail: z.file().optional().meta({
|
||||
description:
|
||||
"The custom thumbnail of the media to be attached, encoded using multipart form data.",
|
||||
}),
|
||||
|
|
@ -75,7 +74,7 @@ export default apiRoute((app) =>
|
|||
focus: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0. Used for media cropping on clients.",
|
||||
externalDocs: {
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@ import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
|||
import { Timeline } from "@versia-server/kit/db";
|
||||
import { Users } from "@versia-server/kit/tables";
|
||||
import { and, gt, gte, lt, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
@ -33,7 +32,7 @@ export default apiRoute((app) =>
|
|||
link: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Links to the next and previous pages",
|
||||
example:
|
||||
|
|
@ -56,30 +55,24 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
max_id: AccountSchema.shape.id.optional().openapi({
|
||||
max_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be lesser than this ID. In effect, sets an upper bound on results.",
|
||||
example: "8d35243d-b959-43e2-8bac-1a9d4eaea2aa",
|
||||
}),
|
||||
since_id: AccountSchema.shape.id.optional().openapi({
|
||||
since_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be greater than this ID. In effect, sets a lower bound on results.",
|
||||
example: undefined,
|
||||
}),
|
||||
min_id: AccountSchema.shape.id.optional().openapi({
|
||||
min_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.",
|
||||
example: undefined,
|
||||
}),
|
||||
limit: z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.max(80)
|
||||
.default(40)
|
||||
.openapi({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
limit: z.coerce.number().int().min(1).max(80).default(40).meta({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
}),
|
||||
handleZodError,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||
import type { Notification } from "@versia/client/schemas";
|
||||
import { generateClient, getTestUsers } from "@versia-server/tests";
|
||||
import type { z } from "zod";
|
||||
import type { z } from "zod/v4";
|
||||
|
||||
const { users, deleteUsers } = await getTestUsers(2);
|
||||
let notifications: z.infer<typeof Notification>[] = [];
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ import {
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
||||
import { Notification } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||
import type { Notification } from "@versia/client/schemas";
|
||||
import { generateClient, getTestUsers } from "@versia-server/tests";
|
||||
import type { z } from "zod";
|
||||
import type { z } from "zod/v4";
|
||||
|
||||
const { users, deleteUsers } = await getTestUsers(2);
|
||||
let notifications: z.infer<typeof Notification>[] = [];
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ import {
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
||||
import { Notification } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {
|
|||
getTestStatuses,
|
||||
getTestUsers,
|
||||
} from "@versia-server/tests";
|
||||
import type { z } from "zod";
|
||||
import type { z } from "zod/v4";
|
||||
|
||||
const { users, deleteUsers } = await getTestUsers(2);
|
||||
const statuses = await getTestStatuses(5, users[0]);
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ import {
|
|||
handleZodError,
|
||||
qsQuery,
|
||||
} from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.delete(
|
||||
|
|
@ -32,7 +31,7 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
ids: z.array(z.string().uuid()),
|
||||
ids: z.array(z.uuid()),
|
||||
}),
|
||||
handleZodError,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@ import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
|||
import { Timeline } from "@versia-server/kit/db";
|
||||
import { Notifications } from "@versia-server/kit/tables";
|
||||
import { and, eq, gt, gte, inArray, lt, not, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
@ -47,17 +46,17 @@ export default apiRoute((app) =>
|
|||
"query",
|
||||
z
|
||||
.object({
|
||||
max_id: NotificationSchema.shape.id.optional().openapi({
|
||||
max_id: NotificationSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be lesser than this ID. In effect, sets an upper bound on results.",
|
||||
example: "8d35243d-b959-43e2-8bac-1a9d4eaea2aa",
|
||||
}),
|
||||
since_id: NotificationSchema.shape.id.optional().openapi({
|
||||
since_id: NotificationSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be greater than this ID. In effect, sets a lower bound on results.",
|
||||
example: undefined,
|
||||
}),
|
||||
min_id: NotificationSchema.shape.id.optional().openapi({
|
||||
min_id: NotificationSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.",
|
||||
example: undefined,
|
||||
|
|
@ -68,27 +67,27 @@ export default apiRoute((app) =>
|
|||
.min(1)
|
||||
.max(80)
|
||||
.default(40)
|
||||
.openapi({
|
||||
.meta({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
types: z
|
||||
.array(NotificationSchema.shape.type)
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description: "Types to include in the result.",
|
||||
}),
|
||||
exclude_types: z
|
||||
.array(NotificationSchema.shape.type)
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description: "Types to exclude from the results.",
|
||||
}),
|
||||
account_id: AccountSchema.shape.id.optional().openapi({
|
||||
account_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"Return only notifications received from the specified account.",
|
||||
}),
|
||||
// TODO: Implement
|
||||
include_filtered: zBoolean.default(false).openapi({
|
||||
include_filtered: zBoolean.default(false).meta({
|
||||
description:
|
||||
"Whether to include notifications filtered by the user's NotificationPolicy.",
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { Account, RolePermission } from "@versia/client/schemas";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.delete(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { Account, RolePermission } from "@versia/client/schemas";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.delete(
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@ import { RolePermission } from "@versia/client/schemas";
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth } from "@versia-server/kit/api";
|
||||
import { PushSubscription } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.delete(
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import {
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth } from "@versia-server/kit/api";
|
||||
import { PushSubscription } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ import {
|
|||
} from "@versia-server/kit/api";
|
||||
import { PushSubscription } from "@versia-server/kit/db";
|
||||
import { randomUUIDv7 } from "bun";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ import {
|
|||
jsonOrForm,
|
||||
} from "@versia-server/kit/api";
|
||||
import { PushSubscription } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.put(
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@ import { RolePermission, Role as RoleSchema } from "@versia/client/schemas";
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
||||
import { Role } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) => {
|
||||
app.get(
|
||||
|
|
@ -28,7 +27,7 @@ export default apiRoute((app) => {
|
|||
auth({
|
||||
auth: true,
|
||||
}),
|
||||
validator("param", z.object({ id: z.string().uuid() }), handleZodError),
|
||||
validator("param", z.object({ id: z.uuid() }), handleZodError),
|
||||
async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
|
||||
|
|
@ -62,7 +61,7 @@ export default apiRoute((app) => {
|
|||
validator(
|
||||
"param",
|
||||
z.object({
|
||||
id: z.string().uuid(),
|
||||
id: z.uuid(),
|
||||
}),
|
||||
handleZodError,
|
||||
),
|
||||
|
|
@ -118,7 +117,7 @@ export default apiRoute((app) => {
|
|||
}
|
||||
|
||||
await role.update({
|
||||
permissions: permissions as unknown as RolePermission[],
|
||||
permissions,
|
||||
priority,
|
||||
description,
|
||||
icon,
|
||||
|
|
@ -150,7 +149,7 @@ export default apiRoute((app) => {
|
|||
validator(
|
||||
"param",
|
||||
z.object({
|
||||
id: z.string().uuid(),
|
||||
id: z.uuid(),
|
||||
}),
|
||||
handleZodError,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@ import { ApiError } from "@versia-server/kit";
|
|||
import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
||||
import { Role } from "@versia-server/kit/db";
|
||||
import { randomUUIDv7 } from "bun";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) => {
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ import {
|
|||
} from "@versia/client/schemas";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withNoteParam } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { RolePermission, Status as StatusSchema } from "@versia/client/schemas";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withNoteParam } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@ import {
|
|||
import { Timeline } from "@versia-server/kit/db";
|
||||
import { Users } from "@versia-server/kit/tables";
|
||||
import { and, gt, gte, lt, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
@ -38,7 +37,7 @@ export default apiRoute((app) =>
|
|||
link: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Links to the next and previous pages",
|
||||
example:
|
||||
|
|
@ -65,30 +64,24 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
max_id: AccountSchema.shape.id.optional().openapi({
|
||||
max_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be lesser than this ID. In effect, sets an upper bound on results.",
|
||||
example: "8d35243d-b959-43e2-8bac-1a9d4eaea2aa",
|
||||
}),
|
||||
since_id: AccountSchema.shape.id.optional().openapi({
|
||||
since_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be greater than this ID. In effect, sets a lower bound on results.",
|
||||
example: undefined,
|
||||
}),
|
||||
min_id: AccountSchema.shape.id.optional().openapi({
|
||||
min_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.",
|
||||
example: undefined,
|
||||
}),
|
||||
limit: z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.max(80)
|
||||
.default(40)
|
||||
.openapi({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
limit: z.coerce.number().int().min(1).max(80).default(40).meta({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
}),
|
||||
handleZodError,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -21,9 +21,8 @@ import {
|
|||
parseMentionsFromText,
|
||||
versiaTextToHtml,
|
||||
} from "@versia-server/kit/parsers";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import { sanitizedHtmlStrip } from "@/sanitization";
|
||||
|
||||
const schema = z
|
||||
|
|
@ -38,7 +37,7 @@ const schema = z
|
|||
"Status contains blocked words",
|
||||
)
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"The text content of the status. If media_ids is provided, this becomes optional. Attaching a poll is optional while status is provided.",
|
||||
}),
|
||||
|
|
@ -46,7 +45,7 @@ const schema = z
|
|||
content_type: z
|
||||
.enum(["text/plain", "text/html", "text/markdown"])
|
||||
.default("text/plain")
|
||||
.openapi({
|
||||
.meta({
|
||||
description: "Content-Type of the status text.",
|
||||
example: "text/markdown",
|
||||
}),
|
||||
|
|
@ -54,15 +53,15 @@ const schema = z
|
|||
.array(AttachmentSchema.shape.id)
|
||||
.max(config.validation.notes.max_attachments)
|
||||
.default([])
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Include Attachment IDs to be attached as media. If provided, status becomes optional, and poll cannot be used.",
|
||||
}),
|
||||
spoiler_text: StatusSourceSchema.shape.spoiler_text.optional().openapi({
|
||||
spoiler_text: StatusSourceSchema.shape.spoiler_text.optional().meta({
|
||||
description:
|
||||
"Text to be shown as a warning or subject before the actual content. Statuses are generally collapsed behind this field.",
|
||||
}),
|
||||
sensitive: zBoolean.default(false).openapi({
|
||||
sensitive: zBoolean.default(false).meta({
|
||||
description: "Mark status and attached media as sensitive?",
|
||||
}),
|
||||
language: StatusSchema.shape.language.optional(),
|
||||
|
|
@ -74,7 +73,7 @@ const schema = z
|
|||
)
|
||||
.max(config.validation.polls.max_options)
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Possible answers to the poll. If provided, media_ids cannot be used, and poll[expires_in] must be provided.",
|
||||
}),
|
||||
|
|
@ -84,14 +83,14 @@ const schema = z
|
|||
.min(config.validation.polls.min_duration_seconds)
|
||||
.max(config.validation.polls.max_duration_seconds)
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Duration that the poll should be open, in seconds. If provided, media_ids cannot be used, and poll[options] must be provided.",
|
||||
}),
|
||||
"poll[multiple]": zBoolean.optional().openapi({
|
||||
"poll[multiple]": zBoolean.optional().meta({
|
||||
description: "Allow multiple choices?",
|
||||
}),
|
||||
"poll[hide_totals]": zBoolean.optional().openapi({
|
||||
"poll[hide_totals]": zBoolean.optional().meta({
|
||||
description: "Hide vote counts until the poll ends?",
|
||||
}),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ import { ApiError } from "@versia-server/kit";
|
|||
import { apiRoute, auth, withNoteParam } from "@versia-server/kit/api";
|
||||
import { db } from "@versia-server/kit/db";
|
||||
import { and, eq, type SQL } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -9,12 +9,11 @@ import {
|
|||
import { Emoji } from "@versia-server/kit/db";
|
||||
import { Emojis } from "@versia-server/kit/tables";
|
||||
import { and, eq, isNull } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import emojis from "unicode-emoji-json/data-ordered-emoji.json" with {
|
||||
type: "json",
|
||||
};
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) => {
|
||||
app.put(
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@ import {
|
|||
} from "@versia/client/schemas";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withNoteParam } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ import {
|
|||
jsonOrForm,
|
||||
withNoteParam,
|
||||
} from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@ import {
|
|||
import { Timeline } from "@versia-server/kit/db";
|
||||
import { Users } from "@versia-server/kit/tables";
|
||||
import { and, gt, gte, lt, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
@ -38,7 +37,7 @@ export default apiRoute((app) =>
|
|||
link: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Links to the next and previous pages",
|
||||
example:
|
||||
|
|
@ -65,30 +64,24 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
max_id: AccountSchema.shape.id.optional().openapi({
|
||||
max_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be lesser than this ID. In effect, sets an upper bound on results.",
|
||||
example: "8d35243d-b959-43e2-8bac-1a9d4eaea2aa",
|
||||
}),
|
||||
since_id: AccountSchema.shape.id.optional().openapi({
|
||||
since_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be greater than this ID. In effect, sets a lower bound on results.",
|
||||
example: undefined,
|
||||
}),
|
||||
min_id: AccountSchema.shape.id.optional().openapi({
|
||||
min_id: AccountSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.",
|
||||
example: undefined,
|
||||
}),
|
||||
limit: z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.max(80)
|
||||
.default(40)
|
||||
.openapi({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
limit: z.coerce.number().int().min(1).max(80).default(40).meta({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
}),
|
||||
handleZodError,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ import {
|
|||
} from "@versia/client/schemas";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withNoteParam } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { RolePermission, Status as StatusSchema } from "@versia/client/schemas";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withNoteParam } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { RolePermission, Status as StatusSchema } from "@versia/client/schemas";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withNoteParam } from "@versia-server/kit/api";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import { RolePermission, Status as StatusSchema } from "@versia/client/schemas";
|
|||
import { ApiError } from "@versia-server/kit";
|
||||
import { apiRoute, auth, withNoteParam } from "@versia-server/kit/api";
|
||||
import { Note } from "@versia-server/kit/db";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver } from "hono-openapi/zod";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.post(
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { Emojis } from "@versia-server/kit/tables";
|
|||
import { generateClient, getTestUsers } from "@versia-server/tests";
|
||||
import { randomUUIDv7 } from "bun";
|
||||
import { eq } from "drizzle-orm";
|
||||
import type { z } from "zod";
|
||||
import type { z } from "zod/v4";
|
||||
|
||||
const { users, deleteUsers } = await getTestUsers(5);
|
||||
let media: Media;
|
||||
|
|
@ -87,7 +87,7 @@ describe("/api/v1/statuses", () => {
|
|||
expect(raw.status).toBe(422);
|
||||
expect(data).toMatchObject({
|
||||
error: expect.stringContaining(
|
||||
"must be at least 5 minutes in the future",
|
||||
"Must be at least 5 minutes in the future",
|
||||
),
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -21,9 +21,8 @@ import {
|
|||
versiaTextToHtml,
|
||||
} from "@versia-server/kit/parsers";
|
||||
import { randomUUIDv7 } from "bun";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
import { sanitizedHtmlStrip } from "@/sanitization";
|
||||
|
||||
const schema = z
|
||||
|
|
@ -38,7 +37,7 @@ const schema = z
|
|||
"Status contains blocked words",
|
||||
)
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"The text content of the status. If media_ids is provided, this becomes optional. Attaching a poll is optional while status is provided.",
|
||||
}),
|
||||
|
|
@ -46,7 +45,7 @@ const schema = z
|
|||
content_type: z
|
||||
.enum(["text/plain", "text/html", "text/markdown"])
|
||||
.default("text/plain")
|
||||
.openapi({
|
||||
.meta({
|
||||
description: "Content-Type of the status text.",
|
||||
example: "text/markdown",
|
||||
}),
|
||||
|
|
@ -54,15 +53,15 @@ const schema = z
|
|||
.array(AttachmentSchema.shape.id)
|
||||
.max(config.validation.notes.max_attachments)
|
||||
.default([])
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Include Attachment IDs to be attached as media. If provided, status becomes optional, and poll cannot be used.",
|
||||
}),
|
||||
spoiler_text: StatusSourceSchema.shape.spoiler_text.optional().openapi({
|
||||
spoiler_text: StatusSourceSchema.shape.spoiler_text.optional().meta({
|
||||
description:
|
||||
"Text to be shown as a warning or subject before the actual content. Statuses are generally collapsed behind this field.",
|
||||
}),
|
||||
sensitive: zBoolean.default(false).openapi({
|
||||
sensitive: zBoolean.default(false).meta({
|
||||
description: "Mark status and attached media as sensitive?",
|
||||
}),
|
||||
language: StatusSchema.shape.language.optional(),
|
||||
|
|
@ -74,7 +73,7 @@ const schema = z
|
|||
)
|
||||
.max(config.validation.polls.max_options)
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Possible answers to the poll. If provided, media_ids cannot be used, and poll[expires_in] must be provided.",
|
||||
}),
|
||||
|
|
@ -84,39 +83,43 @@ const schema = z
|
|||
.min(config.validation.polls.min_duration_seconds)
|
||||
.max(config.validation.polls.max_duration_seconds)
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Duration that the poll should be open, in seconds. If provided, media_ids cannot be used, and poll[options] must be provided.",
|
||||
}),
|
||||
"poll[multiple]": zBoolean.optional().openapi({
|
||||
"poll[multiple]": zBoolean.optional().meta({
|
||||
description: "Allow multiple choices?",
|
||||
}),
|
||||
"poll[hide_totals]": zBoolean.optional().openapi({
|
||||
"poll[hide_totals]": zBoolean.optional().meta({
|
||||
description: "Hide vote counts until the poll ends?",
|
||||
}),
|
||||
in_reply_to_id: StatusSchema.shape.id.optional().nullable().openapi({
|
||||
in_reply_to_id: StatusSchema.shape.id.optional().nullable().meta({
|
||||
description:
|
||||
"ID of the status being replied to, if status is a reply.",
|
||||
}),
|
||||
/* Versia Server API Extension */
|
||||
quote_id: StatusSchema.shape.id.optional().nullable().openapi({
|
||||
quote_id: StatusSchema.shape.id.optional().nullable().meta({
|
||||
description: "ID of the status being quoted, if status is a quote.",
|
||||
}),
|
||||
visibility: StatusSchema.shape.visibility.default("public"),
|
||||
scheduled_at: z.coerce
|
||||
.date()
|
||||
.min(
|
||||
new Date(Date.now() + 5 * 60 * 1000),
|
||||
"must be at least 5 minutes in the future.",
|
||||
scheduled_at: z.iso
|
||||
.datetime()
|
||||
.refine(
|
||||
(date) =>
|
||||
new Date(date).getTime() >=
|
||||
new Date(Date.now() + 5 * 60 * 1000).getTime(),
|
||||
{
|
||||
message: "must be at least 5 minutes in the future.",
|
||||
},
|
||||
)
|
||||
.optional()
|
||||
.nullable()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Datetime at which to schedule a status. Providing this parameter will cause ScheduledStatus to be returned instead of Status. Must be at least 5 minutes in the future.",
|
||||
}),
|
||||
/* Versia Server API Extension */
|
||||
local_only: zBoolean.default(false).openapi({
|
||||
local_only: zBoolean.default(false).meta({
|
||||
description: "If true, this status will not be federated.",
|
||||
}),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@ import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
|||
import { Timeline } from "@versia-server/kit/db";
|
||||
import { Notes } from "@versia-server/kit/tables";
|
||||
import { and, eq, gt, gte, inArray, lt, or, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
@ -31,7 +30,7 @@ export default apiRoute((app) =>
|
|||
link: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Links to the next and previous pages",
|
||||
example:
|
||||
|
|
@ -57,30 +56,24 @@ export default apiRoute((app) =>
|
|||
validator(
|
||||
"query",
|
||||
z.object({
|
||||
max_id: StatusSchema.shape.id.optional().openapi({
|
||||
max_id: StatusSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be lesser than this ID. In effect, sets an upper bound on results.",
|
||||
example: "8d35243d-b959-43e2-8bac-1a9d4eaea2aa",
|
||||
}),
|
||||
since_id: StatusSchema.shape.id.optional().openapi({
|
||||
since_id: StatusSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be greater than this ID. In effect, sets a lower bound on results.",
|
||||
example: undefined,
|
||||
}),
|
||||
min_id: StatusSchema.shape.id.optional().openapi({
|
||||
min_id: StatusSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.",
|
||||
example: undefined,
|
||||
}),
|
||||
limit: z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.max(40)
|
||||
.default(20)
|
||||
.openapi({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
limit: z.coerce.number().int().min(1).max(40).default(20).meta({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
}),
|
||||
handleZodError,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@ import { apiRoute, auth, handleZodError } from "@versia-server/kit/api";
|
|||
import { Timeline } from "@versia-server/kit/db";
|
||||
import { Notes } from "@versia-server/kit/tables";
|
||||
import { and, eq, gt, gte, inArray, lt, or, sql } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.get(
|
||||
|
|
@ -34,7 +33,7 @@ export default apiRoute((app) =>
|
|||
link: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"Links to the next and previous pages",
|
||||
example:
|
||||
|
|
@ -60,28 +59,28 @@ export default apiRoute((app) =>
|
|||
"query",
|
||||
z
|
||||
.object({
|
||||
max_id: StatusSchema.shape.id.optional().openapi({
|
||||
max_id: StatusSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be lesser than this ID. In effect, sets an upper bound on results.",
|
||||
example: "8d35243d-b959-43e2-8bac-1a9d4eaea2aa",
|
||||
}),
|
||||
since_id: StatusSchema.shape.id.optional().openapi({
|
||||
since_id: StatusSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"All results returned will be greater than this ID. In effect, sets a lower bound on results.",
|
||||
example: undefined,
|
||||
}),
|
||||
min_id: StatusSchema.shape.id.optional().openapi({
|
||||
min_id: StatusSchema.shape.id.optional().meta({
|
||||
description:
|
||||
"Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.",
|
||||
example: undefined,
|
||||
}),
|
||||
local: zBoolean.default(false).openapi({
|
||||
local: zBoolean.default(false).meta({
|
||||
description: "Show only local statuses?",
|
||||
}),
|
||||
remote: zBoolean.default(false).openapi({
|
||||
remote: zBoolean.default(false).meta({
|
||||
description: "Show only remote statuses?",
|
||||
}),
|
||||
only_media: zBoolean.default(false).openapi({
|
||||
only_media: zBoolean.default(false).meta({
|
||||
description: "Show only statuses with media attached?",
|
||||
}),
|
||||
limit: z.coerce
|
||||
|
|
@ -90,7 +89,7 @@ export default apiRoute((app) =>
|
|||
.min(1)
|
||||
.max(40)
|
||||
.default(20)
|
||||
.openapi({
|
||||
.meta({
|
||||
description: "Maximum number of results to return.",
|
||||
}),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@ import {
|
|||
import { db } from "@versia-server/kit/db";
|
||||
import { FilterKeywords, Filters } from "@versia-server/kit/tables";
|
||||
import { and, eq, inArray, type SQL } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) => {
|
||||
app.get(
|
||||
|
|
@ -145,7 +144,7 @@ export default apiRoute((app) => {
|
|||
.int()
|
||||
.min(60)
|
||||
.max(60 * 60 * 24 * 365 * 5)
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"How many seconds from now should the filter expire?",
|
||||
}),
|
||||
|
|
@ -157,7 +156,7 @@ export default apiRoute((app) => {
|
|||
})
|
||||
.extend({
|
||||
// biome-ignore lint/style/useNamingConvention: _destroy is a Mastodon API imposed variable name
|
||||
_destroy: zBoolean.default(false).openapi({
|
||||
_destroy: zBoolean.default(false).meta({
|
||||
description:
|
||||
"If true, will remove the keyword with the given ID.",
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@ import { db } from "@versia-server/kit/db";
|
|||
import { FilterKeywords, Filters } from "@versia-server/kit/tables";
|
||||
import { randomUUIDv7 } from "bun";
|
||||
import { eq, type SQL } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { describeRoute, resolver, validator } from "hono-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export default apiRoute((app) => {
|
||||
app.get(
|
||||
|
|
@ -115,7 +114,7 @@ export default apiRoute((app) => {
|
|||
.min(60)
|
||||
.max(60 * 60 * 24 * 365 * 5)
|
||||
.optional()
|
||||
.openapi({
|
||||
.meta({
|
||||
description:
|
||||
"How many seconds from now should the filter expire?",
|
||||
}),
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue