@we8/cms 0.1.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.
- package/README.md +78 -0
- package/dist/auth/auth.d.ts +87 -0
- package/dist/auth/auth.d.ts.map +1 -0
- package/dist/auth/auth.js +90 -0
- package/dist/auth/auth.js.map +1 -0
- package/dist/auth/routes.admin.d.ts +22 -0
- package/dist/auth/routes.admin.d.ts.map +1 -0
- package/dist/auth/routes.admin.js +106 -0
- package/dist/auth/routes.admin.js.map +1 -0
- package/dist/auth/schema.d.ts +1395 -0
- package/dist/auth/schema.d.ts.map +1 -0
- package/dist/auth/schema.js +76 -0
- package/dist/auth/schema.js.map +1 -0
- package/dist/env.d.ts +64 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +48 -0
- package/dist/env.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +170 -0
- package/dist/index.js.map +1 -0
- package/dist/keys/middleware.d.ts +54 -0
- package/dist/keys/middleware.d.ts.map +1 -0
- package/dist/keys/middleware.js +84 -0
- package/dist/keys/middleware.js.map +1 -0
- package/dist/keys/routes.admin.d.ts +16 -0
- package/dist/keys/routes.admin.d.ts.map +1 -0
- package/dist/keys/routes.admin.js +34 -0
- package/dist/keys/routes.admin.js.map +1 -0
- package/dist/keys/service.d.ts +36 -0
- package/dist/keys/service.d.ts.map +1 -0
- package/dist/keys/service.js +120 -0
- package/dist/keys/service.js.map +1 -0
- package/dist/lib/bots.d.ts +24 -0
- package/dist/lib/bots.d.ts.map +1 -0
- package/dist/lib/bots.js +79 -0
- package/dist/lib/bots.js.map +1 -0
- package/dist/lib/email.d.ts +62 -0
- package/dist/lib/email.d.ts.map +1 -0
- package/dist/lib/email.js +64 -0
- package/dist/lib/email.js.map +1 -0
- package/dist/lib/errors.d.ts +12 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +23 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/notify.d.ts +20 -0
- package/dist/lib/notify.d.ts.map +1 -0
- package/dist/lib/notify.js +60 -0
- package/dist/lib/notify.js.map +1 -0
- package/dist/lib/retention.d.ts +15 -0
- package/dist/lib/retention.d.ts.map +1 -0
- package/dist/lib/retention.js +40 -0
- package/dist/lib/retention.js.map +1 -0
- package/dist/lib/sanitize.d.ts +14 -0
- package/dist/lib/sanitize.d.ts.map +1 -0
- package/dist/lib/sanitize.js +145 -0
- package/dist/lib/sanitize.js.map +1 -0
- package/dist/lib/turnstile.d.ts +7 -0
- package/dist/lib/turnstile.d.ts.map +1 -0
- package/dist/lib/turnstile.js +32 -0
- package/dist/lib/turnstile.js.map +1 -0
- package/dist/lib/validate.d.ts +11 -0
- package/dist/lib/validate.d.ts.map +1 -0
- package/dist/lib/validate.js +22 -0
- package/dist/lib/validate.js.map +1 -0
- package/dist/lib/word-count.d.ts +7 -0
- package/dist/lib/word-count.d.ts.map +1 -0
- package/dist/lib/word-count.js +14 -0
- package/dist/lib/word-count.js.map +1 -0
- package/dist/middleware/auth.d.ts +46 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +60 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/cors.d.ts +33 -0
- package/dist/middleware/cors.d.ts.map +1 -0
- package/dist/middleware/cors.js +55 -0
- package/dist/middleware/cors.js.map +1 -0
- package/dist/middleware/module-gate.d.ts +11 -0
- package/dist/middleware/module-gate.d.ts.map +1 -0
- package/dist/middleware/module-gate.js +18 -0
- package/dist/middleware/module-gate.js.map +1 -0
- package/dist/middleware/rate-limit.d.ts +13 -0
- package/dist/middleware/rate-limit.d.ts.map +1 -0
- package/dist/middleware/rate-limit.js +30 -0
- package/dist/middleware/rate-limit.js.map +1 -0
- package/dist/middleware/request-id.d.ts +8 -0
- package/dist/middleware/request-id.d.ts.map +1 -0
- package/dist/middleware/request-id.js +11 -0
- package/dist/middleware/request-id.js.map +1 -0
- package/dist/modules/aeo/checks.d.ts +41 -0
- package/dist/modules/aeo/checks.d.ts.map +1 -0
- package/dist/modules/aeo/checks.js +127 -0
- package/dist/modules/aeo/checks.js.map +1 -0
- package/dist/modules/aeo/llms.d.ts +24 -0
- package/dist/modules/aeo/llms.d.ts.map +1 -0
- package/dist/modules/aeo/llms.js +92 -0
- package/dist/modules/aeo/llms.js.map +1 -0
- package/dist/modules/aeo/routes.admin.d.ts +12 -0
- package/dist/modules/aeo/routes.admin.d.ts.map +1 -0
- package/dist/modules/aeo/routes.admin.js +37 -0
- package/dist/modules/aeo/routes.admin.js.map +1 -0
- package/dist/modules/analytics/db.d.ts +24 -0
- package/dist/modules/analytics/db.d.ts.map +1 -0
- package/dist/modules/analytics/db.js +24 -0
- package/dist/modules/analytics/db.js.map +1 -0
- package/dist/modules/analytics/routes.admin.d.ts +6 -0
- package/dist/modules/analytics/routes.admin.d.ts.map +1 -0
- package/dist/modules/analytics/routes.admin.js +21 -0
- package/dist/modules/analytics/routes.admin.js.map +1 -0
- package/dist/modules/analytics/routes.public.d.ts +6 -0
- package/dist/modules/analytics/routes.public.d.ts.map +1 -0
- package/dist/modules/analytics/routes.public.js +33 -0
- package/dist/modules/analytics/routes.public.js.map +1 -0
- package/dist/modules/analytics/service.d.ts +16 -0
- package/dist/modules/analytics/service.d.ts.map +1 -0
- package/dist/modules/analytics/service.js +148 -0
- package/dist/modules/analytics/service.js.map +1 -0
- package/dist/modules/authors/routes.admin.d.ts +6 -0
- package/dist/modules/authors/routes.admin.d.ts.map +1 -0
- package/dist/modules/authors/routes.admin.js +29 -0
- package/dist/modules/authors/routes.admin.js.map +1 -0
- package/dist/modules/authors/routes.public.d.ts +6 -0
- package/dist/modules/authors/routes.public.d.ts.map +1 -0
- package/dist/modules/authors/routes.public.js +11 -0
- package/dist/modules/authors/routes.public.js.map +1 -0
- package/dist/modules/authors/service.d.ts +26 -0
- package/dist/modules/authors/service.d.ts.map +1 -0
- package/dist/modules/authors/service.js +116 -0
- package/dist/modules/authors/service.js.map +1 -0
- package/dist/modules/content/db.d.ts +127 -0
- package/dist/modules/content/db.d.ts.map +1 -0
- package/dist/modules/content/db.js +203 -0
- package/dist/modules/content/db.js.map +1 -0
- package/dist/modules/content/publish.d.ts +38 -0
- package/dist/modules/content/publish.d.ts.map +1 -0
- package/dist/modules/content/publish.js +184 -0
- package/dist/modules/content/publish.js.map +1 -0
- package/dist/modules/content/routes.admin.d.ts +8 -0
- package/dist/modules/content/routes.admin.d.ts.map +1 -0
- package/dist/modules/content/routes.admin.js +122 -0
- package/dist/modules/content/routes.admin.js.map +1 -0
- package/dist/modules/content/routes.public.d.ts +6 -0
- package/dist/modules/content/routes.public.d.ts.map +1 -0
- package/dist/modules/content/routes.public.js +56 -0
- package/dist/modules/content/routes.public.js.map +1 -0
- package/dist/modules/content/service.d.ts +137 -0
- package/dist/modules/content/service.d.ts.map +1 -0
- package/dist/modules/content/service.js +348 -0
- package/dist/modules/content/service.js.map +1 -0
- package/dist/modules/forms/db.d.ts +42 -0
- package/dist/modules/forms/db.d.ts.map +1 -0
- package/dist/modules/forms/db.js +62 -0
- package/dist/modules/forms/db.js.map +1 -0
- package/dist/modules/forms/forms-routes.admin.d.ts +6 -0
- package/dist/modules/forms/forms-routes.admin.d.ts.map +1 -0
- package/dist/modules/forms/forms-routes.admin.js +37 -0
- package/dist/modules/forms/forms-routes.admin.js.map +1 -0
- package/dist/modules/forms/forms-service.d.ts +18 -0
- package/dist/modules/forms/forms-service.d.ts.map +1 -0
- package/dist/modules/forms/forms-service.js +121 -0
- package/dist/modules/forms/forms-service.js.map +1 -0
- package/dist/modules/forms/routes.public.d.ts +6 -0
- package/dist/modules/forms/routes.public.d.ts.map +1 -0
- package/dist/modules/forms/routes.public.js +41 -0
- package/dist/modules/forms/routes.public.js.map +1 -0
- package/dist/modules/forms/submissions-routes.admin.d.ts +6 -0
- package/dist/modules/forms/submissions-routes.admin.d.ts.map +1 -0
- package/dist/modules/forms/submissions-routes.admin.js +46 -0
- package/dist/modules/forms/submissions-routes.admin.js.map +1 -0
- package/dist/modules/forms/submissions-service.d.ts +45 -0
- package/dist/modules/forms/submissions-service.d.ts.map +1 -0
- package/dist/modules/forms/submissions-service.js +174 -0
- package/dist/modules/forms/submissions-service.js.map +1 -0
- package/dist/modules/media/db.d.ts +15 -0
- package/dist/modules/media/db.d.ts.map +1 -0
- package/dist/modules/media/db.js +24 -0
- package/dist/modules/media/db.js.map +1 -0
- package/dist/modules/media/routes.admin.d.ts +6 -0
- package/dist/modules/media/routes.admin.d.ts.map +1 -0
- package/dist/modules/media/routes.admin.js +30 -0
- package/dist/modules/media/routes.admin.js.map +1 -0
- package/dist/modules/media/routes.public.d.ts +6 -0
- package/dist/modules/media/routes.public.d.ts.map +1 -0
- package/dist/modules/media/routes.public.js +35 -0
- package/dist/modules/media/routes.public.js.map +1 -0
- package/dist/modules/media/service.d.ts +32 -0
- package/dist/modules/media/service.d.ts.map +1 -0
- package/dist/modules/media/service.js +99 -0
- package/dist/modules/media/service.js.map +1 -0
- package/dist/modules/openapi/spec.d.ts +21 -0
- package/dist/modules/openapi/spec.d.ts.map +1 -0
- package/dist/modules/openapi/spec.js +468 -0
- package/dist/modules/openapi/spec.js.map +1 -0
- package/dist/modules/seo/jsonld.d.ts +25 -0
- package/dist/modules/seo/jsonld.d.ts.map +1 -0
- package/dist/modules/seo/jsonld.js +67 -0
- package/dist/modules/seo/jsonld.js.map +1 -0
- package/dist/modules/seo/routes.public.d.ts +6 -0
- package/dist/modules/seo/routes.public.d.ts.map +1 -0
- package/dist/modules/seo/routes.public.js +39 -0
- package/dist/modules/seo/routes.public.js.map +1 -0
- package/dist/modules/seo/sitemap.d.ts +3 -0
- package/dist/modules/seo/sitemap.d.ts.map +1 -0
- package/dist/modules/seo/sitemap.js +39 -0
- package/dist/modules/seo/sitemap.js.map +1 -0
- package/dist/modules/settings/routes.admin.d.ts +12 -0
- package/dist/modules/settings/routes.admin.d.ts.map +1 -0
- package/dist/modules/settings/routes.admin.js +27 -0
- package/dist/modules/settings/routes.admin.js.map +1 -0
- package/dist/modules/site-documents/routes.admin.d.ts +10 -0
- package/dist/modules/site-documents/routes.admin.d.ts.map +1 -0
- package/dist/modules/site-documents/routes.admin.js +29 -0
- package/dist/modules/site-documents/routes.admin.js.map +1 -0
- package/dist/modules/site-documents/routes.public.d.ts +6 -0
- package/dist/modules/site-documents/routes.public.d.ts.map +1 -0
- package/dist/modules/site-documents/routes.public.js +16 -0
- package/dist/modules/site-documents/routes.public.js.map +1 -0
- package/dist/modules/site-documents/service.d.ts +11 -0
- package/dist/modules/site-documents/service.d.ts.map +1 -0
- package/dist/modules/site-documents/service.js +42 -0
- package/dist/modules/site-documents/service.js.map +1 -0
- package/dist/modules/webhooks/dispatch.d.ts +14 -0
- package/dist/modules/webhooks/dispatch.d.ts.map +1 -0
- package/dist/modules/webhooks/dispatch.js +84 -0
- package/dist/modules/webhooks/dispatch.js.map +1 -0
- package/dist/shared/constants.d.ts +79 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/shared/constants.js +89 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/envelope.d.ts +37 -0
- package/dist/shared/envelope.d.ts.map +1 -0
- package/dist/shared/envelope.js +46 -0
- package/dist/shared/envelope.js.map +1 -0
- package/dist/shared/hash.d.ts +2 -0
- package/dist/shared/hash.d.ts.map +1 -0
- package/dist/shared/hash.js +8 -0
- package/dist/shared/hash.js.map +1 -0
- package/dist/shared/index.d.ts +13 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +13 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/schemas/aeo.d.ts +182 -0
- package/dist/shared/schemas/aeo.d.ts.map +1 -0
- package/dist/shared/schemas/aeo.js +43 -0
- package/dist/shared/schemas/aeo.js.map +1 -0
- package/dist/shared/schemas/analytics.d.ts +277 -0
- package/dist/shared/schemas/analytics.d.ts.map +1 -0
- package/dist/shared/schemas/analytics.js +74 -0
- package/dist/shared/schemas/analytics.js.map +1 -0
- package/dist/shared/schemas/api-key.d.ts +77 -0
- package/dist/shared/schemas/api-key.d.ts.map +1 -0
- package/dist/shared/schemas/api-key.js +27 -0
- package/dist/shared/schemas/api-key.js.map +1 -0
- package/dist/shared/schemas/author.d.ts +147 -0
- package/dist/shared/schemas/author.d.ts.map +1 -0
- package/dist/shared/schemas/author.js +27 -0
- package/dist/shared/schemas/author.js.map +1 -0
- package/dist/shared/schemas/form.d.ts +341 -0
- package/dist/shared/schemas/form.d.ts.map +1 -0
- package/dist/shared/schemas/form.js +117 -0
- package/dist/shared/schemas/form.js.map +1 -0
- package/dist/shared/schemas/index.d.ts +12 -0
- package/dist/shared/schemas/index.d.ts.map +1 -0
- package/dist/shared/schemas/index.js +12 -0
- package/dist/shared/schemas/index.js.map +1 -0
- package/dist/shared/schemas/media.d.ts +42 -0
- package/dist/shared/schemas/media.d.ts.map +1 -0
- package/dist/shared/schemas/media.js +16 -0
- package/dist/shared/schemas/media.js.map +1 -0
- package/dist/shared/schemas/pagination.d.ts +34 -0
- package/dist/shared/schemas/pagination.d.ts.map +1 -0
- package/dist/shared/schemas/pagination.js +21 -0
- package/dist/shared/schemas/pagination.js.map +1 -0
- package/dist/shared/schemas/post.d.ts +862 -0
- package/dist/shared/schemas/post.d.ts.map +1 -0
- package/dist/shared/schemas/post.js +187 -0
- package/dist/shared/schemas/post.js.map +1 -0
- package/dist/shared/schemas/settings.d.ts +839 -0
- package/dist/shared/schemas/settings.d.ts.map +1 -0
- package/dist/shared/schemas/settings.js +202 -0
- package/dist/shared/schemas/settings.js.map +1 -0
- package/dist/shared/schemas/site-document.d.ts +38 -0
- package/dist/shared/schemas/site-document.d.ts.map +1 -0
- package/dist/shared/schemas/site-document.js +21 -0
- package/dist/shared/schemas/site-document.js.map +1 -0
- package/dist/shared/schemas/webhook.d.ts +39 -0
- package/dist/shared/schemas/webhook.d.ts.map +1 -0
- package/dist/shared/schemas/webhook.js +20 -0
- package/dist/shared/schemas/webhook.js.map +1 -0
- package/dist/spa.d.ts +9 -0
- package/dist/spa.d.ts.map +1 -0
- package/dist/spa.js +57 -0
- package/dist/spa.js.map +1 -0
- package/migrations/0001_settings.sql +39 -0
- package/migrations/0002_content.sql +135 -0
- package/migrations/0003_forms.sql +35 -0
- package/migrations/0004_analytics.sql +42 -0
- package/migrations/0005_media.sql +17 -0
- package/migrations/0006_site_documents.sql +18 -0
- package/migrations/0007_auth.sql +81 -0
- package/migrations/0008_api_keys.sql +20 -0
- package/package.json +68 -0
- package/scripts/bundle-admin.mjs +54 -0
- package/seed/local.sql +63 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { HttpError } from '../../lib/errors.js';
|
|
2
|
+
/** JSON-text `cta` column -> parsed value; NULL/empty means no CTA configured. */
|
|
3
|
+
function parseCta(raw) {
|
|
4
|
+
return raw ? JSON.parse(raw) : null;
|
|
5
|
+
}
|
|
6
|
+
export function toPostRecord(row, hasPendingDraft, authorIds) {
|
|
7
|
+
return {
|
|
8
|
+
id: row.id,
|
|
9
|
+
slug: row.slug,
|
|
10
|
+
type: row.type,
|
|
11
|
+
title: row.title,
|
|
12
|
+
excerpt: row.excerpt,
|
|
13
|
+
content: row.content,
|
|
14
|
+
coverImageUrl: row.cover_image_url,
|
|
15
|
+
category: row.category,
|
|
16
|
+
tags: JSON.parse(row.tags),
|
|
17
|
+
status: row.status,
|
|
18
|
+
ogTitle: row.og_title,
|
|
19
|
+
ogDescription: row.og_description,
|
|
20
|
+
ogImageUrl: row.og_image_url,
|
|
21
|
+
answerSummary: row.answer_summary,
|
|
22
|
+
questionHeading: row.question_heading,
|
|
23
|
+
cta: parseCta(row.cta),
|
|
24
|
+
currentVersionId: row.current_version_id,
|
|
25
|
+
currentVersionNumber: row.current_version_number,
|
|
26
|
+
viewCount: row.view_count,
|
|
27
|
+
likeCount: row.like_count,
|
|
28
|
+
wordCount: row.word_count,
|
|
29
|
+
publishedAt: row.published_at,
|
|
30
|
+
createdAt: row.created_at,
|
|
31
|
+
updatedAt: row.updated_at,
|
|
32
|
+
hasPendingDraft,
|
|
33
|
+
...(authorIds ? { authorIds } : {}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function toPostVersionRecord(row) {
|
|
37
|
+
return {
|
|
38
|
+
id: row.id,
|
|
39
|
+
postId: row.post_id,
|
|
40
|
+
version: row.version,
|
|
41
|
+
title: row.title,
|
|
42
|
+
excerpt: row.excerpt,
|
|
43
|
+
content: row.content,
|
|
44
|
+
coverImageUrl: row.cover_image_url,
|
|
45
|
+
category: row.category,
|
|
46
|
+
tags: JSON.parse(row.tags),
|
|
47
|
+
ogTitle: row.og_title,
|
|
48
|
+
ogDescription: row.og_description,
|
|
49
|
+
ogImageUrl: row.og_image_url,
|
|
50
|
+
answerSummary: row.answer_summary,
|
|
51
|
+
questionHeading: row.question_heading,
|
|
52
|
+
cta: parseCta(row.cta),
|
|
53
|
+
authorIds: JSON.parse(row.author_ids),
|
|
54
|
+
wordCount: row.word_count,
|
|
55
|
+
note: row.note,
|
|
56
|
+
publishedAt: row.published_at,
|
|
57
|
+
publishedBy: row.published_by,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export async function fetchPostRow(db, id) {
|
|
61
|
+
const row = await db.prepare('SELECT * FROM posts WHERE id = ?1').bind(id).first();
|
|
62
|
+
if (!row)
|
|
63
|
+
throw new HttpError('not_found', 'post not found');
|
|
64
|
+
return row;
|
|
65
|
+
}
|
|
66
|
+
export async function fetchPostRowBySlug(db, slug) {
|
|
67
|
+
return db.prepare('SELECT * FROM posts WHERE slug = ?1').bind(slug).first();
|
|
68
|
+
}
|
|
69
|
+
export async function fetchDraftRow(db, postId) {
|
|
70
|
+
return db
|
|
71
|
+
.prepare('SELECT * FROM post_drafts WHERE post_id = ?1')
|
|
72
|
+
.bind(postId)
|
|
73
|
+
.first();
|
|
74
|
+
}
|
|
75
|
+
export async function hasDraft(db, postId) {
|
|
76
|
+
return (await fetchDraftRow(db, postId)) !== null;
|
|
77
|
+
}
|
|
78
|
+
export async function fetchVersionRow(db, postId, version) {
|
|
79
|
+
return db
|
|
80
|
+
.prepare('SELECT * FROM post_versions WHERE post_id = ?1 AND version = ?2')
|
|
81
|
+
.bind(postId, version)
|
|
82
|
+
.first();
|
|
83
|
+
}
|
|
84
|
+
/** Validates every id exists in authors; throws otherwise (D1 does not enforce the FK). */
|
|
85
|
+
export async function assertAuthorsExist(db, authorIds) {
|
|
86
|
+
if (authorIds.length === 0)
|
|
87
|
+
return;
|
|
88
|
+
const placeholders = authorIds.map((_, i) => `?${i + 1}`).join(', ');
|
|
89
|
+
const { results } = await db
|
|
90
|
+
.prepare(`SELECT id FROM authors WHERE id IN (${placeholders})`)
|
|
91
|
+
.bind(...authorIds)
|
|
92
|
+
.all();
|
|
93
|
+
const found = new Set(results.map((r) => r.id));
|
|
94
|
+
const missing = authorIds.filter((id) => !found.has(id));
|
|
95
|
+
if (missing.length > 0) {
|
|
96
|
+
throw new HttpError('validation_error', `unknown author id(s): ${missing.join(', ')}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** Replaces a post's author associations to match authorIds, in order. */
|
|
100
|
+
export function syncPostAuthorsStatements(db, postId, authorIds) {
|
|
101
|
+
const statements = [db.prepare('DELETE FROM post_authors WHERE post_id = ?1').bind(postId)];
|
|
102
|
+
authorIds.forEach((authorId, position) => {
|
|
103
|
+
statements.push(db
|
|
104
|
+
.prepare('INSERT INTO post_authors (post_id, author_id, position) VALUES (?1, ?2, ?3)')
|
|
105
|
+
.bind(postId, authorId, position));
|
|
106
|
+
});
|
|
107
|
+
return statements;
|
|
108
|
+
}
|
|
109
|
+
export function postRowToContentFields(row) {
|
|
110
|
+
return {
|
|
111
|
+
title: row.title,
|
|
112
|
+
excerpt: row.excerpt,
|
|
113
|
+
content: row.content,
|
|
114
|
+
coverImageUrl: row.cover_image_url,
|
|
115
|
+
category: row.category,
|
|
116
|
+
tags: JSON.parse(row.tags),
|
|
117
|
+
ogTitle: row.og_title,
|
|
118
|
+
ogDescription: row.og_description,
|
|
119
|
+
ogImageUrl: row.og_image_url,
|
|
120
|
+
answerSummary: row.answer_summary,
|
|
121
|
+
questionHeading: row.question_heading,
|
|
122
|
+
cta: parseCta(row.cta),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
export function draftRowToContentFields(row) {
|
|
126
|
+
return {
|
|
127
|
+
title: row.title,
|
|
128
|
+
excerpt: row.excerpt,
|
|
129
|
+
content: row.content,
|
|
130
|
+
coverImageUrl: row.cover_image_url,
|
|
131
|
+
category: row.category,
|
|
132
|
+
tags: JSON.parse(row.tags),
|
|
133
|
+
ogTitle: row.og_title,
|
|
134
|
+
ogDescription: row.og_description,
|
|
135
|
+
ogImageUrl: row.og_image_url,
|
|
136
|
+
answerSummary: row.answer_summary,
|
|
137
|
+
questionHeading: row.question_heading,
|
|
138
|
+
cta: parseCta(row.cta),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
export function versionRowToContentFields(row) {
|
|
142
|
+
return {
|
|
143
|
+
title: row.title,
|
|
144
|
+
excerpt: row.excerpt,
|
|
145
|
+
content: row.content,
|
|
146
|
+
coverImageUrl: row.cover_image_url,
|
|
147
|
+
category: row.category,
|
|
148
|
+
tags: JSON.parse(row.tags),
|
|
149
|
+
ogTitle: row.og_title,
|
|
150
|
+
ogDescription: row.og_description,
|
|
151
|
+
ogImageUrl: row.og_image_url,
|
|
152
|
+
answerSummary: row.answer_summary,
|
|
153
|
+
questionHeading: row.question_heading,
|
|
154
|
+
cta: parseCta(row.cta),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Merges a partial content patch over a base. `sanitizedContent` is applied
|
|
159
|
+
* separately since sanitization happens once, before merge. A field that is
|
|
160
|
+
* `undefined` in the patch (key omitted) keeps the base value; an explicit
|
|
161
|
+
* value replaces it, and "" clears to NULL (the wire protocol for "unset" on
|
|
162
|
+
* a field-merge update: JSON cannot carry undefined, so "" is the only way a
|
|
163
|
+
* client can express clearing; normalized here, the single funnel every
|
|
164
|
+
* update path flows through, so rows never store empty strings). `cta` is a
|
|
165
|
+
* whole object, not a string, so it uses `null` directly as its own clear
|
|
166
|
+
* signal instead of the ""-trick: JSON already distinguishes an explicit
|
|
167
|
+
* null from an omitted key, which is all this needs.
|
|
168
|
+
*/
|
|
169
|
+
export function mergeContentFields(base, patch, sanitizedContent) {
|
|
170
|
+
const clearable = (patchValue, baseValue) => patchValue !== undefined ? patchValue || null : baseValue;
|
|
171
|
+
return {
|
|
172
|
+
title: patch.title ?? base.title,
|
|
173
|
+
excerpt: clearable(patch.excerpt, base.excerpt),
|
|
174
|
+
content: sanitizedContent ?? base.content,
|
|
175
|
+
coverImageUrl: clearable(patch.coverImageUrl, base.coverImageUrl),
|
|
176
|
+
category: clearable(patch.category, base.category),
|
|
177
|
+
tags: patch.tags ?? base.tags,
|
|
178
|
+
ogTitle: clearable(patch.ogTitle, base.ogTitle),
|
|
179
|
+
ogDescription: clearable(patch.ogDescription, base.ogDescription),
|
|
180
|
+
ogImageUrl: clearable(patch.ogImageUrl, base.ogImageUrl),
|
|
181
|
+
answerSummary: clearable(patch.answerSummary, base.answerSummary),
|
|
182
|
+
questionHeading: clearable(patch.questionHeading, base.questionHeading),
|
|
183
|
+
cta: patch.cta !== undefined ? patch.cta : base.cta,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
export async function currentAuthorIds(db, postId) {
|
|
187
|
+
const { results } = await db
|
|
188
|
+
.prepare('SELECT author_id FROM post_authors WHERE post_id = ?1 ORDER BY position')
|
|
189
|
+
.bind(postId)
|
|
190
|
+
.all();
|
|
191
|
+
return results.map((r) => r.author_id);
|
|
192
|
+
}
|
|
193
|
+
/** Appends "-2", "-3", ... until the slug is free. Used by duplicatePost. */
|
|
194
|
+
export async function generateUniqueSlug(db, baseSlug) {
|
|
195
|
+
let candidate = baseSlug;
|
|
196
|
+
let suffix = 2;
|
|
197
|
+
while (await fetchPostRowBySlug(db, candidate)) {
|
|
198
|
+
candidate = `${baseSlug}-${suffix}`;
|
|
199
|
+
suffix += 1;
|
|
200
|
+
}
|
|
201
|
+
return candidate;
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../../src/modules/content/db.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { PostRecord, PostVersionRecord, VersionStatsEntry } from '../../shared/index.js';
|
|
2
|
+
export interface PublishOptions {
|
|
3
|
+
note?: string | undefined;
|
|
4
|
+
publishedBy: string | null;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The publish state machine, the heart of the CMS.
|
|
8
|
+
* Branches on whether this post has ever been published:
|
|
9
|
+
* - never published (current_version_id is null): snapshot the posts row
|
|
10
|
+
* itself as v1.
|
|
11
|
+
* - published before: requires a pending post_drafts row, snapshots it as
|
|
12
|
+
* vN+1, applies it onto posts, and deletes the draft.
|
|
13
|
+
* Both branches are single atomic db.batch() calls: a version snapshot and
|
|
14
|
+
* the posts row it's derived from must never go out of sync.
|
|
15
|
+
*/
|
|
16
|
+
export declare function publishPost(db: D1Database, postId: string, options: PublishOptions): Promise<PostRecord>;
|
|
17
|
+
export declare function discardDraft(db: D1Database, postId: string): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Copies a past version's fields forward as a brand new version (not a
|
|
20
|
+
* destructive rewrite of history). Also un-archives if needed and discards
|
|
21
|
+
* any pending draft, since that draft was staged on top of the version now
|
|
22
|
+
* being superseded and would otherwise silently resurrect on a later publish.
|
|
23
|
+
*/
|
|
24
|
+
export declare function rollbackToVersion(db: D1Database, postId: string, targetVersion: number, publishedBy: string | null): Promise<PostRecord>;
|
|
25
|
+
export declare function archivePost(db: D1Database, postId: string): Promise<PostRecord>;
|
|
26
|
+
export declare function unarchivePost(db: D1Database, postId: string): Promise<PostRecord>;
|
|
27
|
+
export declare function listVersions(db: D1Database, postId: string): Promise<PostVersionRecord[]>;
|
|
28
|
+
export declare function getVersion(db: D1Database, postId: string, version: number): Promise<PostVersionRecord>;
|
|
29
|
+
/**
|
|
30
|
+
* Per-version view and like counts. Two flat GROUP BY queries merged
|
|
31
|
+
* in JS, the same shape as every other stats query in this codebase
|
|
32
|
+
* (getVisitStats): no CTEs, D1's SQLite build's support for them isn't worth
|
|
33
|
+
* betting on. `versionNumber: null` is the pre-tracking bucket (rows written
|
|
34
|
+
* before migration 0008 added the column); always sorted last, never merged
|
|
35
|
+
* into a real version's count.
|
|
36
|
+
*/
|
|
37
|
+
export declare function getVersionStats(db: D1Database, postId: string): Promise<VersionStatsEntry[]>;
|
|
38
|
+
//# sourceMappingURL=publish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../../src/modules/content/publish.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAe9F,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,UAAU,CAAC,CAUrB;AA0HD,wBAAsB,YAAY,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMhF;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB,OAAO,CAAC,UAAU,CAAC,CAwErB;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAUrF;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAWvF;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAM/F;AAED,wBAAsB,UAAU,CAC9B,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,CAAC,CAM5B;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,EAAE,CAAC,CA+B9B"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { HttpError } from '../../lib/errors.js';
|
|
2
|
+
import { countWords } from '../../lib/word-count.js';
|
|
3
|
+
import { currentAuthorIds, fetchDraftRow, fetchPostRow, fetchVersionRow, syncPostAuthorsStatements, toPostVersionRecord, } from './db.js';
|
|
4
|
+
import { getPostAdmin } from './service.js';
|
|
5
|
+
/**
|
|
6
|
+
* The publish state machine, the heart of the CMS.
|
|
7
|
+
* Branches on whether this post has ever been published:
|
|
8
|
+
* - never published (current_version_id is null): snapshot the posts row
|
|
9
|
+
* itself as v1.
|
|
10
|
+
* - published before: requires a pending post_drafts row, snapshots it as
|
|
11
|
+
* vN+1, applies it onto posts, and deletes the draft.
|
|
12
|
+
* Both branches are single atomic db.batch() calls: a version snapshot and
|
|
13
|
+
* the posts row it's derived from must never go out of sync.
|
|
14
|
+
*/
|
|
15
|
+
export async function publishPost(db, postId, options) {
|
|
16
|
+
const row = await fetchPostRow(db, postId);
|
|
17
|
+
if (row.current_version_id === null) {
|
|
18
|
+
await publishFirstVersion(db, row, options);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
await publishPendingDraft(db, row, options);
|
|
22
|
+
}
|
|
23
|
+
return getPostAdmin(db, postId);
|
|
24
|
+
}
|
|
25
|
+
async function publishFirstVersion(db, row, options) {
|
|
26
|
+
const versionId = crypto.randomUUID();
|
|
27
|
+
const authorIds = await currentAuthorIds(db, row.id);
|
|
28
|
+
await db.batch([
|
|
29
|
+
db
|
|
30
|
+
.prepare(`INSERT INTO post_versions
|
|
31
|
+
(id, post_id, version, title, excerpt, content, cover_image_url, category, tags, og_title, og_description, og_image_url, answer_summary, question_heading, cta, author_ids, word_count, note, published_by)
|
|
32
|
+
VALUES (?1, ?2, 1, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18)`)
|
|
33
|
+
.bind(versionId, row.id, row.title, row.excerpt, row.content, row.cover_image_url, row.category, row.tags, row.og_title, row.og_description, row.og_image_url, row.answer_summary, row.question_heading, row.cta, // already JSON text or null; copied verbatim, no re-encode
|
|
34
|
+
JSON.stringify(authorIds), row.word_count, options.note ?? null, options.publishedBy),
|
|
35
|
+
db
|
|
36
|
+
.prepare(`UPDATE posts SET status='published', current_version_id=?2, current_version_number=1,
|
|
37
|
+
published_at=datetime('now'), updated_at=datetime('now') WHERE id=?1`)
|
|
38
|
+
.bind(row.id, versionId),
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
41
|
+
async function publishPendingDraft(db, row, options) {
|
|
42
|
+
const draft = await fetchDraftRow(db, row.id);
|
|
43
|
+
if (!draft) {
|
|
44
|
+
throw new HttpError('validation_error', 'no pending draft to publish');
|
|
45
|
+
}
|
|
46
|
+
const newVersion = (row.current_version_number ?? 0) + 1;
|
|
47
|
+
const versionId = crypto.randomUUID();
|
|
48
|
+
const wordCount = countWords(draft.content);
|
|
49
|
+
const authorIds = JSON.parse(draft.author_ids);
|
|
50
|
+
await db.batch([
|
|
51
|
+
db
|
|
52
|
+
.prepare(`INSERT INTO post_versions
|
|
53
|
+
(id, post_id, version, title, excerpt, content, cover_image_url, category, tags, og_title, og_description, og_image_url, answer_summary, question_heading, cta, author_ids, word_count, note, published_by)
|
|
54
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19)`)
|
|
55
|
+
.bind(versionId, row.id, newVersion, draft.title, draft.excerpt, draft.content, draft.cover_image_url, draft.category, draft.tags, draft.og_title, draft.og_description, draft.og_image_url, draft.answer_summary, draft.question_heading, draft.cta, draft.author_ids, wordCount, options.note ?? null, options.publishedBy),
|
|
56
|
+
db
|
|
57
|
+
.prepare(`UPDATE posts SET
|
|
58
|
+
title=?2, excerpt=?3, content=?4, cover_image_url=?5, category=?6, tags=?7,
|
|
59
|
+
og_title=?8, og_description=?9, og_image_url=?10, answer_summary=?11, question_heading=?12,
|
|
60
|
+
cta=?13, word_count=?14,
|
|
61
|
+
current_version_id=?15, current_version_number=?16,
|
|
62
|
+
published_at=datetime('now'), updated_at=datetime('now'), status='published'
|
|
63
|
+
WHERE id=?1`)
|
|
64
|
+
.bind(row.id, draft.title, draft.excerpt, draft.content, draft.cover_image_url, draft.category, draft.tags, draft.og_title, draft.og_description, draft.og_image_url, draft.answer_summary, draft.question_heading, draft.cta, wordCount, versionId, newVersion),
|
|
65
|
+
...syncPostAuthorsStatements(db, row.id, authorIds),
|
|
66
|
+
db.prepare('DELETE FROM post_drafts WHERE post_id = ?1').bind(row.id),
|
|
67
|
+
]);
|
|
68
|
+
}
|
|
69
|
+
export async function discardDraft(db, postId) {
|
|
70
|
+
const draft = await fetchDraftRow(db, postId);
|
|
71
|
+
if (!draft) {
|
|
72
|
+
throw new HttpError('not_found', 'no pending draft to discard');
|
|
73
|
+
}
|
|
74
|
+
await db.prepare('DELETE FROM post_drafts WHERE post_id = ?1').bind(postId).run();
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Copies a past version's fields forward as a brand new version (not a
|
|
78
|
+
* destructive rewrite of history). Also un-archives if needed and discards
|
|
79
|
+
* any pending draft, since that draft was staged on top of the version now
|
|
80
|
+
* being superseded and would otherwise silently resurrect on a later publish.
|
|
81
|
+
*/
|
|
82
|
+
export async function rollbackToVersion(db, postId, targetVersion, publishedBy) {
|
|
83
|
+
const row = await fetchPostRow(db, postId);
|
|
84
|
+
const target = await fetchVersionRow(db, postId, targetVersion);
|
|
85
|
+
if (!target) {
|
|
86
|
+
throw new HttpError('not_found', 'version not found');
|
|
87
|
+
}
|
|
88
|
+
const newVersion = (row.current_version_number ?? 0) + 1;
|
|
89
|
+
const versionId = crypto.randomUUID();
|
|
90
|
+
const authorIds = JSON.parse(target.author_ids);
|
|
91
|
+
await db.batch([
|
|
92
|
+
db
|
|
93
|
+
.prepare(`INSERT INTO post_versions
|
|
94
|
+
(id, post_id, version, title, excerpt, content, cover_image_url, category, tags, og_title, og_description, og_image_url, answer_summary, question_heading, cta, author_ids, word_count, note, published_by)
|
|
95
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19)`)
|
|
96
|
+
.bind(versionId, postId, newVersion, target.title, target.excerpt, target.content, target.cover_image_url, target.category, target.tags, target.og_title, target.og_description, target.og_image_url, target.answer_summary, target.question_heading, target.cta, target.author_ids, target.word_count, `rollback to v${targetVersion}`, publishedBy),
|
|
97
|
+
db
|
|
98
|
+
.prepare(`UPDATE posts SET
|
|
99
|
+
status='published', title=?2, excerpt=?3, content=?4, cover_image_url=?5, category=?6, tags=?7,
|
|
100
|
+
og_title=?8, og_description=?9, og_image_url=?10, answer_summary=?11, question_heading=?12,
|
|
101
|
+
cta=?13, word_count=?14,
|
|
102
|
+
current_version_id=?15, current_version_number=?16,
|
|
103
|
+
published_at=datetime('now'), updated_at=datetime('now')
|
|
104
|
+
WHERE id=?1`)
|
|
105
|
+
.bind(postId, target.title, target.excerpt, target.content, target.cover_image_url, target.category, target.tags, target.og_title, target.og_description, target.og_image_url, target.answer_summary, target.question_heading, target.cta, target.word_count, versionId, newVersion),
|
|
106
|
+
...syncPostAuthorsStatements(db, postId, authorIds),
|
|
107
|
+
db.prepare('DELETE FROM post_drafts WHERE post_id = ?1').bind(postId),
|
|
108
|
+
]);
|
|
109
|
+
return getPostAdmin(db, postId);
|
|
110
|
+
}
|
|
111
|
+
export async function archivePost(db, postId) {
|
|
112
|
+
const row = await fetchPostRow(db, postId);
|
|
113
|
+
if (row.status === 'archived') {
|
|
114
|
+
throw new HttpError('validation_error', 'post is already archived');
|
|
115
|
+
}
|
|
116
|
+
await db
|
|
117
|
+
.prepare(`UPDATE posts SET status='archived', updated_at=datetime('now') WHERE id=?1`)
|
|
118
|
+
.bind(postId)
|
|
119
|
+
.run();
|
|
120
|
+
return getPostAdmin(db, postId);
|
|
121
|
+
}
|
|
122
|
+
export async function unarchivePost(db, postId) {
|
|
123
|
+
const row = await fetchPostRow(db, postId);
|
|
124
|
+
if (row.status !== 'archived') {
|
|
125
|
+
throw new HttpError('validation_error', 'post is not archived');
|
|
126
|
+
}
|
|
127
|
+
const newStatus = row.current_version_id ? 'published' : 'draft';
|
|
128
|
+
await db
|
|
129
|
+
.prepare(`UPDATE posts SET status=?2, updated_at=datetime('now') WHERE id=?1`)
|
|
130
|
+
.bind(postId, newStatus)
|
|
131
|
+
.run();
|
|
132
|
+
return getPostAdmin(db, postId);
|
|
133
|
+
}
|
|
134
|
+
export async function listVersions(db, postId) {
|
|
135
|
+
const { results } = await db
|
|
136
|
+
.prepare('SELECT * FROM post_versions WHERE post_id = ?1 ORDER BY version DESC')
|
|
137
|
+
.bind(postId)
|
|
138
|
+
.all();
|
|
139
|
+
return results.map(toPostVersionRecord);
|
|
140
|
+
}
|
|
141
|
+
export async function getVersion(db, postId, version) {
|
|
142
|
+
const row = await fetchVersionRow(db, postId, version);
|
|
143
|
+
if (!row) {
|
|
144
|
+
throw new HttpError('not_found', 'version not found');
|
|
145
|
+
}
|
|
146
|
+
return toPostVersionRecord(row);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Per-version view and like counts. Two flat GROUP BY queries merged
|
|
150
|
+
* in JS, the same shape as every other stats query in this codebase
|
|
151
|
+
* (getVisitStats): no CTEs, D1's SQLite build's support for them isn't worth
|
|
152
|
+
* betting on. `versionNumber: null` is the pre-tracking bucket (rows written
|
|
153
|
+
* before migration 0008 added the column); always sorted last, never merged
|
|
154
|
+
* into a real version's count.
|
|
155
|
+
*/
|
|
156
|
+
export async function getVersionStats(db, postId) {
|
|
157
|
+
const [viewRows, likeRows] = await Promise.all([
|
|
158
|
+
db
|
|
159
|
+
.prepare('SELECT version_number, COUNT(*) as count FROM post_views WHERE post_id = ?1 GROUP BY version_number')
|
|
160
|
+
.bind(postId)
|
|
161
|
+
.all(),
|
|
162
|
+
db
|
|
163
|
+
.prepare('SELECT version_number, COUNT(*) as count FROM post_likes WHERE post_id = ?1 GROUP BY version_number')
|
|
164
|
+
.bind(postId)
|
|
165
|
+
.all(),
|
|
166
|
+
]);
|
|
167
|
+
const viewsByVersion = new Map(viewRows.results.map((r) => [r.version_number, r.count]));
|
|
168
|
+
const likesByVersion = new Map(likeRows.results.map((r) => [r.version_number, r.count]));
|
|
169
|
+
const versionNumbers = new Set([...viewsByVersion.keys(), ...likesByVersion.keys()]);
|
|
170
|
+
return [...versionNumbers]
|
|
171
|
+
.map((versionNumber) => ({
|
|
172
|
+
versionNumber,
|
|
173
|
+
viewCount: viewsByVersion.get(versionNumber) ?? 0,
|
|
174
|
+
likeCount: likesByVersion.get(versionNumber) ?? 0,
|
|
175
|
+
}))
|
|
176
|
+
.sort((a, b) => {
|
|
177
|
+
if (a.versionNumber === null)
|
|
178
|
+
return 1;
|
|
179
|
+
if (b.versionNumber === null)
|
|
180
|
+
return -1;
|
|
181
|
+
return b.versionNumber - a.versionNumber;
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../../src/modules/content/publish.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import type { AuthVariables } from '../../middleware/auth.js';
|
|
3
|
+
import type { Bindings } from '../../env.js';
|
|
4
|
+
export declare const contentAdminRoutes: Hono<{
|
|
5
|
+
Bindings: Bindings;
|
|
6
|
+
Variables: AuthVariables;
|
|
7
|
+
}, import("hono/types").BlankSchema, "/">;
|
|
8
|
+
//# sourceMappingURL=routes.admin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.admin.d.ts","sourceRoot":"","sources":["../../../src/modules/content/routes.admin.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAsC7C,eAAO,MAAM,kBAAkB;cAAwB,QAAQ;eAAa,aAAa;yCAAK,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createPostInputSchema, ok, paginationQuerySchema, postStatusSchema, postTypeSchema, publishInputSchema, rollbackInputSchema, updatePostInputSchema, } from '../../shared/index.js';
|
|
3
|
+
import { Hono } from 'hono';
|
|
4
|
+
import { HttpError } from '../../lib/errors.js';
|
|
5
|
+
import { parseOrThrow } from '../../lib/validate.js';
|
|
6
|
+
import { dispatchWebhook } from '../webhooks/dispatch.js';
|
|
7
|
+
import { archivePost, discardDraft, getVersion, getVersionStats, listVersions, publishPost, rollbackToVersion, unarchivePost, } from './publish.js';
|
|
8
|
+
import { createPost, duplicatePost, getContentStats, getPostAdmin, hardDeletePost, listPostsAdmin, updateWorkingCopy, } from './service.js';
|
|
9
|
+
const adminListQuerySchema = paginationQuerySchema.extend({
|
|
10
|
+
status: postStatusSchema.optional(),
|
|
11
|
+
type: postTypeSchema.optional(),
|
|
12
|
+
category: z.string().optional(),
|
|
13
|
+
});
|
|
14
|
+
function parseVersionParam(raw) {
|
|
15
|
+
const version = Number(raw);
|
|
16
|
+
if (!Number.isInteger(version) || version < 1) {
|
|
17
|
+
throw new HttpError('validation_error', 'version must be a positive integer');
|
|
18
|
+
}
|
|
19
|
+
return version;
|
|
20
|
+
}
|
|
21
|
+
export const contentAdminRoutes = new Hono();
|
|
22
|
+
contentAdminRoutes.get('/', async (c) => {
|
|
23
|
+
const query = parseOrThrow(adminListQuerySchema, c.req.query());
|
|
24
|
+
const { items, total } = await listPostsAdmin(c.env.DB, query);
|
|
25
|
+
return c.json(ok({ items, page: query.page, pageSize: query.pageSize, total }));
|
|
26
|
+
});
|
|
27
|
+
contentAdminRoutes.post('/', async (c) => {
|
|
28
|
+
const input = parseOrThrow(createPostInputSchema, await c.req.json());
|
|
29
|
+
const post = await createPost(c.env.DB, input);
|
|
30
|
+
return c.json(ok({ post }), 201);
|
|
31
|
+
});
|
|
32
|
+
// Registered BEFORE the parameterized /:id route below, same reasoning as
|
|
33
|
+
// /:id/versions/stats vs /:id/versions/:version further down: an
|
|
34
|
+
// unconstrained :id would otherwise swallow the literal "stats" segment.
|
|
35
|
+
contentAdminRoutes.get('/stats', async (c) => {
|
|
36
|
+
const stats = await getContentStats(c.env.DB);
|
|
37
|
+
return c.json(ok(stats));
|
|
38
|
+
});
|
|
39
|
+
contentAdminRoutes.get('/:id', async (c) => {
|
|
40
|
+
const post = await getPostAdmin(c.env.DB, c.req.param('id'));
|
|
41
|
+
return c.json(ok({ post }));
|
|
42
|
+
});
|
|
43
|
+
contentAdminRoutes.put('/:id/save', async (c) => {
|
|
44
|
+
const patch = parseOrThrow(updatePostInputSchema, await c.req.json());
|
|
45
|
+
const post = await updateWorkingCopy(c.env.DB, c.req.param('id'), patch);
|
|
46
|
+
return c.json(ok({ post }));
|
|
47
|
+
});
|
|
48
|
+
contentAdminRoutes.post('/:id/publish', async (c) => {
|
|
49
|
+
const input = parseOrThrow(publishInputSchema, await c.req.json().catch(() => ({})));
|
|
50
|
+
const publishedBy = c.get('auth').user;
|
|
51
|
+
const post = await publishPost(c.env.DB, c.req.param('id'), { ...input, publishedBy });
|
|
52
|
+
await dispatchWebhook(c.env.DB, c.executionCtx, c.env.SITE_URL, 'post.published', {
|
|
53
|
+
postId: post.id,
|
|
54
|
+
slug: post.slug,
|
|
55
|
+
title: post.title,
|
|
56
|
+
});
|
|
57
|
+
return c.json(ok({ post }));
|
|
58
|
+
});
|
|
59
|
+
contentAdminRoutes.delete('/:id/draft', async (c) => {
|
|
60
|
+
await discardDraft(c.env.DB, c.req.param('id'));
|
|
61
|
+
// Return the reverted record like every other single-post mutation here
|
|
62
|
+
// (publish/rollback/archive all return getPostAdmin's resolved shape):
|
|
63
|
+
// the admin editor re-seeds its form directly from this response, so an
|
|
64
|
+
// empty body would leave it showing the just-discarded draft content.
|
|
65
|
+
const post = await getPostAdmin(c.env.DB, c.req.param('id'));
|
|
66
|
+
return c.json(ok({ post }));
|
|
67
|
+
});
|
|
68
|
+
contentAdminRoutes.post('/:id/duplicate', async (c) => {
|
|
69
|
+
const post = await duplicatePost(c.env.DB, c.req.param('id'));
|
|
70
|
+
return c.json(ok({ post }), 201);
|
|
71
|
+
});
|
|
72
|
+
contentAdminRoutes.post('/:id/archive', async (c) => {
|
|
73
|
+
// archivePost() itself does not expose the prior status; a cheap pre-fetch
|
|
74
|
+
// (archivePost's own validation does an equivalent read internally anyway)
|
|
75
|
+
// is simpler than changing its already-tested return shape just for this.
|
|
76
|
+
const before = await getPostAdmin(c.env.DB, c.req.param('id'));
|
|
77
|
+
const post = await archivePost(c.env.DB, c.req.param('id'));
|
|
78
|
+
if (before.status === 'published') {
|
|
79
|
+
await dispatchWebhook(c.env.DB, c.executionCtx, c.env.SITE_URL, 'post.unpublished', {
|
|
80
|
+
postId: post.id,
|
|
81
|
+
slug: post.slug,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return c.json(ok({ post }));
|
|
85
|
+
});
|
|
86
|
+
contentAdminRoutes.post('/:id/unarchive', async (c) => {
|
|
87
|
+
const post = await unarchivePost(c.env.DB, c.req.param('id'));
|
|
88
|
+
return c.json(ok({ post }));
|
|
89
|
+
});
|
|
90
|
+
contentAdminRoutes.post('/:id/rollback', async (c) => {
|
|
91
|
+
const input = parseOrThrow(rollbackInputSchema, await c.req.json());
|
|
92
|
+
const publishedBy = c.get('auth').user;
|
|
93
|
+
const post = await rollbackToVersion(c.env.DB, c.req.param('id'), input.version, publishedBy);
|
|
94
|
+
// Rollback republishes, so it fires post.published like any other publish.
|
|
95
|
+
await dispatchWebhook(c.env.DB, c.executionCtx, c.env.SITE_URL, 'post.published', {
|
|
96
|
+
postId: post.id,
|
|
97
|
+
slug: post.slug,
|
|
98
|
+
title: post.title,
|
|
99
|
+
});
|
|
100
|
+
return c.json(ok({ post }));
|
|
101
|
+
});
|
|
102
|
+
contentAdminRoutes.get('/:id/versions', async (c) => {
|
|
103
|
+
const versions = await listVersions(c.env.DB, c.req.param('id'));
|
|
104
|
+
return c.json(ok({ versions }));
|
|
105
|
+
});
|
|
106
|
+
// Registered BEFORE the parameterized /:version route below: Hono matches
|
|
107
|
+
// route registration order, and an unconstrained `:version` param would
|
|
108
|
+
// otherwise swallow the literal "stats" segment first.
|
|
109
|
+
contentAdminRoutes.get('/:id/versions/stats', async (c) => {
|
|
110
|
+
const stats = await getVersionStats(c.env.DB, c.req.param('id'));
|
|
111
|
+
return c.json(ok({ stats }));
|
|
112
|
+
});
|
|
113
|
+
contentAdminRoutes.get('/:id/versions/:version', async (c) => {
|
|
114
|
+
const version = parseVersionParam(c.req.param('version'));
|
|
115
|
+
const versionRecord = await getVersion(c.env.DB, c.req.param('id'), version);
|
|
116
|
+
return c.json(ok({ version: versionRecord }));
|
|
117
|
+
});
|
|
118
|
+
contentAdminRoutes.delete('/:id', async (c) => {
|
|
119
|
+
await hardDeletePost(c.env.DB, c.req.param('id'));
|
|
120
|
+
return c.json(ok({}));
|
|
121
|
+
});
|
|
122
|
+
//# sourceMappingURL=routes.admin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.admin.js","sourceRoot":"","sources":["../../../src/modules/content/routes.admin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.public.d.ts","sourceRoot":"","sources":["../../../src/modules/content/routes.public.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAkB1D,eAAO,MAAM,mBAAmB;cAAwB,QAAQ;yCAAK,CAAC"}
|