Skip to content

Commit

Permalink
Merge pull request #23 from team-nabi/NABI-77
Browse files Browse the repository at this point in the history
🎉 Nabi 77 fetch 관련 설정
  • Loading branch information
oaoong authored Nov 1, 2023
2 parents 324665d + 23b787f commit 3a6b64e
Show file tree
Hide file tree
Showing 14 changed files with 1,104 additions and 752 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
NEXT_PUBLIC_API_ADDRESS=http://localhost:3000
NEXT_PUBLIC_API_MOCKING=enabled # or disabled
CHROMATIC_TOKEN=your-token
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"@tanstack/eslint-plugin-query": "^5.0.0",
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
"@types/node": "^20",
"@types/react": "^18",
"@types/react": "^18.2.33",
"@types/react-dom": "^18",
"@types/tailwindcss": "^3.1.0",
"chromatic": "^7.5.4",
Expand All @@ -66,7 +66,7 @@
"prettier": "^3.0.3",
"storybook": "7.5.0",
"storybook-dark-mode": "^3.0.1",
"typescript": "^5",
"typescript": "^5.2.2",
"vitest": "^0.34.6"
},
"lint-staged": {
Expand Down
1,595 changes: 866 additions & 729 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions src/app/(root)/(routes)/(home)/components/TestBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use client'

import React, { useEffect } from 'react'
// import { useApiClient } from '@/contexts/FetchContext'
import { getTest } from '@/services/test/test'

// async function getTestValue() {
// const res = await getTest()
// const data = await res.json()
// return data
// }

export default function TestBlock() {
// const data = await getTestValue()
// console.log(data.message)

useEffect(() => {
async function fetchData() {
const data = await getTest()
console.log(await data.json())
}
fetchData()
}, [])

return <div>{'index '}</div>
}
2 changes: 2 additions & 0 deletions src/app/(root)/(routes)/(home)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { DarkModeButton } from '@/components/ui/DarkModeButton'
import TestBlock from './components/TestBlock'

export default function HomePage() {
return (
<main className="flex flex-col items-center justify-between min-h-screen p-24 text-4xl font-bold text-text-color bg-background-color">
hi
<TestBlock />
<DarkModeButton />
</main>
)
Expand Down
35 changes: 17 additions & 18 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,17 @@ import { Suspense } from 'react'
import type { Metadata } from 'next'
import Head from 'next/head'
import Header from '@/components/domain/Header'
import { Environment } from '@/config/environment'
import { FetchProvider } from '@/contexts/FetchContext'
import MSWWrapper from '@/contexts/MSWWrapper'
import TanstackQueryContext from '@/contexts/TanstackQueryContext'
import ThemeProviderContext from '@/contexts/ThemeProviderContext'
import { initMockApi } from '@/lib/msw/initMockApi'
import '@/styles/globals.css'

export const metadata: Metadata = {
title: '나비장터',
description: '물물교환 플랫폼 나비장터입니다.',
}

if (Environment.apiMocking() === 'enabled') {
console.log('Mocking enabled')
initMockApi()
}

export default function RootLayout({
children,
authModal,
Expand All @@ -31,17 +26,21 @@ export default function RootLayout({
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</Head>
<body>
<TanstackQueryContext>
<ThemeProviderContext>
<Suspense>
<div className="centered-content">
<Header isLogin={false} />
{children}
{authModal}
</div>
</Suspense>
</ThemeProviderContext>
</TanstackQueryContext>
<FetchProvider>
<TanstackQueryContext>
<MSWWrapper>
<ThemeProviderContext>
<Suspense>
<div className="centered-content">
<Header isLogin={false} />
{children}
{authModal}
</div>
</Suspense>
</ThemeProviderContext>
</MSWWrapper>
</TanstackQueryContext>
</FetchProvider>
</body>
</html>
)
Expand Down
6 changes: 6 additions & 0 deletions src/config/apiEndPoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const ApiEndPoint = {
login: () => '/login',
test: () => '/test',
} as const

export default ApiEndPoint
3 changes: 1 addition & 2 deletions src/config/environment.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { assertValue } from '@/utils/assertValue'

export const Environment = {
apiAddress: () => process.env.NEXT_PUBLIC_API_ADDRESS,
apiMocking: () =>
process.env.NEXT_PUBLIC_API_MOCKING === 'enabled' ? 'enabled' : 'disabled',
}
26 changes: 26 additions & 0 deletions src/contexts/FetchContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use client'

import React, { ReactNode, createContext, useContext, useMemo } from 'react'
import FetchAPI from '@/lib/fetchAPI'

const FetchContext = createContext<{ api: FetchAPI }>({ api: {} as FetchAPI })

export const FetchProvider = ({ children }: { children: ReactNode }) => {
const api = FetchAPI.getInstance()

const contextValue = useMemo(() => ({ api }), [api])

return (
<FetchContext.Provider value={contextValue}>
{children}
</FetchContext.Provider>
)
}

export const useApiClient = () => {
const context = useContext(FetchContext)
if (!context) {
throw new Error('useApiClient must be used within a FetchProvider')
}
return context
}
34 changes: 34 additions & 0 deletions src/contexts/MSWWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use client'

import { useState, type PropsWithChildren, useEffect } from 'react'
import { Environment } from '@/config/environment'

const isMockingMode = Environment.apiMocking() === 'enabled'

const MSWComponent = ({ children }: PropsWithChildren) => {
const [mswReady, setMSWReady] = useState(() => !isMockingMode)

useEffect(() => {
const init = async () => {
if (isMockingMode) {
const initMocks = await import('../lib/msw/initMockApi').then(
(res) => res.initMockApi,
)
await initMocks()
setMSWReady(true)
}
}

if (!mswReady) {
init()
}
}, [mswReady])

if (!mswReady) {
return null
}

return <>{children}</>
}

export default MSWComponent
88 changes: 88 additions & 0 deletions src/lib/fetchAPI.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Environment } from '@/config/environment'

class FetchAPI {
private baseURL: string
private headers: { [key: string]: string }

private static instance: FetchAPI

private constructor() {
this.baseURL = Environment.apiAddress() ?? ''
this.headers = {
'Content-Type': 'application/json',
}
}

public static getInstance(): FetchAPI {
if (!FetchAPI.instance) {
FetchAPI.instance = new FetchAPI()
}
return FetchAPI.instance
}

public setBaseURL(url: string): void {
this.baseURL = url
}

public setDefaultHeader(key: string, value: string): void {
this.headers[key] = value
}

public async get(
endpoint: string,
nextInit: RequestInit = {},
customHeaders: { [key: string]: string } = {},
): Promise<any> {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: 'GET',
headers: { ...this.headers, ...customHeaders },
...nextInit,
})
return response
}

public async post(
endpoint: string,
body: any,
nextInit: RequestInit = {},
customHeaders: { [key: string]: string } = {},
): Promise<any> {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: 'POST',
headers: { ...this.headers, ...customHeaders },
body: JSON.stringify(body),
...nextInit,
})
return response
}

public async put(
endpoint: string,
body: any,
nextInit: RequestInit = {},
customHeaders: { [key: string]: string } = {},
): Promise<any> {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: 'PUT',
headers: { ...this.headers, ...customHeaders },
body: JSON.stringify(body),
...nextInit,
})
return response
}

public async delete(
endpoint: string,
nextInit: RequestInit = {},
customHeaders: { [key: string]: string } = {},
): Promise<any> {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: 'DELETE',
headers: { ...this.headers, ...customHeaders },
...nextInit,
})
return response
}
}

export default FetchAPI
5 changes: 4 additions & 1 deletion src/lib/msw/mocks/testHandler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { rest } from 'msw'
import { Environment } from '@/config/environment'

const baseUrl = Environment.apiAddress()

export const testHandlers = [
rest.get('/test', async (_req, res, ctx) => {
rest.get(`${baseUrl}/test`, async (_req, res, ctx) => {
return res(
ctx.status(200),
ctx.json({
Expand Down
15 changes: 15 additions & 0 deletions src/services/auth/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import ApiEndPoint from '@/config/apiEndPoint'
import { Environment } from '@/config/environment'

const postLogin = async () => {
const response = await fetch(Environment.apiAddress() + ApiEndPoint.login(), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
})
const data = await response.json()
return data
}

export { postLogin }
16 changes: 16 additions & 0 deletions src/services/test/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import ApiEndPoint from '@/config/apiEndPoint'
import FetchAPI from '@/lib/fetchAPI'

const getTest = async () => {
const api = FetchAPI.getInstance()
const response = await api.get(
ApiEndPoint.test(),
{ next: { revalidate: 10 } },
{
'Content-Type': 'application/json',
},
)
return response
}

export { getTest }

0 comments on commit 3a6b64e

Please sign in to comment.