@vigilkids/cms-client 0.1.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/README.md +155 -14
- package/dist/index.d.mts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.mjs +8 -0
- package/dist/types.d.mts +42 -1
- package/dist/types.d.ts +42 -1
- package/package.json +4 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.3.0] - 2026-06-03
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Added localized category SEO, Open Graph, and Twitter Card metadata map types.
|
|
13
|
+
- Added category node metadata fields for CMS taxonomy landing pages.
|
|
14
|
+
|
|
15
|
+
## [0.2.0] - 2026-06-03
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Added `searchArticles` for published article search through the CMS Public API.
|
|
20
|
+
- Added `ArticleSearchParams` and `ArticleSearchResultItem` public types.
|
|
21
|
+
- Added article list sorting parameters through `ArticleListParams.sort_by` and `ArticleListParams.sort_order`.
|
|
22
|
+
- Added sitemap route metadata, hreflang route parameters, and `SitemapImageEntry` image metadata types.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Included `CHANGELOG.md` in the published package contents.
|
|
27
|
+
|
|
28
|
+
## [0.1.2] - 2026-03-26
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- `last_published_at` field to `ArticleListItem` type (aligns with backend `DeliveryArticleListItem`)
|
|
33
|
+
|
|
34
|
+
## [0.1.0] - 2026-03-23
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- ESLint flat config (`@antfu/eslint-config`) + Prettier
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- Codebase formatted with Prettier (singleQuote, no semi, printWidth 100)
|
|
43
|
+
|
|
44
|
+
## [0.0.1] - 2025-03-23
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- CMS API client with typed request/response interfaces
|
|
49
|
+
- Article delivery API (getBySlug, list, categories, sitemap)
|
|
50
|
+
- Preview token validation
|
|
51
|
+
- Webhook payload types for content events
|
|
52
|
+
- TypeScript-first with full type exports
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @vigilkids/cms-client
|
|
2
2
|
|
|
3
|
-
TypeScript
|
|
3
|
+
Framework-agnostic TypeScript client for the OneX CMS Public API. It provides a typed fetch-based client for published CMS content, sitemap data, redirects, comments, authors, series, and server-side webhook signature verification.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,36 +8,177 @@ TypeScript HTTP client for the OneX CMS delivery API. Framework-agnostic — wor
|
|
|
8
8
|
pnpm add @vigilkids/cms-client
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
The `baseUrl` must point at the CMS Public API root that serves `/articles`, `/search`, `/sitemap`, and the other delivery endpoints.
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createCmsClient } from '@vigilkids/cms-client'
|
|
17
|
+
|
|
18
|
+
export const cms = createCmsClient({
|
|
19
|
+
baseUrl: 'https://api.example.com/api/v1/cms',
|
|
20
|
+
productCode: 'example-product',
|
|
21
|
+
defaultLocale: 'en',
|
|
22
|
+
timeout: 10_000,
|
|
23
|
+
})
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
| Option | Required | Description |
|
|
27
|
+
|--------|----------|-------------|
|
|
28
|
+
| `baseUrl` | Yes | CMS Public API base URL. |
|
|
29
|
+
| `productCode` | No | Adds `X-Product-Code` to each request. |
|
|
30
|
+
| `defaultLocale` | No | Locale automatically added to GET requests when no locale is provided. Defaults to `en`. |
|
|
31
|
+
| `previewToken` | No | Adds `X-Preview-Token` to each request. |
|
|
32
|
+
| `fetch` | No | Custom fetch-compatible implementation. Defaults to `globalThis.fetch`. |
|
|
33
|
+
| `timeout` | No | Request timeout in milliseconds. Defaults to `10000`. |
|
|
34
|
+
| `headers` | No | Additional request headers merged into each request. |
|
|
35
|
+
|
|
36
|
+
## Articles
|
|
37
|
+
|
|
38
|
+
Use `getArticles`, `getArticle`, and `searchArticles` for published article delivery.
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { createCmsClient } from '@vigilkids/cms-client'
|
|
42
|
+
|
|
43
|
+
const cms = createCmsClient({
|
|
44
|
+
baseUrl: 'https://api.example.com/api/v1/cms',
|
|
45
|
+
defaultLocale: 'en',
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
export async function loadArticles(): Promise<void> {
|
|
49
|
+
const articlePage = await cms.getArticles({
|
|
50
|
+
page: 1,
|
|
51
|
+
page_size: 10,
|
|
52
|
+
sort_by: 'last_published_at',
|
|
53
|
+
sort_order: 'desc',
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const article = await cms.getArticle('getting-started', 'en')
|
|
57
|
+
|
|
58
|
+
const searchPage = await cms.searchArticles({
|
|
59
|
+
q: 'privacy',
|
|
60
|
+
locale: 'en',
|
|
61
|
+
page: 1,
|
|
62
|
+
page_size: 5,
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
console.log(articlePage.pagination.total, article.title, searchPage.data.length)
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Related article and taxonomy helpers are available when the consuming app needs more content context.
|
|
12
70
|
|
|
13
71
|
```typescript
|
|
14
72
|
import { createCmsClient } from '@vigilkids/cms-client'
|
|
15
73
|
|
|
16
74
|
const cms = createCmsClient({
|
|
17
|
-
baseUrl: 'https://api.example.com',
|
|
18
|
-
|
|
75
|
+
baseUrl: 'https://api.example.com/api/v1/cms',
|
|
76
|
+
defaultLocale: 'en',
|
|
19
77
|
})
|
|
20
78
|
|
|
21
|
-
|
|
22
|
-
const
|
|
79
|
+
export async function loadArticleContext(slug: string): Promise<void> {
|
|
80
|
+
const related = await cms.getRelatedArticles(slug, { limit: 3, locale: 'en' })
|
|
81
|
+
const categories = await cms.getCategories()
|
|
23
82
|
|
|
24
|
-
|
|
25
|
-
|
|
83
|
+
console.log(related.map(article => article.slug), categories.length)
|
|
84
|
+
}
|
|
26
85
|
```
|
|
27
86
|
|
|
87
|
+
## Sitemap
|
|
88
|
+
|
|
89
|
+
Use `getSitemap` to retrieve CMS-managed sitemap entries, including optional route parameters, hreflang entries, and image metadata.
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import type { SitemapEntry } from '@vigilkids/cms-client'
|
|
93
|
+
import { createCmsClient } from '@vigilkids/cms-client'
|
|
94
|
+
|
|
95
|
+
const cms = createCmsClient({
|
|
96
|
+
baseUrl: 'https://api.example.com/api/v1/cms',
|
|
97
|
+
defaultLocale: 'en',
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
export async function loadSitemap(): Promise<SitemapEntry[]> {
|
|
101
|
+
const entries = await cms.getSitemap('en')
|
|
102
|
+
return entries.filter(entry => entry.loc.startsWith('https://'))
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Webhook Verification
|
|
107
|
+
|
|
108
|
+
Import webhook helpers from the webhook entry point. Verification uses HMAC-SHA256 and expects a signature formatted as `sha256=<hex>`.
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
import type { RevalidatePayload } from '@vigilkids/cms-client'
|
|
112
|
+
import { verifyWebhookSignature } from '@vigilkids/cms-client/webhook'
|
|
113
|
+
|
|
114
|
+
export function parseCmsWebhook(
|
|
115
|
+
rawBody: string,
|
|
116
|
+
signature: string,
|
|
117
|
+
secret: string,
|
|
118
|
+
): RevalidatePayload {
|
|
119
|
+
const verified = verifyWebhookSignature({
|
|
120
|
+
rawBody,
|
|
121
|
+
signature,
|
|
122
|
+
secret,
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
if (!verified) {
|
|
126
|
+
throw new Error('Invalid CMS webhook signature')
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return JSON.parse(rawBody) as RevalidatePayload
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Client Methods
|
|
134
|
+
|
|
135
|
+
| Area | Methods |
|
|
136
|
+
|------|---------|
|
|
137
|
+
| Articles | `getArticles`, `getArticle`, `getRelatedArticles`, `searchArticles` |
|
|
138
|
+
| Authors | `getAuthorsPage`, `getAuthors`, `getAuthor`, `getAuthorArticlesPage`, `getAuthorArticles` |
|
|
139
|
+
| Categories | `getCategories` |
|
|
140
|
+
| Comments | `getComments`, `createComment` |
|
|
141
|
+
| Sitemap, redirects, series | `getSitemap`, `getRedirects`, `getSeries` |
|
|
142
|
+
|
|
28
143
|
## Exports
|
|
29
144
|
|
|
30
145
|
| Entry Point | Import | Content |
|
|
31
146
|
|-------------|--------|---------|
|
|
32
|
-
| Main | `@vigilkids/cms-client` |
|
|
33
|
-
| Types | `@vigilkids/cms-client/types` |
|
|
34
|
-
| Webhook | `@vigilkids/cms-client/webhook` |
|
|
147
|
+
| Main | `@vigilkids/cms-client` | `CmsClient`, `createCmsClient`, `CmsApiError`, `CmsClientConfig`, and all public request/response types |
|
|
148
|
+
| Types | `@vigilkids/cms-client/types` | Public CMS request/response type definitions |
|
|
149
|
+
| Webhook | `@vigilkids/cms-client/webhook` | `verifyWebhookSignature` and `VerifyWebhookOptions` |
|
|
150
|
+
|
|
151
|
+
## Error Handling
|
|
152
|
+
|
|
153
|
+
`CmsApiError` is thrown for non-2xx API responses.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { CmsApiError, createCmsClient } from '@vigilkids/cms-client'
|
|
157
|
+
|
|
158
|
+
const cms = createCmsClient({
|
|
159
|
+
baseUrl: 'https://api.example.com/api/v1/cms',
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
export async function loadRequiredArticle(slug: string): Promise<string> {
|
|
163
|
+
try {
|
|
164
|
+
const article = await cms.getArticle(slug)
|
|
165
|
+
return article.title
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
if (error instanceof CmsApiError && error.isNotFound) {
|
|
169
|
+
return 'Article not found'
|
|
170
|
+
}
|
|
171
|
+
throw error
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
35
175
|
|
|
36
176
|
## Compatibility
|
|
37
177
|
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
178
|
+
- ESM package.
|
|
179
|
+
- Main client requires a fetch-compatible runtime. Node.js 18+ provides `globalThis.fetch`; other runtimes can pass `fetch` in the client configuration.
|
|
180
|
+
- `@vigilkids/cms-client/webhook` uses Node.js `crypto` and `Buffer`, so signature verification should run in a server runtime.
|
|
181
|
+
- TypeScript declarations are included with the package.
|
|
41
182
|
|
|
42
183
|
## License
|
|
43
184
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ArticleListParams, Paginated, ArticleListItem, ArticleDetail, PaginationParams, Author, CategoryNode, Comment, CreateCommentPayload, SitemapEntry, RedirectRule, Series } from './types.mjs';
|
|
2
|
-
export { HreflangEntry, ListResponse, LocalizedString, OgMeta, PaginationMeta, RevalidatePayload, SeoMeta, TwitterMeta, WebhookEventType } from './types.mjs';
|
|
1
|
+
import { ArticleListParams, Paginated, ArticleListItem, ArticleDetail, ArticleSearchParams, ArticleSearchResultItem, PaginationParams, Author, CategoryNode, Comment, CreateCommentPayload, SitemapEntry, RedirectRule, Series } from './types.mjs';
|
|
2
|
+
export { HreflangEntry, ListResponse, LocalizedOgMetaMap, LocalizedSeoMetaMap, LocalizedString, LocalizedTwitterMetaMap, OgMeta, PaginationMeta, RevalidatePayload, SeoMeta, SitemapImageEntry, TwitterMeta, WebhookEventType } from './types.mjs';
|
|
3
3
|
|
|
4
4
|
/** CMS 客户端配置 */
|
|
5
5
|
interface CmsClientConfig {
|
|
@@ -33,6 +33,8 @@ declare class CmsClient {
|
|
|
33
33
|
limit?: number;
|
|
34
34
|
locale?: string;
|
|
35
35
|
}): Promise<ArticleListItem[]>;
|
|
36
|
+
/** 搜索已发布文章 */
|
|
37
|
+
searchArticles(params: ArticleSearchParams): Promise<Paginated<ArticleSearchResultItem>>;
|
|
36
38
|
/** 获取作者分页列表 */
|
|
37
39
|
getAuthorsPage(options?: {
|
|
38
40
|
locale?: string;
|
|
@@ -84,5 +86,5 @@ declare class CmsApiError extends Error {
|
|
|
84
86
|
get isUnauthorized(): boolean;
|
|
85
87
|
}
|
|
86
88
|
|
|
87
|
-
export { ArticleDetail, ArticleListItem, ArticleListParams, Author, CategoryNode, CmsApiError, CmsClient, Comment, CreateCommentPayload, Paginated, PaginationParams, RedirectRule, Series, SitemapEntry, createCmsClient };
|
|
89
|
+
export { ArticleDetail, ArticleListItem, ArticleListParams, ArticleSearchParams, ArticleSearchResultItem, Author, CategoryNode, CmsApiError, CmsClient, Comment, CreateCommentPayload, Paginated, PaginationParams, RedirectRule, Series, SitemapEntry, createCmsClient };
|
|
88
90
|
export type { CmsClientConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ArticleListParams, Paginated, ArticleListItem, ArticleDetail, PaginationParams, Author, CategoryNode, Comment, CreateCommentPayload, SitemapEntry, RedirectRule, Series } from './types.js';
|
|
2
|
-
export { HreflangEntry, ListResponse, LocalizedString, OgMeta, PaginationMeta, RevalidatePayload, SeoMeta, TwitterMeta, WebhookEventType } from './types.js';
|
|
1
|
+
import { ArticleListParams, Paginated, ArticleListItem, ArticleDetail, ArticleSearchParams, ArticleSearchResultItem, PaginationParams, Author, CategoryNode, Comment, CreateCommentPayload, SitemapEntry, RedirectRule, Series } from './types.js';
|
|
2
|
+
export { HreflangEntry, ListResponse, LocalizedOgMetaMap, LocalizedSeoMetaMap, LocalizedString, LocalizedTwitterMetaMap, OgMeta, PaginationMeta, RevalidatePayload, SeoMeta, SitemapImageEntry, TwitterMeta, WebhookEventType } from './types.js';
|
|
3
3
|
|
|
4
4
|
/** CMS 客户端配置 */
|
|
5
5
|
interface CmsClientConfig {
|
|
@@ -33,6 +33,8 @@ declare class CmsClient {
|
|
|
33
33
|
limit?: number;
|
|
34
34
|
locale?: string;
|
|
35
35
|
}): Promise<ArticleListItem[]>;
|
|
36
|
+
/** 搜索已发布文章 */
|
|
37
|
+
searchArticles(params: ArticleSearchParams): Promise<Paginated<ArticleSearchResultItem>>;
|
|
36
38
|
/** 获取作者分页列表 */
|
|
37
39
|
getAuthorsPage(options?: {
|
|
38
40
|
locale?: string;
|
|
@@ -84,5 +86,5 @@ declare class CmsApiError extends Error {
|
|
|
84
86
|
get isUnauthorized(): boolean;
|
|
85
87
|
}
|
|
86
88
|
|
|
87
|
-
export { ArticleDetail, ArticleListItem, ArticleListParams, Author, CategoryNode, CmsApiError, CmsClient, Comment, CreateCommentPayload, Paginated, PaginationParams, RedirectRule, Series, SitemapEntry, createCmsClient };
|
|
89
|
+
export { ArticleDetail, ArticleListItem, ArticleListParams, ArticleSearchParams, ArticleSearchResultItem, Author, CategoryNode, CmsApiError, CmsClient, Comment, CreateCommentPayload, Paginated, PaginationParams, RedirectRule, Series, SitemapEntry, createCmsClient };
|
|
88
90
|
export type { CmsClientConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -79,6 +79,14 @@ class CmsClient {
|
|
|
79
79
|
);
|
|
80
80
|
return normalizeListResponse(result, endpoint);
|
|
81
81
|
}
|
|
82
|
+
/** 搜索已发布文章 */
|
|
83
|
+
async searchArticles(params) {
|
|
84
|
+
return this.request(
|
|
85
|
+
"GET",
|
|
86
|
+
"/search",
|
|
87
|
+
params
|
|
88
|
+
);
|
|
89
|
+
}
|
|
82
90
|
// ─── 作者 ───────────────────────────────────────────
|
|
83
91
|
/** 获取作者分页列表 */
|
|
84
92
|
async getAuthorsPage(options) {
|
package/dist/types.d.mts
CHANGED
|
@@ -81,6 +81,29 @@ interface ArticleListParams extends PaginationParams {
|
|
|
81
81
|
category_slug?: string;
|
|
82
82
|
tag?: string;
|
|
83
83
|
is_pinned?: boolean;
|
|
84
|
+
sort_by?: string;
|
|
85
|
+
sort_order?: 'asc' | 'desc';
|
|
86
|
+
}
|
|
87
|
+
/** 文章搜索查询参数 */
|
|
88
|
+
interface ArticleSearchParams extends PaginationParams {
|
|
89
|
+
locale?: string;
|
|
90
|
+
q: string;
|
|
91
|
+
}
|
|
92
|
+
/** 文章搜索结果项 */
|
|
93
|
+
interface ArticleSearchResultItem {
|
|
94
|
+
article_id: number;
|
|
95
|
+
title: string;
|
|
96
|
+
excerpt?: string;
|
|
97
|
+
slug: string;
|
|
98
|
+
score: number;
|
|
99
|
+
category_slug?: string;
|
|
100
|
+
featured_image_url?: string;
|
|
101
|
+
featured_image_alt?: string;
|
|
102
|
+
published_at?: string | null;
|
|
103
|
+
last_published_at?: string | null;
|
|
104
|
+
reading_time_minutes?: number;
|
|
105
|
+
tags?: string[];
|
|
106
|
+
authors?: Author[];
|
|
84
107
|
}
|
|
85
108
|
/** SEO 元信息 */
|
|
86
109
|
interface SeoMeta {
|
|
@@ -106,12 +129,21 @@ interface TwitterMeta {
|
|
|
106
129
|
image: string | null;
|
|
107
130
|
}
|
|
108
131
|
|
|
132
|
+
/** 本地化 SEO 元信息 */
|
|
133
|
+
type LocalizedSeoMetaMap = Record<string, Partial<SeoMeta>>;
|
|
134
|
+
/** 本地化 Open Graph 元信息 */
|
|
135
|
+
type LocalizedOgMetaMap = Record<string, Partial<OgMeta>>;
|
|
136
|
+
/** 本地化 Twitter Card 元信息 */
|
|
137
|
+
type LocalizedTwitterMetaMap = Record<string, Partial<TwitterMeta>>;
|
|
109
138
|
/** 分类树节点 (Go: delivery.CategoryNodeResponse) */
|
|
110
139
|
interface CategoryNode {
|
|
111
140
|
id: number;
|
|
112
141
|
slug: string;
|
|
113
142
|
name: LocalizedString;
|
|
114
143
|
description: LocalizedString;
|
|
144
|
+
seo_meta?: LocalizedSeoMetaMap;
|
|
145
|
+
og_meta?: LocalizedOgMetaMap;
|
|
146
|
+
twitter_meta?: LocalizedTwitterMetaMap;
|
|
115
147
|
article_count: number;
|
|
116
148
|
article_counts?: Record<string, number>;
|
|
117
149
|
children?: CategoryNode[];
|
|
@@ -157,14 +189,23 @@ interface Series {
|
|
|
157
189
|
interface HreflangEntry {
|
|
158
190
|
lang: string;
|
|
159
191
|
href: string;
|
|
192
|
+
route_params?: Record<string, string | number | boolean | null | undefined>;
|
|
193
|
+
}
|
|
194
|
+
/** Sitemap 图片条目 */
|
|
195
|
+
interface SitemapImageEntry {
|
|
196
|
+
loc: string;
|
|
197
|
+
title?: string;
|
|
160
198
|
}
|
|
161
199
|
/** Sitemap 条目 (Go: delivery.SitemapEntryResponse) */
|
|
162
200
|
interface SitemapEntry {
|
|
163
201
|
loc: string;
|
|
202
|
+
resource_type?: string;
|
|
203
|
+
route_params?: Record<string, string | number | boolean | null | undefined>;
|
|
164
204
|
last_mod: string;
|
|
165
205
|
change_freq: string;
|
|
166
206
|
priority: number;
|
|
167
207
|
hreflang?: HreflangEntry[];
|
|
208
|
+
images?: SitemapImageEntry[];
|
|
168
209
|
}
|
|
169
210
|
|
|
170
211
|
/** Webhook 事件类型 */
|
|
@@ -177,4 +218,4 @@ interface RevalidatePayload {
|
|
|
177
218
|
category_slug?: string;
|
|
178
219
|
}
|
|
179
220
|
|
|
180
|
-
export type { ArticleDetail, ArticleListItem, ArticleListParams, Author, CategoryNode, Comment, CreateCommentPayload, HreflangEntry, ListResponse, LocalizedString, OgMeta, Paginated, PaginationMeta, PaginationParams, RedirectRule, RevalidatePayload, SeoMeta, Series, SitemapEntry, TwitterMeta, WebhookEventType };
|
|
221
|
+
export type { ArticleDetail, ArticleListItem, ArticleListParams, ArticleSearchParams, ArticleSearchResultItem, Author, CategoryNode, Comment, CreateCommentPayload, HreflangEntry, ListResponse, LocalizedOgMetaMap, LocalizedSeoMetaMap, LocalizedString, LocalizedTwitterMetaMap, OgMeta, Paginated, PaginationMeta, PaginationParams, RedirectRule, RevalidatePayload, SeoMeta, Series, SitemapEntry, SitemapImageEntry, TwitterMeta, WebhookEventType };
|
package/dist/types.d.ts
CHANGED
|
@@ -81,6 +81,29 @@ interface ArticleListParams extends PaginationParams {
|
|
|
81
81
|
category_slug?: string;
|
|
82
82
|
tag?: string;
|
|
83
83
|
is_pinned?: boolean;
|
|
84
|
+
sort_by?: string;
|
|
85
|
+
sort_order?: 'asc' | 'desc';
|
|
86
|
+
}
|
|
87
|
+
/** 文章搜索查询参数 */
|
|
88
|
+
interface ArticleSearchParams extends PaginationParams {
|
|
89
|
+
locale?: string;
|
|
90
|
+
q: string;
|
|
91
|
+
}
|
|
92
|
+
/** 文章搜索结果项 */
|
|
93
|
+
interface ArticleSearchResultItem {
|
|
94
|
+
article_id: number;
|
|
95
|
+
title: string;
|
|
96
|
+
excerpt?: string;
|
|
97
|
+
slug: string;
|
|
98
|
+
score: number;
|
|
99
|
+
category_slug?: string;
|
|
100
|
+
featured_image_url?: string;
|
|
101
|
+
featured_image_alt?: string;
|
|
102
|
+
published_at?: string | null;
|
|
103
|
+
last_published_at?: string | null;
|
|
104
|
+
reading_time_minutes?: number;
|
|
105
|
+
tags?: string[];
|
|
106
|
+
authors?: Author[];
|
|
84
107
|
}
|
|
85
108
|
/** SEO 元信息 */
|
|
86
109
|
interface SeoMeta {
|
|
@@ -106,12 +129,21 @@ interface TwitterMeta {
|
|
|
106
129
|
image: string | null;
|
|
107
130
|
}
|
|
108
131
|
|
|
132
|
+
/** 本地化 SEO 元信息 */
|
|
133
|
+
type LocalizedSeoMetaMap = Record<string, Partial<SeoMeta>>;
|
|
134
|
+
/** 本地化 Open Graph 元信息 */
|
|
135
|
+
type LocalizedOgMetaMap = Record<string, Partial<OgMeta>>;
|
|
136
|
+
/** 本地化 Twitter Card 元信息 */
|
|
137
|
+
type LocalizedTwitterMetaMap = Record<string, Partial<TwitterMeta>>;
|
|
109
138
|
/** 分类树节点 (Go: delivery.CategoryNodeResponse) */
|
|
110
139
|
interface CategoryNode {
|
|
111
140
|
id: number;
|
|
112
141
|
slug: string;
|
|
113
142
|
name: LocalizedString;
|
|
114
143
|
description: LocalizedString;
|
|
144
|
+
seo_meta?: LocalizedSeoMetaMap;
|
|
145
|
+
og_meta?: LocalizedOgMetaMap;
|
|
146
|
+
twitter_meta?: LocalizedTwitterMetaMap;
|
|
115
147
|
article_count: number;
|
|
116
148
|
article_counts?: Record<string, number>;
|
|
117
149
|
children?: CategoryNode[];
|
|
@@ -157,14 +189,23 @@ interface Series {
|
|
|
157
189
|
interface HreflangEntry {
|
|
158
190
|
lang: string;
|
|
159
191
|
href: string;
|
|
192
|
+
route_params?: Record<string, string | number | boolean | null | undefined>;
|
|
193
|
+
}
|
|
194
|
+
/** Sitemap 图片条目 */
|
|
195
|
+
interface SitemapImageEntry {
|
|
196
|
+
loc: string;
|
|
197
|
+
title?: string;
|
|
160
198
|
}
|
|
161
199
|
/** Sitemap 条目 (Go: delivery.SitemapEntryResponse) */
|
|
162
200
|
interface SitemapEntry {
|
|
163
201
|
loc: string;
|
|
202
|
+
resource_type?: string;
|
|
203
|
+
route_params?: Record<string, string | number | boolean | null | undefined>;
|
|
164
204
|
last_mod: string;
|
|
165
205
|
change_freq: string;
|
|
166
206
|
priority: number;
|
|
167
207
|
hreflang?: HreflangEntry[];
|
|
208
|
+
images?: SitemapImageEntry[];
|
|
168
209
|
}
|
|
169
210
|
|
|
170
211
|
/** Webhook 事件类型 */
|
|
@@ -177,4 +218,4 @@ interface RevalidatePayload {
|
|
|
177
218
|
category_slug?: string;
|
|
178
219
|
}
|
|
179
220
|
|
|
180
|
-
export type { ArticleDetail, ArticleListItem, ArticleListParams, Author, CategoryNode, Comment, CreateCommentPayload, HreflangEntry, ListResponse, LocalizedString, OgMeta, Paginated, PaginationMeta, PaginationParams, RedirectRule, RevalidatePayload, SeoMeta, Series, SitemapEntry, TwitterMeta, WebhookEventType };
|
|
221
|
+
export type { ArticleDetail, ArticleListItem, ArticleListParams, ArticleSearchParams, ArticleSearchResultItem, Author, CategoryNode, Comment, CreateCommentPayload, HreflangEntry, ListResponse, LocalizedOgMetaMap, LocalizedSeoMetaMap, LocalizedString, LocalizedTwitterMetaMap, OgMeta, Paginated, PaginationMeta, PaginationParams, RedirectRule, RevalidatePayload, SeoMeta, Series, SitemapEntry, SitemapImageEntry, TwitterMeta, WebhookEventType };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vigilkids/cms-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Framework-agnostic TypeScript client for OnEx CMS Public API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
|
-
"dist"
|
|
23
|
+
"dist",
|
|
24
|
+
"CHANGELOG.md"
|
|
24
25
|
],
|
|
25
26
|
"sideEffects": false,
|
|
26
27
|
"scripts": {
|
|
@@ -34,7 +35,7 @@
|
|
|
34
35
|
},
|
|
35
36
|
"repository": {
|
|
36
37
|
"type": "git",
|
|
37
|
-
"url": "git+https://github.com/
|
|
38
|
+
"url": "git+https://github.com/vigikids/onex.git",
|
|
38
39
|
"directory": "packages/cms-client"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|