Adds API docs annotations & generator (#927)

* initial commit

* fixes category api route

* fixes follow api routes

---------

Co-authored-by: Christian Beutel <>
This commit is contained in:
Flomp
2026-04-18 17:04:49 +02:00
committed by GitHub
parent da38cfc19a
commit b7b16e5a6e
91 changed files with 18668 additions and 37201 deletions

View File

@@ -1,79 +0,0 @@
<script lang="ts">
import type { User } from "$lib/models/user";
import { show_toast } from "$lib/stores/toast_store.svelte";
import { users_search } from "$lib/stores/user_store";
import { getFileURL } from "$lib/util/file_util";
import Search, { type SearchItem } from "./base/search.svelte";
import { _ } from "svelte-i18n";
interface Props {
label?: string;
value?: string;
includeSelf?: boolean;
clearAfterSelect?: boolean;
onclear?: () => void
onclick?: (item: SearchItem) => void
}
let {
label = "",
value = $bindable(""),
includeSelf = true,
clearAfterSelect = true,
onclear,
onclick
}: Props = $props();
let searchItems: SearchItem[] = $state([]);
async function updateUsers(q: string) {
if (!q.length) {
searchItems = [];
onclear?.();
return;
}
try {
const users: User[] = await users_search(q, includeSelf);
searchItems = users.map((u) => ({
text: u.username!,
value: u,
icon: "user",
}));
} catch (e) {
console.error(e);
show_toast({
type: "error",
icon: "close",
text: "Error during search",
});
}
}
function onClick(item: SearchItem) {
value = item.value.username ?? value;
onclick?.(item);
searchItems = [];
}
</script>
<Search
onupdate={(q) => updateUsers(q)}
onclick={(item) => onClick(item)}
placeholder={`${$_("username")}...`}
items={searchItems}
{clearAfterSelect}
{label}
bind:value
>
{#snippet prepend({ item })}
<img
class="rounded-full w-8 aspect-square mr-2"
src={getFileURL(item.value, item.value.avatar) ||
`https://api.dicebear.com/7.x/initials/svg?seed=${item.value.username}&backgroundType=gradientLinear`}
alt="avatar"
/>
{/snippet}
</Search>

File diff suppressed because it is too large Load Diff

View File

@@ -23,37 +23,6 @@ export async function users_create(user: User) {
return createdUser;
}
export async function users_search(q: string, includeSelf: boolean = true) {
const user = get(currentUser)
let r = await fetch('/api/v1/user/anonymous?' + new URLSearchParams({
"filter": `username~"${q}"${includeSelf ? '' : `&&id!="${user?.id}"`}`,
}), {
method: 'GET',
})
if (!r.ok) {
const response = await r.json();
throw new APIError(r.status, response.message, response.detail)
}
const response = await r.json()
return response.items;
}
export async function users_show(id: string, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
let r = await f(`/api/v1/user/anonymous/${id}`, {
method: 'GET',
})
if (!r.ok) {
const response = await r.json();
throw new APIError(r.status, response.message, response.detail)
}
const response: UserAnonymous = await r.json()
return response;
}
export async function users_auth_methods(f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch): Promise<AuthMethodsList> {
const r = await f('/api/v1/auth/oauth', {
method: 'GET',

View File

@@ -3,6 +3,32 @@ import { Collection, handleError, show } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
import type { APActivity, APRoot } from 'activitypub-types';
/**
* @swagger
* /api/v1/activitypub/activity/{id}:
* get:
* summary: Get ActivityPub activity
* description: Retrieves an ActivityPub Activity object by ID
* tags:
* - ActivityPub
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: ActivityPub Activity object
* content:
* application/json:
* schema:
* type: object
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const a = await show<Activity>(event, Collection.activitypub_activities)

View File

@@ -3,6 +3,32 @@ import { handleError } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/activitypub/comment/{id}:
* get:
* summary: Get ActivityPub comment
* description: Retrieves an ActivityPub Comment object by ID (proxied from backend)
* tags:
* - ActivityPub
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: ActivityPub Comment object
* content:
* application/json:
* schema:
* type: object
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
const id = event.params.id;

View File

@@ -3,6 +3,32 @@ import { handleError } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/activitypub/trail/{id}:
* get:
* summary: Get ActivityPub trail
* description: Retrieves an ActivityPub Trail object by ID (proxied from backend)
* tags:
* - ActivityPub
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: ActivityPub Trail object
* content:
* application/json:
* schema:
* type: object
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
const id = event.params.id;

View File

@@ -8,6 +8,32 @@ import { error, json, type RequestEvent } from '@sveltejs/kit';
import { type APActor, type APRoot } from 'activitypub-types';
/**
* @swagger
* /api/v1/activitypub/user/{handle}:
* get:
* summary: Get ActivityPub actor profile
* description: Retrieves an ActivityPub Person object for a user with public key
* tags:
* - ActivityPub
* parameters:
* - in: path
* name: handle
* required: true
* schema:
* type: string
* responses:
* 200:
* description: ActivityPub Person object with publicKey
* content:
* application/json:
* schema:
* type: object
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {

View File

@@ -9,6 +9,37 @@ import type { APOrderedCollectionPage, APRoot } from 'activitypub-types';
import type { ListResult } from 'pocketbase';
/**
* @swagger
* /api/v1/activitypub/user/{handle}/followers:
* get:
* summary: Get ActivityPub followers collection
* description: Retrieves an OrderedCollection paginated list of followers for a user
* tags:
* - ActivityPub
* parameters:
* - in: path
* name: handle
* required: true
* schema:
* type: string
* - in: query
* name: page
* schema:
* type: integer
* responses:
* 200:
* description: ActivityPub OrderedCollectionPage
* content:
* application/json:
* schema:
* type: object
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {

View File

@@ -1,15 +1,45 @@
import { env } from '$env/dynamic/private';
import { env as publicEnv } from '$env/dynamic/public';
import type { Actor } from '$lib/models/activitypub/actor';
import type { Follow } from '$lib/models/follow';
import { splitUsername } from '$lib/util/activitypub_util';
import { handleError } from '$lib/util/api_util';
import { error, json, type RequestEvent } from '@sveltejs/kit';
import { json, type RequestEvent } from '@sveltejs/kit';
import type { APOrderedCollectionPage, APRoot } from 'activitypub-types';
import type { ListResult } from 'pocketbase';
/**
* @swagger
* /api/v1/activitypub/user/{handle}/following:
* get:
* summary: Get ActivityPub following collection
* description: Retrieves an OrderedCollection paginated list of accounts the user follows
* tags:
* - ActivityPub
* parameters:
* - in: path
* name: handle
* required: true
* schema:
* type: string
* - in: query
* name: page
* schema:
* type: integer
* responses:
* 200:
* description: ActivityPub OrderedCollectionPage
* content:
* application/json:
* schema:
* type: object
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {

View File

@@ -4,6 +4,34 @@ import { handleError } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
import type { APActivity } from 'activitypub-types';
/**
* @swagger
* /api/v1/activitypub/user/{handle}/inbox:
* post:
* summary: Receive ActivityPub activities
* description: Receives and processes incoming ActivityPub activities (Create, Update, Delete, Follow, etc.)
* tags:
* - ActivityPub
* parameters:
* - in: path
* name: handle
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* responses:
* 200:
* description: Activity processed
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {

View File

@@ -11,6 +11,40 @@ import type { APActivity, APOrderedCollectionPage, APRoot } from 'activitypub-ty
import type { ListResult } from 'pocketbase';
/**
* @swagger
* /api/v1/activitypub/user/{handle}/outbox:
* get:
* summary: Get ActivityPub outbox collection
* description: Retrieves an OrderedCollection paginated list of activities published by this user
* tags:
* - ActivityPub
* parameters:
* - in: path
* name: handle
* required: true
* schema:
* type: string
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* responses:
* 200:
* description: ActivityPub OrderedCollectionPage
* content:
* application/json:
* schema:
* type: object
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {

View File

@@ -4,6 +4,62 @@ import { Collection, handleError, list } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
import { APITokenCreateSchema } from "$lib/models/api/api_token_schema";
/**
* @swagger
* /api/v1/api-token:
* get:
* summary: List API tokens
* description: Retrieves a paginated list of API tokens with optional filtering and sorting
* tags:
* - API Tokens
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* default: 1
* - in: query
* name: perPage
* schema:
* type: integer
* default: 30
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: Success
* content:
* application/json:
* schema:
* type: object
* properties:
* page:
* type: integer
* perPage:
* type: integer
* totalItems:
* type: integer
* totalPages:
* type: integer
* items:
* type: array
* items:
* $ref: '#/components/schemas/APIToken'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await list<APIToken>(event, Collection.api_tokens);
@@ -14,7 +70,37 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/api-token:
* put:
* summary: Create API token
* description: Creates a new API token
* tags:
* - API Tokens
* parameters:
* - in: query
* name: expand
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/APITokenInput'
* responses:
* 201:
* description: Created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/APIToken'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const r = await create<APIToken>(event, APITokenCreateSchema, Collection.api_tokens)
@@ -22,4 +108,4 @@ export async function PUT(event: RequestEvent) {
} catch (e) {
return handleError(e)
}
}
}

View File

@@ -1,6 +1,29 @@
import { Collection, handleError, remove } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/api-token/{id}:
* delete:
* summary: Delete API token
* description: Deletes an API token by ID
* tags:
* - API Tokens
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* description: API token ID (15 chars)
* responses:
* 200:
* description: Success
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function DELETE(event: RequestEvent) {
try {
const r = await remove(event, Collection.api_tokens)

View File

@@ -2,6 +2,28 @@ import { handleError } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
import { z } from "zod";
/**
* @swagger
* /api/v1/auth/confirm-reset:
* post:
* summary: Confirm password reset
* description: Confirms and applies a password reset with a valid token
* tags:
* - Authentication
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* responses:
* 200:
* description: Password reset completed
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const data = await event.request.json()

View File

@@ -2,6 +2,42 @@ import { handleError } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
import { z } from "zod";
/**
* @swagger
* /api/v1/auth/login:
* post:
* summary: Authenticate user
* description: Authenticates a user with email or username and password
* tags:
* - Authentication
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - password
* properties:
* email:
* type: string
* format: email
* username:
* type: string
* password:
* type: string
* responses:
* 200:
* description: User authenticated with auth token
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/User'
* 400:
* description: Bad Request - Invalid credentials
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const data = await event.request.json();

View File

@@ -7,6 +7,24 @@ import { handleError } from "$lib/util/api_util";
const redirectURL = private_env.ORIGIN + "/login/redirect"
/**
* @swagger
* /api/v1/auth/oauth:
* get:
* summary: List OAuth providers
* description: Lists available OAuth2 authentication methods with provider images
* tags:
* - Authentication
* responses:
* 200:
* description: OAuth2 providers and configuration
* content:
* application/json:
* schema:
* type: object
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await event.locals.pb.collection('users').listAuthMethods();

View File

@@ -2,6 +2,34 @@ import { handleError } from "$lib/util/api_util";
import { error, json, type RequestEvent } from "@sveltejs/kit";
import { z } from "zod";
/**
* @swagger
* /api/v1/auth/reset:
* post:
* summary: Request password reset
* description: Sends a password reset email
* tags:
* - Authentication
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - email
* properties:
* email:
* type: string
* format: email
* responses:
* 200:
* description: Password reset email sent
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const data = await event.request.json()

View File

@@ -2,6 +2,44 @@ import type { Category } from "$lib/models/category";
import { Collection, handleError, list } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/category:
* get:
* summary: List categories
* description: Retrieves a paginated list of activity categories
* tags:
* - Categories
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* responses:
* 200:
* description: List of categories
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListResult'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await list<Category>(event, Collection.categories);

View File

@@ -4,6 +4,51 @@ import { Collection, create, handleError, list } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
import { type ListResult } from "pocketbase";
/**
* @swagger
* /api/v1/comment:
* get:
* summary: List comments
* tags:
* - Comments
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* - in: query
* name: handle
* schema:
* type: string
* description: Federated query parameter
* responses:
* 200:
* description: List of comments
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListResult'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
if (!event.url.searchParams.has("handle")) {

View File

@@ -3,6 +3,35 @@ import type { Comment } from "$lib/models/comment";
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/comment/{id}:
* get:
* summary: Get comment
* tags:
* - Comments
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: Comment details
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Comment'
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await show<Comment>(event, Collection.comments)
@@ -12,6 +41,39 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/comment/{id}:
* post:
* summary: Update comment
* tags:
* - Comments
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/CommentUpdateInput'
* responses:
* 200:
* description: Comment updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Comment'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await update<Comment>(event, CommentUpdateSchema, Collection.comments)
@@ -21,6 +83,27 @@ export async function POST(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/comment/{id}:
* delete:
* summary: Delete comment
* tags:
* - Comments
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Comment deleted
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function DELETE(event: RequestEvent) {
try {
const r = await remove(event, Collection.comments)

View File

@@ -2,6 +2,47 @@ import type { FeedItem } from "$lib/models/feed";
import { Collection, handleError, list } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/feed:
* get:
* summary: Get activity feed
* description: Retrieves the user's activity feed
* tags:
* - Feed
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: Activity feed
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListResult'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await list<FeedItem>(event, Collection.feed);

View File

@@ -1,6 +1,49 @@
import { error, json, type RequestEvent } from "@sveltejs/kit";
import { z } from "zod";
/**
* @swagger
* /api/v1/files/{collection}/{record}/{file}:
* get:
* summary: Download file
* description: Downloads a file from a record with optional thumbnail generation
* tags:
* - Files
* parameters:
* - in: path
* name: collection
* required: true
* schema:
* type: string
* - in: path
* name: record
* required: true
* schema:
* type: string
* - in: path
* name: file
* required: true
* schema:
* type: string
* - in: query
* name: thumb
* schema:
* type: string
* responses:
* 200:
* description: File download
* content:
* application/octet-stream:
* schema:
* type: string
* format: binary
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
const safeParams = z.object({

View File

@@ -7,6 +7,56 @@ import { json, type RequestEvent } from '@sveltejs/kit';
import type { APOrderedCollectionPage } from 'activitypub-types';
import { ClientResponseError, type ListResult } from "pocketbase";
/**
* @swagger
* /api/v1/follow:
* get:
* summary: List follows
* description: Retrieves follows or ActivityPub follower/following collections. Supports federated queries via handle parameter
* tags:
* - Follows
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* - in: query
* name: handle
* schema:
* type: string
* - in: query
* name: type
* schema:
* type: string
* enum: [followers, following]
* responses:
* 200:
* description: List of follows or ActivityPub collection
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListResult'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
if (!event.url.searchParams.has("handle")) {

View File

@@ -2,6 +2,27 @@ import { Collection, handleError, remove } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/follow/{id}:
* delete:
* summary: Delete follow
* tags:
* - Follows
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Follow deleted
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function DELETE(event: RequestEvent) {
try {
const r = await remove(event, Collection.follows)

View File

@@ -3,6 +3,46 @@ import type { Integration } from "$lib/models/integration";
import { Collection, create, handleError, list } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/integration:
* get:
* summary: List integrations
* tags:
* - Integrations
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: List of integrations
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListResult'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await list<Integration>(event, Collection.integrations);
@@ -13,9 +53,34 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/integration:
* put:
* summary: Create integration
* tags:
* - Integrations
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/IntegrationInput'
* responses:
* 201:
* description: Integration created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Integration'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const r = await create<Comment>(event, IntegrationCreateSchema, Collection.integrations)
const r = await create<Integration>(event, IntegrationCreateSchema, Collection.integrations)
return json(r);
} catch (e) {
return handleError(e)

View File

@@ -3,6 +3,35 @@ import type { Integration } from "$lib/models/integration";
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/integration/{id}:
* get:
* summary: Get integration
* tags:
* - Integrations
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: Integration details
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Integration'
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await show<Integration>(event, Collection.integrations)
@@ -12,6 +41,39 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/integration/{id}:
* post:
* summary: Update integration
* tags:
* - Integrations
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/IntegrationUpdateInput'
* responses:
* 200:
* description: Integration updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Integration'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await update<Integration>(event, IntegrationUpdateSchema, Collection.integrations)
@@ -21,6 +83,27 @@ export async function POST(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/integration/{id}:
* delete:
* summary: Delete integration
* tags:
* - Integrations
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Integration deleted
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function DELETE(event: RequestEvent) {
try {
const r = await remove(event, Collection.integrations)

View File

@@ -1,6 +1,24 @@
import { handleError } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/integration/hammerhead/login:
* get:
* summary: Get Hammerhead login endpoint
* description: Proxies to backend to get Hammerhead login configuration
* tags:
* - Integrations
* responses:
* 200:
* description: Hammerhead login endpoint
* content:
* application/json:
* schema:
* type: object
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await event.locals.pb.send("/integration/hammerhead/login", {

View File

@@ -1,6 +1,38 @@
import { handleError } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/integration/hammerhead/upload:
* post:
* summary: Upload via Hammerhead integration
* description: Proxies file upload to backend Hammerhead integration
* tags:
* - Integrations
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* type: object
* required:
* - file
* properties:
* file:
* type: string
* format: binary
* responses:
* 200:
* description: Upload result
* content:
* application/json:
* schema:
* type: object
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const formData = await event.request.formData();

View File

@@ -1,6 +1,24 @@
import { handleError } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/integration/komoot/login:
* get:
* summary: Get Komoot login endpoint
* description: Proxies to backend to get Komoot login configuration
* tags:
* - Integrations
* responses:
* 200:
* description: Komoot login endpoint
* content:
* application/json:
* schema:
* type: object
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await event.locals.pb.send("/integration/komoot/login", {

View File

@@ -4,6 +4,43 @@ import type { ListShare } from '$lib/models/list_share';
import { Collection, create, handleError, list } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/list-share:
* get:
* summary: List list shares
* description: Retrieves a paginated list of list shares with optional ActivityPub actor resolution
* tags:
* - List Shares
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: ListResult<ListShare>
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await list<ListShare>(event, Collection.list_share);
@@ -13,6 +50,32 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/list-share:
* put:
* summary: Create list share
* description: Creates a new list share. Converts ActivityPub actor IRI to ID
* tags:
* - List Shares
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListShareInput'
* responses:
* 201:
* description: List share created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListShare'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const data = await event.request.json();

View File

@@ -3,6 +3,32 @@ import type { ListShare } from "$lib/models/list_share";
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/list-share/{id}:
* get:
* summary: Get list share
* description: Retrieves a list share by ID
* tags:
* - List Shares
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: ListShare
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await show<ListShare>(event, Collection.list_share)
@@ -12,6 +38,39 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/list-share/{id}:
* post:
* summary: Update list share
* tags:
* - List Shares
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListShareUpdateInput'
* responses:
* 200:
* description: List share updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListShare'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await update<ListShare>(event, ListShareUpdateSchema, Collection.list_share)
@@ -21,6 +80,27 @@ export async function POST(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/list-share/{id}:
* delete:
* summary: Delete list share
* tags:
* - List Shares
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: List share deleted
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function DELETE(event: RequestEvent) {
try {
const r = await remove(event, Collection.list_share)

View File

@@ -3,6 +3,46 @@ import type { List } from '$lib/models/list';
import { Collection, create, handleError, list } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/list:
* get:
* summary: List all lists
* tags:
* - Lists
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: List of lists
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListResult'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await list<List>(event, Collection.lists);
@@ -18,6 +58,31 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/list:
* put:
* summary: Create list
* tags:
* - Lists
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListInput'
* responses:
* 201:
* description: List created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/List'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const r = await create<List>(event, ListCreateSchema, Collection.lists)

View File

@@ -5,6 +5,80 @@ import { objectToFormData } from "$lib/util/file_util";
import { json, type RequestEvent } from "@sveltejs/kit";
import { ClientResponseError } from "pocketbase";
/**
* @swagger
* /api/v1/list/{id}:
* get:
* summary: Get list
* description: Retrieves a list by ID. Supports federated queries via handle parameter, fetching from remote instances and remapping file URLs
* tags:
* - Lists
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* - in: query
* name: handle
* schema:
* type: string
* responses:
* 200:
* description: List with optional federated data
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
* post:
* summary: Update list
* description: Updates a list by ID
* tags:
* - Lists
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* responses:
* 200:
* description: List
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
* delete:
* summary: Delete list
* description: Deletes a list by ID
* tags:
* - Lists
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Success
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
if (!event.url.searchParams.has("handle")) {

View File

@@ -1,7 +1,45 @@
import { Collection, handleError, upload } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
import type { List } from "postcss/lib/list";
import type { List } from "$lib/models/list";
/**
* @swagger
* /api/v1/list/{id}/file:
* post:
* summary: Upload list file
* description: Uploads a file (cover image) for a list
* tags:
* - Lists
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* type: object
* properties:
* file:
* type: string
* format: binary
* responses:
* 200:
* description: File uploaded, list updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/List'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await upload<List>(event, Collection.lists);

View File

@@ -2,6 +2,28 @@ import type { List } from '$lib/models/list';
import { Collection, handleError, uploadCreate } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/list/form:
* put:
* summary: Create list with file upload
* description: Creates a new list with file upload (avatar)
* tags:
* - Lists
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* type: object
* responses:
* 201:
* description: List
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const r = await uploadCreate<List>(event, Collection.lists)

View File

@@ -2,6 +2,36 @@ import type { List } from "$lib/models/list";
import { Collection, handleError, uploadUpdate } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/list/form/{id}:
* post:
* summary: Update list with file upload
* description: Updates a list with file upload (avatar)
* tags:
* - Lists
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* type: object
* responses:
* 200:
* description: List
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await uploadUpdate<List>(event, Collection.lists)

View File

@@ -2,6 +2,46 @@ import type { Notification } from '$lib/models/notification';
import { Collection, handleError, list } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/notification:
* get:
* summary: List notifications
* tags:
* - Notifications
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: List of notifications
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListResult'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await list<Notification>(event, Collection.notifications);

View File

@@ -1,11 +1,42 @@
import { NotificationUpdateSchema } from "$lib/models/api/notification_schema";
import type { Notification } from "$lib/models/notification";
import { Collection, handleError, update } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/notification/{id}:
* post:
* summary: Update notification
* description: Updates a notification by ID (typically to mark as read)
* tags:
* - Notifications
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* responses:
* 200:
* description: Notification
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await update<Comment>(event, NotificationUpdateSchema, Collection.notifications)
const r = await update<Notification>(event, NotificationUpdateSchema, Collection.notifications)
return json(r);
} catch (e: any) {
return handleError(e)

View File

@@ -3,6 +3,32 @@ import { getActorResponseForHandle } from '$lib/util/activitypub_server_util';
import { handleError } from '$lib/util/api_util';
import { error, json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/profile/{handle}:
* get:
* summary: Get user profile
* description: Retrieves a user's profile by handle, with optional federation support
* tags:
* - Profiles
* parameters:
* - in: path
* name: handle
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Profile and actor data
* content:
* application/json:
* schema:
* type: object
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
const handle = event.params.handle;
if (!handle) {

View File

@@ -6,6 +6,40 @@ import { Collection, handleError } from '$lib/util/api_util';
import { error, json, type RequestEvent } from '@sveltejs/kit';
import { ClientResponseError, type ListResult } from 'pocketbase';
/**
* @swagger
* /api/v1/profile/{handle}/feed:
* get:
* summary: Get user activity feed
* description: Retrieves activity feed for a user, with federation support
* tags:
* - Profiles
* parameters:
* - in: path
* name: handle
* required: true
* schema:
* type: string
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* responses:
* 200:
* description: FeedItem list
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListResult'
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
const handle = event.params.handle;
if (!handle) {

View File

@@ -6,6 +6,47 @@ import { error, json, type RequestEvent } from '@sveltejs/kit';
import type { SearchResponse } from 'meilisearch';
import { ClientResponseError } from 'pocketbase';
/**
* @swagger
* /api/v1/profile/{handle}/lists:
* post:
* summary: Search user lists
* description: Searches a user's lists via Meilisearch, with federation support
* tags:
* - Profiles
* parameters:
* - in: path
* name: handle
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - q
* properties:
* q:
* type: string
* options:
* type: object
* responses:
* 200:
* description: Meilisearch response with list results
* content:
* application/json:
* schema:
* type: object
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
const handle = event.params.handle;
if (!handle) {

View File

@@ -5,6 +5,40 @@ import { Collection, handleError } from '$lib/util/api_util';
import { error, json, type RequestEvent } from '@sveltejs/kit';
import { ClientResponseError, type ListResult } from 'pocketbase';
/**
* @swagger
* /api/v1/profile/{handle}/stats:
* get:
* summary: Get user summit statistics
* description: Retrieves summit log statistics for a user, with federation support
* tags:
* - Profiles
* parameters:
* - in: path
* name: handle
* required: true
* schema:
* type: string
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* responses:
* 200:
* description: SummitLog statistics
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListResult'
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
const handle = event.params.handle;
if (!handle) {

View File

@@ -5,6 +5,47 @@ import { error, json, type RequestEvent } from '@sveltejs/kit';
import type { SearchResponse } from 'meilisearch';
import { ClientResponseError } from 'pocketbase';
/**
* @swagger
* /api/v1/profile/{handle}/trails:
* post:
* summary: Search user trails
* description: Searches a user's trails via Meilisearch, with federation support
* tags:
* - Profiles
* parameters:
* - in: path
* name: handle
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - q
* properties:
* q:
* type: string
* options:
* type: object
* responses:
* 200:
* description: Meilisearch response with trail results
* content:
* application/json:
* schema:
* type: object
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
const handle = event.params.handle;
if (!handle) {

View File

@@ -1,5 +1,44 @@
import { error, json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/search/{index}:
* post:
* summary: Search Meilisearch index
* description: Performs a search on a specific Meilisearch index
* tags:
* - Search
* parameters:
* - in: path
* name: index
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - q
* properties:
* q:
* type: string
* options:
* type: object
* responses:
* 200:
* description: Meilisearch search results
* content:
* application/json:
* schema:
* type: object
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
const data = await event.request.json()

View File

@@ -4,6 +4,38 @@ import { handleError } from '$lib/util/api_util';
import { error, json, type RequestEvent } from '@sveltejs/kit';
import { ClientResponseError, type ListResult } from "pocketbase"
/**
* @swagger
* /api/v1/search/actor:
* get:
* summary: Search actors
* description: Searches for ActivityPub actors by username, combining local and federated results
* tags:
* - Search
* parameters:
* - in: query
* name: q
* required: true
* schema:
* type: string
* - in: query
* name: includeSelf
* schema:
* type: boolean
* responses:
* 200:
* description: Array of matching actors
* content:
* application/json:
* schema:
* type: array
* items:
* type: object
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {

View File

@@ -1,5 +1,38 @@
import { error, json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/search/multi:
* post:
* summary: Multi-index search
* description: Performs batch searches across multiple Meilisearch indices
* tags:
* - Search
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - queries
* properties:
* queries:
* type: array
* items:
* type: object
* responses:
* 200:
* description: Combined Meilisearch results
* content:
* application/json:
* schema:
* type: object
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
const data = await event.request.json()

View File

@@ -1,10 +1,36 @@
import { SettingsCreateSchema } from '$lib/models/api/settings_schema';
import type { Settings } from '$lib/models/settings';
import { Collection, create } from '$lib/util/api_util';
import { error, json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/settings:
* put:
* summary: Create settings
* tags:
* - Settings
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SettingsInput'
* responses:
* 201:
* description: Settings created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Settings'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const r = await create<Comment>(event, SettingsCreateSchema, Collection.settings)
const r = await create<Settings>(event, SettingsCreateSchema, Collection.settings)
return json(r);
} catch (e: any) {

View File

@@ -4,6 +4,35 @@ import { Collection, handleError, remove, show, update } from "$lib/util/api_uti
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/settings/{id}:
* get:
* summary: Get settings
* tags:
* - Settings
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: Settings details
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Settings'
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await show<Settings>(event, Collection.settings)
@@ -13,6 +42,39 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/settings/{id}:
* post:
* summary: Update settings
* tags:
* - Settings
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SettingsInput'
* responses:
* 200:
* description: Settings updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Settings'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await update<Settings>(event, SettingsCreateSchema, Collection.settings)
@@ -22,6 +84,27 @@ export async function POST(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/settings/{id}:
* delete:
* summary: Delete settings
* tags:
* - Settings
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Settings deleted
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function DELETE(event: RequestEvent) {
try {
const r = await remove(event, Collection.settings)

View File

@@ -4,6 +4,47 @@ import { Collection, create, handleError, list } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
import { type ListResult } from "pocketbase";
/**
* @swagger
* /api/v1/summit-log:
* get:
* summary: List summit logs
* description: Retrieves a paginated list of summit logs with deduplication of federated data
* tags:
* - Summit Logs
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* - in: query
* name: handle
* schema:
* type: string
* responses:
* 200:
* description: ListResult<SummitLog> with local/remote items deduplicated
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
if (!event.url.searchParams.has("handle")) {
@@ -89,6 +130,31 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/summit-log:
* put:
* summary: Create summit log
* tags:
* - Summit Logs
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SummitLogInput'
* responses:
* 201:
* description: Summit log created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SummitLog'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const r = await create<SummitLog>(event, SummitLogCreateSchema, Collection.summit_logs)

View File

@@ -4,6 +4,35 @@ import { Collection, handleError, remove, show, update } from "$lib/util/api_uti
import { error, json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/summit-log/{id}:
* get:
* summary: Get summit log
* tags:
* - Summit Logs
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: Summit log details
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SummitLog'
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await show<SummitLog>(event, Collection.summit_logs)
@@ -13,6 +42,39 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/summit-log/{id}:
* post:
* summary: Update summit log
* tags:
* - Summit Logs
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SummitLogUpdateInput'
* responses:
* 200:
* description: Summit log updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SummitLog'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await update<SummitLog>(event, SummitLogUpdateSchema, Collection.summit_logs)
@@ -22,6 +84,27 @@ export async function POST(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/summit-log/{id}:
* delete:
* summary: Delete summit log
* tags:
* - Summit Logs
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Summit log deleted
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function DELETE(event: RequestEvent) {
try {
const r = await remove(event, Collection.summit_logs)

View File

@@ -2,6 +2,44 @@ import type { SummitLog } from "$lib/models/summit_log";
import { Collection, upload } from "$lib/util/api_util";
import { error, json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/summit-log/{id}/file:
* post:
* summary: Upload summit log file
* description: Uploads a file (photo or GPX) for a summit log
* tags:
* - Summit Logs
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* type: object
* properties:
* file:
* type: string
* format: binary
* responses:
* 200:
* description: File uploaded, summit log updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SummitLog'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await upload<SummitLog>(event, Collection.summit_logs);

View File

@@ -2,6 +2,32 @@ import type { SummitLog } from '$lib/models/summit_log';
import { Collection, handleError, uploadCreate } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/summit-log/form:
* put:
* summary: Create summit log with file upload
* description: Creates a new summit log with file upload (photos/GPX) and date normalization
* tags:
* - Summit Logs
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* $ref: '#/components/schemas/SummitLogInput'
* responses:
* 201:
* description: Summit log created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SummitLog'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const r = await uploadCreate<SummitLog>(event, Collection.summit_logs)

View File

@@ -2,6 +2,40 @@ import type { SummitLog } from "$lib/models/summit_log";
import { Collection, handleError, uploadUpdate } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/summit-log/form/{id}:
* post:
* summary: Update summit log with file upload
* description: Updates a summit log with file upload (photos/GPX) and date normalization
* tags:
* - Summit Logs
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* $ref: '#/components/schemas/SummitLogUpdateInput'
* responses:
* 200:
* description: Summit log updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SummitLog'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await uploadUpdate<SummitLog>(event, Collection.summit_logs)

View File

@@ -3,6 +3,46 @@ import type { Tag } from '$lib/models/tag';
import { Collection, create, handleError, list } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/tag:
* get:
* summary: List tags
* tags:
* - Tags
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: List of tags
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListResult'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await list<Tag>(event, Collection.tags);
@@ -13,6 +53,31 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/tag:
* put:
* summary: Create tag
* tags:
* - Tags
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TagInput'
* responses:
* 201:
* description: Tag created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Tag'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const r = await create<Tag>(event, TagCreateSchema, Collection.tags)

View File

@@ -3,6 +3,35 @@ import type { Tag } from "$lib/models/tag";
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/tag/{id}:
* get:
* summary: Get tag
* tags:
* - Tags
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: Tag details
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Tag'
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await show<Tag>(event, Collection.tags)
@@ -12,6 +41,39 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/tag/{id}:
* post:
* summary: Update tag
* tags:
* - Tags
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TagUpdateInput'
* responses:
* 200:
* description: Tag updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Tag'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await update<Tag>(event, TagUpdateSchema, Collection.tags)
@@ -21,6 +83,27 @@ export async function POST(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/tag/{id}:
* delete:
* summary: Delete tag
* tags:
* - Tags
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Tag deleted
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function DELETE(event: RequestEvent) {
try {
const r = await remove(event, Collection.tags)

View File

@@ -3,6 +3,46 @@ import type { TrailLike } from '$lib/models/trail_like';
import { Collection, create, handleError, list } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/trail-like:
* get:
* summary: List trail likes
* tags:
* - Trail Likes
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: List of trail likes
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListResult'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await list<TrailLike>(event, Collection.trail_share);
@@ -12,6 +52,31 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/trail-like:
* put:
* summary: Create trail like
* tags:
* - Trail Likes
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TrailLikeInput'
* responses:
* 201:
* description: Trail like created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TrailLike'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const r = await create<TrailLike>(event, TrailLikeCreateSchema, Collection.trail_like)

View File

@@ -2,6 +2,32 @@ import type { TrailLike } from "$lib/models/trail_like";
import { Collection, handleError, remove, show } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/trail-like/{id}:
* get:
* summary: Get trail like
* description: Retrieves a trail like by ID
* tags:
* - Trail Likes
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: TrailLike
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await show<TrailLike>(event, Collection.trail_like)
@@ -11,6 +37,27 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/trail-like/{id}:
* delete:
* summary: Delete trail like
* tags:
* - Trail Likes
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Trail like deleted
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function DELETE(event: RequestEvent) {
try {
const r = await remove(event, Collection.trail_like)

View File

@@ -3,7 +3,30 @@ import { Collection, handleError } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
// this route exists so we can delete a like without knowing its ID
/**
* @swagger
* /api/v1/trail-like/delete:
* post:
* summary: Delete trail like by actor and trail
* description: Deletes a trail like without needing to know its ID. Uses actor and trail IDs to find and delete
* tags:
* - Trail Likes
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TrailLikeInput'
* responses:
* 200:
* description: Trail like deleted
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {

View File

@@ -3,6 +3,46 @@ import type { TrailLinkShare } from '$lib/models/trail_link_share';
import { Collection, handleError, list } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/trail-link-share:
* get:
* summary: List trail link shares
* tags:
* - Trail Link Shares
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: List of trail link shares
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListResult'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await list<TrailLinkShare>(event, Collection.trail_link_share);
@@ -12,6 +52,31 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/trail-link-share:
* put:
* summary: Create trail link share
* tags:
* - Trail Link Shares
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TrailLinkShareInput'
* responses:
* 201:
* description: Trail link share created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TrailLinkShare'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const data = await event.request.json();

View File

@@ -3,6 +3,32 @@ import type { TrailLinkShare } from "$lib/models/trail_link_share";
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/trail-link-share/{id}:
* get:
* summary: Get trail link share
* description: Retrieves a trail link share by ID
* tags:
* - Trail Link Shares
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: TrailLinkShare
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await show<TrailLinkShare>(event, Collection.trail_link_share)
@@ -12,6 +38,39 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/trail-link-share/{id}:
* post:
* summary: Update trail link share
* tags:
* - Trail Link Shares
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TrailLinkShareUpdateInput'
* responses:
* 200:
* description: Trail link share updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TrailLinkShare'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await update<TrailLinkShare>(event, TrailLinkShareUpdateSchema, Collection.trail_link_share)
@@ -21,6 +80,27 @@ export async function POST(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/trail-link-share/{id}:
* delete:
* summary: Delete trail link share
* tags:
* - Trail Link Shares
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Trail link share deleted
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function DELETE(event: RequestEvent) {
try {
const r = await remove(event, Collection.trail_link_share)

View File

@@ -4,6 +4,43 @@ import type { TrailShare } from '$lib/models/trail_share';
import { Collection, create, handleError, list } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/trail-share:
* get:
* summary: List trail shares
* description: Retrieves a paginated list of trail shares with optional ActivityPub actor resolution
* tags:
* - Trail Shares
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: ListResult<TrailShare>
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await list<TrailShare>(event, Collection.trail_share);
@@ -13,6 +50,32 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/trail-share:
* put:
* summary: Create trail share
* description: Creates a new trail share. Converts ActivityPub actor IRI to ID
* tags:
* - Trail Shares
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TrailShareInput'
* responses:
* 201:
* description: Trail share created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TrailShare'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const data = await event.request.json();

View File

@@ -3,6 +3,32 @@ import type { TrailShare } from "$lib/models/trail_share";
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/trail-share/{id}:
* get:
* summary: Get trail share
* description: Retrieves a trail share by ID
* tags:
* - Trail Shares
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: TrailShare
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await show<TrailShare>(event, Collection.trail_share)
@@ -12,6 +38,39 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/trail-share/{id}:
* post:
* summary: Update trail share
* tags:
* - Trail Shares
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TrailShareUpdateInput'
* responses:
* 200:
* description: Trail share updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TrailShare'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await update<TrailShare>(event, TrailShareUpdateSchema, Collection.trail_share)
@@ -21,6 +80,27 @@ export async function POST(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/trail-share/{id}:
* delete:
* summary: Delete trail share
* tags:
* - Trail Shares
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Trail share deleted
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function DELETE(event: RequestEvent) {
try {
const r = await remove(event, Collection.trail_share)

View File

@@ -3,6 +3,43 @@ import type { Trail } from '$lib/models/trail';
import { Collection, create, handleError, list } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/trail:
* get:
* summary: List trails
* description: Retrieves a paginated list of trails with optional filtering and sorting
* tags:
* - Trails
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: ListResult<Trail>
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await list<Trail>(event, Collection.trails);
@@ -23,6 +60,31 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/trail:
* put:
* summary: Create trail
* tags:
* - Trails
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/TrailCreateInput'
* responses:
* 201:
* description: Trail created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Trail'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const r = await create<Trail>(event, TrailCreateSchema, Collection.trails)

View File

@@ -7,6 +7,40 @@ import { json, type RequestEvent } from "@sveltejs/kit";
import type PocketBase from "pocketbase";
import { ClientResponseError } from "pocketbase";
/**
* @swagger
* /api/v1/trail/{id}:
* get:
* summary: Get trail
* description: Retrieves a trail by ID. Supports federated queries via handle parameter, fetching from remote instances and remapping file URLs
* tags:
* - Trails
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* - in: query
* name: handle
* schema:
* type: string
* - in: query
* name: share
* schema:
* type: string
* responses:
* 200:
* description: Trail with optional federated data
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
// try to get the trail simply via the

View File

@@ -2,6 +2,44 @@ import type { Trail } from "$lib/models/trail";
import { Collection, upload } from "$lib/util/api_util";
import { error, json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/trail/{id}/file:
* post:
* summary: Upload trail file
* description: Uploads a file for a trail
* tags:
* - Trails
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* type: object
* properties:
* file:
* type: string
* format: binary
* responses:
* 200:
* description: File uploaded
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Trail'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await upload<Trail>(event, Collection.trails);

View File

@@ -2,6 +2,35 @@ import { type TrailBoundingBox, type TrailFilterValues } from '$lib/models/trail
import { handleError } from '$lib/util/api_util';
import { error, json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/trail/bounding-box:
* get:
* summary: Get trail bounding box
* description: Retrieves geographic bounding box (lat/lon bounds) for user's trails
* tags:
* - Trails
* responses:
* 200:
* description: Bounding box coordinates
* content:
* application/json:
* schema:
* type: object
* properties:
* max_lat:
* type: number
* min_lat:
* type: number
* max_lon:
* type: number
* min_lon:
* type: number
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
if (!event.locals.pb.authStore.record) {
return json({

View File

@@ -1,6 +1,39 @@
import { handleError } from "$lib/util/api_util";
import { type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/trail/download:
* post:
* summary: Download file from URL
* description: Downloads a file from a URL and returns it as a blob
* tags:
* - Trails
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - url
* properties:
* url:
* type: string
* format: uri
* responses:
* 200:
* description: File blob
* content:
* application/octet-stream:
* schema:
* type: string
* format: binary
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
const data = await event.request.json();

View File

@@ -2,6 +2,39 @@ import { type TrailFilterValues } from '$lib/models/trail';
import { handleError } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/trail/filter:
* get:
* summary: Get trail filter values
* description: Retrieves min/max values for trail filtering (distance, elevation gain/loss)
* tags:
* - Trails
* responses:
* 200:
* description: Trail filter values (min/max for distance, elevation)
* content:
* application/json:
* schema:
* type: object
* properties:
* min_distance:
* type: number
* max_distance:
* type: number
* min_elevation_gain:
* type: number
* max_elevation_gain:
* type: number
* min_elevation_loss:
* type: number
* max_elevation_loss:
* type: number
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
if (!event.locals.pb.authStore.record) {
return json({

View File

@@ -2,6 +2,32 @@ import type { Trail } from '$lib/models/trail';
import { Collection, handleError, uploadCreate } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/trail/form:
* put:
* summary: Create trail with file upload
* description: Creates a new trail with file upload (GPX/photos) and date normalization
* tags:
* - Trails
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* $ref: '#/components/schemas/TrailCreateInput'
* responses:
* 201:
* description: Trail created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Trail'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const r = await uploadCreate<Trail>(event, Collection.trails)

View File

@@ -2,6 +2,40 @@ import type { Trail } from "$lib/models/trail";
import { Collection, handleError, uploadUpdate } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/trail/form/{id}:
* post:
* summary: Update trail with file upload
* description: Updates a trail with file upload (GPX/photos) and date normalization
* tags:
* - Trails
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* $ref: '#/components/schemas/TrailUpdateInput'
* responses:
* 200:
* description: Trail updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Trail'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await uploadUpdate<Trail>(event, Collection.trails)

View File

@@ -2,6 +2,34 @@ import { TrailRecommendSchema } from '$lib/models/api/trail_schema';
import { handleError } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/trail/recommend:
* get:
* summary: Get trail recommendations
* description: Retrieves random trail recommendations from Meilisearch
* tags:
* - Trails
* parameters:
* - in: query
* name: size
* schema:
* type: integer
* default: 10
* responses:
* 200:
* description: Array of recommended trails
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: '#/components/schemas/Trail'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const searchParams = Object.fromEntries(event.url.searchParams);

View File

@@ -9,6 +9,40 @@ import { json, type RequestEvent } from "@sveltejs/kit";
import type { Hits, MeiliSearch } from "meilisearch";
import { ClientResponseError } from "pocketbase";
/**
* @swagger
* /api/v1/trail/upload:
* put:
* summary: Upload and parse GPX file as trail
* description: Uploads a GPX file, parses it to extract trail data, performs duplicate detection, and indexes in search
* tags:
* - Trails
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* type: object
* properties:
* file:
* type: string
* format: binary
* name:
* type: string
* ignoreDuplicates:
* type: boolean
* responses:
* 201:
* description: Trail created from GPX
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Trail'
* 400:
* description: Bad Request - Invalid or empty GPX file
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const data = await event.request.formData();

View File

@@ -5,6 +5,31 @@ import { Collection, handleError } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
import { ClientResponseError } from 'pocketbase';
/**
* @swagger
* /api/v1/user:
* put:
* summary: Create user (sign up)
* tags:
* - Users
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/UserCreateInput'
* responses:
* 201:
* description: User created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/User'
* 400:
* description: Bad Request - Signup disabled or invalid data
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
if (env.PUBLIC_DISABLE_SIGNUP === "true") {
throw new ClientResponseError({ status: 401, response: { messgage: "Forbidden" } })

View File

@@ -4,6 +4,35 @@ import type { User } from '$lib/models/user';
import { Collection, handleError, remove, show } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/user/{id}:
* get:
* summary: Get user by ID
* tags:
* - Users
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: User details
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/User'
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await show<User>(event, Collection.users)
@@ -14,6 +43,40 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/user/{id}:
* post:
* summary: Update user
* description: Updates a user. Handles password changes and email change requests
* tags:
* - Users
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/UserUpdateInput'
* responses:
* 200:
* description: User updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/User'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
const data = await event.request.json()
try {
@@ -38,6 +101,27 @@ export async function POST(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/user/{id}:
* delete:
* summary: Delete user
* tags:
* - Users
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: User deleted
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function DELETE(event: RequestEvent) {
try {
const r = await remove(event, Collection.users)

View File

@@ -2,6 +2,44 @@ import type { User } from "$lib/models/user";
import { Collection, upload } from "$lib/util/api_util";
import { error, json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/user/{id}/file:
* post:
* summary: Upload user file
* description: Uploads a file (avatar) for a user
* tags:
* - Users
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* type: object
* properties:
* file:
* type: string
* format: binary
* responses:
* 200:
* description: File uploaded, user updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/User'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await upload<User>(event, Collection.users);

View File

@@ -1,23 +0,0 @@
import type { UserAnonymous } from '$lib/models/user';
import { Collection, handleError, list } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
export async function GET(event: RequestEvent) {
let filter = event.url.searchParams.get("filter");
if (!filter) {
filter = "private=false"
} else {
filter += "&&private=false"
}
event.url.searchParams.set("filter", filter);
try {
const r = await list<UserAnonymous>(event, Collection.users_anonymous);
return json(r)
} catch (e: any) {
return handleError(e);
}
}

View File

@@ -1,13 +0,0 @@
import type { UserAnonymous } from "$lib/models/user";
import { Collection, handleError, show } from '$lib/util/api_util';
import { error, json, type RequestEvent } from '@sveltejs/kit';
export async function GET(event: RequestEvent) {
try {
const r = await show<UserAnonymous>(event, Collection.users_anonymous)
return json(r)
} catch (e: any) {
return handleError(e);
}
}

View File

@@ -2,6 +2,32 @@ import { env } from '$env/dynamic/public';
import { error, json, type NumericRange, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/valhalla/height:
* post:
* summary: Get elevation data
* description: Queries Valhalla service for elevation data at coordinates
* tags:
* - Valhalla
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* responses:
* 200:
* description: Elevation data from Valhalla
* content:
* application/json:
* schema:
* type: object
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
const data = await event.request.json()
if (!env.PUBLIC_VALHALLA_URL) {

View File

@@ -2,6 +2,32 @@ import { env } from '$env/dynamic/public';
import { error, json, type NumericRange, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/valhalla/route:
* post:
* summary: Get route data
* description: Queries Valhalla service for routing data
* tags:
* - Valhalla
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* responses:
* 200:
* description: Route data from Valhalla
* content:
* application/json:
* schema:
* type: object
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
const data = await event.request.json()
if (!env.PUBLIC_VALHALLA_URL) {

View File

@@ -3,6 +3,46 @@ import type { Waypoint } from '$lib/models/waypoint';
import { Collection, create, handleError, list } from '$lib/util/api_util';
import { json, type RequestEvent } from '@sveltejs/kit';
/**
* @swagger
* /api/v1/waypoint:
* get:
* summary: List waypoints
* tags:
* - Waypoints
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* - in: query
* name: perPage
* schema:
* type: integer
* - in: query
* name: sort
* schema:
* type: string
* - in: query
* name: filter
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: List of waypoints
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ListResult'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await list<Waypoint>(event, Collection.waypoints);
@@ -12,6 +52,31 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/waypoint:
* put:
* summary: Create waypoint
* tags:
* - Waypoints
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/WaypointInput'
* responses:
* 201:
* description: Waypoint created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Waypoint'
* 400:
* description: Bad Request
* 500:
* description: Internal Server Error
*/
export async function PUT(event: RequestEvent) {
try {
const r = await create<Waypoint>(event, WaypointCreateSchema, Collection.waypoints)

View File

@@ -3,6 +3,35 @@ import type { Waypoint } from "$lib/models/waypoint";
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/waypoint/{id}:
* get:
* summary: Get waypoint
* tags:
* - Waypoints
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* - in: query
* name: expand
* schema:
* type: string
* responses:
* 200:
* description: Waypoint details
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Waypoint'
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function GET(event: RequestEvent) {
try {
const r = await show<Waypoint>(event, Collection.waypoints)
@@ -12,6 +41,39 @@ export async function GET(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/waypoint/{id}:
* post:
* summary: Update waypoint
* tags:
* - Waypoints
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/WaypointUpdateInput'
* responses:
* 200:
* description: Waypoint updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Waypoint'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await update<Waypoint>(event, WaypointUpdateSchema, Collection.waypoints)
@@ -21,6 +83,27 @@ export async function POST(event: RequestEvent) {
}
}
/**
* @swagger
* /api/v1/waypoint/{id}:
* delete:
* summary: Delete waypoint
* tags:
* - Waypoints
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Waypoint deleted
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function DELETE(event: RequestEvent) {
try {
const r = await remove(event, Collection.waypoints)

View File

@@ -2,6 +2,44 @@ import type { Waypoint } from "$lib/models/waypoint";
import { Collection, handleError, upload } from "$lib/util/api_util";
import { json, type RequestEvent } from "@sveltejs/kit";
/**
* @swagger
* /api/v1/waypoint/{id}/file:
* post:
* summary: Upload waypoint file
* description: Uploads a file (photo) for a waypoint
* tags:
* - Waypoints
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* type: object
* properties:
* file:
* type: string
* format: binary
* responses:
* 200:
* description: File uploaded, waypoint updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Waypoint'
* 400:
* description: Bad Request
* 404:
* description: Not Found
* 500:
* description: Internal Server Error
*/
export async function POST(event: RequestEvent) {
try {
const r = await upload<Waypoint>(event, Collection.waypoints);