mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 16:38:19 +01:00
docs(federation): 📝 Update SDK documentation
This commit is contained in:
parent
f79b0bc999
commit
45e5460975
|
|
@ -5,7 +5,6 @@ import { Account as AccountSchema, zBoolean } from "@versia/client/schemas";
|
||||||
import { RolePermission } from "@versia/client/schemas";
|
import { RolePermission } from "@versia/client/schemas";
|
||||||
import { Emoji, Media, User } from "@versia/kit/db";
|
import { Emoji, Media, User } from "@versia/kit/db";
|
||||||
import { Users } from "@versia/kit/tables";
|
import { Users } from "@versia/kit/tables";
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import { and, eq, isNull } from "drizzle-orm";
|
import { and, eq, isNull } from "drizzle-orm";
|
||||||
import { describeRoute } from "hono-openapi";
|
import { describeRoute } from "hono-openapi";
|
||||||
import { resolver, validator } from "hono-openapi/zod";
|
import { resolver, validator } from "hono-openapi/zod";
|
||||||
|
|
@ -14,6 +13,7 @@ import { ApiError } from "~/classes/errors/api-error";
|
||||||
import { contentToHtml } from "~/classes/functions/status";
|
import { contentToHtml } from "~/classes/functions/status";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
import { rateLimit } from "~/middlewares/rate-limit";
|
import { rateLimit } from "~/middlewares/rate-limit";
|
||||||
|
import * as VersiaEntities from "~/packages/sdk/entities";
|
||||||
|
|
||||||
export default apiRoute((app) =>
|
export default apiRoute((app) =>
|
||||||
app.patch(
|
app.patch(
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,13 @@ import {
|
||||||
} from "@versia/client/schemas";
|
} from "@versia/client/schemas";
|
||||||
import { RolePermission } from "@versia/client/schemas";
|
import { RolePermission } from "@versia/client/schemas";
|
||||||
import { Emoji, Media } from "@versia/kit/db";
|
import { Emoji, Media } from "@versia/kit/db";
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import { describeRoute } from "hono-openapi";
|
import { describeRoute } from "hono-openapi";
|
||||||
import { resolver, validator } from "hono-openapi/zod";
|
import { resolver, validator } from "hono-openapi/zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ApiError } from "~/classes/errors/api-error";
|
import { ApiError } from "~/classes/errors/api-error";
|
||||||
import { contentToHtml, parseTextMentions } from "~/classes/functions/status";
|
import { contentToHtml, parseTextMentions } from "~/classes/functions/status";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import * as VersiaEntities from "~/packages/sdk/entities";
|
||||||
|
|
||||||
const schema = z
|
const schema = z
|
||||||
.object({
|
.object({
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import {
|
||||||
} from "@versia/client/schemas";
|
} from "@versia/client/schemas";
|
||||||
import { RolePermission } from "@versia/client/schemas";
|
import { RolePermission } from "@versia/client/schemas";
|
||||||
import { Emoji, Media, Note } from "@versia/kit/db";
|
import { Emoji, Media, Note } from "@versia/kit/db";
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import { randomUUIDv7 } from "bun";
|
import { randomUUIDv7 } from "bun";
|
||||||
import { describeRoute } from "hono-openapi";
|
import { describeRoute } from "hono-openapi";
|
||||||
import { resolver, validator } from "hono-openapi/zod";
|
import { resolver, validator } from "hono-openapi/zod";
|
||||||
|
|
@ -17,6 +16,7 @@ import { z } from "zod";
|
||||||
import { ApiError } from "~/classes/errors/api-error";
|
import { ApiError } from "~/classes/errors/api-error";
|
||||||
import { contentToHtml, parseTextMentions } from "~/classes/functions/status";
|
import { contentToHtml, parseTextMentions } from "~/classes/functions/status";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import * as VersiaEntities from "~/packages/sdk/entities";
|
||||||
|
|
||||||
const schema = z
|
const schema = z
|
||||||
.object({
|
.object({
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ import { apiRoute, handleZodError } from "@/api";
|
||||||
import { Status as StatusSchema } from "@versia/client/schemas";
|
import { Status as StatusSchema } from "@versia/client/schemas";
|
||||||
import { Like, User } from "@versia/kit/db";
|
import { Like, User } from "@versia/kit/db";
|
||||||
import { Likes } from "@versia/kit/tables";
|
import { Likes } from "@versia/kit/tables";
|
||||||
import { LikeSchema } from "@versia/sdk/schemas";
|
|
||||||
import { and, eq, sql } from "drizzle-orm";
|
import { and, eq, sql } from "drizzle-orm";
|
||||||
import { describeRoute } from "hono-openapi";
|
import { describeRoute } from "hono-openapi";
|
||||||
import { resolver, validator } from "hono-openapi/zod";
|
import { resolver, validator } from "hono-openapi/zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ApiError } from "~/classes/errors/api-error";
|
import { ApiError } from "~/classes/errors/api-error";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import { LikeSchema } from "~/packages/sdk/schemas";
|
||||||
|
|
||||||
export default apiRoute((app) =>
|
export default apiRoute((app) =>
|
||||||
app.get(
|
app.get(
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ import { apiRoute, handleZodError } from "@/api";
|
||||||
import { Status as StatusSchema } from "@versia/client/schemas";
|
import { Status as StatusSchema } from "@versia/client/schemas";
|
||||||
import { Note } from "@versia/kit/db";
|
import { Note } from "@versia/kit/db";
|
||||||
import { Notes } from "@versia/kit/tables";
|
import { Notes } from "@versia/kit/tables";
|
||||||
import { NoteSchema } from "@versia/sdk/schemas";
|
|
||||||
import { and, eq, inArray } from "drizzle-orm";
|
import { and, eq, inArray } from "drizzle-orm";
|
||||||
import { describeRoute } from "hono-openapi";
|
import { describeRoute } from "hono-openapi";
|
||||||
import { resolver, validator } from "hono-openapi/zod";
|
import { resolver, validator } from "hono-openapi/zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ApiError } from "~/classes/errors/api-error";
|
import { ApiError } from "~/classes/errors/api-error";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import { NoteSchema } from "~/packages/sdk/schemas";
|
||||||
|
|
||||||
export default apiRoute((app) =>
|
export default apiRoute((app) =>
|
||||||
app.get(
|
app.get(
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@ import { apiRoute, handleZodError } from "@/api";
|
||||||
import { Status as StatusSchema } from "@versia/client/schemas";
|
import { Status as StatusSchema } from "@versia/client/schemas";
|
||||||
import { Note, db } from "@versia/kit/db";
|
import { Note, db } from "@versia/kit/db";
|
||||||
import { Notes } from "@versia/kit/tables";
|
import { Notes } from "@versia/kit/tables";
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import { URICollectionSchema } from "@versia/sdk/schemas";
|
|
||||||
import { and, eq, inArray } from "drizzle-orm";
|
import { and, eq, inArray } from "drizzle-orm";
|
||||||
import { describeRoute } from "hono-openapi";
|
import { describeRoute } from "hono-openapi";
|
||||||
import { resolver, validator } from "hono-openapi/zod";
|
import { resolver, validator } from "hono-openapi/zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ApiError } from "~/classes/errors/api-error";
|
import { ApiError } from "~/classes/errors/api-error";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import * as VersiaEntities from "~/packages/sdk/entities";
|
||||||
|
import { URICollectionSchema } from "~/packages/sdk/schemas";
|
||||||
|
|
||||||
export default apiRoute((app) =>
|
export default apiRoute((app) =>
|
||||||
app.get(
|
app.get(
|
||||||
|
|
@ -94,7 +94,9 @@ export default apiRoute((app) =>
|
||||||
last:
|
last:
|
||||||
replyCount > limit
|
replyCount > limit
|
||||||
? new URL(
|
? new URL(
|
||||||
`/notes/${note.id}/quotes?offset=${replyCount - limit}`,
|
`/notes/${note.id}/quotes?offset=${
|
||||||
|
replyCount - limit
|
||||||
|
}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
)
|
||||||
: new URL(
|
: new URL(
|
||||||
|
|
@ -104,14 +106,18 @@ export default apiRoute((app) =>
|
||||||
next:
|
next:
|
||||||
offset + limit < replyCount
|
offset + limit < replyCount
|
||||||
? new URL(
|
? new URL(
|
||||||
`/notes/${note.id}/quotes?offset=${offset + limit}`,
|
`/notes/${note.id}/quotes?offset=${
|
||||||
|
offset + limit
|
||||||
|
}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
previous:
|
previous:
|
||||||
offset - limit >= 0
|
offset - limit >= 0
|
||||||
? new URL(
|
? new URL(
|
||||||
`/notes/${note.id}/quotes?offset=${offset - limit}`,
|
`/notes/${note.id}/quotes?offset=${
|
||||||
|
offset - limit
|
||||||
|
}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@ import { apiRoute, handleZodError } from "@/api";
|
||||||
import { Status as StatusSchema } from "@versia/client/schemas";
|
import { Status as StatusSchema } from "@versia/client/schemas";
|
||||||
import { Note, db } from "@versia/kit/db";
|
import { Note, db } from "@versia/kit/db";
|
||||||
import { Notes } from "@versia/kit/tables";
|
import { Notes } from "@versia/kit/tables";
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import { URICollectionSchema } from "@versia/sdk/schemas";
|
|
||||||
import { and, eq, inArray } from "drizzle-orm";
|
import { and, eq, inArray } from "drizzle-orm";
|
||||||
import { describeRoute } from "hono-openapi";
|
import { describeRoute } from "hono-openapi";
|
||||||
import { resolver, validator } from "hono-openapi/zod";
|
import { resolver, validator } from "hono-openapi/zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ApiError } from "~/classes/errors/api-error";
|
import { ApiError } from "~/classes/errors/api-error";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import * as VersiaEntities from "~/packages/sdk/entities";
|
||||||
|
import { URICollectionSchema } from "~/packages/sdk/schemas";
|
||||||
|
|
||||||
export default apiRoute((app) =>
|
export default apiRoute((app) =>
|
||||||
app.get(
|
app.get(
|
||||||
|
|
@ -92,7 +92,9 @@ export default apiRoute((app) =>
|
||||||
last:
|
last:
|
||||||
replyCount > limit
|
replyCount > limit
|
||||||
? new URL(
|
? new URL(
|
||||||
`/notes/${note.id}/replies?offset=${replyCount - limit}`,
|
`/notes/${note.id}/replies?offset=${
|
||||||
|
replyCount - limit
|
||||||
|
}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
)
|
||||||
: new URL(
|
: new URL(
|
||||||
|
|
@ -102,14 +104,18 @@ export default apiRoute((app) =>
|
||||||
next:
|
next:
|
||||||
offset + limit < replyCount
|
offset + limit < replyCount
|
||||||
? new URL(
|
? new URL(
|
||||||
`/notes/${note.id}/replies?offset=${offset + limit}`,
|
`/notes/${note.id}/replies?offset=${
|
||||||
|
offset + limit
|
||||||
|
}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
previous:
|
previous:
|
||||||
offset - limit >= 0
|
offset - limit >= 0
|
||||||
? new URL(
|
? new URL(
|
||||||
`/notes/${note.id}/replies?offset=${offset - limit}`,
|
`/notes/${note.id}/replies?offset=${
|
||||||
|
offset - limit
|
||||||
|
}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { resolver, validator } from "hono-openapi/zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ApiError } from "~/classes/errors/api-error";
|
import { ApiError } from "~/classes/errors/api-error";
|
||||||
import { InboxJobType, inboxQueue } from "~/classes/queues/inbox";
|
import { InboxJobType, inboxQueue } from "~/classes/queues/inbox";
|
||||||
import type { JSONObject } from "~/packages/federation/types";
|
import type { JSONObject } from "~/packages/sdk/types";
|
||||||
|
|
||||||
export default apiRoute((app) =>
|
export default apiRoute((app) =>
|
||||||
app.post(
|
app.post(
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { apiRoute, handleZodError } from "@/api";
|
import { apiRoute, handleZodError } from "@/api";
|
||||||
import { User } from "@versia/kit/db";
|
import { User } from "@versia/kit/db";
|
||||||
import { UserSchema } from "@versia/sdk/schemas";
|
|
||||||
import { describeRoute } from "hono-openapi";
|
import { describeRoute } from "hono-openapi";
|
||||||
import { resolver, validator } from "hono-openapi/zod";
|
import { resolver, validator } from "hono-openapi/zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ApiError } from "~/classes/errors/api-error";
|
import { ApiError } from "~/classes/errors/api-error";
|
||||||
|
import { UserSchema } from "~/packages/sdk/schemas";
|
||||||
|
|
||||||
export default apiRoute((app) =>
|
export default apiRoute((app) =>
|
||||||
app.get(
|
app.get(
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import { apiRoute, handleZodError } from "@/api";
|
import { apiRoute, handleZodError } from "@/api";
|
||||||
import { Note, User, db } from "@versia/kit/db";
|
import { Note, User, db } from "@versia/kit/db";
|
||||||
import { Notes } from "@versia/kit/tables";
|
import { Notes } from "@versia/kit/tables";
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import { CollectionSchema, NoteSchema } from "@versia/sdk/schemas";
|
|
||||||
import { and, eq, inArray } from "drizzle-orm";
|
import { and, eq, inArray } from "drizzle-orm";
|
||||||
import { describeRoute } from "hono-openapi";
|
import { describeRoute } from "hono-openapi";
|
||||||
import { resolver, validator } from "hono-openapi/zod";
|
import { resolver, validator } from "hono-openapi/zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ApiError } from "~/classes/errors/api-error";
|
import { ApiError } from "~/classes/errors/api-error";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import * as VersiaEntities from "~/packages/sdk/entities";
|
||||||
|
import { CollectionSchema, NoteSchema } from "~/packages/sdk/schemas";
|
||||||
|
|
||||||
const NOTES_PER_PAGE = 20;
|
const NOTES_PER_PAGE = 20;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@ import { apiRoute } from "@/api";
|
||||||
import { urlToContentFormat } from "@/content_types";
|
import { urlToContentFormat } from "@/content_types";
|
||||||
import { User } from "@versia/kit/db";
|
import { User } from "@versia/kit/db";
|
||||||
import { Users } from "@versia/kit/tables";
|
import { Users } from "@versia/kit/tables";
|
||||||
import { InstanceMetadataSchema } from "@versia/sdk/schemas";
|
|
||||||
import { asc } from "drizzle-orm";
|
import { asc } from "drizzle-orm";
|
||||||
import { describeRoute } from "hono-openapi";
|
import { describeRoute } from "hono-openapi";
|
||||||
import { resolver } from "hono-openapi/zod";
|
import { resolver } from "hono-openapi/zod";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
import pkg from "~/package.json";
|
import pkg from "~/package.json";
|
||||||
|
import { InstanceMetadataSchema } from "~/packages/sdk/schemas";
|
||||||
|
|
||||||
export default apiRoute((app) =>
|
export default apiRoute((app) =>
|
||||||
app.get(
|
app.get(
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@ import {
|
||||||
import { getLogger } from "@logtape/logtape";
|
import { getLogger } from "@logtape/logtape";
|
||||||
import { User } from "@versia/kit/db";
|
import { User } from "@versia/kit/db";
|
||||||
import { Users } from "@versia/kit/tables";
|
import { Users } from "@versia/kit/tables";
|
||||||
import { WebFingerSchema } from "@versia/sdk/schemas";
|
|
||||||
import { and, eq, isNull } from "drizzle-orm";
|
import { and, eq, isNull } from "drizzle-orm";
|
||||||
import { describeRoute } from "hono-openapi";
|
import { describeRoute } from "hono-openapi";
|
||||||
import { resolver, validator } from "hono-openapi/zod";
|
import { resolver, validator } from "hono-openapi/zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ApiError } from "~/classes/errors/api-error";
|
import { ApiError } from "~/classes/errors/api-error";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import { WebFingerSchema } from "~/packages/sdk/schemas";
|
||||||
|
|
||||||
export default apiRoute((app) =>
|
export default apiRoute((app) =>
|
||||||
app.get(
|
app.get(
|
||||||
|
|
@ -101,7 +101,9 @@ export default apiRoute((app) =>
|
||||||
|
|
||||||
return context.json(
|
return context.json(
|
||||||
{
|
{
|
||||||
subject: `acct:${isUuid ? user.id : user.data.username}@${host}`,
|
subject: `acct:${
|
||||||
|
isUuid ? user.id : user.data.username
|
||||||
|
}@${host}`,
|
||||||
|
|
||||||
links: [
|
links: [
|
||||||
// Keep the ActivityPub link first, because Misskey only searches
|
// Keep the ActivityPub link first, because Misskey only searches
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ import { emojiValidatorWithColons, emojiValidatorWithIdentifiers } from "@/api";
|
||||||
import type { CustomEmoji } from "@versia/client/schemas";
|
import type { CustomEmoji } from "@versia/client/schemas";
|
||||||
import { type Instance, Media, db } from "@versia/kit/db";
|
import { type Instance, Media, db } from "@versia/kit/db";
|
||||||
import { Emojis, type Instances, type Medias } from "@versia/kit/tables";
|
import { Emojis, type Instances, type Medias } from "@versia/kit/tables";
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import type { ImageContentFormatSchema } from "@versia/sdk/schemas";
|
|
||||||
import { randomUUIDv7 } from "bun";
|
import { randomUUIDv7 } from "bun";
|
||||||
import {
|
import {
|
||||||
type InferInsertModel,
|
type InferInsertModel,
|
||||||
|
|
@ -16,6 +14,8 @@ import {
|
||||||
isNull,
|
isNull,
|
||||||
} from "drizzle-orm";
|
} from "drizzle-orm";
|
||||||
import type { z } from "zod";
|
import type { z } from "zod";
|
||||||
|
import * as VersiaEntities from "~/packages/sdk/entities/index.ts";
|
||||||
|
import type { ImageContentFormatSchema } from "~/packages/sdk/schemas/index.ts";
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
|
|
||||||
type EmojiType = InferSelectModel<typeof Emojis> & {
|
type EmojiType = InferSelectModel<typeof Emojis> & {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { getLogger } from "@logtape/logtape";
|
import { getLogger } from "@logtape/logtape";
|
||||||
import { db } from "@versia/kit/db";
|
import { db } from "@versia/kit/db";
|
||||||
import { Instances } from "@versia/kit/tables";
|
import { Instances } from "@versia/kit/tables";
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import { randomUUIDv7 } from "bun";
|
import { randomUUIDv7 } from "bun";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import {
|
import {
|
||||||
|
|
@ -13,6 +12,7 @@ import {
|
||||||
inArray,
|
inArray,
|
||||||
} from "drizzle-orm";
|
} from "drizzle-orm";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import * as VersiaEntities from "~/packages/sdk/entities/index.ts";
|
||||||
import { ApiError } from "../errors/api-error.ts";
|
import { ApiError } from "../errors/api-error.ts";
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
import { User } from "./user.ts";
|
import { User } from "./user.ts";
|
||||||
|
|
@ -319,7 +319,9 @@ export class Instance extends BaseInterface<typeof Instances> {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!output) {
|
if (!output) {
|
||||||
logger.error`Failed to update instance ${chalk.bold(this.data.baseUrl)}`;
|
logger.error`Failed to update instance ${chalk.bold(
|
||||||
|
this.data.baseUrl,
|
||||||
|
)}`;
|
||||||
throw new Error("Failed to update instance");
|
throw new Error("Failed to update instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import {
|
||||||
Notifications,
|
Notifications,
|
||||||
type Users,
|
type Users,
|
||||||
} from "@versia/kit/tables";
|
} from "@versia/kit/tables";
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import {
|
import {
|
||||||
type InferInsertModel,
|
type InferInsertModel,
|
||||||
type InferSelectModel,
|
type InferSelectModel,
|
||||||
|
|
@ -16,6 +15,7 @@ import {
|
||||||
inArray,
|
inArray,
|
||||||
} from "drizzle-orm";
|
} from "drizzle-orm";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import * as VersiaEntities from "~/packages/sdk/entities/index.ts";
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
import { User } from "./user.ts";
|
import { User } from "./user.ts";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,6 @@ import { mimeLookup } from "@/content_types.ts";
|
||||||
import type { Attachment as AttachmentSchema } from "@versia/client/schemas";
|
import type { Attachment as AttachmentSchema } from "@versia/client/schemas";
|
||||||
import { db } from "@versia/kit/db";
|
import { db } from "@versia/kit/db";
|
||||||
import { Medias } from "@versia/kit/tables";
|
import { Medias } from "@versia/kit/tables";
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import type {
|
|
||||||
ContentFormatSchema,
|
|
||||||
ImageContentFormatSchema,
|
|
||||||
} from "@versia/sdk/schemas";
|
|
||||||
import { S3Client, SHA256, randomUUIDv7, write } from "bun";
|
import { S3Client, SHA256, randomUUIDv7, write } from "bun";
|
||||||
import {
|
import {
|
||||||
type InferInsertModel,
|
type InferInsertModel,
|
||||||
|
|
@ -21,6 +16,11 @@ import sharp from "sharp";
|
||||||
import type { z } from "zod";
|
import type { z } from "zod";
|
||||||
import { MediaBackendType } from "~/classes/config/schema.ts";
|
import { MediaBackendType } from "~/classes/config/schema.ts";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import * as VersiaEntities from "~/packages/sdk/entities/index.ts";
|
||||||
|
import type {
|
||||||
|
ContentFormatSchema,
|
||||||
|
ImageContentFormatSchema,
|
||||||
|
} from "~/packages/sdk/schemas/index.ts";
|
||||||
import { ApiError } from "../errors/api-error.ts";
|
import { ApiError } from "../errors/api-error.ts";
|
||||||
import { getMediaHash } from "../media/media-hasher.ts";
|
import { getMediaHash } from "../media/media-hasher.ts";
|
||||||
import { ProxiableUrl } from "../media/url.ts";
|
import { ProxiableUrl } from "../media/url.ts";
|
||||||
|
|
@ -278,7 +278,9 @@ export class Media extends BaseInterface<typeof Medias> {
|
||||||
throw new ApiError(
|
throw new ApiError(
|
||||||
415,
|
415,
|
||||||
`File type ${file.type} is not allowed`,
|
`File type ${file.type} is not allowed`,
|
||||||
`Allowed types: ${config.validation.media.allowed_mime_types.join(", ")}`,
|
`Allowed types: ${config.validation.media.allowed_mime_types.join(
|
||||||
|
", ",
|
||||||
|
)}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import {
|
||||||
Notes,
|
Notes,
|
||||||
Users,
|
Users,
|
||||||
} from "@versia/kit/tables";
|
} from "@versia/kit/tables";
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import { randomUUIDv7 } from "bun";
|
import { randomUUIDv7 } from "bun";
|
||||||
import {
|
import {
|
||||||
type InferInsertModel,
|
type InferInsertModel,
|
||||||
|
|
@ -28,7 +27,8 @@ import { createRegExp, exactly, global } from "magic-regexp";
|
||||||
import type { z } from "zod";
|
import type { z } from "zod";
|
||||||
import { contentToHtml, findManyNotes } from "~/classes/functions/status";
|
import { contentToHtml, findManyNotes } from "~/classes/functions/status";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
import type { NonTextContentFormatSchema } from "~/packages/federation/schemas/contentformat.ts";
|
import * as VersiaEntities from "~/packages/sdk/entities/index.ts";
|
||||||
|
import type { NonTextContentFormatSchema } from "~/packages/sdk/schemas/contentformat.ts";
|
||||||
import { DeliveryJobType, deliveryQueue } from "../queues/delivery.ts";
|
import { DeliveryJobType, deliveryQueue } from "../queues/delivery.ts";
|
||||||
import { Application } from "./application.ts";
|
import { Application } from "./application.ts";
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { Emoji, Instance, type Note, User, db } from "@versia/kit/db";
|
import { Emoji, Instance, type Note, User, db } from "@versia/kit/db";
|
||||||
import { type Notes, Reactions, type Users } from "@versia/kit/tables";
|
import { type Notes, Reactions, type Users } from "@versia/kit/tables";
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import { randomUUIDv7 } from "bun";
|
import { randomUUIDv7 } from "bun";
|
||||||
import {
|
import {
|
||||||
type InferInsertModel,
|
type InferInsertModel,
|
||||||
|
|
@ -11,6 +10,7 @@ import {
|
||||||
inArray,
|
inArray,
|
||||||
} from "drizzle-orm";
|
} from "drizzle-orm";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import * as VersiaEntities from "~/packages/sdk/entities/index.ts";
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
|
|
||||||
type ReactionType = InferSelectModel<typeof Reactions> & {
|
type ReactionType = InferSelectModel<typeof Reactions> & {
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,6 @@ import {
|
||||||
UserToPinnedNotes,
|
UserToPinnedNotes,
|
||||||
Users,
|
Users,
|
||||||
} from "@versia/kit/tables";
|
} from "@versia/kit/tables";
|
||||||
import { sign } from "@versia/sdk/crypto";
|
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import { FederationRequester } from "@versia/sdk/http";
|
|
||||||
import type { ImageContentFormatSchema } from "@versia/sdk/schemas";
|
|
||||||
import { randomUUIDv7 } from "bun";
|
import { randomUUIDv7 } from "bun";
|
||||||
import { password as bunPassword } from "bun";
|
import { password as bunPassword } from "bun";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
|
|
@ -45,6 +41,10 @@ import type { z } from "zod";
|
||||||
import { findManyUsers } from "~/classes/functions/user";
|
import { findManyUsers } from "~/classes/functions/user";
|
||||||
import { searchManager } from "~/classes/search/search-manager";
|
import { searchManager } from "~/classes/search/search-manager";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import { sign } from "~/packages/sdk/crypto.ts";
|
||||||
|
import * as VersiaEntities from "~/packages/sdk/entities/index.ts";
|
||||||
|
import { FederationRequester } from "~/packages/sdk/http.ts";
|
||||||
|
import type { ImageContentFormatSchema } from "~/packages/sdk/schemas/index.ts";
|
||||||
import type { HttpVerb, KnownEntity } from "~/types/api.ts";
|
import type { HttpVerb, KnownEntity } from "~/types/api.ts";
|
||||||
import { ProxiableUrl } from "../media/url.ts";
|
import { ProxiableUrl } from "../media/url.ts";
|
||||||
import { DeliveryJobType, deliveryQueue } from "../queues/delivery.ts";
|
import { DeliveryJobType, deliveryQueue } from "../queues/delivery.ts";
|
||||||
|
|
@ -1023,8 +1023,9 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
entity,
|
entity,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
getLogger(["federation", "delivery"])
|
getLogger(["federation", "delivery"]).error`Federating ${chalk.gray(
|
||||||
.error`Federating ${chalk.gray(entity.data.type)} to ${user.uri} ${chalk.bold.red("failed")}`;
|
entity.data.type,
|
||||||
|
)} to ${user.uri} ${chalk.bold.red("failed")}`;
|
||||||
getLogger(["federation", "delivery"]).error`${e}`;
|
getLogger(["federation", "delivery"]).error`${e}`;
|
||||||
sentry?.captureException(e);
|
sentry?.captureException(e);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import { sanitizeHtml, sanitizeHtmlInline } from "@/sanitization";
|
||||||
import markdownItTaskLists from "@hackmd/markdown-it-task-lists";
|
import markdownItTaskLists from "@hackmd/markdown-it-task-lists";
|
||||||
import { type Note, User, db } from "@versia/kit/db";
|
import { type Note, User, db } from "@versia/kit/db";
|
||||||
import { Instances, Users } from "@versia/kit/tables";
|
import { Instances, Users } from "@versia/kit/tables";
|
||||||
import type * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import { and, eq, inArray, isNull, or, sql } from "drizzle-orm";
|
import { and, eq, inArray, isNull, or, sql } from "drizzle-orm";
|
||||||
import linkifyHtml from "linkify-html";
|
import linkifyHtml from "linkify-html";
|
||||||
import {
|
import {
|
||||||
|
|
@ -19,6 +18,7 @@ import MarkdownIt from "markdown-it";
|
||||||
import markdownItContainer from "markdown-it-container";
|
import markdownItContainer from "markdown-it-container";
|
||||||
import markdownItTocDoneRight from "markdown-it-toc-done-right";
|
import markdownItTocDoneRight from "markdown-it-toc-done-right";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import type * as VersiaEntities from "~/packages/sdk/entities/index.ts";
|
||||||
import {
|
import {
|
||||||
transformOutputToUserWithRelations,
|
transformOutputToUserWithRelations,
|
||||||
userExtrasTemplate,
|
userExtrasTemplate,
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,6 @@ import { sentry } from "@/sentry";
|
||||||
import { type Logger, getLogger } from "@logtape/logtape";
|
import { type Logger, getLogger } from "@logtape/logtape";
|
||||||
import { type Instance, Like, Note, Relationship, User } from "@versia/kit/db";
|
import { type Instance, Like, Note, Relationship, User } from "@versia/kit/db";
|
||||||
import { Likes, Notes } from "@versia/kit/tables";
|
import { Likes, Notes } from "@versia/kit/tables";
|
||||||
import { EntitySorter } from "@versia/sdk";
|
|
||||||
import { verify } from "@versia/sdk/crypto";
|
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import type { SocketAddress } from "bun";
|
import type { SocketAddress } from "bun";
|
||||||
import { Glob } from "bun";
|
import { Glob } from "bun";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
|
|
@ -12,7 +9,10 @@ import { eq } from "drizzle-orm";
|
||||||
import { matches } from "ip-matching";
|
import { matches } from "ip-matching";
|
||||||
import { isValidationError } from "zod-validation-error";
|
import { isValidationError } from "zod-validation-error";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
import type { JSONObject } from "~/packages/federation/types.ts";
|
import { verify } from "~/packages/sdk/crypto.ts";
|
||||||
|
import * as VersiaEntities from "~/packages/sdk/entities/index.ts";
|
||||||
|
import { EntitySorter } from "~/packages/sdk/inbox-processor.ts";
|
||||||
|
import type { JSONObject } from "~/packages/sdk/types.ts";
|
||||||
import { ApiError } from "../errors/api-error.ts";
|
import { ApiError } from "../errors/api-error.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { User } from "@versia/kit/db";
|
import { User } from "@versia/kit/db";
|
||||||
import * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import { Queue } from "bullmq";
|
import { Queue } from "bullmq";
|
||||||
import { Worker } from "bullmq";
|
import { Worker } from "bullmq";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
import type { JSONObject } from "~/packages/federation/types";
|
import * as VersiaEntities from "~/packages/sdk/entities";
|
||||||
|
import type { JSONObject } from "~/packages/sdk/types";
|
||||||
import { connection } from "~/utils/redis.ts";
|
import { connection } from "~/utils/redis.ts";
|
||||||
|
|
||||||
export enum DeliveryJobType {
|
export enum DeliveryJobType {
|
||||||
|
|
@ -40,7 +40,9 @@ export const getDeliveryWorker = (): Worker<
|
||||||
|
|
||||||
if (!sender) {
|
if (!sender) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Could not resolve sender ID ${chalk.gray(senderId)}`,
|
`Could not resolve sender ID ${chalk.gray(
|
||||||
|
senderId,
|
||||||
|
)}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,12 +50,16 @@ export const getDeliveryWorker = (): Worker<
|
||||||
|
|
||||||
if (!recipient) {
|
if (!recipient) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Could not resolve recipient ID ${chalk.gray(recipientId)}`,
|
`Could not resolve recipient ID ${chalk.gray(
|
||||||
|
recipientId,
|
||||||
|
)}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await job.log(
|
await job.log(
|
||||||
`Federating entity [${entity.id}] from @${sender.getAcct()} to @${recipient.getAcct()}`,
|
`Federating entity [${
|
||||||
|
entity.id
|
||||||
|
}] from @${sender.getAcct()} to @${recipient.getAcct()}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const type = entity.type;
|
const type = entity.type;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { Queue } from "bullmq";
|
||||||
import { Worker } from "bullmq";
|
import { Worker } from "bullmq";
|
||||||
import type { SocketAddress } from "bun";
|
import type { SocketAddress } from "bun";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
import type { JSONObject } from "~/packages/federation/types.ts";
|
import type { JSONObject } from "~/packages/sdk/types.ts";
|
||||||
import { connection } from "~/utils/redis.ts";
|
import { connection } from "~/utils/redis.ts";
|
||||||
import { ApiError } from "../errors/api-error.ts";
|
import { ApiError } from "../errors/api-error.ts";
|
||||||
import { InboxProcessor } from "../inbox/processor.ts";
|
import { InboxProcessor } from "../inbox/processor.ts";
|
||||||
|
|
@ -182,7 +182,9 @@ export const getInboxWorker = (): Worker<InboxJobData, void, InboxJobType> =>
|
||||||
);
|
);
|
||||||
|
|
||||||
await remoteInstance.sendMessage(
|
await remoteInstance.sendMessage(
|
||||||
`Failed processing entity [${data.uri}] delivered to inbox. Returned error:\n\n${JSON.stringify(
|
`Failed processing entity [${
|
||||||
|
data.uri
|
||||||
|
}] delivered to inbox. Returned error:\n\n${JSON.stringify(
|
||||||
e.message,
|
e.message,
|
||||||
null,
|
null,
|
||||||
4,
|
4,
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,6 @@ import type {
|
||||||
Status as StatusSchema,
|
Status as StatusSchema,
|
||||||
} from "@versia/client/schemas";
|
} from "@versia/client/schemas";
|
||||||
import type { RolePermission } from "@versia/client/schemas";
|
import type { RolePermission } from "@versia/client/schemas";
|
||||||
import type {
|
|
||||||
ContentFormatSchema,
|
|
||||||
ImageContentFormatSchema,
|
|
||||||
InstanceMetadataSchema,
|
|
||||||
NonTextContentFormatSchema,
|
|
||||||
TextContentFormatSchema,
|
|
||||||
} from "@versia/sdk/schemas";
|
|
||||||
import type { Challenge } from "altcha-lib/types";
|
import type { Challenge } from "altcha-lib/types";
|
||||||
import { relations, sql } from "drizzle-orm";
|
import { relations, sql } from "drizzle-orm";
|
||||||
import {
|
import {
|
||||||
|
|
@ -26,6 +19,13 @@ import {
|
||||||
uuid,
|
uuid,
|
||||||
} from "drizzle-orm/pg-core";
|
} from "drizzle-orm/pg-core";
|
||||||
import type { z } from "zod";
|
import type { z } from "zod";
|
||||||
|
import type {
|
||||||
|
ContentFormatSchema,
|
||||||
|
ImageContentFormatSchema,
|
||||||
|
InstanceMetadataSchema,
|
||||||
|
NonTextContentFormatSchema,
|
||||||
|
TextContentFormatSchema,
|
||||||
|
} from "~/packages/sdk/schemas";
|
||||||
|
|
||||||
// biome-ignore lint/nursery/useExplicitType: Type is too complex
|
// biome-ignore lint/nursery/useExplicitType: Type is too complex
|
||||||
const createdAt = () =>
|
const createdAt = () =>
|
||||||
|
|
|
||||||
220
packages/sdk/README.md
Normal file
220
packages/sdk/README.md
Normal file
|
|
@ -0,0 +1,220 @@
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://versia.pub"><img src="https://cdn.versia.pub/branding/logo-dark.svg" alt="Versia Logo" height="110"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<center><h1><code>@versia/sdk</code></h1></center>
|
||||||
|
|
||||||
|
Federation types, validators and cryptography for Versia server implementations.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
## Entities
|
||||||
|
|
||||||
|
The `@versia/sdk/entities` module provides TypeScript classes for working with Versia entities. These classes provide type-safe access to entity properties and methods for serialization/deserialization.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { Note, User } from "@versia/sdk/entities";
|
||||||
|
|
||||||
|
const note = new Note({
|
||||||
|
id: "00000000-0000-0000-0000-000000000000",
|
||||||
|
type: "Note",
|
||||||
|
});
|
||||||
|
|
||||||
|
// You can also parse from JSON, which will apply the schema validation
|
||||||
|
const invalidJson = {
|
||||||
|
id: "00000000-0000-0000-0000-000000000000",
|
||||||
|
invalid: "property",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Will throw an error
|
||||||
|
const invalidNote = await Note.fromJSON(invalidJson);
|
||||||
|
|
||||||
|
const validJson = {
|
||||||
|
id: "00000000-0000-0000-0000-000000000000",
|
||||||
|
type: "Note",
|
||||||
|
};
|
||||||
|
|
||||||
|
const validNote = await Note.fromJSON(validJson);
|
||||||
|
```
|
||||||
|
|
||||||
|
Some entities like `Note` have additional properties, like `content` or `attachments`, which are automatically calculated from the relevant properties.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { TextContentFormat, Note } from "@versia/sdk/entities";
|
||||||
|
|
||||||
|
const note = new Note({
|
||||||
|
id: "00000000-0000-0000-0000-000000000000",
|
||||||
|
type: "Note",
|
||||||
|
content: {
|
||||||
|
"text/plain": {
|
||||||
|
content: "Hello, world!",
|
||||||
|
remote: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const content = note.content;
|
||||||
|
// Is equivalent to
|
||||||
|
const content = new TextContentFormat(note.data.content);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Schemas
|
||||||
|
|
||||||
|
Additionally, the [**Zod**](https://zod.dev) schemas used for validation are available in the `@versia/sdk/schemas` module. You can use these to directly validate incoming data, without using the entity classes.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { NoteSchema, UserSchema } from "@versia/sdk/schemas";
|
||||||
|
|
||||||
|
const response = await fetch("https://example.com/notes/123");
|
||||||
|
const json = await response.json();
|
||||||
|
|
||||||
|
const noteSchema = NoteSchema.parse(json);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sorter
|
||||||
|
|
||||||
|
The `@versia/sdk/sorter` module provides a class for inbox request handling. It allows you to automatically sort and process incoming entities based on their type.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { EntitySorter } from "@versia/sdk";
|
||||||
|
import { Note, User } from "@versia/sdk/entities";
|
||||||
|
|
||||||
|
app.post("/inbox", async (req, res) => {
|
||||||
|
const json = await req.json();
|
||||||
|
|
||||||
|
const sorter = new EntitySorter(json);
|
||||||
|
|
||||||
|
await sorter
|
||||||
|
.on(Note, (note) => {
|
||||||
|
console.log(note);
|
||||||
|
})
|
||||||
|
.on(User, (user) => {
|
||||||
|
console.log(user);
|
||||||
|
})
|
||||||
|
.sort();
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cryptography
|
||||||
|
|
||||||
|
The `@versia/sdk/crypto` module provides functions for signing and verifying requests using the [**Ed25519**](https://en.wikipedia.org/wiki/EdDSA) algorithm.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { sign, verify } from "@versia/sdk/crypto";
|
||||||
|
|
||||||
|
const keys = await crypto.subtle.generateKey("Ed25519", true, [
|
||||||
|
"sign",
|
||||||
|
"verify",
|
||||||
|
]);
|
||||||
|
|
||||||
|
// URI of the User that is signing the request
|
||||||
|
const authorUrl = new URL("https://example.com");
|
||||||
|
|
||||||
|
const req = new Request("https://example.com/notes/123", {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
id: "00000000-0000-0000-0000-000000000000",
|
||||||
|
type: "Note",
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const signedReq = await sign(keys.privateKey, authorUrl, req);
|
||||||
|
|
||||||
|
const verified = await verify(keys.publicKey, signedReq);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
#### For Usage
|
||||||
|
|
||||||
|
See the [**Compatibility**](#compatibility) section for the supported environments. Any package manager can be used to install the packages.
|
||||||
|
|
||||||
|
#### For Development
|
||||||
|
|
||||||
|
- [**Bun**](https://bun.sh) version `1.1.8` or higher.
|
||||||
|
- Either the [**Linux**](https://www.linux.org) or [**macOS**](https://www.apple.com/macos) operating systems. ([**Windows**](https://www.microsoft.com/windows) will work, but is not officially supported.)
|
||||||
|
|
||||||
|
### Compatibility
|
||||||
|
|
||||||
|
This library is built for JavaScript runtimes with the support for:
|
||||||
|
|
||||||
|
- [**ES Modules**](https://nodejs.org/api/esm.html)
|
||||||
|
- [**ECMAScript 2020**](https://www.ecma-international.org/ecma-262/11.0/index.html)
|
||||||
|
- (only required for cryptography) [**Ed25519**](https://en.wikipedia.org/wiki/EdDSA) cryptography in the [**WebCrypto API**](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)
|
||||||
|
|
||||||
|
#### Runtimes
|
||||||
|
|
||||||
|
- **Node.js**: 14.0+ is the minimum (18.0+ for cryptography), but only Node.js 20.0+ (LTS) is officially supported.
|
||||||
|
- **Deno**: Support is unknown. 1.0+ is expected to work.
|
||||||
|
- **Bun**: Bun 1.1.8 is the minimum-supported version. As Bun is rapidly evolving, this may change. Previous versions may also work.
|
||||||
|
|
||||||
|
#### Browsers
|
||||||
|
|
||||||
|
Consequently, this library is compatible without any bundling in the following browser versions:
|
||||||
|
|
||||||
|
- **Chrome**: 80+
|
||||||
|
- **Edge**: 80+
|
||||||
|
- **Firefox**: 74+
|
||||||
|
- **Safari**: 13.1+
|
||||||
|
- **Opera**: 67+
|
||||||
|
- **Internet Explorer**: None
|
||||||
|
|
||||||
|
Cryptography functions are supported in the following browsers:
|
||||||
|
|
||||||
|
- **Safari**: 17.0+
|
||||||
|
- **Firefox**: 129.0+
|
||||||
|
- **Chrome**: 113.0+ with `#enable-experimental-web-platform-features` enabled
|
||||||
|
|
||||||
|
If you are targeting older browsers, please don't, you are doing yourself a disservice.
|
||||||
|
|
||||||
|
Transpilation to non-ES Module environments is not officially supported, but should be simple with the use of a bundler like [**Parcel**](https://parceljs.org) or [**Rollup**](https://rollupjs.org).
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
Package is distributed as a scoped package on the NPM registry and [JSR](https://jsr.io).
|
||||||
|
|
||||||
|
We strongly recommend using JSR over NPM for all your packages that are available on it.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# NPM version
|
||||||
|
deno add npm:@versia/sdk # For Deno
|
||||||
|
npm install @versia/sdk # For NPM
|
||||||
|
yarn add @versia/sdk # For Yarn
|
||||||
|
pnpm add @versia/sdk # For PNPM
|
||||||
|
bun add @versia/sdk # For Bun
|
||||||
|
|
||||||
|
# JSR version
|
||||||
|
deno add @versia/sdk # For Deno
|
||||||
|
npx jsr add @versia/sdk # For JSR
|
||||||
|
yarn dlx jsr add @versia/sdk # For Yarn
|
||||||
|
pnpm dlx jsr add @versia/sdk # For PNPM
|
||||||
|
bunx jsr add @versia/sdk # For Bun
|
||||||
|
```
|
||||||
|
|
||||||
|
#### From Source
|
||||||
|
|
||||||
|
If you want to install from source, you can clone [this repository](https://github.com/versia-pub/api) and run the following commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun install # Install dependencies
|
||||||
|
|
||||||
|
bun run build # Build the packages
|
||||||
|
```
|
||||||
|
|
||||||
|
The built package will be in the `sdk/dist` folder.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
|
## Acknowledgments
|
||||||
|
|
||||||
|
### Projects
|
||||||
|
|
||||||
|
- [**Bun**](https://bun.sh): Thanks to the Bun team for creating an amazing JavaScript runtime.
|
||||||
|
- [**TypeScript**](https://www.typescriptlang.org): TypeScript is the backbone of this project.
|
||||||
|
- [**Node.js**](https://nodejs.org): Node.js created the idea of JavaScript on the server.
|
||||||
|
|
||||||
|
### People
|
||||||
|
|
||||||
|
- [**April John**](https://github.com/cutestnekoaqua): Creator and maintainer of the Versia Server ActivityPub bridge.
|
||||||
|
|
@ -9,6 +9,16 @@ const stringToBase64Hash = async (str: string): Promise<string> => {
|
||||||
const base64ToArrayBuffer = (base64: string): ArrayBuffer =>
|
const base64ToArrayBuffer = (base64: string): ArrayBuffer =>
|
||||||
Uint8Array.fromBase64(base64).buffer as ArrayBuffer;
|
Uint8Array.fromBase64(base64).buffer as ArrayBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signs a request using the Ed25519 algorithm, according to the [**Versia**](https://versia.pub/signatures) specification.
|
||||||
|
*
|
||||||
|
* @see https://versia.pub/signatures
|
||||||
|
* @param privateKey - Private key of the User that is signing the request.
|
||||||
|
* @param authorUrl - URL of the User that is signing the request.
|
||||||
|
* @param req - Request to sign.
|
||||||
|
* @param timestamp - (optional) Timestamp of the request.
|
||||||
|
* @returns The signed request.
|
||||||
|
*/
|
||||||
export const sign = async (
|
export const sign = async (
|
||||||
privateKey: CryptoKey,
|
privateKey: CryptoKey,
|
||||||
authorUrl: URL,
|
authorUrl: URL,
|
||||||
|
|
@ -45,6 +55,14 @@ export const sign = async (
|
||||||
return newReq;
|
return newReq;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies a signed request using the Ed25519 algorithm, according to the [**Versia**](https://versia.pub/signatures) specification.
|
||||||
|
*
|
||||||
|
* @see https://versia.pub/signatures
|
||||||
|
* @param publicKey - Public key of the User that is verifying the request.
|
||||||
|
* @param req - Request to verify.
|
||||||
|
* @returns Whether the request signature is valid or not.
|
||||||
|
*/
|
||||||
export const verify = async (
|
export const verify = async (
|
||||||
publicKey: CryptoKey,
|
publicKey: CryptoKey,
|
||||||
req: Request,
|
req: Request,
|
||||||
|
|
@ -62,7 +80,9 @@ export const verify = async (
|
||||||
|
|
||||||
const digest = await stringToBase64Hash(body);
|
const digest = await stringToBase64Hash(body);
|
||||||
|
|
||||||
const expectedSignedString = `${req.method.toLowerCase()} ${encodeURI(url.pathname)} ${signedAt} ${digest}`;
|
const expectedSignedString = `${req.method.toLowerCase()} ${encodeURI(
|
||||||
|
url.pathname,
|
||||||
|
)} ${signedAt} ${digest}`;
|
||||||
|
|
||||||
// Check if this matches the signature
|
// Check if this matches the signature
|
||||||
return crypto.subtle.verify(
|
return crypto.subtle.verify(
|
||||||
|
|
@ -10,7 +10,7 @@ type MaybePromise<T> = T | Promise<T>;
|
||||||
/**
|
/**
|
||||||
* @example
|
* @example
|
||||||
* const jsonData = { ... };
|
* const jsonData = { ... };
|
||||||
* const processor = new EntitySorter(jsonData)
|
* const processor = await new EntitySorter(jsonData)
|
||||||
* .on(User, async (user) => {
|
* .on(User, async (user) => {
|
||||||
* // Do something with the user
|
* // Do something with the user
|
||||||
* })
|
* })
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import type * as VersiaEntities from "@versia/sdk/entities";
|
|
||||||
import type { SocketAddress } from "bun";
|
import type { SocketAddress } from "bun";
|
||||||
import type { Hono } from "hono";
|
import type { Hono } from "hono";
|
||||||
import type { RouterRoute } from "hono/types";
|
import type { RouterRoute } from "hono/types";
|
||||||
import type { z } from "zod";
|
import type { z } from "zod";
|
||||||
import type { ConfigSchema } from "~/classes/config/schema";
|
import type { ConfigSchema } from "~/classes/config/schema";
|
||||||
import type { AuthData } from "~/classes/functions/user";
|
import type { AuthData } from "~/classes/functions/user";
|
||||||
|
import type * as VersiaEntities from "~/packages/sdk/entities";
|
||||||
|
|
||||||
export type HttpVerb = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS";
|
export type HttpVerb = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import type { ContentFormatSchema } from "@versia/sdk/schemas";
|
|
||||||
import { htmlToText as htmlToTextLib } from "html-to-text";
|
import { htmlToText as htmlToTextLib } from "html-to-text";
|
||||||
import { lookup } from "mime-types";
|
import { lookup } from "mime-types";
|
||||||
import type { z } from "zod";
|
import type { z } from "zod";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
|
import type { ContentFormatSchema } from "~/packages/sdk/schemas";
|
||||||
|
|
||||||
export const getBestContentType = (
|
export const getBestContentType = (
|
||||||
content?: z.infer<typeof ContentFormatSchema> | null,
|
content?: z.infer<typeof ContentFormatSchema> | null,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue