diff --git a/components/NotionPage.tsx b/components/NotionPage.tsx index ba25c7f..ea9f27a 100644 --- a/components/NotionPage.tsx +++ b/components/NotionPage.tsx @@ -4,7 +4,6 @@ import Link from 'next/link' import { useRouter } from 'next/router' import { useLocalStorage, useSearchParam } from 'react-use' import BodyClassName from 'react-body-classname' -import isUrl from 'is-url-superb' // core notion renderer import { NotionRenderer } from 'react-notion-x' @@ -15,6 +14,7 @@ import * as types from 'lib/types' import { mapPageUrl, getCanonicalPageUrl } from 'lib/map-page-url' import { mapNotionImageUrl } from 'lib/map-image-url' import { isDev } from 'lib/config' +import { searchNotion } from 'lib/search-notion' // components import { CustomFont } from './CustomFont' @@ -130,13 +130,14 @@ export const NotionPage: React.FC = ({ ) }} recordMap={recordMap} + rootPageId={site.rootNotionPageId} fullPage={!isLiteMode} darkMode={isDarkMode} previewImages={site.previewImages !== false} showCollectionViewDropdown={false} mapPageUrl={siteMapPageUrl} mapImageUrl={mapNotionImageUrl} - rootPageId={site.rootNotionPageId} + searchNotion={searchNotion} /> diff --git a/lib/config.ts b/lib/config.ts index 7d4e77f..f73030b 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -16,3 +16,10 @@ export const fathomConfig = fathomId excludedDomains: ['localhost', 'localhost:3000'] } : undefined + +// TODO: address duplication between server-side env and client-side config +export const apiBaseUrl = `/api` +export const api = { + createPreviewImage: `${apiBaseUrl}/create-preview-image`, + searchNotion: `${apiBaseUrl}/search-notion` +} diff --git a/lib/env.ts b/lib/env.ts index 7f60a53..38a42ab 100644 --- a/lib/env.ts +++ b/lib/env.ts @@ -15,7 +15,8 @@ export const host = isDev ? `http://localhost:${port}` : `https://${domain}` export const apiBaseUrl = `${host}/api` export const api = { - createPreviewImage: `${apiBaseUrl}/create-preview-image` + createPreviewImage: `${apiBaseUrl}/create-preview-image`, + searchNotion: `${apiBaseUrl}/search-notion` } export const googleProjectId = getEnv('GCLOUD_PROJECT') diff --git a/lib/notion.ts b/lib/notion.ts index a217ba8..09ab24e 100644 --- a/lib/notion.ts +++ b/lib/notion.ts @@ -1,5 +1,5 @@ import { NotionAPI } from 'notion-client' -import { ExtendedRecordMap } from 'notion-types' +import { ExtendedRecordMap, SearchParams, SearchResults } from 'notion-types' import { getPreviewImages } from './get-preview-images' import { mapNotionImageUrl } from './map-image-url' @@ -52,14 +52,6 @@ export async function getPage(pageId: string): Promise { return recordMap } -// export const getSearch = pMemoize(getSearchImpl, { maxAge: 20000 }) - -// async function getSearchImpl( -// params: types.SearchParams -// ): Promise { -// const url = `${apiBaseUrl}/v1/search?${new URLSearchParams( -// params as any -// ).toString()}` - -// return fetch(url).then((res) => res.json()) -// } +export async function search(params: SearchParams): Promise { + return notion.search(params) +} diff --git a/lib/search-notion.ts b/lib/search-notion.ts new file mode 100644 index 0000000..289f2c1 --- /dev/null +++ b/lib/search-notion.ts @@ -0,0 +1,39 @@ +// import ky from 'ky' +import fetch from 'isomorphic-unfetch' +import pMemoize from 'p-memoize' + +import { api } from './config' +import * as types from './types' + +export const searchNotion = pMemoize(searchNotionImpl, { maxAge: 10000 }) + +async function searchNotionImpl( + params: types.SearchParams +): Promise { + return fetch(api.searchNotion, { + method: 'POST', + body: JSON.stringify(params), + headers: { + 'content-type': 'application/json' + } + }) + .then((res) => { + console.log(res) + + if (res.ok) { + return res + } + + // convert non-2xx HTTP responses into errors + const error: any = new Error(res.statusText) + error.response = res + return Promise.reject(error) + }) + .then((res) => res.json()) + + // return ky + // .post(api.searchNotion, { + // json: params + // }) + // .json() +} diff --git a/package.json b/package.json index 35f76ec..61c2334 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "dangerously-set-html-content": "^1.0.8", "fathom-client": "^3.0.0", "got": "^11.8.1", - "is-url-superb": "^5.0.0", + "isomorphic-unfetch": "^3.1.0", "lqip-modern": "^1.1.3", "next": "^10.0.6-canary.2", "notion-client": "^3.0.1", diff --git a/pages/api/search-notion.ts b/pages/api/search-notion.ts new file mode 100644 index 0000000..46a46be --- /dev/null +++ b/pages/api/search-notion.ts @@ -0,0 +1,20 @@ +import { NextApiRequest, NextApiResponse } from 'next' + +import * as types from 'lib/types' +import * as notion from 'lib/notion' + +export default async (req: NextApiRequest, res: NextApiResponse) => { + if (req.method !== 'POST') { + return res.status(405).send({ error: 'method not allowed' }) + } + + const searchParams: types.SearchParams = req.body + + const results = await notion.search(searchParams) + + res.setHeader( + 'Cache-Control', + 'public, s-maxage=60, max-age=60, stale-while-revalidate=60' + ) + res.status(200).json(results) +} diff --git a/tsconfig.json b/tsconfig.json index e07630d..40a78a5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "target": "es2016", "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": false, + "allowJs": true, "skipLibCheck": true, "strict": false, "forceConsistentCasingInFileNames": true, diff --git a/yarn.lock b/yarn.lock index 5f0c72c..407f88a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3603,11 +3603,6 @@ is-url-superb@^4.0.0: resolved "https://registry.yarnpkg.com/is-url-superb/-/is-url-superb-4.0.0.tgz#b54d1d2499bb16792748ac967aa3ecb41a33a8c2" integrity sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA== -is-url-superb@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-url-superb/-/is-url-superb-5.0.0.tgz#8b3c0ce1ceacaa7561fefb9510018106091dccf5" - integrity sha512-jGkG59ra7/JlcV8ap3dsc0M79IgpuFU/obfsSf6X5D0z1NVvFTFuzt4ob7nfBTZEPbTwjGXVKNQDfWfPghapKQ== - isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -3630,6 +3625,14 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= +isomorphic-unfetch@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz#87341d5f4f7b63843d468438128cb087b7c3e98f" + integrity sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q== + dependencies: + node-fetch "^2.6.1" + unfetch "^4.2.0" + jest-worker@24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" @@ -6207,6 +6210,11 @@ typescript@^4.0.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== +unfetch@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" + integrity sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA== + unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"