mirror of
https://github.com/YuzuZensai/Pien-Studio.git
synced 2026-09-02 14:18:35 +00:00
✨ feat: initial app
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "@pien-studio/api",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "bun --watch src/index.ts",
|
||||
"build": "bun build src/index.ts --outdir dist",
|
||||
"start": "bun run dist/index.js",
|
||||
"test": "vitest run",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pien-studio/types": "workspace:*",
|
||||
"elysia": "^1.1.25",
|
||||
"zod": "^4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bun-types": "latest",
|
||||
"typescript": "^6.0.3",
|
||||
"vitest": "^4.1.5"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { createApp } from "./index";
|
||||
|
||||
describe("api endpoints", () => {
|
||||
it("returns root route info", async () => {
|
||||
const app = createApp();
|
||||
const response = await app.handle(new Request("http://localhost/"));
|
||||
const body = await response.json();
|
||||
expect(response.status).toBe(200);
|
||||
expect(body.name).toBe("pien-api");
|
||||
});
|
||||
|
||||
it("returns healthy status", async () => {
|
||||
const app = createApp();
|
||||
const response = await app.handle(new Request("http://localhost/health"));
|
||||
const body = await response.json();
|
||||
expect(response.status).toBe(200);
|
||||
expect(body.ok).toBe(true);
|
||||
});
|
||||
|
||||
it("returns token for valid device payload", async () => {
|
||||
const app = createApp();
|
||||
const response = await app.handle(
|
||||
new Request("http://localhost/auth/device", {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({ deviceId: "dev1234", locale: "en" }),
|
||||
}),
|
||||
);
|
||||
const body = await response.json();
|
||||
expect(response.status).toBe(200);
|
||||
expect(body.token).toBe("dev_dev1234");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Elysia } from "elysia";
|
||||
import { DeviceSessionSchema } from "@pien-studio/types";
|
||||
|
||||
export function createApp() {
|
||||
return new Elysia()
|
||||
.get("/", () => ({
|
||||
name: "pien-api",
|
||||
status: "ok",
|
||||
}))
|
||||
.get("/health", () => ({ ok: true, service: "pien-api" }))
|
||||
.post("/auth/device", ({ body }) => {
|
||||
const parsed = DeviceSessionSchema.safeParse(body);
|
||||
if (!parsed.success) {
|
||||
return new Response(JSON.stringify({ error: "invalid_device_payload" }), {
|
||||
status: 400,
|
||||
});
|
||||
}
|
||||
return {
|
||||
token: `dev_${parsed.data.deviceId}`,
|
||||
scope: "local-sync",
|
||||
};
|
||||
})
|
||||
.get("/sync/bootstrap", () => ({
|
||||
replication: {
|
||||
pull: "/sync/pull",
|
||||
push: "/sync/push",
|
||||
strategy: "couch-compatible",
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
if (import.meta.main) {
|
||||
createApp().listen(4000);
|
||||
console.log("pien api listening on http://localhost:4000");
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"types": ["bun-types"]
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
environment: "node",
|
||||
include: ["**/*.test.ts"],
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user