diff --git a/README.md b/README.md index 29c94b1..1373348 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ This is a [Next.js](https://nextjs.org/) project bootstrapped with [`microCMS`]( This project will help you quickly implement JAMStack service with TypeScript-friendly. -## Getting Started Development +## Set up -First, run the development server: +Run the development server: ```bash yarn dev @@ -36,6 +36,8 @@ This project supports [Incremental Static Regeneration](https://nextjs.org/docs/ Let's create account of `microCMS` for free, and make one api that has `/articles` path and create first article content. +This sample uses `/articles` API in `microCMS`. Please make an API that has `/articles` path, and it has following properties: `title`, `body`, `description` (there are string types). + Then you can access the api by below command. ```bash @@ -53,6 +55,8 @@ And, run the command `yarn build:api` and you will get `types/apiClient/$api.ts` Then, check `modules/apiClient.ts`. This initializes aspida client and export it. With optimizing for `microCMS` APIs. +*Notice:* at local development, we can use [`aspida-mock`](https://github.com/aspida/aspida/tree/master/packages/aspida-mock). The library make us building mock server and response data by using same API as real backend APIs. Please look at `modules/apiClient.ts`. + You can get microCMS content by following code. ```typescript @@ -63,13 +67,15 @@ const article = await apiClient.articles._cmsId(id).$get() ## Environments -You touch the env file. Called `.env.local` +You can touch the env file. Called `.env.local` ```dotenv MICROCMS_GET_API_KEY= MICROCMS_BASE_URL=https://.microcms.io/api/v1 ``` +Only this sample, aspida uses mock-server at local development. So the env file isn't needed. But you must set these env values at [Vercel Platform](https://vercel.com/import?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) console. + ## Deploy on Vercel The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/import?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. diff --git a/modules/apiClient.ts b/modules/apiClient.ts index 782006c..323f8fe 100644 --- a/modules/apiClient.ts +++ b/modules/apiClient.ts @@ -1,8 +1,14 @@ -import aspida from '@aspida/fetch' +import aspida from '@aspida/axios' +import mockClient from '@aspida/axios/dist/mockClient' + import api from '../types/apiClient/$api' +import mock from '../types/apiClient/$mock' +import axios from 'axios' const fetchConfig = { headers: { 'X-API-KEY': process.env.MICROCMS_GET_API_KEY }, baseURL: process.env.MICROCMS_BASE_URL } -export const apiClient = api(aspida(fetch, fetchConfig)) \ No newline at end of file +// in local development, use aspida-mock. +// @see https://github.com/aspida/aspida/tree/master/packages/aspida-mock +export const apiClient = process.env.NODE_ENV === 'development' ? mock(mockClient()) : api(aspida(axios, fetchConfig)) \ No newline at end of file diff --git a/package.json b/package.json index 38eebb3..72cd647 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "license": "MIT", "scripts": { "dev": "next dev", - "build": "aspida --build && next build", - "build:api": "aspida --build", + "build": "aspida --build && aspida-mock && next build", + "build:api": "aspida --build && aspida-mock", "start": "next start" }, "lint-staged": { @@ -21,7 +21,8 @@ } }, "dependencies": { - "@aspida/fetch": "^0.8.1", + "@aspida/axios": "^0.10.2", + "axios": "^0.19.2", "next": "9.5.1", "react": "16.13.1", "react-dom": "16.13.1" @@ -31,6 +32,7 @@ "@types/react": "^16.9.44", "@typescript-eslint/eslint-plugin": "^3.7.1", "@typescript-eslint/parser": "^3.7.1", + "aspida-mock": "^0.7.1", "eslint": "^7.6.0", "eslint-plugin-react": "^7.20.5", "husky": "^4.2.5", diff --git a/pages/articles/[id].tsx b/pages/articles/[id].tsx index e7afd6d..a57f2ae 100644 --- a/pages/articles/[id].tsx +++ b/pages/articles/[id].tsx @@ -9,6 +9,7 @@ import React from 'react' import { MicroCmsArticle } from '../../types/microcms/type' import { useRouter } from 'next/router' import Loading from '../../components/parts/loading/Loading' +import Head from 'next/head' export const getStaticProps: GetStaticProps<{ article: MicroCmsArticle }> = async (context: GetStaticPropsContext<{id: string}>) => { const { id } = context.params @@ -50,6 +51,9 @@ const ArticleDetail = ({ article }: InferGetStaticPropsType + + { article.title } +

{ article.title }

diff --git a/types/apiClient/$mock.ts b/types/apiClient/$mock.ts new file mode 100644 index 0000000..43a0455 --- /dev/null +++ b/types/apiClient/$mock.ts @@ -0,0 +1,16 @@ +/* eslint-disable */ +import { MockClient, MockConfig } from 'aspida-mock' +import api from './$api' +import mock0 from './articles/index' +import mock1 from './articles/_cmsId@string/index' + +export const mockRoutes = () => [ + { path: '/articles', methods: mock0 }, + { path: '/articles/_cmsId@string', methods: mock1 } +] + +export default (client: MockClient, config?: MockConfig) => { + client.attachRoutes(mockRoutes(), config) + + return api(client) +} diff --git a/types/apiClient/articles/_cmsId@string/index.ts b/types/apiClient/articles/_cmsId@string/index.ts index 9d08535..0fbcde3 100644 --- a/types/apiClient/articles/_cmsId@string/index.ts +++ b/types/apiClient/articles/_cmsId@string/index.ts @@ -1,6 +1,23 @@ import { MicroCmsArticle } from '../../../microcms/type' +import { mockMethods } from 'aspida-mock/dist' export interface Methods { get: { resBody: MicroCmsArticle } } + +export default mockMethods({ + get: ({ query, reqHeaders, reqBody }) => ({ + status: 200, + resHeaders: {}, + resBody: { + title: 'title mock', + description: 'description mock', + body: 'body mock', + id: 'XXXX', + createdAt: '2020-08-09T13:49:53.413Z', + updatedAt: '2020-08-09T13:49:53.413Z', + publishedAt: '2020-08-09T13:49:53.413Z', + } + }) +}) \ No newline at end of file diff --git a/types/apiClient/articles/index.ts b/types/apiClient/articles/index.ts index 37d6a08..45b7d8f 100644 --- a/types/apiClient/articles/index.ts +++ b/types/apiClient/articles/index.ts @@ -1,7 +1,28 @@ import { MicroCmsArticle } from '../../microcms/type' +import { mockMethods } from 'aspida-mock/dist' export interface Methods { get: { resBody: { contents: MicroCmsArticle[] } } } + +export default mockMethods({ + get: ({ query, reqHeaders, reqBody }) => ({ + status: 200, + resHeaders: {}, + resBody: { + contents: [ + { + title: 'title mock', + description: 'description mock', + body: 'body mock', + id: 'XXXX', + createdAt: '2020-08-09T13:49:53.413Z', + updatedAt: '2020-08-09T13:49:53.413Z', + publishedAt: '2020-08-09T13:49:53.413Z', + } + ] + } + }) +}) \ No newline at end of file diff --git a/types/microcms/type.ts b/types/microcms/type.ts index 99f620b..9059a05 100644 --- a/types/microcms/type.ts +++ b/types/microcms/type.ts @@ -1,16 +1,10 @@ -export type MicroCmsArticle = MicroCmsIdentity & MicroCmsArticleCntent & MicroCmsImage - -type MicroCmsImage = { - // サムネ - image_url: { - url: string - } -} +export type MicroCmsArticle = MicroCmsIdentity & MicroCmsArticleCntent type MicroCmsIdentity = { id: string createdAt: string updatedAt: string + publishedAt: string } type MicroCmsArticleCntent = { diff --git a/yarn.lock b/yarn.lock index 16e15b7..8d82684 100644 --- a/yarn.lock +++ b/yarn.lock @@ -52,12 +52,12 @@ dependencies: cross-fetch "3.0.5" -"@aspida/fetch@^0.8.1": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@aspida/fetch/-/fetch-0.8.1.tgz#cacd409a4d5f764f90f26b8ded1da9cfe32ae7bd" - integrity sha512-Ox2UAF8XjPeEuTn8/Pq87Na6gA641QOn+vhKtFhwbYmD84eZ12Gk5qxW8OvReOkIixZK+lx0PgKJYv6onji09Q== +"@aspida/axios@^0.10.2": + version "0.10.2" + resolved "https://registry.yarnpkg.com/@aspida/axios/-/axios-0.10.2.tgz#0d1a835a9bfdd6ffef1ae4d3b0da7bff283312c4" + integrity sha512-PS904nIERssoDjH+uSe4W2nGHBFUzu55i0cDHWjBP9PCtF4T8btl3eJx1xTDCQSCs9NThVPbb/XCmoIQm2WbDA== dependencies: - aspida "^0.20.2" + aspida "^0.20.3" "@babel/code-frame@7.8.3": version "7.8.3" @@ -1055,6 +1055,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== +"@types/minimist@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" + integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= + "@types/node@^14.0.27": version "14.0.27" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.27.tgz#a151873af5a5e851b51b3b065c9e63390a9e0eb1" @@ -1494,12 +1499,18 @@ asn1.js@^4.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -aspida@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/aspida/-/aspida-0.20.2.tgz#766d9cb616674e8bebade9e7fccb180c09fcd37e" - integrity sha512-TXB75EVfOg8toIsnc+6HLjThkC+2MM8FDGIgf2xIzCgIHUfShQbvDF5Jtn2241JhJ5vBzZvgBl01Pj/74TFAWQ== +aspida-mock@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/aspida-mock/-/aspida-mock-0.7.1.tgz#8a1f83f12fbe61fde4bc78e545f52bad688181ce" + integrity sha512-TXI1+A+E89rQmSyukaYMNeXnmXM1bdji05d7QbOkSOjKzb2kcglAnPyMcDYYL4Dj+FHwwCd9BOucbls+tmVivQ== + +aspida@^0.20.3: + version "0.20.3" + resolved "https://registry.yarnpkg.com/aspida/-/aspida-0.20.3.tgz#86c8d88e38fa92973f1bddedb913508476dfe660" + integrity sha512-XOt8Udd86BE33ku/bVGLNxmVFhDN+IlV4i8tK1WIhaWtGdBalP0dC5c4PBDhuWraKPgjUzNNw+utwF9HLV0mgg== dependencies: - chokidar "^3.4.1" + "@types/minimist" "^1.2.0" + chokidar "^3.4.2" minimist "^1.2.5" assert@1.4.1: @@ -1547,6 +1558,13 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +axios@^0.19.2: + version "0.19.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" + integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA== + dependencies: + follow-redirects "1.5.10" + babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" @@ -1944,6 +1962,21 @@ chokidar@^3.4.1: optionalDependencies: fsevents "~2.1.2" +chokidar@^3.4.2: + version "3.4.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" + integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.4.0" + optionalDependencies: + fsevents "~2.1.2" + chownr@^1.1.1, chownr@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -2457,6 +2490,13 @@ data-uri-to-buffer@3.0.0: dependencies: buffer-from "^1.1.1" +debug@=3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -3091,6 +3131,13 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" +follow-redirects@1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" + integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== + dependencies: + debug "=3.1.0" + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"