From c48fbd57d7b5b8cc5374454f0c3efe6bc2b64605 Mon Sep 17 00:00:00 2001 From: Vandivier Date: Sun, 18 Feb 2024 22:35:42 -0500 Subject: [PATCH 1/2] feat: perm harden apis --- src/checklist-items/mutations/createChecklistItem.ts | 2 +- src/checklist-items/mutations/deleteChecklistItem.ts | 2 +- src/checklist-items/mutations/updateChecklistItem.ts | 2 +- src/checklists/mutations/createChecklist.ts | 2 +- src/checklists/mutations/deleteChecklist.ts | 2 +- src/checklists/mutations/updateChecklist.ts | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/checklist-items/mutations/createChecklistItem.ts b/src/checklist-items/mutations/createChecklistItem.ts index 616b102d..e95fb0d0 100644 --- a/src/checklist-items/mutations/createChecklistItem.ts +++ b/src/checklist-items/mutations/createChecklistItem.ts @@ -4,7 +4,7 @@ import { CreateChecklistItemSchema } from "../schemas" export default resolver.pipe( resolver.zod(CreateChecklistItemSchema), - resolver.authorize(), + resolver.authorize(["admin"]), async (input) => { const checklistItem = await db.checklistItem.create({ data: input }) diff --git a/src/checklist-items/mutations/deleteChecklistItem.ts b/src/checklist-items/mutations/deleteChecklistItem.ts index fea839c0..af1ca706 100644 --- a/src/checklist-items/mutations/deleteChecklistItem.ts +++ b/src/checklist-items/mutations/deleteChecklistItem.ts @@ -4,7 +4,7 @@ import { DeleteChecklistItemSchema } from "../schemas" export default resolver.pipe( resolver.zod(DeleteChecklistItemSchema), - resolver.authorize(), + resolver.authorize(["admin"]), async ({ id }) => { // TODO: in multi-tenant app, you must add validation to ensure correct tenant const checklistItem = await db.checklistItem.deleteMany({ where: { id } }) diff --git a/src/checklist-items/mutations/updateChecklistItem.ts b/src/checklist-items/mutations/updateChecklistItem.ts index b120e9d9..a4525e5f 100644 --- a/src/checklist-items/mutations/updateChecklistItem.ts +++ b/src/checklist-items/mutations/updateChecklistItem.ts @@ -4,7 +4,7 @@ import { UpdateChecklistItemSchema } from "../schemas" export default resolver.pipe( resolver.zod(UpdateChecklistItemSchema), - resolver.authorize(), + resolver.authorize(["admin"]), async ({ id, ...data }) => { const checklistItem = await db.checklistItem.update({ where: { id }, diff --git a/src/checklists/mutations/createChecklist.ts b/src/checklists/mutations/createChecklist.ts index a89e90e7..4db1b1e7 100644 --- a/src/checklists/mutations/createChecklist.ts +++ b/src/checklists/mutations/createChecklist.ts @@ -4,7 +4,7 @@ import { CreateChecklistSchema } from "../schemas" export default resolver.pipe( resolver.zod(CreateChecklistSchema), - resolver.authorize(), + resolver.authorize(["admin"]), async (input) => { const checklist = await db.checklist.create({ data: input }) diff --git a/src/checklists/mutations/deleteChecklist.ts b/src/checklists/mutations/deleteChecklist.ts index 26de88e7..eff45159 100644 --- a/src/checklists/mutations/deleteChecklist.ts +++ b/src/checklists/mutations/deleteChecklist.ts @@ -4,7 +4,7 @@ import { DeleteChecklistSchema } from "../schemas" export default resolver.pipe( resolver.zod(DeleteChecklistSchema), - resolver.authorize(), + resolver.authorize(["admin"]), async ({ id }) => { // TODO: in multi-tenant app, you must add validation to ensure correct tenant const checklist = await db.checklist.deleteMany({ where: { id } }) diff --git a/src/checklists/mutations/updateChecklist.ts b/src/checklists/mutations/updateChecklist.ts index 0299ea45..868e9c25 100644 --- a/src/checklists/mutations/updateChecklist.ts +++ b/src/checklists/mutations/updateChecklist.ts @@ -4,7 +4,7 @@ import { UpdateChecklistSchema } from "../schemas" export default resolver.pipe( resolver.zod(UpdateChecklistSchema), - resolver.authorize(), + resolver.authorize(["admin"]), async ({ id, ...data }) => { // TODO: in multi-tenant app, you must add validation to ensure correct tenant const checklist = await db.checklist.update({ where: { id }, data }) From 74a5fb93f27295ce912bc915494fd0b073f1f734 Mon Sep 17 00:00:00 2001 From: Vandivier Date: Sun, 18 Feb 2024 22:50:01 -0500 Subject: [PATCH 2/2] feat: rm store and admin -> ADMIN --- package-lock.json | 100 ----------------- package.json | 1 - public/sitemap.xml | 5 - .../mutations/createChecklistItem.ts | 2 +- .../mutations/deleteChecklistItem.ts | 2 +- .../mutations/updateChecklistItem.ts | 2 +- src/checklists/mutations/createChecklist.ts | 2 +- src/checklists/mutations/deleteChecklist.ts | 2 +- src/checklists/mutations/updateChecklist.ts | 2 +- .../components/page-wrapper/TopNavRight.tsx | 27 +++-- src/pages/store/index.tsx | 47 -------- src/store/components/Product.tsx | 81 -------------- src/store/components/ProductGrid.tsx | 15 --- src/store/components/VariantPicker.tsx | 18 ---- src/store/types.ts | 101 ------------------ src/store/utils.ts | 9 -- 16 files changed, 23 insertions(+), 393 deletions(-) delete mode 100644 src/pages/store/index.tsx delete mode 100644 src/store/components/Product.tsx delete mode 100644 src/store/components/ProductGrid.tsx delete mode 100644 src/store/components/VariantPicker.tsx delete mode 100644 src/store/types.ts delete mode 100644 src/store/utils.ts diff --git a/package-lock.json b/package-lock.json index 664800c9..675971e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,6 @@ "nextjs-google-analytics": "2.3.3", "postcss": "8.4.24", "postmark": "4.0.2", - "printful-request": "2.0.0", "prisma": "4.6.1", "react": "18.2.0", "react-dom": "18.2.0", @@ -5860,52 +5859,6 @@ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dependencies": { - "node-fetch": "2.6.7" - } - }, - "node_modules/cross-fetch/node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/cross-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/cross-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/cross-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -14061,14 +14014,6 @@ "node": ">=8" } }, - "node_modules/printful-request": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/printful-request/-/printful-request-2.0.0.tgz", - "integrity": "sha512-bXtEFmqqZbhhgffianuxJT9o9D5yXpohQI+Vh/L6WyBFbBSov7ZwIyAifSLktBSighxroY/PiJmXPYiLrd+uKw==", - "dependencies": { - "cross-fetch": "3.1.5" - } - }, "node_modules/prisma": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.6.1.tgz", @@ -23119,43 +23064,6 @@ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, - "cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "requires": { - "node-fetch": "2.6.7" - }, - "dependencies": { - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - } - }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -28816,14 +28724,6 @@ } } }, - "printful-request": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/printful-request/-/printful-request-2.0.0.tgz", - "integrity": "sha512-bXtEFmqqZbhhgffianuxJT9o9D5yXpohQI+Vh/L6WyBFbBSov7ZwIyAifSLktBSighxroY/PiJmXPYiLrd+uKw==", - "requires": { - "cross-fetch": "3.1.5" - } - }, "prisma": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.6.1.tgz", diff --git a/package.json b/package.json index 9a38138d..37ba3c61 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,6 @@ "nextjs-google-analytics": "2.3.3", "postcss": "8.4.24", "postmark": "4.0.2", - "printful-request": "2.0.0", "prisma": "4.6.1", "react": "18.2.0", "react-dom": "18.2.0", diff --git a/public/sitemap.xml b/public/sitemap.xml index 459cc65b..b028b0c6 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -129,9 +129,4 @@ https://ladderly.io/privacy-policy - - - https://ladderly.io/store/ - - \ No newline at end of file diff --git a/src/checklist-items/mutations/createChecklistItem.ts b/src/checklist-items/mutations/createChecklistItem.ts index e95fb0d0..a9c70702 100644 --- a/src/checklist-items/mutations/createChecklistItem.ts +++ b/src/checklist-items/mutations/createChecklistItem.ts @@ -4,7 +4,7 @@ import { CreateChecklistItemSchema } from "../schemas" export default resolver.pipe( resolver.zod(CreateChecklistItemSchema), - resolver.authorize(["admin"]), + resolver.authorize(["ADMIN"]), async (input) => { const checklistItem = await db.checklistItem.create({ data: input }) diff --git a/src/checklist-items/mutations/deleteChecklistItem.ts b/src/checklist-items/mutations/deleteChecklistItem.ts index af1ca706..0c86ce80 100644 --- a/src/checklist-items/mutations/deleteChecklistItem.ts +++ b/src/checklist-items/mutations/deleteChecklistItem.ts @@ -4,7 +4,7 @@ import { DeleteChecklistItemSchema } from "../schemas" export default resolver.pipe( resolver.zod(DeleteChecklistItemSchema), - resolver.authorize(["admin"]), + resolver.authorize(["ADMIN"]), async ({ id }) => { // TODO: in multi-tenant app, you must add validation to ensure correct tenant const checklistItem = await db.checklistItem.deleteMany({ where: { id } }) diff --git a/src/checklist-items/mutations/updateChecklistItem.ts b/src/checklist-items/mutations/updateChecklistItem.ts index a4525e5f..354968b6 100644 --- a/src/checklist-items/mutations/updateChecklistItem.ts +++ b/src/checklist-items/mutations/updateChecklistItem.ts @@ -4,7 +4,7 @@ import { UpdateChecklistItemSchema } from "../schemas" export default resolver.pipe( resolver.zod(UpdateChecklistItemSchema), - resolver.authorize(["admin"]), + resolver.authorize(["ADMIN"]), async ({ id, ...data }) => { const checklistItem = await db.checklistItem.update({ where: { id }, diff --git a/src/checklists/mutations/createChecklist.ts b/src/checklists/mutations/createChecklist.ts index 4db1b1e7..f0242cae 100644 --- a/src/checklists/mutations/createChecklist.ts +++ b/src/checklists/mutations/createChecklist.ts @@ -4,7 +4,7 @@ import { CreateChecklistSchema } from "../schemas" export default resolver.pipe( resolver.zod(CreateChecklistSchema), - resolver.authorize(["admin"]), + resolver.authorize(["ADMIN"]), async (input) => { const checklist = await db.checklist.create({ data: input }) diff --git a/src/checklists/mutations/deleteChecklist.ts b/src/checklists/mutations/deleteChecklist.ts index eff45159..c52aea38 100644 --- a/src/checklists/mutations/deleteChecklist.ts +++ b/src/checklists/mutations/deleteChecklist.ts @@ -4,7 +4,7 @@ import { DeleteChecklistSchema } from "../schemas" export default resolver.pipe( resolver.zod(DeleteChecklistSchema), - resolver.authorize(["admin"]), + resolver.authorize(["ADMIN"]), async ({ id }) => { // TODO: in multi-tenant app, you must add validation to ensure correct tenant const checklist = await db.checklist.deleteMany({ where: { id } }) diff --git a/src/checklists/mutations/updateChecklist.ts b/src/checklists/mutations/updateChecklist.ts index 868e9c25..cd1f0336 100644 --- a/src/checklists/mutations/updateChecklist.ts +++ b/src/checklists/mutations/updateChecklist.ts @@ -4,7 +4,7 @@ import { UpdateChecklistSchema } from "../schemas" export default resolver.pipe( resolver.zod(UpdateChecklistSchema), - resolver.authorize(["admin"]), + resolver.authorize(["ADMIN"]), async ({ id, ...data }) => { // TODO: in multi-tenant app, you must add validation to ensure correct tenant const checklist = await db.checklist.update({ where: { id }, data }) diff --git a/src/core/components/page-wrapper/TopNavRight.tsx b/src/core/components/page-wrapper/TopNavRight.tsx index 71d7fc1b..fd63f440 100644 --- a/src/core/components/page-wrapper/TopNavRight.tsx +++ b/src/core/components/page-wrapper/TopNavRight.tsx @@ -5,7 +5,11 @@ import React from "react" import { useCurrentUser } from "src/users/hooks/useCurrentUser" import { IconVerticalChevron } from "../icons/VerticalChevron" import { MenuContext } from "./MenuProvider" -import { AccountMenuItems, CommunityMenuItems, TOP_NAV_STANDARD_CLASSES } from "./TopNavSubmenu" +import { + AccountMenuItems, + CommunityMenuItems, + TOP_NAV_STANDARD_CLASSES, +} from "./TopNavSubmenu" const TOP_NAV_RIGHT_SECTION_CLASSES = "ml-auto flex items-center space-x-6" @@ -35,18 +39,21 @@ export const TopNavRight = () => { return (
- - Store - Blog - {currentUser ? ( - @@ -55,7 +62,10 @@ export const TopNavRight = () => { Log In - + Create Account @@ -66,9 +76,6 @@ export const TopNavRight = () => { export const TopNavRightSkeleton = () => (
- - Store - Blog diff --git a/src/pages/store/index.tsx b/src/pages/store/index.tsx deleted file mode 100644 index d59c3adb..00000000 --- a/src/pages/store/index.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { GetStaticProps } from "next" -import React from "react" -import { LadderlyPageWrapper } from "src/core/components/page-wrapper/LadderlyPageWrapper" - -import ProductGrid from "src/store/components/ProductGrid" -import { PrintfulProduct } from "src/store/types" -import { formatVariantName, printful } from "src/store/utils" - -type StorePageProps = { - products: PrintfulProduct[] -} - -const StorePage: React.FC = ({ products }) => ( - -
-

All Products

-
- - -
-) - -export const getStaticProps: GetStaticProps = async () => { - const { result: productIds } = await printful.get("sync/products") - - const allProducts = await Promise.all( - productIds.map(async ({ id }) => await printful.get(`sync/products/${id}`)) - ) - - const products: PrintfulProduct[] = allProducts.map( - ({ result: { sync_product, sync_variants } }) => ({ - ...sync_product, - variants: sync_variants.map(({ name, ...variant }) => ({ - name: formatVariantName(name), - ...variant, - })), - }) - ) - - return { - props: { - products, - }, - } -} - -export default StorePage diff --git a/src/store/components/Product.tsx b/src/store/components/Product.tsx deleted file mode 100644 index 36023b93..00000000 --- a/src/store/components/Product.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import Image from "next/image" -import React from "react" -import VariantPicker from "./VariantPicker" - -type ProductProps = { - name: string - variants: { - external_id: string - name: string - files: { - type: string - preview_url: string - }[] - currency: string - retail_price: number - }[] -} - -const Product: React.FC = (product: ProductProps) => { - const { name, variants } = product - const firstVariant = variants[0] - const oneStyle = variants.length === 1 - const [activeVariantExternalId, setActiveVariantExternalId] = React.useState( - firstVariant?.external_id - ) - - const activeVariant = variants.find((v) => v.external_id === activeVariantExternalId) - if (activeVariant === undefined) return null - - const activeVariantFile = activeVariant.files.find(({ type }) => type === "preview") - if (activeVariantFile === undefined) return null - - const formattedPrice = new Intl.NumberFormat("en-US", { - style: "currency", - currency: activeVariant.currency, - }).format(activeVariant.retail_price) - - return ( -
-
- {activeVariantFile && ( - {`${activeVariant.name} - )} -
-
-
-

{name}

-

{formattedPrice}

-
-
-
- setActiveVariantExternalId(value)} - variants={variants} - disabled={oneStyle} - /> - {/* TODO: uncomment this button - */} -
-
- ) -} - -export default Product diff --git a/src/store/components/ProductGrid.tsx b/src/store/components/ProductGrid.tsx deleted file mode 100644 index b46696f7..00000000 --- a/src/store/components/ProductGrid.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import Product from "./Product" - -const ProductGrid = ({ products }) => { - if (!products || products.length === 0) return null - - return ( -
- {products.map((product) => ( - - ))} -
- ) -} - -export default ProductGrid diff --git a/src/store/components/VariantPicker.tsx b/src/store/components/VariantPicker.tsx deleted file mode 100644 index 4654b9c1..00000000 --- a/src/store/components/VariantPicker.tsx +++ /dev/null @@ -1,18 +0,0 @@ -const VariantPicker = ({ variants, ...props }) => { - if (variants.length === (0 || 1)) return null - - return ( - - ) -} - -export default VariantPicker diff --git a/src/store/types.ts b/src/store/types.ts deleted file mode 100644 index 90fb3c77..00000000 --- a/src/store/types.ts +++ /dev/null @@ -1,101 +0,0 @@ -import type { NextApiRequest } from "next" - -declare global { - interface Window { - Snipcart: any - } - namespace JSX { - interface IntrinsicElements { - "address-fields": any - "snipcart-label": any - "snipcart-input": any - } - } -} - -export type SnipcartWebhookEvent = - | "order.completed" - | "order.status.changed" - | "order.paymentStatus.changed" - | "order.trackingNumber.changed" - | "order.refund.created" - | "order.notification.created" - | "subscription.created" - | "subscription.cancelled" - | "subscription.paused" - | "subscription.resumed" - | "subscription.invoice.created" - | "shippingrates.fetch" - | "taxes.calculate" - | "customauth:customer_updated" - -export interface SnipcartWebhookContent { - discounts: { [key: string]: any } - items: { [key: string]: any } - shippingAddress: { - fullName: string - firstName?: string - name: string - company?: string - address1: string - address2?: string - fullAddress: string - city: string - country: string - postalCode: string - province: string - phone?: string - } - shippingRateUserDefinedId?: string - [key: string]: any -} - -export type SnipcartShippingRate = { - /** Shipping method's price. */ - cost: number - /** Name or description of the shipping method. */ - description: string - /** Estimated time for delivery in days. */ - guaranteedDaysToDelivery?: number - /** Internal ID of shipping method, can be useful when using shipping fulfillment solutions. */ - userDefinedId?: string -} - -export type SnipcartTaxItem = { - name: string - amount: number - rate: number - numberForInvoice?: string - includedInPrice?: boolean - appliesOnShipping?: boolean -} - -export interface SnipcartRequest extends NextApiRequest { - headers: { - "x-snipcart-requesttoken"?: string - } - body: { - eventName: SnipcartWebhookEvent - mode: string - createdOn: string - content: SnipcartWebhookContent - } -} - -export interface ISyncProduct { - id: string - external_id: string - name: string - variants: number - synced: number -} - -export interface PrintfulProduct { - id: string - name: string -} - -export type PrintfulShippingItem = { - external_variant_id: string - quantity: number -} diff --git a/src/store/utils.ts b/src/store/utils.ts deleted file mode 100644 index 59b91a9f..00000000 --- a/src/store/utils.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { PrintfulClient } from "printful-request" - -export const printful = new PrintfulClient(process.env.PRINTFUL_API_TOKEN) - -export const formatVariantName = (variantName: string): string => { - const [, name] = variantName.split(" - ") - - return name ? name : "One style" -}