refactor: ♻️ Refactor naming and code exports for both modules

This commit is contained in:
Jesse Wierzbinski 2024-06-19 12:21:34 -10:00
parent 8a37e7df95
commit dc352bc276
No known key found for this signature in database
29 changed files with 629 additions and 312 deletions

View file

@ -1,5 +1,5 @@
{ {
"$schema": "https://biomejs.dev/schemas/1.7.3/schema.json", "$schema": "https://biomejs.dev/schemas/1.8.1/schema.json",
"organizeImports": { "organizeImports": {
"enabled": true, "enabled": true,
"ignore": ["node_modules", "dist"] "ignore": ["node_modules", "dist"]
@ -7,7 +7,68 @@
"linter": { "linter": {
"enabled": true, "enabled": true,
"rules": { "rules": {
"recommended": true "all": true,
"correctness": {
"noNodejsModules": "off"
},
"complexity": {
"noExcessiveCognitiveComplexity": "off"
},
"style": {
"noDefaultExport": "off",
"noParameterProperties": "off",
"noNamespaceImport": "off",
"useFilenamingConvention": "off",
"useNamingConvention": {
"level": "warn",
"options": {
"requireAscii": false,
"strictCase": false,
"conventions": [
{
"selector": {
"kind": "typeProperty"
},
"formats": [
"camelCase",
"CONSTANT_CASE",
"PascalCase",
"snake_case"
]
},
{
"selector": {
"kind": "objectLiteralProperty",
"scope": "any"
},
"formats": [
"camelCase",
"CONSTANT_CASE",
"PascalCase",
"snake_case"
]
},
{
"selector": {
"kind": "classMethod",
"scope": "any"
},
"formats": ["camelCase", "PascalCase"]
}
]
}
}
},
"nursery": {
"noDuplicateElseIf": "warn",
"noDuplicateJsonKeys": "warn",
"noEvolvingTypes": "warn",
"noYodaExpression": "warn",
"useConsistentBuiltinInstantiation": "warn",
"useErrorMessage": "warn",
"useImportExtensions": "off",
"useThrowNewError": "warn"
}
}, },
"ignore": ["node_modules", "dist"] "ignore": ["node_modules", "dist"]
}, },
@ -16,5 +77,8 @@
"indentStyle": "space", "indentStyle": "space",
"indentWidth": 4, "indentWidth": 4,
"ignore": ["node_modules", "dist"] "ignore": ["node_modules", "dist"]
},
"javascript": {
"globals": ["Bun"]
} }
} }

View file

@ -24,7 +24,9 @@ export interface Output<ReturnType> {
const objectToFormData = (obj: ConvertibleObject): FormData => { const objectToFormData = (obj: ConvertibleObject): FormData => {
return Object.keys(obj).reduce((formData, key) => { return Object.keys(obj).reduce((formData, key) => {
if (obj[key] === undefined || obj[key] === null) return formData; if (obj[key] === undefined || obj[key] === null) {
return formData;
}
if (obj[key] instanceof File) { if (obj[key] instanceof File) {
formData.append(key, obj[key] as Blob); formData.append(key, obj[key] as Blob);
return formData; return formData;
@ -113,12 +115,12 @@ export class BaseClient {
}; };
} }
private async constructRequest( private constructRequest(
path: string, path: string,
method: HttpVerb, method: HttpVerb,
body?: object | FormData, body?: object | FormData,
extra?: RequestInit, extra?: RequestInit,
): Promise<Request> { ): Request {
const headers = new Headers({ const headers = new Headers({
"User-Agent": DEFAULT_UA, "User-Agent": DEFAULT_UA,
}); });
@ -148,32 +150,30 @@ export class BaseClient {
}); });
} }
public async get<ReturnType>( public get<ReturnType>(
path: string, path: string,
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<ReturnType>> { ): Promise<Output<ReturnType>> {
return await this.request( return this.request(
await this.constructRequest(path, "GET", undefined, extra), this.constructRequest(path, "GET", undefined, extra),
); );
} }
public async post<ReturnType>( public post<ReturnType>(
path: string, path: string,
body?: object, body?: object,
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<ReturnType>> { ): Promise<Output<ReturnType>> {
return await this.request( return this.request(this.constructRequest(path, "POST", body, extra));
await this.constructRequest(path, "POST", body, extra),
);
} }
public async postForm<ReturnType>( public postForm<ReturnType>(
path: string, path: string,
body: FormData | ConvertibleObject, body: FormData | ConvertibleObject,
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<ReturnType>> { ): Promise<Output<ReturnType>> {
return await this.request( return this.request(
await this.constructRequest( this.constructRequest(
path, path,
"POST", "POST",
body instanceof FormData ? body : objectToFormData(body), body instanceof FormData ? body : objectToFormData(body),
@ -182,23 +182,21 @@ export class BaseClient {
); );
} }
public async put<ReturnType>( public put<ReturnType>(
path: string, path: string,
body?: object, body?: object,
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<ReturnType>> { ): Promise<Output<ReturnType>> {
return await this.request( return this.request(this.constructRequest(path, "PUT", body, extra));
await this.constructRequest(path, "PUT", body, extra),
);
} }
public async putForm<ReturnType>( public putForm<ReturnType>(
path: string, path: string,
body: FormData | ConvertibleObject, body: FormData | ConvertibleObject,
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<ReturnType>> { ): Promise<Output<ReturnType>> {
return await this.request( return this.request(
await this.constructRequest( this.constructRequest(
path, path,
"PUT", "PUT",
body instanceof FormData ? body : objectToFormData(body), body instanceof FormData ? body : objectToFormData(body),
@ -207,23 +205,21 @@ export class BaseClient {
); );
} }
public async patch<ReturnType>( public patch<ReturnType>(
path: string, path: string,
body?: object, body?: object,
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<ReturnType>> { ): Promise<Output<ReturnType>> {
return await this.request( return this.request(this.constructRequest(path, "PATCH", body, extra));
await this.constructRequest(path, "PATCH", body, extra),
);
} }
public async patchForm<ReturnType>( public patchForm<ReturnType>(
path: string, path: string,
body: FormData | ConvertibleObject, body: FormData | ConvertibleObject,
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<ReturnType>> { ): Promise<Output<ReturnType>> {
return await this.request( return this.request(
await this.constructRequest( this.constructRequest(
path, path,
"PATCH", "PATCH",
body instanceof FormData ? body : objectToFormData(body), body instanceof FormData ? body : objectToFormData(body),
@ -232,23 +228,21 @@ export class BaseClient {
); );
} }
public async delete<ReturnType>( public delete<ReturnType>(
path: string, path: string,
body?: object, body?: object,
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<ReturnType>> { ): Promise<Output<ReturnType>> {
return await this.request( return this.request(this.constructRequest(path, "DELETE", body, extra));
await this.constructRequest(path, "DELETE", body, extra),
);
} }
public async deleteForm<ReturnType>( public deleteForm<ReturnType>(
path: string, path: string,
body: FormData | ConvertibleObject, body: FormData | ConvertibleObject,
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<ReturnType>> { ): Promise<Output<ReturnType>> {
return await this.request( return this.request(
await this.constructRequest( this.constructRequest(
path, path,
"DELETE", "DELETE",
body instanceof FormData ? body : objectToFormData(body), body instanceof FormData ? body : objectToFormData(body),

View file

@ -71,12 +71,12 @@ export class LysandClient extends BaseClient {
*/ */
public addAccountToList( public addAccountToList(
id: string, id: string,
account_ids: string[], accountIds: string[],
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<void>> { ): Promise<Output<void>> {
return this.post<void>( return this.post<void>(
`/api/v1/lists/${id}/accounts`, `/api/v1/lists/${id}/accounts`,
{ account_ids }, { accountIds },
extra, extra,
); );
} }
@ -175,7 +175,7 @@ export class LysandClient extends BaseClient {
* @param options.website URL to the application's website. * @param options.website URL to the application's website.
*/ */
public createApp( public createApp(
client_name: string, clientName: string,
options?: Partial<{ options?: Partial<{
redirect_uris: string; redirect_uris: string;
scopes: string[]; scopes: string[];
@ -183,7 +183,7 @@ export class LysandClient extends BaseClient {
}>, }>,
): Promise<Output<ApplicationData>> { ): Promise<Output<ApplicationData>> {
return this.postForm<ApplicationData>("/api/v1/apps", { return this.postForm<ApplicationData>("/api/v1/apps", {
client_name, clientName,
...options, ...options,
scopes: options?.scopes?.join(" ") || DEFAULT_SCOPE.join(" "), scopes: options?.scopes?.join(" ") || DEFAULT_SCOPE.join(" "),
redirect_uris: options?.redirect_uris || NO_REDIRECT, redirect_uris: options?.redirect_uris || NO_REDIRECT,
@ -243,12 +243,12 @@ export class LysandClient extends BaseClient {
*/ */
public deleteAccountsFromList( public deleteAccountsFromList(
id: string, id: string,
account_ids: string[], accountIds: string[],
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<void>> { ): Promise<Output<void>> {
return this.delete<void>( return this.delete<void>(
`/api/v1/lists/${id}/accounts`, `/api/v1/lists/${id}/accounts`,
{ account_ids }, { accountIds },
extra, extra,
); );
} }
@ -441,19 +441,19 @@ export class LysandClient extends BaseClient {
* @param redirect_uri Must be the same URI as the time when you register your OAuth2 application * @param redirect_uri Must be the same URI as the time when you register your OAuth2 application
*/ */
public fetchAccessToken( public fetchAccessToken(
client_id: string, clientId: string,
client_secret: string, clientSecret: string,
code?: string, code?: string,
redirect_uri: string = NO_REDIRECT, redirectUri: string = NO_REDIRECT,
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<Token>> { ): Promise<Output<Token>> {
return this.postForm<Token>( return this.postForm<Token>(
"/oauth/token", "/oauth/token",
{ {
client_id, clientId,
client_secret, clientSecret,
code, code,
redirect_uri, redirectUri,
grant_type: "authorization_code", grant_type: "authorization_code",
}, },
extra, extra,
@ -505,8 +505,8 @@ export class LysandClient extends BaseClient {
* @returns * @returns
*/ */
public generateAuthUrl( public generateAuthUrl(
client_id: string, clientId: string,
client_secret: string, clientSecret: string,
options: Partial<{ options: Partial<{
redirect_uri: string; redirect_uri: string;
scopes: string[]; scopes: string[];
@ -514,8 +514,8 @@ export class LysandClient extends BaseClient {
): Promise<string> { ): Promise<string> {
const oauthClient = new OAuth2Client({ const oauthClient = new OAuth2Client({
server: this.baseUrl.toString(), server: this.baseUrl.toString(),
clientId: client_id, clientId: clientId,
clientSecret: client_secret, clientSecret: clientSecret,
tokenEndpoint: "/oauth/token", tokenEndpoint: "/oauth/token",
authorizationEndpoint: "/oauth/authorize", authorizationEndpoint: "/oauth/authorize",
}); });
@ -560,9 +560,15 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.since_id) params.set("since_id", options.since_id); params.set("max_id", options.max_id);
if (options.limit) params.set("limit", options.limit.toString()); }
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Account[]>( return this.get<Account[]>(
@ -592,9 +598,15 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.since_id) params.set("since_id", options.since_id); params.set("max_id", options.max_id);
if (options.limit) params.set("limit", options.limit.toString()); }
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Account[]>( return this.get<Account[]>(
@ -647,14 +659,30 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.min_id) params.set("min_id", options.min_id); params.set("max_id", options.max_id);
if (options.since_id) params.set("since_id", options.since_id); }
if (options.limit) params.set("limit", options.limit.toString()); if (options.min_id) {
if (options.only_media) params.set("only_media", "true"); params.set("min_id", options.min_id);
if (options.pinned) params.set("pinned", "true"); }
if (options.exclude_replies) params.set("exclude_replies", "true"); if (options.since_id) {
if (options.exclude_reblogs) params.set("exclude_reblogs", "true"); params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
if (options.only_media) {
params.set("only_media", "true");
}
if (options.pinned) {
params.set("pinned", "true");
}
if (options.exclude_replies) {
params.set("exclude_replies", "true");
}
if (options.exclude_reblogs) {
params.set("exclude_reblogs", "true");
}
} }
return this.get<Status[]>( return this.get<Status[]>(
@ -686,10 +714,18 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.since_id) params.set("since_id", options.since_id); params.set("max_id", options.max_id);
if (options.min_id) params.set("min_id", options.min_id); }
if (options.limit) params.set("limit", options.limit.toString()); if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.min_id) {
params.set("min_id", options.min_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Account[]>( return this.get<Account[]>(
@ -716,9 +752,15 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.min_id) params.set("min_id", options.min_id); params.set("max_id", options.max_id);
if (options.limit) params.set("limit", options.limit.toString()); }
if (options.min_id) {
params.set("min_id", options.min_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Account[]>(`/api/v1/blocks?${params}`); return this.get<Account[]>(`/api/v1/blocks?${params}`);
@ -744,10 +786,18 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.min_id) params.set("min_id", options.min_id); params.set("max_id", options.max_id);
if (options.since_id) params.set("since_id", options.since_id); }
if (options.limit) params.set("limit", options.limit.toString()); if (options.min_id) {
params.set("min_id", options.min_id);
}
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Status[]>(`/api/v1/bookmarks?${params}`); return this.get<Status[]>(`/api/v1/bookmarks?${params}`);
@ -775,10 +825,18 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.min_id) params.set("min_id", options.min_id); params.set("max_id", options.max_id);
if (options.since_id) params.set("since_id", options.since_id); }
if (options.limit) params.set("limit", options.limit.toString()); if (options.min_id) {
params.set("min_id", options.min_id);
}
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Conversation[]>( return this.get<Conversation[]>(
@ -805,9 +863,15 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.since_id) params.set("since_id", options.since_id); params.set("max_id", options.max_id);
if (options.limit) params.set("limit", options.limit.toString()); }
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<string[]>(`/api/v1/domain_blocks?${params}`); return this.get<string[]>(`/api/v1/domain_blocks?${params}`);
@ -832,9 +896,15 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.since_id) params.set("since_id", options.since_id); params.set("max_id", options.max_id);
if (options.limit) params.set("limit", options.limit.toString()); }
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Account[]>(`/api/v1/endorsements?${params}`, extra); return this.get<Account[]>(`/api/v1/endorsements?${params}`, extra);
@ -858,9 +928,15 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.min_id) params.set("min_id", options.min_id); params.set("max_id", options.max_id);
if (options.limit) params.set("limit", options.limit.toString()); }
if (options.min_id) {
params.set("min_id", options.min_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Status[]>(`/api/v1/favourites?${params}`); return this.get<Status[]>(`/api/v1/favourites?${params}`);
@ -894,7 +970,9 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.limit) params.set("limit", options.limit.toString()); if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Account[]>(`/api/v1/follow_requests?${params}`); return this.get<Account[]>(`/api/v1/follow_requests?${params}`);
@ -932,11 +1010,21 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.min_id) params.set("min_id", options.min_id); params.set("max_id", options.max_id);
if (options.since_id) params.set("since_id", options.since_id); }
if (options.limit) params.set("limit", options.limit.toString()); if (options.min_id) {
if (options.local) params.set("local", "true"); params.set("min_id", options.min_id);
}
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
if (options.local) {
params.set("local", "true");
}
} }
return this.get<Status[]>(`/api/v1/timelines/home?${params}`, extra); return this.get<Status[]>(`/api/v1/timelines/home?${params}`, extra);
@ -1007,10 +1095,18 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.limit) params.set("limit", options.limit.toString()); if (options.limit) {
if (options.local) params.set("local", "true"); params.set("limit", options.limit.toString());
if (options.offset) params.set("offset", options.offset.toString()); }
if (options.order) params.set("order", options.order); if (options.local) {
params.set("local", "true");
}
if (options.offset) {
params.set("offset", options.offset.toString());
}
if (options.order) {
params.set("order", options.order);
}
} }
return this.get<Account[]>(`/api/v1/directory?${params}`, extra); return this.get<Account[]>(`/api/v1/directory?${params}`, extra);
@ -1078,7 +1174,9 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.limit) params.set("limit", options.limit.toString()); if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Tag[]>(`/api/v1/trends?${params}`); return this.get<Tag[]>(`/api/v1/trends?${params}`);
@ -1117,10 +1215,18 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.min_id) params.set("min_id", options.min_id); params.set("max_id", options.max_id);
if (options.since_id) params.set("since_id", options.since_id); }
if (options.limit) params.set("limit", options.limit.toString()); if (options.min_id) {
params.set("min_id", options.min_id);
}
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Status[]>( return this.get<Status[]>(
@ -1162,11 +1268,21 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.min_id) params.set("min_id", options.min_id); params.set("max_id", options.max_id);
if (options.since_id) params.set("since_id", options.since_id); }
if (options.limit) params.set("limit", options.limit.toString()); if (options.min_id) {
if (options.only_media) params.set("only_media", "true"); params.set("min_id", options.min_id);
}
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
if (options.only_media) {
params.set("only_media", "true");
}
} }
return this.get<Status[]>(`/api/v1/timelines/public?${params}`, extra); return this.get<Status[]>(`/api/v1/timelines/public?${params}`, extra);
@ -1223,9 +1339,15 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.since_id) params.set("since_id", options.since_id); params.set("max_id", options.max_id);
if (options.limit) params.set("limit", options.limit.toString()); }
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Account[]>(`/api/v1/mutes?${params}`); return this.get<Account[]>(`/api/v1/mutes?${params}`);
@ -1268,18 +1390,27 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.min_id) params.set("min_id", options.min_id); params.set("max_id", options.max_id);
if (options.since_id) params.set("since_id", options.since_id); }
if (options.limit) params.set("limit", options.limit.toString()); if (options.min_id) {
params.set("min_id", options.min_id);
}
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
if (options.exclude_types) { if (options.exclude_types) {
for (const type of options.exclude_types) { for (const type of options.exclude_types) {
params.append("exclude_types[]", type); params.append("exclude_types[]", type);
} }
} }
if (options.account_id) if (options.account_id) {
params.set("account_id", options.account_id); params.set("account_id", options.account_id);
} }
}
return this.get<Notification[]>(`/api/v1/notifications?${params}`); return this.get<Notification[]>(`/api/v1/notifications?${params}`);
} }
@ -1326,11 +1457,21 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.min_id) params.set("min_id", options.min_id); params.set("max_id", options.max_id);
if (options.since_id) params.set("since_id", options.since_id); }
if (options.limit) params.set("limit", options.limit.toString()); if (options.min_id) {
if (options.only_media) params.set("only_media", "true"); params.set("min_id", options.min_id);
}
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
if (options.only_media) {
params.set("only_media", "true");
}
} }
return this.get<Status[]>(`/api/v1/timelines/public?${params}`, extra); return this.get<Status[]>(`/api/v1/timelines/public?${params}`, extra);
@ -1388,7 +1529,9 @@ export class LysandClient extends BaseClient {
} }
if (options) { if (options) {
if (options.with_suspended) params.set("with_suspended", "true"); if (options.with_suspended) {
params.set("with_suspended", "true");
}
} }
return this.get<Relationship[]>( return this.get<Relationship[]>(
@ -1457,10 +1600,18 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.min_id) params.set("min_id", options.min_id); params.set("max_id", options.max_id);
if (options.since_id) params.set("since_id", options.since_id); }
if (options.limit) params.set("limit", options.limit.toString()); if (options.min_id) {
params.set("min_id", options.min_id);
}
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<ScheduledStatus[]>( return this.get<ScheduledStatus[]>(
@ -1501,9 +1652,15 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.limit) params.set("limit", options.limit.toString()); if (options.limit) {
if (options.max_id) params.set("max_id", options.max_id); params.set("limit", options.limit.toString());
if (options.since_id) params.set("since_id", options.since_id); }
if (options.max_id) {
params.set("max_id", options.max_id);
}
if (options.since_id) {
params.set("since_id", options.since_id);
}
} }
return this.get<Context>( return this.get<Context>(
@ -1533,9 +1690,15 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.since_id) params.set("since_id", options.since_id); params.set("max_id", options.max_id);
if (options.limit) params.set("limit", options.limit.toString()); }
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Account[]>( return this.get<Account[]>(
@ -1565,9 +1728,15 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.since_id) params.set("since_id", options.since_id); params.set("max_id", options.max_id);
if (options.limit) params.set("limit", options.limit.toString()); }
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Account[]>( return this.get<Account[]>(
@ -1611,7 +1780,9 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.limit) params.set("limit", options.limit.toString()); if (options.limit) {
params.set("limit", options.limit.toString());
}
} }
return this.get<Account[]>(`/api/v1/suggestions?${params}`); return this.get<Account[]>(`/api/v1/suggestions?${params}`);
@ -1654,12 +1825,24 @@ export class LysandClient extends BaseClient {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options) { if (options) {
if (options.max_id) params.set("max_id", options.max_id); if (options.max_id) {
if (options.min_id) params.set("min_id", options.min_id); params.set("max_id", options.max_id);
if (options.since_id) params.set("since_id", options.since_id); }
if (options.limit) params.set("limit", options.limit.toString()); if (options.min_id) {
if (options.local) params.set("local", "true"); params.set("min_id", options.min_id);
if (options.only_media) params.set("only_media", "true"); }
if (options.since_id) {
params.set("since_id", options.since_id);
}
if (options.limit) {
params.set("limit", options.limit.toString());
}
if (options.local) {
params.set("local", "true");
}
if (options.only_media) {
params.set("only_media", "true");
}
} }
return this.get<Status[]>( return this.get<Status[]>(
@ -1848,18 +2031,18 @@ export class LysandClient extends BaseClient {
* @param token will be get #fetchAccessToken * @param token will be get #fetchAccessToken
*/ */
public refreshToken( public refreshToken(
client_id: string, clientId: string,
client_secret: string, clientSecret: string,
refresh_token: string, refreshToken: string,
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<Token>> { ): Promise<Output<Token>> {
return this.post<Token>( return this.post<Token>(
"/oauth/token", "/oauth/token",
{ {
client_id, clientId,
client_secret, clientSecret,
grant_type: "refresh_token", grant_type: "refresh_token",
refresh_token, refreshToken,
}, },
extra, extra,
); );
@ -1900,7 +2083,7 @@ export class LysandClient extends BaseClient {
* @param options Form Data * @param options Form Data
*/ */
public registerApp( public registerApp(
client_name: string, clientName: string,
options: { options: {
redirect_uris: string; redirect_uris: string;
scopes?: string; scopes?: string;
@ -1910,7 +2093,7 @@ export class LysandClient extends BaseClient {
): Promise<Output<ApplicationData>> { ): Promise<Output<ApplicationData>> {
return this.post<ApplicationData>( return this.post<ApplicationData>(
"/api/v1/apps", "/api/v1/apps",
{ client_name, ...options }, { clientName, ...options },
extra, extra,
); );
} }
@ -1976,7 +2159,7 @@ export class LysandClient extends BaseClient {
* @return Report. * @return Report.
*/ */
public report( public report(
account_id: string, accountId: string,
options: { options: {
status_ids?: string[]; status_ids?: string[];
rule_ids?: string[]; rule_ids?: string[];
@ -1988,7 +2171,7 @@ export class LysandClient extends BaseClient {
): Promise<Output<Report>> { ): Promise<Output<Report>> {
return this.post<Report>( return this.post<Report>(
"/api/v1/reports", "/api/v1/reports",
{ account_id, ...options }, { accountId, ...options },
extra, extra,
); );
} }
@ -2002,14 +2185,14 @@ export class LysandClient extends BaseClient {
* @param token will be get #fetchAccessToken * @param token will be get #fetchAccessToken
*/ */
public revokeToken( public revokeToken(
client_id: string, clientId: string,
client_secret: string, clientSecret: string,
token: string, token: string,
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<void>> { ): Promise<Output<void>> {
return this.post<void>( return this.post<void>(
"/oauth/revoke", "/oauth/revoke",
{ client_id, client_secret, token }, { clientId, clientSecret, token },
extra, extra,
); );
} }
@ -2044,12 +2227,12 @@ export class LysandClient extends BaseClient {
*/ */
public scheduleStatus( public scheduleStatus(
id: string, id: string,
scheduled_at?: Date, scheduledAt?: Date,
extra?: RequestInit, extra?: RequestInit,
): Promise<Output<ScheduledStatus>> { ): Promise<Output<ScheduledStatus>> {
return this.put<ScheduledStatus>( return this.put<ScheduledStatus>(
`/api/v1/scheduled_statuses/${id}`, `/api/v1/scheduled_statuses/${id}`,
{ scheduled_at: scheduled_at?.toISOString() }, { scheduled_at: scheduledAt?.toISOString() },
extra, extra,
); );
} }
@ -2088,17 +2271,33 @@ export class LysandClient extends BaseClient {
params.set("q", q); params.set("q", q);
if (options) { if (options) {
if (options.account_id) if (options.account_id) {
params.set("account_id", options.account_id); params.set("account_id", options.account_id);
if (options.exclude_unreviewed) }
if (options.exclude_unreviewed) {
params.set("exclude_unreviewed", "true"); params.set("exclude_unreviewed", "true");
if (options.following) params.set("following", "true"); }
if (options.limit) params.set("limit", options.limit.toString()); if (options.following) {
if (options.max_id) params.set("max_id", options.max_id); params.set("following", "true");
if (options.min_id) params.set("min_id", options.min_id); }
if (options.offset) params.set("offset", options.offset.toString()); if (options.limit) {
if (options.resolve) params.set("resolve", "true"); params.set("limit", options.limit.toString());
if (options.type) params.set("type", options.type); }
if (options.max_id) {
params.set("max_id", options.max_id);
}
if (options.min_id) {
params.set("min_id", options.min_id);
}
if (options.offset) {
params.set("offset", options.offset.toString());
}
if (options.resolve) {
params.set("resolve", "true");
}
if (options.type) {
params.set("type", options.type);
}
} }
return this.get<Results>(`/api/v2/search?${params}`, extra); return this.get<Results>(`/api/v2/search?${params}`, extra);
@ -2131,11 +2330,21 @@ export class LysandClient extends BaseClient {
params.set("q", q); params.set("q", q);
if (options) { if (options) {
if (options.following) params.set("following", "true"); if (options.following) {
if (options.limit) params.set("limit", options.limit.toString()); params.set("following", "true");
if (options.max_id) params.set("max_id", options.max_id); }
if (options.resolve) params.set("resolve", "true"); if (options.limit) {
if (options.since_id) params.set("since_id", options.since_id); params.set("limit", options.limit.toString());
}
if (options.max_id) {
params.set("max_id", options.max_id);
}
if (options.resolve) {
params.set("resolve", "true");
}
if (options.since_id) {
params.set("since_id", options.since_id);
}
} }
return this.get<Account[]>(`/api/v1/accounts/search?${params}`, extra); return this.get<Account[]>(`/api/v1/accounts/search?${params}`, extra);

View file

@ -25,9 +25,9 @@ export type Account = {
avatar_static: string; avatar_static: string;
header: string; header: string;
header_static: string; header_static: string;
emojis: Array<Emoji>; emojis: Emoji[];
moved: Account | null; moved: Account | null;
fields: Array<Field>; fields: Field[];
bot: boolean | null; bot: boolean | null;
source?: Source; source?: Source;
role?: Role; role?: Role;

View file

@ -11,11 +11,11 @@ export type Announcement = {
published_at: string; published_at: string;
updated_at: string | null; updated_at: string | null;
read: boolean | null; read: boolean | null;
mentions: Array<AnnouncementAccount>; mentions: AnnouncementAccount[];
statuses: Array<AnnouncementStatus>; statuses: AnnouncementStatus[];
tags: Array<StatusTag>; tags: StatusTag[];
emojis: Array<Emoji>; emojis: Emoji[];
reactions: Array<AnnouncementReaction>; reactions: AnnouncementReaction[];
}; };
export type AnnouncementAccount = { export type AnnouncementAccount = {

View file

@ -1,6 +1,6 @@
import type { Status } from "./status"; import type { Status } from "./status";
export type Context = { export type Context = {
ancestors: Array<Status>; ancestors: Status[];
descendants: Array<Status>; descendants: Status[];
}; };

View file

@ -3,7 +3,7 @@ import type { Status } from "./status";
export type Conversation = { export type Conversation = {
id: string; id: string;
accounts: Array<Account>; accounts: Account[];
last_status: Status | null; last_status: Status | null;
unread: boolean; unread: boolean;
}; };

View file

@ -1,7 +1,7 @@
export type Filter = { export type Filter = {
id: string; id: string;
phrase: string; phrase: string;
context: Array<FilterContext>; context: FilterContext[];
expires_at: string | null; expires_at: string | null;
irreversible: boolean; irreversible: boolean;
whole_word: boolean; whole_word: boolean;

View file

@ -20,6 +20,6 @@ export type FollowRequest = {
followers_count: number; followers_count: number;
following_count: number; following_count: number;
statuses_count: number; statuses_count: number;
emojis: Array<Emoji>; emojis: Emoji[];
fields: Array<Field>; fields: Field[];
}; };

View file

@ -10,47 +10,48 @@ export type LysandRole = {
// Last updated: 2024-06-07 // Last updated: 2024-06-07
export enum LysandRolePermissions { export enum LysandRolePermissions {
MANAGE_NOTES = "notes", ManageNotes = "notes",
MANAGE_OWN_NOTES = "owner:note", ManageOwnNotes = "owner:note",
VIEW_NOTES = "read:note", ViewNotes = "read:note",
VIEW_NOTE_LIKES = "read:note_likes", ViewNoteLikes = "read:note_likes",
VIEW_NOTE_BOOSTS = "read:note_boosts", ViewNoteBoosts = "read:note_boosts",
MANAGE_ACCOUNTS = "accounts", ManageAccounts = "accounts",
MANAGE_OWN_ACCOUNT = "owner:account", ManageOwnAccount = "owner:account",
VIEW_ACCOUNT_FOLLOWS = "read:account_follows", ViewAccountFollows = "read:account_follows",
MANAGE_LIKES = "likes", ManageLikes = "likes",
MANAGE_OWN_LIKES = "owner:like", ManageOwnLikes = "owner:like",
MANAGE_BOOSTS = "boosts", ManageBoosts = "boosts",
MANAGE_OWN_BOOSTS = "owner:boost", ManageOwnBoosts = "owner:boost",
VIEW_ACCOUNTS = "read:account", ViewAccounts = "read:account",
MANAGE_EMOJIS = "emojis", ManageEmojis = "emojis",
VIEW_EMOJIS = "read:emoji", ViewEmojis = "read:emoji",
MANAGE_OWN_EMOJIS = "owner:emoji", ManageOwnEmojis = "owner:emoji",
MANAGE_MEDIA = "media", ManageMedia = "media",
MANAGE_OWN_MEDIA = "owner:media", ManageOwnMedia = "owner:media",
MANAGE_BLOCKS = "blocks", ManageBlocks = "blocks",
MANAGE_OWN_BLOCKS = "owner:block", ManageOwnBlocks = "owner:block",
MANAGE_FILTERS = "filters", ManageFilters = "filters",
MANAGE_OWN_FILTERS = "owner:filter", ManageOwnFilters = "owner:filter",
MANAGE_MUTES = "mutes", ManageMutes = "mutes",
MANAGE_OWN_MUTES = "owner:mute", ManageOwnMutes = "owner:mute",
MANAGE_REPORTS = "reports", ManageReports = "reports",
MANAGE_OWN_REPORTS = "owner:report", ManageOwnReports = "owner:report",
MANAGE_SETTINGS = "settings", ManageSettings = "settings",
MANAGE_OWN_SETTINGS = "owner:settings", ManageOwnSettings = "owner:settings",
MANAGE_ROLES = "roles", ManageRoles = "roles",
MANAGE_NOTIFICATIONS = "notifications", ManageNotifications = "notifications",
MANAGE_OWN_NOTIFICATIONS = "owner:notification", ManageOwnNotifications = "owner:notification",
MANAGE_FOLLOWS = "follows", ManageFollows = "follows",
MANAGE_OWN_FOLLOWS = "owner:follow", ManageOwnFollows = "owner:follow",
MANAGE_OWN_APPS = "owner:app", ManageOwnApps = "owner:app",
SEARCH = "search", Search = "search",
VIEW_PUBLIC_TIMELINES = "public_timelines", ViewPublicTimelines = "public_timelines",
VIEW_PRIVATE_TIMELINES = "private_timelines", ViewPrimateTimelines = "private_timelines",
IGNORE_RATE_LIMITS = "ignore_rate_limits", IgnoreRateLimits = "ignore_rate_limits",
IMPERSONATE = "impersonate", Impersonate = "impersonate",
MANAGE_INSTANCE = "instance", ManageInstance = "instance",
MANAGE_INSTANCE_FEDERATION = "instance:federation", ManageInstanceFederation = "instance:federation",
MANAGE_INSTANCE_SETTINGS = "instance:settings", ManageInstanceSettings = "instance:settings",
OAUTH = "oauth", /** Users who do not have this permission will not be able to login! */
OAuth = "oauth",
} }

View file

@ -4,7 +4,7 @@ export type Poll = {
expired: boolean; expired: boolean;
multiple: boolean; multiple: boolean;
votes_count: number; votes_count: number;
options: Array<PollOption>; options: PollOption[];
voted: boolean; voted: boolean;
}; };

View file

@ -6,6 +6,6 @@ export type Reaction = {
name: string; name: string;
url?: string; url?: string;
static_url?: string; static_url?: string;
accounts?: Array<Account>; accounts?: Account[];
account_ids?: Array<string>; account_ids?: string[];
}; };

View file

@ -4,8 +4,8 @@ export type Report = {
id: string; id: string;
action_taken: boolean; action_taken: boolean;
action_taken_at: string | null; action_taken_at: string | null;
status_ids: Array<string> | null; status_ids: string[] | null;
rule_ids: Array<string> | null; rule_ids: string[] | null;
// These parameters don't exist in Pleroma // These parameters don't exist in Pleroma
category: Category | null; category: Category | null;
comment: string | null; comment: string | null;

View file

@ -3,7 +3,7 @@ import type { Status } from "./status";
import type { Tag } from "./tag"; import type { Tag } from "./tag";
export type Results = { export type Results = {
accounts: Array<Account>; accounts: Account[];
statuses: Array<Status>; statuses: Status[];
hashtags: Array<Tag>; hashtags: Tag[];
}; };

View file

@ -5,5 +5,5 @@ export type ScheduledStatus = {
id: string; id: string;
scheduled_at: string; scheduled_at: string;
params: StatusParams; params: StatusParams;
media_attachments: Array<Attachment> | null; media_attachments: Attachment[] | null;
}; };

View file

@ -5,5 +5,5 @@ export type Source = {
sensitive: boolean | null; sensitive: boolean | null;
language: string | null; language: string | null;
note: string; note: string;
fields: Array<Field>; fields: Field[];
}; };

View file

@ -29,15 +29,15 @@ export type Status = {
sensitive: boolean; sensitive: boolean;
spoiler_text: string; spoiler_text: string;
visibility: StatusVisibility; visibility: StatusVisibility;
media_attachments: Array<Attachment>; media_attachments: Attachment[];
mentions: Array<Mention>; mentions: Mention[];
tags: Array<StatusTag>; tags: StatusTag[];
card: Card | null; card: Card | null;
poll: Poll | null; poll: Poll | null;
application: Application | null; application: Application | null;
language: string | null; language: string | null;
pinned: boolean | null; pinned: boolean | null;
emoji_reactions: Array<Reaction>; emoji_reactions: Reaction[];
quote: Status | null; quote: Status | null;
bookmarked: boolean; bookmarked: boolean;
}; };

View file

@ -3,7 +3,7 @@ import type { StatusVisibility } from "./status";
export type StatusParams = { export type StatusParams = {
text: string; text: string;
in_reply_to_id: string | null; in_reply_to_id: string | null;
media_ids: Array<string> | null; media_ids: string[] | null;
sensitive: boolean | null; sensitive: boolean | null;
spoiler_text: string | null; spoiler_text: string | null;
visibility: StatusVisibility | null; visibility: StatusVisibility | null;

View file

@ -3,6 +3,6 @@ import type { History } from "./history";
export type Tag = { export type Tag = {
name: string; name: string;
url: string; url: string;
history: Array<History>; history: History[];
following?: boolean; following?: boolean;
}; };

View file

@ -10,9 +10,9 @@ type HttpVerb =
| "OPTIONS" | "OPTIONS"
| "HEAD"; | "HEAD";
const checkEvironmentSupport = async () => { const checkEvironmentSupport = () => {
// Check if WebCrypto is supported // Check if WebCrypto is supported
if (!globalThis.crypto || !globalThis.crypto.subtle) { if (!globalThis.crypto?.subtle) {
throw new Error("WebCrypto is not supported in this environment"); throw new Error("WebCrypto is not supported in this environment");
} }
@ -27,9 +27,9 @@ const checkEvironmentSupport = async () => {
export class SignatureValidator { export class SignatureValidator {
/** /**
* Creates a new instance of SignatureValidator. * Creates a new instance of SignatureValidator.
* @param public_key The public key used for signature verification. * @param publicKey The public key used for signature verification.
*/ */
constructor(private public_key: CryptoKey) { constructor(private publicKey: CryptoKey) {
checkEvironmentSupport(); checkEvironmentSupport();
} }
@ -114,9 +114,9 @@ export class SignatureValidator {
].filter(Boolean); ].filter(Boolean);
// Check if all headers are present // Check if all headers are present
if (!signature || !date || !method || !url || !body) { if (!(signature && date && method && url && body)) {
// Say which headers are missing // Say which headers are missing
throw TypeError( throw new TypeError(
`Headers are missing in request: ${missingHeaders.join( `Headers are missing in request: ${missingHeaders.join(
", ", ", ",
)}`, )}`,
@ -124,7 +124,7 @@ export class SignatureValidator {
} }
if (signature.split("signature=").length < 2) { if (signature.split("signature=").length < 2) {
throw TypeError( throw new TypeError(
"Invalid Signature header (wrong format or missing signature)", "Invalid Signature header (wrong format or missing signature)",
); );
} }
@ -134,7 +134,7 @@ export class SignatureValidator {
.replace(/"/g, ""); .replace(/"/g, "");
if (!extractedSignature) { if (!extractedSignature) {
throw TypeError( throw new TypeError(
"Invalid Signature header (wrong format or missing signature)", "Invalid Signature header (wrong format or missing signature)",
); );
} }
@ -148,8 +148,8 @@ export class SignatureValidator {
); );
} }
if (!date || !method || !url || !body) { if (!(date && method && url && body)) {
throw TypeError( throw new TypeError(
"Missing or empty required parameters: date, method, url or body", "Missing or empty required parameters: date, method, url or body",
); );
} }
@ -172,7 +172,7 @@ export class SignatureValidator {
// Check if signed string is valid // Check if signed string is valid
const isValid = await crypto.subtle.verify( const isValid = await crypto.subtle.verify(
"Ed25519", "Ed25519",
this.public_key, this.publicKey,
Buffer.from(signature, "base64"), Buffer.from(signature, "base64"),
new TextEncoder().encode(expectedSignedString), new TextEncoder().encode(expectedSignedString),
); );
@ -302,8 +302,8 @@ export class SignatureConstructor {
return { request, signedString }; return { request, signedString };
} }
if (!url || !body || !headers) { if (!(url && body && headers)) {
throw TypeError( throw new TypeError(
"Missing or empty required parameters: url, body or headers", "Missing or empty required parameters: url, body or headers",
); );
} }

View file

@ -69,27 +69,35 @@ export class RequestParserHandler {
public async parseBody<ReturnType = void>( public async parseBody<ReturnType = void>(
callbacks: Partial<ParserCallbacks<ReturnType>>, callbacks: Partial<ParserCallbacks<ReturnType>>,
): Promise<ReturnType> { ): Promise<ReturnType> {
if (!this.body.type) throw new Error("Missing type field in body"); if (!this.body.type) {
throw new Error("Missing type field in body");
}
switch (this.body.type) { switch (this.body.type) {
case "Note": { case "Note": {
const note = await this.validator.Note(this.body); const note = await this.validator.Note(this.body);
if (callbacks.note) return await callbacks.note(note); if (callbacks.note) {
return await callbacks.note(note);
}
break; break;
} }
case "Patch": { case "Patch": {
const patch = await this.validator.Patch(this.body); const patch = await this.validator.Patch(this.body);
if (callbacks.patch) return await callbacks.patch(patch); if (callbacks.patch) {
return await callbacks.patch(patch);
}
break; break;
} }
case "Follow": { case "Follow": {
const follow = await this.validator.Follow(this.body); const follow = await this.validator.Follow(this.body);
if (callbacks.follow) return await callbacks.follow(follow); if (callbacks.follow) {
return await callbacks.follow(follow);
}
break; break;
} }
@ -98,8 +106,9 @@ export class RequestParserHandler {
this.body, this.body,
); );
if (callbacks.followAccept) if (callbacks.followAccept) {
return await callbacks.followAccept(followAccept); return await callbacks.followAccept(followAccept);
}
break; break;
} }
@ -108,36 +117,45 @@ export class RequestParserHandler {
this.body, this.body,
); );
if (callbacks.followReject) if (callbacks.followReject) {
return await callbacks.followReject(followReject); return await callbacks.followReject(followReject);
}
break; break;
} }
case "User": { case "User": {
const user = await this.validator.User(this.body); const user = await this.validator.User(this.body);
if (callbacks.user) return await callbacks.user(user); if (callbacks.user) {
return await callbacks.user(user);
}
break; break;
} }
case "Like": { case "Like": {
const like = await this.validator.Like(this.body); const like = await this.validator.Like(this.body);
if (callbacks.like) return await callbacks.like(like); if (callbacks.like) {
return await callbacks.like(like);
}
break; break;
} }
case "Dislike": { case "Dislike": {
const dislike = await this.validator.Dislike(this.body); const dislike = await this.validator.Dislike(this.body);
if (callbacks.dislike) return await callbacks.dislike(dislike); if (callbacks.dislike) {
return await callbacks.dislike(dislike);
}
break; break;
} }
case "Undo": { case "Undo": {
const undo = await this.validator.Undo(this.body); const undo = await this.validator.Undo(this.body);
if (callbacks.undo) return await callbacks.undo(undo); if (callbacks.undo) {
return await callbacks.undo(undo);
}
break; break;
} }
@ -146,16 +164,18 @@ export class RequestParserHandler {
this.body, this.body,
); );
if (callbacks.serverMetadata) if (callbacks.serverMetadata) {
return await callbacks.serverMetadata(serverMetadata); return await callbacks.serverMetadata(serverMetadata);
}
break; break;
} }
case "Extension": { case "Extension": {
const extension = await this.validator.Extension(this.body); const extension = await this.validator.Extension(this.body);
if (callbacks.extension) if (callbacks.extension) {
return await callbacks.extension(extension); return await callbacks.extension(extension);
}
break; break;
} }

View file

@ -3,6 +3,7 @@
"name": "@lysand-org/federation", "name": "@lysand-org/federation",
"version": "0.0.0", "version": "0.0.0",
"exports": { "exports": {
".": "./index.ts" ".": "./index.ts",
"./types": "./schemas.ts"
} }
} }

View file

@ -41,6 +41,10 @@
".": { ".": {
"import": "./index.ts", "import": "./index.ts",
"default": "./index.ts" "default": "./index.ts"
},
"./types": {
"import": "./schemas.ts",
"default": "./schemas.ts"
} }
}, },
"funding": { "funding": {

51
federation/schemas.ts Normal file
View file

@ -0,0 +1,51 @@
import type { z } from "zod";
import type {
ActionSchema,
ActorPublicKeyDataSchema,
ContentFormatSchema,
CustomEmojiExtensionSchema,
DislikeSchema,
EntitySchema,
ExtensionPropertySchema,
ExtensionSchema,
FollowAcceptSchema,
FollowRejectSchema,
FollowSchema,
LikeSchema,
NoteSchema,
PatchSchema,
PublicationSchema,
ReportSchema,
ServerMetadataSchema,
UndoSchema,
UserSchema,
VanityExtensionSchema,
VisibilitySchema,
} from "./schemas/base";
// biome-ignore lint/suspicious/noExplicitAny: Used only as a base type
type AnyZod = z.ZodType<any, any, any>;
type InferType<T extends AnyZod> = z.infer<T>;
export type Note = InferType<typeof NoteSchema>;
export type Patch = InferType<typeof PatchSchema>;
export type ActorPublicKeyData = InferType<typeof ActorPublicKeyDataSchema>;
export type ExtensionProperty = InferType<typeof ExtensionPropertySchema>;
export type VanityExtension = InferType<typeof VanityExtensionSchema>;
export type User = InferType<typeof UserSchema>;
export type Action = InferType<typeof ActionSchema>;
export type Like = InferType<typeof LikeSchema>;
export type Undo = InferType<typeof UndoSchema>;
export type Dislike = InferType<typeof DislikeSchema>;
export type Follow = InferType<typeof FollowSchema>;
export type FollowAccept = InferType<typeof FollowAcceptSchema>;
export type FollowReject = InferType<typeof FollowRejectSchema>;
export type Extension = InferType<typeof ExtensionSchema>;
export type Report = InferType<typeof ReportSchema>;
export type ServerMetadata = InferType<typeof ServerMetadataSchema>;
export type ContentFormat = InferType<typeof ContentFormatSchema>;
export type CustomEmojiExtension = InferType<typeof CustomEmojiExtensionSchema>;
export type Visibility = InferType<typeof VisibilitySchema>;
export type Publication = InferType<typeof PublicationSchema>;
export type Entity = InferType<typeof EntitySchema>;

View file

@ -1,7 +1,7 @@
import { z } from "zod"; import { z } from "zod";
import { ContentFormatSchema } from "./content_format"; import { ContentFormatSchema } from "./content_format";
import { ExtensionPropertySchema } from "./extensions"; import { ExtensionPropertySchema } from "./extensions";
import { CustomEmojiExtension } from "./extensions/custom_emojis"; import { CustomEmojiExtensionSchema } from "./extensions/custom_emojis";
import { VanityExtensionSchema } from "./extensions/vanity"; import { VanityExtensionSchema } from "./extensions/vanity";
import { extensionTypeRegex } from "./regex"; import { extensionTypeRegex } from "./regex";
@ -187,6 +187,6 @@ export {
ReportSchema, ReportSchema,
ServerMetadataSchema, ServerMetadataSchema,
ContentFormatSchema, ContentFormatSchema,
CustomEmojiExtension, CustomEmojiExtensionSchema,
ExtensionPropertySchema, ExtensionPropertySchema,
}; };

View file

@ -1,6 +1,6 @@
import { z } from "zod"; import { z } from "zod";
import { CustomEmojiExtension } from "./extensions/custom_emojis"; import { CustomEmojiExtensionSchema } from "./extensions/custom_emojis";
export const ExtensionPropertySchema = z.object({ export const ExtensionPropertySchema = z.object({
"org.lysand:custom_emojis": CustomEmojiExtension.optional(), "org.lysand:custom_emojis": CustomEmojiExtensionSchema.optional(),
}); });

View file

@ -33,7 +33,7 @@ import { emojiRegex } from "../regex";
* // ... * // ...
* } * }
*/ */
export const CustomEmojiExtension = z.object({ export const CustomEmojiExtensionSchema = z.object({
emojis: z.array( emojis: z.array(
z.object({ z.object({
name: z name: z

View file

@ -2,7 +2,7 @@ import { describe, expect, it } from "bun:test";
import { EntityValidator } from "../index"; import { EntityValidator } from "../index";
describe("Package testing", () => { describe("Package testing", () => {
it("should not validate a bad Note", async () => { it("should not validate a bad Note", () => {
const badObject = { const badObject = {
IamBad: "Note", IamBad: "Note",
}; };

View file

@ -4,7 +4,7 @@ import {
ActionSchema, ActionSchema,
ActorPublicKeyDataSchema, ActorPublicKeyDataSchema,
ContentFormatSchema, ContentFormatSchema,
CustomEmojiExtension, CustomEmojiExtensionSchema,
DislikeSchema, DislikeSchema,
EntitySchema, EntitySchema,
ExtensionPropertySchema, ExtensionPropertySchema,
@ -54,10 +54,11 @@ type InferType<T extends AnyZod> = z.infer<T>;
* } * }
* *
* // Types are also included for TypeScript users that don't use the extracted ones * // Types are also included for TypeScript users that don't use the extracted ones
* const noteObject: typeof EntityValidator.$Note = { * import type { Note } from "@lysand-org/federation/types";
* type: "Note", *
* // ... * const note: Note = {
* } * ...
* };
*/ */
export class EntityValidator { export class EntityValidator {
private async validate<T extends AnyZod>( private async validate<T extends AnyZod>(
@ -71,34 +72,6 @@ export class EntityValidator {
} }
} }
declare static $Note: InferType<typeof NoteSchema>;
declare static $Patch: InferType<typeof PatchSchema>;
declare static $ActorPublicKeyData: InferType<
typeof ActorPublicKeyDataSchema
>;
declare static $ExtensionProperty: InferType<
typeof ExtensionPropertySchema
>;
declare static $VanityExtension: InferType<typeof VanityExtensionSchema>;
declare static $User: InferType<typeof UserSchema>;
declare static $Action: InferType<typeof ActionSchema>;
declare static $Like: InferType<typeof LikeSchema>;
declare static $Undo: InferType<typeof UndoSchema>;
declare static $Dislike: InferType<typeof DislikeSchema>;
declare static $Follow: InferType<typeof FollowSchema>;
declare static $FollowAccept: InferType<typeof FollowAcceptSchema>;
declare static $FollowReject: InferType<typeof FollowRejectSchema>;
declare static $Extension: InferType<typeof ExtensionSchema>;
declare static $Report: InferType<typeof ReportSchema>;
declare static $ServerMetadata: InferType<typeof ServerMetadataSchema>;
declare static $ContentFormat: InferType<typeof ContentFormatSchema>;
declare static $CustomEmojiExtension: InferType<
typeof CustomEmojiExtension
>;
declare static $Visibility: InferType<typeof VisibilitySchema>;
declare static $Publication: InferType<typeof PublicationSchema>;
declare static $Entity: InferType<typeof EntitySchema>;
/** /**
* Validates a Note entity. * Validates a Note entity.
* @param data - The data to validate * @param data - The data to validate
@ -264,8 +237,8 @@ export class EntityValidator {
*/ */
public CustomEmojiExtension( public CustomEmojiExtension(
data: unknown, data: unknown,
): Promise<InferType<typeof CustomEmojiExtension>> { ): Promise<InferType<typeof CustomEmojiExtensionSchema>> {
return this.validate(CustomEmojiExtension, data); return this.validate(CustomEmojiExtensionSchema, data);
} }
/** /**