Skip to content

Commit

Permalink
chore: improved types
Browse files Browse the repository at this point in the history
  • Loading branch information
ovflowd committed Dec 26, 2024
1 parent 2589a37 commit 6df8fb5
Show file tree
Hide file tree
Showing 15 changed files with 123 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ import {
providePaginatedBlogPosts,
} from '@/next-data/providers/blogData';
import { defaultLocale } from '@/next.locales.mjs';
import type { BlogCategory } from '@/types';

type DynamicStaticPaths = { locale: string; category: string; page: string };
type DynamicStaticPaths = {
locale: string;
category: BlogCategory;
page: string;
};
type StaticParams = { params: Promise<DynamicStaticPaths> };

// This is the Route Handler for the `GET` method which handles the request
Expand Down
3 changes: 2 additions & 1 deletion apps/site/components/Common/BlogPostCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import FormattedTime from '@/components/Common/FormattedTime';
import Preview from '@/components/Common/Preview';
import Link from '@/components/Link';
import WithAvatarGroup from '@/components/withAvatarGroup';
import type { BlogCategory } from '@/types';
import { mapBlogCategoryToPreviewType } from '@/util/blogUtils';

import styles from './index.module.css';

type BlogPostCardProps = {
title: string;
category: string;
category: BlogCategory;
description?: string;
authors?: Array<string>;
date?: Date;
Expand Down
4 changes: 2 additions & 2 deletions apps/site/components/Containers/MetaBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Link from '@/components/Link';
import styles from './index.module.css';

type MetaBarProps = {
items: Record<string, React.ReactNode>;
items: Partial<Record<IntlMessageKeys, React.ReactNode>>;
headings?: {
items: Array<Heading>;
minDepth?: number;
Expand All @@ -33,7 +33,7 @@ const MetaBar: FC<MetaBarProps> = ({ items, headings }) => {
.filter(([, value]) => !!value)
.map(([key, value]) => (
<Fragment key={key}>
<dt>{t(key)}</dt>
<dt>{t(key as IntlMessageKeys)}</dt>
<dd>{value}</dd>
</Fragment>
))}
Expand Down
31 changes: 14 additions & 17 deletions apps/site/components/Downloads/Release/ReleaseCodeBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ const ReleaseCodeBox: FC = () => {
// Determines if the code box should render the skeleton loader
const renderSkeleton = os === 'LOADING' || platform === '';

// Defines fallbacks for the currentPlatform object
const {
label = '',
url = '',
info = 'layouts.download.codeBox.platformInfo.default',
} = currentPlatform ?? {};

return (
<div className="mb-6 mt-4 flex flex-col gap-2">
{release.status === 'End-of-life' && (
Expand All @@ -78,11 +85,11 @@ const ReleaseCodeBox: FC = () => {
</AlertBox>
)}

<Skeleton loading={renderSkeleton} hide={currentPlatform?.recommended}>
{!currentPlatform || currentPlatform.recommended || (
<AlertBox title="Info" level="info" size="small">
{t('layouts.download.codeBox.communityPlatformInfo')}
</AlertBox>
</Skeleton>
)}

<Skeleton loading={renderSkeleton}>
<JSXCodeBox language={codeLanguage} className="min-h-[15.5rem]">
Expand All @@ -92,22 +99,12 @@ const ReleaseCodeBox: FC = () => {

<span className="text-center text-xs text-neutral-800 dark:text-neutral-200">
<Skeleton loading={renderSkeleton} hide={!currentPlatform}>
{t(
currentPlatform?.bottomInfo ??
'layouts.download.codeBox.platformInfo.default',
{ platform: currentPlatform?.label as string }
)}
</Skeleton>

<br />

<Skeleton loading={renderSkeleton} hide={!currentPlatform}>
{t(info, { platform: label })}{' '}
{t.rich('layouts.download.codeBox.externalSupportInfo', {
platform: currentPlatform?.label as string,
b: chunks => <b>{chunks}</b>,
link: chunks => (
<LinkWithArrow href={currentPlatform?.url}>
{chunks}
platform: label,
link: text => (
<LinkWithArrow href={url}>
<b>{text}</b>
</LinkWithArrow>
),
})}
Expand Down
3 changes: 2 additions & 1 deletion apps/site/components/withBlogCrossLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import type { FC } from 'react';
import { getClientContext } from '@/client-context';
import CrossLink from '@/components/Common/CrossLink';
import getBlogData from '@/next-data/blogData';
import type { BlogCategory } from '@/types';

const WithBlogCrossLinks: FC = async () => {
const { pathname } = getClientContext();

// Extracts from the static URL the components used for the Blog Post slug
const [, , category, postname] = pathname.split('/');

const { posts } = await getBlogData(category);
const { posts } = await getBlogData(category as BlogCategory);

const currentItem = posts.findIndex(
({ slug }) => slug === `/blog/${category}/${postname}`
Expand Down
29 changes: 29 additions & 0 deletions apps/site/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type baseMessages from '@node-core/website-i18n/locales/en.json';
import type { MessageKeys, NestedValueOf, NestedKeyOf } from 'next-intl';

declare global {
// Defines a type for all the IntlMessage shape (which is used internall by next-intl)
// @see https://next-intl.dev/docs/workflows/typescript
type IntlMessages = typeof baseMessages;

// Defines a generic type for all available i18n translation keys, by default not using any namespace
type IntlMessageKeys<
NestedKey extends NamespaceKeys<
IntlMessages,
NestedKeyOf<IntlMessages>
> = never,
> = MessageKeys<
NestedValueOf<
{ '!': IntlMessages },
[NestedKey] extends [never] ? '!' : `!.${NestedKey}`
>,
NestedKeyOf<
NestedValueOf<
{ '!': IntlMessages },
[NestedKey] extends [never] ? '!' : `!.${NestedKey}`
>
>
>;
}

export {};
2 changes: 1 addition & 1 deletion apps/site/hooks/react-generic/useSiteNavigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const useSiteNavigation = () => {
const t = useTranslations();

const mapNavigationEntries = (entries: Navigation, context: Context = {}) => {
const getFormattedMessage = (label: string, key: string) =>
const getFormattedMessage = (label: IntlMessageKeys, key: string) =>
t.rich(label, context[key] || {}) as FormattedMessage;

return Object.entries(entries).map(
Expand Down
8 changes: 6 additions & 2 deletions apps/site/layouts/Blog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import WithBlogCategories from '@/components/withBlogCategories';
import WithFooter from '@/components/withFooter';
import WithNavBar from '@/components/withNavBar';
import getBlogData from '@/next-data/blogData';
import type { BlogCategory } from '@/types';

import styles from './layouts.module.css';

Expand All @@ -18,7 +19,10 @@ const getBlogCategory = async (pathname: string) => {
// note that malformed routes can't happen as they are all statically generated
const [, , category = 'all', , page = 1] = pathname.split('/');

const { posts, pagination } = await getBlogData(category, Number(page));
const { posts, pagination } = await getBlogData(
category as BlogCategory,
Number(page)
);

return { category, posts, pagination, page: Number(page) };
};
Expand All @@ -27,7 +31,7 @@ const BlogLayout: FC = async () => {
const { pathname } = getClientContext();
const t = await getTranslations();

const mapCategoriesToTabs = (categories: Array<string>) =>
const mapCategoriesToTabs = (categories: Array<BlogCategory>) =>
categories.map(category => ({
key: category,
label: t(`layouts.blog.categories.${category}`),
Expand Down
7 changes: 5 additions & 2 deletions apps/site/next-data/blogData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import {
VERCEL_ENV,
VERCEL_REGION,
} from '@/next.constants.mjs';
import type { BlogPostsRSC } from '@/types';
import type { BlogCategory, BlogPostsRSC } from '@/types';

const getBlogData = (cat: string, page?: number): Promise<BlogPostsRSC> => {
const getBlogData = (
cat: BlogCategory,
page?: number
): Promise<BlogPostsRSC> => {
const IS_NOT_VERCEL_RUNTIME_ENV =
(!IS_DEV_ENV && VERCEL_ENV && !VERCEL_REGION) ||
(!IS_DEV_ENV && !VERCEL_ENV);
Expand Down
42 changes: 22 additions & 20 deletions apps/site/next-data/providers/blogData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,37 @@ import { cache } from 'react';

import generateBlogData from '@/next-data/generators/blogData.mjs';
import { BLOG_POSTS_PER_PAGE } from '@/next.constants.mjs';
import type { BlogPostsRSC } from '@/types';
import type { BlogCategory, BlogPostsRSC } from '@/types';

const { categories, posts } = await generateBlogData();

export const provideBlogCategories = cache(() => categories);

export const provideBlogPosts = cache((category: string): BlogPostsRSC => {
const categoryPosts = posts
.filter(post => post.categories.includes(category))
.sort((a, b) => b.date.getTime() - a.date.getTime());
export const provideBlogPosts = cache(
(category: BlogCategory): BlogPostsRSC => {
const categoryPosts = posts
.filter(post => post.categories.includes(category))
.sort((a, b) => b.date.getTime() - a.date.getTime());

// Total amount of possible pages given the amount of blog posts
const total = categoryPosts.length / BLOG_POSTS_PER_PAGE;
// Total amount of possible pages given the amount of blog posts
const total = categoryPosts.length / BLOG_POSTS_PER_PAGE;

return {
posts: categoryPosts,
pagination: {
prev: null,
next: null,
// In case the division results on a remainder we need
// to have an extra page containing the remainder entries
pages: Math.floor(total % 1 === 0 ? total : total + 1),
total: categoryPosts.length,
},
};
});
return {
posts: categoryPosts,
pagination: {
prev: null,
next: null,
// In case the division results on a remainder we need
// to have an extra page containing the remainder entries
pages: Math.floor(total % 1 === 0 ? total : total + 1),
total: categoryPosts.length,
},
};
}
);

export const providePaginatedBlogPosts = cache(
(category: string, page: number): BlogPostsRSC => {
(category: BlogCategory, page: number): BlogPostsRSC => {
const { posts, pagination } = provideBlogPosts(category);

// This autocorrects if invalid numbers are given to only allow
Expand Down
1 change: 1 addition & 0 deletions apps/site/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
},
"include": [
"next-env.d.ts",
"global.d.ts",
"**/*.mdx",
"**/*.ts",
"**/*.tsx",
Expand Down
5 changes: 3 additions & 2 deletions apps/site/types/blog.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
export type BlogPreviewType = 'announcements' | 'release' | 'vulnerability';
export type BlogCategory = IntlMessageKeys<'layouts.blog.categories'>;

export interface BlogPost {
title: string;
author: string;
username: string;
date: Date;
categories: Array<string>;
categories: Array<BlogCategory>;
slug: string;
}

export interface BlogData {
posts: Array<BlogPost>;
categories: Array<string>;
categories: Array<BlogCategory>;
}

export interface BlogPagination {
Expand Down
4 changes: 2 additions & 2 deletions apps/site/types/navigation.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { HTMLAttributeAnchorTarget } from 'react';

export interface FooterConfig {
text: string;
text: IntlMessageKeys;
link: string;
}

Expand All @@ -21,7 +21,7 @@ export type NavigationKeys =
| 'blog';

export interface NavigationEntry {
label?: string;
label?: IntlMessageKeys;
link?: string;
items?: Record<string, NavigationEntry>;
target?: HTMLAttributeAnchorTarget | undefined;
Expand Down
Loading

0 comments on commit 6df8fb5

Please sign in to comment.