@mx-space/api-client 2.1.0 → 2.1.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.
@@ -56,9 +56,8 @@ const axiosAdaptor = Object.preventExtensions({
56
56
  return $http.patch(url, data, config);
57
57
  }
58
58
  });
59
- var axios_default = axiosAdaptor;
60
59
 
61
60
  //#endregion
62
61
  exports.__toESM = __toESM;
63
62
  exports.axiosAdaptor = axiosAdaptor;
64
- exports.default = axios_default;
63
+ exports.default = axiosAdaptor;
@@ -27,7 +27,6 @@ const axiosAdaptor = Object.preventExtensions({
27
27
  return $http.patch(url, data, config);
28
28
  }
29
29
  });
30
- var axios_default = axiosAdaptor;
31
30
 
32
31
  //#endregion
33
- export { axiosAdaptor, axios_default as default };
32
+ export { axiosAdaptor, axiosAdaptor as default };
@@ -29,8 +29,7 @@ const umiAdaptor = Object.preventExtensions({
29
29
  return $http.patch(url, options);
30
30
  }
31
31
  });
32
- var umi_request_default = umiAdaptor;
33
32
 
34
33
  //#endregion
35
- exports.default = umi_request_default;
34
+ exports.default = umiAdaptor;
36
35
  exports.umiAdaptor = umiAdaptor;
@@ -27,7 +27,6 @@ const umiAdaptor = Object.preventExtensions({
27
27
  return $http.patch(url, options);
28
28
  }
29
29
  });
30
- var umi_request_default = umiAdaptor;
31
30
 
32
31
  //#endregion
33
- export { umi_request_default as default, umiAdaptor };
32
+ export { umiAdaptor as default, umiAdaptor };
package/dist/index.cjs CHANGED
@@ -201,6 +201,14 @@ var AggregateController = class {
201
201
  year
202
202
  } });
203
203
  }
204
+ getLatest(options) {
205
+ const { limit, types, combined } = options || {};
206
+ return this.proxy.latest.get({ params: {
207
+ limit,
208
+ types: types?.join(","),
209
+ combined
210
+ } });
211
+ }
204
212
  /**
205
213
  * 获取聚合数据统计
206
214
  */
@@ -517,6 +525,15 @@ var NoteController = class {
517
525
  prefer
518
526
  } });
519
527
  }
528
+ getNoteBySlugDate(year, month, day, slug, options) {
529
+ const { password, single, lang, prefer } = options || {};
530
+ return this.proxy(year.toString())(month.toString())(day.toString())(slug).get({ params: {
531
+ password,
532
+ single: single ? "1" : void 0,
533
+ lang,
534
+ prefer
535
+ } });
536
+ }
520
537
  /**
521
538
  * 日记列表分页
522
539
  */
package/dist/index.d.cts CHANGED
@@ -172,6 +172,7 @@ interface TextBaseModelMarkdown extends BaseCommentIndexModel {
172
172
  content?: undefined;
173
173
  images?: Image[];
174
174
  modified: string | null;
175
+ meta?: Record<string, any> | null;
175
176
  }
176
177
  interface TextBaseModelLexical extends BaseCommentIndexModel {
177
178
  title: string;
@@ -180,6 +181,7 @@ interface TextBaseModelLexical extends BaseCommentIndexModel {
180
181
  content: string;
181
182
  images?: Image[];
182
183
  modified: string | null;
184
+ meta?: Record<string, any> | null;
183
185
  }
184
186
  type TextBaseModel = TextBaseModelMarkdown | TextBaseModelLexical;
185
187
  type ModelWithLiked<T> = T & {
@@ -374,6 +376,7 @@ type NoteModel = TextBaseModel & {
374
376
  publicAt?: Date;
375
377
  password?: string | null;
376
378
  nid: number;
379
+ slug?: string;
377
380
  location?: string;
378
381
  coordinates?: Coordinate;
379
382
  topic?: TopicModel;
@@ -620,6 +623,19 @@ interface TimelineData {
620
623
  url: string;
621
624
  })[];
622
625
  }
626
+ interface LatestPostItem extends Pick<PostModel, 'id' | 'title' | 'slug' | 'created' | 'modified' | 'tags'> {
627
+ category: Pick<CategoryModel, 'name' | 'slug'> | null;
628
+ }
629
+ interface LatestNoteItem extends Pick<NoteModel, 'id' | 'title' | 'nid' | 'created' | 'modified' | 'mood' | 'weather' | 'bookmark'> {}
630
+ interface LatestData {
631
+ posts?: LatestPostItem[];
632
+ notes?: LatestNoteItem[];
633
+ }
634
+ type LatestCombinedItem = (LatestPostItem & {
635
+ type: 'post';
636
+ }) | (LatestNoteItem & {
637
+ type: 'note';
638
+ });
623
639
  interface AggregateStat {
624
640
  allComments: number;
625
641
  categories: number;
@@ -1048,6 +1064,16 @@ declare class AggregateController<ResponseWrapper> implements IController {
1048
1064
  data: TimelineData;
1049
1065
  };
1050
1066
  }>;
1067
+ getLatest(options: {
1068
+ limit?: number;
1069
+ types?: TimelineType[];
1070
+ combined: true;
1071
+ }): RequestProxyResult<LatestCombinedItem[], ResponseWrapper>;
1072
+ getLatest(options?: {
1073
+ limit?: number;
1074
+ types?: TimelineType[];
1075
+ combined?: false;
1076
+ }): RequestProxyResult<LatestData, ResponseWrapper>;
1051
1077
  /**
1052
1078
  * 获取聚合数据统计
1053
1079
  */
@@ -1451,7 +1477,7 @@ declare class CategoryController<ResponseWrapper> implements IController {
1451
1477
  name: string;
1452
1478
  created: string;
1453
1479
  id: string;
1454
- children: Pick<PostModel, "id" | "title" | "slug" | "modified" | "created">[];
1480
+ children: Pick<PostModel, "id" | "title" | "modified" | "created" | "slug">[];
1455
1481
  } : T_1 : never : never;
1456
1482
  } : ResponseWrapper;
1457
1483
  $request: {
@@ -1503,7 +1529,7 @@ declare class CategoryController<ResponseWrapper> implements IController {
1503
1529
  };
1504
1530
  }) ? T_1 extends unknown ? {
1505
1531
  tag: string;
1506
- data: Pick<PostModel, "category" | "id" | "title" | "slug" | "created">[];
1532
+ data: Pick<PostModel, "category" | "id" | "title" | "created" | "slug">[];
1507
1533
  } : T_1 : never : never;
1508
1534
  } : ResponseWrapper;
1509
1535
  $request: {
@@ -1695,6 +1721,7 @@ type NoteByNidOptions = {
1695
1721
  lang?: string;
1696
1722
  prefer?: 'lexical';
1697
1723
  };
1724
+ type NoteBySlugDateOptions = NoteByNidOptions;
1698
1725
  type NoteMiddleListOptions = {
1699
1726
  lang?: string;
1700
1727
  };
@@ -1742,6 +1769,7 @@ declare class NoteController<ResponseWrapper> implements IController {
1742
1769
  * @param options 可选参数:password, single, lang
1743
1770
  */
1744
1771
  getNoteByNid(nid: number, options?: NoteByNidOptions): RequestProxyResult<NoteWrappedWithLikedAndTranslationPayload, ResponseWrapper>;
1772
+ getNoteBySlugDate(year: number, month: number, day: number, slug: string, options?: NoteBySlugDateOptions): RequestProxyResult<NoteWrappedWithLikedAndTranslationPayload, ResponseWrapper>;
1745
1773
  /**
1746
1774
  * 日记列表分页
1747
1775
  */
@@ -2306,11 +2334,11 @@ declare class SearchController<ResponseWrapper> implements IController {
2306
2334
  * @param options
2307
2335
  * @returns
2308
2336
  */
2309
- searchByAlgolia(keyword: string, options?: SearchOption): RequestProxyResult<RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "slug" | "modified" | "created"> & {
2337
+ searchByAlgolia(keyword: string, options?: SearchOption): RequestProxyResult<RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "modified" | "created" | "slug"> & {
2310
2338
  type: "post";
2311
2339
  }) | (Pick<NoteModel, "id" | "title" | "modified" | "created" | "nid"> & {
2312
2340
  type: "note";
2313
- }) | (Pick<PageModel, "id" | "title" | "slug" | "modified" | "created"> & {
2341
+ }) | (Pick<PageModel, "id" | "title" | "modified" | "created" | "slug"> & {
2314
2342
  type: "page";
2315
2343
  })> & {
2316
2344
  /**
@@ -2319,11 +2347,11 @@ declare class SearchController<ResponseWrapper> implements IController {
2319
2347
  raw?: any;
2320
2348
  }, ResponseWrapper>, ResponseWrapper, ResponseWrapper extends unknown ? {
2321
2349
  [key: string]: any;
2322
- data: RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "slug" | "modified" | "created"> & {
2350
+ data: RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "modified" | "created" | "slug"> & {
2323
2351
  type: "post";
2324
2352
  }) | (Pick<NoteModel, "id" | "title" | "modified" | "created" | "nid"> & {
2325
2353
  type: "note";
2326
- }) | (Pick<PageModel, "id" | "title" | "slug" | "modified" | "created"> & {
2354
+ }) | (Pick<PageModel, "id" | "title" | "modified" | "created" | "slug"> & {
2327
2355
  type: "page";
2328
2356
  })> & {
2329
2357
  /**
@@ -2332,11 +2360,11 @@ declare class SearchController<ResponseWrapper> implements IController {
2332
2360
  raw?: any;
2333
2361
  }, ResponseWrapper>;
2334
2362
  } : ResponseWrapper extends {
2335
- data: RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "slug" | "modified" | "created"> & {
2363
+ data: RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "modified" | "created" | "slug"> & {
2336
2364
  type: "post";
2337
2365
  }) | (Pick<NoteModel, "id" | "title" | "modified" | "created" | "nid"> & {
2338
2366
  type: "note";
2339
- }) | (Pick<PageModel, "id" | "title" | "slug" | "modified" | "created"> & {
2367
+ }) | (Pick<PageModel, "id" | "title" | "modified" | "created" | "slug"> & {
2340
2368
  type: "page";
2341
2369
  })> & {
2342
2370
  /**
@@ -2345,11 +2373,11 @@ declare class SearchController<ResponseWrapper> implements IController {
2345
2373
  raw?: any;
2346
2374
  }, ResponseWrapper>;
2347
2375
  } ? ResponseWrapper : Omit<ResponseWrapper, "data"> & {
2348
- data: RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "slug" | "modified" | "created"> & {
2376
+ data: RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "modified" | "created" | "slug"> & {
2349
2377
  type: "post";
2350
2378
  }) | (Pick<NoteModel, "id" | "title" | "modified" | "created" | "nid"> & {
2351
2379
  type: "note";
2352
- }) | (Pick<PageModel, "id" | "title" | "slug" | "modified" | "created"> & {
2380
+ }) | (Pick<PageModel, "id" | "title" | "modified" | "created" | "slug"> & {
2353
2381
  type: "page";
2354
2382
  })> & {
2355
2383
  /**
@@ -2498,4 +2526,4 @@ declare const allControllerNames: readonly ["ai", "ack", "activity", "aggregate"
2498
2526
  */
2499
2527
  declare const camelcaseKeys: <T = any>(obj: any) => T;
2500
2528
  //#endregion
2501
- export { AIController, AIDeepReadingModel, AISummaryModel, AISummaryStreamEvent, AITranslationModel, AITranslationStreamEvent, AckController, ActivityController, ActivityPresence, AdminExtraModel, AggregateAIConfig, AggregateController, AggregateRoot, AggregateRootWithTheme, AggregateStat, AggregateTop, AggregateTopNote, AggregateTopPost, AlgoliaSearchOptionsModel, AuthUser, BackupOptionsModel, BaiduSearchOptionsModel, BaseCommentIndexModel, BaseModel, BetterAuthSession, BetterAuthSessionResult, BetterAuthSignInResult, BetterAuthUser, BetterAuthUserRole, BingSearchOptionsModel, CategoryController, CategoryEntries, CategoryModel, CategoryType, CategoryWithChildrenModel, CheckLoggedResult, CollectionRefTypes, CommentController, CommentDto, CommentModel, CommentOptionsModel, CommentRef, CommentState, Coordinate, Count, EnumPageType, type HTTPClient, IConfig, IConfigKeys, type IRequestAdapter, Image, LastYearPublication, LinkController, LinkModel, LinkState, LinkType, MailOptionsModel, ModelWithLiked, ModelWithTranslation, NoteController, type NoteMiddleListOptions, NoteModel, type NoteTimelineItem, type NoteTopicListItem, type NoteTopicListOptions, NoteWrappedPayload, NoteWrappedWithLikedAndTranslationPayload, NoteWrappedWithLikedPayload, OwnerAllowLoginResult, OwnerSessionResult, PageController, PageModel, Pager, PaginateResult, PostController, type PostListItem, type PostListOptions, PostModel, ProjectController, ProjectModel, ReaderModel, RecentActivities, RecentComment, RecentLike, RecentNote, RecentPost, RecentRecent, RecentlyAttitudeEnum, RecentlyAttitudeResultEnum, RecentlyController, RecentlyModel, RecentlyRefType, RecentlyRefTypes, RequestError, RoomOmittedNote, RoomOmittedPage, RoomOmittedPost, RoomsData, SayController, SayModel, SearchController, SeoOptionModel, ServerlessController, SnippetController, SnippetModel, SnippetType, SubscribeAllBit, SubscribeController, SubscribeNoteCreateBit, SubscribePostCreateBit, SubscribeRecentCreateBit, SubscribeSayCreateBit, SubscribeType, SubscribeTypeToBitMap, TLogin, TagModel, TextBaseModel, ThirdPartyServiceIntegrationModel, TimelineData, TimelineType, TopicController, TopicModel, TranslationMeta, Url, UrlOptionModel, UserController, UserModel, allControllerNames, allControllers, createClient, createClient as default, camelcaseKeys as simpleCamelcaseKeys };
2529
+ export { AIController, AIDeepReadingModel, AISummaryModel, AISummaryStreamEvent, AITranslationModel, AITranslationStreamEvent, AckController, ActivityController, ActivityPresence, AdminExtraModel, AggregateAIConfig, AggregateController, AggregateRoot, AggregateRootWithTheme, AggregateStat, AggregateTop, AggregateTopNote, AggregateTopPost, AlgoliaSearchOptionsModel, AuthUser, BackupOptionsModel, BaiduSearchOptionsModel, BaseCommentIndexModel, BaseModel, BetterAuthSession, BetterAuthSessionResult, BetterAuthSignInResult, BetterAuthUser, BetterAuthUserRole, BingSearchOptionsModel, CategoryController, CategoryEntries, CategoryModel, CategoryType, CategoryWithChildrenModel, CheckLoggedResult, CollectionRefTypes, CommentController, CommentDto, CommentModel, CommentOptionsModel, CommentRef, CommentState, Coordinate, Count, EnumPageType, type HTTPClient, IConfig, IConfigKeys, type IRequestAdapter, Image, LastYearPublication, LatestCombinedItem, LatestData, LatestNoteItem, LatestPostItem, LinkController, LinkModel, LinkState, LinkType, MailOptionsModel, ModelWithLiked, ModelWithTranslation, NoteController, type NoteMiddleListOptions, NoteModel, type NoteTimelineItem, type NoteTopicListItem, type NoteTopicListOptions, NoteWrappedPayload, NoteWrappedWithLikedAndTranslationPayload, NoteWrappedWithLikedPayload, OwnerAllowLoginResult, OwnerSessionResult, PageController, PageModel, Pager, PaginateResult, PostController, type PostListItem, type PostListOptions, PostModel, ProjectController, ProjectModel, ReaderModel, RecentActivities, RecentComment, RecentLike, RecentNote, RecentPost, RecentRecent, RecentlyAttitudeEnum, RecentlyAttitudeResultEnum, RecentlyController, RecentlyModel, RecentlyRefType, RecentlyRefTypes, RequestError, RoomOmittedNote, RoomOmittedPage, RoomOmittedPost, RoomsData, SayController, SayModel, SearchController, SeoOptionModel, ServerlessController, SnippetController, SnippetModel, SnippetType, SubscribeAllBit, SubscribeController, SubscribeNoteCreateBit, SubscribePostCreateBit, SubscribeRecentCreateBit, SubscribeSayCreateBit, SubscribeType, SubscribeTypeToBitMap, TLogin, TagModel, TextBaseModel, TextBaseModelLexical, TextBaseModelMarkdown, ThirdPartyServiceIntegrationModel, TimelineData, TimelineType, TopicController, TopicModel, TranslationMeta, Url, UrlOptionModel, UserController, UserModel, allControllerNames, allControllers, createClient, createClient as default, camelcaseKeys as simpleCamelcaseKeys };
package/dist/index.d.mts CHANGED
@@ -172,6 +172,7 @@ interface TextBaseModelMarkdown extends BaseCommentIndexModel {
172
172
  content?: undefined;
173
173
  images?: Image[];
174
174
  modified: string | null;
175
+ meta?: Record<string, any> | null;
175
176
  }
176
177
  interface TextBaseModelLexical extends BaseCommentIndexModel {
177
178
  title: string;
@@ -180,6 +181,7 @@ interface TextBaseModelLexical extends BaseCommentIndexModel {
180
181
  content: string;
181
182
  images?: Image[];
182
183
  modified: string | null;
184
+ meta?: Record<string, any> | null;
183
185
  }
184
186
  type TextBaseModel = TextBaseModelMarkdown | TextBaseModelLexical;
185
187
  type ModelWithLiked<T> = T & {
@@ -374,6 +376,7 @@ type NoteModel = TextBaseModel & {
374
376
  publicAt?: Date;
375
377
  password?: string | null;
376
378
  nid: number;
379
+ slug?: string;
377
380
  location?: string;
378
381
  coordinates?: Coordinate;
379
382
  topic?: TopicModel;
@@ -620,6 +623,19 @@ interface TimelineData {
620
623
  url: string;
621
624
  })[];
622
625
  }
626
+ interface LatestPostItem extends Pick<PostModel, 'id' | 'title' | 'slug' | 'created' | 'modified' | 'tags'> {
627
+ category: Pick<CategoryModel, 'name' | 'slug'> | null;
628
+ }
629
+ interface LatestNoteItem extends Pick<NoteModel, 'id' | 'title' | 'nid' | 'created' | 'modified' | 'mood' | 'weather' | 'bookmark'> {}
630
+ interface LatestData {
631
+ posts?: LatestPostItem[];
632
+ notes?: LatestNoteItem[];
633
+ }
634
+ type LatestCombinedItem = (LatestPostItem & {
635
+ type: 'post';
636
+ }) | (LatestNoteItem & {
637
+ type: 'note';
638
+ });
623
639
  interface AggregateStat {
624
640
  allComments: number;
625
641
  categories: number;
@@ -1048,6 +1064,16 @@ declare class AggregateController<ResponseWrapper> implements IController {
1048
1064
  data: TimelineData;
1049
1065
  };
1050
1066
  }>;
1067
+ getLatest(options: {
1068
+ limit?: number;
1069
+ types?: TimelineType[];
1070
+ combined: true;
1071
+ }): RequestProxyResult<LatestCombinedItem[], ResponseWrapper>;
1072
+ getLatest(options?: {
1073
+ limit?: number;
1074
+ types?: TimelineType[];
1075
+ combined?: false;
1076
+ }): RequestProxyResult<LatestData, ResponseWrapper>;
1051
1077
  /**
1052
1078
  * 获取聚合数据统计
1053
1079
  */
@@ -1451,7 +1477,7 @@ declare class CategoryController<ResponseWrapper> implements IController {
1451
1477
  name: string;
1452
1478
  created: string;
1453
1479
  id: string;
1454
- children: Pick<PostModel, "id" | "title" | "slug" | "modified" | "created">[];
1480
+ children: Pick<PostModel, "id" | "title" | "modified" | "created" | "slug">[];
1455
1481
  } : T_1 : never : never;
1456
1482
  } : ResponseWrapper;
1457
1483
  $request: {
@@ -1503,7 +1529,7 @@ declare class CategoryController<ResponseWrapper> implements IController {
1503
1529
  };
1504
1530
  }) ? T_1 extends unknown ? {
1505
1531
  tag: string;
1506
- data: Pick<PostModel, "category" | "id" | "title" | "slug" | "created">[];
1532
+ data: Pick<PostModel, "category" | "id" | "title" | "created" | "slug">[];
1507
1533
  } : T_1 : never : never;
1508
1534
  } : ResponseWrapper;
1509
1535
  $request: {
@@ -1695,6 +1721,7 @@ type NoteByNidOptions = {
1695
1721
  lang?: string;
1696
1722
  prefer?: 'lexical';
1697
1723
  };
1724
+ type NoteBySlugDateOptions = NoteByNidOptions;
1698
1725
  type NoteMiddleListOptions = {
1699
1726
  lang?: string;
1700
1727
  };
@@ -1742,6 +1769,7 @@ declare class NoteController<ResponseWrapper> implements IController {
1742
1769
  * @param options 可选参数:password, single, lang
1743
1770
  */
1744
1771
  getNoteByNid(nid: number, options?: NoteByNidOptions): RequestProxyResult<NoteWrappedWithLikedAndTranslationPayload, ResponseWrapper>;
1772
+ getNoteBySlugDate(year: number, month: number, day: number, slug: string, options?: NoteBySlugDateOptions): RequestProxyResult<NoteWrappedWithLikedAndTranslationPayload, ResponseWrapper>;
1745
1773
  /**
1746
1774
  * 日记列表分页
1747
1775
  */
@@ -2306,11 +2334,11 @@ declare class SearchController<ResponseWrapper> implements IController {
2306
2334
  * @param options
2307
2335
  * @returns
2308
2336
  */
2309
- searchByAlgolia(keyword: string, options?: SearchOption): RequestProxyResult<RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "slug" | "modified" | "created"> & {
2337
+ searchByAlgolia(keyword: string, options?: SearchOption): RequestProxyResult<RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "modified" | "created" | "slug"> & {
2310
2338
  type: "post";
2311
2339
  }) | (Pick<NoteModel, "id" | "title" | "modified" | "created" | "nid"> & {
2312
2340
  type: "note";
2313
- }) | (Pick<PageModel, "id" | "title" | "slug" | "modified" | "created"> & {
2341
+ }) | (Pick<PageModel, "id" | "title" | "modified" | "created" | "slug"> & {
2314
2342
  type: "page";
2315
2343
  })> & {
2316
2344
  /**
@@ -2319,11 +2347,11 @@ declare class SearchController<ResponseWrapper> implements IController {
2319
2347
  raw?: any;
2320
2348
  }, ResponseWrapper>, ResponseWrapper, ResponseWrapper extends unknown ? {
2321
2349
  [key: string]: any;
2322
- data: RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "slug" | "modified" | "created"> & {
2350
+ data: RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "modified" | "created" | "slug"> & {
2323
2351
  type: "post";
2324
2352
  }) | (Pick<NoteModel, "id" | "title" | "modified" | "created" | "nid"> & {
2325
2353
  type: "note";
2326
- }) | (Pick<PageModel, "id" | "title" | "slug" | "modified" | "created"> & {
2354
+ }) | (Pick<PageModel, "id" | "title" | "modified" | "created" | "slug"> & {
2327
2355
  type: "page";
2328
2356
  })> & {
2329
2357
  /**
@@ -2332,11 +2360,11 @@ declare class SearchController<ResponseWrapper> implements IController {
2332
2360
  raw?: any;
2333
2361
  }, ResponseWrapper>;
2334
2362
  } : ResponseWrapper extends {
2335
- data: RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "slug" | "modified" | "created"> & {
2363
+ data: RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "modified" | "created" | "slug"> & {
2336
2364
  type: "post";
2337
2365
  }) | (Pick<NoteModel, "id" | "title" | "modified" | "created" | "nid"> & {
2338
2366
  type: "note";
2339
- }) | (Pick<PageModel, "id" | "title" | "slug" | "modified" | "created"> & {
2367
+ }) | (Pick<PageModel, "id" | "title" | "modified" | "created" | "slug"> & {
2340
2368
  type: "page";
2341
2369
  })> & {
2342
2370
  /**
@@ -2345,11 +2373,11 @@ declare class SearchController<ResponseWrapper> implements IController {
2345
2373
  raw?: any;
2346
2374
  }, ResponseWrapper>;
2347
2375
  } ? ResponseWrapper : Omit<ResponseWrapper, "data"> & {
2348
- data: RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "slug" | "modified" | "created"> & {
2376
+ data: RequestProxyResult<PaginateResult<(Pick<PostModel, "category" | "id" | "title" | "modified" | "created" | "slug"> & {
2349
2377
  type: "post";
2350
2378
  }) | (Pick<NoteModel, "id" | "title" | "modified" | "created" | "nid"> & {
2351
2379
  type: "note";
2352
- }) | (Pick<PageModel, "id" | "title" | "slug" | "modified" | "created"> & {
2380
+ }) | (Pick<PageModel, "id" | "title" | "modified" | "created" | "slug"> & {
2353
2381
  type: "page";
2354
2382
  })> & {
2355
2383
  /**
@@ -2498,4 +2526,4 @@ declare const allControllerNames: readonly ["ai", "ack", "activity", "aggregate"
2498
2526
  */
2499
2527
  declare const camelcaseKeys: <T = any>(obj: any) => T;
2500
2528
  //#endregion
2501
- export { AIController, AIDeepReadingModel, AISummaryModel, AISummaryStreamEvent, AITranslationModel, AITranslationStreamEvent, AckController, ActivityController, ActivityPresence, AdminExtraModel, AggregateAIConfig, AggregateController, AggregateRoot, AggregateRootWithTheme, AggregateStat, AggregateTop, AggregateTopNote, AggregateTopPost, AlgoliaSearchOptionsModel, AuthUser, BackupOptionsModel, BaiduSearchOptionsModel, BaseCommentIndexModel, BaseModel, BetterAuthSession, BetterAuthSessionResult, BetterAuthSignInResult, BetterAuthUser, BetterAuthUserRole, BingSearchOptionsModel, CategoryController, CategoryEntries, CategoryModel, CategoryType, CategoryWithChildrenModel, CheckLoggedResult, CollectionRefTypes, CommentController, CommentDto, CommentModel, CommentOptionsModel, CommentRef, CommentState, Coordinate, Count, EnumPageType, type HTTPClient, IConfig, IConfigKeys, type IRequestAdapter, Image, LastYearPublication, LinkController, LinkModel, LinkState, LinkType, MailOptionsModel, ModelWithLiked, ModelWithTranslation, NoteController, type NoteMiddleListOptions, NoteModel, type NoteTimelineItem, type NoteTopicListItem, type NoteTopicListOptions, NoteWrappedPayload, NoteWrappedWithLikedAndTranslationPayload, NoteWrappedWithLikedPayload, OwnerAllowLoginResult, OwnerSessionResult, PageController, PageModel, Pager, PaginateResult, PostController, type PostListItem, type PostListOptions, PostModel, ProjectController, ProjectModel, ReaderModel, RecentActivities, RecentComment, RecentLike, RecentNote, RecentPost, RecentRecent, RecentlyAttitudeEnum, RecentlyAttitudeResultEnum, RecentlyController, RecentlyModel, RecentlyRefType, RecentlyRefTypes, RequestError, RoomOmittedNote, RoomOmittedPage, RoomOmittedPost, RoomsData, SayController, SayModel, SearchController, SeoOptionModel, ServerlessController, SnippetController, SnippetModel, SnippetType, SubscribeAllBit, SubscribeController, SubscribeNoteCreateBit, SubscribePostCreateBit, SubscribeRecentCreateBit, SubscribeSayCreateBit, SubscribeType, SubscribeTypeToBitMap, TLogin, TagModel, TextBaseModel, ThirdPartyServiceIntegrationModel, TimelineData, TimelineType, TopicController, TopicModel, TranslationMeta, Url, UrlOptionModel, UserController, UserModel, allControllerNames, allControllers, createClient, createClient as default, camelcaseKeys as simpleCamelcaseKeys };
2529
+ export { AIController, AIDeepReadingModel, AISummaryModel, AISummaryStreamEvent, AITranslationModel, AITranslationStreamEvent, AckController, ActivityController, ActivityPresence, AdminExtraModel, AggregateAIConfig, AggregateController, AggregateRoot, AggregateRootWithTheme, AggregateStat, AggregateTop, AggregateTopNote, AggregateTopPost, AlgoliaSearchOptionsModel, AuthUser, BackupOptionsModel, BaiduSearchOptionsModel, BaseCommentIndexModel, BaseModel, BetterAuthSession, BetterAuthSessionResult, BetterAuthSignInResult, BetterAuthUser, BetterAuthUserRole, BingSearchOptionsModel, CategoryController, CategoryEntries, CategoryModel, CategoryType, CategoryWithChildrenModel, CheckLoggedResult, CollectionRefTypes, CommentController, CommentDto, CommentModel, CommentOptionsModel, CommentRef, CommentState, Coordinate, Count, EnumPageType, type HTTPClient, IConfig, IConfigKeys, type IRequestAdapter, Image, LastYearPublication, LatestCombinedItem, LatestData, LatestNoteItem, LatestPostItem, LinkController, LinkModel, LinkState, LinkType, MailOptionsModel, ModelWithLiked, ModelWithTranslation, NoteController, type NoteMiddleListOptions, NoteModel, type NoteTimelineItem, type NoteTopicListItem, type NoteTopicListOptions, NoteWrappedPayload, NoteWrappedWithLikedAndTranslationPayload, NoteWrappedWithLikedPayload, OwnerAllowLoginResult, OwnerSessionResult, PageController, PageModel, Pager, PaginateResult, PostController, type PostListItem, type PostListOptions, PostModel, ProjectController, ProjectModel, ReaderModel, RecentActivities, RecentComment, RecentLike, RecentNote, RecentPost, RecentRecent, RecentlyAttitudeEnum, RecentlyAttitudeResultEnum, RecentlyController, RecentlyModel, RecentlyRefType, RecentlyRefTypes, RequestError, RoomOmittedNote, RoomOmittedPage, RoomOmittedPost, RoomsData, SayController, SayModel, SearchController, SeoOptionModel, ServerlessController, SnippetController, SnippetModel, SnippetType, SubscribeAllBit, SubscribeController, SubscribeNoteCreateBit, SubscribePostCreateBit, SubscribeRecentCreateBit, SubscribeSayCreateBit, SubscribeType, SubscribeTypeToBitMap, TLogin, TagModel, TextBaseModel, TextBaseModelLexical, TextBaseModelMarkdown, ThirdPartyServiceIntegrationModel, TimelineData, TimelineType, TopicController, TopicModel, TranslationMeta, Url, UrlOptionModel, UserController, UserModel, allControllerNames, allControllers, createClient, createClient as default, camelcaseKeys as simpleCamelcaseKeys };
package/dist/index.mjs CHANGED
@@ -199,6 +199,14 @@ var AggregateController = class {
199
199
  year
200
200
  } });
201
201
  }
202
+ getLatest(options) {
203
+ const { limit, types, combined } = options || {};
204
+ return this.proxy.latest.get({ params: {
205
+ limit,
206
+ types: types?.join(","),
207
+ combined
208
+ } });
209
+ }
202
210
  /**
203
211
  * 获取聚合数据统计
204
212
  */
@@ -515,6 +523,15 @@ var NoteController = class {
515
523
  prefer
516
524
  } });
517
525
  }
526
+ getNoteBySlugDate(year, month, day, slug, options) {
527
+ const { password, single, lang, prefer } = options || {};
528
+ return this.proxy(year.toString())(month.toString())(day.toString())(slug).get({ params: {
529
+ password,
530
+ single: single ? "1" : void 0,
531
+ lang,
532
+ prefer
533
+ } });
534
+ }
518
535
  /**
519
536
  * 日记列表分页
520
537
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mx-space/api-client",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
4
4
  "description": "A api client for mx-space server@next",
5
5
  "type": "module",
6
6
  "engines": {
@@ -56,10 +56,10 @@
56
56
  "axios": "^1.13.3",
57
57
  "camelcase-keys": "^10.0.2",
58
58
  "cors": "2.8.6",
59
- "es-toolkit": "1.44.0",
59
+ "es-toolkit": "1.45.0",
60
60
  "express": "4.21.2",
61
61
  "form-data": "4.0.5",
62
- "tsdown": "0.20.1",
62
+ "tsdown": "0.21.0-beta.2",
63
63
  "umi-request": "1.4.0",
64
64
  "vite": "^7.3.1",
65
65
  "vitest": "4.0.18"
package/readme.md CHANGED
@@ -1,133 +1,74 @@
1
- # MApi Client
1
+ # @mx-space/api-client
2
2
 
3
- 这是一个适用于 MServer v3 JS SDK,封装了常用接口请求方法以及返回类型的声明,以快速开发前端应用。
3
+ A framework-agnostic TypeScript/JavaScript SDK for the MX Space server (MServer v3). It wraps common API endpoints with typed request methods and response types for fast frontend and server-side integration.
4
4
 
5
- ## 版本兼容性
5
+ ---
6
6
 
7
- | api-client 版本 | 支持的 Server 版本 | 说明 |
8
- | --------------- | ------------------ | ----------------------------- |
9
- | v2.x | >= 10 | 基于 Better Auth 的新认证系统 |
10
- | v1.x | <= 9 | 旧版认证系统 |
7
+ ## Table of Contents
11
8
 
12
- **注意**: v2 版本与 v1 版本存在 Breaking Changes,升级时请参考下方迁移指南。
9
+ - [Requirements](#requirements)
10
+ - [Installation](#installation)
11
+ - [Quick Start](#quick-start)
12
+ - [Architecture](#architecture)
13
+ - [Adapters](#adapters)
14
+ - [Controllers](#controllers)
15
+ - [Client Options](#client-options)
16
+ - [Proxy API](#proxy-api)
17
+ - [Version Compatibility & Migration](#version-compatibility--migration)
18
+ - [Development](#development)
19
+ - [License](#license)
13
20
 
14
- ## 迁移到 v2
21
+ ---
15
22
 
16
- ### Breaking Changes
23
+ ## Requirements
17
24
 
18
- #### 1. 控制器重命名
25
+ - **Node.js** ≥ 22 (see `engines` in `package.json`)
26
+ - **MX Space server** v10+ for api-client v2.x (Better Auth); v9 or below use api-client v1.x
19
27
 
20
- `user` 控制器已重命名为 `owner`,`master` 别名已被移除:
28
+ ---
21
29
 
22
- ```diff
23
- - client.user.getMasterInfo()
24
- + client.owner.getOwnerInfo()
25
-
26
- - client.master.getMasterInfo()
27
- + client.owner.getOwnerInfo()
28
- ```
30
+ ## Installation
29
31
 
30
- #### 2. 登录接口变更
32
+ From the monorepo root (recommended):
31
33
 
32
- 登录接口从 `POST /master/login` 变更为 `POST /auth/sign-in`:
33
-
34
- ```diff
35
- - client.user.login(username, password)
36
- + client.owner.login(username, password, { rememberMe: boolean })
34
+ ```bash
35
+ pnpm add @mx-space/api-client
37
36
  ```
38
37
 
39
- v2 版本的 `login` 方法返回的数据结构也发生了变化,现在返回 `{ token, user }` 格式。
40
-
41
- #### 3. 新增 Better Auth 相关接口
42
-
43
- v2 版本新增了 Better Auth 认证相关的接口:
38
+ Or with npm:
44
39
 
45
- ```ts
46
- // 获取当前会话
47
- client.owner.getSession()
48
-
49
- // 获取 Better Auth 原生会话
50
- client.owner.getAuthSession()
51
-
52
- // 登出
53
- client.owner.logout()
54
-
55
- // 获取支持的登录方式
56
- client.owner.getAllowLoginMethods()
57
-
58
- // 获取 OAuth 提供商列表
59
- client.owner.getProviders()
60
-
61
- // 列出所有会话
62
- client.owner.listSessions()
63
-
64
- // 撤销指定会话
65
- client.owner.revokeSession(token)
66
-
67
- // 撤销所有会话
68
- client.owner.revokeSessions()
69
-
70
- // 撤销其他会话
71
- client.owner.revokeOtherSessions()
40
+ ```bash
41
+ npm install @mx-space/api-client
72
42
  ```
73
43
 
74
- ## 迁移到 v1
75
-
76
- 不再提供 camelcase-keys 的 re-export,此库不再依赖 camelcase-keys 库,如有需要可自行安装。
44
+ The package is **framework-agnostic** and does not bundle a specific HTTP client. You must provide an adapter (e.g. Axios or fetch). Install the HTTP library you use:
77
45
 
78
- ```diff
79
- - import { camelcaseKeysDeep, camelcaseKeys } from '@mx-space/api-client'
80
- + import { simpleCamelcaseKeys as camelcaseKeysDeep } from '@mx-space/api-client'
46
+ ```bash
47
+ pnpm add axios
48
+ # or use the built-in fetch adapter (no extra install)
81
49
  ```
82
50
 
83
- ## 如何使用
51
+ ---
84
52
 
85
- SDK 框架无关,不捆绑任何一个网络请求库,只需要提供适配器。你需要手动传入符合接口标准的适配器。
53
+ ## Quick Start
86
54
 
87
- 此项目提供 `axios` `umi-request` 两个适配器。
88
-
89
- `axios` 为例。
55
+ 1. **Create a client** with an endpoint and an adapter.
56
+ 2. **Inject controllers** you need (tree-shakeable).
57
+ 3. **Call methods** on the client (e.g. `client.post`, `client.note`).
90
58
 
91
59
  ```ts
92
60
  import {
93
- AggregateController,
94
- allControllers, // ...
95
- CategoryController,
96
61
  createClient,
97
- NoteController,
98
62
  PostController,
63
+ NoteController,
64
+ AggregateController,
65
+ CategoryController,
99
66
  } from '@mx-space/api-client'
100
67
  import { axiosAdaptor } from '@mx-space/api-client/adaptors/axios'
101
68
 
102
- const endpoint = 'https://api.innei.dev/v2'
69
+ const endpoint = 'https://api.example.com/v2'
103
70
  const client = createClient(axiosAdaptor)(endpoint)
104
71
 
105
- // `default` is AxiosInstance
106
- // you can do anything else on this
107
- // interceptor or re-configure
108
- const $axios = axiosAdaptor.default
109
- // re-config (optional)
110
- $axios.defaults.timeout = 10000
111
- // set interceptors (optional)
112
- $axios.interceptors.request.use(
113
- (config) => {
114
- const token = getToken()
115
- if (token) {
116
- config.headers!.Authorization = `bearer ${getToken()}`
117
- }
118
-
119
- return config
120
- },
121
- (error) => {
122
- if (__DEV__) {
123
- console.log(error.message)
124
- }
125
-
126
- return Promise.reject(error)
127
- },
128
- )
129
-
130
- // inject controller first.
131
72
  client.injectControllers([
132
73
  PostController,
133
74
  NoteController,
@@ -135,40 +76,206 @@ client.injectControllers([
135
76
  CategoryController,
136
77
  ])
137
78
 
138
- // or you can inject allControllers
139
- client.injectControllers(allControllers)
79
+ // Typed API calls
80
+ const posts = await client.post.post.getList(1, 10, { year: 2024 })
81
+ const aggregate = await client.aggregate.getAggregateData()
82
+ ```
140
83
 
141
- // then you can request `post` `note` and `aggregate` controller
84
+ **Optional: set token and interceptors** (example with Axios):
142
85
 
143
- client.post.post.getList(page, 10, { year }).then((data) => {
144
- // do anything
86
+ ```ts
87
+ const $axios = axiosAdaptor.default
88
+ $axios.defaults.timeout = 10000
89
+ $axios.interceptors.request.use((config) => {
90
+ const token = getToken()
91
+ if (token) config.headers!.Authorization = `bearer ${token}`
92
+ return config
145
93
  })
146
94
  ```
147
95
 
148
- **为什么要手动注入控制器**
96
+ ---
97
+
98
+ ## Architecture
99
+
100
+ - **Core**: `HTTPClient` in `core/client.ts` — builds a route proxy and delegates HTTP calls to an adapter.
101
+ - **Adapters**: Implement `IRequestAdapter` (get/post/put/patch/delete + optional `default` client). Responses are normalized to `{ data }`; optional `transformResponse` (e.g. camelCase) runs on `data`.
102
+ - **Controllers**: Classes that receive the client and attach methods under a name (e.g. `post`, `note`). Controllers are **injected at runtime** so you only bundle what you use.
103
+ - **Proxy**: `client.proxy` allows arbitrary path chains and HTTP methods for endpoints not modeled by a controller (e.g. `client.note.proxy.something.other('123').info.get()`).
104
+
105
+ **Response shape**: The adapter is expected to return a value with a `data` property. By default, `getDataFromResponse` uses `(res) => res.data`, and `transformResponse` converts keys to camelCase. Each returned object gets attached `$raw` (adapter response), `$request` (url, method, options), and `$serialized` (transformed data).
106
+
107
+ ---
108
+
109
+ ## Adapters
149
110
 
150
- 按需加载,可以减少打包体积 (Tree Shake)
111
+ Official adapters live under `@mx-space/api-client/adaptors/`:
151
112
 
152
- **为什么不依赖请求库**
113
+ | Adapter | Import path | Notes |
114
+ |----------------|------------------------------------------|--------------------------|
115
+ | **Axios** | `@mx-space/api-client/adaptors/axios` | Exposes `axiosAdaptor.default` (AxiosInstance). |
116
+ | **umi-request**| `@mx-space/api-client/adaptors/umi-request` | For umi-request users. |
117
+ | **Fetch** | `@mx-space/api-client/adaptors/fetch` | Uses global `fetch`; no extra dependency. |
153
118
 
154
- 可以防止项目中出现两个请求库,减少打包体积
119
+ **Custom adapter**: Implement `IRequestAdapter` from `@mx-space/api-client` (methods: `get`, `post`, `put`, `patch`, `delete`; optional `default`). See `src/adaptors/axios.ts` and `src/adaptors/umi-request.ts` for reference.
155
120
 
156
- **如果不使用 axios,应该如何编写适配器**
121
+ ---
157
122
 
158
- 参考 `src/adaptors/axios.ts` 和 `src/adaptors/umi-request.ts`
123
+ ## Controllers
159
124
 
160
- **如何使用 proxy 来访问 sdk 内未包含的请求**
125
+ Inject one or more controllers so the client exposes them (e.g. `client.post`, `client.note`). Use `allControllers` to inject everything, or list only what you need for smaller bundles.
161
126
 
162
- 如请求 `GET /notes/something/other/123456/info`,可以使用
127
+ | Controller | Client name | Purpose (high level) |
128
+ |-------------|---------------|-----------------------------|
129
+ | PostController | `post` | Blog posts |
130
+ | NoteController | `note` | Notes / private posts |
131
+ | PageController | `page` | Pages |
132
+ | CategoryController | `category` | Categories |
133
+ | AggregateController | `aggregate` | Site aggregate data |
134
+ | CommentController | `comment` | Comments |
135
+ | UserController (owner) | `owner` | Auth, session, login, OAuth |
136
+ | SayController | `say` | Says / short notes |
137
+ | LinkController | `link` | Links |
138
+ | SnippetController| `snippet` | Snippets |
139
+ | ProjectController | `project` | Projects |
140
+ | TopicController | `topic` | Topics |
141
+ | RecentlyController | `recently` | Recently items |
142
+ | SearchController | `search` | Search |
143
+ | ActivityController| `activity`| Activity |
144
+ | AIController | `ai` | AI-related endpoints |
145
+ | SubscribeController | `subscribe` | Subscriptions |
146
+ | ServerlessController | `serverless` | Serverless functions |
147
+ | AckController | `ack` | Ack |
148
+
149
+ **Example — inject all controllers:**
163
150
 
164
151
  ```ts
165
- client.note.proxy.something.other('123456').info.get()
152
+ import { createClient, allControllers } from '@mx-space/api-client'
153
+ import { axiosAdaptor } from '@mx-space/api-client/adaptors/axios'
154
+
155
+ const client = createClient(axiosAdaptor)('https://api.example.com/v2')
156
+ client.injectControllers(allControllers)
166
157
  ```
167
158
 
168
- **从 proxy 获取请求地址但不发出**
159
+ **Why inject manually?** To keep bundle size small (tree-shaking) and to avoid pulling in a specific HTTP library by default.
160
+
161
+ ---
162
+
163
+ ## Client Options
164
+
165
+ `createClient(adapter)(endpoint, options)` accepts optional second argument:
166
+
167
+ | Option | Description |
168
+ |----------------------------|-------------|
169
+ | `controllers` | Array of controller classes to inject immediately. |
170
+ | `transformResponse` | `(data) => transformed`. Default: camelCase keys. |
171
+ | `getDataFromResponse` | `(response) => data`. Default: `(res) => res.data`. |
172
+ | `getCodeMessageFromException` | `(error) => { message?, code? }` for custom error parsing. |
173
+ | `customThrowResponseError` | `(error) => Error` to throw a custom error type. |
174
+
175
+ ---
176
+
177
+ ## Proxy API
178
+
179
+ For paths not covered by a controller, use the **proxy** to build URLs and perform requests:
169
180
 
170
181
  ```ts
171
- client.note.proxy.something.other('123456').info.toString() // /notes/something/other/123456/info
182
+ // GET /notes/something/other/123456/info
183
+ const data = await client.note.proxy.something.other('123456').info.get()
184
+
185
+ // Get path only (no request)
186
+ client.note.proxy.something.other('123456').info.toString()
187
+ // => '/notes/something/other/123456/info'
188
+
189
+ // Full URL (with base endpoint)
190
+ client.note.proxy.something.other('123456').info.toString(true)
191
+ // => 'https://api.example.com/v2/notes/something/other/123456/info'
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Version Compatibility & Migration
197
+
198
+ ### Compatibility
199
+
200
+ | api-client version | Server version | Notes |
201
+ |--------------------|----------------|-------|
202
+ | v2.x | ≥ 10 | Better Auth; owner API; new auth endpoints. |
203
+ | v1.x | ≤ 9 | Legacy auth. |
204
+
205
+ v2 introduces breaking changes; see migration below.
206
+
207
+ ### Migrating to v2
208
+
209
+ **1. Controller renames**
210
+
211
+ - `user` / `master` → `owner`. Use `client.owner` for auth and owner info.
212
+
213
+ ```diff
214
+ - client.user.getMasterInfo()
215
+ - client.master.getMasterInfo()
216
+ + client.owner.getOwnerInfo()
217
+ ```
218
+
219
+ **2. Login**
220
+
221
+ - Endpoint: `POST /master/login` → `POST /auth/sign-in`.
222
+ - v2 `login` returns `{ token, user }`.
223
+
224
+ ```diff
225
+ - client.user.login(username, password)
226
+ + client.owner.login(username, password, { rememberMe: boolean })
227
+ ```
228
+
229
+ **3. New auth-related APIs (v2)**
230
+
231
+ - `client.owner.getSession()`
232
+ - `client.owner.getAuthSession()`
233
+ - `client.owner.logout()`
234
+ - `client.owner.getAllowLoginMethods()`
235
+ - `client.owner.getProviders()`
236
+ - `client.owner.listSessions()`
237
+ - `client.owner.revokeSession(token)` / `revokeSessions()` / `revokeOtherSessions()`
238
+
239
+ ### Migrating from v2 to v1 (downgrade)
172
240
 
173
- client.note.proxy.something.other('123456').info.toString(true) // http://localhost:2333/notes/something/other/123456/info
241
+ - No re-export of `camelcase-keys`. Use the built-in helper or install yourself:
242
+
243
+ ```diff
244
+ - import { camelcaseKeysDeep, camelcaseKeys } from '@mx-space/api-client'
245
+ + import { simpleCamelcaseKeys as camelcaseKeysDeep } from '@mx-space/api-client'
174
246
  ```
247
+
248
+ ---
249
+
250
+ ## Development
251
+
252
+ **From repo root:**
253
+
254
+ ```bash
255
+ pnpm i
256
+ ```
257
+
258
+ **From `packages/api-client`:**
259
+
260
+ - **Build**: `pnpm run package` or `pnpm run build` (cleans `dist`, runs `tsdown`).
261
+ - **Test**: `pnpm test` (Vitest).
262
+ - **Dev (watch tests)**: `pnpm run dev`.
263
+
264
+ **Project layout (high level):**
265
+
266
+ - `core/` — client, request attachment, error type.
267
+ - `controllers/` — one class per API area; names listed in `controllers/index.ts`.
268
+ - `adaptors/` — axios, umi-request, fetch.
269
+ - `models/`, `dtos/`, `interfaces/` — types and DTOs for requests/responses.
270
+ - `utils/` — path resolution, camelCase, auto-bind.
271
+
272
+ **Exports:**
273
+
274
+ - Main: `createClient`, `RequestError`, controllers, models, DTOs, `simpleCamelcaseKeys`, `HTTPClient` type, `IRequestAdapter` type.
275
+ - Adapters: `@mx-space/api-client/adaptors/axios`, `/adaptors/umi-request`, `/adaptors/fetch`.
276
+
277
+ ---
278
+
279
+ ## License
280
+
281
+ MIT.