Skip to content

Commit

Permalink
feat: add validation to context and to creation of shopifyClient
Browse files Browse the repository at this point in the history
  • Loading branch information
Yokaito committed Nov 21, 2023
1 parent c72fdbc commit 1129602
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 4 deletions.
27 changes: 26 additions & 1 deletion packages/server/src/integrations/shopify/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { ensureStartsWith } from "../../utils";
import type { ExtractVariables } from "../../utils/types";
import { isShopifyError } from "./type-guards";
Expand All @@ -22,12 +24,35 @@ type ShopifyResponse<T> = {
body: T;
};

const schemaShopifyClient = z.object({
key: z.string(),
endpoint: z.string().regex(/^[a-z0-9-]+\.myshopify\.com$/),
version: z.nativeEnum(versions),
});

export class ShopifyClient {
constructor(
private readonly key: string,
private readonly endpoint: string,
private readonly version: keyof typeof versions = "2023-01"
) {}
) {
const isShopifyClient = schemaShopifyClient.safeParse({
key,
endpoint,
version,
});

if (!isShopifyClient.success) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: isShopifyClient.error.message,
});
}

this.key = isShopifyClient.data.key;
this.endpoint = isShopifyClient.data.endpoint;
this.version = isShopifyClient.data.version;
}

fetch = async <T>({
cache = "force-cache",
Expand Down
39 changes: 39 additions & 0 deletions packages/server/src/middlewares/validateContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { ShopifyClient } from "../integrations/shopify";
import { t } from "../trpc";

const schemaShopify = z.object({
integrations: z.object({
shopify: z.object({
client: z.instanceof(ShopifyClient),
}),
}),
});

export const validatedContext = t.middleware(async (opts) => {
const { integrations } = opts.ctx;

const isContextShopify = schemaShopify.safeParse({
integrations: {
shopify: {
client: integrations?.shopify?.client,
},
},
});

if (!isContextShopify.success) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: isContextShopify.error.message,
});
}

return opts.next({
ctx: {
...opts.ctx,
},
});
});

export const validatedProcedure = t.procedure.use(validatedContext);
5 changes: 3 additions & 2 deletions packages/server/src/routers/product/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import {
ShopifyProductOperation,
getProductQuery,
} from "../../integrations/shopify/queries/product";
import { createTRPCRouter, publicProcedure } from "../../trpc";
import { validatedProcedure } from "../../middlewares/validateContext";
import { createTRPCRouter } from "../../trpc";
import { reshapeProduct } from "../../utils/reshapes";

export const productRouter = createTRPCRouter({
getProductByHandle: publicProcedure
getProductByHandle: validatedProcedure
.input(
z.object({
handle: z.string(),
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/trpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export const createTRPCContext = (opts: {
* errors on the backend.
*/

const t = initTRPC.context<typeof createTRPCContext>().create({
export const t = initTRPC.context<typeof createTRPCContext>().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
Expand Down

0 comments on commit 1129602

Please sign in to comment.