mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 16:38:19 +01:00
feat: Add working building and bundling system
This commit is contained in:
parent
2333bbead9
commit
df47fa4750
8
build.ts
Normal file
8
build.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
await Bun.build({
|
||||||
|
entrypoints: ["./index.ts"],
|
||||||
|
outdir: "./dist",
|
||||||
|
target: "bun",
|
||||||
|
splitting: true,
|
||||||
|
minify: false,
|
||||||
|
external: ["bullmq", "@prisma/client"],
|
||||||
|
});
|
||||||
24
index.ts
24
index.ts
|
|
@ -1,12 +1,9 @@
|
||||||
import { getConfig } from "@config";
|
import { getConfig } from "@config";
|
||||||
import { jsonResponse } from "@response";
|
import { jsonResponse } from "@response";
|
||||||
import type { MatchedRoute } from "bun";
|
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import { appendFile } from "fs/promises";
|
import { appendFile } from "fs/promises";
|
||||||
import { matches } from "ip-matching";
|
import { matches } from "ip-matching";
|
||||||
import type { AuthData } from "~database/entities/User";
|
|
||||||
import { getFromRequest } from "~database/entities/User";
|
import { getFromRequest } from "~database/entities/User";
|
||||||
import type { APIRouteMeta } from "~types/api";
|
|
||||||
import { mkdir } from "fs/promises";
|
import { mkdir } from "fs/promises";
|
||||||
import { client } from "~database/datasource";
|
import { client } from "~database/datasource";
|
||||||
import type { PrismaClientInitializationError } from "@prisma/client/runtime/library";
|
import type { PrismaClientInitializationError } from "@prisma/client/runtime/library";
|
||||||
|
|
@ -14,15 +11,11 @@ import { HookTypes, Server } from "~plugins/types";
|
||||||
import { initializeRedisCache } from "@redis";
|
import { initializeRedisCache } from "@redis";
|
||||||
import { connectMeili } from "@meilisearch";
|
import { connectMeili } from "@meilisearch";
|
||||||
import routes from "~pages/routes";
|
import routes from "~pages/routes";
|
||||||
|
import { matchRoute } from "~routes";
|
||||||
|
|
||||||
const timeAtStart = performance.now();
|
const timeAtStart = performance.now();
|
||||||
const server = new Server();
|
const server = new Server();
|
||||||
|
|
||||||
const router = new Bun.FileSystemRouter({
|
|
||||||
style: "nextjs",
|
|
||||||
dir: process.cwd() + "/server/api",
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`${chalk.green(`>`)} ${chalk.bold("Starting Lysand...")}`);
|
console.log(`${chalk.green(`>`)} ${chalk.bold("Starting Lysand...")}`);
|
||||||
|
|
||||||
server.emit(HookTypes.PreServe);
|
server.emit(HookTypes.PreServe);
|
||||||
|
|
@ -87,19 +80,10 @@ Bun.serve({
|
||||||
return jsonResponse({});
|
return jsonResponse({});
|
||||||
}
|
}
|
||||||
|
|
||||||
const matchedRoute = router.match(req);
|
const { file, matchedRoute } = matchRoute(req.url);
|
||||||
|
|
||||||
if (matchedRoute) {
|
if (matchedRoute) {
|
||||||
const file: {
|
const meta = (await file).meta;
|
||||||
meta: APIRouteMeta;
|
|
||||||
default: (
|
|
||||||
req: Request,
|
|
||||||
matchedRoute: MatchedRoute,
|
|
||||||
auth: AuthData
|
|
||||||
) => Response | Promise<Response>;
|
|
||||||
} = await import(matchedRoute.filePath);
|
|
||||||
|
|
||||||
const meta = file.meta;
|
|
||||||
|
|
||||||
// Check for allowed requests
|
// Check for allowed requests
|
||||||
if (!meta.allowedMethods.includes(req.method as any)) {
|
if (!meta.allowedMethods.includes(req.method as any)) {
|
||||||
|
|
@ -134,7 +118,7 @@ Bun.serve({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return await file.default(req.clone(), matchedRoute, auth);
|
return await (await file).default(req.clone(), matchedRoute, auth);
|
||||||
} else {
|
} else {
|
||||||
// Check if path matches Vite routes
|
// Check if path matches Vite routes
|
||||||
if (
|
if (
|
||||||
|
|
|
||||||
|
|
@ -83,8 +83,6 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.461.0",
|
"@aws-sdk/client-s3": "^3.461.0",
|
||||||
"@prisma/client": "^5.6.0",
|
"@prisma/client": "^5.6.0",
|
||||||
|
|
||||||
|
|
||||||
"blurhash": "^2.0.5",
|
"blurhash": "^2.0.5",
|
||||||
"bullmq": "^4.14.4",
|
"bullmq": "^4.14.4",
|
||||||
"chalk": "^5.3.0",
|
"chalk": "^5.3.0",
|
||||||
|
|
@ -102,6 +100,7 @@
|
||||||
"linkifyjs": "^4.1.3",
|
"linkifyjs": "^4.1.3",
|
||||||
"marked": "^9.1.2",
|
"marked": "^9.1.2",
|
||||||
"meilisearch": "^0.36.0",
|
"meilisearch": "^0.36.0",
|
||||||
|
"next-route-matcher": "^1.0.1",
|
||||||
"oauth4webapi": "^2.4.0",
|
"oauth4webapi": "^2.4.0",
|
||||||
"prisma": "^5.6.0",
|
"prisma": "^5.6.0",
|
||||||
"prisma-redis-middleware": "^4.8.0",
|
"prisma-redis-middleware": "^4.8.0",
|
||||||
|
|
|
||||||
177
routes.ts
Normal file
177
routes.ts
Normal file
|
|
@ -0,0 +1,177 @@
|
||||||
|
import type { MatchedRoute } from "bun";
|
||||||
|
import type { AuthData } from "~database/entities/User";
|
||||||
|
import type { APIRouteMeta } from "~types/api";
|
||||||
|
|
||||||
|
const serverPath = process.cwd() + "/server/api";
|
||||||
|
|
||||||
|
// Why are these routes specified manually instead of using Bun's FileSystemRouter?
|
||||||
|
// This is to allow for compilation of the routes, so that we can minify them and
|
||||||
|
// node_modules in production
|
||||||
|
export const rawRoutes = {
|
||||||
|
"/api/v1/accounts": import(serverPath + "/api/v1/accounts/index.ts"),
|
||||||
|
"/api/v1/accounts/familiar_followers": import(
|
||||||
|
serverPath + "/api/v1/accounts/familiar_followers/index.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/relationships": import(
|
||||||
|
serverPath + "/api/v1/accounts/relationships/index.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/search": import(
|
||||||
|
serverPath + "/api/v1/accounts/search/index.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/update_credentials": import(
|
||||||
|
serverPath + "/api/v1/accounts/update_credentials/index.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/verify_credentials": import(
|
||||||
|
serverPath + "/api/v1/accounts/verify_credentials/index.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/apps": import(serverPath + "/api/v1/apps/index.ts"),
|
||||||
|
"/api/v1/apps/verify_credentials": import(
|
||||||
|
serverPath + "/api/v1/apps/verify_credentials/index.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/blocks": import(serverPath + "/api/v1/blocks/index.ts"),
|
||||||
|
"/api/v1/custom_emojis": import(
|
||||||
|
serverPath + "/api/v1/custom_emojis/index.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/favourites": import(serverPath + "/api/v1/favourites/index.ts"),
|
||||||
|
"/api/v1/follow_requests": import(
|
||||||
|
serverPath + "/api/v1/follow_requests/index.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/instance": import(serverPath + "/api/v1/instance/index.ts"),
|
||||||
|
"/api/v1/media": import(serverPath + "/api/v1/media/index.ts"),
|
||||||
|
"/api/v1/mutes": import(serverPath + "/api/v1/mutes/index.ts"),
|
||||||
|
"/api/v1/notifications": import(
|
||||||
|
serverPath + "/api/v1/notifications/index.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/profile/avatar": import(serverPath + "/api/v1/profile/avatar.ts"),
|
||||||
|
"/api/v1/profile/header": import(serverPath + "/api/v1/profile/header.ts"),
|
||||||
|
"/api/v1/statuses": import(serverPath + "/api/v1/statuses/index.ts"),
|
||||||
|
"/api/v1/timelines/home": import(serverPath + "/api/v1/timelines/home.ts"),
|
||||||
|
"/api/v1/timelines/public": import(
|
||||||
|
serverPath + "/api/v1/timelines/public.ts"
|
||||||
|
),
|
||||||
|
"/api/v2/media": import(serverPath + "/api/v2/media/index.ts"),
|
||||||
|
"/api/v2/search": import(serverPath + "/api/v2/search/index.ts"),
|
||||||
|
"/auth/login": import(serverPath + "/auth/login/index.ts"),
|
||||||
|
"/nodeinfo/2.0": import(serverPath + "/nodeinfo/2.0/index.ts"),
|
||||||
|
"/oauth/authorize-external": import(
|
||||||
|
serverPath + "/oauth/authorize-external/index.ts"
|
||||||
|
),
|
||||||
|
"/oauth/providers": import(serverPath + "/oauth/providers/index.ts"),
|
||||||
|
"/oauth/token": import(serverPath + "/oauth/token/index.ts"),
|
||||||
|
"/api/v1/accounts/[id]": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/index.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/[id]/block": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/block.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/[id]/follow": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/follow.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/[id]/followers": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/followers.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/[id]/following": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/following.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/[id]/mute": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/mute.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/[id]/note": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/note.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/[id]/pin": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/pin.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/[id]/remove_from_followers": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/remove_from_followers.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/[id]/statuses": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/statuses.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/[id]/unblock": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/unblock.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/[id]/unfollow": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/unfollow.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/[id]/unmute": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/unmute.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/accounts/[id]/unpin": import(
|
||||||
|
serverPath + "/api/v1/accounts/[id]/unpin.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/follow_requests/[account_id]/authorize": import(
|
||||||
|
serverPath + "/api/v1/follow_requests/[account_id]/authorize.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/follow_requests/[account_id]/reject": import(
|
||||||
|
serverPath + "/api/v1/follow_requests/[account_id]/reject.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/media/[id]": import(serverPath + "/api/v1/media/[id]/index.ts"),
|
||||||
|
"/api/v1/statuses/[id]": import(
|
||||||
|
serverPath + "/api/v1/statuses/[id]/index.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/statuses/[id]/context": import(
|
||||||
|
serverPath + "/api/v1/statuses/[id]/context.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/statuses/[id]/favourite": import(
|
||||||
|
serverPath + "/api/v1/statuses/[id]/favourite.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/statuses/[id]/favourited_by": import(
|
||||||
|
serverPath + "/api/v1/statuses/[id]/favourited_by.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/statuses/[id]/pin": import(
|
||||||
|
serverPath + "/api/v1/statuses/[id]/pin.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/statuses/[id]/reblog": import(
|
||||||
|
serverPath + "/api/v1/statuses/[id]/reblog.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/statuses/[id]/reblogged_by": import(
|
||||||
|
serverPath + "/api/v1/statuses/[id]/reblogged_by.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/statuses/[id]/source": import(
|
||||||
|
serverPath + "/api/v1/statuses/[id]/source.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/statuses/[id]/unfavourite": import(
|
||||||
|
serverPath + "/api/v1/statuses/[id]/unfavourite.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/statuses/[id]/unpin": import(
|
||||||
|
serverPath + "/api/v1/statuses/[id]/unpin.ts"
|
||||||
|
),
|
||||||
|
"/api/v1/statuses/[id]/unreblog": import(
|
||||||
|
serverPath + "/api/v1/statuses/[id]/unreblog.ts"
|
||||||
|
),
|
||||||
|
"/media/[id]": import(serverPath + "/media/[id]/index.ts"),
|
||||||
|
"/oauth/callback/[issuer]": import(
|
||||||
|
serverPath + "/oauth/callback/[issuer]/index.ts"
|
||||||
|
),
|
||||||
|
"/object/[uuid]": import(serverPath + "/object/[uuid]/index.ts"),
|
||||||
|
"/users/[uuid]": import(serverPath + "/users/[uuid]/index.ts"),
|
||||||
|
"/users/[uuid]/inbox": import(serverPath + "/users/[uuid]/inbox/index.ts"),
|
||||||
|
"/users/[uuid]/outbox": import(
|
||||||
|
serverPath + "/users/[uuid]/outbox/index.ts"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the route filesystem path when given a URL
|
||||||
|
export const routeMatcher = new Bun.FileSystemRouter({
|
||||||
|
style: "nextjs",
|
||||||
|
dir: process.cwd() + "/server/api",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const matchRoute = (url: string) => {
|
||||||
|
const route = routeMatcher.match(url);
|
||||||
|
if (!route) return { file: null, matchedRoute: null };
|
||||||
|
|
||||||
|
return {
|
||||||
|
// @ts-expect-error TypeScript parses this as a defined object instead of an arbitrarily editable route file
|
||||||
|
file: rawRoutes[route.name] as Promise<{
|
||||||
|
meta: APIRouteMeta;
|
||||||
|
default: (
|
||||||
|
req: Request,
|
||||||
|
matchedRoute: MatchedRoute,
|
||||||
|
auth: AuthData
|
||||||
|
) => Response | Promise<Response>;
|
||||||
|
}>,
|
||||||
|
matchedRoute: route,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -26,7 +26,8 @@
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@*": ["./utils/*"],
|
"@*": ["./utils/*"],
|
||||||
"~*": ["./*"]
|
"~*": ["./*"],
|
||||||
|
"+*": ["./server/api/*"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue