aboutsummaryrefslogtreecommitdiffstats
path: root/src/types
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-09-19 18:13:57 +0200
committerArmand Philippot <git@armandphilippot.com>2023-09-19 19:12:31 +0200
commit2faf2e34331703b3bdea3eb487cb8799c8d65377 (patch)
treededc6557ddaa8fedd42d9bdf77950f8f9168ebcb /src/types
parentd1fe9e2164fc5c8fd767b456eecc2a4eb929a33f (diff)
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.
Diffstat (limited to 'src/types')
-rw-r--r--src/types/app.ts132
-rw-r--r--src/types/graphql/generics.ts25
-rw-r--r--src/types/graphql/mutations.ts61
-rw-r--r--src/types/graphql/queries.ts147
-rw-r--r--src/types/mdx.ts22
-rw-r--r--src/types/raw-data.ts111
-rw-r--r--src/types/swr.ts5
7 files changed, 503 insertions, 0 deletions
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<T = {}> = NextPage<T> & {
+ getLayout?: (
+ page: ReactElement,
+ options: NextPageWithLayoutOptions
+ ) => ReactNode;
+};
+
+// modified version - allows for custom pageProps type, falling back to 'any'
+type AppProps<P = any> = {
+ pageProps: P;
+} & Omit<NextAppProps<P>, 'pageProps'>;
+
+type CustomPageProps = {
+ translation: Record<string, string> | Record<string, MessageFormatElement[]>;
+};
+
+export type AppPropsWithLayout = AppProps<CustomPageProps> & {
+ Component: NextPageWithLayout;
+};
+
+export type ContentKind =
+ | 'article'
+ | 'comment'
+ | 'page'
+ | 'project'
+ | 'thematic'
+ | 'topic';
+
+export type Author<T extends ContentKind> = {
+ 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<ContentKind, 'comment'>;
+
+export type Meta<T extends PageKind> = {
+ articles?: T extends 'thematic' | 'topic' ? Article[] : never;
+ author?: T extends 'article' | 'page' ? Author<T> : 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<T extends PageKind> = {
+ content: string;
+ id: number | string;
+ intro: string;
+ meta: Meta<T>;
+ slug: string;
+ title: string;
+};
+
+export type PageLink = {
+ id: number;
+ logo?: Image;
+ name: string;
+ url: string;
+};
+
+export type Article = Page<'article'>;
+export type ArticleCard = Pick<Article, 'id' | 'slug' | 'title'> &
+ Pick<Meta<'article'>, 'cover' | 'dates'>;
+export type Project = Page<'project'>;
+export type ProjectPreview = Omit<Page<'project'>, 'content'>;
+export type ProjectCard = Pick<Page<'project'>, 'id' | 'slug' | 'title'> & {
+ meta: Pick<Meta<'project'>, '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<T> = {
+ cursor: string;
+ node: T;
+};
+
+export type GraphQLEdgesInput = {
+ after?: string;
+ before?: string;
+ first?: number;
+ last?: number;
+};
+
+export type GraphQLNode<T> = {
+ node: T;
+};
+
+export type GraphQLNodes<T> = {
+ 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<T> = {
+ createComment: T;
+};
+
+export type SendMailResponse<T> = {
+ sendEmail: T;
+};
+
+export type MutationsResponseMap<T> = {
+ [sendCommentMutation]: SendCommentResponse<T>;
+ [sendMailMutation]: SendMailResponse<T>;
+};
+
+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<T> = {
+ post: T;
+};
+
+export type ArticlesResponse<T> = {
+ posts: T;
+};
+
+export type CommentsResponse<T> = {
+ comments: T;
+};
+
+export type ThematicResponse<T> = {
+ thematic: T;
+};
+
+export type ThematicsResponse<T> = {
+ thematics: T;
+};
+
+export type TopicResponse<T> = {
+ topic: T;
+};
+
+export type TopicsResponse<T> = {
+ topics: T;
+};
+
+export type EdgesResponse<T> = {
+ edges: GraphQLEdges<T>[];
+ pageInfo: GraphQLPageInfo;
+};
+
+export type EndCursorResponse = {
+ pageInfo: Pick<GraphQLPageInfo, 'endCursor'>;
+};
+
+export type QueriesResponseMap<T> = {
+ [articleBySlugQuery]: ArticleResponse<T>;
+ [articlesCardQuery]: ArticlesResponse<GraphQLNodes<T>>;
+ [articlesEndCursorQuery]: ArticlesResponse<EndCursorResponse>;
+ [articlesQuery]: ArticlesResponse<EdgesResponse<T>>;
+ [articlesSlugQuery]: ArticlesResponse<EdgesResponse<T>>;
+ [commentsQuery]: CommentsResponse<EdgesResponse<T>>;
+ [thematicBySlugQuery]: ThematicResponse<T>;
+ [thematicsListQuery]: ThematicsResponse<EdgesResponse<T>>;
+ [thematicsSlugQuery]: ThematicsResponse<EdgesResponse<T>>;
+ [topicBySlugQuery]: TopicResponse<T>;
+ [topicsListQuery]: TopicsResponse<EdgesResponse<T>>;
+ [topicsSlugQuery]: TopicsResponse<EdgesResponse<T>>;
+ [totalArticlesQuery]: ArticlesResponse<T>;
+ [totalThematicsQuery]: ThematicsResponse<T>;
+ [totalTopicsQuery]: TopicsResponse<T>;
+};
+
+//===========================================================================
+// Queries input types
+//===========================================================================
+
+export type QueryEdges = Pick<GraphQLEdgesInput, 'after' | 'first'>;
+
+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<Meta<'page'>, 'cover' | 'dates' | 'seo'> & {
+ intro: string;
+ title: string;
+};
+
+export type MDXProjectMeta = Exclude<Meta<'project'>, '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<T extends ContentKind> = {
+ description?: T extends 'comment' ? never : string;
+ gravatarUrl?: string;
+ name: string;
+ url?: string;
+};
+
+export type RawComment = {
+ approved: boolean;
+ author: GraphQLNode<RawAuthor<'comment'>>;
+ 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<RawAuthor<'page'>>;
+ contentParts: ContentParts;
+ databaseId: number;
+ date: string;
+ featuredImage: GraphQLNode<RawCover> | 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<GraphQLPageInfo, 'total'>;
+};
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<T> = {
+ data?: T;
+ isLoading: boolean;
+ isError: boolean;
+};