From a09d11e8e44b56b7c3c1938c8d51f192d20fc87c Mon Sep 17 00:00:00 2001 From: Dominic Ferrando Date: Fri, 10 Jul 2026 14:41:54 -0400 Subject: [PATCH] Api cleanup --- apps/api/src/scripts/register-webhooks.ts | 6 +- apps/api/src/server.ts | 99 ++++++++++--------- .../(app)/commerce/products/+page.svelte | 8 +- 3 files changed, 57 insertions(+), 56 deletions(-) diff --git a/apps/api/src/scripts/register-webhooks.ts b/apps/api/src/scripts/register-webhooks.ts index 5eb0130..88dd790 100644 --- a/apps/api/src/scripts/register-webhooks.ts +++ b/apps/api/src/scripts/register-webhooks.ts @@ -1,10 +1,10 @@ import { Printful, PrintfulClient, PrintfulError, Webflow, WebflowClient, WebflowError } from "@blade-and-brawn/commerce"; import { env } from "../util"; -const BASE_URL = "http://dev.api.bladeandbrawn.com"; +const DOMAIN = "dev.api.bladeandbrawn.com"; -const PRINTFUL_WEBHOOK_URL = `${BASE_URL}/webhook/printful`; -const WEBFLOW_WEBHOOK_URL = `${BASE_URL}/webhook/webflow`; +const PRINTFUL_WEBHOOK_URL = `http://${DOMAIN}/webhooks/printful`; +const WEBFLOW_WEBHOOK_URL = `https://${DOMAIN}/webhooks/webflow`; function printError(err: unknown): never { if (err instanceof WebflowError || err instanceof PrintfulError) diff --git a/apps/api/src/server.ts b/apps/api/src/server.ts index 0f17776..d9c100c 100644 --- a/apps/api/src/server.ts +++ b/apps/api/src/server.ts @@ -75,8 +75,10 @@ export const app = new Elysia() }) .onAfterResponse(({ request, status, path }) => { - const skip: Record = { "/products/sync/": ["GET"] }; - if (env.NODE_ENV === "development" && skip[path]?.includes(request.method)) return; + if (env.NODE_ENV === "development") { + const skip: Record = { "/commerce/products/sync/": ["GET"] }; + if (skip[path]?.includes(request.method)) return; + } log.info({ method: request.method, @@ -107,30 +109,29 @@ export const app = new Elysia() }, { body: t.Object({ password: t.String() }) }) // CALCULATOR - .group("/calculator", - (app) => app - // Non-authenticated - .post("/calculate", async ({ body }) => { - return { levels: await s.Calculator.calculate(body.player, body.activityPerformances) }; - }, { - body: t.Object({ - player: PlayerSchema, - activityPerformances: t.Array(ActivityPerformanceSchema) - }), - }) - .resolve(async ({ jwt, cookie: { auth } }) => { - const token = auth.value && await jwt.verify(auth.value); - if (!token || !token.sessionId) throw status(401, "Unauthorized"); - return { sessionId: token.sessionId.toString() }; - }) - .get("/standards/config", async () => { - return await s.Calculator.Standards.Config.get(); - }) - .post("/standards/config/switch", async ({ body: { standardsConfigId } }) => { - await s.Calculator.Standards.Config.switch(standardsConfigId); - }, { - body: t.Object({ standardsConfigId: t.String() }) - }) + .group("/calculator", (app) => app + // Non-authenticated + .post("/calculate", async ({ body }) => { + return { levels: await s.Calculator.calculate(body.player, body.activityPerformances) }; + }, { + body: t.Object({ + player: PlayerSchema, + activityPerformances: t.Array(ActivityPerformanceSchema) + }), + }) + .resolve(async ({ jwt, cookie: { auth } }) => { + const token = auth.value && await jwt.verify(auth.value); + if (!token || !token.sessionId) throw status(401, "Unauthorized"); + return { sessionId: token.sessionId.toString() }; + }) + .get("/standards/config", async () => { + return await s.Calculator.Standards.Config.get(); + }) + .post("/standards/config/switch", async ({ body: { standardsConfigId } }) => { + await s.Calculator.Standards.Config.switch(standardsConfigId); + }, { + body: t.Object({ standardsConfigId: t.String() }) + }) ) .group("/standards", (app) => app .resolve(async ({ jwt, cookie: { auth } }) => { @@ -177,15 +178,15 @@ export const app = new Elysia() ) // COMMERCE - .group("/products", - (app) => app - .resolve(async ({ jwt, cookie: { auth } }) => { - const token = auth.value && await jwt.verify(auth.value); - if (!token || !token.sessionId) throw status(401, "Unauthorized"); - return { sessionId: token.sessionId.toString() }; - }) - .group("/sync", (app) => - app + .group("/commerce", (app) => app + .group("/products", + (app) => app + .resolve(async ({ jwt, cookie: { auth } }) => { + const token = auth.value && await jwt.verify(auth.value); + if (!token || !token.sessionId) throw status(401, "Unauthorized"); + return { sessionId: token.sessionId.toString() }; + }) + .group("/sync", (app) => app // Sync status .get("/", async ({ sessionId }) => { const latestSync = await s.Commerce.Sync.getLatest(sessionId); @@ -205,24 +206,24 @@ export const app = new Elysia() } }); }, { params: t.Object({ pProductId: t.Optional(t.Numeric()) }) }), - ) - .get("/:pProductId", async ({ params: { pProductId } }) => { - const pProduct = await s.Commerce.Printful.Products.get(pProductId); - if (!pProduct) throw new NotFoundError("Missing printful product"); + ) + .get("/:pProductId", async ({ params: { pProductId } }) => { + const pProduct = await s.Commerce.Printful.Products.get(pProductId); + if (!pProduct) throw new NotFoundError("Missing printful product"); - const wProductId = pProduct.sync_product.external_id.split("-")[0]; - if (!wProductId) throw new NotFoundError("Missing webflow product ID"); + const wProductId = pProduct.sync_product.external_id.split("-")[0]; + if (!wProductId) throw new NotFoundError("Missing webflow product ID"); - const wProduct = await s.Commerce.Webflow.Products.get(wProductId); + const wProduct = await s.Commerce.Webflow.Products.get(wProductId); - return { pProduct, wProduct }; - }, { - params: t.Object({ pProductId: t.Numeric() }) - }) - ) + return { pProduct, wProduct }; + }, { + params: t.Object({ pProductId: t.Numeric() }) + }) + )) // WEBHOOKS - .post("/webhook/printful", async ({ body }) => { + .post("/webhooks/printful", async ({ body }) => { // https://webflow.com/integrations/printful const payload = body as Printful.Webhook.EventPayload; @@ -267,7 +268,7 @@ export const app = new Elysia() log.warn({ type: (payload as any).type }, "printful webhook: unhandled event type"); } }) - .post("/webhook/webflow", async ({ request, body }) => { + .post("/webhooks/webflow", async ({ request, body }) => { if (!s.Commerce.Webflow.Util.verifyWebflowSignature(request, body)) throw status(400, "Invalid signature"); diff --git a/apps/portal/src/routes/(app)/commerce/products/+page.svelte b/apps/portal/src/routes/(app)/commerce/products/+page.svelte index 2a8129b..e914ca6 100644 --- a/apps/portal/src/routes/(app)/commerce/products/+page.svelte +++ b/apps/portal/src/routes/(app)/commerce/products/+page.svelte @@ -14,7 +14,7 @@ return this.status === "active" || this.status === "queued"; }, poll: async function () { - const res = await api.products.sync.get(); + const res = await api.commerce.products.sync.get(); if (res.error) { synchronizer.status = "none"; synchronizer.syncingPProductIds = []; @@ -32,11 +32,11 @@ }, syncAll: async () => { synchronizer.startPolling(); - await api.products.sync.post(); + await api.commerce.products.sync.post(); }, sync: async (pProductId: number) => { synchronizer.startPolling(); - await api.products.sync({ pProductId }).post(); + await api.commerce.products.sync({ pProductId }).post(); }, }); @@ -86,7 +86,7 @@