Skip to content

Commit

Permalink
Work around to cast json and avoid known drizzle bug
Browse files Browse the repository at this point in the history
  • Loading branch information
JDLanctot committed Jun 25, 2024
1 parent f7d928b commit 8081f2f
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/db/schema/carts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const carts = pgTable("carts", {
.primaryKey(), // prefix_ + nanoid (12)
paymentIntentId: varchar("payment_intent_id", { length: 256 }),
clientSecret: text("client_secret"),
items: json("items").$type<CartItemSchema[] | null>().default(null),
items: json("items").array().$type<CartItemSchema[] | null>().default(null),
closed: boolean("closed").notNull().default(false),
...lifecycleDates,
})
Expand Down
35 changes: 26 additions & 9 deletions src/lib/actions/cart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
type deleteCartItemSchema,
type deleteCartItemsSchema,
} from "@/lib/validations/cart"
import { dbPrefix } from "@/lib/constants"

export async function getCart(input?: {
storeId: string
Expand Down Expand Up @@ -103,8 +102,10 @@ export async function getUniqueStoreIds() {
.from(carts)
.leftJoin(
products,
// Injecting the dbPrefix is breaking things for some reason
sql`skateshop_carts.items::jsonb @> jsonb_build_array(jsonb_build_object('productId', skateshop_products.id))`
sql`EXISTS (
SELECT 1 FROM unnest(carts.items::json[]) as item
WHERE (item->>'productId')::text = products.id::text
)`
)
.groupBy(products.storeId)
.where(eq(carts.id, cartId))
Expand Down Expand Up @@ -160,10 +161,11 @@ export async function addToCart(rawInput: z.infer<typeof cartItemSchema>) {
const cartId = cookieStore.get("cartId")?.value

if (!cartId) {
// Note: ARRAY[]::json[] is a workaround for a drizzle bug with escaping json
const cart = await db
.insert(carts)
.values({
items: [input],
items: sql`ARRAY[${input}::json]::json[]`,
})
.returning({ insertedId: carts.id })

Expand Down Expand Up @@ -198,10 +200,11 @@ export async function addToCart(rawInput: z.infer<typeof cartItemSchema>) {
if (cart.closed) {
await db.delete(carts).where(eq(carts.id, cartId))

// Note: ARRAY[]::json[] is a workaround for a drizzle bug with escaping json
const newCart = await db
.insert(carts)
.values({
items: [input],
items: sql`ARRAY[${input}::json]::json[]`,
})
.returning({ insertedId: carts.id })

Expand All @@ -224,10 +227,14 @@ export async function addToCart(rawInput: z.infer<typeof cartItemSchema>) {
cart.items?.push(input)
}

// Note: ARRAY[]::json[] is a workaround for a drizzle bug with escaping json
await db
.update(carts)
.set({
items: cart.items,
items: sql`ARRAY[${sql.raw(
// @ts-ignore - cart is not null due to early returns
cart.items.map(item => `'${JSON.stringify(item)}'::json`).join(',')
)}]::json[]`
})
.where(eq(carts.id, cartId))

Expand Down Expand Up @@ -280,10 +287,14 @@ export async function updateCartItem(rawInput: z.infer<typeof cartItemSchema>) {
cartItem.quantity = input.quantity
}

// Note: ARRAY[]::json[] is a workaround for a drizzle bug with escaping json
await db
.update(carts)
.set({
items: cart.items,
items: sql`ARRAY[${sql.raw(
// @ts-ignore - cart is not null due to early returns
cart.items.map(item => `'${JSON.stringify(item)}'::json`).join(',')
)}]::json[]`
})
.where(eq(carts.id, cartId))

Expand Down Expand Up @@ -348,10 +359,13 @@ export async function deleteCartItem(
cart.items =
cart.items?.filter((item) => item.productId !== input.productId) ?? []

// Note: ARRAY[]::json[] is a workaround for a drizzle bug with escaping json
await db
.update(carts)
.set({
items: cart.items,
items: sql`ARRAY[${sql.raw(
cart.items.map(item => `'${JSON.stringify(item)}'::json`).join(',')
)}]::json[]`
})
.where(eq(carts.id, cartId))

Expand Down Expand Up @@ -387,10 +401,13 @@ export async function deleteCartItems(
(item) => !input.productIds.includes(item.productId)
) ?? []

// Note: ARRAY[]::json[] is a workaround for a drizzle bug with escaping json
await db
.update(carts)
.set({
items: cart.items,
items: sql`ARRAY[${sql.raw(
cart.items.map(item => `'${JSON.stringify(item)}'::json`).join(',')
)}]::json[]`
})
.where(eq(carts.id, cartId))

Expand Down

0 comments on commit 8081f2f

Please sign in to comment.