@bbki.ng/site 5.5.36 → 5.5.37

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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # @bbki.ng/site
2
2
 
3
+ ## 5.5.37
4
+
5
+ ### Patch Changes
6
+
7
+ - 56a7bc7: fix 404 error page
8
+ - Updated dependencies [56a7bc7]
9
+ - @bbki.ng/ui@0.2.18
10
+
3
11
  ## 5.5.36
4
12
 
5
13
  ### Patch Changes
package/eslint.config.js CHANGED
@@ -9,6 +9,13 @@ const __dirname = path.dirname(__filename);
9
9
  export default [
10
10
  includeIgnoreFile(path.resolve(__dirname, '.gitignore')),
11
11
  ...webConfig,
12
+ {
13
+ languageOptions: {
14
+ globals: {
15
+ GLOBAL_COMMIT_HASH: 'readonly',
16
+ },
17
+ },
18
+ },
12
19
  {
13
20
  rules: {
14
21
  // Site specific overrides
package/index.d.ts CHANGED
@@ -15,5 +15,3 @@ declare global {
15
15
  }
16
16
  }
17
17
  }
18
-
19
- export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbki.ng/site",
3
- "version": "5.5.36",
3
+ "version": "5.5.37",
4
4
  "description": "code behind bbki.ng",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -14,7 +14,7 @@
14
14
  "react-dom": "^18.0.0",
15
15
  "react-router-dom": "6",
16
16
  "swr": "^2.2.5",
17
- "@bbki.ng/ui": "0.2.17"
17
+ "@bbki.ng/ui": "0.2.18"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@eslint/compat": "^1.0.0",
package/src/blog/app.tsx CHANGED
@@ -36,8 +36,8 @@ const AppRoutes = () => {
36
36
  {pluginEntries?.map(route => (
37
37
  <Route key={route.path} path={route.path} element={<Slot name="route" data={route} />} />
38
38
  ))}
39
+ <Route path="*" element={pluginEntries?.length ? <NotFound /> : null} />
39
40
  </Route>
40
- <Route path="*" element={<NotFound />} />
41
41
  </Routes>
42
42
  );
43
43
  };
@@ -10,6 +10,11 @@ import { useMiddlewareRunner } from '#/core/hooks/useMiddlewareTransData';
10
10
  const isProd = true;
11
11
  const POSTS_API = !isProd ? '/api/posts' : `${API_ENDPOINT}/posts`;
12
12
 
13
+ interface PostsApiResponse {
14
+ data: IPost[];
15
+ // 可能还有其他字段如 status, message 等
16
+ }
17
+
13
18
  export interface TitleListItem {
14
19
  name: string;
15
20
  to: string;
@@ -18,7 +23,7 @@ export interface TitleListItem {
18
23
  }
19
24
 
20
25
  export const usePosts = (name: string = '', suspense?: boolean) => {
21
- const { data: response, error: swrError } = useSWR(POSTS_API, baseFetcher, {
26
+ const { data: response, error: swrError } = useSWR<PostsApiResponse>(POSTS_API, baseFetcher, {
22
27
  revalidateOnFocus: false,
23
28
  suspense,
24
29
  });
@@ -6,6 +6,7 @@ import { usePosts } from '@/hooks/use_posts';
6
6
  import { ArticlePage } from '@/components/article';
7
7
  import { useBlogScrollReset } from '@/hooks/use_blog_scroll_pos_restoration';
8
8
  import { useMiddlewareTransformedData } from '#/core/hooks/useMiddlewareTransData';
9
+ import { IPost } from '#/types/posts';
9
10
 
10
11
  function TxtArticle() {
11
12
  const { title } = useParams();
@@ -13,7 +14,9 @@ function TxtArticle() {
13
14
 
14
15
  useBlogScrollReset();
15
16
 
16
- const transformedContent = useMiddlewareTransformedData('transformPostContent', posts?.content);
17
+ const p = posts as IPost;
18
+
19
+ const transformedContent = useMiddlewareTransformedData('transformPostContent', p?.content);
17
20
 
18
21
  if (!title) {
19
22
  return <NotFound />;
@@ -27,7 +30,7 @@ function TxtArticle() {
27
30
  return null;
28
31
  }
29
32
 
30
- const date = posts.createdAt ? posts.createdAt.split('T')[0] : '';
33
+ const date = p.createdAt ? p.createdAt.split('T')[0] : '';
31
34
 
32
35
  return (
33
36
  <ArticlePage title={title} date={date}>
@@ -2,33 +2,38 @@ import { API_ENDPOINT } from '@/constants/routes';
2
2
 
3
3
  import { getStableDeviceId } from './fingerprints';
4
4
 
5
- type Fetcher = (resource: string, init?: RequestInit) => Promise<unknown>;
5
+ type RequestInit = globalThis.RequestInit;
6
+
7
+ type Fetcher = <T>(resource: string, init?: RequestInit) => Promise<T>;
6
8
 
7
9
  export const floatNumberToPercentageString = (num: number): string => {
8
10
  return `${num * 100}%`;
9
11
  };
10
12
 
11
- export const baseFetcher = async (resource: string, init: RequestInit = {}) => {
13
+ // 2. 显式声明为 Fetcher 类型,init 默认值改为 RequestInit
14
+ export const baseFetcher: Fetcher = async (resource, init = {}) => {
12
15
  const headers = new Headers(init.headers || {});
13
16
  const fp = await getStableDeviceId();
14
17
  headers.set('X-Device-Fingerprint', fp.id);
15
- return fetch(resource, {
18
+
19
+ const response = await fetch(resource, {
16
20
  ...init,
17
21
  headers,
18
22
  mode: 'cors',
19
- }).then(res => {
20
- if (!res.ok) {
21
- throw new Error('An error occurred while fetching the data.');
22
- }
23
-
24
- return res.json();
25
23
  });
24
+
25
+ if (!response.ok) {
26
+ throw new Error('An error occurred while fetching the data.');
27
+ }
28
+
29
+ return response.json();
26
30
  };
27
31
 
32
+ // 3. 简化 withBBApi 类型定义,确保参数类型一致
28
33
  export const withBBApi =
29
34
  (fetcher: Fetcher) =>
30
35
  (apiEndPoint: string): Fetcher =>
31
- async (resource: string, init: RequestInit = {}) =>
36
+ async (resource, init = {}) =>
32
37
  fetcher(`${apiEndPoint}/${resource}`, { ...init, mode: 'cors' });
33
38
 
34
39
  export const cfApiFetcher = withBBApi(baseFetcher)(API_ENDPOINT);
@@ -9,6 +9,7 @@ import { useStreaming } from '../../hooks/use_streaming';
9
9
  import { useScrollBtnVisibility } from './useScrollBtnVisibility';
10
10
 
11
11
  declare global {
12
+ // eslint-disable-next-line @typescript-eslint/no-namespace
12
13
  namespace JSX {
13
14
  interface IntrinsicElements {
14
15
  'bb-msg-history': React.DetailedHTMLProps<
@@ -39,7 +40,7 @@ const Streaming = () => {
39
40
 
40
41
  useEffect(() => {
41
42
  const el = bbMsgHistoryRef.current;
42
- let timer: NodeJS.Timeout;
43
+ let timer: ReturnType<typeof setTimeout>;
43
44
  if (!isLoading && el) {
44
45
  // 检查自定义元素是否已定义并升级
45
46
  if (el.scrollToBottom) {
@@ -2,6 +2,7 @@ import { IHostContext } from '#/types/hostApi';
2
2
  import { IPlugin } from '#/types/plugin';
3
3
  import { HookPoint } from '#/types/slots';
4
4
 
5
+ import { HookPointTypeMap, Transformer } from './types';
5
6
  import { SpecialTitle } from './components/article';
6
7
  import { XwyLogo } from './components/logo';
7
8
  import { FontRules, LOADING_CLASS } from './const';
@@ -43,7 +44,9 @@ class XwyPlugin implements IPlugin {
43
44
  ctx.api.registerSlot('articleTitle', SpecialTitle, this.id);
44
45
  };
45
46
 
46
- private trasformerMap: Partial<Record<HookPoint, Array<(baseData: any) => any>>> = {
47
+ private trasformerMap: {
48
+ [K in Extract<HookPoint, keyof HookPointTypeMap>]?: Array<Transformer<K>>;
49
+ } = {
47
50
  transformTitleList: [pinTitle, transformTitleList],
48
51
  transformBreadcrumbPath: [transformBreadcrumbPaths],
49
52
  transformPostContent: [transformPostContent],
@@ -1,3 +1,7 @@
1
+ import { PathObj } from '@bbki.ng/ui';
2
+
3
+ import { TitleListItem } from '#/types/posts';
4
+
1
5
  export interface FontConfig {
2
6
  name: string;
3
7
  src: string;
@@ -15,3 +19,17 @@ export interface FontRule {
15
19
  extraCls?: string;
16
20
  variant?: 'default' | 'special';
17
21
  }
22
+
23
+ // 1. 先定义每个 HookPoint 对应的类型映射
24
+ export interface HookPointTypeMap {
25
+ transformTitleList: { input: TitleListItem[]; output: TitleListItem[] };
26
+ transformBreadcrumbPath: { input: PathObj[]; output: PathObj[] };
27
+ transformPostContent: { input: string; output: string };
28
+ }
29
+
30
+ type HookPoint = keyof HookPointTypeMap;
31
+
32
+ // 2. 定义带类型的 Transformer
33
+ export type Transformer<K extends HookPoint> = (
34
+ baseData: HookPointTypeMap[K]['input']
35
+ ) => HookPointTypeMap[K]['output'];
package/tsconfig.json CHANGED
@@ -10,5 +10,5 @@
10
10
  "#/*": ["./src/*"]
11
11
  }
12
12
  },
13
- "include": ["./src", "vite.config.js", "index.d.ts"]
13
+ "include": ["./src", "vite.config.js", "**/*.d.ts"]
14
14
  }