Skip to content
/ core Public

Commit e20a006

Browse files
committed
feat(aggregate)!: refactor Aggregate API and add site metadata endpoint
This update refactors the Aggregate API by removing `categories` and `pageMeta` from the `GET /aggregate` endpoint, introducing a new `GET /aggregate/site` endpoint for lightweight site metadata. Additionally, SEO configuration is enhanced with optional `icon` and `iconDark` fields. Documentation for upgrading to v11 is also added. Signed-off-by: Innei <[email protected]>
1 parent f2ce6f6 commit e20a006

File tree

10 files changed

+365
-137
lines changed

10 files changed

+365
-137
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ All response keys are converted to **snake_case** (e.g., `createdAt` → `create
201201

202202
## Upgrading
203203

204+
### v10 → v11
205+
206+
v11 refactors the Aggregate API: `categories` and `pageMeta` are removed from `GET /aggregate`; a new `GET /aggregate/site` endpoint is added for lightweight site metadata. See [Upgrading to v11](./docs/migrations/v11.md).
207+
204208
### v9 → v10
205209

206210
v10 includes a breaking auth system refactor. See [Upgrading to v10](./docs/migrations/v10.md).

apps/core/src/constants/cache.constant.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ export enum CacheKeys {
3737
RSS = `${API_CACHE_PREFIX}rss`,
3838
RSSXml = `${API_CACHE_PREFIX}rss_xml`,
3939
Aggregate = `${API_CACHE_PREFIX}aggregate`,
40+
AggregateSite = `${API_CACHE_PREFIX}aggregate_site`,
4041
}

apps/core/src/modules/aggregate/aggregate.controller.ts

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -38,74 +38,49 @@ export class AggregateController {
3838
private readonly translationService: TranslationService,
3939
) {}
4040

41+
private async getThemeConfig(theme?: string) {
42+
if (!theme) {
43+
return
44+
}
45+
46+
const cached = await this.snippetService.getCachedSnippet(
47+
'theme',
48+
theme,
49+
'public',
50+
)
51+
if (cached) {
52+
return JSON.safeParse(cached) || cached
53+
}
54+
return this.snippetService.getPublicSnippetByName(theme, 'theme')
55+
}
56+
4157
@Get('/')
4258
@HttpCache({
4359
key: CacheKeys.Aggregate,
4460
ttl: 10 * 60,
4561
withQuery: true,
4662
})
47-
@TranslateFields({
48-
path: 'categories[].name',
49-
keyPath: 'category.name',
50-
idField: '_id',
51-
})
52-
async aggregate(@Query() query: AggregateQueryDto, @Lang() lang?: string) {
63+
async aggregate(@Query() query: AggregateQueryDto) {
5364
const { theme } = query
5465

5566
const tasks = await Promise.allSettled([
5667
this.ownerService.getOwner(),
57-
this.aggregateService.getAllCategory(),
58-
this.aggregateService.getAllPages(),
5968
this.configsService.get('url'),
6069
this.configsService.get('seo'),
6170
this.configsService.get('commentOptions'),
6271
this.noteService.getLatestNoteId(),
63-
!theme
64-
? Promise.resolve()
65-
: this.snippetService
66-
.getCachedSnippet('theme', theme, 'public')
67-
.then((cached) => {
68-
if (cached) {
69-
return JSON.safeParse(cached) || cached
70-
}
71-
return this.snippetService.getPublicSnippetByName(theme, 'theme')
72-
}),
72+
this.getThemeConfig(theme),
7373
this.configsService.get('ai'),
7474
])
7575
const [
7676
user,
77-
categories,
78-
pageMeta,
7977
url,
8078
seo,
8179
commentOptions,
8280
latestNoteId,
8381
themeConfig,
8482
aiConfig,
8583
] = tasks.map((t) => (t.status === 'fulfilled' ? t.value : null))
86-
let translatedPageMeta = pageMeta as any[]
87-
if (lang && translatedPageMeta?.length) {
88-
translatedPageMeta = await this.translationService.translateList({
89-
items: translatedPageMeta,
90-
targetLang: lang,
91-
translationFields: ['title', 'translationMeta'] as const,
92-
getInput: (item: any) => ({
93-
id: item._id?.toString?.() ?? '',
94-
title: item.title ?? '',
95-
created: item.created,
96-
modified: item.modified,
97-
}),
98-
applyResult: (item: any, translation) => {
99-
if (!translation?.isTranslated) return item
100-
return {
101-
...item,
102-
title: translation.title,
103-
isTranslated: true,
104-
translationMeta: translation.translationMeta,
105-
}
106-
},
107-
})
108-
}
10984

11085
return {
11186
user,
@@ -117,8 +92,6 @@ export class AggregateController {
11792
allowGuestComment: commentOptions.allowGuestComment ?? true,
11893
}
11994
: undefined,
120-
categories,
121-
pageMeta: translatedPageMeta,
12295
latestNoteId,
12396
theme: themeConfig,
12497
ai: {
@@ -127,6 +100,32 @@ export class AggregateController {
127100
}
128101
}
129102

103+
@Get('/site')
104+
@HttpCache({
105+
key: CacheKeys.AggregateSite,
106+
ttl: 10 * 60,
107+
withQuery: true,
108+
})
109+
async site() {
110+
const [user, url, seo] = await Promise.all([
111+
this.ownerService.getOwner(),
112+
this.configsService.get('url'),
113+
this.configsService.get('seo'),
114+
])
115+
116+
return {
117+
user: {
118+
id: user.id,
119+
name: user.name,
120+
socialIds: user.socialIds,
121+
},
122+
seo,
123+
url: {
124+
webUrl: url.webUrl,
125+
},
126+
}
127+
}
128+
130129
@Get('/top')
131130
@TranslateFields(
132131
{ path: 'notes[].mood', keyPath: 'note.mood' },

apps/core/src/modules/configs/configs.default.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ export const generateDefaultConfig: () => IConfig = () => ({
44
seo: {
55
title: '我的小世界呀',
66
description: '哈喽~欢迎光临',
7+
icon: '',
8+
iconDark: '',
79
keywords: [],
810
},
911
url: {

apps/core/src/modules/configs/configs.schema.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { field, section, withMeta } from './configs.zod-schema.util'
1010
export const SeoSchema = section('SEO 优化', {
1111
title: field.plain(z.string().min(1).optional(), '网站标题'),
1212
description: field.plain(z.string().min(1).optional(), '网站描述'),
13+
icon: field.halfGrid(z.string().optional(), '浅色图标 URL'),
14+
iconDark: field.halfGrid(z.string().optional(), '深色图标 URL'),
1315
keywords: field.array(z.array(z.string()).optional(), '关键字'),
1416
})
1517
export class SeoDto extends createZodDto(SeoSchema) {}

0 commit comments

Comments
 (0)