From 2faf2e34331703b3bdea3eb487cb8799c8d65377 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Tue, 19 Sep 2023 18:13:57 +0200 Subject: refactor(build): replace paths aliases with relative paths Using paths aliases starting with "@" can be confusing and can lead to conflict with existings modules. I prefer to use relative paths to avoid extra configuration in tools because of these aliases. --- src/types/app.ts | 132 ++++++++++++++++++++++++++++++++++++ src/types/graphql/generics.ts | 25 +++++++ src/types/graphql/mutations.ts | 61 +++++++++++++++++ src/types/graphql/queries.ts | 147 +++++++++++++++++++++++++++++++++++++++++ src/types/mdx.ts | 22 ++++++ src/types/raw-data.ts | 111 +++++++++++++++++++++++++++++++ src/types/swr.ts | 5 ++ 7 files changed, 503 insertions(+) create mode 100644 src/types/app.ts create mode 100644 src/types/graphql/generics.ts create mode 100644 src/types/graphql/mutations.ts create mode 100644 src/types/graphql/queries.ts create mode 100644 src/types/mdx.ts create mode 100644 src/types/raw-data.ts create mode 100644 src/types/swr.ts (limited to 'src/types') diff --git a/src/types/app.ts b/src/types/app.ts new file mode 100644 index 0000000..64bb3af --- /dev/null +++ b/src/types/app.ts @@ -0,0 +1,132 @@ +import { NextPage } from 'next'; +import { AppProps as NextAppProps } from 'next/app'; +import { ReactElement, ReactNode } from 'react'; +import { MessageFormatElement } from 'react-intl'; + +export type NextPageWithLayoutOptions = { + withExtraPadding?: boolean; + isHome?: boolean; + useGrid?: boolean; +}; + +export type NextPageWithLayout = NextPage & { + getLayout?: ( + page: ReactElement, + options: NextPageWithLayoutOptions + ) => ReactNode; +}; + +// modified version - allows for custom pageProps type, falling back to 'any' +type AppProps

= { + pageProps: P; +} & Omit, 'pageProps'>; + +type CustomPageProps = { + translation: Record | Record; +}; + +export type AppPropsWithLayout = AppProps & { + Component: NextPageWithLayout; +}; + +export type ContentKind = + | 'article' + | 'comment' + | 'page' + | 'project' + | 'thematic' + | 'topic'; + +export type Author = { + avatar?: Image; + description?: T extends 'comment' ? never : string; + name: string; + website?: string; +}; + +export type CommentMeta = { + author: Author<'comment'>; + date: string; +}; + +export type SingleComment = { + approved: boolean; + content: string; + id: number; + meta: CommentMeta; + parentId?: number; + replies: SingleComment[]; +}; + +export type Dates = { + publication: string; + update?: string; +}; + +export type Image = { + alt: string; + height: number; + src: string; + title?: string; + width: number; +}; + +export type Repos = { + github?: string; + gitlab?: string; +}; + +export type SEO = { + description: string; + title: string; +}; + +export type PageKind = Exclude; + +export type Meta = { + articles?: T extends 'thematic' | 'topic' ? Article[] : never; + author?: T extends 'article' | 'page' ? Author : never; + commentsCount?: T extends 'article' ? number : never; + cover?: Image; + dates: Dates; + license?: T extends 'project' ? string : never; + repos?: T extends 'project' ? Repos : never; + seo: SEO; + tagline?: T extends 'project' ? string : never; + technologies?: T extends 'project' ? string[] : never; + thematics?: T extends 'article' | 'topic' ? PageLink[] : never; + topics?: T extends 'article' | 'thematic' ? PageLink[] : never; + website?: T extends 'topic' ? string : never; + wordsCount: number; +}; + +export type Page = { + content: string; + id: number | string; + intro: string; + meta: Meta; + slug: string; + title: string; +}; + +export type PageLink = { + id: number; + logo?: Image; + name: string; + url: string; +}; + +export type Article = Page<'article'>; +export type ArticleCard = Pick & + Pick, 'cover' | 'dates'>; +export type Project = Page<'project'>; +export type ProjectPreview = Omit, 'content'>; +export type ProjectCard = Pick, 'id' | 'slug' | 'title'> & { + meta: Pick, 'cover' | 'dates' | 'tagline' | 'technologies'>; +}; +export type Thematic = Page<'thematic'>; +export type Topic = Page<'topic'>; + +export type Slug = { + slug: string; +}; diff --git a/src/types/graphql/generics.ts b/src/types/graphql/generics.ts new file mode 100644 index 0000000..dec5f10 --- /dev/null +++ b/src/types/graphql/generics.ts @@ -0,0 +1,25 @@ +export type GraphQLPageInfo = { + endCursor: string; + hasNextPage: boolean; + total: number; +}; + +export type GraphQLEdges = { + cursor: string; + node: T; +}; + +export type GraphQLEdgesInput = { + after?: string; + before?: string; + first?: number; + last?: number; +}; + +export type GraphQLNode = { + node: T; +}; + +export type GraphQLNodes = { + nodes: T[]; +}; diff --git a/src/types/graphql/mutations.ts b/src/types/graphql/mutations.ts new file mode 100644 index 0000000..581a46e --- /dev/null +++ b/src/types/graphql/mutations.ts @@ -0,0 +1,61 @@ +import { sendCommentMutation } from '../../services/graphql/comments.mutation'; +import { sendMailMutation } from '../../services/graphql/contact.mutation'; + +//=========================================================================== +// Existing mutations list +//=========================================================================== + +export type Mutations = typeof sendMailMutation | typeof sendCommentMutation; + +//=========================================================================== +// Mutations response types +//=========================================================================== + +export type SendCommentResponse = { + createComment: T; +}; + +export type SendMailResponse = { + sendEmail: T; +}; + +export type MutationsResponseMap = { + [sendCommentMutation]: SendCommentResponse; + [sendMailMutation]: SendMailResponse; +}; + +export type Approved = { + approved: boolean; +}; + +export type SentComment = { + clientMutationId: string; + success: boolean; + comment: Approved | null; +}; + +//=========================================================================== +// Mutations input types +//=========================================================================== + +export type SendCommentInput = { + author: string; + authorEmail: string; + authorUrl: string; + clientMutationId: string; + commentOn: number; + content: string; + parent?: number; +}; + +export type SendMailInput = { + body: string; + clientMutationId: string; + replyTo: string; + subject: string; +}; + +export type MutationsInputMap = { + [sendCommentMutation]: SendCommentInput; + [sendMailMutation]: SendMailInput; +}; diff --git a/src/types/graphql/queries.ts b/src/types/graphql/queries.ts new file mode 100644 index 0000000..fceae30 --- /dev/null +++ b/src/types/graphql/queries.ts @@ -0,0 +1,147 @@ +import { + articleBySlugQuery, + articlesCardQuery, + articlesEndCursorQuery, + articlesQuery, + articlesSlugQuery, + totalArticlesQuery, +} from '../../services/graphql/articles.query'; +import { commentsQuery } from '../../services/graphql/comments.query'; +import { + thematicBySlugQuery, + thematicsListQuery, + thematicsSlugQuery, + totalThematicsQuery, +} from '../../services/graphql/thematics.query'; +import { + topicBySlugQuery, + topicsListQuery, + topicsSlugQuery, + totalTopicsQuery, +} from '../../services/graphql/topics.query'; +import { Slug } from '../app'; +import { RawComment } from '../raw-data'; +import { + GraphQLEdges, + GraphQLEdgesInput, + GraphQLNodes, + GraphQLPageInfo, +} from './generics'; + +//=========================================================================== +// Existing queries list +//=========================================================================== + +export type Queries = + | typeof articlesQuery + | typeof articleBySlugQuery + | typeof articlesCardQuery + | typeof articlesEndCursorQuery + | typeof articlesSlugQuery + | typeof commentsQuery + | typeof thematicBySlugQuery + | typeof thematicsListQuery + | typeof thematicsSlugQuery + | typeof topicBySlugQuery + | typeof topicsListQuery + | typeof topicsSlugQuery + | typeof totalArticlesQuery + | typeof totalThematicsQuery + | typeof totalTopicsQuery; + +//=========================================================================== +// Queries response types +//=========================================================================== + +export type ArticleResponse = { + post: T; +}; + +export type ArticlesResponse = { + posts: T; +}; + +export type CommentsResponse = { + comments: T; +}; + +export type ThematicResponse = { + thematic: T; +}; + +export type ThematicsResponse = { + thematics: T; +}; + +export type TopicResponse = { + topic: T; +}; + +export type TopicsResponse = { + topics: T; +}; + +export type EdgesResponse = { + edges: GraphQLEdges[]; + pageInfo: GraphQLPageInfo; +}; + +export type EndCursorResponse = { + pageInfo: Pick; +}; + +export type QueriesResponseMap = { + [articleBySlugQuery]: ArticleResponse; + [articlesCardQuery]: ArticlesResponse>; + [articlesEndCursorQuery]: ArticlesResponse; + [articlesQuery]: ArticlesResponse>; + [articlesSlugQuery]: ArticlesResponse>; + [commentsQuery]: CommentsResponse>; + [thematicBySlugQuery]: ThematicResponse; + [thematicsListQuery]: ThematicsResponse>; + [thematicsSlugQuery]: ThematicsResponse>; + [topicBySlugQuery]: TopicResponse; + [topicsListQuery]: TopicsResponse>; + [topicsSlugQuery]: TopicsResponse>; + [totalArticlesQuery]: ArticlesResponse; + [totalThematicsQuery]: ThematicsResponse; + [totalTopicsQuery]: TopicsResponse; +}; + +//=========================================================================== +// Queries input types +//=========================================================================== + +export type QueryEdges = Pick; + +export type ContentId = { + contentId: number; +}; + +export type Search = { + search?: string; +}; + +export type QueriesInputMap = { + [articleBySlugQuery]: Slug; + [articlesCardQuery]: QueryEdges & Search; + [articlesEndCursorQuery]: QueryEdges & Search; + [articlesQuery]: QueryEdges & Search; + [articlesSlugQuery]: QueryEdges & Search; + [commentsQuery]: ContentId & QueryEdges; + [thematicBySlugQuery]: Slug; + [thematicsListQuery]: QueryEdges & Search; + [thematicsSlugQuery]: QueryEdges & Search; + [topicBySlugQuery]: Slug; + [topicsListQuery]: QueryEdges & Search; + [topicsSlugQuery]: QueryEdges & Search; + [totalArticlesQuery]: Search; + [totalThematicsQuery]: null; + [totalTopicsQuery]: null; +}; + +export type CommentPage = { + comments: RawComment[]; + hasNextPage: boolean; + endCursor: string; +}; diff --git a/src/types/mdx.ts b/src/types/mdx.ts new file mode 100644 index 0000000..7645ce6 --- /dev/null +++ b/src/types/mdx.ts @@ -0,0 +1,22 @@ +import { StaticImageData } from 'next/image'; +import { Meta } from './app'; + +export type MDXData = { + file: string; + image: MDXImage; +}; + +export type MDXImage = StaticImageData & { + alt: string; + title?: string; +}; + +export type MDXPageMeta = Pick, 'cover' | 'dates' | 'seo'> & { + intro: string; + title: string; +}; + +export type MDXProjectMeta = Exclude, 'wordsCount'> & { + intro: string; + title: string; +}; diff --git a/src/types/raw-data.ts b/src/types/raw-data.ts new file mode 100644 index 0000000..022016e --- /dev/null +++ b/src/types/raw-data.ts @@ -0,0 +1,111 @@ +/** + * Types for raw data coming from GraphQL API. + */ + +import { ContentKind } from './app'; +import { GraphQLNode, GraphQLPageInfo } from './graphql/generics'; + +export type ACFPosts = { + postsInThematic?: RawThematicPreview[]; + postsInTopic?: RawTopicPreview[]; +}; + +export type ACFThematics = { + postsInThematic: RawArticle[]; +}; + +export type ACFTopics = { + officialWebsite: string; + postsInTopic: RawArticle[]; +}; + +export type ContentParts = { + afterMore: string; + beforeMore: string; +}; + +export type Info = { + wordsCount: number; +}; + +export type RawAuthor = { + description?: T extends 'comment' ? never : string; + gravatarUrl?: string; + name: string; + url?: string; +}; + +export type RawComment = { + approved: boolean; + author: GraphQLNode>; + content: string; + databaseId: number; + date: string; + parentDatabaseId: number; +}; + +export type RawCommentsPage = { + comments: RawComment[]; + hasNextPage: boolean; + endCursor: string; +}; + +export type RawCover = { + altText: string; + mediaDetails: { + width: number; + height: number; + }; + sourceUrl: string; + title?: string; +}; + +export type RawArticle = RawPage & { + acfPosts: ACFPosts; + commentCount: number | null; +}; + +export type RawArticlePreview = Pick< + RawArticle, + 'databaseId' | 'date' | 'featuredImage' | 'slug' | 'title' +>; + +export type RawPage = { + author?: GraphQLNode>; + contentParts: ContentParts; + databaseId: number; + date: string; + featuredImage: GraphQLNode | null; + info: Info; + modified: string; + seo?: RawSEO; + slug: string; + title: string; +}; + +export type RawSEO = { + metaDesc: string; + title: string; +}; + +export type RawThematic = RawPage & { + acfThematics: ACFThematics; +}; + +export type RawThematicPreview = Pick< + RawThematic, + 'databaseId' | 'featuredImage' | 'slug' | 'title' +>; + +export type RawTopic = RawPage & { + acfTopics: ACFTopics; +}; + +export type RawTopicPreview = Pick< + RawTopic, + 'databaseId' | 'featuredImage' | 'slug' | 'title' +>; + +export type TotalItems = { + pageInfo: Pick; +}; diff --git a/src/types/swr.ts b/src/types/swr.ts new file mode 100644 index 0000000..4da6b2c --- /dev/null +++ b/src/types/swr.ts @@ -0,0 +1,5 @@ +export type SWRResult = { + data?: T; + isLoading: boolean; + isError: boolean; +}; -- cgit v1.2.3