Refactor CMS to handle ContentLayer and WordPress platforms
This commit refactors the CMS to handle two platforms: ContentLayer and WordPress. The CMS layer is abstracted into a core package, and separate implementations for each platform are created. This change allows the app to switch the CMS type based on environment variable, which can improve the flexibility of content management. It also updates several functions in the `server-sitemap.xml` route to accommodate these changes and generate sitemaps based on the CMS client. Further, documentation content and posts have been relocated to align with the new structure. Notably, this refactor is a comprehensive update to the way the CMS is structured and managed.
This commit is contained in:
72
packages/cms/core/src/cms-client.ts
Normal file
72
packages/cms/core/src/cms-client.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
export namespace Cms {
|
||||
export type ContentType = 'post' | 'page';
|
||||
|
||||
export interface ContentItem {
|
||||
id: string;
|
||||
title: string;
|
||||
type: ContentType;
|
||||
url: string;
|
||||
description: string | undefined;
|
||||
content: string;
|
||||
author: string;
|
||||
publishedAt: Date;
|
||||
image: string | undefined;
|
||||
slug: string;
|
||||
categories: Category[];
|
||||
tags: Tag[];
|
||||
parentId?: string;
|
||||
children?: ContentItem[];
|
||||
}
|
||||
|
||||
export interface Category {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
}
|
||||
|
||||
export interface Tag {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
}
|
||||
|
||||
export interface GetContentItemsOptions {
|
||||
type?: ContentType;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
categories?: string[];
|
||||
tags?: string[];
|
||||
depth?: number;
|
||||
}
|
||||
|
||||
export interface GetCategoriesOptions {
|
||||
type?: ContentType;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
export interface GetTagsOptions {
|
||||
type?: ContentType;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class CmsClient {
|
||||
abstract getContentItems(
|
||||
options?: Cms.GetContentItemsOptions,
|
||||
): Promise<Cms.ContentItem[]>;
|
||||
|
||||
abstract getContentItemById(id: string): Promise<Cms.ContentItem | undefined>;
|
||||
|
||||
abstract getCategories(
|
||||
options?: Cms.GetCategoriesOptions,
|
||||
): Promise<Cms.Category[]>;
|
||||
|
||||
abstract getCategoryBySlug(slug: string): Promise<Cms.Category | undefined>;
|
||||
|
||||
abstract getTags(options?: Cms.GetTagsOptions): Promise<Cms.Tag[]>;
|
||||
|
||||
abstract getTagBySlug(slug: string): Promise<Cms.Tag | undefined>;
|
||||
}
|
||||
3
packages/cms/core/src/cms.type.ts
Normal file
3
packages/cms/core/src/cms.type.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// we can add more types here if we have more CMSs
|
||||
// ex. export type CmsType = 'contentlayer' | 'other-cms';
|
||||
export type CmsType = 'contentlayer' | 'wordpress';
|
||||
17
packages/cms/core/src/content-renderer.tsx
Normal file
17
packages/cms/core/src/content-renderer.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import { CmsType } from './cms.type';
|
||||
|
||||
export async function ContentRenderer({
|
||||
content,
|
||||
type = process.env.CMS_CLIENT as CmsType,
|
||||
}: {
|
||||
content: string;
|
||||
type?: CmsType;
|
||||
}) {
|
||||
switch (type) {
|
||||
case 'contentlayer': {
|
||||
const { ContentRenderer } = await import('@kit/contentlayer');
|
||||
|
||||
return ContentRenderer({ content });
|
||||
}
|
||||
}
|
||||
}
|
||||
36
packages/cms/core/src/create-cms-client.ts
Normal file
36
packages/cms/core/src/create-cms-client.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { CmsClient } from './cms-client';
|
||||
import { CmsType } from './cms.type';
|
||||
|
||||
/**
|
||||
* Creates a CMS client based on the specified type.
|
||||
*
|
||||
* @param {CmsType} type - The type of CMS client to create. Defaults to the value of the CMS_CLIENT environment variable.
|
||||
* @returns {Promise<CmsClient>} A Promise that resolves to the created CMS client.
|
||||
* @throws {Error} If the specified CMS type is unknown.
|
||||
*/
|
||||
export async function createCmsClient(
|
||||
type: CmsType = process.env.CMS_CLIENT as CmsType,
|
||||
): Promise<CmsClient> {
|
||||
switch (type) {
|
||||
case 'contentlayer':
|
||||
return getContentLayerClient();
|
||||
|
||||
case 'wordpress':
|
||||
return getWordpressClient();
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown CMS type: ${type}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function getContentLayerClient() {
|
||||
const { ContentlayerClient } = await import('@kit/contentlayer');
|
||||
|
||||
return new ContentlayerClient();
|
||||
}
|
||||
|
||||
async function getWordpressClient() {
|
||||
const { WordpressClient } = await import('@kit/wordpress');
|
||||
|
||||
return new WordpressClient();
|
||||
}
|
||||
4
packages/cms/core/src/index.ts
Normal file
4
packages/cms/core/src/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from './cms-client';
|
||||
export * from './create-cms-client';
|
||||
export * from './cms.type';
|
||||
export * from './content-renderer';
|
||||
Reference in New Issue
Block a user