mirror of
https://github.com/d0zingcat/nextjs-notion-starter-kit.git
synced 2026-05-13 23:16:47 +00:00
feat: moving api/
This commit is contained in:
@@ -1,75 +0,0 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
import got from 'got'
|
||||
import lqip from 'lqip-modern'
|
||||
|
||||
import * as types from '../../lib/types'
|
||||
import * as db from '../../lib/db'
|
||||
|
||||
export default async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
if (req.method !== 'POST') {
|
||||
return res.status(405).send({ error: 'method not allowed' })
|
||||
}
|
||||
|
||||
const { url, id } = req.body
|
||||
|
||||
const result = await createPreviewImage(url, id)
|
||||
|
||||
res.setHeader(
|
||||
'Cache-Control',
|
||||
result.error
|
||||
? 'public, s-maxage=60, max-age=60, stale-while-revalidate=60'
|
||||
: 'public, immutable, s-maxage=31536000, max-age=31536000, stale-while-revalidate=60'
|
||||
)
|
||||
res.status(200).json(result)
|
||||
}
|
||||
|
||||
export async function createPreviewImage(
|
||||
url: string,
|
||||
id: string
|
||||
): Promise<types.PreviewImage> {
|
||||
const doc = db.images.doc(id)
|
||||
|
||||
try {
|
||||
const model = await doc.get()
|
||||
if (model.exists) {
|
||||
return model.data() as types.PreviewImage
|
||||
}
|
||||
|
||||
const { body } = await got(url, { responseType: 'buffer' })
|
||||
const result = await lqip(body)
|
||||
console.log('lqip', result.metadata)
|
||||
|
||||
const image = {
|
||||
url,
|
||||
originalWidth: result.metadata.originalWidth,
|
||||
originalHeight: result.metadata.originalHeight,
|
||||
width: result.metadata.width,
|
||||
height: result.metadata.height,
|
||||
type: result.metadata.type,
|
||||
dataURIBase64: result.metadata.dataURIBase64
|
||||
}
|
||||
|
||||
await doc.create(image)
|
||||
return image
|
||||
} catch (err) {
|
||||
console.error('lqip error', err)
|
||||
|
||||
try {
|
||||
const error: any = {
|
||||
url,
|
||||
error: err.message || 'unknown error'
|
||||
}
|
||||
|
||||
if (err?.response?.statusCode) {
|
||||
error.statusCode = err?.response?.statusCode
|
||||
}
|
||||
|
||||
await doc.create(error)
|
||||
return error
|
||||
} catch (err) {
|
||||
// ignore errors
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import chromium from 'chrome-aws-lambda'
|
||||
import renderSocialImage from 'puppeteer-social-image-transitive-bs'
|
||||
import { getBlockIcon, getBlockTitle } from 'notion-utils'
|
||||
|
||||
import { getPage } from 'lib/notion'
|
||||
import * as types from 'lib/types'
|
||||
import {
|
||||
siteDescription,
|
||||
defaultPageCover,
|
||||
defaultPageIcon,
|
||||
siteDomain,
|
||||
siteName
|
||||
} from 'lib/config'
|
||||
import { getPageDescription } from 'lib/get-page-description'
|
||||
|
||||
export interface SocialImageConfig {
|
||||
title: string
|
||||
subtitle?: string
|
||||
eyebrow?: string
|
||||
logo?: string
|
||||
imageUrl?: string
|
||||
unsplashId?: string
|
||||
unsplashKeywords?: string
|
||||
backgroundImageAnchor?: string
|
||||
backgroundImageOverlay?: boolean
|
||||
background?: string
|
||||
color?: string
|
||||
googleFont?: string
|
||||
fontFamily?: string
|
||||
watermark?: string
|
||||
size?:
|
||||
| 'facebook'
|
||||
| 'twitter'
|
||||
| 'ig-landscape'
|
||||
| 'ig-portrait'
|
||||
| 'ig-square'
|
||||
| 'ig-story'
|
||||
}
|
||||
|
||||
export default async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
if (req.method !== 'GET') {
|
||||
return res.status(405).send({ error: 'method not allowed' })
|
||||
}
|
||||
|
||||
const pageId = req.query.pageId as string
|
||||
|
||||
if (!pageId) {
|
||||
return res.status(400).send({ error: 'missing required parameter pageId' })
|
||||
}
|
||||
|
||||
let recordMap: types.ExtendedRecordMap
|
||||
let block: types.PageBlock
|
||||
|
||||
try {
|
||||
recordMap = await getPage(pageId)
|
||||
|
||||
const pageBlockId = Object.keys(recordMap.block)[0]
|
||||
block = recordMap.block[pageBlockId]?.value as types.PageBlock
|
||||
|
||||
if (!block) {
|
||||
return res.status(404).send({
|
||||
error: `unable to resolve root block for notion page "${pageId}"`
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
return res
|
||||
.status(404)
|
||||
.send({ error: `unable to load notion page "${pageId}"` })
|
||||
}
|
||||
|
||||
// TODO: centralize these default config values
|
||||
const image = await createSocialImage({
|
||||
imageUrl: block.format?.page_cover ?? defaultPageCover,
|
||||
title: getBlockTitle(block, recordMap) ?? siteName,
|
||||
logo: getBlockIcon(block, recordMap) ?? defaultPageIcon,
|
||||
subtitle: getPageDescription(block, recordMap) ?? siteDescription,
|
||||
watermark: siteDomain
|
||||
})
|
||||
|
||||
res.setHeader(
|
||||
'Cache-Control',
|
||||
'public, immutable, s-maxage=31536000, max-age=31536000, stale-while-revalidate=60'
|
||||
)
|
||||
res.setHeader('Content-Type', 'image/jpeg')
|
||||
res.status(200).send(image)
|
||||
}
|
||||
|
||||
async function createSocialImage(params: SocialImageConfig) {
|
||||
let browser
|
||||
|
||||
try {
|
||||
browser = await chromium.puppeteer.launch({
|
||||
args: chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: await chromium.executablePath,
|
||||
headless: true, // chromium.headless,
|
||||
ignoreHTTPSErrors: true
|
||||
})
|
||||
|
||||
const res = await renderSocialImage({
|
||||
template: 'article',
|
||||
templateParams: params,
|
||||
templateStyles: `h1 { font-size: 96px; text-align: center; } h2 { font-size: 32px; }`,
|
||||
size: params.size,
|
||||
browser
|
||||
})
|
||||
|
||||
return res
|
||||
} finally {
|
||||
if (browser) {
|
||||
await browser.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user