@btst/stack 1.2.2 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/packages/better-stack/src/plugins/blog/api/plugin.cjs +101 -120
- package/dist/packages/better-stack/src/plugins/blog/api/plugin.mjs +101 -120
- package/dist/packages/better-stack/src/plugins/blog/client/components/pages/post-page.internal.cjs +1 -1
- package/dist/packages/better-stack/src/plugins/blog/client/components/pages/post-page.internal.mjs +1 -1
- package/dist/packages/better-stack/src/plugins/blog/client/components/shared/on-this-page.cjs +1 -1
- package/dist/packages/better-stack/src/plugins/blog/client/components/shared/on-this-page.mjs +1 -1
- package/dist/packages/better-stack/src/plugins/blog/client/components/shared/recent-posts-carousel.cjs +2 -2
- package/dist/packages/better-stack/src/plugins/blog/client/components/shared/recent-posts-carousel.mjs +2 -2
- package/dist/packages/better-stack/src/plugins/blog/db.cjs +12 -2
- package/dist/packages/better-stack/src/plugins/blog/db.mjs +12 -2
- package/dist/plugins/blog/api/index.d.cts +1 -1
- package/dist/plugins/blog/api/index.d.mts +1 -1
- package/dist/plugins/blog/api/index.d.ts +1 -1
- package/dist/plugins/blog/client/hooks/index.d.cts +3 -3
- package/dist/plugins/blog/client/hooks/index.d.mts +3 -3
- package/dist/plugins/blog/client/hooks/index.d.ts +3 -3
- package/dist/plugins/blog/client/index.d.cts +1 -1
- package/dist/plugins/blog/client/index.d.mts +1 -1
- package/dist/plugins/blog/client/index.d.ts +1 -1
- package/dist/plugins/blog/query-keys.d.cts +6 -6
- package/dist/plugins/blog/query-keys.d.mts +6 -6
- package/dist/plugins/blog/query-keys.d.ts +6 -6
- package/package.json +3 -3
- package/src/plugins/blog/api/plugin.ts +122 -147
- package/src/plugins/blog/client/components/pages/post-page.internal.tsx +1 -1
- package/src/plugins/blog/client/components/shared/on-this-page.tsx +1 -1
- package/src/plugins/blog/client/components/shared/recent-posts-carousel.tsx +2 -2
- package/src/plugins/blog/db.ts +10 -0
- package/src/plugins/blog/types.ts +7 -0
- package/dist/shared/{stack.Cr2JoQdo.d.cts → stack.CbuN2zVV.d.cts} +3 -3
- package/dist/shared/{stack.Cr2JoQdo.d.mts → stack.CbuN2zVV.d.mts} +3 -3
- package/dist/shared/{stack.Cr2JoQdo.d.ts → stack.CbuN2zVV.d.ts} +3 -3
|
@@ -26,53 +26,7 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
26
26
|
name: "blog",
|
|
27
27
|
dbPlugin: db.blogSchema,
|
|
28
28
|
routes: (adapter) => {
|
|
29
|
-
const
|
|
30
|
-
let cache = null;
|
|
31
|
-
return {
|
|
32
|
-
getAllTags: async () => {
|
|
33
|
-
if (!cache) {
|
|
34
|
-
cache = await adapter.findMany({
|
|
35
|
-
model: "tag"
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
return cache;
|
|
39
|
-
},
|
|
40
|
-
invalidate: () => {
|
|
41
|
-
cache = null;
|
|
42
|
-
},
|
|
43
|
-
addTag: (tag) => {
|
|
44
|
-
if (cache) {
|
|
45
|
-
cache.push(tag);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
};
|
|
50
|
-
const createPostTagCache = () => {
|
|
51
|
-
let cache = null;
|
|
52
|
-
const getAllPostTags = async () => {
|
|
53
|
-
if (!cache) {
|
|
54
|
-
cache = await adapter.findMany({
|
|
55
|
-
model: "postTag"
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
return cache;
|
|
59
|
-
};
|
|
60
|
-
return {
|
|
61
|
-
getAllPostTags,
|
|
62
|
-
invalidate: () => {
|
|
63
|
-
cache = null;
|
|
64
|
-
},
|
|
65
|
-
getByTagId: async (tagId) => {
|
|
66
|
-
const allPostTags = await getAllPostTags();
|
|
67
|
-
return allPostTags.filter((pt) => pt.tagId === tagId);
|
|
68
|
-
},
|
|
69
|
-
getByPostId: async (postId) => {
|
|
70
|
-
const allPostTags = await getAllPostTags();
|
|
71
|
-
return allPostTags.filter((pt) => pt.postId === postId);
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
};
|
|
75
|
-
const findOrCreateTags = async (tagInputs, tagCache) => {
|
|
29
|
+
const findOrCreateTags = async (tagInputs) => {
|
|
76
30
|
if (tagInputs.length === 0) return [];
|
|
77
31
|
const normalizeTagName = (name) => {
|
|
78
32
|
return name.trim();
|
|
@@ -95,7 +49,9 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
95
49
|
if (tagsToFindOrCreate.length === 0) {
|
|
96
50
|
return tagsWithIds;
|
|
97
51
|
}
|
|
98
|
-
const allTags = await
|
|
52
|
+
const allTags = await adapter.findMany({
|
|
53
|
+
model: "tag"
|
|
54
|
+
});
|
|
99
55
|
const tagMapBySlug = /* @__PURE__ */ new Map();
|
|
100
56
|
for (const tag of allTags) {
|
|
101
57
|
tagMapBySlug.set(tag.slug, tag);
|
|
@@ -128,33 +84,9 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
128
84
|
}
|
|
129
85
|
});
|
|
130
86
|
createdTags.push(newTag);
|
|
131
|
-
tagCache.addTag(newTag);
|
|
132
87
|
}
|
|
133
88
|
return [...tagsWithIds, ...foundTags, ...createdTags];
|
|
134
89
|
};
|
|
135
|
-
const loadTagsForPosts = async (postIds, tagCache, postTagCache) => {
|
|
136
|
-
if (postIds.length === 0) return /* @__PURE__ */ new Map();
|
|
137
|
-
const allPostTags = await postTagCache.getAllPostTags();
|
|
138
|
-
const relevantPostTags = allPostTags.filter(
|
|
139
|
-
(pt) => postIds.includes(pt.postId)
|
|
140
|
-
);
|
|
141
|
-
const tagIds = [...new Set(relevantPostTags.map((pt) => pt.tagId))];
|
|
142
|
-
if (tagIds.length === 0) return /* @__PURE__ */ new Map();
|
|
143
|
-
const allTags = await tagCache.getAllTags();
|
|
144
|
-
const tagMap = /* @__PURE__ */ new Map();
|
|
145
|
-
for (const tag of allTags) {
|
|
146
|
-
tagMap.set(tag.id, tag);
|
|
147
|
-
}
|
|
148
|
-
const postTagsMap = /* @__PURE__ */ new Map();
|
|
149
|
-
for (const postTag of relevantPostTags) {
|
|
150
|
-
const tag = tagMap.get(postTag.tagId);
|
|
151
|
-
if (tag) {
|
|
152
|
-
const existing = postTagsMap.get(postTag.postId) || [];
|
|
153
|
-
postTagsMap.set(postTag.postId, [...existing, { ...tag }]);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return postTagsMap;
|
|
157
|
-
};
|
|
158
90
|
const listPosts = api.createEndpoint(
|
|
159
91
|
"/posts",
|
|
160
92
|
{
|
|
@@ -164,8 +96,6 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
164
96
|
async (ctx) => {
|
|
165
97
|
const { query, headers } = ctx;
|
|
166
98
|
const context = { query, headers };
|
|
167
|
-
const tagCache = createTagCache();
|
|
168
|
-
const postTagCache = createPostTagCache();
|
|
169
99
|
try {
|
|
170
100
|
if (hooks?.onBeforeListPosts) {
|
|
171
101
|
const canList = await hooks.onBeforeListPosts(query, context);
|
|
@@ -177,12 +107,29 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
177
107
|
}
|
|
178
108
|
let tagFilterPostIds = null;
|
|
179
109
|
if (query.tagSlug) {
|
|
180
|
-
const
|
|
181
|
-
|
|
110
|
+
const tag = await adapter.findOne({
|
|
111
|
+
model: "tag",
|
|
112
|
+
where: [
|
|
113
|
+
{
|
|
114
|
+
field: "slug",
|
|
115
|
+
value: query.tagSlug,
|
|
116
|
+
operator: "eq"
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
});
|
|
182
120
|
if (!tag) {
|
|
183
121
|
return [];
|
|
184
122
|
}
|
|
185
|
-
const postTags = await
|
|
123
|
+
const postTags = await adapter.findMany({
|
|
124
|
+
model: "postTag",
|
|
125
|
+
where: [
|
|
126
|
+
{
|
|
127
|
+
field: "tagId",
|
|
128
|
+
value: tag.id,
|
|
129
|
+
operator: "eq"
|
|
130
|
+
}
|
|
131
|
+
]
|
|
132
|
+
});
|
|
186
133
|
tagFilterPostIds = new Set(postTags.map((pt) => pt.postId));
|
|
187
134
|
if (tagFilterPostIds.size === 0) {
|
|
188
135
|
return [];
|
|
@@ -211,17 +158,39 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
211
158
|
sortBy: {
|
|
212
159
|
field: "createdAt",
|
|
213
160
|
direction: "desc"
|
|
161
|
+
},
|
|
162
|
+
join: {
|
|
163
|
+
postTag: true
|
|
214
164
|
}
|
|
215
165
|
});
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
166
|
+
const tagIds = /* @__PURE__ */ new Set();
|
|
167
|
+
for (const post of posts) {
|
|
168
|
+
if (post.postTag) {
|
|
169
|
+
for (const pt of post.postTag) {
|
|
170
|
+
tagIds.add(pt.tagId);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const tags = tagIds.size > 0 ? await adapter.findMany({
|
|
175
|
+
model: "tag"
|
|
176
|
+
}) : [];
|
|
177
|
+
const tagMap = /* @__PURE__ */ new Map();
|
|
178
|
+
for (const tag of tags) {
|
|
179
|
+
if (tagIds.has(tag.id)) {
|
|
180
|
+
tagMap.set(tag.id, tag);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
let result = posts.map((post) => {
|
|
184
|
+
const postTags = (post.postTag || []).map((pt) => {
|
|
185
|
+
const tag = tagMap.get(pt.tagId);
|
|
186
|
+
return tag ? { ...tag } : void 0;
|
|
187
|
+
}).filter((tag) => tag !== void 0);
|
|
188
|
+
const { postTag: _, ...postWithoutJoin } = post;
|
|
189
|
+
return {
|
|
190
|
+
...postWithoutJoin,
|
|
191
|
+
tags: postTags
|
|
192
|
+
};
|
|
193
|
+
});
|
|
225
194
|
if (tagFilterPostIds) {
|
|
226
195
|
result = result.filter((post) => tagFilterPostIds.has(post.id));
|
|
227
196
|
}
|
|
@@ -262,7 +231,6 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
262
231
|
body: ctx.body,
|
|
263
232
|
headers: ctx.headers
|
|
264
233
|
};
|
|
265
|
-
const tagCache = createTagCache();
|
|
266
234
|
try {
|
|
267
235
|
if (hooks?.onBeforeCreatePost) {
|
|
268
236
|
const canCreate = await hooks.onBeforeCreatePost(
|
|
@@ -288,7 +256,7 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
288
256
|
}
|
|
289
257
|
});
|
|
290
258
|
if (tagNames.length > 0) {
|
|
291
|
-
const createdTags = await findOrCreateTags(tagNames
|
|
259
|
+
const createdTags = await findOrCreateTags(tagNames);
|
|
292
260
|
await adapter.transaction(async (tx) => {
|
|
293
261
|
for (const tag of createdTags) {
|
|
294
262
|
await tx.create({
|
|
@@ -328,7 +296,6 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
328
296
|
params: ctx.params,
|
|
329
297
|
headers: ctx.headers
|
|
330
298
|
};
|
|
331
|
-
const tagCache = createTagCache();
|
|
332
299
|
try {
|
|
333
300
|
if (hooks?.onBeforeUpdatePost) {
|
|
334
301
|
const canUpdate = await hooks.onBeforeUpdatePost(
|
|
@@ -386,7 +353,7 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
386
353
|
});
|
|
387
354
|
}
|
|
388
355
|
if (tagNames.length > 0) {
|
|
389
|
-
const createdTags = await findOrCreateTags(tagNames
|
|
356
|
+
const createdTags = await findOrCreateTags(tagNames);
|
|
390
357
|
for (const tag of createdTags) {
|
|
391
358
|
await tx.create({
|
|
392
359
|
model: "postTag",
|
|
@@ -436,15 +403,9 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
436
403
|
});
|
|
437
404
|
}
|
|
438
405
|
}
|
|
439
|
-
await adapter.
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
where: [{ field: "postId", value: ctx.params.id }]
|
|
443
|
-
});
|
|
444
|
-
await tx.delete({
|
|
445
|
-
model: "post",
|
|
446
|
-
where: [{ field: "id", value: ctx.params.id }]
|
|
447
|
-
});
|
|
406
|
+
await adapter.delete({
|
|
407
|
+
model: "post",
|
|
408
|
+
where: [{ field: "id", value: ctx.params.id }]
|
|
448
409
|
});
|
|
449
410
|
if (hooks?.onPostDeleted) {
|
|
450
411
|
await hooks.onPostDeleted(ctx.params.id, context);
|
|
@@ -467,8 +428,6 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
467
428
|
async (ctx) => {
|
|
468
429
|
const { query, headers } = ctx;
|
|
469
430
|
const context = { query, headers };
|
|
470
|
-
const tagCache = createTagCache();
|
|
471
|
-
const postTagCache = createPostTagCache();
|
|
472
431
|
try {
|
|
473
432
|
if (hooks?.onBeforeListPosts) {
|
|
474
433
|
const canList = await hooks.onBeforeListPosts(
|
|
@@ -482,7 +441,7 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
482
441
|
}
|
|
483
442
|
}
|
|
484
443
|
const date = query.date;
|
|
485
|
-
const
|
|
444
|
+
const previousPosts = await adapter.findMany({
|
|
486
445
|
model: "post",
|
|
487
446
|
limit: 1,
|
|
488
447
|
where: [
|
|
@@ -500,9 +459,12 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
500
459
|
sortBy: {
|
|
501
460
|
field: "createdAt",
|
|
502
461
|
direction: "desc"
|
|
462
|
+
},
|
|
463
|
+
join: {
|
|
464
|
+
postTag: true
|
|
503
465
|
}
|
|
504
466
|
});
|
|
505
|
-
const
|
|
467
|
+
const nextPosts = await adapter.findMany({
|
|
506
468
|
model: "post",
|
|
507
469
|
limit: 1,
|
|
508
470
|
where: [
|
|
@@ -520,26 +482,45 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
520
482
|
sortBy: {
|
|
521
483
|
field: "createdAt",
|
|
522
484
|
direction: "asc"
|
|
485
|
+
},
|
|
486
|
+
join: {
|
|
487
|
+
postTag: true
|
|
523
488
|
}
|
|
524
489
|
});
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
490
|
+
const tagIds = /* @__PURE__ */ new Set();
|
|
491
|
+
const allPosts = [...previousPosts, ...nextPosts];
|
|
492
|
+
for (const post of allPosts) {
|
|
493
|
+
if (post.postTag) {
|
|
494
|
+
for (const pt of post.postTag) {
|
|
495
|
+
tagIds.add(pt.tagId);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
const tagMap = /* @__PURE__ */ new Map();
|
|
500
|
+
if (tagIds.size > 0) {
|
|
501
|
+
const tags = await adapter.findMany({
|
|
502
|
+
model: "tag"
|
|
503
|
+
});
|
|
504
|
+
for (const tag of tags) {
|
|
505
|
+
if (tagIds.has(tag.id)) {
|
|
506
|
+
tagMap.set(tag.id, tag);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
const mapPostWithTags = (post) => {
|
|
511
|
+
const tags = (post.postTag || []).map((pt) => {
|
|
512
|
+
const tag = tagMap.get(pt.tagId);
|
|
513
|
+
return tag ? { ...tag } : void 0;
|
|
514
|
+
}).filter((tag) => tag !== void 0);
|
|
515
|
+
const { postTag: _, ...postWithoutJoin } = post;
|
|
516
|
+
return {
|
|
517
|
+
...postWithoutJoin,
|
|
518
|
+
tags
|
|
519
|
+
};
|
|
520
|
+
};
|
|
534
521
|
return {
|
|
535
|
-
previous:
|
|
536
|
-
|
|
537
|
-
tags: postTagsMap.get(previousPost[0].id) || []
|
|
538
|
-
} : null,
|
|
539
|
-
next: nextPost?.[0] ? {
|
|
540
|
-
...nextPost[0],
|
|
541
|
-
tags: postTagsMap.get(nextPost[0].id) || []
|
|
542
|
-
} : null
|
|
522
|
+
previous: previousPosts[0] ? mapPostWithTags(previousPosts[0]) : null,
|
|
523
|
+
next: nextPosts[0] ? mapPostWithTags(nextPosts[0]) : null
|
|
543
524
|
};
|
|
544
525
|
} catch (error) {
|
|
545
526
|
if (hooks?.onListPostsError) {
|
|
@@ -24,53 +24,7 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
24
24
|
name: "blog",
|
|
25
25
|
dbPlugin: blogSchema,
|
|
26
26
|
routes: (adapter) => {
|
|
27
|
-
const
|
|
28
|
-
let cache = null;
|
|
29
|
-
return {
|
|
30
|
-
getAllTags: async () => {
|
|
31
|
-
if (!cache) {
|
|
32
|
-
cache = await adapter.findMany({
|
|
33
|
-
model: "tag"
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
return cache;
|
|
37
|
-
},
|
|
38
|
-
invalidate: () => {
|
|
39
|
-
cache = null;
|
|
40
|
-
},
|
|
41
|
-
addTag: (tag) => {
|
|
42
|
-
if (cache) {
|
|
43
|
-
cache.push(tag);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
};
|
|
48
|
-
const createPostTagCache = () => {
|
|
49
|
-
let cache = null;
|
|
50
|
-
const getAllPostTags = async () => {
|
|
51
|
-
if (!cache) {
|
|
52
|
-
cache = await adapter.findMany({
|
|
53
|
-
model: "postTag"
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
return cache;
|
|
57
|
-
};
|
|
58
|
-
return {
|
|
59
|
-
getAllPostTags,
|
|
60
|
-
invalidate: () => {
|
|
61
|
-
cache = null;
|
|
62
|
-
},
|
|
63
|
-
getByTagId: async (tagId) => {
|
|
64
|
-
const allPostTags = await getAllPostTags();
|
|
65
|
-
return allPostTags.filter((pt) => pt.tagId === tagId);
|
|
66
|
-
},
|
|
67
|
-
getByPostId: async (postId) => {
|
|
68
|
-
const allPostTags = await getAllPostTags();
|
|
69
|
-
return allPostTags.filter((pt) => pt.postId === postId);
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
};
|
|
73
|
-
const findOrCreateTags = async (tagInputs, tagCache) => {
|
|
27
|
+
const findOrCreateTags = async (tagInputs) => {
|
|
74
28
|
if (tagInputs.length === 0) return [];
|
|
75
29
|
const normalizeTagName = (name) => {
|
|
76
30
|
return name.trim();
|
|
@@ -93,7 +47,9 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
93
47
|
if (tagsToFindOrCreate.length === 0) {
|
|
94
48
|
return tagsWithIds;
|
|
95
49
|
}
|
|
96
|
-
const allTags = await
|
|
50
|
+
const allTags = await adapter.findMany({
|
|
51
|
+
model: "tag"
|
|
52
|
+
});
|
|
97
53
|
const tagMapBySlug = /* @__PURE__ */ new Map();
|
|
98
54
|
for (const tag of allTags) {
|
|
99
55
|
tagMapBySlug.set(tag.slug, tag);
|
|
@@ -126,33 +82,9 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
126
82
|
}
|
|
127
83
|
});
|
|
128
84
|
createdTags.push(newTag);
|
|
129
|
-
tagCache.addTag(newTag);
|
|
130
85
|
}
|
|
131
86
|
return [...tagsWithIds, ...foundTags, ...createdTags];
|
|
132
87
|
};
|
|
133
|
-
const loadTagsForPosts = async (postIds, tagCache, postTagCache) => {
|
|
134
|
-
if (postIds.length === 0) return /* @__PURE__ */ new Map();
|
|
135
|
-
const allPostTags = await postTagCache.getAllPostTags();
|
|
136
|
-
const relevantPostTags = allPostTags.filter(
|
|
137
|
-
(pt) => postIds.includes(pt.postId)
|
|
138
|
-
);
|
|
139
|
-
const tagIds = [...new Set(relevantPostTags.map((pt) => pt.tagId))];
|
|
140
|
-
if (tagIds.length === 0) return /* @__PURE__ */ new Map();
|
|
141
|
-
const allTags = await tagCache.getAllTags();
|
|
142
|
-
const tagMap = /* @__PURE__ */ new Map();
|
|
143
|
-
for (const tag of allTags) {
|
|
144
|
-
tagMap.set(tag.id, tag);
|
|
145
|
-
}
|
|
146
|
-
const postTagsMap = /* @__PURE__ */ new Map();
|
|
147
|
-
for (const postTag of relevantPostTags) {
|
|
148
|
-
const tag = tagMap.get(postTag.tagId);
|
|
149
|
-
if (tag) {
|
|
150
|
-
const existing = postTagsMap.get(postTag.postId) || [];
|
|
151
|
-
postTagsMap.set(postTag.postId, [...existing, { ...tag }]);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return postTagsMap;
|
|
155
|
-
};
|
|
156
88
|
const listPosts = createEndpoint(
|
|
157
89
|
"/posts",
|
|
158
90
|
{
|
|
@@ -162,8 +94,6 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
162
94
|
async (ctx) => {
|
|
163
95
|
const { query, headers } = ctx;
|
|
164
96
|
const context = { query, headers };
|
|
165
|
-
const tagCache = createTagCache();
|
|
166
|
-
const postTagCache = createPostTagCache();
|
|
167
97
|
try {
|
|
168
98
|
if (hooks?.onBeforeListPosts) {
|
|
169
99
|
const canList = await hooks.onBeforeListPosts(query, context);
|
|
@@ -175,12 +105,29 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
175
105
|
}
|
|
176
106
|
let tagFilterPostIds = null;
|
|
177
107
|
if (query.tagSlug) {
|
|
178
|
-
const
|
|
179
|
-
|
|
108
|
+
const tag = await adapter.findOne({
|
|
109
|
+
model: "tag",
|
|
110
|
+
where: [
|
|
111
|
+
{
|
|
112
|
+
field: "slug",
|
|
113
|
+
value: query.tagSlug,
|
|
114
|
+
operator: "eq"
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
});
|
|
180
118
|
if (!tag) {
|
|
181
119
|
return [];
|
|
182
120
|
}
|
|
183
|
-
const postTags = await
|
|
121
|
+
const postTags = await adapter.findMany({
|
|
122
|
+
model: "postTag",
|
|
123
|
+
where: [
|
|
124
|
+
{
|
|
125
|
+
field: "tagId",
|
|
126
|
+
value: tag.id,
|
|
127
|
+
operator: "eq"
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
});
|
|
184
131
|
tagFilterPostIds = new Set(postTags.map((pt) => pt.postId));
|
|
185
132
|
if (tagFilterPostIds.size === 0) {
|
|
186
133
|
return [];
|
|
@@ -209,17 +156,39 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
209
156
|
sortBy: {
|
|
210
157
|
field: "createdAt",
|
|
211
158
|
direction: "desc"
|
|
159
|
+
},
|
|
160
|
+
join: {
|
|
161
|
+
postTag: true
|
|
212
162
|
}
|
|
213
163
|
});
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
164
|
+
const tagIds = /* @__PURE__ */ new Set();
|
|
165
|
+
for (const post of posts) {
|
|
166
|
+
if (post.postTag) {
|
|
167
|
+
for (const pt of post.postTag) {
|
|
168
|
+
tagIds.add(pt.tagId);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const tags = tagIds.size > 0 ? await adapter.findMany({
|
|
173
|
+
model: "tag"
|
|
174
|
+
}) : [];
|
|
175
|
+
const tagMap = /* @__PURE__ */ new Map();
|
|
176
|
+
for (const tag of tags) {
|
|
177
|
+
if (tagIds.has(tag.id)) {
|
|
178
|
+
tagMap.set(tag.id, tag);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
let result = posts.map((post) => {
|
|
182
|
+
const postTags = (post.postTag || []).map((pt) => {
|
|
183
|
+
const tag = tagMap.get(pt.tagId);
|
|
184
|
+
return tag ? { ...tag } : void 0;
|
|
185
|
+
}).filter((tag) => tag !== void 0);
|
|
186
|
+
const { postTag: _, ...postWithoutJoin } = post;
|
|
187
|
+
return {
|
|
188
|
+
...postWithoutJoin,
|
|
189
|
+
tags: postTags
|
|
190
|
+
};
|
|
191
|
+
});
|
|
223
192
|
if (tagFilterPostIds) {
|
|
224
193
|
result = result.filter((post) => tagFilterPostIds.has(post.id));
|
|
225
194
|
}
|
|
@@ -260,7 +229,6 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
260
229
|
body: ctx.body,
|
|
261
230
|
headers: ctx.headers
|
|
262
231
|
};
|
|
263
|
-
const tagCache = createTagCache();
|
|
264
232
|
try {
|
|
265
233
|
if (hooks?.onBeforeCreatePost) {
|
|
266
234
|
const canCreate = await hooks.onBeforeCreatePost(
|
|
@@ -286,7 +254,7 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
286
254
|
}
|
|
287
255
|
});
|
|
288
256
|
if (tagNames.length > 0) {
|
|
289
|
-
const createdTags = await findOrCreateTags(tagNames
|
|
257
|
+
const createdTags = await findOrCreateTags(tagNames);
|
|
290
258
|
await adapter.transaction(async (tx) => {
|
|
291
259
|
for (const tag of createdTags) {
|
|
292
260
|
await tx.create({
|
|
@@ -326,7 +294,6 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
326
294
|
params: ctx.params,
|
|
327
295
|
headers: ctx.headers
|
|
328
296
|
};
|
|
329
|
-
const tagCache = createTagCache();
|
|
330
297
|
try {
|
|
331
298
|
if (hooks?.onBeforeUpdatePost) {
|
|
332
299
|
const canUpdate = await hooks.onBeforeUpdatePost(
|
|
@@ -384,7 +351,7 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
384
351
|
});
|
|
385
352
|
}
|
|
386
353
|
if (tagNames.length > 0) {
|
|
387
|
-
const createdTags = await findOrCreateTags(tagNames
|
|
354
|
+
const createdTags = await findOrCreateTags(tagNames);
|
|
388
355
|
for (const tag of createdTags) {
|
|
389
356
|
await tx.create({
|
|
390
357
|
model: "postTag",
|
|
@@ -434,15 +401,9 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
434
401
|
});
|
|
435
402
|
}
|
|
436
403
|
}
|
|
437
|
-
await adapter.
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
where: [{ field: "postId", value: ctx.params.id }]
|
|
441
|
-
});
|
|
442
|
-
await tx.delete({
|
|
443
|
-
model: "post",
|
|
444
|
-
where: [{ field: "id", value: ctx.params.id }]
|
|
445
|
-
});
|
|
404
|
+
await adapter.delete({
|
|
405
|
+
model: "post",
|
|
406
|
+
where: [{ field: "id", value: ctx.params.id }]
|
|
446
407
|
});
|
|
447
408
|
if (hooks?.onPostDeleted) {
|
|
448
409
|
await hooks.onPostDeleted(ctx.params.id, context);
|
|
@@ -465,8 +426,6 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
465
426
|
async (ctx) => {
|
|
466
427
|
const { query, headers } = ctx;
|
|
467
428
|
const context = { query, headers };
|
|
468
|
-
const tagCache = createTagCache();
|
|
469
|
-
const postTagCache = createPostTagCache();
|
|
470
429
|
try {
|
|
471
430
|
if (hooks?.onBeforeListPosts) {
|
|
472
431
|
const canList = await hooks.onBeforeListPosts(
|
|
@@ -480,7 +439,7 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
480
439
|
}
|
|
481
440
|
}
|
|
482
441
|
const date = query.date;
|
|
483
|
-
const
|
|
442
|
+
const previousPosts = await adapter.findMany({
|
|
484
443
|
model: "post",
|
|
485
444
|
limit: 1,
|
|
486
445
|
where: [
|
|
@@ -498,9 +457,12 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
498
457
|
sortBy: {
|
|
499
458
|
field: "createdAt",
|
|
500
459
|
direction: "desc"
|
|
460
|
+
},
|
|
461
|
+
join: {
|
|
462
|
+
postTag: true
|
|
501
463
|
}
|
|
502
464
|
});
|
|
503
|
-
const
|
|
465
|
+
const nextPosts = await adapter.findMany({
|
|
504
466
|
model: "post",
|
|
505
467
|
limit: 1,
|
|
506
468
|
where: [
|
|
@@ -518,26 +480,45 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
518
480
|
sortBy: {
|
|
519
481
|
field: "createdAt",
|
|
520
482
|
direction: "asc"
|
|
483
|
+
},
|
|
484
|
+
join: {
|
|
485
|
+
postTag: true
|
|
521
486
|
}
|
|
522
487
|
});
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
488
|
+
const tagIds = /* @__PURE__ */ new Set();
|
|
489
|
+
const allPosts = [...previousPosts, ...nextPosts];
|
|
490
|
+
for (const post of allPosts) {
|
|
491
|
+
if (post.postTag) {
|
|
492
|
+
for (const pt of post.postTag) {
|
|
493
|
+
tagIds.add(pt.tagId);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
const tagMap = /* @__PURE__ */ new Map();
|
|
498
|
+
if (tagIds.size > 0) {
|
|
499
|
+
const tags = await adapter.findMany({
|
|
500
|
+
model: "tag"
|
|
501
|
+
});
|
|
502
|
+
for (const tag of tags) {
|
|
503
|
+
if (tagIds.has(tag.id)) {
|
|
504
|
+
tagMap.set(tag.id, tag);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
const mapPostWithTags = (post) => {
|
|
509
|
+
const tags = (post.postTag || []).map((pt) => {
|
|
510
|
+
const tag = tagMap.get(pt.tagId);
|
|
511
|
+
return tag ? { ...tag } : void 0;
|
|
512
|
+
}).filter((tag) => tag !== void 0);
|
|
513
|
+
const { postTag: _, ...postWithoutJoin } = post;
|
|
514
|
+
return {
|
|
515
|
+
...postWithoutJoin,
|
|
516
|
+
tags
|
|
517
|
+
};
|
|
518
|
+
};
|
|
532
519
|
return {
|
|
533
|
-
previous:
|
|
534
|
-
|
|
535
|
-
tags: postTagsMap.get(previousPost[0].id) || []
|
|
536
|
-
} : null,
|
|
537
|
-
next: nextPost?.[0] ? {
|
|
538
|
-
...nextPost[0],
|
|
539
|
-
tags: postTagsMap.get(nextPost[0].id) || []
|
|
540
|
-
} : null
|
|
520
|
+
previous: previousPosts[0] ? mapPostWithTags(previousPosts[0]) : null,
|
|
521
|
+
next: nextPosts[0] ? mapPostWithTags(nextPosts[0]) : null
|
|
541
522
|
};
|
|
542
523
|
} catch (error) {
|
|
543
524
|
if (hooks?.onListPostsError) {
|
package/dist/packages/better-stack/src/plugins/blog/client/components/pages/post-page.internal.cjs
CHANGED
|
@@ -51,7 +51,7 @@ function PostPage({ slug }) {
|
|
|
51
51
|
if (!slug || !post) {
|
|
52
52
|
return /* @__PURE__ */ jsxRuntime.jsx(pageWrapper.PageWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(emptyList.EmptyList, { message: localization.BLOG_PAGE_NOT_FOUND_DESCRIPTION }) });
|
|
53
53
|
}
|
|
54
|
-
return /* @__PURE__ */ jsxRuntime.jsx(pageWrapper.PageWrapper, { className: "gap-0 px-4 lg:px-
|
|
54
|
+
return /* @__PURE__ */ jsxRuntime.jsx(pageWrapper.PageWrapper, { className: "gap-0 px-4 lg:px-2 py-0 pb-18", testId: "post-page", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start w-full", children: [
|
|
55
55
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-44 shrink-0 hidden xl:flex mr-auto" }),
|
|
56
56
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center flex-1 mx-auto w-full max-w-4xl min-w-0", children: [
|
|
57
57
|
/* @__PURE__ */ jsxRuntime.jsx(onThisPage.OnThisPageSelect, { markdown: post.content }),
|
package/dist/packages/better-stack/src/plugins/blog/client/components/pages/post-page.internal.mjs
CHANGED
|
@@ -49,7 +49,7 @@ function PostPage({ slug }) {
|
|
|
49
49
|
if (!slug || !post) {
|
|
50
50
|
return /* @__PURE__ */ jsx(PageWrapper, { children: /* @__PURE__ */ jsx(EmptyList, { message: localization.BLOG_PAGE_NOT_FOUND_DESCRIPTION }) });
|
|
51
51
|
}
|
|
52
|
-
return /* @__PURE__ */ jsx(PageWrapper, { className: "gap-0 px-4 lg:px-
|
|
52
|
+
return /* @__PURE__ */ jsx(PageWrapper, { className: "gap-0 px-4 lg:px-2 py-0 pb-18", testId: "post-page", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start w-full", children: [
|
|
53
53
|
/* @__PURE__ */ jsx("div", { className: "w-44 shrink-0 hidden xl:flex mr-auto" }),
|
|
54
54
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center flex-1 mx-auto w-full max-w-4xl min-w-0", children: [
|
|
55
55
|
/* @__PURE__ */ jsx(OnThisPageSelect, { markdown: post.content }),
|