Updated TS types and added support
ci/woodpecker/push/ociImagePush Pipeline is running
Details
ci/woodpecker/push/ociImagePush Pipeline is running
Details
This commit is contained in:
parent
1bef42ead5
commit
b2543b29d3
|
@ -18,9 +18,9 @@ import {
|
|||
FrontendApiEndpoints,
|
||||
MagApiClient,
|
||||
Method,
|
||||
types,
|
||||
} from "magnetar-common";
|
||||
import { magReactionToLegacy } from "@/scripts-mag/mag-util";
|
||||
import { types } from "magnetar-common";
|
||||
|
||||
export const pendingApiRequestsCount = ref(0);
|
||||
|
||||
|
@ -35,11 +35,13 @@ export async function magApi<
|
|||
T["method"] & Method,
|
||||
T["pathParams"] & string[],
|
||||
T["request"],
|
||||
T["response"]
|
||||
T["response"],
|
||||
T["paginated"] & boolean
|
||||
>
|
||||
>(
|
||||
endpoint: T,
|
||||
data: T["request"],
|
||||
data: T["request"] &
|
||||
(T["paginated"] extends true ? Partial<types.PaginationShape> : any),
|
||||
pathParams: {
|
||||
[K in keyof T["pathParams"] as T["pathParams"][K] & string]:
|
||||
| string
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
import { PaginationShape } from "./types/PaginationShape";
|
||||
|
||||
export type Method = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
||||
|
||||
export interface BackendApiEndpoint<
|
||||
M extends Method,
|
||||
PP extends string[],
|
||||
T,
|
||||
R
|
||||
R,
|
||||
PG extends boolean
|
||||
> {
|
||||
method: M;
|
||||
endpoint: string;
|
||||
pathParams: PP;
|
||||
request?: T;
|
||||
response?: R;
|
||||
paginated: PG;
|
||||
}
|
||||
|
||||
function nestedUrlSearchParams(data: any, topLevel: boolean = true): string {
|
||||
|
@ -52,6 +56,39 @@ export interface MagApiError {
|
|||
message: string;
|
||||
}
|
||||
|
||||
export interface PaginatedResult<T> {
|
||||
prev?: URL;
|
||||
data: T;
|
||||
next?: URL;
|
||||
}
|
||||
|
||||
function extractHeaderRel(
|
||||
headers: Headers,
|
||||
rel: "prev" | "next"
|
||||
): URL | undefined {
|
||||
for (const [k, v] of headers) {
|
||||
if (k.toLowerCase() !== "link") {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const links of v.split(",").map(String.prototype.trim)) {
|
||||
const [url, relPar] = links.split(";").map(String.prototype.trim);
|
||||
if (!url || !relPar) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const urlMatch = url.match(/^<(.+?)>$/)?.[1];
|
||||
const relMatch = relPar.match(/rel="(.+?)"/)?.[1];
|
||||
|
||||
if (relMatch == rel && urlMatch) {
|
||||
return new URL(urlMatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export class MagApiClient {
|
||||
private readonly baseUrl: string;
|
||||
|
||||
|
@ -64,18 +101,24 @@ export class MagApiClient {
|
|||
T["method"] & Method,
|
||||
T["pathParams"] & string[],
|
||||
T["request"],
|
||||
T["response"]
|
||||
T["response"],
|
||||
T["paginated"] & boolean
|
||||
>
|
||||
>(
|
||||
{ endpoint, method }: T,
|
||||
data: T["request"],
|
||||
{ endpoint, method, paginated }: T,
|
||||
data: T["request"] &
|
||||
(T["paginated"] extends true ? Partial<PaginationShape> : any),
|
||||
pathParams: {
|
||||
[K in keyof T["pathParams"] as T["pathParams"][K] & string]:
|
||||
| string
|
||||
| number;
|
||||
},
|
||||
token?: string | null | undefined
|
||||
): Promise<T["response"]> {
|
||||
): Promise<
|
||||
T["paginated"] extends true
|
||||
? PaginatedResult<T["response"]>
|
||||
: T["response"]
|
||||
> {
|
||||
type Response = T["response"];
|
||||
|
||||
const authorizationToken = token ?? undefined;
|
||||
|
@ -97,7 +140,7 @@ export class MagApiClient {
|
|||
}
|
||||
}
|
||||
|
||||
return await fetch(url, {
|
||||
return (await fetch(url, {
|
||||
method,
|
||||
body: method !== "GET" ? JSON.stringify(data) : undefined,
|
||||
credentials: "omit",
|
||||
|
@ -108,9 +151,25 @@ export class MagApiClient {
|
|||
const body = res.status === 204 ? null : await res.json();
|
||||
|
||||
if (res.status === 200) {
|
||||
return body as Response;
|
||||
if (paginated) {
|
||||
return {
|
||||
prev: extractHeaderRel(res.headers, "prev"),
|
||||
data: body as Response,
|
||||
next: extractHeaderRel(res.headers, "next"),
|
||||
};
|
||||
} else {
|
||||
return body as Response;
|
||||
}
|
||||
} else if (res.status === 204) {
|
||||
return null as any as Response;
|
||||
if (paginated) {
|
||||
return {
|
||||
prev: extractHeaderRel(res.headers, "prev"),
|
||||
data: null as any as Response,
|
||||
next: extractHeaderRel(res.headers, "next"),
|
||||
};
|
||||
} else {
|
||||
return null as any as Response;
|
||||
}
|
||||
} else {
|
||||
throw body as MagApiError;
|
||||
}
|
||||
|
@ -121,6 +180,8 @@ export class MagApiClient {
|
|||
code: "Client:GenericApiError",
|
||||
message: e,
|
||||
} as MagApiError;
|
||||
});
|
||||
})) as T["paginated"] extends true
|
||||
? PaginatedResult<Response>
|
||||
: Response;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,3 +48,4 @@ export { StartFilter } from "./types/StartFilter";
|
|||
export { NoFilter } from "./types/NoFilter";
|
||||
export { TimelineType } from "./types/TimelineType";
|
||||
export { Empty } from "./types/Empty";
|
||||
export { PaginationShape } from "./types/PaginationShape";
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type Empty = null;
|
||||
export type Empty = Record<string, never>;
|
|
@ -1,5 +1,4 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { NoteListFilter } from "./NoteListFilter";
|
||||
import type { SpanFilter } from "./SpanFilter";
|
||||
|
||||
export interface GetTimelineReq { limit?: bigint, filter?: NoteListFilter, range?: SpanFilter, }
|
||||
export interface GetTimelineReq { filter?: NoteListFilter, }
|
|
@ -0,0 +1,4 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { SpanFilter } from "./SpanFilter";
|
||||
|
||||
export interface PaginationShape { pagination: SpanFilter, limit: bigint, }
|
|
@ -1,12 +1,13 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Empty } from "../Empty";
|
||||
import type { PackUserBase } from "../packed/PackUserBase";
|
||||
import type { PackUserMaybeAll } from "../packed/PackUserMaybeAll";
|
||||
|
||||
export const GetFollowRequestsSelf = {
|
||||
endpoint: "/users/@self/follow-requests",
|
||||
pathParams: [] as [],
|
||||
method: "GET" as "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
|
||||
request: undefined as unknown as Empty,
|
||||
response: undefined as unknown as Array<PackUserBase>
|
||||
response: undefined as unknown as Array<PackUserMaybeAll>,
|
||||
paginated: true as true
|
||||
}
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Empty } from "../Empty";
|
||||
import type { PackUserBase } from "../packed/PackUserBase";
|
||||
import type { PackUserMaybeAll } from "../packed/PackUserMaybeAll";
|
||||
|
||||
export const GetFollowersById = {
|
||||
endpoint: "/users/:id/followers",
|
||||
pathParams: ["id"] as ["id"],
|
||||
method: "GET" as "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
|
||||
request: undefined as unknown as Empty,
|
||||
response: undefined as unknown as Array<PackUserBase>
|
||||
response: undefined as unknown as Array<PackUserMaybeAll>,
|
||||
paginated: true as true
|
||||
}
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Empty } from "../Empty";
|
||||
import type { PackUserBase } from "../packed/PackUserBase";
|
||||
import type { PackUserMaybeAll } from "../packed/PackUserMaybeAll";
|
||||
|
||||
export const GetFollowersSelf = {
|
||||
endpoint: "/users/@self/followers",
|
||||
pathParams: [] as [],
|
||||
method: "GET" as "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
|
||||
request: undefined as unknown as Empty,
|
||||
response: undefined as unknown as Array<PackUserBase>
|
||||
response: undefined as unknown as Array<PackUserMaybeAll>,
|
||||
paginated: true as true
|
||||
}
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Empty } from "../Empty";
|
||||
import type { PackUserBase } from "../packed/PackUserBase";
|
||||
import type { PackUserMaybeAll } from "../packed/PackUserMaybeAll";
|
||||
|
||||
export const GetFollowingById = {
|
||||
endpoint: "/users/:id/following",
|
||||
pathParams: ["id"] as ["id"],
|
||||
method: "GET" as "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
|
||||
request: undefined as unknown as Empty,
|
||||
response: undefined as unknown as Array<PackUserBase>
|
||||
response: undefined as unknown as Array<PackUserMaybeAll>,
|
||||
paginated: true as true
|
||||
}
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Empty } from "../Empty";
|
||||
import type { PackUserBase } from "../packed/PackUserBase";
|
||||
import type { PackUserMaybeAll } from "../packed/PackUserMaybeAll";
|
||||
|
||||
export const GetFollowingSelf = {
|
||||
endpoint: "/users/@self/following",
|
||||
pathParams: [] as [],
|
||||
method: "GET" as "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
|
||||
request: undefined as unknown as Empty,
|
||||
response: undefined as unknown as Array<PackUserBase>
|
||||
response: undefined as unknown as Array<PackUserMaybeAll>,
|
||||
paginated: true as true
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ export const GetManyUsersById = {
|
|||
pathParams: [] as [],
|
||||
method: "GET" as "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
|
||||
request: undefined as unknown as ManyUsersByIdReq,
|
||||
response: undefined as unknown as Array<PackUserBase | null>
|
||||
response: undefined as unknown as Array<PackUserBase | null>,
|
||||
paginated: false as false
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ export const GetNoteById = {
|
|||
pathParams: ["id"] as ["id"],
|
||||
method: "GET" as "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
|
||||
request: undefined as unknown as NoteByIdReq,
|
||||
response: undefined as unknown as PackNoteMaybeFull
|
||||
response: undefined as unknown as PackNoteMaybeFull,
|
||||
paginated: false as false
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ export const GetTimeline = {
|
|||
pathParams: ["timeline_type"] as ["timeline_type"],
|
||||
method: "GET" as "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
|
||||
request: undefined as unknown as GetTimelineReq,
|
||||
response: undefined as unknown as Array<PackNoteMaybeFull>
|
||||
response: undefined as unknown as Array<PackNoteMaybeFull>,
|
||||
paginated: true as true
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ export const GetUserByAcct = {
|
|||
pathParams: ["user_acct"] as ["user_acct"],
|
||||
method: "GET" as "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
|
||||
request: undefined as unknown as UserByIdReq,
|
||||
response: undefined as unknown as PackUserMaybeAll
|
||||
response: undefined as unknown as PackUserMaybeAll,
|
||||
paginated: false as false
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ export const GetUserById = {
|
|||
pathParams: ["user_id"] as ["user_id"],
|
||||
method: "GET" as "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
|
||||
request: undefined as unknown as UserByIdReq,
|
||||
response: undefined as unknown as PackUserMaybeAll
|
||||
response: undefined as unknown as PackUserMaybeAll,
|
||||
paginated: false as false
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ export const GetUserSelf = {
|
|||
pathParams: [] as [],
|
||||
method: "GET" as "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
|
||||
request: undefined as unknown as UserSelfReq,
|
||||
response: undefined as unknown as PackUserSelfMaybeAll
|
||||
response: undefined as unknown as PackUserSelfMaybeAll,
|
||||
paginated: false as false
|
||||
}
|
||||
|
|
@ -155,6 +155,7 @@ pub fn derive_endpoint(item: TokenStream) -> TokenStream {
|
|||
let mut method = None;
|
||||
let mut request = None;
|
||||
let mut response = None;
|
||||
let mut paginated = false;
|
||||
let mut request_args = None;
|
||||
let mut response_args = None;
|
||||
|
||||
|
@ -203,6 +204,17 @@ pub fn derive_endpoint(item: TokenStream) -> TokenStream {
|
|||
|
||||
name = new_name.value();
|
||||
}
|
||||
"paginated" => {
|
||||
let Expr::Lit(ExprLit {
|
||||
lit: Lit::Bool(val),
|
||||
..
|
||||
}) = value
|
||||
else {
|
||||
panic!("expected a boolean");
|
||||
};
|
||||
|
||||
paginated = val.value();
|
||||
}
|
||||
"endpoint" => {
|
||||
let Expr::Lit(ExprLit {
|
||||
lit: Lit::Str(endpoint_val),
|
||||
|
@ -376,6 +388,7 @@ pub fn derive_endpoint(item: TokenStream) -> TokenStream {
|
|||
const NAME: &'static str = #name;
|
||||
const ENDPOINT: &'static str = #endpoint;
|
||||
const METHOD: Method = #method;
|
||||
const PAGINATED: bool = #paginated;
|
||||
|
||||
type Request = #request;
|
||||
type Response = #response;
|
||||
|
@ -397,7 +410,8 @@ pub fn derive_endpoint(item: TokenStream) -> TokenStream {
|
|||
pathParams: {} as {},\n \
|
||||
method: \"{}\" as \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\",\n \
|
||||
request: undefined as unknown as {},\n \
|
||||
response: undefined as unknown as {}\n\
|
||||
response: undefined as unknown as {},\n \
|
||||
paginated: {} as {}\n\
|
||||
}}
|
||||
",
|
||||
Self::name(),
|
||||
|
@ -406,7 +420,9 @@ pub fn derive_endpoint(item: TokenStream) -> TokenStream {
|
|||
#path_params,
|
||||
Self::METHOD,
|
||||
#call_name_req,
|
||||
#call_name_res
|
||||
#call_name_res,
|
||||
#paginated,
|
||||
#paginated
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ pub trait Endpoint {
|
|||
const NAME: &'static str;
|
||||
const ENDPOINT: &'static str;
|
||||
const METHOD: Method;
|
||||
const PAGINATED: bool;
|
||||
|
||||
type Request: Serialize + DeserializeOwned + Send + Sync + 'static;
|
||||
type Response: Serialize + DeserializeOwned + Send + Sync + 'static;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
use crate::endpoints::Endpoint;
|
||||
use crate::types::note::{NoteListFilter, PackNoteMaybeFull};
|
||||
use crate::types::SpanFilter;
|
||||
use crate::util_types::U64Range;
|
||||
use http::Method;
|
||||
use magnetar_sdk_macros::Endpoint;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -11,16 +9,8 @@ use ts_rs::TS;
|
|||
#[derive(Serialize, Deserialize, TS)]
|
||||
#[ts(export)]
|
||||
pub struct GetTimelineReq {
|
||||
#[ts(optional)]
|
||||
pub limit: Option<U64Range<1, 100>>,
|
||||
#[ts(optional)]
|
||||
pub filter: Option<NoteListFilter>,
|
||||
#[ts(optional)]
|
||||
pub range: Option<SpanFilter>,
|
||||
}
|
||||
|
||||
pub fn default_timeline_limit<const MIN: u64, const MAX: u64>() -> U64Range<MIN, MAX> {
|
||||
30.try_into().unwrap()
|
||||
}
|
||||
|
||||
#[derive(Endpoint)]
|
||||
|
@ -29,5 +19,6 @@ pub fn default_timeline_limit<const MIN: u64, const MAX: u64>() -> U64Range<MIN,
|
|||
method = Method::GET,
|
||||
request = "GetTimelineReq",
|
||||
response = "Vec<PackNoteMaybeFull>",
|
||||
paginated = true
|
||||
)]
|
||||
pub struct GetTimeline;
|
||||
|
|
|
@ -88,7 +88,8 @@ pub struct GetUserByAcct;
|
|||
endpoint = "/users/:id/followers",
|
||||
method = Method::GET,
|
||||
request = "Empty",
|
||||
response = "Vec<PackUserMaybeAll>"
|
||||
response = "Vec<PackUserMaybeAll>",
|
||||
paginated = true
|
||||
)]
|
||||
pub struct GetFollowersById;
|
||||
|
||||
|
@ -97,7 +98,8 @@ pub struct GetFollowersById;
|
|||
endpoint = "/users/:id/following",
|
||||
method = Method::GET,
|
||||
request = "Empty",
|
||||
response = "Vec<PackUserMaybeAll>"
|
||||
response = "Vec<PackUserMaybeAll>",
|
||||
paginated = true
|
||||
)]
|
||||
pub struct GetFollowingById;
|
||||
|
||||
|
@ -106,7 +108,8 @@ pub struct GetFollowingById;
|
|||
endpoint = "/users/@self/followers",
|
||||
method = Method::GET,
|
||||
request = "Empty",
|
||||
response = "Vec<PackUserMaybeAll>"
|
||||
response = "Vec<PackUserMaybeAll>",
|
||||
paginated = true
|
||||
)]
|
||||
pub struct GetFollowersSelf;
|
||||
|
||||
|
@ -115,7 +118,8 @@ pub struct GetFollowersSelf;
|
|||
endpoint = "/users/@self/following",
|
||||
method = Method::GET,
|
||||
request = "Empty",
|
||||
response = "Vec<PackUserMaybeAll>"
|
||||
response = "Vec<PackUserMaybeAll>",
|
||||
paginated = true
|
||||
)]
|
||||
pub struct GetFollowingSelf;
|
||||
|
||||
|
@ -124,6 +128,7 @@ pub struct GetFollowingSelf;
|
|||
endpoint = "/users/@self/follow-requests",
|
||||
method = Method::GET,
|
||||
request = "Empty",
|
||||
response = "Vec<PackUserMaybeAll>"
|
||||
response = "Vec<PackUserMaybeAll>",
|
||||
paginated = true
|
||||
)]
|
||||
pub struct GetFollowRequestsSelf;
|
||||
|
|
Loading…
Reference in New Issue