@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,103 @@
1
+ import { EntitySchema } from 'typeorm';
2
+ export type BlogPostStatus = 'draft' | 'published' | 'archived';
3
+ export type BlogCommentStatus = 'pending' | 'approved' | 'rejected';
4
+ export type BlogPagePosition = 'navigation' | 'sidebar';
5
+ export interface BlogCategoryRow {
6
+ id: string;
7
+ name: string;
8
+ slug: string;
9
+ description: string | null;
10
+ sortOrder: number;
11
+ createdAt: Date;
12
+ updatedAt: Date;
13
+ }
14
+ export interface BlogPostRow {
15
+ id: string;
16
+ categoryId: string;
17
+ title: string;
18
+ slug: string;
19
+ summary: string | null;
20
+ coverUrl: string | null;
21
+ content: string;
22
+ status: BlogPostStatus;
23
+ publishedAt: Date | null;
24
+ createdAt: Date;
25
+ updatedAt: Date;
26
+ viewCount: number;
27
+ postTags?: BlogPostTagRow[];
28
+ }
29
+ export interface BlogTagRow {
30
+ id: string;
31
+ name: string;
32
+ slug: string;
33
+ createdAt: Date;
34
+ updatedAt: Date;
35
+ postTags?: BlogPostTagRow[];
36
+ }
37
+ export interface BlogPostTagRow {
38
+ postId: string;
39
+ tagId: string;
40
+ post?: BlogPostRow;
41
+ tag?: BlogTagRow;
42
+ }
43
+ export interface BlogPostViewMarkRow {
44
+ postId: string;
45
+ subjectHash: string;
46
+ countedAt: Date;
47
+ updatedAt: Date;
48
+ }
49
+ export interface BlogPostLikeRow {
50
+ postId: string;
51
+ userId: string;
52
+ createdAt: Date;
53
+ }
54
+ export interface BlogCommentRow {
55
+ id: string;
56
+ postId: string;
57
+ userId: string;
58
+ content: string;
59
+ ipAddress: string | null;
60
+ userAgent: string | null;
61
+ ipLocation: string | null;
62
+ clientLabel: string | null;
63
+ replyContent: string | null;
64
+ repliedAt: Date | null;
65
+ status: BlogCommentStatus;
66
+ createdAt: Date;
67
+ updatedAt: Date;
68
+ }
69
+ export interface BlogFriendLinkRow {
70
+ id: string;
71
+ name: string;
72
+ url: string;
73
+ description: string | null;
74
+ logoUrl: string | null;
75
+ enabled: boolean;
76
+ sortOrder: number;
77
+ createdAt: Date;
78
+ updatedAt: Date;
79
+ }
80
+ export interface BlogPageRow {
81
+ id: string;
82
+ title: string;
83
+ slug: string;
84
+ summary: string;
85
+ content: string;
86
+ status: BlogPostStatus;
87
+ position: BlogPagePosition | null;
88
+ sortOrder: number;
89
+ publishedAt: Date | null;
90
+ createdAt: Date;
91
+ updatedAt: Date;
92
+ }
93
+ export declare const BlogCategoryEntity: EntitySchema<BlogCategoryRow>;
94
+ export declare const BlogPostEntity: EntitySchema<BlogPostRow>;
95
+ export declare const BlogPostViewMarkEntity: EntitySchema<BlogPostViewMarkRow>;
96
+ export declare const BlogPostLikeEntity: EntitySchema<BlogPostLikeRow>;
97
+ export declare const BlogTagEntity: EntitySchema<BlogTagRow>;
98
+ export declare const BlogPostTagEntity: EntitySchema<BlogPostTagRow>;
99
+ export declare const BlogCommentEntity: EntitySchema<BlogCommentRow>;
100
+ export declare const BlogFriendLinkEntity: EntitySchema<BlogFriendLinkRow>;
101
+ export declare const BlogPageEntity: EntitySchema<BlogPageRow>;
102
+ export declare const blogEntities: readonly [EntitySchema<BlogCategoryRow>, EntitySchema<BlogPostRow>, EntitySchema<BlogTagRow>, EntitySchema<BlogPostTagRow>, EntitySchema<BlogPostViewMarkRow>, EntitySchema<BlogPostLikeRow>, EntitySchema<BlogCommentRow>, EntitySchema<BlogFriendLinkRow>, EntitySchema<BlogPageRow>];
103
+ //# sourceMappingURL=entities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../src/persistence/entities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,188 @@
1
+ import { EntitySchema } from 'typeorm';
2
+ const timestamps = {
3
+ createdAt: { name: 'created_at', type: 'timestamptz', createDate: true },
4
+ updatedAt: { name: 'updated_at', type: 'timestamptz', updateDate: true },
5
+ };
6
+ export const BlogCategoryEntity = new EntitySchema({
7
+ name: 'BlogCategory', tableName: 'blog_categories',
8
+ columns: {
9
+ id: { type: 'uuid', primary: true, generated: 'uuid' },
10
+ name: { type: 'varchar', length: 100, unique: true },
11
+ slug: { type: 'varchar', length: 120, unique: true },
12
+ description: { type: 'varchar', length: 500, nullable: true },
13
+ sortOrder: { name: 'sort_order', type: 'integer', default: 0 },
14
+ ...timestamps,
15
+ },
16
+ indices: [{ name: 'idx_blog_categories_sort', columns: ['sortOrder', 'id'] }],
17
+ });
18
+ export const BlogPostEntity = new EntitySchema({
19
+ name: 'BlogPost', tableName: 'blog_posts',
20
+ columns: {
21
+ id: { type: 'uuid', primary: true, generated: 'uuid' },
22
+ categoryId: { name: 'category_id', type: 'uuid' },
23
+ title: { type: 'varchar', length: 200 },
24
+ slug: { type: 'varchar', length: 200, unique: true },
25
+ summary: { type: 'varchar', length: 500, nullable: true },
26
+ coverUrl: { name: 'cover_url', type: 'varchar', length: 2048, nullable: true },
27
+ content: { type: 'text' },
28
+ status: { type: 'varchar', length: 16, default: 'draft' },
29
+ publishedAt: { name: 'published_at', type: 'timestamptz', nullable: true },
30
+ viewCount: { name: 'view_count', type: 'integer', default: 0 },
31
+ ...timestamps,
32
+ },
33
+ foreignKeys: [{
34
+ name: 'fk_blog_posts_category', target: BlogCategoryEntity,
35
+ columnNames: ['categoryId'], referencedColumnNames: ['id'], onDelete: 'RESTRICT',
36
+ }],
37
+ checks: [
38
+ { name: 'chk_blog_posts_status', expression: `"status" IN ('draft', 'published', 'archived')` },
39
+ { name: 'chk_blog_posts_content_length', expression: `char_length("content") BETWEEN 1 AND 1000000` },
40
+ { name: 'chk_blog_posts_view_count', expression: `"view_count" >= 0` },
41
+ {
42
+ name: 'chk_blog_posts_published_at',
43
+ expression: `("status" = 'published' AND "published_at" IS NOT NULL) OR ("status" = 'draft' AND "published_at" IS NULL) OR "status" = 'archived'`,
44
+ },
45
+ ],
46
+ relations: {
47
+ postTags: { type: 'one-to-many', target: 'BlogPostTag', inverseSide: 'post' },
48
+ },
49
+ indices: [
50
+ { name: 'idx_blog_posts_public', columns: ['status', 'publishedAt', 'id'] },
51
+ { name: 'idx_blog_posts_category', columns: ['categoryId', 'status', 'publishedAt', 'id'] },
52
+ ],
53
+ });
54
+ export const BlogPostViewMarkEntity = new EntitySchema({
55
+ name: 'BlogPostViewMark', tableName: 'blog_post_view_marks',
56
+ columns: {
57
+ postId: { name: 'post_id', type: 'uuid', primary: true },
58
+ subjectHash: { name: 'subject_hash', type: 'varchar', length: 64, primary: true },
59
+ countedAt: { name: 'counted_at', type: 'timestamptz' },
60
+ updatedAt: { name: 'updated_at', type: 'timestamptz', updateDate: true },
61
+ },
62
+ foreignKeys: [{
63
+ name: 'fk_blog_post_view_marks_post', target: BlogPostEntity,
64
+ columnNames: ['postId'], referencedColumnNames: ['id'], onDelete: 'CASCADE',
65
+ }],
66
+ checks: [{ name: 'chk_blog_post_view_marks_subject_hash', expression: `char_length("subject_hash") = 64` }],
67
+ indices: [{ name: 'idx_blog_post_view_marks_counted_at', columns: ['countedAt'] }],
68
+ });
69
+ export const BlogPostLikeEntity = new EntitySchema({
70
+ name: 'BlogPostLike', tableName: 'blog_post_likes',
71
+ columns: {
72
+ postId: { name: 'post_id', type: 'uuid', primary: true },
73
+ userId: { name: 'user_id', type: 'uuid', primary: true },
74
+ createdAt: { name: 'created_at', type: 'timestamptz', createDate: true },
75
+ },
76
+ foreignKeys: [{
77
+ name: 'fk_blog_post_likes_post', target: BlogPostEntity,
78
+ columnNames: ['postId'], referencedColumnNames: ['id'], onDelete: 'CASCADE',
79
+ }],
80
+ indices: [{ name: 'idx_blog_post_likes_user', columns: ['userId', 'createdAt'] }],
81
+ });
82
+ export const BlogTagEntity = new EntitySchema({
83
+ name: 'BlogTag', tableName: 'blog_tags',
84
+ columns: {
85
+ id: { type: 'uuid', primary: true, generated: 'uuid' },
86
+ name: { type: 'varchar', length: 100, unique: true },
87
+ slug: { type: 'varchar', length: 120, unique: true },
88
+ ...timestamps,
89
+ },
90
+ relations: {
91
+ postTags: { type: 'one-to-many', target: 'BlogPostTag', inverseSide: 'tag' },
92
+ },
93
+ });
94
+ export const BlogPostTagEntity = new EntitySchema({
95
+ name: 'BlogPostTag', tableName: 'blog_post_tags',
96
+ columns: {
97
+ postId: { name: 'post_id', type: 'uuid', primary: true },
98
+ tagId: { name: 'tag_id', type: 'uuid', primary: true },
99
+ },
100
+ foreignKeys: [
101
+ { name: 'fk_blog_post_tags_post', target: BlogPostEntity, columnNames: ['postId'], referencedColumnNames: ['id'], onDelete: 'CASCADE' },
102
+ { name: 'fk_blog_post_tags_tag', target: BlogTagEntity, columnNames: ['tagId'], referencedColumnNames: ['id'], onDelete: 'CASCADE' },
103
+ ],
104
+ relations: {
105
+ post: { type: 'many-to-one', target: 'BlogPost', joinColumn: { name: 'post_id' }, createForeignKeyConstraints: false },
106
+ tag: { type: 'many-to-one', target: 'BlogTag', joinColumn: { name: 'tag_id' }, createForeignKeyConstraints: false },
107
+ },
108
+ indices: [{ name: 'idx_blog_post_tags_tag', columns: ['tagId', 'postId'] }],
109
+ });
110
+ export const BlogCommentEntity = new EntitySchema({
111
+ name: 'BlogComment', tableName: 'blog_comments',
112
+ columns: {
113
+ id: { type: 'uuid', primary: true, generated: 'uuid' },
114
+ postId: { name: 'post_id', type: 'uuid' },
115
+ userId: { name: 'user_id', type: 'uuid' },
116
+ content: { type: 'text' },
117
+ ipAddress: { name: 'ip_address', type: 'varchar', length: 45, nullable: true },
118
+ userAgent: { name: 'user_agent', type: 'varchar', length: 1024, nullable: true },
119
+ ipLocation: { name: 'ip_location', type: 'varchar', length: 200, nullable: true },
120
+ clientLabel: { name: 'client_label', type: 'varchar', length: 160, nullable: true },
121
+ replyContent: { name: 'reply_content', type: 'text', nullable: true },
122
+ repliedAt: { name: 'replied_at', type: 'timestamptz', nullable: true },
123
+ status: { type: 'varchar', length: 16, default: 'pending' },
124
+ ...timestamps,
125
+ },
126
+ foreignKeys: [{
127
+ name: 'fk_blog_comments_post', target: BlogPostEntity,
128
+ columnNames: ['postId'], referencedColumnNames: ['id'], onDelete: 'CASCADE',
129
+ }],
130
+ checks: [
131
+ { name: 'chk_blog_comments_status', expression: `"status" IN ('pending', 'approved', 'rejected')` },
132
+ { name: 'chk_blog_comments_content_length', expression: `char_length(btrim("content", chr(32) || chr(9) || chr(10) || chr(13) || chr(12) || chr(11))) BETWEEN 1 AND 2000` },
133
+ { name: 'chk_blog_comments_reply_length', expression: `"reply_content" IS NULL OR char_length(btrim("reply_content", chr(32) || chr(9) || chr(10) || chr(13) || chr(12) || chr(11))) BETWEEN 1 AND 2000` },
134
+ {
135
+ name: 'chk_blog_comments_reply_pair',
136
+ expression: `("reply_content" IS NULL AND "replied_at" IS NULL) OR ("reply_content" IS NOT NULL AND "replied_at" IS NOT NULL)`,
137
+ },
138
+ ],
139
+ indices: [
140
+ { name: 'idx_blog_comments_post', columns: ['postId', 'status', 'createdAt', 'id'] },
141
+ { name: 'idx_blog_comments_user', columns: ['userId', 'createdAt', 'id'] },
142
+ ],
143
+ });
144
+ export const BlogFriendLinkEntity = new EntitySchema({
145
+ name: 'BlogFriendLink', tableName: 'blog_friend_links',
146
+ columns: {
147
+ id: { type: 'uuid', primary: true, generated: 'uuid' },
148
+ name: { type: 'varchar', length: 100 },
149
+ url: { type: 'varchar', length: 2048, unique: true },
150
+ description: { type: 'varchar', length: 500, nullable: true },
151
+ logoUrl: { name: 'logo_url', type: 'varchar', length: 2048, nullable: true },
152
+ enabled: { type: 'boolean', default: true },
153
+ sortOrder: { name: 'sort_order', type: 'integer', default: 0 },
154
+ ...timestamps,
155
+ },
156
+ indices: [{ name: 'idx_blog_friend_links_public', columns: ['enabled', 'sortOrder', 'id'] }],
157
+ });
158
+ export const BlogPageEntity = new EntitySchema({
159
+ name: 'BlogPage', tableName: 'blog_pages',
160
+ columns: {
161
+ id: { type: 'uuid', primary: true, generated: 'uuid' },
162
+ title: { type: 'varchar', length: 200 },
163
+ slug: { type: 'varchar', length: 200, unique: true },
164
+ summary: { type: 'varchar', length: 500 },
165
+ content: { type: 'text' },
166
+ status: { type: 'varchar', length: 16, default: 'draft' },
167
+ position: { type: 'varchar', length: 16, nullable: true },
168
+ sortOrder: { name: 'sort_order', type: 'integer', default: 0 },
169
+ publishedAt: { name: 'published_at', type: 'timestamptz', nullable: true },
170
+ ...timestamps,
171
+ },
172
+ checks: [
173
+ { name: 'chk_blog_pages_status', expression: `"status" IN ('draft', 'published', 'archived')` },
174
+ { name: 'chk_blog_pages_position', expression: `"position" IS NULL OR "position" IN ('navigation', 'sidebar')` },
175
+ { name: 'chk_blog_pages_content_length', expression: `char_length("content") BETWEEN 1 AND 1000000` },
176
+ {
177
+ name: 'chk_blog_pages_published_at',
178
+ expression: `("status" = 'published' AND "published_at" IS NOT NULL) OR ("status" = 'draft' AND "published_at" IS NULL) OR "status" = 'archived'`,
179
+ },
180
+ ],
181
+ indices: [{ name: 'idx_blog_pages_public', columns: ['status', 'position', 'sortOrder', 'id'] }],
182
+ });
183
+ export const blogEntities = [
184
+ BlogCategoryEntity, BlogPostEntity, BlogTagEntity,
185
+ BlogPostTagEntity, BlogPostViewMarkEntity, BlogPostLikeEntity,
186
+ BlogCommentEntity, BlogFriendLinkEntity, BlogPageEntity,
187
+ ];
188
+ //# sourceMappingURL=entities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entities.js","sourceRoot":"","sources":["../../src/persistence/entities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { type DataSource } from 'typeorm';
2
+ import { type BlogFriendLinkRow } from './entities.js';
3
+ export interface FriendLinkInput {
4
+ readonly name: string;
5
+ readonly url: string;
6
+ readonly description: string | null;
7
+ readonly logoUrl: string | null;
8
+ readonly enabled: boolean;
9
+ readonly sortOrder: number;
10
+ }
11
+ export declare class FriendLinkStore {
12
+ private readonly dataSource;
13
+ constructor(dataSource: DataSource);
14
+ listEnabled(signal?: AbortSignal): Promise<BlogFriendLinkRow[]>;
15
+ listPage(limit: number, cursorId?: string, signal?: AbortSignal): Promise<{
16
+ items: BlogFriendLinkRow[];
17
+ nextCursor: string | null;
18
+ }>;
19
+ read(id: string, signal?: AbortSignal): Promise<BlogFriendLinkRow>;
20
+ create(input: FriendLinkInput, signal?: AbortSignal): Promise<BlogFriendLinkRow>;
21
+ update(id: string, input: FriendLinkInput, signal?: AbortSignal): Promise<BlogFriendLinkRow>;
22
+ setEnabled(id: string, enabled: boolean, signal?: AbortSignal): Promise<BlogFriendLinkRow>;
23
+ delete(id: string, signal?: AbortSignal): Promise<void>;
24
+ private mutate;
25
+ }
26
+ //# sourceMappingURL=friend-link-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"friend-link-store.d.ts","sourceRoot":"","sources":["../../src/persistence/friend-link-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,UAAU,EAAyB,MAAM,SAAS,CAAC;AAElF,OAAO,EAAwB,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE7E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACjF,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CACxF;AAED,qBAAa,eAAe;IACP,OAAO,CAAC,QAAQ,CAAC,UAAU;IAA9C,YAAoC,UAAU,EAAE,UAAU,EAAI;IACjD,WAAW,CAAC,MAAM,CAAC,EAAE,WAAW,gCAK5C;IACY,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW;;;OAW3E;IACY,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,8BAMjD;IACM,MAAM,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAItF;IACM,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,WAAW,8BAErE;IACM,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,8BAEnE;IACM,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,iBAU7C;IACD,OAAO,CAAC,MAAM;CAcf"}
@@ -0,0 +1,80 @@
1
+ import { Equal, MoreThan } from 'typeorm';
2
+ import { BlogCursorError, BlogNotFoundError } from '../blog/errors.js';
3
+ import { BlogFriendLinkEntity } from './entities.js';
4
+ export class FriendLinkStore {
5
+ dataSource;
6
+ constructor(dataSource) {
7
+ this.dataSource = dataSource;
8
+ }
9
+ async listEnabled(signal) {
10
+ signal?.throwIfAborted();
11
+ const rows = await this.dataSource.getRepository(BlogFriendLinkEntity).find({ where: { enabled: true }, order: { sortOrder: 'ASC', id: 'ASC' }, take: 500 });
12
+ signal?.throwIfAborted();
13
+ return rows;
14
+ }
15
+ async listPage(limit, cursorId, signal) {
16
+ signal?.throwIfAborted();
17
+ const cursor = cursorId ? await this.dataSource.getRepository(BlogFriendLinkEntity).findOneBy({ id: cursorId }) : undefined;
18
+ signal?.throwIfAborted();
19
+ if (cursorId && !cursor)
20
+ throw new BlogCursorError('Friend link cursor not found');
21
+ const where = cursor
22
+ ? [{ sortOrder: MoreThan(cursor.sortOrder) }, { sortOrder: Equal(cursor.sortOrder), id: MoreThan(cursor.id) }]
23
+ : {};
24
+ const rows = await this.dataSource.getRepository(BlogFriendLinkEntity).find({ where, order: { sortOrder: 'ASC', id: 'ASC' }, take: limit + 1 });
25
+ signal?.throwIfAborted();
26
+ return page(rows, limit);
27
+ }
28
+ async read(id, signal) {
29
+ signal?.throwIfAborted();
30
+ const row = await this.dataSource.getRepository(BlogFriendLinkEntity).findOneBy({ id });
31
+ signal?.throwIfAborted();
32
+ if (!row)
33
+ throw new BlogNotFoundError('Friend link not found');
34
+ return row;
35
+ }
36
+ create(input, signal) {
37
+ signal?.throwIfAborted();
38
+ const repository = this.dataSource.getRepository(BlogFriendLinkEntity);
39
+ return repository.save(repository.create(input));
40
+ }
41
+ update(id, input, signal) {
42
+ return this.mutate(id, input, signal);
43
+ }
44
+ setEnabled(id, enabled, signal) {
45
+ return this.mutate(id, { enabled }, signal);
46
+ }
47
+ delete(id, signal) {
48
+ signal?.throwIfAborted();
49
+ return this.dataSource.transaction(async (manager) => {
50
+ const repository = manager.getRepository(BlogFriendLinkEntity);
51
+ const current = await repository.findOneBy({ id });
52
+ signal?.throwIfAborted();
53
+ if (!current)
54
+ throw new BlogNotFoundError('Friend link not found');
55
+ await repository.delete({ id });
56
+ signal?.throwIfAborted();
57
+ });
58
+ }
59
+ mutate(id, input, signal) {
60
+ signal?.throwIfAborted();
61
+ return this.dataSource.transaction(async (manager) => {
62
+ const repository = manager.getRepository(BlogFriendLinkEntity);
63
+ const current = await repository.findOneBy({ id });
64
+ signal?.throwIfAborted();
65
+ if (!current)
66
+ throw new BlogNotFoundError('Friend link not found');
67
+ await repository.update({ id }, input);
68
+ signal?.throwIfAborted();
69
+ const updated = await repository.findOneByOrFail({ id });
70
+ signal?.throwIfAborted();
71
+ return updated;
72
+ });
73
+ }
74
+ }
75
+ function page(rows, limit) {
76
+ const hasMore = rows.length > limit;
77
+ const items = hasMore ? rows.slice(0, limit) : rows;
78
+ return { items, nextCursor: hasMore ? items.at(-1)?.id ?? null : null };
79
+ }
80
+ //# sourceMappingURL=friend-link-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"friend-link-store.js","sourceRoot":"","sources":["../../src/persistence/friend-link-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { type DataSource } from 'typeorm';
2
+ import { type BlogPagePosition, type BlogPageRow } from './entities.js';
3
+ export interface PageInput {
4
+ readonly title: string;
5
+ readonly slug: string;
6
+ readonly summary: string;
7
+ readonly content: string;
8
+ readonly position: BlogPagePosition | null;
9
+ readonly sortOrder: number;
10
+ }
11
+ export declare class PageStore {
12
+ private readonly dataSource;
13
+ private readonly clock;
14
+ constructor(dataSource: DataSource, clock?: () => Date);
15
+ list(input: {
16
+ limit: number;
17
+ cursor?: string | undefined;
18
+ status?: BlogPageRow['status'] | undefined;
19
+ position?: BlogPagePosition | null | undefined;
20
+ }, signal?: AbortSignal): Promise<{
21
+ items: BlogPageRow[];
22
+ nextCursor: string | null;
23
+ }>;
24
+ listPublished(position?: BlogPagePosition | null, signal?: AbortSignal): Promise<BlogPageRow[]>;
25
+ read(id: string, signal?: AbortSignal): Promise<BlogPageRow>;
26
+ readPublishedBySlug(slug: string, signal?: AbortSignal): Promise<BlogPageRow | undefined>;
27
+ create(input: PageInput, signal?: AbortSignal): Promise<BlogPageRow>;
28
+ update(id: string, input: PageInput, signal?: AbortSignal): Promise<BlogPageRow>;
29
+ publish(id: string, signal?: AbortSignal): Promise<BlogPageRow>;
30
+ archive(id: string, signal?: AbortSignal): Promise<BlogPageRow>;
31
+ delete(id: string, signal?: AbortSignal): Promise<void>;
32
+ private transition;
33
+ private filters;
34
+ }
35
+ //# sourceMappingURL=page-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-store.d.ts","sourceRoot":"","sources":["../../src/persistence/page-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,UAAU,EAAyB,MAAM,SAAS,CAAC;AAE1F,OAAO,EAAkB,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAExF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC3C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFxB,YACmB,UAAU,EAAE,UAAU,EACtB,KAAK,aAAmB,EACvC;IAES,IAAI,CAAC,KAAK,EAAE;QACvB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC5B,MAAM,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC;QAC3C,QAAQ,CAAC,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,CAAC;KAChD,EAAE,MAAM,CAAC,EAAE,WAAW;;;OAqBtB;IAEY,aAAa,CAAC,QAAQ,CAAC,EAAE,gBAAgB,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,WAAW,0BAWlF;IAEY,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,wBAMjD;IAEY,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,oCAOlE;IAEY,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,WAAW,wBAQzD;IAEM,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,WAAW,wBAW/D;IAEM,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,wBAE9C;IAEM,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,wBAE9C;IAEY,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,iBASnD;IAED,OAAO,CAAC,UAAU;IAgBlB,OAAO,CAAC,OAAO;CAShB"}
@@ -0,0 +1,125 @@
1
+ import { Equal, IsNull, LessThan } from 'typeorm';
2
+ import { BlogConflictError, BlogCursorError, BlogNotFoundError } from '../blog/errors.js';
3
+ import { BlogPageEntity } from './entities.js';
4
+ export class PageStore {
5
+ dataSource;
6
+ clock;
7
+ constructor(dataSource, clock = () => new Date()) {
8
+ this.dataSource = dataSource;
9
+ this.clock = clock;
10
+ }
11
+ async list(input, signal) {
12
+ signal?.throwIfAborted();
13
+ const base = this.filters(input);
14
+ const cursor = input.cursor
15
+ ? await this.dataSource.getRepository(BlogPageEntity).findOne({ where: { id: input.cursor, ...base } })
16
+ : undefined;
17
+ signal?.throwIfAborted();
18
+ if (input.cursor && !cursor)
19
+ throw new BlogCursorError('Page cursor not found in current filter');
20
+ const where = cursor
21
+ ? [
22
+ { ...base, createdAt: LessThan(cursor.createdAt) },
23
+ { ...base, createdAt: Equal(cursor.createdAt), id: LessThan(cursor.id) },
24
+ ]
25
+ : base;
26
+ const pages = await this.dataSource.getRepository(BlogPageEntity).find({
27
+ where, order: { createdAt: 'DESC', id: 'DESC' }, take: input.limit + 1,
28
+ });
29
+ signal?.throwIfAborted();
30
+ const hasMore = pages.length > input.limit;
31
+ const items = hasMore ? pages.slice(0, input.limit) : pages;
32
+ return { items, nextCursor: hasMore ? items.at(-1)?.id ?? null : null };
33
+ }
34
+ async listPublished(position, signal) {
35
+ signal?.throwIfAborted();
36
+ const where = {
37
+ status: 'published',
38
+ ...(position === undefined ? {} : { position: position ?? IsNull() }),
39
+ };
40
+ const pages = await this.dataSource.getRepository(BlogPageEntity).find({
41
+ where, order: { sortOrder: 'ASC', id: 'ASC' }, take: 500,
42
+ });
43
+ signal?.throwIfAborted();
44
+ return pages;
45
+ }
46
+ async read(id, signal) {
47
+ signal?.throwIfAborted();
48
+ const page = await this.dataSource.getRepository(BlogPageEntity).findOneBy({ id });
49
+ signal?.throwIfAborted();
50
+ if (!page)
51
+ throw new BlogNotFoundError('Page not found');
52
+ return page;
53
+ }
54
+ async readPublishedBySlug(slug, signal) {
55
+ signal?.throwIfAborted();
56
+ const page = await this.dataSource.getRepository(BlogPageEntity).findOneBy({
57
+ slug, status: 'published',
58
+ });
59
+ signal?.throwIfAborted();
60
+ return page ?? undefined;
61
+ }
62
+ async create(input, signal) {
63
+ signal?.throwIfAborted();
64
+ const repository = this.dataSource.getRepository(BlogPageEntity);
65
+ const page = await repository.save(repository.create({
66
+ ...input, status: 'draft', publishedAt: null,
67
+ }));
68
+ signal?.throwIfAborted();
69
+ return page;
70
+ }
71
+ update(id, input, signal) {
72
+ signal?.throwIfAborted();
73
+ return this.dataSource.transaction(async (manager) => {
74
+ const repository = manager.getRepository(BlogPageEntity);
75
+ const current = await repository.findOne({ where: { id }, lock: { mode: 'pessimistic_write' } });
76
+ signal?.throwIfAborted();
77
+ if (!current)
78
+ throw new BlogNotFoundError('Page not found');
79
+ await repository.update({ id }, input);
80
+ signal?.throwIfAborted();
81
+ return repository.findOneByOrFail({ id });
82
+ });
83
+ }
84
+ publish(id, signal) {
85
+ return this.transition(id, 'published', signal);
86
+ }
87
+ archive(id, signal) {
88
+ return this.transition(id, 'archived', signal);
89
+ }
90
+ async delete(id, signal) {
91
+ signal?.throwIfAborted();
92
+ const repository = this.dataSource.getRepository(BlogPageEntity);
93
+ const page = await repository.findOneBy({ id });
94
+ signal?.throwIfAborted();
95
+ if (!page)
96
+ throw new BlogNotFoundError('Page not found');
97
+ if (page.status === 'published')
98
+ throw new BlogConflictError('Published page must be archived before deletion');
99
+ await repository.delete({ id });
100
+ signal?.throwIfAborted();
101
+ }
102
+ transition(id, status, signal) {
103
+ signal?.throwIfAborted();
104
+ return this.dataSource.transaction(async (manager) => {
105
+ const repository = manager.getRepository(BlogPageEntity);
106
+ const page = await repository.findOne({ where: { id }, lock: { mode: 'pessimistic_write' } });
107
+ signal?.throwIfAborted();
108
+ if (!page)
109
+ throw new BlogNotFoundError('Page not found');
110
+ await repository.update({ id }, {
111
+ status,
112
+ ...(status === 'published' && page.status !== 'published' ? { publishedAt: this.clock() } : {}),
113
+ });
114
+ signal?.throwIfAborted();
115
+ return repository.findOneByOrFail({ id });
116
+ });
117
+ }
118
+ filters(input) {
119
+ return {
120
+ ...(input.status ? { status: input.status } : {}),
121
+ ...(input.position === undefined ? {} : { position: input.position ?? IsNull() }),
122
+ };
123
+ }
124
+ }
125
+ //# sourceMappingURL=page-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-store.js","sourceRoot":"","sources":["../../src/persistence/page-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAA0C,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC1F,OAAO,EAAE,cAAc,EAA2C,MAAM,eAAe,CAAC;AAWxF,MAAM,OAAO,SAAS;IAED,UAAU;IACV,KAAK;IAFxB,YACmB,UAAsB,EACtB,KAAK,GAAG,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE;0BADxB,UAAU;qBACV,KAAK;IACrB,CAAC;IAEG,KAAK,CAAC,IAAI,CAAC,KAKjB,EAAE,MAAoB;QACrB,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;YACzB,CAAC,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC;YACvG,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,eAAe,CAAC,yCAAyC,CAAC,CAAC;QAClG,MAAM,KAAK,GAAoE,MAAM;YACnF,CAAC,CAAC;gBACE,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE;gBAClD,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;aACzE;YACH,CAAC,CAAC,IAAI,CAAC;QACT,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC;YACrE,KAAK,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC;SACvE,CAAC,CAAC;QACH,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;QAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC5D,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1E,CAAC;IAEM,KAAK,CAAC,aAAa,CAAC,QAAkC,EAAE,MAAoB;QACjF,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,MAAM,KAAK,GAAkC;YAC3C,MAAM,EAAE,WAAW;YACnB,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,IAAI,MAAM,EAAE,EAAE,CAAC;SACtE,CAAC;QACF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC;YACrE,KAAK,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG;SACzD,CAAC,CAAC;QACH,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,EAAU,EAAE,MAAoB;QAChD,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACnF,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,mBAAmB,CAAC,IAAY,EAAE,MAAoB;QACjE,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,SAAS,CAAC;YACzE,IAAI,EAAE,MAAM,EAAE,WAAW;SAC1B,CAAC,CAAC;QACH,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,OAAO,IAAI,IAAI,SAAS,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,KAAgB,EAAE,MAAoB;QACxD,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;YACnD,GAAG,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI;SAC7C,CAAC,CAAC,CAAC;QACJ,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,MAAM,CAAC,EAAU,EAAE,KAAgB,EAAE,MAAoB;QAC9D,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YACnD,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;YACzD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,CAAC,CAAC;YACjG,MAAM,EAAE,cAAc,EAAE,CAAC;YACzB,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;YAC5D,MAAM,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;YACvC,MAAM,EAAE,cAAc,EAAE,CAAC;YACzB,OAAO,UAAU,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,OAAO,CAAC,EAAU,EAAE,MAAoB;QAC7C,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IAClD,CAAC;IAEM,OAAO,CAAC,EAAU,EAAE,MAAoB;QAC7C,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IACjD,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,MAAoB;QAClD,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAChD,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;QACzD,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW;YAAE,MAAM,IAAI,iBAAiB,CAAC,iDAAiD,CAAC,CAAC;QAChH,MAAM,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAChC,MAAM,EAAE,cAAc,EAAE,CAAC;IAC3B,CAAC;IAEO,UAAU,CAAC,EAAU,EAAE,MAAgC,EAAE,MAAoB;QACnF,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YACnD,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;YACzD,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,CAAC,CAAC;YAC9F,MAAM,EAAE,cAAc,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;YACzD,MAAM,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE;gBAC9B,MAAM;gBACN,GAAG,CAAC,MAAM,KAAK,WAAW,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChG,CAAC,CAAC;YACH,MAAM,EAAE,cAAc,EAAE,CAAC;YACzB,OAAO,UAAU,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,OAAO,CAAC,KAGf;QACC,OAAO;YACL,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,MAAM,EAAE,EAAE,CAAC;SAClF,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,23 @@
1
+ import { type DataSource } from 'typeorm';
2
+ export interface PostViewResult {
3
+ readonly counted: boolean;
4
+ readonly countedAt: Date;
5
+ readonly viewCount: number;
6
+ }
7
+ export interface PostEngagementResult {
8
+ readonly viewCount: number;
9
+ readonly likeCount: number;
10
+ readonly liked: boolean;
11
+ }
12
+ export declare class PostEngagementStore {
13
+ private readonly dataSource;
14
+ constructor(dataSource: DataSource);
15
+ recordView(postId: string, subjectHashes: readonly string[], now: Date, windowMs: number, signal?: AbortSignal): Promise<PostViewResult>;
16
+ read(postId: string, userId?: string, signal?: AbortSignal): Promise<PostEngagementResult>;
17
+ setLiked(postId: string, userId: string, liked: boolean, signal?: AbortSignal): Promise<{
18
+ liked: boolean;
19
+ likeCount: number;
20
+ }>;
21
+ private saveMarks;
22
+ }
23
+ //# sourceMappingURL=post-engagement-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-engagement-store.d.ts","sourceRoot":"","sources":["../../src/persistence/post-engagement-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,UAAU,EAAmB,MAAM,SAAS,CAAC;AAS/D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,qBAAa,mBAAmB;IACX,OAAO,CAAC,QAAQ,CAAC,UAAU;IAA9C,YAAoC,UAAU,EAAE,UAAU,EAAI;IAEvD,UAAU,CACf,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,GAAG,EAAE,IAAI,EACT,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,CAAC,CA4BzB;IAEY,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAYtG;IAEM,QAAQ,CACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAkBhD;IAED,OAAO,CAAC,SAAS;CAYlB"}