diff --git a/api/.gitignore b/api/.gitignore new file mode 100644 index 0000000..9093358 --- /dev/null +++ b/api/.gitignore @@ -0,0 +1,45 @@ +# compiled output +/dist +/node_modules + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# OS +.DS_Store + +# Tests +/coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# prisma +/prisma/migrations + +# build output +/build + +.env + +package-lock.json \ No newline at end of file diff --git a/api/package.json b/api/package.json new file mode 100644 index 0000000..6ad5876 --- /dev/null +++ b/api/package.json @@ -0,0 +1,28 @@ +{ + "name": "lavalink-api", + "version": "1.0.0", + "description": "lavalink-api for list of lavalink nodes in cloudflare workers", + "main": "index.js", + "devDependencies": { + "@cloudflare/vitest-pool-workers": "0.1.17", + "@cloudflare/workers-types": "4.20240405.0", + "@types/node": "^20.12.5", + "prisma": "5.12.1", + "typescript": "5.4.4", + "vitest": "1.4.0", + "wrangler": "3.48.0" + }, + "dependencies": { + "@prisma/client": "5.12.1", + "@prisma/extension-accelerate": "^1.0.0" + }, + "scripts": { + "deploy": "wrangler deploy -e production", + "dev": "wrangler dev", + "start": "wrangler dev", + "test": "vitest" + }, + "keywords": [], + "author": "", + "license": "ISC" +} \ No newline at end of file diff --git a/api/prisma/schema.prisma b/api/prisma/schema.prisma new file mode 100644 index 0000000..4d43e22 --- /dev/null +++ b/api/prisma/schema.prisma @@ -0,0 +1,33 @@ + +generator client { + provider = "prisma-client-js" + previewFeatures = ["driverAdapters"] +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") + directUrl = env("DIRECT_DATABASE_URL") +} + +model Node { + authorId String + host String + identifier String @unique + password String + port Int + restVersion String + secure Boolean + isConnected Boolean @default(false) + info Json? + author Json? + memory String? + connections String? + systemLoad String? + cpuCores Int? + uptime String? + cpu String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + diff --git a/api/process.json b/api/process.json new file mode 100644 index 0000000..72d27d9 --- /dev/null +++ b/api/process.json @@ -0,0 +1,12 @@ +{ + "apps": [ + { + "name": "lava-list-api", + "script": "build/index.js", + "node_args": [ + "--enable-source-maps" + ], + "restart_delay": 10000 + } + ] +} \ No newline at end of file diff --git a/api/src/index.ts b/api/src/index.ts new file mode 100644 index 0000000..2bd898b --- /dev/null +++ b/api/src/index.ts @@ -0,0 +1,61 @@ +import { PrismaClient } from '@prisma/client/edge' +import { withAccelerate } from '@prisma/extension-accelerate' + +export interface Env { + DATABASE_URL: string; +} + + +export default { + fetch: async (request: Request, env: Env, ctx: ExecutionContext) => { + try { + + const prisma = new PrismaClient({ + datasourceUrl: env.DATABASE_URL + }).$extends(withAccelerate()); + const url = new URL(request.url); + + if (url.pathname === "/") { + return new Response("Welcome to Lavalink status api", { + headers: { + "Content-Type": "text/plain" + } + }); + } else if (url.pathname === "/ssl-nodes" || url.pathname === "/non-ssl-nodes") { + + const nodes = await prisma.node.findMany({ + where: { + secure: url.pathname === "/ssl-nodes" ? true : false + } + }); + if (nodes.length === 0) { + return new Response("Not Found", { + status: 404, + headers: { + "Content-Type": "text/plain" + } + }); + } + return new Response(JSON.stringify(nodes), { + headers: { + "Content-Type": "application/json" + } + }); + } else { + return new Response("Not Found", { + status: 404, + headers: { + "Content-Type": "text/plain" + } + }); + } + } catch (error: any) { + return new Response(error.message || "Internal Server Error", { + status: 500, + headers: { + "Content-Type": "text/plain" + } + }); + } + } +} \ No newline at end of file diff --git a/api/tsconfig.json b/api/tsconfig.json new file mode 100644 index 0000000..e4ef89f --- /dev/null +++ b/api/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "outDir": "./dist", + "module": "commonjs", + "target": "esnext", + "lib": ["webworker", "dom", "es6"], + "alwaysStrict": true, + "strict": true, + "noImplicitAny": false, + "preserveConstEnums": true, + "moduleResolution": "node", + "sourceMap": true, + "esModuleInterop": true, + "types": ["@cloudflare/workers-types", "@types/node"] + }, + "include": ["src"], + "exclude": ["node_modules", "dist", "test"] +} \ No newline at end of file diff --git a/api/vitest.config.ts b/api/vitest.config.ts new file mode 100644 index 0000000..fd9661e --- /dev/null +++ b/api/vitest.config.ts @@ -0,0 +1,11 @@ +import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config"; + +export default defineWorkersConfig({ + test: { + poolOptions: { + workers: { + wrangler: { configPath: "./wrangler.toml" }, + }, + }, + }, +}); \ No newline at end of file diff --git a/api/wrangler.toml b/api/wrangler.toml new file mode 100644 index 0000000..7444614 --- /dev/null +++ b/api/wrangler.toml @@ -0,0 +1,8 @@ +name = "cloudflare-worker-api" +account_id = "" +main = "src/index.ts" +compatibility_date = "2024-04-07" +compatibility_flags = ["nodejs_compat"] + + +[env.production.vars]