@vigilkids/cms-client 0.3.0 → 0.3.2
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 +6 -0
- package/dist/index.d.mts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.mjs +14 -2
- package/dist/routes.d.mts +54 -0
- package/dist/routes.d.ts +54 -0
- package/dist/routes.mjs +147 -0
- package/dist/types.d.mts +23 -1
- package/dist/types.d.ts +23 -1
- package/package.json +22 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.1] - 2026-06-05
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Added `RedirectRule.priority` for CMS delivery redirect ordering metadata.
|
|
13
|
+
|
|
8
14
|
## [0.3.0] - 2026-06-03
|
|
9
15
|
|
|
10
16
|
### Added
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { ArticleListParams, Paginated, ArticleListItem, ArticleDetail, ArticleSearchParams, ArticleSearchResultItem, PaginationParams, Author, CategoryNode, Comment, CreateCommentPayload, SitemapEntry, RedirectRule, Series } from './types.mjs';
|
|
1
|
+
import { ArticleListParams, Paginated, ArticleListItem, ArticleDetail, ArticleSearchParams, ArticleSearchResultItem, PaginationParams, Author, CategoryNode, Comment, CreateCommentPayload, SitemapEntry, RedirectRule, SiteConfigQuery, SiteConfig, Series } from './types.mjs';
|
|
2
2
|
export { HreflangEntry, ListResponse, LocalizedOgMetaMap, LocalizedSeoMetaMap, LocalizedString, LocalizedTwitterMetaMap, OgMeta, PaginationMeta, RevalidatePayload, SeoMeta, SitemapImageEntry, TwitterMeta, WebhookEventType } from './types.mjs';
|
|
3
|
+
export { BuildRoutePathOptions, BuildRouteUrlOptions, DEFAULT_ROUTE_RESOURCES, ResolvedRouteLocalePolicy, ResolvedRoutePolicy, RouteLocalePolicy, RouteParams, RoutePolicy, RoutePolicyConfig, RouteResourceDefaults, RouteResources, buildRoutePath, buildRouteUrl, extractRouteParams, extractSourceRouteParams, formatRoutePolicy, hasCustomArticleRoute, isRoutePolicy, mergeRouteParams, resolveRoutePolicy } from './routes.mjs';
|
|
3
4
|
|
|
4
5
|
/** CMS 客户端配置 */
|
|
5
6
|
interface CmsClientConfig {
|
|
@@ -65,6 +66,8 @@ declare class CmsClient {
|
|
|
65
66
|
getSitemap(locale?: string): Promise<SitemapEntry[]>;
|
|
66
67
|
/** 获取重定向规则 */
|
|
67
68
|
getRedirects(): Promise<RedirectRule[]>;
|
|
69
|
+
/** 获取站点运行时配置 */
|
|
70
|
+
getSiteConfig(options?: SiteConfigQuery): Promise<SiteConfig>;
|
|
68
71
|
/** 获取文章系列 */
|
|
69
72
|
getSeries(slug: string, locale?: string): Promise<Series>;
|
|
70
73
|
private request;
|
|
@@ -86,5 +89,5 @@ declare class CmsApiError extends Error {
|
|
|
86
89
|
get isUnauthorized(): boolean;
|
|
87
90
|
}
|
|
88
91
|
|
|
89
|
-
export { ArticleDetail, ArticleListItem, ArticleListParams, ArticleSearchParams, ArticleSearchResultItem, Author, CategoryNode, CmsApiError, CmsClient, Comment, CreateCommentPayload, Paginated, PaginationParams, RedirectRule, Series, SitemapEntry, createCmsClient };
|
|
92
|
+
export { ArticleDetail, ArticleListItem, ArticleListParams, ArticleSearchParams, ArticleSearchResultItem, Author, CategoryNode, CmsApiError, CmsClient, Comment, CreateCommentPayload, Paginated, PaginationParams, RedirectRule, Series, SiteConfig, SiteConfigQuery, SitemapEntry, createCmsClient };
|
|
90
93
|
export type { CmsClientConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { ArticleListParams, Paginated, ArticleListItem, ArticleDetail, ArticleSearchParams, ArticleSearchResultItem, PaginationParams, Author, CategoryNode, Comment, CreateCommentPayload, SitemapEntry, RedirectRule, Series } from './types.js';
|
|
1
|
+
import { ArticleListParams, Paginated, ArticleListItem, ArticleDetail, ArticleSearchParams, ArticleSearchResultItem, PaginationParams, Author, CategoryNode, Comment, CreateCommentPayload, SitemapEntry, RedirectRule, SiteConfigQuery, SiteConfig, Series } from './types.js';
|
|
2
2
|
export { HreflangEntry, ListResponse, LocalizedOgMetaMap, LocalizedSeoMetaMap, LocalizedString, LocalizedTwitterMetaMap, OgMeta, PaginationMeta, RevalidatePayload, SeoMeta, SitemapImageEntry, TwitterMeta, WebhookEventType } from './types.js';
|
|
3
|
+
export { BuildRoutePathOptions, BuildRouteUrlOptions, DEFAULT_ROUTE_RESOURCES, ResolvedRouteLocalePolicy, ResolvedRoutePolicy, RouteLocalePolicy, RouteParams, RoutePolicy, RoutePolicyConfig, RouteResourceDefaults, RouteResources, buildRoutePath, buildRouteUrl, extractRouteParams, extractSourceRouteParams, formatRoutePolicy, hasCustomArticleRoute, isRoutePolicy, mergeRouteParams, resolveRoutePolicy } from './routes.js';
|
|
3
4
|
|
|
4
5
|
/** CMS 客户端配置 */
|
|
5
6
|
interface CmsClientConfig {
|
|
@@ -65,6 +66,8 @@ declare class CmsClient {
|
|
|
65
66
|
getSitemap(locale?: string): Promise<SitemapEntry[]>;
|
|
66
67
|
/** 获取重定向规则 */
|
|
67
68
|
getRedirects(): Promise<RedirectRule[]>;
|
|
69
|
+
/** 获取站点运行时配置 */
|
|
70
|
+
getSiteConfig(options?: SiteConfigQuery): Promise<SiteConfig>;
|
|
68
71
|
/** 获取文章系列 */
|
|
69
72
|
getSeries(slug: string, locale?: string): Promise<Series>;
|
|
70
73
|
private request;
|
|
@@ -86,5 +89,5 @@ declare class CmsApiError extends Error {
|
|
|
86
89
|
get isUnauthorized(): boolean;
|
|
87
90
|
}
|
|
88
91
|
|
|
89
|
-
export { ArticleDetail, ArticleListItem, ArticleListParams, ArticleSearchParams, ArticleSearchResultItem, Author, CategoryNode, CmsApiError, CmsClient, Comment, CreateCommentPayload, Paginated, PaginationParams, RedirectRule, Series, SitemapEntry, createCmsClient };
|
|
92
|
+
export { ArticleDetail, ArticleListItem, ArticleListParams, ArticleSearchParams, ArticleSearchResultItem, Author, CategoryNode, CmsApiError, CmsClient, Comment, CreateCommentPayload, Paginated, PaginationParams, RedirectRule, Series, SiteConfig, SiteConfigQuery, SitemapEntry, createCmsClient };
|
|
90
93
|
export type { CmsClientConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { DEFAULT_ROUTE_RESOURCES, buildRoutePath, buildRouteUrl, extractRouteParams, extractSourceRouteParams, formatRoutePolicy, hasCustomArticleRoute, isRoutePolicy, mergeRouteParams, resolveRoutePolicy } from './routes.mjs';
|
|
2
|
+
|
|
1
3
|
const DEFAULT_CONFIG = {
|
|
2
4
|
defaultLocale: "en",
|
|
3
5
|
timeout: 1e4
|
|
@@ -158,13 +160,23 @@ class CmsClient {
|
|
|
158
160
|
);
|
|
159
161
|
return normalizeListResponse(result, "/redirects");
|
|
160
162
|
}
|
|
163
|
+
/** 获取站点运行时配置 */
|
|
164
|
+
async getSiteConfig(options) {
|
|
165
|
+
return this.request(
|
|
166
|
+
"GET",
|
|
167
|
+
"/site-config",
|
|
168
|
+
options,
|
|
169
|
+
void 0,
|
|
170
|
+
{ defaultLocale: false }
|
|
171
|
+
);
|
|
172
|
+
}
|
|
161
173
|
/** 获取文章系列 */
|
|
162
174
|
async getSeries(slug, locale) {
|
|
163
175
|
return this.request("GET", `/series/${encodeURIComponent(slug)}`, { locale });
|
|
164
176
|
}
|
|
165
177
|
// ─── 内部请求方法 ──────────────────────────────────
|
|
166
|
-
async request(method, path, query, body) {
|
|
167
|
-
if (method === "GET" && this.config.defaultLocale) {
|
|
178
|
+
async request(method, path, query, body, options) {
|
|
179
|
+
if (method === "GET" && options?.defaultLocale !== false && this.config.defaultLocale) {
|
|
168
180
|
const q = query ?? {};
|
|
169
181
|
if (q.locale === void 0 || q.locale === null) {
|
|
170
182
|
q.locale = this.config.defaultLocale;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
type RouteParams = Record<string, string | number | boolean | null | undefined>;
|
|
2
|
+
interface RouteResources {
|
|
3
|
+
index?: string;
|
|
4
|
+
category?: string;
|
|
5
|
+
article?: string;
|
|
6
|
+
author?: string;
|
|
7
|
+
[resource: string]: string | undefined;
|
|
8
|
+
}
|
|
9
|
+
interface RouteLocalePolicy {
|
|
10
|
+
defaultLocale?: string;
|
|
11
|
+
prefixes?: Record<string, string>;
|
|
12
|
+
includeDefaultLocale?: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface RoutePolicy {
|
|
15
|
+
resources?: RouteResources;
|
|
16
|
+
sourceResources?: RouteResources;
|
|
17
|
+
locale?: RouteLocalePolicy;
|
|
18
|
+
}
|
|
19
|
+
interface RoutePolicyConfig {
|
|
20
|
+
defaultLocale?: string;
|
|
21
|
+
localePrefixes?: Record<string, string>;
|
|
22
|
+
routes?: RoutePolicy;
|
|
23
|
+
}
|
|
24
|
+
interface BuildRoutePathOptions {
|
|
25
|
+
includeLocale?: boolean;
|
|
26
|
+
}
|
|
27
|
+
interface BuildRouteUrlOptions extends BuildRoutePathOptions {
|
|
28
|
+
}
|
|
29
|
+
interface ResolvedRouteLocalePolicy {
|
|
30
|
+
defaultLocale: string;
|
|
31
|
+
prefixes: Record<string, string>;
|
|
32
|
+
includeDefaultLocale: boolean;
|
|
33
|
+
}
|
|
34
|
+
type RouteResourceDefaults = RouteResources & Required<Pick<RouteResources, 'article' | 'author' | 'category' | 'index'>>;
|
|
35
|
+
interface ResolvedRoutePolicy {
|
|
36
|
+
resources: RouteResourceDefaults;
|
|
37
|
+
sourceResources: RouteResourceDefaults;
|
|
38
|
+
locale: ResolvedRouteLocalePolicy;
|
|
39
|
+
}
|
|
40
|
+
declare const DEFAULT_ROUTE_RESOURCES: RouteResourceDefaults;
|
|
41
|
+
declare function resolveRoutePolicy(config?: RoutePolicyConfig): ResolvedRoutePolicy;
|
|
42
|
+
declare function buildRoutePath(policy: RoutePolicy, resource: string, params?: RouteParams, options?: BuildRoutePathOptions): string;
|
|
43
|
+
declare function buildRouteUrl(baseUrl: string, policy: null | RoutePolicy | undefined, resource: string, params?: RouteParams, options?: BuildRouteUrlOptions): string;
|
|
44
|
+
declare function isRoutePolicy(value: unknown): value is RoutePolicy;
|
|
45
|
+
declare function hasCustomArticleRoute(policy?: null | RoutePolicy): boolean;
|
|
46
|
+
declare function formatRoutePolicy(policy?: null | RoutePolicy): string;
|
|
47
|
+
declare function extractRouteParams(pattern: string, path: string): RouteParams | null;
|
|
48
|
+
declare function extractSourceRouteParams(policy: RoutePolicy, resource: string, path: string): RouteParams | null;
|
|
49
|
+
declare function mergeRouteParams(left: RouteParams | null | undefined, right: RouteParams | null | undefined): {
|
|
50
|
+
[x: string]: string | number | boolean | null | undefined;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export { DEFAULT_ROUTE_RESOURCES, buildRoutePath, buildRouteUrl, extractRouteParams, extractSourceRouteParams, formatRoutePolicy, hasCustomArticleRoute, isRoutePolicy, mergeRouteParams, resolveRoutePolicy };
|
|
54
|
+
export type { BuildRoutePathOptions, BuildRouteUrlOptions, ResolvedRouteLocalePolicy, ResolvedRoutePolicy, RouteLocalePolicy, RouteParams, RoutePolicy, RoutePolicyConfig, RouteResourceDefaults, RouteResources };
|
package/dist/routes.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
type RouteParams = Record<string, string | number | boolean | null | undefined>;
|
|
2
|
+
interface RouteResources {
|
|
3
|
+
index?: string;
|
|
4
|
+
category?: string;
|
|
5
|
+
article?: string;
|
|
6
|
+
author?: string;
|
|
7
|
+
[resource: string]: string | undefined;
|
|
8
|
+
}
|
|
9
|
+
interface RouteLocalePolicy {
|
|
10
|
+
defaultLocale?: string;
|
|
11
|
+
prefixes?: Record<string, string>;
|
|
12
|
+
includeDefaultLocale?: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface RoutePolicy {
|
|
15
|
+
resources?: RouteResources;
|
|
16
|
+
sourceResources?: RouteResources;
|
|
17
|
+
locale?: RouteLocalePolicy;
|
|
18
|
+
}
|
|
19
|
+
interface RoutePolicyConfig {
|
|
20
|
+
defaultLocale?: string;
|
|
21
|
+
localePrefixes?: Record<string, string>;
|
|
22
|
+
routes?: RoutePolicy;
|
|
23
|
+
}
|
|
24
|
+
interface BuildRoutePathOptions {
|
|
25
|
+
includeLocale?: boolean;
|
|
26
|
+
}
|
|
27
|
+
interface BuildRouteUrlOptions extends BuildRoutePathOptions {
|
|
28
|
+
}
|
|
29
|
+
interface ResolvedRouteLocalePolicy {
|
|
30
|
+
defaultLocale: string;
|
|
31
|
+
prefixes: Record<string, string>;
|
|
32
|
+
includeDefaultLocale: boolean;
|
|
33
|
+
}
|
|
34
|
+
type RouteResourceDefaults = RouteResources & Required<Pick<RouteResources, 'article' | 'author' | 'category' | 'index'>>;
|
|
35
|
+
interface ResolvedRoutePolicy {
|
|
36
|
+
resources: RouteResourceDefaults;
|
|
37
|
+
sourceResources: RouteResourceDefaults;
|
|
38
|
+
locale: ResolvedRouteLocalePolicy;
|
|
39
|
+
}
|
|
40
|
+
declare const DEFAULT_ROUTE_RESOURCES: RouteResourceDefaults;
|
|
41
|
+
declare function resolveRoutePolicy(config?: RoutePolicyConfig): ResolvedRoutePolicy;
|
|
42
|
+
declare function buildRoutePath(policy: RoutePolicy, resource: string, params?: RouteParams, options?: BuildRoutePathOptions): string;
|
|
43
|
+
declare function buildRouteUrl(baseUrl: string, policy: null | RoutePolicy | undefined, resource: string, params?: RouteParams, options?: BuildRouteUrlOptions): string;
|
|
44
|
+
declare function isRoutePolicy(value: unknown): value is RoutePolicy;
|
|
45
|
+
declare function hasCustomArticleRoute(policy?: null | RoutePolicy): boolean;
|
|
46
|
+
declare function formatRoutePolicy(policy?: null | RoutePolicy): string;
|
|
47
|
+
declare function extractRouteParams(pattern: string, path: string): RouteParams | null;
|
|
48
|
+
declare function extractSourceRouteParams(policy: RoutePolicy, resource: string, path: string): RouteParams | null;
|
|
49
|
+
declare function mergeRouteParams(left: RouteParams | null | undefined, right: RouteParams | null | undefined): {
|
|
50
|
+
[x: string]: string | number | boolean | null | undefined;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export { DEFAULT_ROUTE_RESOURCES, buildRoutePath, buildRouteUrl, extractRouteParams, extractSourceRouteParams, formatRoutePolicy, hasCustomArticleRoute, isRoutePolicy, mergeRouteParams, resolveRoutePolicy };
|
|
54
|
+
export type { BuildRoutePathOptions, BuildRouteUrlOptions, ResolvedRouteLocalePolicy, ResolvedRoutePolicy, RouteLocalePolicy, RouteParams, RoutePolicy, RoutePolicyConfig, RouteResourceDefaults, RouteResources };
|
package/dist/routes.mjs
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
const DEFAULT_ROUTE_RESOURCES = {
|
|
2
|
+
index: "/",
|
|
3
|
+
category: "/{category_slug}",
|
|
4
|
+
article: "/{category_slug}/{slug}",
|
|
5
|
+
author: "/authors/{slug}"
|
|
6
|
+
};
|
|
7
|
+
function trimSlashes(value) {
|
|
8
|
+
return value.replace(/^\/+|\/+$/g, "");
|
|
9
|
+
}
|
|
10
|
+
function normalizePath(path) {
|
|
11
|
+
const clean = path.split("?")[0]?.split("#")[0] ?? "";
|
|
12
|
+
const withSlash = clean.startsWith("/") ? clean : `/${clean}`;
|
|
13
|
+
const collapsed = withSlash.replace(/\/{2,}/g, "/");
|
|
14
|
+
if (collapsed.length > 1) return collapsed.replace(/\/+$/g, "");
|
|
15
|
+
return collapsed;
|
|
16
|
+
}
|
|
17
|
+
function encodePathValue(value) {
|
|
18
|
+
return encodeURIComponent(String(value));
|
|
19
|
+
}
|
|
20
|
+
function isPlainObject(value) {
|
|
21
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22
|
+
}
|
|
23
|
+
function isStringRecord(value) {
|
|
24
|
+
if (!isPlainObject(value)) return false;
|
|
25
|
+
return Object.values(value).every((item) => typeof item === "string");
|
|
26
|
+
}
|
|
27
|
+
function localePrefix(locale, policy) {
|
|
28
|
+
if (!locale) return "";
|
|
29
|
+
if (locale === policy.defaultLocale && !policy.includeDefaultLocale) return "";
|
|
30
|
+
const prefix = policy.prefixes[locale] ?? locale.toLowerCase();
|
|
31
|
+
return `/${trimSlashes(prefix)}`;
|
|
32
|
+
}
|
|
33
|
+
function mergeResources(resources) {
|
|
34
|
+
return {
|
|
35
|
+
...DEFAULT_ROUTE_RESOURCES,
|
|
36
|
+
...resources ?? {}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function resolveRoutePolicy(config) {
|
|
40
|
+
const routes = config?.routes ?? {};
|
|
41
|
+
const defaultLocale = routes.locale?.defaultLocale ?? config?.defaultLocale ?? "en";
|
|
42
|
+
const prefixes = {
|
|
43
|
+
...config?.localePrefixes ?? {},
|
|
44
|
+
...routes.locale?.prefixes ?? {}
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
resources: mergeResources(routes.resources),
|
|
48
|
+
sourceResources: mergeResources(routes.sourceResources),
|
|
49
|
+
locale: {
|
|
50
|
+
defaultLocale,
|
|
51
|
+
prefixes,
|
|
52
|
+
includeDefaultLocale: routes.locale?.includeDefaultLocale ?? false
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function buildRoutePath(policy, resource, params = {}, options = {}) {
|
|
57
|
+
const resolvedPolicy = resolveRoutePolicy({ routes: policy });
|
|
58
|
+
const pattern = resolvedPolicy.resources[resource];
|
|
59
|
+
if (!pattern) {
|
|
60
|
+
throw new Error(`CMS route pattern is not configured for resource '${resource}'`);
|
|
61
|
+
}
|
|
62
|
+
const path = normalizePath(
|
|
63
|
+
pattern.replace(/\{(\w+)\}/g, (_, key) => {
|
|
64
|
+
const value = params[key];
|
|
65
|
+
if (value === void 0 || value === null || value === "") {
|
|
66
|
+
throw new Error(`CMS route parameter '${key}' is required for resource '${resource}'`);
|
|
67
|
+
}
|
|
68
|
+
return encodePathValue(value);
|
|
69
|
+
})
|
|
70
|
+
);
|
|
71
|
+
if (!options.includeLocale) return path;
|
|
72
|
+
return normalizePath(`${localePrefix(String(params.locale ?? ""), resolvedPolicy.locale)}${path}`);
|
|
73
|
+
}
|
|
74
|
+
function buildRouteUrl(baseUrl, policy, resource, params = {}, options = {}) {
|
|
75
|
+
const path = buildRoutePath(policy ?? {}, resource, params, options);
|
|
76
|
+
const normalizedBaseUrl = baseUrl.replace(/\/+$/g, "");
|
|
77
|
+
return normalizedBaseUrl ? `${normalizedBaseUrl}${path}` : path;
|
|
78
|
+
}
|
|
79
|
+
function isRoutePolicy(value) {
|
|
80
|
+
if (!isPlainObject(value)) return false;
|
|
81
|
+
const { locale, resources, sourceResources } = value;
|
|
82
|
+
if (resources !== void 0 && !isStringRecord(resources)) return false;
|
|
83
|
+
if (sourceResources !== void 0 && !isStringRecord(sourceResources)) return false;
|
|
84
|
+
if (locale !== void 0) {
|
|
85
|
+
if (!isPlainObject(locale)) return false;
|
|
86
|
+
if (locale.defaultLocale !== void 0 && typeof locale.defaultLocale !== "string") return false;
|
|
87
|
+
if (locale.includeDefaultLocale !== void 0 && typeof locale.includeDefaultLocale !== "boolean")
|
|
88
|
+
return false;
|
|
89
|
+
if (locale.prefixes !== void 0 && !isStringRecord(locale.prefixes)) return false;
|
|
90
|
+
}
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
function hasCustomArticleRoute(policy) {
|
|
94
|
+
return resolveRoutePolicy({ routes: policy ?? void 0 }).resources.article !== DEFAULT_ROUTE_RESOURCES.article;
|
|
95
|
+
}
|
|
96
|
+
function formatRoutePolicy(policy) {
|
|
97
|
+
return JSON.stringify(resolveRoutePolicy({ routes: policy ?? void 0 }), null, 2);
|
|
98
|
+
}
|
|
99
|
+
function extractRouteParams(pattern, path) {
|
|
100
|
+
const keys = [];
|
|
101
|
+
const source = normalizePath(pattern);
|
|
102
|
+
let expression = "^";
|
|
103
|
+
for (let index = 0; index < source.length; index++) {
|
|
104
|
+
const char = source[index];
|
|
105
|
+
if (char === "{") {
|
|
106
|
+
const closeIndex = source.indexOf("}", index);
|
|
107
|
+
if (closeIndex > index) {
|
|
108
|
+
const key = source.slice(index + 1, closeIndex);
|
|
109
|
+
keys.push(key);
|
|
110
|
+
expression += "([^/]+)";
|
|
111
|
+
index = closeIndex;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
expression += char.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
116
|
+
}
|
|
117
|
+
expression += "$";
|
|
118
|
+
const match = normalizePath(path).match(new RegExp(expression));
|
|
119
|
+
if (!match) return null;
|
|
120
|
+
const params = {};
|
|
121
|
+
for (let index = 0; index < keys.length; index++) {
|
|
122
|
+
const raw = match[index + 1];
|
|
123
|
+
if (raw) params[keys[index]] = decodeURIComponent(raw);
|
|
124
|
+
}
|
|
125
|
+
return params;
|
|
126
|
+
}
|
|
127
|
+
function extractSourceRouteParams(policy, resource, path) {
|
|
128
|
+
const resolvedPolicy = resolveRoutePolicy({ routes: policy });
|
|
129
|
+
const candidates = [
|
|
130
|
+
resolvedPolicy.sourceResources[resource],
|
|
131
|
+
resolvedPolicy.resources[resource],
|
|
132
|
+
DEFAULT_ROUTE_RESOURCES[resource]
|
|
133
|
+
].filter((pattern) => Boolean(pattern));
|
|
134
|
+
for (const pattern of candidates) {
|
|
135
|
+
const params = extractRouteParams(pattern, path);
|
|
136
|
+
if (params) return params;
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
function mergeRouteParams(left, right) {
|
|
141
|
+
return {
|
|
142
|
+
...left ?? {},
|
|
143
|
+
...right ?? {}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export { DEFAULT_ROUTE_RESOURCES, buildRoutePath, buildRouteUrl, extractRouteParams, extractSourceRouteParams, formatRoutePolicy, hasCustomArticleRoute, isRoutePolicy, mergeRouteParams, resolveRoutePolicy };
|
package/dist/types.d.mts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { RoutePolicy } from './routes.mjs';
|
|
2
|
+
export { BuildRoutePathOptions, ResolvedRouteLocalePolicy, ResolvedRoutePolicy, RouteLocalePolicy, RouteParams, RoutePolicyConfig, RouteResourceDefaults, RouteResources } from './routes.mjs';
|
|
3
|
+
|
|
1
4
|
/** 作者信息 (Go: delivery.DeliveryAuthorResponse) */
|
|
2
5
|
interface Author {
|
|
3
6
|
id: number;
|
|
@@ -6,6 +9,9 @@ interface Author {
|
|
|
6
9
|
slug: string;
|
|
7
10
|
avatar_url?: string;
|
|
8
11
|
bio?: string;
|
|
12
|
+
seo_meta?: Partial<SeoMeta>;
|
|
13
|
+
og_meta?: Partial<OgMeta>;
|
|
14
|
+
twitter_meta?: Partial<TwitterMeta>;
|
|
9
15
|
available_locales?: string[];
|
|
10
16
|
localized_slugs?: Record<string, string>;
|
|
11
17
|
}
|
|
@@ -174,6 +180,7 @@ interface RedirectRule {
|
|
|
174
180
|
destination_path: string;
|
|
175
181
|
status_code: number;
|
|
176
182
|
match_type: string;
|
|
183
|
+
priority: number;
|
|
177
184
|
}
|
|
178
185
|
|
|
179
186
|
/** 文章系列 (Go: delivery.DeliverySeriesResponse) */
|
|
@@ -185,6 +192,20 @@ interface Series {
|
|
|
185
192
|
articles: ArticleListItem[];
|
|
186
193
|
}
|
|
187
194
|
|
|
195
|
+
interface SiteConfig {
|
|
196
|
+
product_code: string;
|
|
197
|
+
site_name: string;
|
|
198
|
+
site_url: string;
|
|
199
|
+
sitemap_path: string;
|
|
200
|
+
domain_aliases: string[];
|
|
201
|
+
route_policy: RoutePolicy;
|
|
202
|
+
updated_at: string;
|
|
203
|
+
}
|
|
204
|
+
interface SiteConfigQuery {
|
|
205
|
+
site_url?: string;
|
|
206
|
+
host?: string;
|
|
207
|
+
}
|
|
208
|
+
|
|
188
209
|
/** Hreflang 条目 (Go: delivery.HreflangEntry) */
|
|
189
210
|
interface HreflangEntry {
|
|
190
211
|
lang: string;
|
|
@@ -218,4 +239,5 @@ interface RevalidatePayload {
|
|
|
218
239
|
category_slug?: string;
|
|
219
240
|
}
|
|
220
241
|
|
|
221
|
-
export
|
|
242
|
+
export { RoutePolicy };
|
|
243
|
+
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, SiteConfig, SiteConfigQuery, SitemapEntry, SitemapImageEntry, TwitterMeta, WebhookEventType };
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { RoutePolicy } from './routes.js';
|
|
2
|
+
export { BuildRoutePathOptions, ResolvedRouteLocalePolicy, ResolvedRoutePolicy, RouteLocalePolicy, RouteParams, RoutePolicyConfig, RouteResourceDefaults, RouteResources } from './routes.js';
|
|
3
|
+
|
|
1
4
|
/** 作者信息 (Go: delivery.DeliveryAuthorResponse) */
|
|
2
5
|
interface Author {
|
|
3
6
|
id: number;
|
|
@@ -6,6 +9,9 @@ interface Author {
|
|
|
6
9
|
slug: string;
|
|
7
10
|
avatar_url?: string;
|
|
8
11
|
bio?: string;
|
|
12
|
+
seo_meta?: Partial<SeoMeta>;
|
|
13
|
+
og_meta?: Partial<OgMeta>;
|
|
14
|
+
twitter_meta?: Partial<TwitterMeta>;
|
|
9
15
|
available_locales?: string[];
|
|
10
16
|
localized_slugs?: Record<string, string>;
|
|
11
17
|
}
|
|
@@ -174,6 +180,7 @@ interface RedirectRule {
|
|
|
174
180
|
destination_path: string;
|
|
175
181
|
status_code: number;
|
|
176
182
|
match_type: string;
|
|
183
|
+
priority: number;
|
|
177
184
|
}
|
|
178
185
|
|
|
179
186
|
/** 文章系列 (Go: delivery.DeliverySeriesResponse) */
|
|
@@ -185,6 +192,20 @@ interface Series {
|
|
|
185
192
|
articles: ArticleListItem[];
|
|
186
193
|
}
|
|
187
194
|
|
|
195
|
+
interface SiteConfig {
|
|
196
|
+
product_code: string;
|
|
197
|
+
site_name: string;
|
|
198
|
+
site_url: string;
|
|
199
|
+
sitemap_path: string;
|
|
200
|
+
domain_aliases: string[];
|
|
201
|
+
route_policy: RoutePolicy;
|
|
202
|
+
updated_at: string;
|
|
203
|
+
}
|
|
204
|
+
interface SiteConfigQuery {
|
|
205
|
+
site_url?: string;
|
|
206
|
+
host?: string;
|
|
207
|
+
}
|
|
208
|
+
|
|
188
209
|
/** Hreflang 条目 (Go: delivery.HreflangEntry) */
|
|
189
210
|
interface HreflangEntry {
|
|
190
211
|
lang: string;
|
|
@@ -218,4 +239,5 @@ interface RevalidatePayload {
|
|
|
218
239
|
category_slug?: string;
|
|
219
240
|
}
|
|
220
241
|
|
|
221
|
-
export
|
|
242
|
+
export { RoutePolicy };
|
|
243
|
+
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, SiteConfig, SiteConfigQuery, SitemapEntry, SitemapImageEntry, TwitterMeta, WebhookEventType };
|
package/package.json
CHANGED
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vigilkids/cms-client",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Framework-agnostic TypeScript client for OnEx CMS Public API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
|
+
"typesVersions": {
|
|
9
|
+
"*": {
|
|
10
|
+
"routes": [
|
|
11
|
+
"./dist/routes.d.ts"
|
|
12
|
+
],
|
|
13
|
+
"types": [
|
|
14
|
+
"./dist/types.d.ts"
|
|
15
|
+
],
|
|
16
|
+
"webhook": [
|
|
17
|
+
"./dist/webhook.d.ts"
|
|
18
|
+
],
|
|
19
|
+
"*": [
|
|
20
|
+
"./dist/index.d.ts"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
},
|
|
8
24
|
"exports": {
|
|
9
25
|
".": {
|
|
10
26
|
"types": "./dist/index.d.ts",
|
|
@@ -14,6 +30,10 @@
|
|
|
14
30
|
"types": "./dist/types.d.ts",
|
|
15
31
|
"import": "./dist/types.mjs"
|
|
16
32
|
},
|
|
33
|
+
"./routes": {
|
|
34
|
+
"types": "./dist/routes.d.ts",
|
|
35
|
+
"import": "./dist/routes.mjs"
|
|
36
|
+
},
|
|
17
37
|
"./webhook": {
|
|
18
38
|
"types": "./dist/webhook.d.ts",
|
|
19
39
|
"import": "./dist/webhook.mjs"
|
|
@@ -26,6 +46,7 @@
|
|
|
26
46
|
"sideEffects": false,
|
|
27
47
|
"scripts": {
|
|
28
48
|
"build": "unbuild",
|
|
49
|
+
"prepack": "pnpm build",
|
|
29
50
|
"lint": "eslint .",
|
|
30
51
|
"lint:fix": "eslint . --fix",
|
|
31
52
|
"format": "prettier --write src/"
|