diff --git a/apps/api/src/server.ts b/apps/api/src/server.ts index 66ef883..e21a14d 100644 --- a/apps/api/src/server.ts +++ b/apps/api/src/server.ts @@ -35,6 +35,21 @@ const s = (() => { return { Standards, Calculator, Commerce }; })(); +// PLUGINS +// ----------------------- +const authPlugin = new Elysia({ name: "auth" }) + .use(jwt({ name: "jwt", secret: env.AUTH_SECRET })) + .guard({ cookie: t.Cookie({ auth: t.Optional(t.String()) }) }) + .macro({ + auth: { + async resolve({ 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() }; + } + } + }); + // ELYSIA // ----------------------- export const app = new Elysia() @@ -50,7 +65,9 @@ export const app = new Elysia() "http://localhost:5173", ], }), - ).use(jwt({ name: "jwt", secret: env.AUTH_SECRET })) + ) + .guard({ cookie: t.Cookie({ auth: t.Optional(t.String()) }) }) + .use(authPlugin) .error({ PrintfulError, @@ -91,7 +108,6 @@ export const app = new Elysia() status }, "request"); }) - .guard({ cookie: t.Cookie({ auth: t.Optional(t.String()) }) }) .get("/", () => ({ status: "ok" })) .get("/health", () => ({ status: "ok" })) @@ -124,11 +140,8 @@ export const app = new Elysia() 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() }; - }) + // Authenticated + .guard({ auth: true }) .get("/standards/config", async () => { return await s.Calculator.Standards.Config.get(); }) @@ -138,12 +151,7 @@ export const app = new Elysia() body: t.Object({ standardsConfigId: t.String() }) }) ) - .group("/standards", (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("/standards", { auth: true }, (app) => app .post("/configs", async ({ body: { name, datasetId, params } }) => { return await s.Standards.Configs.create(name, datasetId, params); }, { @@ -184,47 +192,41 @@ export const app = new Elysia() // COMMERCE .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("/products", { auth: true }, (app) => app + .group("/sync", (app) => app + // Sync status + .get("/", async ({ sessionId }) => { + const latestSyncState = await s.Commerce.ProductSync.getLatestSyncState(sessionId); + if (!latestSyncState) throw new NotFoundError("No product sync found for the provided session"); + return latestSyncState; }) - .group("/sync", (app) => app - // Sync status - .get("/", async ({ sessionId }) => { - const latestSyncState = await s.Commerce.ProductSync.getLatestSyncState(sessionId); - if (!latestSyncState) throw new NotFoundError("No product sync found for the provided session"); - return latestSyncState; - }) - // Run sync - .post("/:pProductId?", async ({ params: { pProductId }, sessionId }) => { - await s.Commerce.ProductSync.Queue.enqueue({ - type: "product_sync_update", - source: "portal", - payload: { - session: { id: sessionId, name: "Portal" }, - filter: { - pProductIds: pProductId ? [pProductId] : undefined - } + // Run sync + .post("/:pProductId?", async ({ params: { pProductId }, sessionId }) => { + await s.Commerce.ProductSync.Queue.enqueue({ + type: "product_sync_update", + source: "portal", + payload: { + session: { id: sessionId, name: "Portal" }, + filter: { + pProductIds: pProductId ? [pProductId] : undefined } - }); - }, { 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"); + } + }); + }, { 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"); - 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