feat: Change logs a lil bit

This commit is contained in:
Wanjohi
2025-10-25 23:57:15 +03:00
parent 687bc47870
commit 815246afc0
10 changed files with 341 additions and 100 deletions

View File

@@ -13,7 +13,7 @@
},
"dependencies": {
"@openauthjs/openauth": "catalog:",
"hono": "^4.10.1",
"hono": "catalog:",
"hono-openapi": "^1.1.0",
"zod": "catalog:"
}

View File

@@ -1,69 +1,48 @@
import { subjects } from "../subjects";
import { MiddlewareHandler } from "hono";
import { Actor } from "@nestri/core/actor";
import { Api } from "@nestri/core/api/index";
import { Hono } from "hono";
import { auth } from "./utils/auth";
import { logger } from "hono/logger";
import { Log } from "@nestri/core/utils/log";
import { createClient } from "@openauthjs/openauth/client";
import { HTTPException } from "hono/http-exception";
import { VisibleError, ErrorCodes } from "@nestri/core/error";
const client = createClient({
clientID: "api",
issuer: process.env.AUTH_URL,
subjects,
});
const log = Log.create({ service: "api" });
const log = Log.create({ namespace: "api" });
export const app = new Hono();
app
.use(logger())
.use(async (c, next) => {
c.header("Cache-Control", "no-store");
return next();
})
.use(auth);
const auth: MiddlewareHandler = async (c, next) => {
const authHeader =
c.req.query("authorization") ?? c.req.header("authorization");
if (authHeader) {
const match = authHeader.match(/^Bearer (.+)$/);
if (!match || !match[1]) {
throw new VisibleError(
"authentication",
ErrorCodes.Authentication.UNAUTHORIZED,
"Bearer token not found or improperly formatted",
);
}
const bearerToken = match[1];
if (bearerToken?.startsWith("nst_")) {
const token = await Api.Personal.fromToken(bearerToken);
if (!token)
throw new VisibleError(
"authentication",
ErrorCodes.Authentication.INVALID_TOKEN,
"Invalid personal access token",
);
return Actor.provide(
"token",
{
teamID: token.teamID,
tokenID: token.id,
},
next,
);
}
const result = await client.verify(bearerToken!);
if (result.err)
throw new VisibleError(
"authentication",
ErrorCodes.Authentication.INVALID_TOKEN,
"Invalid bearer token",
);
if (result.subject.type === "team") {
return Actor.provide(
"team",
{
email: result.subject.properties.email,
teamID: result.subject.properties.teamID,
},
next,
);
}
app.onError((error, c) => {
// Handle our custom VisibleError
if (error instanceof VisibleError) {
return c.json(error.toResponse(), error.statusCode());
}
return Actor.provide("public", {}, next);
};
// Handle HTTP exceptions
if (error instanceof HTTPException) {
console.error("http error:", error);
return c.json(
{
type: "validation",
code: ErrorCodes.Validation.INVALID_PARAMETER,
message: "Invalid request",
},
400,
);
}
// Handle any other errors as internal server errors
log.error("Unhandled API error:", { error });
return c.json(
{
type: "internal",
code: ErrorCodes.Server.INTERNAL_ERROR,
message: "Internal server error",
},
500,
);
});

View File

@@ -0,0 +1,67 @@
import { subjects } from "@/subjects";
import { MiddlewareHandler } from "hono";
import { Actor } from "@nestri/core/actor";
import { Api } from "@nestri/core/api/index";
import { createClient } from "@openauthjs/openauth/client";
import { VisibleError, ErrorCodes } from "@nestri/core/error";
const client = createClient({
clientID: "api",
issuer: process.env.AUTH_URL,
subjects,
});
export const auth: MiddlewareHandler = async (c, next) => {
const authHeader =
c.req.query("authorization") ?? c.req.header("authorization");
if (authHeader) {
const match = authHeader.match(/^Bearer (.+)$/);
if (!match || !match[1]) {
throw new VisibleError(
"authentication",
ErrorCodes.Authentication.UNAUTHORIZED,
"Bearer token not found or improperly formatted",
);
}
const bearerToken = match[1];
if (bearerToken?.startsWith("nst_")) {
const token = await Api.Personal.fromToken(bearerToken);
if (!token)
throw new VisibleError(
"authentication",
ErrorCodes.Authentication.INVALID_TOKEN,
"Invalid personal access token",
);
return Actor.provide(
"token",
{
teamID: token.teamID,
tokenID: token.id,
},
next,
);
}
const result = await client.verify(bearerToken!);
if (result.err)
throw new VisibleError(
"authentication",
ErrorCodes.Authentication.INVALID_TOKEN,
"Invalid bearer token",
);
if (result.subject.type === "team") {
return Actor.provide(
"team",
{
email: result.subject.properties.email,
teamID: result.subject.properties.teamID,
},
next,
);
}
}
return Actor.provide("public", {}, next);
};

View File

@@ -1,6 +1,7 @@
import { z } from "zod/v4";
import { RedisClient } from "bun";
import { subjects } from "../subjects.js";
import { logger } from "hono/logger";
import { subjects } from "@/subjects.js";
import { issuer } from "@openauthjs/openauth";
import { Team } from "@nestri/core/team/index";
import { RedisStorage } from "./src/storage.js";
@@ -62,12 +63,10 @@ const app = issuer({
async allow(input) {
const url = new URL(input.redirectURI);
return (
url.hostname.endsWith("localhost") ||
url.hostname.endsWith("nestri.io") ||
url.hostname.endsWith("console.nestri.io")
url.hostname.endsWith("localhost") || url.hostname.endsWith("nestri.io")
);
},
});
}).use(logger());
export default {
port: 3000,