-
Notifications
You must be signed in to change notification settings - Fork 27.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
update with-turbopack example (#49332)
Updated to latest app-playground code
- Loading branch information
Showing
223 changed files
with
4,858 additions
and
1,773 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export type Category = { | ||
name: string | ||
slug: string | ||
count: number | ||
parent: string | null | ||
} |
49 changes: 49 additions & 0 deletions
49
examples/with-turbopack/app/api/categories/getCategories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { getBaseUrl } from '#/lib/getBaseUrl' | ||
import { notFound } from 'next/navigation' | ||
import type { Category } from './category' | ||
|
||
// `server-only` guarantees any modules that import code in file | ||
// will never run on the client. Even though this particular api | ||
// doesn't currently use sensitive environment variables, it's | ||
// good practise to add `server-only` preemptively. | ||
import 'server-only' | ||
|
||
export async function getCategories({ parent }: { parent?: string } = {}) { | ||
const res = await fetch( | ||
`${getBaseUrl()}/api/categories${parent ? `?parent=${parent}` : ''}` | ||
) | ||
|
||
if (!res.ok) { | ||
// Render the closest `error.js` Error Boundary | ||
throw new Error('Something went wrong!') | ||
} | ||
|
||
const categories = (await res.json()) as Category[] | ||
|
||
if (categories.length === 0) { | ||
// Render the closest `not-found.js` Error Boundary | ||
notFound() | ||
} | ||
|
||
return categories | ||
} | ||
|
||
export async function getCategory({ slug }: { slug: string }) { | ||
const res = await fetch( | ||
`${getBaseUrl()}/api/categories${slug ? `?slug=${slug}` : ''}` | ||
) | ||
|
||
if (!res.ok) { | ||
// Render the closest `error.js` Error Boundary | ||
throw new Error('Something went wrong!') | ||
} | ||
|
||
const category = (await res.json()) as Category | ||
|
||
if (!category) { | ||
// Render the closest `not-found.js` Error Boundary | ||
notFound() | ||
} | ||
|
||
return category | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import type { Category } from './category' | ||
|
||
const data: Category[] = [ | ||
{ name: 'Electronics', slug: 'electronics', count: 11, parent: null }, | ||
{ name: 'Clothing', slug: 'clothing', count: 12, parent: null }, | ||
{ name: 'Books', slug: 'books', count: 10, parent: null }, | ||
{ name: 'Phones', slug: 'phones', count: 4, parent: 'electronics' }, | ||
{ name: 'Tablets', slug: 'tablets', count: 5, parent: 'electronics' }, | ||
{ name: 'Laptops', slug: 'laptops', count: 2, parent: 'electronics' }, | ||
{ name: 'Tops', slug: 'tops', count: 3, parent: 'clothing' }, | ||
{ name: 'Shorts', slug: 'shorts', count: 4, parent: 'clothing' }, | ||
{ name: 'Shoes', slug: 'shoes', count: 5, parent: 'clothing' }, | ||
{ name: 'Fiction', slug: 'fiction', count: 5, parent: 'books' }, | ||
{ name: 'Biography', slug: 'biography', count: 2, parent: 'books' }, | ||
{ name: 'Education', slug: 'education', count: 3, parent: 'books' }, | ||
] | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function GET(request: Request) { | ||
const { searchParams } = new URL(request.url) | ||
|
||
// We sometimes artificially delay a reponse for demo purposes. | ||
// Don't do this in real life :) | ||
const delay = searchParams.get('delay') | ||
if (delay) { | ||
await new Promise((resolve) => setTimeout(resolve, Number(delay))) | ||
} | ||
|
||
const slug = searchParams.get('slug') | ||
if (slug) { | ||
const category = data.find((category) => category.slug === slug) | ||
|
||
return new Response(JSON.stringify(category ?? null), { | ||
status: 200, | ||
headers: { | ||
'content-type': 'application/json', | ||
}, | ||
}) | ||
} | ||
|
||
const parent = searchParams.get('parent') | ||
const categories = data.filter((category) => | ||
parent ? category.parent === parent : category.parent === null | ||
) | ||
|
||
return new Response(JSON.stringify(categories), { | ||
status: 200, | ||
headers: { | ||
'content-type': 'application/json', | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
export type Product = { | ||
id: string | ||
stock: number | ||
rating: number | ||
name: string | ||
description: string | ||
price: Price | ||
isBestSeller: boolean | ||
leadTime: number | ||
image?: string | ||
imageBlur?: string | ||
discount?: Discount | ||
usedPrice?: UsedPrice | ||
} | ||
|
||
type Price = { | ||
amount: number | ||
currency: Currency | ||
scale: number | ||
} | ||
|
||
type Currency = { | ||
code: string | ||
base: number | ||
exponent: number | ||
} | ||
|
||
type Discount = { | ||
percent: number | ||
expires?: number | ||
} | ||
|
||
type UsedPrice = { | ||
amount: number | ||
currency: Currency | ||
scale: number | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
import type { Product } from '#/app/api/products/product' | ||
|
||
const data: Product[] = [ | ||
{ | ||
id: '1', | ||
stock: 2, | ||
rating: 5, | ||
name: 'Donec sit elit', | ||
description: | ||
'Morbi eu ullamcorper urna, a condimentum massa. In fermentum ante non turpis cursus fringilla. Praesent neque eros, gravida vel ante sed, vehicula elementum orci. Sed eu ipsum eget enim mattis mollis.', | ||
price: { | ||
amount: 4200, | ||
currency: { code: 'USD', base: 10, exponent: 2 }, | ||
scale: 2, | ||
}, | ||
isBestSeller: false, | ||
leadTime: 2, | ||
discount: { percent: 90, expires: 2 }, | ||
image: 'eniko-kis-KsLPTsYaqIQ-unsplash.jpg', | ||
imageBlur: | ||
'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAAqgAwAEAAAAAQAAAAoAAAAA/8AAEQgACgAKAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAgICAgICAwICAwUDAwMFBgUFBQUGCAYGBgYGCAoICAgICAgKCgoKCgoKCgwMDAwMDA4ODg4ODw8PDw8PDw8PD//bAEMBAgICBAQEBwQEBxALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/dAAQAAf/aAAwDAQACEQMRAD8A+3/HPx10jQPE0+k6ZrPh6TTtKsbi41R7nVUiu7WeMkQxi2H3lk2su4sCrjBHFd54c+InhvxJ4e0vxFa3aRw6pawXSKxG5VnQOAfcA81474z8G+ENU1OeXU9Dsbt/N8zdNbRSHfn72WU/N79a9U03TtPj061jjtYkRIkAARQAAowAMV2Sa7GsIH//2Q==', | ||
}, | ||
{ | ||
id: '2', | ||
stock: 5, | ||
rating: 4, | ||
name: 'Fusce commodo porta posuere', | ||
description: | ||
'Morbi eu ullamcorper urna, a condimentum massa. In fermentum ante non turpis cursus fringilla. Praesent neque eros, gravida vel ante sed, vehicula elementum orci. Sed eu ipsum eget enim mattis mollis.', | ||
price: { | ||
amount: 4600, | ||
currency: { code: 'USD', base: 10, exponent: 2 }, | ||
scale: 2, | ||
}, | ||
isBestSeller: false, | ||
leadTime: 1, | ||
image: 'patrick-OIFgeLnjwrM-unsplash.jpg', | ||
imageBlur: | ||
'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAAqgAwAEAAAAAQAAAAoAAAAA/8AAEQgACgAKAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAgICAgICAwICAwUDAwMFBgUFBQUGCAYGBgYGCAoICAgICAgKCgoKCgoKCgwMDAwMDA4ODg4ODw8PDw8PDw8PD//bAEMBAgICBAQEBwQEBxALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/dAAQAAf/aAAwDAQACEQMRAD8AwNV+KvwHs7vSNLi8faJoy2VtcQatFLaSz3X2shBGyuUKjy23kgKwY4HStq5j0O4uZZ9Lfz7KR2aCQArviJyjYIyMrg4NXY7Cxddz20bE9SUU/wBKfsQcBQAPav6Gyrh+vQq1pyxMpKTuk+mr0Wr7/gf568TeI2DxlDDUqWXwpumrNpr3tIq7tFa6X67n/9k=', | ||
}, | ||
{ | ||
id: '3', | ||
stock: 3, | ||
rating: 3, | ||
name: 'Praesent tincidunt lectus', | ||
description: | ||
'Morbi eu ullamcorper urna, a condimentum massa. In fermentum ante non turpis cursus fringilla. Praesent neque eros, gravida vel ante sed, vehicula elementum orci. Sed eu ipsum eget enim mattis mollis.', | ||
price: { | ||
amount: 29200, | ||
currency: { code: 'USD', base: 10, exponent: 2 }, | ||
scale: 2, | ||
}, | ||
discount: { percent: 70, expires: 7 }, | ||
isBestSeller: true, | ||
leadTime: 2, | ||
image: 'yoann-siloine-_T4w3JDm6ug-unsplash.jpg', | ||
imageBlur: | ||
'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAAqgAwAEAAAAAQAAAAoAAAAA/8AAEQgACgAKAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAgICAgICAwICAwUDAwMFBgUFBQUGCAYGBgYGCAoICAgICAgKCgoKCgoKCgwMDAwMDA4ODg4ODw8PDw8PDw8PD//bAEMBAgICBAQEBwQEBxALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/dAAQAAf/aAAwDAQACEQMRAD8A+6vG/wC1t4J+GniLxP4L1Wynub7RrqWOQBJ1DvLbG9AVxC6ECHPO4DdhM7yBX2XpP2iTSrOROFaGMgegKivPPEGnafLrEckttE7yOu4siktgdzjmvTE4RQOAAKDSx//Z', | ||
}, | ||
{ | ||
id: '4', | ||
stock: 2, | ||
rating: 5, | ||
name: 'Morbi at viverra turpis', | ||
description: | ||
'Morbi eu ullamcorper urna, a condimentum massa. In fermentum ante non turpis cursus fringilla. Praesent neque eros, gravida vel ante sed, vehicula elementum orci. Sed eu ipsum eget enim mattis mollis.', | ||
price: { | ||
amount: 21200, | ||
currency: { code: 'USD', base: 10, exponent: 2 }, | ||
scale: 2, | ||
}, | ||
isBestSeller: false, | ||
leadTime: 2, | ||
image: 'alexander-andrews-brAkTCdnhW8-unsplash.jpg', | ||
imageBlur: | ||
'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAAqgAwAEAAAAAQAAAAoAAAAA/8AAEQgACgAKAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAgICAgICAwICAwUDAwMFBgUFBQUGCAYGBgYGCAoICAgICAgKCgoKCgoKCgwMDAwMDA4ODg4ODw8PDw8PDw8PD//bAEMBAgICBAQEBwQEBxALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/dAAQAAf/aAAwDAQACEQMRAD8Ay59W0U20sUGmapJf2hZZVR7TyWVbd5hKgd1k2yOohVeu4jHGTXBwa9PcQR3BhaAyqG8uQ/Om4Z2tjjI6HHGa2dVtrad3aeJJCOhZQf51TjACKAMAAV0u99z8bni6E4RUaVmt3fc//9k=', | ||
}, | ||
{ | ||
id: '5', | ||
stock: 1, | ||
rating: 4, | ||
name: 'Maecenas interdum', | ||
description: | ||
'Morbi eu ullamcorper urna, a condimentum massa. In fermentum ante non turpis cursus fringilla. Praesent neque eros, gravida vel ante sed, vehicula elementum orci. Sed eu ipsum eget enim mattis mollis.', | ||
price: { | ||
amount: 28700, | ||
currency: { code: 'USD', base: 10, exponent: 2 }, | ||
scale: 2, | ||
}, | ||
isBestSeller: false, | ||
leadTime: 4, | ||
image: 'guillaume-coupy-6HuoHgK7FN8-unsplash.jpg', | ||
imageBlur: | ||
'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAAqgAwAEAAAAAQAAAAoAAAAA/8AAEQgACgAKAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAgICAgICAwICAwUDAwMFBgUFBQUGCAYGBgYGCAoICAgICAgKCgoKCgoKCgwMDAwMDA4ODg4ODw8PDw8PDw8PD//bAEMBAgICBAQEBwQEBxALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/dAAQAAf/aAAwDAQACEQMRAD8A9P8Aj/qni3w58aNel0PV9UENm3lraDUfLtpJJLeOMKlqwXYELGRX3/M3zD3/AE5tPDB+yQ7pFc7FySeTx1NeX+PfhF8J/FPjI+IfE3grRNX1UPC4u7zTba4uN0f3D5skbPlf4TnjtXvcdrbLGoEKAADjaKpQa3Z1Od9j/9k=', | ||
}, | ||
] | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function GET(request: Request) { | ||
const { searchParams } = new URL(request.url) | ||
|
||
// We sometimes artificially delay a reponse for demo purposes. | ||
// Don't do this in real life :) | ||
const delay = searchParams.get('delay') | ||
if (delay) { | ||
await new Promise((resolve) => setTimeout(resolve, Number(delay))) | ||
} | ||
|
||
const id = searchParams.get('id') | ||
if (id) { | ||
let product = data.find((product) => product.id === id) | ||
|
||
const fields = searchParams.get('fields') | ||
if (product && fields) { | ||
product = fields.split(',').reduce((acc, field) => { | ||
// @ts-ignore | ||
acc[field] = product[field] | ||
|
||
return acc | ||
}, {} as Product) | ||
} | ||
|
||
return new Response(JSON.stringify(product ?? null), { | ||
status: 200, | ||
headers: { | ||
'content-type': 'application/json', | ||
}, | ||
}) | ||
} | ||
|
||
const filter = searchParams.get('filter') | ||
const products = filter | ||
? data.filter((product) => product.id !== filter) | ||
: data | ||
|
||
return new Response(JSON.stringify(products), { | ||
status: 200, | ||
headers: { | ||
'content-type': 'application/json', | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { getBaseUrl } from '#/lib/getBaseUrl' | ||
import { notFound } from 'next/navigation' | ||
import type { Review } from './review' | ||
|
||
// `server-only` guarantees any modules that import code in file | ||
// will never run on the client. Even though this particular api | ||
// doesn't currently use sensitive environment variables, it's | ||
// good practise to add `server-only` preemptively. | ||
import 'server-only' | ||
|
||
export async function getReviews() { | ||
const res = await fetch(`${getBaseUrl()}/api/reviews`) | ||
|
||
if (!res.ok) { | ||
// Render the closest `error.js` Error Boundary | ||
throw new Error('Something went wrong!') | ||
} | ||
|
||
const reviews = (await res.json()) as Review[] | ||
|
||
if (reviews.length === 0) { | ||
// Render the closest `not-found.js` Error Boundary | ||
notFound() | ||
} | ||
|
||
return reviews | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export type Review = { | ||
id: string | ||
name: string | ||
rating: number | ||
text: string | ||
} |
Oops, something went wrong.