lichx-blog/types/ArticleMetaData.ts

119 lines
3.9 KiB
TypeScript
Raw Normal View History

2025-08-17 17:22:06 +08:00
import wordCount from 'word-count';
export enum DataAnomaly {
DataNotFound = 'DataNotFound',
Invalid = 'DataInvalid',
}
export type ArticleMetaData = {
id: string;
title: string;
description: string;
created_at: Date | DataAnomaly;
published_at: Date | DataAnomaly;
draft: boolean;
updated_at: Date[] | DataAnomaly;
tags: string[];
tech_stack: string[] | DataAnomaly;
tech_stack_percent: number[] | DataAnomaly;
tech_stack_icon_names: string[] | DataAnomaly;
tech_stack_theme_colors: string[] | DataAnomaly;
word_count: number | DataAnomaly;
};
/*
* Nuxt Content也能做值处理ts传参的自动化生成类型
*
*/
function getDate(data: Record<string, unknown>, key: string): Date | DataAnomaly {
if (data[key] === undefined)
return DataAnomaly.DataNotFound;
if (typeof data[key] !== 'string')
return DataAnomaly.Invalid;
const date = new Date(data[key] as string);
if (isNaN(date.getTime()))
return DataAnomaly.Invalid;
return date;
}
export function toArticleMetaDataType(src: unknown): ArticleMetaData {
if (typeof src !== 'object' || src === null) {
throw new TypeError('Expected an object');
}
const data = src as Record<string, unknown>;
const created_at: Date | DataAnomaly = getDate(data, 'created_at');
const published_at: Date | DataAnomaly = getDate(data, 'published_at');
let updated_at: Date[] | DataAnomaly;
if (data.updated_at === undefined) {
updated_at = DataAnomaly.DataNotFound;
} else if (!Array.isArray(data.updated_at)) {
updated_at = DataAnomaly.Invalid;
} else {
updated_at = data.updated_at.map((x: string) => new Date(x));
updated_at = updated_at.reduce((last, cur) => last || isNaN(cur.getTime()), false) ? DataAnomaly.Invalid : updated_at;
}
let tech_stack: string[] | DataAnomaly;
if (data.tech_stack === undefined) {
tech_stack = DataAnomaly.DataNotFound;
} else if (!Array.isArray(data.tech_stack)) {
tech_stack = DataAnomaly.Invalid;
} else {
tech_stack = data.tech_stack;
}
let tech_stack_percent: number[] | DataAnomaly;
if (data.tech_stack_percent === undefined) {
tech_stack_percent = DataAnomaly.DataNotFound;
} else if (!Array.isArray(data.tech_stack_percent)) {
tech_stack_percent = DataAnomaly.Invalid;
} else {
tech_stack_percent = data.tech_stack_percent;
}
let tech_stack_icon_names: string[] | DataAnomaly;
if (data.tech_stack_icon_names === undefined) {
tech_stack_icon_names = DataAnomaly.DataNotFound;
} else if (!Array.isArray(data.tech_stack_icon_names)) {
tech_stack_icon_names = DataAnomaly.Invalid;
} else {
tech_stack_icon_names = data.tech_stack_icon_names;
}
let tech_stack_theme_colors: string[] | DataAnomaly;
if (data.tech_stack_theme_colors === undefined) {
tech_stack_theme_colors = DataAnomaly.DataNotFound;
} else if (!Array.isArray(data.tech_stack_theme_colors)) {
tech_stack_theme_colors = DataAnomaly.Invalid;
} else {
tech_stack_theme_colors = data.tech_stack_theme_colors;
}
let wordCountResult;
if (data.rawbody === undefined)
wordCountResult = DataAnomaly.DataNotFound;
else if (typeof data.rawbody !== 'string')
wordCountResult = DataAnomaly.Invalid;
else {
const contentWithoutMetaData = data.rawbody.replace(/^---[\s\S]*?---\n?/, '');
wordCountResult = wordCount(contentWithoutMetaData);
}
return {
id: String(data.id),
title: String(data.title),
description: String(data.description ?? ''),
created_at: created_at,
published_at: published_at,
draft: Boolean(data.draft ?? false),
updated_at: updated_at,
tags: Array.isArray(data.tags) ? data.tags.map(String) : [],
tech_stack: tech_stack,
tech_stack_percent: tech_stack_percent,
tech_stack_icon_names: tech_stack_icon_names,
tech_stack_theme_colors: tech_stack_theme_colors,
word_count: wordCountResult,
};
}