chore: moved org routes over to hono

This commit is contained in:
John Yeo
2025-11-18 21:08:49 +00:00
parent 36c40d1622
commit ac1162140b
18 changed files with 399 additions and 439 deletions

View File

@@ -0,0 +1,28 @@
import { ErrCode, RecaseError } from "@autumn/shared";
import type { Context, Next } from "hono";
import type { HonoEnv } from "@/honoUtils/HonoEnv.js";
import { auth } from "@/utils/auth.js";
import { ADMIN_USER_IDs } from "@/utils/constants.js";
/**
* Admin auth middleware for Hono
* Validates that the user is an admin user
*/
export const adminAuthMiddleware = async (c: Context<HonoEnv>, next: Next) => {
const data = await auth.api.getSession({
headers: c.req.raw.headers,
});
if (
!ADMIN_USER_IDs.includes(data?.session?.userId || "") &&
!ADMIN_USER_IDs.includes(data?.session?.impersonatedBy || "")
) {
throw new RecaseError({
message: "Method not allowed",
code: ErrCode.InvalidRequest,
statusCode: 403,
});
}
await next();
};

View File

@@ -1,13 +1,11 @@
import { getRequestListener } from "@hono/node-server";
import { type Context, Hono } from "hono";
import { Hono } from "hono";
import { cors } from "hono/cors";
import type { ContentfulStatusCode } from "hono/utils/http-status";
import { vercelWebhookRouter } from "./external/vercel/vercelWebhookRouter.js";
import { handleConnectWebhook } from "./external/webhooks/connectWebhookRouter.js";
import { analyticsMiddleware } from "./honoMiddlewares/analyticsMiddleware.js";
import { apiVersionMiddleware } from "./honoMiddlewares/apiVersionMiddleware.js";
import { baseMiddleware } from "./honoMiddlewares/baseMiddleware.js";
import { betterAuthMiddleware } from "./honoMiddlewares/betterAuthMiddleware.js";
import { errorMiddleware } from "./honoMiddlewares/errorMiddleware.js";
import { orgConfigMiddleware } from "./honoMiddlewares/orgConfigMiddleware.js";
import { queryMiddleware } from "./honoMiddlewares/queryMiddleware.js";
@@ -19,18 +17,17 @@ import { handleHealthCheck } from "./honoUtils/handleHealthCheck.js";
import { balancesRouter } from "./internal/balances/balancesRouter.js";
import { billingRouter } from "./internal/billing/billingRouter.js";
import { cusRouter } from "./internal/customers/cusRouter.js";
import { internalCusRouter } from "./internal/customers/internalCusRouter.js";
import { entityRouter } from "./internal/entities/entityRouter.js";
import { featureRouter } from "./internal/features/featureRouter.js";
import { handleOAuthCallback } from "./internal/orgs/handlers/stripeHandlers/handleOAuthCallback.js";
import { honoOrgRouter } from "./internal/orgs/orgRouter.js";
import { platformBetaRouter } from "./internal/platform/platformBeta/platformBetaRouter.js";
import { internalProductRouter } from "./internal/products/internalProductRouter.js";
import {
honoProductBetaRouter,
honoProductRouter,
migrationRouter,
} from "./internal/products/productRouter.js";
import { internalRouter } from "./routers/internalRouter.js";
import { auth } from "./utils/auth.js";
const ALLOWED_ORIGINS = [
@@ -112,12 +109,6 @@ export const createHonoApp = () => {
app.use("/v1/*", refreshCacheMiddleware);
app.use("/v1/*", queryMiddleware());
// General org rate limiter for all other /v1/* routes
// app.use("/v1/*", generalRateLimiter);
app.get("/v1/test-incident", (c: Context<HonoEnv>) => {
return c.json({ message: "Hello, world!" }, 520 as ContentfulStatusCode);
});
app.route("v1", billingRouter);
app.route("v1", balancesRouter);
app.route("v1", migrationRouter);
@@ -134,11 +125,7 @@ export const createHonoApp = () => {
app.route("v1/platform/beta", platformBetaRouter);
app.route("v1/organization", honoOrgRouter);
// Internal/dashboard routes - use betterAuthMiddleware for session auth
app.use("/products/*", betterAuthMiddleware);
app.route("/products", internalProductRouter);
app.use("/customers/*", betterAuthMiddleware);
app.route("/customers", internalCusRouter);
app.route("", internalRouter);
app.onError(errorMiddleware);

View File

@@ -1,164 +1,9 @@
import { member, organizations, user } from "@autumn/shared";
import { and, desc, eq, gt, gte, ilike, inArray, lt, or } from "drizzle-orm";
import { Router } from "express";
import { handleFrontendReqError } from "@/utils/errorUtils.js";
import type { ExtendedRequest } from "@/utils/models/Request.js";
import { Hono } from "hono";
import type { HonoEnv } from "../../honoUtils/HonoEnv";
import { handleListAdminOrgs } from "./handleListAdminOrgs";
import { handleListAdminUsers } from "./handleListAdminUsers";
export const adminRouter: Router = Router();
export const honoAdminRouter = new Hono<HonoEnv>();
// adminRouter.post()
adminRouter.get("/users", async (req: any, res: any) => {
try {
const { db } = req as ExtendedRequest;
let { search, after, before } = req.query;
if (after) {
after = {
id: after.split(",")[0],
createdAt: new Date(after.split(",")[1]),
};
} else if (before) {
before = {
id: before.split(",")[0],
createdAt: new Date(before.split(",")[1]),
};
}
const users = await db
.select()
.from(user)
.where(
and(
search
? or(
ilike(user.email, `%${search as string}%`),
ilike(user.name, `%${search as string}%`),
ilike(user.id, `%${search as string}%`),
)
: undefined,
after
? or(
lt(user.createdAt, after.createdAt),
or(
and(
eq(user.createdAt, after.createdAt),
lt(user.id, after.id),
),
),
)
: undefined,
before
? or(
gte(user.createdAt, before.createdAt),
or(
and(
eq(user.createdAt, before.createdAt),
gt(user.id, before.id),
),
),
)
: undefined,
),
)
.orderBy(desc(user.createdAt), desc(user.id))
.limit(21);
res.json({
rows: users.slice(0, 20),
hasNextPage: users.length > 20,
});
} catch (error) {
handleFrontendReqError({
res,
req,
error,
action: "admin: search users",
});
}
});
adminRouter.get("/orgs", async (req: any, res: any) => {
try {
const { db } = req as ExtendedRequest;
let { search, after, before } = req.query;
if (after) {
after = {
id: after.split(",")[0],
createdAt: new Date(after.split(",")[1]),
};
} else if (before) {
before = {
id: before.split(",")[0],
createdAt: new Date(before.split(",")[1]),
};
}
const orgs = await db
.select()
.from(organizations)
.where(
and(
search
? or(
ilike(organizations.name, `%${search as string}%`),
ilike(organizations.id, `%${search as string}%`),
ilike(organizations.slug, `%${search as string}%`),
)
: undefined,
after
? or(
lt(organizations.createdAt, after.createdAt),
or(
and(
eq(organizations.createdAt, after.createdAt),
lt(organizations.id, after.id),
),
),
)
: undefined,
before
? or(
gte(organizations.createdAt, before.createdAt),
or(
and(
eq(organizations.createdAt, before.createdAt),
gt(organizations.id, before.id),
),
),
)
: undefined,
),
)
.orderBy(desc(organizations.createdAt), desc(organizations.id))
.limit(21);
const orgIds = orgs.map((org) => org.id);
const memberships = await db
.select()
.from(member)
.leftJoin(user, eq(member.userId, user.id))
.where(inArray(member.organizationId, orgIds));
res.json({
rows: orgs.slice(0, 20).map((org) => ({
...org,
users: memberships
.filter((membership) => membership.member.organizationId === org.id)
.map((membership) => membership.user),
})),
hasNextPage: orgs.length > 20,
});
} catch (error) {
handleFrontendReqError({
res,
req,
error,
action: "admin: search orgs",
});
}
});
honoAdminRouter.get("/users", ...handleListAdminUsers);
honoAdminRouter.get("/orgs", ...handleListAdminOrgs);

View File

@@ -0,0 +1,89 @@
import { member, organizations, user } from "@autumn/shared";
import { and, desc, eq, gt, gte, ilike, inArray, lt, or } from "drizzle-orm";
import { createRoute } from "../../honoMiddlewares/routeHandler";
export const handleListAdminOrgs = createRoute({
handler: async (c) => {
const ctx = c.get("ctx");
const { db } = ctx;
const { search, after: afterQuery, before: beforeQuery } = c.req.query();
let after,
before:
| {
id: string;
createdAt: Date;
}
| undefined;
if (afterQuery) {
after = {
id: afterQuery.split(",")[0],
createdAt: new Date(afterQuery.split(",")[1]),
};
} else if (beforeQuery) {
before = {
id: beforeQuery.split(",")[0],
createdAt: new Date(beforeQuery.split(",")[1]),
};
}
const orgs = await db
.select()
.from(organizations)
.where(
and(
search
? or(
ilike(organizations.name, `%${search as string}%`),
ilike(organizations.id, `%${search as string}%`),
ilike(organizations.slug, `%${search as string}%`),
)
: undefined,
after
? or(
lt(organizations.createdAt, after.createdAt),
or(
and(
eq(organizations.createdAt, after.createdAt),
lt(organizations.id, after.id),
),
),
)
: undefined,
before
? or(
gte(organizations.createdAt, before.createdAt),
or(
and(
eq(organizations.createdAt, before.createdAt),
gt(organizations.id, before.id),
),
),
)
: undefined,
),
)
.orderBy(desc(organizations.createdAt), desc(organizations.id))
.limit(21);
const orgIds = orgs.map((org) => org.id);
const memberships = await db
.select()
.from(member)
.leftJoin(user, eq(member.userId, user.id))
.where(inArray(member.organizationId, orgIds));
return c.json({
rows: orgs.slice(0, 20).map((org) => ({
...org,
users: memberships
.filter((membership) => membership.member.organizationId === org.id)
.map((membership) => membership.user),
})),
hasNextPage: orgs.length > 20,
});
},
});

View File

@@ -0,0 +1,76 @@
import { user } from "@autumn/shared";
import { and, desc, eq, gt, gte, ilike, lt, or } from "drizzle-orm";
import { createRoute } from "../../honoMiddlewares/routeHandler";
export const handleListAdminUsers = createRoute({
handler: async (c) => {
const ctx = c.get("ctx");
const { db } = ctx;
const { search, after: afterQuery, before: beforeQuery } = c.req.query();
let after,
before:
| {
id: string;
createdAt: Date;
}
| undefined;
if (afterQuery) {
after = {
id: afterQuery.split(",")[0],
createdAt: new Date(afterQuery.split(",")[1]),
};
} else if (beforeQuery) {
before = {
id: beforeQuery.split(",")[0],
createdAt: new Date(beforeQuery.split(",")[1]),
};
}
const users = await db
.select()
.from(user)
.where(
and(
search
? or(
ilike(user.email, `%${search as string}%`),
ilike(user.name, `%${search as string}%`),
ilike(user.id, `%${search as string}%`),
)
: undefined,
after
? or(
lt(user.createdAt, after.createdAt),
or(
and(
eq(user.createdAt, after.createdAt),
lt(user.id, after.id),
),
),
)
: undefined,
before
? or(
gte(user.createdAt, before.createdAt),
or(
and(
eq(user.createdAt, before.createdAt),
gt(user.id, before.id),
),
),
)
: undefined,
),
)
.orderBy(desc(user.createdAt), desc(user.id))
.limit(21);
return c.json({
rows: users.slice(0, 20),
hasNextPage: users.length > 20,
});
},
});

View File

@@ -8,7 +8,6 @@ import { analyticsRouter } from "../analytics/analyticsRouter.js";
import { attachRouter } from "../customers/attach/attachRouter.js";
import cancelRouter from "../customers/cancel/cancelRouter.js";
import { expressCusRouter } from "../customers/cusRouter.js";
import { handleGetOrg } from "../orgs/handlers/handleGetOrg.js";
import { platformRouter } from "../platform/platformLegacy/platformRouter.js";
import { expressProductRouter } from "../products/productRouter.js";
import { componentRouter } from "./components/componentRouter.js";
@@ -44,11 +43,6 @@ apiRouter.use("/platform", platformRouter);
apiRouter.use("/products", expressProductRouter);
apiRouter.use("/customers", expressCusRouter);
// // Used for tests...
// apiRouter.post("/organization/stripe", ...handleConnectStripe);
// apiRouter.delete("/organization/stripe", ...handleDeleteStripe);
apiRouter.get("/organization", handleGetOrg);
export { apiRouter };
// Features

View File

@@ -5,30 +5,26 @@ import { autumnHandler } from "autumn-js/express";
import { Router } from "express";
import rateLimit from "express-rate-limit";
import { createStripeCli } from "@/external/connect/createStripeCli.js";
import { withAuth, withOrgAuth } from "../middleware/authMiddleware.js";
import { adminRouter } from "./admin/adminRouter.js";
import { withAdminAuth } from "./admin/withAdminAuth.js";
import { withOrgAuth } from "../middleware/authMiddleware.js";
import { analyticsRouter } from "./analytics/internalAnalyticsRouter.js";
import { trmnlRouter } from "./api/trmnl/trmnlRouter.js";
import { cusRouter } from "./customers/internalCusRouter.js";
import { devRouter } from "./dev/devRouter.js";
import { InvoiceService } from "./invoices/InvoiceService.js";
import { onboardingRouter } from "./orgs/onboarding/onboardingRouter.js";
import { orgRouter } from "./orgs/orgRouter.js";
import { expressProductRouter } from "./products/internalProductRouter.js";
import { viewsRouter } from "./saved-views/savedViewsRouter.js";
import { userRouter } from "./users/userRouter.js";
const mainRouter: Router = Router();
mainRouter.get("", async (req: any, res) => {
res.status(200).json({ message: "Hello World" });
});
// mainRouter.get("", async (req: any, res) => {
// res.status(200).json({ message: "Hello World" });
// });
mainRouter.use("/admin", withAdminAuth, adminRouter);
mainRouter.use("/users", withAuth, userRouter);
// mainRouter.use("/users", withAuth, userRouter);
mainRouter.use("/onboarding", withOrgAuth, onboardingRouter);
mainRouter.use("/organization", withOrgAuth, orgRouter);
mainRouter.use("/products", withOrgAuth, expressProductRouter);
mainRouter.use("/dev", devRouter);
mainRouter.use("/customers", withOrgAuth, cusRouter);

View File

@@ -1,15 +1,14 @@
import { AppEnv, customers, ErrCode, type Organization } from "@autumn/shared";
import { and, eq } from "drizzle-orm";
import type { Response } from "express";
import {
deauthorizeAccount,
deleteConnectedAccount,
} from "@/external/connect/connectUtils.js";
import type { Logger } from "@/external/logtail/logtailUtils.js";
import { deleteSvixApp } from "@/external/svix/svixHelpers.js";
import RecaseError, { handleFrontendReqError } from "@/utils/errorUtils.js";
import type { ExtendedRequest } from "@/utils/models/Request.js";
import { deleteStripeWebhook } from "../orgUtils.js";
import RecaseError from "@/utils/errorUtils.js";
import { createRoute } from "../../../../honoMiddlewares/routeHandler.js";
import { deleteStripeWebhook } from "../../orgUtils.js";
const deleteSvixWebhooks = async ({
org,
@@ -98,9 +97,10 @@ export const deleteStripeAccounts = async ({
}
};
export const handleDeleteOrg = async (req: ExtendedRequest, res: Response) => {
try {
const { org, db, logger } = req;
export const handleDeleteOrg = createRoute({
handler: async (c) => {
const ctx = c.get("ctx");
const { org, db, logger } = ctx;
// 1. Check if any customers
const hasCustomers = await db.query.customers.findFirst({
@@ -134,15 +134,8 @@ export const handleDeleteOrg = async (req: ExtendedRequest, res: Response) => {
and(eq(customers.org_id, org.id), eq(customers.env, AppEnv.Sandbox)),
);
res.status(200).json({
return c.json({
message: "Org deleted",
});
} catch (error) {
handleFrontendReqError({
res,
error,
req,
action: "delete-org",
});
}
};
},
});

View File

@@ -0,0 +1,10 @@
import { createRoute } from "../../../../honoMiddlewares/routeHandler.js";
import { createOrgResponse } from "../../orgUtils.js";
export const handleGetOrg = createRoute({
handler: async (c) => {
const ctx = c.get("ctx");
const { org, env } = ctx;
return c.json(createOrgResponse({ org, env }));
},
});

View File

@@ -1,61 +0,0 @@
import { invitation, user as userTable } from "@autumn/shared";
import { and, eq, gt } from "drizzle-orm";
import type {
ExtendedRequest,
ExtendedResponse,
} from "@/utils/models/Request.js";
export const handleGetInvites = async (
req: ExtendedRequest,
res: ExtendedResponse,
) => {
try {
const { userId, db } = req;
const user = await db.query.user.findFirst({
where: eq(userTable.id, userId ?? ""),
});
const invites = await db.query.invitation.findMany({
where: and(
eq(invitation.status, "pending"),
eq(invitation.email, user?.email ?? ""),
gt(invitation.expiresAt, new Date()),
),
with: {
inviter: true,
organization: true,
},
});
// const joinRequests = await db
// .select({
// id: orgJoinRequests.id,
// organizationId: orgJoinRequests.organizationId,
// organizationName: organizations.name,
// role: orgJoinRequests.role,
// status: orgJoinRequests.status,
// createdAt: orgJoinRequests.createdAt,
// inviterName: user.name,
// inviterEmail: user.email,
// })
// .from(orgJoinRequests)
// .innerJoin(
// organizations,
// eq(orgJoinRequests.organizationId, organizations.id)
// )
// .innerJoin(user, eq(orgJoinRequests.inviterId, user.id))
// .where(
// and(
// eq(orgJoinRequests.userId, userId),
// eq(orgJoinRequests.status, "pending")
// )
// )
// .orderBy(orgJoinRequests.createdAt);
res.status(200).json({ invites });
} catch (error) {
console.error("Error fetching join requests:", error);
res.status(500).json({ message: "Internal server error" });
}
};

View File

@@ -1,26 +0,0 @@
import type {
ExtendedRequest,
ExtendedResponse,
} from "@/utils/models/Request.js";
import { routeHandler } from "@/utils/routerUtils.js";
import { OrgService } from "../OrgService.js";
import { createOrgResponse } from "../orgUtils.js";
export const handleGetOrg = async (req: any, res: any) =>
routeHandler({
req,
res,
action: "get org",
handler: async (req: ExtendedRequest, res: ExtendedResponse) => {
if (!req.orgId) {
res.status(400).json({
message: "Missing orgId",
});
return;
}
const org = await OrgService.getFromReq(req);
res.status(200).json(createOrgResponse({ org, env: req.env }));
},
});

View File

@@ -1,98 +0,0 @@
import { session as authSession, member } from "@autumn/shared";
import { and, eq } from "drizzle-orm";
import { handleFrontendReqError } from "@/utils/errorUtils.js";
import { OrgService } from "../OrgService.js";
export const handleGetOrgMembers = async (req: any, res: any) => {
try {
const { org, db } = req;
const orgId = org.id;
const memberships = await OrgService.getMembers({ db, orgId });
const invites = await OrgService.getInvites({ db, orgId });
res.status(200).json({
memberships,
invites,
});
} catch (error) {
console.error("Error getting org members:", error);
handleFrontendReqError({
req,
error,
res,
action: "get org members",
});
}
};
export const handleRemoveMember = async (req: any, res: any) => {
try {
const { org, db } = req;
const { memberId, userId } = req.body;
const orgId = org.id;
// First check if the member exists by memberId
let existingMember = await db.query.member.findFirst({
where: and(eq(member.id, memberId), eq(member.organizationId, orgId)),
});
if (!existingMember) {
// Try to find by userId as fallback
const memberByUserId = await db.query.member.findFirst({
where: and(eq(member.userId, userId), eq(member.organizationId, orgId)),
});
if (!memberByUserId) {
console.warn(
`Member not found by userId either: userId=${userId}, orgId=${orgId}`,
);
return res.status(404).json({
message: "Member not found in this organization",
code: "MEMBER_NOT_FOUND",
});
}
// Use the member found by userId
existingMember = memberByUserId;
}
// Remove member from database using the found member
await db
.delete(member)
.where(
and(eq(member.id, existingMember.id), eq(member.organizationId, orgId)),
);
// Revoke all sessions for this user in this organization
try {
await db
.delete(authSession)
.where(
and(
eq(authSession.userId, existingMember.userId),
eq(authSession.activeOrganizationId, orgId),
),
);
} catch (error) {
// Log but don't fail the request if session revocation fails
req.logger?.warn(
`Failed to revoke sessions for user ${existingMember.userId} in org ${orgId}:`,
error,
);
console.warn("Session revocation failed:", error);
}
res.status(200).json({
message: "Member removed successfully",
});
} catch (error) {
console.error("Error in handleRemoveMember:", error);
handleFrontendReqError({
req,
error,
res,
action: "remove member",
});
}
};

View File

@@ -1,32 +1,25 @@
import { ErrCode } from "@autumn/shared";
import { logger } from "@/external/logtail/logtailUtils.js";
import { getUploadUrl } from "@/external/supabase/storageUtils.js";
import RecaseError, { handleFrontendReqError } from "@/utils/errorUtils.js";
import RecaseError from "@/utils/errorUtils.js";
import { createRoute } from "../../../honoMiddlewares/routeHandler";
export const handleGetUploadUrl = async (req: any, res: any) => {
try {
const { org } = req;
export const handleGetUploadUrl = createRoute({
handler: async (c) => {
const ctx = c.get("ctx");
const { org } = ctx;
const path = `logo/${org.id}`;
if (!process.env.SUPABASE_URL || !process.env.SUPABASE_SERVICE_KEY) {
logger.warn("Supabase storage not set up");
res.status(400).json({
throw new RecaseError({
message: "Supabase storage not set up",
code: ErrCode.SupabaseNotFound,
statusCode: 400,
});
return;
}
const data = await getUploadUrl({ path });
res.status(200).json(data);
} catch (error) {
handleFrontendReqError({
req,
error,
res,
action: "get upload url",
});
}
};
return c.json(data);
},
});

View File

@@ -0,0 +1,28 @@
import { invitation, user as userTable } from "@autumn/shared";
import { and, eq, gt } from "drizzle-orm";
import { createRoute } from "../../../../honoMiddlewares/routeHandler";
export const handleGetInvites = createRoute({
handler: async (c) => {
const ctx = c.get("ctx");
const { userId, db } = ctx;
const user = await db.query.user.findFirst({
where: eq(userTable.id, userId ?? ""),
});
const invites = await db.query.invitation.findMany({
where: and(
eq(invitation.status, "pending"),
eq(invitation.email, user?.email ?? ""),
gt(invitation.expiresAt, new Date()),
),
with: {
inviter: true,
organization: true,
},
});
return c.json({ invites });
},
});

View File

@@ -0,0 +1,17 @@
import { createRoute } from "../../../../honoMiddlewares/routeHandler.js";
import { OrgService } from "../../OrgService.js";
export const handleGetOrgMembers = createRoute({
handler: async (c) => {
const ctx = c.get("ctx");
const { db, org } = ctx;
const memberships = await OrgService.getMembers({ db, orgId: org.id });
const invites = await OrgService.getInvites({ db, orgId: org.id });
return c.json({
memberships,
invites,
});
},
});

View File

@@ -0,0 +1,70 @@
import { session as authSession, member, RecaseError } from "@autumn/shared";
import { and, eq } from "drizzle-orm";
import { z } from "zod/v4";
import { createRoute } from "../../../../honoMiddlewares/routeHandler";
export const handleRemoveMember = createRoute({
body: z.object({
memberId: z.string(),
userId: z.string(),
}),
handler: async (c) => {
const ctx = c.get("ctx");
const { memberId, userId } = c.req.valid("json");
const { org, db } = ctx;
// First check if the member exists by memberId
let existingMember = await db.query.member.findFirst({
where: and(eq(member.id, memberId), eq(member.organizationId, org.id)),
});
if (!existingMember) {
// Try to find by userId as fallback
const memberByUserId = await db.query.member.findFirst({
where: and(
eq(member.userId, userId),
eq(member.organizationId, org.id),
),
});
if (!memberByUserId) {
throw new RecaseError({
message: "Member not found in this organization",
code: "MEMBER_NOT_FOUND",
statusCode: 404,
});
}
// Use the member found by userId
existingMember = memberByUserId;
}
// Remove member from database using the found member
await db
.delete(member)
.where(
and(
eq(member.id, existingMember.id),
eq(member.organizationId, org.id),
),
);
// Revoke all sessions for this user in this organization
try {
await db
.delete(authSession)
.where(
and(
eq(authSession.userId, existingMember.userId),
eq(authSession.activeOrganizationId, org.id),
),
);
} catch (error) {
console.warn(`Session revocation failed: ${error}`);
}
return c.json({
message: "Member removed successfully",
});
},
});

View File

@@ -1,13 +1,7 @@
import express, { type Router } from "express";
import { Hono } from "hono";
import type { HonoEnv } from "@/honoUtils/HonoEnv.js";
import { handleDeleteOrg } from "./handlers/handleDeleteOrg.js";
import { handleGetInvites } from "./handlers/handleGetInvites.js";
import { handleGetOrg } from "./handlers/handleGetOrg.js";
import {
handleGetOrgMembers,
handleRemoveMember,
} from "./handlers/handleGetOrgMembers.js";
import { handleDeleteOrg } from "./handlers/crudHandlers/handleDeleteOrg.js";
import { handleGetOrg } from "./handlers/crudHandlers/handleGetOrg.js";
import { handleGetUploadUrl } from "./handlers/handleGetUploadUrl.js";
import { handleResetDefaultAccount } from "./handlers/handleResetDefaultAccount.js";
import { handleUpdateOrg } from "./handlers/handleUpdateOrg.js";
@@ -15,30 +9,25 @@ import {
handleGetVercelSink,
handleUpsertVercelConfig,
} from "./handlers/handleVercelConfig.js";
import { handleGetInvites } from "./handlers/memberHandlers/handleGetInvites.js";
import { handleGetOrgMembers } from "./handlers/memberHandlers/handleGetOrgMembers.js";
import { handleRemoveMember } from "./handlers/memberHandlers/handleRemoveMember.js";
import { handleConnectStripe } from "./handlers/stripeHandlers/handleConnectStripe.js";
import { handleDeleteStripe } from "./handlers/stripeHandlers/handleDeleteStripe.js";
import { handleGetOAuthUrl } from "./handlers/stripeHandlers/handleGetOAuthUrl.js";
import { handleGetStripeAccount } from "./handlers/stripeHandlers/handleGetStripeAccount.js";
export const orgRouter: Router = express.Router();
orgRouter.get("/members", handleGetOrgMembers);
orgRouter.post("/remove-member", handleRemoveMember);
orgRouter.get("/upload_url", handleGetUploadUrl);
orgRouter.get("/invites", handleGetInvites as any);
orgRouter.delete("", handleDeleteOrg as any);
export const internalOrgRouter = new Hono<HonoEnv>();
orgRouter.delete("/delete-user", async (req: any, res) => {
res.status(200).json({
message: "User deleted",
});
});
orgRouter.get("", handleGetOrg);
// orgRouter.post("/stripe", handleConnectStripe);
internalOrgRouter.get("", ...handleGetOrg);
internalOrgRouter.delete("", ...handleDeleteOrg);
internalOrgRouter.get("/members", ...handleGetOrgMembers);
internalOrgRouter.post("/remove-member", ...handleRemoveMember);
internalOrgRouter.get("/upload_url", ...handleGetUploadUrl);
internalOrgRouter.get("/invites", ...handleGetInvites);
export const honoOrgRouter = new Hono<HonoEnv>();
honoOrgRouter.get("", ...handleGetOrg);
honoOrgRouter.patch("", ...handleUpdateOrg);
honoOrgRouter.get("/stripe", ...handleGetStripeAccount);
honoOrgRouter.delete("/stripe", ...handleDeleteStripe);

View File

@@ -0,0 +1,30 @@
import { Hono } from "hono";
import { adminAuthMiddleware } from "../honoMiddlewares/adminAuthMiddleware";
import { analyticsMiddleware } from "../honoMiddlewares/analyticsMiddleware";
import { apiVersionMiddleware } from "../honoMiddlewares/apiVersionMiddleware";
import { betterAuthMiddleware } from "../honoMiddlewares/betterAuthMiddleware";
import { orgConfigMiddleware } from "../honoMiddlewares/orgConfigMiddleware";
import { queryMiddleware } from "../honoMiddlewares/queryMiddleware";
import { refreshCacheMiddleware } from "../honoMiddlewares/refreshCacheMiddleware";
import type { HonoEnv } from "../honoUtils/HonoEnv";
import { honoAdminRouter } from "../internal/admin/adminRouter";
import { internalCusRouter } from "../internal/customers/internalCusRouter";
import { internalOrgRouter } from "../internal/orgs/orgRouter";
import { internalProductRouter } from "../internal/products/internalProductRouter";
export const internalRouter = new Hono<HonoEnv>();
// Internal/dashboard routes - use betterAuthMiddleware for session auth
internalRouter.use("*", betterAuthMiddleware);
internalRouter.use("*", orgConfigMiddleware);
internalRouter.use("*", apiVersionMiddleware);
internalRouter.use("*", analyticsMiddleware);
internalRouter.use("*", refreshCacheMiddleware);
internalRouter.use("*", queryMiddleware());
internalRouter.use("/admin/*", adminAuthMiddleware);
internalRouter.route("admin", honoAdminRouter);
internalRouter.route("organization", internalOrgRouter);
internalRouter.route("/products", internalProductRouter);
internalRouter.route("/customers", internalCusRouter);