@zlooks.cn/blog-server 1.0.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.
Files changed (265) hide show
  1. package/dist/blog/blog-application.d.ts +153 -0
  2. package/dist/blog/blog-application.d.ts.map +1 -0
  3. package/dist/blog/blog-application.js +115 -0
  4. package/dist/blog/blog-application.js.map +1 -0
  5. package/dist/blog/comment-client-metadata.d.ts +19 -0
  6. package/dist/blog/comment-client-metadata.d.ts.map +1 -0
  7. package/dist/blog/comment-client-metadata.js +78 -0
  8. package/dist/blog/comment-client-metadata.js.map +1 -0
  9. package/dist/blog/errors.d.ts +12 -0
  10. package/dist/blog/errors.d.ts.map +1 -0
  11. package/dist/blog/errors.js +21 -0
  12. package/dist/blog/errors.js.map +1 -0
  13. package/dist/blog/micro-user-directory.d.ts +11 -0
  14. package/dist/blog/micro-user-directory.d.ts.map +1 -0
  15. package/dist/blog/micro-user-directory.js +18 -0
  16. package/dist/blog/micro-user-directory.js.map +1 -0
  17. package/dist/blog/post-content-audit.d.ts +34 -0
  18. package/dist/blog/post-content-audit.d.ts.map +1 -0
  19. package/dist/blog/post-content-audit.js +190 -0
  20. package/dist/blog/post-content-audit.js.map +1 -0
  21. package/dist/blog/post-view-cache.d.ts +15 -0
  22. package/dist/blog/post-view-cache.d.ts.map +1 -0
  23. package/dist/blog/post-view-cache.js +23 -0
  24. package/dist/blog/post-view-cache.js.map +1 -0
  25. package/dist/blog/public-blog-micro.d.ts +291 -0
  26. package/dist/blog/public-blog-micro.d.ts.map +1 -0
  27. package/dist/blog/public-blog-micro.js +71 -0
  28. package/dist/blog/public-blog-micro.js.map +1 -0
  29. package/dist/blog/public-blog-service.d.ts +104 -0
  30. package/dist/blog/public-blog-service.d.ts.map +1 -0
  31. package/dist/blog/public-blog-service.js +341 -0
  32. package/dist/blog/public-blog-service.js.map +1 -0
  33. package/dist/browser-api/dispatch-stream.d.ts +5 -0
  34. package/dist/browser-api/dispatch-stream.d.ts.map +1 -0
  35. package/dist/browser-api/dispatch-stream.js +4 -0
  36. package/dist/browser-api/dispatch-stream.js.map +1 -0
  37. package/dist/browser-api/dispatcher.d.ts +15 -0
  38. package/dist/browser-api/dispatcher.d.ts.map +1 -0
  39. package/dist/browser-api/dispatcher.js +145 -0
  40. package/dist/browser-api/dispatcher.js.map +1 -0
  41. package/dist/browser-api/provider-publisher.d.ts +24 -0
  42. package/dist/browser-api/provider-publisher.d.ts.map +1 -0
  43. package/dist/browser-api/provider-publisher.js +107 -0
  44. package/dist/browser-api/provider-publisher.js.map +1 -0
  45. package/dist/command/index.d.ts +3 -0
  46. package/dist/command/index.d.ts.map +1 -0
  47. package/dist/command/index.js +24 -0
  48. package/dist/command/index.js.map +1 -0
  49. package/dist/config/schema.d.ts +25 -0
  50. package/dist/config/schema.d.ts.map +1 -0
  51. package/dist/config/schema.js +19 -0
  52. package/dist/config/schema.js.map +1 -0
  53. package/dist/contracts/identity.d.ts +2 -0
  54. package/dist/contracts/identity.d.ts.map +1 -0
  55. package/dist/contracts/identity.js +2 -0
  56. package/dist/contracts/identity.js.map +1 -0
  57. package/dist/contracts/mcp.d.ts +69 -0
  58. package/dist/contracts/mcp.d.ts.map +1 -0
  59. package/dist/contracts/mcp.js +41 -0
  60. package/dist/contracts/mcp.js.map +1 -0
  61. package/dist/contracts/public-api.d.ts +3 -0
  62. package/dist/contracts/public-api.d.ts.map +1 -0
  63. package/dist/contracts/public-api.js +2 -0
  64. package/dist/contracts/public-api.js.map +1 -0
  65. package/dist/mcp/blog-prompts.d.ts +135 -0
  66. package/dist/mcp/blog-prompts.d.ts.map +1 -0
  67. package/dist/mcp/blog-prompts.js +107 -0
  68. package/dist/mcp/blog-prompts.js.map +1 -0
  69. package/dist/mcp/blog-provider.d.ts +4 -0
  70. package/dist/mcp/blog-provider.d.ts.map +1 -0
  71. package/dist/mcp/blog-provider.js +27 -0
  72. package/dist/mcp/blog-provider.js.map +1 -0
  73. package/dist/mcp/blog-theme-authoring-prompt.d.ts +19 -0
  74. package/dist/mcp/blog-theme-authoring-prompt.d.ts.map +1 -0
  75. package/dist/mcp/blog-theme-authoring-prompt.js +171 -0
  76. package/dist/mcp/blog-theme-authoring-prompt.js.map +1 -0
  77. package/dist/mcp/category-tools.d.ts +45 -0
  78. package/dist/mcp/category-tools.d.ts.map +1 -0
  79. package/dist/mcp/category-tools.js +14 -0
  80. package/dist/mcp/category-tools.js.map +1 -0
  81. package/dist/mcp/comment-tools.d.ts +44 -0
  82. package/dist/mcp/comment-tools.d.ts.map +1 -0
  83. package/dist/mcp/comment-tools.js +15 -0
  84. package/dist/mcp/comment-tools.js.map +1 -0
  85. package/dist/mcp/friend-link-tools.d.ts +63 -0
  86. package/dist/mcp/friend-link-tools.d.ts.map +1 -0
  87. package/dist/mcp/friend-link-tools.js +16 -0
  88. package/dist/mcp/friend-link-tools.js.map +1 -0
  89. package/dist/mcp/page-tools.d.ts +67 -0
  90. package/dist/mcp/page-tools.d.ts.map +1 -0
  91. package/dist/mcp/page-tools.js +36 -0
  92. package/dist/mcp/page-tools.js.map +1 -0
  93. package/dist/mcp/post-tools.d.ts +114 -0
  94. package/dist/mcp/post-tools.d.ts.map +1 -0
  95. package/dist/mcp/post-tools.js +122 -0
  96. package/dist/mcp/post-tools.js.map +1 -0
  97. package/dist/mcp/tag-tools.d.ts +37 -0
  98. package/dist/mcp/tag-tools.d.ts.map +1 -0
  99. package/dist/mcp/tag-tools.js +14 -0
  100. package/dist/mcp/tag-tools.js.map +1 -0
  101. package/dist/mcp/theme-tools.d.ts +16 -0
  102. package/dist/mcp/theme-tools.d.ts.map +1 -0
  103. package/dist/mcp/theme-tools.js +71 -0
  104. package/dist/mcp/theme-tools.js.map +1 -0
  105. package/dist/mcp/tool-descriptions.d.ts +5 -0
  106. package/dist/mcp/tool-descriptions.d.ts.map +1 -0
  107. package/dist/mcp/tool-descriptions.js +51 -0
  108. package/dist/mcp/tool-descriptions.js.map +1 -0
  109. package/dist/mcp/tool-support.d.ts +242 -0
  110. package/dist/mcp/tool-support.d.ts.map +1 -0
  111. package/dist/mcp/tool-support.js +127 -0
  112. package/dist/mcp/tool-support.js.map +1 -0
  113. package/dist/messages/browser/dispatch.msg.d.ts +3 -0
  114. package/dist/messages/browser/dispatch.msg.d.ts.map +1 -0
  115. package/dist/messages/browser/dispatch.msg.js +9 -0
  116. package/dist/messages/browser/dispatch.msg.js.map +1 -0
  117. package/dist/messages/public/categories/list.msg.d.ts +3 -0
  118. package/dist/messages/public/categories/list.msg.d.ts.map +1 -0
  119. package/dist/messages/public/categories/list.msg.js +8 -0
  120. package/dist/messages/public/categories/list.msg.js.map +1 -0
  121. package/dist/messages/public/comments/list.msg.d.ts +3 -0
  122. package/dist/messages/public/comments/list.msg.d.ts.map +1 -0
  123. package/dist/messages/public/comments/list.msg.js +8 -0
  124. package/dist/messages/public/comments/list.msg.js.map +1 -0
  125. package/dist/messages/public/comments/recent.msg.d.ts +3 -0
  126. package/dist/messages/public/comments/recent.msg.d.ts.map +1 -0
  127. package/dist/messages/public/comments/recent.msg.js +8 -0
  128. package/dist/messages/public/comments/recent.msg.js.map +1 -0
  129. package/dist/messages/public/friend-links/list.msg.d.ts +3 -0
  130. package/dist/messages/public/friend-links/list.msg.d.ts.map +1 -0
  131. package/dist/messages/public/friend-links/list.msg.js +8 -0
  132. package/dist/messages/public/friend-links/list.msg.js.map +1 -0
  133. package/dist/messages/public/pages/list.msg.d.ts +3 -0
  134. package/dist/messages/public/pages/list.msg.d.ts.map +1 -0
  135. package/dist/messages/public/pages/list.msg.js +8 -0
  136. package/dist/messages/public/pages/list.msg.js.map +1 -0
  137. package/dist/messages/public/pages/read.msg.d.ts +3 -0
  138. package/dist/messages/public/pages/read.msg.d.ts.map +1 -0
  139. package/dist/messages/public/pages/read.msg.js +8 -0
  140. package/dist/messages/public/pages/read.msg.js.map +1 -0
  141. package/dist/messages/public/posts/archive.msg.d.ts +3 -0
  142. package/dist/messages/public/posts/archive.msg.d.ts.map +1 -0
  143. package/dist/messages/public/posts/archive.msg.js +8 -0
  144. package/dist/messages/public/posts/archive.msg.js.map +1 -0
  145. package/dist/messages/public/posts/connections.msg.d.ts +3 -0
  146. package/dist/messages/public/posts/connections.msg.d.ts.map +1 -0
  147. package/dist/messages/public/posts/connections.msg.js +8 -0
  148. package/dist/messages/public/posts/connections.msg.js.map +1 -0
  149. package/dist/messages/public/posts/list.msg.d.ts +3 -0
  150. package/dist/messages/public/posts/list.msg.d.ts.map +1 -0
  151. package/dist/messages/public/posts/list.msg.js +8 -0
  152. package/dist/messages/public/posts/list.msg.js.map +1 -0
  153. package/dist/messages/public/posts/open.msg.d.ts +3 -0
  154. package/dist/messages/public/posts/open.msg.d.ts.map +1 -0
  155. package/dist/messages/public/posts/open.msg.js +8 -0
  156. package/dist/messages/public/posts/open.msg.js.map +1 -0
  157. package/dist/messages/public/posts/read.msg.d.ts +3 -0
  158. package/dist/messages/public/posts/read.msg.d.ts.map +1 -0
  159. package/dist/messages/public/posts/read.msg.js +8 -0
  160. package/dist/messages/public/posts/read.msg.js.map +1 -0
  161. package/dist/messages/public/tags/list.msg.d.ts +3 -0
  162. package/dist/messages/public/tags/list.msg.d.ts.map +1 -0
  163. package/dist/messages/public/tags/list.msg.js +8 -0
  164. package/dist/messages/public/tags/list.msg.js.map +1 -0
  165. package/dist/migrations/index.d.ts +3 -0
  166. package/dist/migrations/index.d.ts.map +1 -0
  167. package/dist/migrations/index.js +2 -0
  168. package/dist/migrations/index.js.map +1 -0
  169. package/dist/persistence/category-store.d.ts +23 -0
  170. package/dist/persistence/category-store.d.ts.map +1 -0
  171. package/dist/persistence/category-store.js +86 -0
  172. package/dist/persistence/category-store.js.map +1 -0
  173. package/dist/persistence/comment-store.d.ts +41 -0
  174. package/dist/persistence/comment-store.d.ts.map +1 -0
  175. package/dist/persistence/comment-store.js +146 -0
  176. package/dist/persistence/comment-store.js.map +1 -0
  177. package/dist/persistence/entities.d.ts +103 -0
  178. package/dist/persistence/entities.d.ts.map +1 -0
  179. package/dist/persistence/entities.js +188 -0
  180. package/dist/persistence/entities.js.map +1 -0
  181. package/dist/persistence/friend-link-store.d.ts +26 -0
  182. package/dist/persistence/friend-link-store.d.ts.map +1 -0
  183. package/dist/persistence/friend-link-store.js +80 -0
  184. package/dist/persistence/friend-link-store.js.map +1 -0
  185. package/dist/persistence/page-store.d.ts +35 -0
  186. package/dist/persistence/page-store.d.ts.map +1 -0
  187. package/dist/persistence/page-store.js +125 -0
  188. package/dist/persistence/page-store.js.map +1 -0
  189. package/dist/persistence/post-engagement-store.d.ts +23 -0
  190. package/dist/persistence/post-engagement-store.d.ts.map +1 -0
  191. package/dist/persistence/post-engagement-store.js +85 -0
  192. package/dist/persistence/post-engagement-store.js.map +1 -0
  193. package/dist/persistence/post-store.d.ts +87 -0
  194. package/dist/persistence/post-store.d.ts.map +1 -0
  195. package/dist/persistence/post-store.js +465 -0
  196. package/dist/persistence/post-store.js.map +1 -0
  197. package/dist/persistence/tag-store.d.ts +21 -0
  198. package/dist/persistence/tag-store.d.ts.map +1 -0
  199. package/dist/persistence/tag-store.js +82 -0
  200. package/dist/persistence/tag-store.js.map +1 -0
  201. package/dist/services/application.service.d.ts +4 -0
  202. package/dist/services/application.service.d.ts.map +1 -0
  203. package/dist/services/application.service.js +22 -0
  204. package/dist/services/application.service.js.map +1 -0
  205. package/dist/services/blog-runtime.service.d.ts +10 -0
  206. package/dist/services/blog-runtime.service.d.ts.map +1 -0
  207. package/dist/services/blog-runtime.service.js +32 -0
  208. package/dist/services/blog-runtime.service.js.map +1 -0
  209. package/dist/services/blog.boot.d.ts +6 -0
  210. package/dist/services/blog.boot.d.ts.map +1 -0
  211. package/dist/services/blog.boot.js +13 -0
  212. package/dist/services/blog.boot.js.map +1 -0
  213. package/dist/services/browser-api-provider.service.d.ts +4 -0
  214. package/dist/services/browser-api-provider.service.d.ts.map +1 -0
  215. package/dist/services/browser-api-provider.service.js +25 -0
  216. package/dist/services/browser-api-provider.service.js.map +1 -0
  217. package/dist/services/config.service.d.ts +3 -0
  218. package/dist/services/config.service.d.ts.map +1 -0
  219. package/dist/services/config.service.js +22 -0
  220. package/dist/services/config.service.js.map +1 -0
  221. package/dist/services/database.service.d.ts +3 -0
  222. package/dist/services/database.service.d.ts.map +1 -0
  223. package/dist/services/database.service.js +16 -0
  224. package/dist/services/database.service.js.map +1 -0
  225. package/dist/services/logger.service.d.ts +4 -0
  226. package/dist/services/logger.service.d.ts.map +1 -0
  227. package/dist/services/logger.service.js +8 -0
  228. package/dist/services/logger.service.js.map +1 -0
  229. package/dist/services/mcp-provider.service.d.ts +3 -0
  230. package/dist/services/mcp-provider.service.d.ts.map +1 -0
  231. package/dist/services/mcp-provider.service.js +17 -0
  232. package/dist/services/mcp-provider.service.js.map +1 -0
  233. package/dist/services/redis.service.d.ts +4 -0
  234. package/dist/services/redis.service.d.ts.map +1 -0
  235. package/dist/services/redis.service.js +18 -0
  236. package/dist/services/redis.service.js.map +1 -0
  237. package/dist/services/theme-control.service.d.ts +4 -0
  238. package/dist/services/theme-control.service.d.ts.map +1 -0
  239. package/dist/services/theme-control.service.js +53 -0
  240. package/dist/services/theme-control.service.js.map +1 -0
  241. package/dist/themes/theme-catalog.d.ts +40 -0
  242. package/dist/themes/theme-catalog.d.ts.map +1 -0
  243. package/dist/themes/theme-catalog.js +164 -0
  244. package/dist/themes/theme-catalog.js.map +1 -0
  245. package/dist/themes/theme-control.d.ts +16 -0
  246. package/dist/themes/theme-control.d.ts.map +1 -0
  247. package/dist/themes/theme-control.js +57 -0
  248. package/dist/themes/theme-control.js.map +1 -0
  249. package/dist/themes/theme-discovery-runtime.d.ts +41 -0
  250. package/dist/themes/theme-discovery-runtime.d.ts.map +1 -0
  251. package/dist/themes/theme-discovery-runtime.js +109 -0
  252. package/dist/themes/theme-discovery-runtime.js.map +1 -0
  253. package/dist/themes/theme-generation-store.d.ts +14 -0
  254. package/dist/themes/theme-generation-store.d.ts.map +1 -0
  255. package/dist/themes/theme-generation-store.js +49 -0
  256. package/dist/themes/theme-generation-store.js.map +1 -0
  257. package/dist/themes/theme-selection-publisher.d.ts +28 -0
  258. package/dist/themes/theme-selection-publisher.d.ts.map +1 -0
  259. package/dist/themes/theme-selection-publisher.js +92 -0
  260. package/dist/themes/theme-selection-publisher.js.map +1 -0
  261. package/dist/themes/theme-selection-store.d.ts +22 -0
  262. package/dist/themes/theme-selection-store.d.ts.map +1 -0
  263. package/dist/themes/theme-selection-store.js +84 -0
  264. package/dist/themes/theme-selection-store.js.map +1 -0
  265. package/package.json +74 -0
@@ -0,0 +1,190 @@
1
+ import { toString } from 'mdast-util-to-string';
2
+ import remarkParse from 'remark-parse';
3
+ import { unified } from 'unified';
4
+ import { visit } from 'unist-util-visit';
5
+ const MEANINGLESS_IMAGE_ALT = new Set(['image', 'img', 'photo', 'picture', '图片', '图像', '照片', '截图']);
6
+ const BROAD_TAXONOMY_NAMES = new Set([
7
+ 'general', 'misc', 'miscellaneous', 'uncategorized',
8
+ '其他', '其它', '内容', '文章', '未分类', '默认',
9
+ ]);
10
+ const HIDDEN_HTML_PATTERN = /(?:display\s*:\s*none|visibility\s*:\s*hidden|font-size\s*:\s*0|opacity\s*:\s*0)/iu;
11
+ const RAW_H1_PATTERN = /<\s*h1(?:\s|>)/iu;
12
+ const RECOMMENDED_TAG_LIMIT = 5;
13
+ const RECOMMENDED_TAG_NAME_LENGTH = 20;
14
+ export const POST_CONTENT_AUDIT_FINDING_LIMIT = 200;
15
+ export function auditPostContent(input) {
16
+ const tree = unified().use(remarkParse).parse(input.content);
17
+ const findings = [
18
+ ...auditTitle(input.title),
19
+ ...auditSummary(input.summary, input.title),
20
+ ...auditMarkdown(tree),
21
+ ...(input.taxonomy ? auditTaxonomy(input.taxonomy) : []),
22
+ ];
23
+ const blocks = findings.filter((finding) => finding.severity === 'block');
24
+ const advice = findings.filter((finding) => finding.severity !== 'block');
25
+ return {
26
+ publishable: findings.every((finding) => finding.severity !== 'block'),
27
+ findings: [...blocks, ...advice].slice(0, POST_CONTENT_AUDIT_FINDING_LIMIT),
28
+ };
29
+ }
30
+ function auditTaxonomy(taxonomy) {
31
+ const findings = [];
32
+ const categoryName = normalizeText(taxonomy.category.name);
33
+ if (BROAD_TAXONOMY_NAMES.has(categoryName)) {
34
+ findings.push(finding('CATEGORY_TOO_BROAD', 'warning', 'category', '文章分类名称过于宽泛', '选择能够稳定概括文章主题的分类'));
35
+ }
36
+ if (!taxonomy.tags.length) {
37
+ findings.push(finding('TAGS_MISSING', 'info', 'tags', '文章没有设置标签', '需要建立主题关联时添加一至五个准确标签'));
38
+ return findings;
39
+ }
40
+ if (taxonomy.tags.length > RECOMMENDED_TAG_LIMIT) {
41
+ findings.push(finding('TAGS_TOO_MANY', 'warning', 'tags', '文章标签较多,可能分散主题', '保留一至五个最能代表文章主题的标签'));
42
+ }
43
+ const names = new Set();
44
+ for (const tag of taxonomy.tags) {
45
+ const name = tag.name.trim();
46
+ const normalized = normalizeText(name);
47
+ if ([...name].length > RECOMMENDED_TAG_NAME_LENGTH) {
48
+ findings.push(finding('TAG_TOO_LONG', 'warning', 'tags', '存在名称过长或句子化的标签', '将标签缩短为清晰的主题短语'));
49
+ }
50
+ if (BROAD_TAXONOMY_NAMES.has(normalized)) {
51
+ findings.push(finding('TAG_TOO_BROAD', 'warning', 'tags', '存在含义过于宽泛的标签', '改用能够描述具体主题的标签'));
52
+ }
53
+ if (normalized && normalized === categoryName) {
54
+ findings.push(finding('TAG_DUPLICATES_CATEGORY', 'warning', 'tags', '标签与文章分类重复', '删除重复标签或选择更具体的主题标签'));
55
+ }
56
+ if (normalized && names.has(normalized)) {
57
+ findings.push(finding('TAG_NORMALIZED_DUPLICATE', 'warning', 'tags', '存在大小写或字符形式不同但含义相同的标签', '合并重复标签并保留统一名称'));
58
+ }
59
+ if (normalized)
60
+ names.add(normalized);
61
+ }
62
+ return findings;
63
+ }
64
+ function auditTitle(title) {
65
+ const value = title.trim();
66
+ const length = [...value].length;
67
+ if (length < 4)
68
+ return [finding('TITLE_TOO_SHORT', 'warning', 'title', '标题过短,可能无法清楚表达文章主题', '使用准确、完整的一句话标题')];
69
+ const chineseLength = [...value.matchAll(/[\p{Script=Han}]/gu)].length;
70
+ const tooLong = chineseLength > length / 2 ? length > 30 : length > 60;
71
+ return tooLong
72
+ ? [finding('TITLE_TOO_LONG', 'warning', 'title', '标题可能在搜索结果中被截断', '缩短标题并把核心主题放在前面')]
73
+ : [];
74
+ }
75
+ function auditSummary(summary, title) {
76
+ const value = summary?.trim() ?? '';
77
+ if (!value)
78
+ return [finding('SUMMARY_MISSING', 'warning', 'summary', '文章没有独立摘要', '用一句话概括正文核心内容')];
79
+ const length = [...value].length;
80
+ const findings = [];
81
+ if (length < 30)
82
+ findings.push(finding('SUMMARY_TOO_SHORT', 'warning', 'summary', '摘要可能不足以概括正文', '补充文章解决的问题和主要内容'));
83
+ if (length > 80)
84
+ findings.push(finding('SUMMARY_TOO_LONG', 'warning', 'summary', '摘要过长,可能在搜索结果中被截断', '将摘要压缩到约 40 至 60 个中文字符'));
85
+ if (normalizeText(value) === normalizeText(title))
86
+ findings.push(finding('SUMMARY_DUPLICATES_TITLE', 'warning', 'summary', '摘要与标题相同,没有提供额外信息', '补充正文的核心结论或适用场景'));
87
+ return findings;
88
+ }
89
+ function auditMarkdown(tree) {
90
+ const findings = [];
91
+ const visibleText = collectVisibleText(tree);
92
+ if (!visibleText)
93
+ findings.push(finding('CONTENT_EMPTY', 'block', 'content', '正文没有有效可见内容', '补充文章正文'));
94
+ if ([...visibleText].length < 300)
95
+ findings.push(finding('CONTENT_TOO_SHORT', 'warning', 'content', '正文内容较少,可能无法充分回答读者问题', '确认内容已经完整覆盖主题'));
96
+ auditHeadings(tree, findings);
97
+ auditParagraphs(tree, findings);
98
+ auditImages(tree, findings);
99
+ auditLinks(tree, findings);
100
+ auditRawHtml(tree, findings);
101
+ return findings;
102
+ }
103
+ function collectVisibleText(tree) {
104
+ const values = [];
105
+ visit(tree, (node) => {
106
+ if (node.type === 'text' || node.type === 'code' || node.type === 'inlineCode')
107
+ values.push(node.value);
108
+ if (node.type === 'image' && node.alt)
109
+ values.push(node.alt);
110
+ });
111
+ return values.join(' ').trim();
112
+ }
113
+ function auditHeadings(tree, findings) {
114
+ const headings = [];
115
+ visit(tree, 'heading', (heading) => headings.push(heading));
116
+ const first = headings[0];
117
+ if (first && first.depth !== 1 && first.depth !== 2) {
118
+ findings.push(finding('CONTENT_HEADING_START', 'block', 'content', '正文的第一个标题必须是 H2', '将第一个正文标题改为二级标题', first));
119
+ }
120
+ let previousDepth;
121
+ const titles = new Set();
122
+ for (const heading of headings) {
123
+ const title = toString(heading).trim();
124
+ if (heading.depth === 1)
125
+ findings.push(finding('CONTENT_H1_FORBIDDEN', 'block', 'content', '主题已经生成文章 H1,正文不能再包含 H1', '将一级标题改为 H2 或删除', heading));
126
+ if (!title)
127
+ findings.push(finding('CONTENT_EMPTY_HEADING', 'block', 'content', '正文包含空标题', '填写标题文字或删除该标题', heading));
128
+ if (previousDepth !== undefined && heading.depth > previousDepth + 1)
129
+ findings.push(finding('HEADING_LEVEL_SKIPPED', 'warning', 'content', '正文标题层级发生跳跃', '按 H2、H3、H4 的顺序组织标题', heading));
130
+ const normalized = normalizeText(title);
131
+ if (normalized && titles.has(normalized))
132
+ findings.push(finding('HEADING_DUPLICATED', 'warning', 'content', '正文中存在重复的小标题', '使用不同标题明确各章节内容', heading));
133
+ titles.add(normalized);
134
+ previousDepth = heading.depth;
135
+ }
136
+ }
137
+ function auditParagraphs(tree, findings) {
138
+ visit(tree, 'paragraph', (paragraph) => {
139
+ if ([...toString(paragraph).trim()].length > 300) {
140
+ findings.push(finding('PARAGRAPH_TOO_LONG', 'warning', 'content', '单个段落过长,阅读负担较大', '将段落拆分为更短的逻辑单元', paragraph));
141
+ }
142
+ });
143
+ }
144
+ function auditImages(tree, findings) {
145
+ visit(tree, 'image', (image) => {
146
+ const alt = image.alt?.trim() ?? '';
147
+ if (!alt)
148
+ findings.push(finding('IMAGE_ALT_MISSING', 'warning', 'content', '正文图片缺少替代文本', '使用简短文字描述图片内容', image));
149
+ if (alt && MEANINGLESS_IMAGE_ALT.has(alt.toLocaleLowerCase()))
150
+ findings.push(finding('IMAGE_ALT_MEANINGLESS', 'warning', 'content', '图片替代文本没有描述具体内容', '说明图片展示的对象或信息', image));
151
+ if (!isSafeContentUrl(image.url))
152
+ findings.push(finding('CONTENT_IMAGE_SOURCE_INVALID', 'block', 'content', '正文图片地址无效或使用了不允许的协议', '改用 HTTPS 或站内相对图片地址', image));
153
+ });
154
+ }
155
+ function auditLinks(tree, findings) {
156
+ visit(tree, 'link', (link) => {
157
+ if (!isSafeContentUrl(link.url))
158
+ findings.push(finding('CONTENT_LINK_INVALID', 'block', 'content', '正文链接地址无效或使用了不允许的协议', '改用 HTTPS、邮件或站内相对地址', link));
159
+ const text = toString(link).trim().toLocaleLowerCase();
160
+ if (['点击这里', '点这里', '详情', '更多', 'click here', 'here'].includes(text))
161
+ findings.push(finding('LINK_TEXT_MEANINGLESS', 'warning', 'content', '链接文字没有说明目标内容', '使用能描述目标页面的链接文字', link));
162
+ });
163
+ }
164
+ function auditRawHtml(tree, findings) {
165
+ visit(tree, 'html', (html) => {
166
+ if (RAW_H1_PATTERN.test(html.value))
167
+ findings.push(finding('CONTENT_H1_FORBIDDEN', 'block', 'content', '主题已经生成文章 H1,正文不能再包含 H1', '删除 HTML H1 或改为 H2', html));
168
+ if (HIDDEN_HTML_PATTERN.test(html.value))
169
+ findings.push(finding('CONTENT_HIDDEN_KEYWORDS', 'block', 'content', '正文包含隐藏内容样式', '删除隐藏文本并自然表达主题', html));
170
+ });
171
+ }
172
+ function isSafeContentUrl(value) {
173
+ const url = value.trim();
174
+ if (!url)
175
+ return false;
176
+ if (/^(?:#|\/|\.\.?\/)/u.test(url))
177
+ return true;
178
+ return /^(?:https?:|mailto:)/iu.test(url);
179
+ }
180
+ function finding(ruleId, severity, field, message, suggestion, node) {
181
+ const location = node?.position?.start;
182
+ return {
183
+ ruleId, severity, source: 'project', field, message, suggestion,
184
+ ...(location ? { location: { line: location.line, column: location.column } } : {}),
185
+ };
186
+ }
187
+ function normalizeText(value) {
188
+ return value.normalize('NFKC').toLocaleLowerCase().replace(/[\p{P}\p{S}\s]+/gu, '');
189
+ }
190
+ //# sourceMappingURL=post-content-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-content-audit.js","sourceRoot":"","sources":["../../src/blog/post-content-audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface PostViewDedupeRedis {
2
+ get(key: string): Promise<string | null>;
3
+ set(key: string, value: string, mode: 'PX', durationMs: number): Promise<unknown>;
4
+ }
5
+ export interface PostViewDedupeCache {
6
+ hasRecent(postId: string, subjectHash: string, now: Date, windowMs: number): Promise<boolean>;
7
+ remember(postId: string, subjectHash: string, countedAt: Date, now: Date, windowMs: number): Promise<void>;
8
+ }
9
+ export declare class RedisPostViewDedupeCache implements PostViewDedupeCache {
10
+ private readonly redis;
11
+ constructor(redis: PostViewDedupeRedis);
12
+ hasRecent(postId: string, subjectHash: string, now: Date, windowMs: number): Promise<boolean>;
13
+ remember(postId: string, subjectHash: string, countedAt: Date, now: Date, windowMs: number): Promise<void>;
14
+ }
15
+ //# sourceMappingURL=post-view-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-view-cache.d.ts","sourceRoot":"","sources":["../../src/blog/post-view-cache.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnF;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,CACP,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,IAAI,EACT,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,QAAQ,CACN,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,IAAI,EACf,GAAG,EAAE,IAAI,EACT,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;AAED,qBAAa,wBAAyB,YAAW,mBAAmB;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK;IAAzC,YAAoC,KAAK,EAAE,mBAAmB,EAAI;IAErD,SAAS,CACpB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,IAAI,EACT,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAOlB;IAEY,QAAQ,CACnB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,IAAI,EACf,GAAG,EAAE,IAAI,EACT,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAIf;CACF"}
@@ -0,0 +1,23 @@
1
+ export class RedisPostViewDedupeCache {
2
+ redis;
3
+ constructor(redis) {
4
+ this.redis = redis;
5
+ }
6
+ async hasRecent(postId, subjectHash, now, windowMs) {
7
+ const value = await this.redis.get(key(postId, subjectHash));
8
+ if (!value)
9
+ return false;
10
+ const countedAt = Date.parse(value);
11
+ return Number.isFinite(countedAt)
12
+ && countedAt <= now.getTime()
13
+ && countedAt >= now.getTime() - windowMs;
14
+ }
15
+ async remember(postId, subjectHash, countedAt, now, windowMs) {
16
+ const remaining = countedAt.getTime() + windowMs - now.getTime();
17
+ if (remaining <= 0)
18
+ return;
19
+ await this.redis.set(key(postId, subjectHash), countedAt.toISOString(), 'PX', remaining);
20
+ }
21
+ }
22
+ const key = (postId, subjectHash) => `view:${postId}:${subjectHash}`;
23
+ //# sourceMappingURL=post-view-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-view-cache.js","sourceRoot":"","sources":["../../src/blog/post-view-cache.ts"],"names":[],"mappings":"AAqBA,MAAM,OAAO,wBAAwB;IACC,KAAK;IAAzC,YAAoC,KAA0B;qBAA1B,KAAK;IAAwB,CAAC;IAE3D,KAAK,CAAC,SAAS,CACpB,MAAc,EACd,WAAmB,EACnB,GAAS,EACT,QAAgB;QAEhB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;QAC7D,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACpC,OAAO,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;eAC5B,SAAS,IAAI,GAAG,CAAC,OAAO,EAAE;eAC1B,SAAS,IAAI,GAAG,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC;IAC7C,CAAC;IAEM,KAAK,CAAC,QAAQ,CACnB,MAAc,EACd,WAAmB,EACnB,SAAe,EACf,GAAS,EACT,QAAgB;QAEhB,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,EAAE,GAAG,QAAQ,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;QACjE,IAAI,SAAS,IAAI,CAAC;YAAE,OAAO;QAC3B,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,SAAS,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC3F,CAAC;CACF;AAED,MAAM,GAAG,GAAG,CAAC,MAAc,EAAE,WAAmB,EAAE,EAAE,CAAC,QAAQ,MAAM,IAAI,WAAW,EAAE,CAAC"}
@@ -0,0 +1,291 @@
1
+ import type { InvocationContext } from '@hile/context';
2
+ import type { PublicBlogService } from './public-blog-service.js';
3
+ type PublicBlogReadPort = Pick<PublicBlogService, 'listPosts' | 'listPostArchive' | 'readPost' | 'openPost' | 'readPostConnections' | 'listComments' | 'listRecentComments' | 'listCategories' | 'listTags' | 'listFriendLinks' | 'listPages' | 'readPage'>;
4
+ export declare class PublicBlogMicroService {
5
+ private readonly blog;
6
+ constructor(blog: PublicBlogReadPort);
7
+ listPosts(input: unknown, signal?: AbortSignal): Promise<Readonly<{
8
+ items: readonly Readonly<{
9
+ id: string;
10
+ category: Readonly<{
11
+ id: string;
12
+ name: string;
13
+ slug: string;
14
+ description: string | null;
15
+ sortOrder: number;
16
+ }>;
17
+ title: string;
18
+ slug: string;
19
+ summary: string | null;
20
+ coverUrl: string | null;
21
+ publishedAt: string;
22
+ updatedAt: string;
23
+ tags: readonly Readonly<{
24
+ id: string;
25
+ name: string;
26
+ slug: string;
27
+ }>[];
28
+ }>[];
29
+ nextCursor: string | null;
30
+ total: number;
31
+ }>>;
32
+ listPostArchive(input: unknown, signal?: AbortSignal): Promise<Readonly<{
33
+ items: readonly Readonly<{
34
+ id: string;
35
+ category: Readonly<{
36
+ id: string;
37
+ name: string;
38
+ slug: string;
39
+ description: string | null;
40
+ sortOrder: number;
41
+ }>;
42
+ title: string;
43
+ slug: string;
44
+ summary: string | null;
45
+ coverUrl: string | null;
46
+ publishedAt: string;
47
+ updatedAt: string;
48
+ tags: readonly Readonly<{
49
+ id: string;
50
+ name: string;
51
+ slug: string;
52
+ }>[];
53
+ }>[];
54
+ months: readonly Readonly<{
55
+ year: number;
56
+ month: number;
57
+ count: number;
58
+ }>[];
59
+ nextCursor: string | null;
60
+ total: number;
61
+ }>>;
62
+ readPost(input: unknown, signal?: AbortSignal): Promise<Readonly<{
63
+ found: false;
64
+ }> | Readonly<{
65
+ found: true;
66
+ post: Readonly<{
67
+ id: string;
68
+ category: Readonly<{
69
+ id: string;
70
+ name: string;
71
+ slug: string;
72
+ description: string | null;
73
+ sortOrder: number;
74
+ }>;
75
+ title: string;
76
+ slug: string;
77
+ summary: string | null;
78
+ coverUrl: string | null;
79
+ publishedAt: string;
80
+ updatedAt: string;
81
+ tags: readonly Readonly<{
82
+ id: string;
83
+ name: string;
84
+ slug: string;
85
+ }>[];
86
+ content: string;
87
+ }>;
88
+ }>>;
89
+ openPost(input: unknown, invocation: InvocationContext): Promise<Readonly<{
90
+ found: false;
91
+ }> | Readonly<{
92
+ found: true;
93
+ post: Readonly<{
94
+ id: string;
95
+ category: Readonly<{
96
+ id: string;
97
+ name: string;
98
+ slug: string;
99
+ description: string | null;
100
+ sortOrder: number;
101
+ }>;
102
+ title: string;
103
+ slug: string;
104
+ summary: string | null;
105
+ coverUrl: string | null;
106
+ publishedAt: string;
107
+ updatedAt: string;
108
+ tags: readonly Readonly<{
109
+ id: string;
110
+ name: string;
111
+ slug: string;
112
+ }>[];
113
+ content: string;
114
+ }>;
115
+ engagement: Readonly<{
116
+ viewCount: number;
117
+ likeCount: number;
118
+ viewerState: "anonymous" | "liked" | "not-liked" | "unavailable";
119
+ }>;
120
+ }>>;
121
+ readPostConnections(input: unknown, signal?: AbortSignal): Promise<Readonly<{
122
+ found: false;
123
+ }> | Readonly<{
124
+ found: true;
125
+ connections: Readonly<{
126
+ previousPost: Readonly<{
127
+ id: string;
128
+ category: Readonly<{
129
+ id: string;
130
+ name: string;
131
+ slug: string;
132
+ description: string | null;
133
+ sortOrder: number;
134
+ }>;
135
+ title: string;
136
+ slug: string;
137
+ summary: string | null;
138
+ coverUrl: string | null;
139
+ publishedAt: string;
140
+ updatedAt: string;
141
+ tags: readonly Readonly<{
142
+ id: string;
143
+ name: string;
144
+ slug: string;
145
+ }>[];
146
+ }> | null;
147
+ nextPost: Readonly<{
148
+ id: string;
149
+ category: Readonly<{
150
+ id: string;
151
+ name: string;
152
+ slug: string;
153
+ description: string | null;
154
+ sortOrder: number;
155
+ }>;
156
+ title: string;
157
+ slug: string;
158
+ summary: string | null;
159
+ coverUrl: string | null;
160
+ publishedAt: string;
161
+ updatedAt: string;
162
+ tags: readonly Readonly<{
163
+ id: string;
164
+ name: string;
165
+ slug: string;
166
+ }>[];
167
+ }> | null;
168
+ relatedPosts: readonly Readonly<{
169
+ id: string;
170
+ category: Readonly<{
171
+ id: string;
172
+ name: string;
173
+ slug: string;
174
+ description: string | null;
175
+ sortOrder: number;
176
+ }>;
177
+ title: string;
178
+ slug: string;
179
+ summary: string | null;
180
+ coverUrl: string | null;
181
+ publishedAt: string;
182
+ updatedAt: string;
183
+ tags: readonly Readonly<{
184
+ id: string;
185
+ name: string;
186
+ slug: string;
187
+ }>[];
188
+ }>[];
189
+ }>;
190
+ }>>;
191
+ listComments(input: unknown, invocation: InvocationContext): Promise<Readonly<{
192
+ found: false;
193
+ }> | Readonly<{
194
+ found: true;
195
+ comments: Readonly<{
196
+ items: readonly Readonly<{
197
+ id: string;
198
+ postId: string;
199
+ user: Readonly<{
200
+ id: string;
201
+ displayName: string | null;
202
+ avatar: string | null;
203
+ homepage: string | null;
204
+ bio: string | null;
205
+ }>;
206
+ content: string;
207
+ replyContent: string | null;
208
+ repliedAt: string | null;
209
+ createdAt: string;
210
+ location: string | null;
211
+ client: string | null;
212
+ pendingReview?: true | undefined;
213
+ }>[];
214
+ nextCursor: string | null;
215
+ }>;
216
+ }>>;
217
+ listRecentComments(input: unknown, invocation: InvocationContext): Promise<readonly Readonly<{
218
+ comment: Readonly<{
219
+ id: string;
220
+ postId: string;
221
+ user: Readonly<{
222
+ id: string;
223
+ displayName: string | null;
224
+ avatar: string | null;
225
+ homepage: string | null;
226
+ bio: string | null;
227
+ }>;
228
+ content: string;
229
+ replyContent: string | null;
230
+ repliedAt: string | null;
231
+ createdAt: string;
232
+ location: string | null;
233
+ client: string | null;
234
+ pendingReview?: true | undefined;
235
+ }>;
236
+ post: Readonly<{
237
+ id: string;
238
+ title: string;
239
+ slug: string;
240
+ }>;
241
+ }>[]>;
242
+ listCategories(input: unknown, signal?: AbortSignal): Promise<readonly Readonly<{
243
+ id: string;
244
+ name: string;
245
+ slug: string;
246
+ description: string | null;
247
+ sortOrder: number;
248
+ postCount: number;
249
+ }>[]>;
250
+ listTags(input: unknown, signal?: AbortSignal): Promise<readonly Readonly<{
251
+ id: string;
252
+ name: string;
253
+ slug: string;
254
+ }>[]>;
255
+ listFriendLinks(input: unknown, signal?: AbortSignal): Promise<readonly Readonly<{
256
+ id: string;
257
+ name: string;
258
+ url: string;
259
+ description: string | null;
260
+ logoUrl: string | null;
261
+ sortOrder: number;
262
+ }>[]>;
263
+ listPages(input: unknown, signal?: AbortSignal): Promise<readonly Readonly<{
264
+ id: string;
265
+ title: string;
266
+ slug: string;
267
+ summary: string;
268
+ position: "navigation" | "sidebar" | null;
269
+ sortOrder: number;
270
+ publishedAt: string;
271
+ updatedAt: string;
272
+ }>[]>;
273
+ readPage(input: unknown, signal?: AbortSignal): Promise<Readonly<{
274
+ found: false;
275
+ }> | Readonly<{
276
+ found: true;
277
+ page: Readonly<{
278
+ id: string;
279
+ title: string;
280
+ slug: string;
281
+ summary: string;
282
+ position: "navigation" | "sidebar" | null;
283
+ sortOrder: number;
284
+ publishedAt: string;
285
+ updatedAt: string;
286
+ content: string;
287
+ }>;
288
+ }>>;
289
+ }
290
+ export {};
291
+ //# sourceMappingURL=public-blog-micro.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public-blog-micro.d.ts","sourceRoot":"","sources":["../../src/blog/public-blog-micro.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,KAAK,kBAAkB,GAAG,IAAI,CAAC,iBAAiB,EAC5C,WAAW,GACX,iBAAiB,GACjB,UAAU,GACV,UAAU,GACV,qBAAqB,GACrB,cAAc,GACd,oBAAoB,GACpB,gBAAgB,GAChB,UAAU,GACV,iBAAiB,GACjB,WAAW,GACX,UAAU,CAAC,CAAC;AAEhB,qBAAa,sBAAsB;IACd,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAxC,YAAoC,IAAI,EAAE,kBAAkB,EAAI;IAEnD,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW;;;;;;;;;;;;;;;;;;;;;;;;QAS1D;IAEY,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAGhE;IAEY,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;QAIzD;IAEY,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAQlE;IAEY,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAUpE;IAEY,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;QAUtE;IAEY,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;UAK5E;IAEY,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW;;;;;;;UAG/D;IAEY,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW;;;;UAGzD;IAEY,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW;;;;;;;UAGhE;IAEY,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW;;;;;;;;;UAG1D;IAEY,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW;;;;;;;;;;;;;;;QAIzD;CACF"}
@@ -0,0 +1,71 @@
1
+ import { blogCategoryListSchema, blogCommentListInputSchema, blogRecentCommentListInputSchema, blogRecentCommentListSchema, blogEmptyRequestSchema, blogFriendLinkListSchema, blogPageListInputSchema, blogPageListSchema, blogReadPageInputSchema, blogReadPageResponseSchema, blogListCommentsResponseSchema, blogPostListInputSchema, blogPostListSchema, blogPostArchiveInputSchema, blogPostArchiveSchema, blogPostConnectionsInputSchema, blogReadPostConnectionsResponseSchema, blogReadPostInputSchema, blogOpenPostResponseSchema, blogReadPostResponseSchema, blogTagListSchema, } from '@zlooks.cn/blog-schema';
2
+ export class PublicBlogMicroService {
3
+ blog;
4
+ constructor(blog) {
5
+ this.blog = blog;
6
+ }
7
+ async listPosts(input, signal) {
8
+ const request = blogPostListInputSchema.parse(input);
9
+ return blogPostListSchema.parse(await this.blog.listPosts({
10
+ limit: request.limit,
11
+ ...(request.cursor ? { cursor: request.cursor } : {}),
12
+ ...(request.page ? { page: request.page } : {}),
13
+ ...(request.categorySlug ? { category: request.categorySlug } : {}),
14
+ ...(request.tagSlug ? { tag: request.tagSlug } : {}),
15
+ }, signal));
16
+ }
17
+ async listPostArchive(input, signal) {
18
+ const request = blogPostArchiveInputSchema.parse(input);
19
+ return blogPostArchiveSchema.parse(await this.blog.listPostArchive(request, signal));
20
+ }
21
+ async readPost(input, signal) {
22
+ const request = blogReadPostInputSchema.parse(input);
23
+ const post = await this.blog.readPost(request.slug, signal);
24
+ return blogReadPostResponseSchema.parse(post ? { found: true, post } : { found: false });
25
+ }
26
+ async openPost(input, invocation) {
27
+ const request = blogReadPostInputSchema.parse(input);
28
+ const opened = await this.blog.openPost(request.slug, invocation.context, invocation.signal);
29
+ return blogOpenPostResponseSchema.parse(opened ? { found: true, ...opened } : { found: false });
30
+ }
31
+ async readPostConnections(input, signal) {
32
+ const request = blogPostConnectionsInputSchema.parse(input);
33
+ const connections = await this.blog.readPostConnections(request.slug, request.relatedLimit, signal);
34
+ return blogReadPostConnectionsResponseSchema.parse(connections ? { found: true, connections } : { found: false });
35
+ }
36
+ async listComments(input, invocation) {
37
+ const request = blogCommentListInputSchema.parse(input);
38
+ const comments = await this.blog.listComments(request.postSlug, {
39
+ limit: request.limit,
40
+ ...(request.cursor ? { cursor: request.cursor } : {}),
41
+ order: request.order ?? 'desc',
42
+ }, invocation.context, invocation.signal);
43
+ return blogListCommentsResponseSchema.parse(comments ? { found: true, comments } : { found: false });
44
+ }
45
+ async listRecentComments(input, invocation) {
46
+ const request = blogRecentCommentListInputSchema.parse(input);
47
+ return blogRecentCommentListSchema.parse(await this.blog.listRecentComments(request.limit, invocation.context, invocation.signal));
48
+ }
49
+ async listCategories(input, signal) {
50
+ blogEmptyRequestSchema.parse(input);
51
+ return blogCategoryListSchema.parse(await this.blog.listCategories(signal));
52
+ }
53
+ async listTags(input, signal) {
54
+ blogEmptyRequestSchema.parse(input);
55
+ return blogTagListSchema.parse(await this.blog.listTags(signal));
56
+ }
57
+ async listFriendLinks(input, signal) {
58
+ blogEmptyRequestSchema.parse(input);
59
+ return blogFriendLinkListSchema.parse(await this.blog.listFriendLinks(signal));
60
+ }
61
+ async listPages(input, signal) {
62
+ const request = blogPageListInputSchema.parse(input);
63
+ return blogPageListSchema.parse(await this.blog.listPages(request.position, signal));
64
+ }
65
+ async readPage(input, signal) {
66
+ const request = blogReadPageInputSchema.parse(input);
67
+ const page = await this.blog.readPage(request.slug, signal);
68
+ return blogReadPageResponseSchema.parse(page ? { found: true, page } : { found: false });
69
+ }
70
+ }
71
+ //# sourceMappingURL=public-blog-micro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public-blog-micro.js","sourceRoot":"","sources":["../../src/blog/public-blog-micro.ts"],"names":[],"mappings":"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"}