refactor: LPE types

This commit is contained in:
Hossein Mehrabi 2023-08-10 13:30:04 +03:30
parent 1035bccc9a
commit 9abacc4f92
No known key found for this signature in database
GPG Key ID: 45C04964191AFAA1
9 changed files with 98 additions and 65 deletions

View File

@ -49,7 +49,6 @@ export const getStaticProps = async () => {
} = await unbodyApi.getHomepagePosts() } = await unbodyApi.getHomepagePosts()
const { data: topics, errors: topicErrors } = await unbodyApi.getTopics() const { data: topics, errors: topicErrors } = await unbodyApi.getTopics()
await unbodyApi.getPodcastsInfo()
return { return {
props: { props: {

View File

@ -25,14 +25,12 @@ export const ArticleDataType: UnbodyDataTypeConfig<
classes: 'article', classes: 'article',
}) })
const blocks = await helpers.dataTypes.transformMany< const blocks =
any, await helpers.dataTypes.transformMany<LPE.Article.ContentBlock>(
LPE.Article.ContentBlock [...textBlock, ...imageBlock],
>( [...(data.blocks || [])].sort((a, b) => a.order - b.order),
[...textBlock, ...imageBlock], data,
[...(data.blocks || [])].sort((a, b) => a.order - b.order), )
data,
)
const readingTime = calcReadingTime( const readingTime = calcReadingTime(
(data.blocks || []) (data.blocks || [])

View File

@ -43,7 +43,7 @@ export const ArticleSearchResultItemDataType: UnbodyDataTypeConfig<
), ),
} }
const document = helpers.dataTypes.transform( const document = await helpers.dataTypes.transform(
[helpers.dataTypes.getOne({ key: 'ArticleDocument' })!], [helpers.dataTypes.getOne({ key: 'ArticleDocument' })!],
'document' in data && data.document?.[0], 'document' in data && data.document?.[0],
) )

View File

@ -2,14 +2,14 @@ import { LPE } from '../../../types/lpe.types'
import { UnbodyResGoogleDocData } from '../unbody.types' import { UnbodyResGoogleDocData } from '../unbody.types'
import { UnbodyDataTypeConfig } from './types' import { UnbodyDataTypeConfig } from './types'
export const PodcastInfoDataType: UnbodyDataTypeConfig< export const PodcastShowDataType: UnbodyDataTypeConfig<
LPE.Article.Data, LPE.Article.Data,
LPE.Podcast.Info, LPE.Podcast.Show,
UnbodyResGoogleDocData UnbodyResGoogleDocData
> = { > = {
key: 'PodcastInfoDocument', key: 'PodcastShowDocument',
objectType: 'GoogleDoc', objectType: 'GoogleDoc',
classes: ['podcast', 'document'], classes: ['podcast', 'show', 'document'],
isMatch: (helpers, data, original) => isMatch: (helpers, data, original) =>
original original

View File

@ -62,7 +62,7 @@ export class UnbodyDataTypes {
return dataTypes return dataTypes
} }
transform = async <T = any, O = any>( transform = async <O = any, T = any>(
pipeline: UnbodyDataTypeConfig[], pipeline: UnbodyDataTypeConfig[],
data: T, data: T,
root?: any, root?: any,
@ -78,11 +78,11 @@ export class UnbodyDataTypes {
return obj as O | Promise<O> return obj as O | Promise<O>
} }
transformMany = async <T = any, O = any>( transformMany = async <O = any, T = any>(
pipeline: UnbodyDataTypeConfig[], pipeline: UnbodyDataTypeConfig[],
data: T[], data: T[],
root?: any, root?: any,
): Promise<O[]> => { ): Promise<O[]> => {
return Promise.all(data.map((d) => this.transform<T, O>(pipeline, d, root))) return Promise.all(data.map((d) => this.transform<O, T>(pipeline, d, root)))
} }
} }

View File

@ -3,7 +3,7 @@ import { ArticleImageBlockDataType } from './ArticleImageBlock.dataType'
import { ArticleSearchResultItemDataType } from './ArticleSearchResultItem.dataType' import { ArticleSearchResultItemDataType } from './ArticleSearchResultItem.dataType'
import { ArticleTextBlockDataType } from './ArticleTextBlock.dataType' import { ArticleTextBlockDataType } from './ArticleTextBlock.dataType'
import { ImageBlockDataType } from './ImageBlock.dataType' import { ImageBlockDataType } from './ImageBlock.dataType'
import { PodcastInfoDataType } from './PodcastInfoDocument.dataType' import { PodcastShowDataType } from './PodcastShowDocument.dataType'
import { TextBlockDataType } from './TextBlock.dataType' import { TextBlockDataType } from './TextBlock.dataType'
import { UnbodyDataTypes } from './UnbodyDataTypes' import { UnbodyDataTypes } from './UnbodyDataTypes'
@ -14,5 +14,5 @@ export const unbodyDataTypes = new UnbodyDataTypes([
ArticleTextBlockDataType, ArticleTextBlockDataType,
ArticleImageBlockDataType, ArticleImageBlockDataType,
ArticleSearchResultItemDataType, ArticleSearchResultItemDataType,
PodcastInfoDataType, PodcastShowDataType,
]) ])

View File

@ -39,7 +39,8 @@ export const UnbodyDataTypeKeys = {
ArticleTextBlock: 'ArticleTextBlock', ArticleTextBlock: 'ArticleTextBlock',
ArticleImageBlock: 'ArticleImageBlock', ArticleImageBlock: 'ArticleImageBlock',
ArticleSearchResultItem: 'ArticleSearchResultItem', ArticleSearchResultItem: 'ArticleSearchResultItem',
PodcastInfoDocument: 'PodcastInfoDocument', PodcastShowDocument: 'PodcastShowDocument',
PodcastEpisodeDocument: 'PodcastEpisodeDocument',
} as const } as const
export type UnbodyDataTypeKey = export type UnbodyDataTypeKey =
@ -48,6 +49,8 @@ export type UnbodyDataTypeKey =
export const UnbodyDataTypeClasses = { export const UnbodyDataTypeClasses = {
Article: 'article', Article: 'article',
Podcast: 'podcast', Podcast: 'podcast',
Show: 'show',
Episode: 'episode',
Document: 'document', Document: 'document',
Search: 'search', Search: 'search',
} as const } as const

View File

@ -25,7 +25,7 @@ const articleDocument = unbodyDataTypes.get({
const articleSearchResultItem = unbodyDataTypes.get({ const articleSearchResultItem = unbodyDataTypes.get({
classes: ['article', 'search'], classes: ['article', 'search'],
})! })!
const podcastInfoDocument = unbodyDataTypes.get({ const podcastShowDocument = unbodyDataTypes.get({
classes: ['podcast', 'document'], classes: ['podcast', 'document'],
objectType: 'GoogleDoc', objectType: 'GoogleDoc',
})! })!
@ -99,10 +99,14 @@ export class UnbodyService {
const docs = data.Get?.GoogleDoc || [] const docs = data.Get?.GoogleDoc || []
const [doc] = docs const [doc] = docs
return this.handleResponse( const result = doc
(doc && (await unbodyDataTypes.transform(articleDocument, doc))) || ? await unbodyDataTypes.transform<LPE.Article.Data>(
null, articleDocument,
) doc,
)
: null
return this.handleResponse(result)
} catch (error) { } catch (error) {
return this.handleResponse(null, error) return this.handleResponse(null, error)
} }
@ -130,8 +134,9 @@ export class UnbodyService {
return this.handleResponse({ return this.handleResponse({
featured: (await this.getFeaturedPost())?.data, featured: (await this.getFeaturedPost())?.data,
posts: await Promise.all( posts: await unbodyDataTypes.transformMany<LPE.Article.Data>(
docs.map((doc) => unbodyDataTypes.transform(articleDocument, doc)), articleDocument,
docs,
), ),
}) })
} catch (error) { } catch (error) {
@ -194,7 +199,10 @@ export class UnbodyService {
return doc return doc
? this.handleResponse( ? this.handleResponse(
await unbodyDataTypes.transform(articleDocument, doc), await unbodyDataTypes.transform<LPE.Article.Data>(
articleDocument,
doc,
),
) )
: this.handleResponse(null, 'No data') : this.handleResponse(null, 'No data')
} catch (error) { } catch (error) {
@ -258,8 +266,9 @@ export class UnbodyService {
return this.handleResponse([], 'No data for same authors') return this.handleResponse([], 'No data for same authors')
return this.handleResponse( return this.handleResponse(
await Promise.all( await unbodyDataTypes.transformMany<LPE.Article.Metadata>(
docs.map((doc) => unbodyDataTypes.transform(articleDocument, doc)), articleDocument,
docs,
), ),
) )
} catch (error) { } catch (error) {
@ -325,18 +334,13 @@ export class UnbodyService {
}, },
}) })
const blocks = ( const blocks = await unbodyDataTypes.transformMany<
await Promise.all( SearchResultItem<LPE.Article.ContentBlock>
[...(ImageBlock || []), ...(TextBlock || [])].map((block) => >(articleSearchResultItem, [...(ImageBlock || []), ...(TextBlock || [])])
unbodyDataTypes.transform<any, SearchResultItem<LPE.Article.Data>>(
articleSearchResultItem,
block,
),
),
)
).sort((a, b) => b.score - a.score)
return this.handleResponse(blocks) const result = blocks.sort((a, b) => b.score - a.score)
return this.handleResponse(result)
} catch (error) { } catch (error) {
return this.handleResponse([], error) return this.handleResponse([], error)
} }
@ -378,11 +382,12 @@ export class UnbodyService {
if (!data) return this.handleResponse([], 'No data') if (!data) return this.handleResponse([], 'No data')
const docs = data.Get.GoogleDoc.map((doc) => const result = await unbodyDataTypes.transformMany<LPE.Article.Data>(
unbodyDataTypes.transform(articleSearchResultItem, doc), articleSearchResultItem,
data.Get.GoogleDoc || [],
) )
return this.handleResponse(docs) return this.handleResponse(result)
} catch (error) { } catch (error) {
return this.handleResponse(null, error) return this.handleResponse(null, error)
} }
@ -405,7 +410,7 @@ export class UnbodyService {
} }
} }
getPodcastsInfo = async (): Promise<ApiResponse<LPE.Podcast.Info[]>> => { getPodcastShows = async (): Promise<ApiResponse<LPE.Podcast.Show[]>> => {
try { try {
const { data } = await this.client.query({ const { data } = await this.client.query({
query: GetArticlePostQueryDocument, query: GetArticlePostQueryDocument,
@ -419,10 +424,11 @@ export class UnbodyService {
}) })
const docs = data.Get.GoogleDoc const docs = data.Get.GoogleDoc
const result = await unbodyDataTypes.transformMany( const result = await unbodyDataTypes.transformMany<LPE.Podcast.Show>(
podcastInfoDocument, podcastShowDocument,
docs, docs,
) )
console.log(JSON.stringify(result)) console.log(JSON.stringify(result))
return this.handleResponse([]) return this.handleResponse([])

View File

@ -17,7 +17,7 @@ export namespace LPE {
} }
} }
export namespace Article { export namespace Post {
export type Footnote = { export type Footnote = {
index: number index: number
id: string id: string
@ -55,28 +55,40 @@ export namespace LPE {
export type ContentBlockLabel = export type ContentBlockLabel =
(typeof ContentBlockLabels)[keyof typeof ContentBlockLabels] (typeof ContentBlockLabels)[keyof typeof ContentBlockLabels]
export type ContentBlockCommon = { export type ContentBlockCommon<D = any> = {
id: string id: string
order: number order: number
labels: ContentBlockLabel[] labels: ContentBlockLabel[]
document?: Partial<Article.Metadata> document?: D
} }
export type TextBlock = ContentBlockCommon & { export type TextBlock<D = any> = ContentBlockCommon<D> & {
text: string text: string
html: string html: string
tagName: string tagName: string
classNames: string[] classNames: string[]
type: Extract<ContentBlockType, 'text'> type: Extract<ContentBlockType, 'text'>
footnotes: Article.Footnotes footnotes: Post.Footnotes
} }
export type ImageBlock = ContentBlockCommon & export type ImageBlock<D = any> = ContentBlockCommon<D> &
Image.Document & { Image.Document & {
type: Extract<ContentBlockType, 'image'> type: Extract<ContentBlockType, 'image'>
} }
export type ContentBlock = TextBlock | ImageBlock export type ContentBlock<D = any> = TextBlock<D> | ImageBlock<D>
}
export namespace Article {
export type Toc = Post.Toc
export type TocItem = Post.TocItem
export type TextBlock = Post.TextBlock<Metadata>
export type ImageBlock = Post.ImageBlock<Metadata>
export type ContentBlock = Post.ContentBlock<Metadata>
export type Footnote = Post.Footnote
export type Footnotes = Post.Footnotes
export const ContentBlockLabels = Post.ContentBlockLabels
export type ContentBlockLabel = Post.ContentBlockLabel
export type Metadata = { export type Metadata = {
id: string id: string
@ -92,7 +104,7 @@ export namespace LPE {
} }
export type Data = Article.Metadata & { export type Data = Article.Metadata & {
toc: Article.Toc toc: Post.Toc
readingTime: number readingTime: number
coverImage: Image.Document | null coverImage: Image.Document | null
content: Array<Article.ContentBlock> content: Array<Article.ContentBlock>
@ -106,28 +118,43 @@ export namespace LPE {
} }
export namespace Podcast { export namespace Podcast {
export type Info = { export type Show = {
id: string id: string
slug: string slug: string
title: string title: string
description: string description: string
coverImage: Image.Document | null logo: Image.Document
hosts: Author.Document[]
episodes?: Omit<Podcast.Document, 'show'>[]
}
export type Metadata = {
id: string
slug: string
title: string
tags: string[]
summary: string
publishedAt: string
episodeNumber: number
} }
export type TranscriptionItem = { export type TranscriptionItem = {
text: string text: string
start: number start?: number
end: number end?: number
speaker: string speaker?: string
} }
export type EpisodeExtra = { export type Content = {
info: Partial<Podcast.Info> coverImage?: Post.ImageBlock
transcription: TranscriptionItem[] transcription: TranscriptionItem[]
references?: Post.TextBlock[]
credits?: Post.TextBlock[]
} }
export type Episode = Article.Data & EpisodeExtra export type Document = Metadata &
Content & {
export type Document = Info & { episodes: Podcast.Episode[] } show: Show
}
} }
} }