@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,468 @@
|
|
|
1
|
+
import { CONSENT_DECISIONS, POST_TYPES } from '../../shared/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* The we8 public API, described as OpenAPI 3.1.
|
|
4
|
+
*
|
|
5
|
+
* This is the durable, language-agnostic contract: a frontend in any stack
|
|
6
|
+
* calls these endpoints over HTTPS with the site's publishable key. The JS SDK
|
|
7
|
+
* (@we8/client, @we8/astro) is an optional convenience over exactly these
|
|
8
|
+
* routes, never a requirement. Served live at GET /v1/openapi.json so a
|
|
9
|
+
* deployment's API is self-describing, and kept in sync BY HAND with the public
|
|
10
|
+
* routes (the golden-file contract tests pin the actual JSON shapes; this
|
|
11
|
+
* document is the human and tooling facing description of the same surface).
|
|
12
|
+
*
|
|
13
|
+
* It is deliberately the SAME dialect a managed we8 tenant speaks, extended
|
|
14
|
+
* only by what 0.1 adds for AEO, so a site can move between the two without
|
|
15
|
+
* rewriting its frontend.
|
|
16
|
+
*
|
|
17
|
+
* Scope: the PUBLIC, frontend-facing surface only. The admin API (/v1/admin/*,
|
|
18
|
+
* reached with a signed-in session) is not documented here; this spec is what
|
|
19
|
+
* a site owner hands to whoever builds their site.
|
|
20
|
+
*/
|
|
21
|
+
export function buildOpenApiSpec(siteUrl) {
|
|
22
|
+
const okEnvelope = (dataProps, required = []) => ({
|
|
23
|
+
type: 'object',
|
|
24
|
+
required: ['ok', ...required],
|
|
25
|
+
properties: { ok: { type: 'boolean', enum: [true] }, ...dataProps },
|
|
26
|
+
});
|
|
27
|
+
return {
|
|
28
|
+
openapi: '3.1.0',
|
|
29
|
+
info: {
|
|
30
|
+
title: 'we8 public API',
|
|
31
|
+
version: '1.0.0',
|
|
32
|
+
description: 'The public content and engagement API for a we8 site. Call it from any ' +
|
|
33
|
+
'frontend, in any language, over HTTPS with your publishable key in the ' +
|
|
34
|
+
'X-We8-Key header. Reads are safe with a publishable (pk_) key; the ' +
|
|
35
|
+
'optional @we8/client SDK is a thin typed wrapper over these same routes.',
|
|
36
|
+
},
|
|
37
|
+
// A standalone deployment IS the API origin: there is no router in front
|
|
38
|
+
// splitting a path prefix off to somewhere else.
|
|
39
|
+
servers: [{ url: siteUrl, description: 'Your CMS' }],
|
|
40
|
+
security: [{ publishableKey: [] }],
|
|
41
|
+
tags: [
|
|
42
|
+
{ name: 'content', description: 'Published posts and authors' },
|
|
43
|
+
{ name: 'site', description: 'Site identity and documents' },
|
|
44
|
+
{ name: 'forms', description: 'Form submissions' },
|
|
45
|
+
{ name: 'analytics', description: 'Visit and consent beacons' },
|
|
46
|
+
{ name: 'media', description: 'Uploaded media (keyless)' },
|
|
47
|
+
{ name: 'aeo', description: 'Answer-engine surfaces' },
|
|
48
|
+
{ name: 'meta', description: 'Health and this spec' },
|
|
49
|
+
],
|
|
50
|
+
paths: {
|
|
51
|
+
'/v1/posts': {
|
|
52
|
+
get: {
|
|
53
|
+
tags: ['content'],
|
|
54
|
+
summary: 'List published posts',
|
|
55
|
+
parameters: [
|
|
56
|
+
{ name: 'page', in: 'query', schema: { type: 'integer', minimum: 1, default: 1 } },
|
|
57
|
+
{
|
|
58
|
+
name: 'pageSize',
|
|
59
|
+
in: 'query',
|
|
60
|
+
schema: { type: 'integer', minimum: 1, maximum: 50, default: 20 },
|
|
61
|
+
},
|
|
62
|
+
{ name: 'type', in: 'query', schema: { type: 'string', enum: [...POST_TYPES] } },
|
|
63
|
+
{ name: 'category', in: 'query', schema: { type: 'string' } },
|
|
64
|
+
{ name: 'tag', in: 'query', schema: { type: 'string' } },
|
|
65
|
+
],
|
|
66
|
+
responses: {
|
|
67
|
+
'200': {
|
|
68
|
+
description: 'A page of published posts.',
|
|
69
|
+
content: {
|
|
70
|
+
'application/json': {
|
|
71
|
+
schema: okEnvelope({
|
|
72
|
+
items: { type: 'array', items: { $ref: '#/components/schemas/Post' } },
|
|
73
|
+
page: { type: 'integer' },
|
|
74
|
+
pageSize: { type: 'integer' },
|
|
75
|
+
total: { type: 'integer' },
|
|
76
|
+
}),
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
'/v1/posts/{slug}': {
|
|
84
|
+
get: {
|
|
85
|
+
tags: ['content'],
|
|
86
|
+
summary: 'Get a published post by slug',
|
|
87
|
+
parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }],
|
|
88
|
+
responses: {
|
|
89
|
+
'200': {
|
|
90
|
+
description: 'The post, its resolved authors, and its JSON-LD.',
|
|
91
|
+
content: {
|
|
92
|
+
'application/json': {
|
|
93
|
+
schema: okEnvelope({
|
|
94
|
+
post: { $ref: '#/components/schemas/Post' },
|
|
95
|
+
authors: { type: 'array', items: { $ref: '#/components/schemas/Author' } },
|
|
96
|
+
jsonld: { type: 'object', additionalProperties: true },
|
|
97
|
+
}),
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
'404': { $ref: '#/components/responses/NotFound' },
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
'/v1/posts/{slug}/view': {
|
|
106
|
+
post: {
|
|
107
|
+
tags: ['content'],
|
|
108
|
+
summary: 'Record a view (one per session)',
|
|
109
|
+
parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }],
|
|
110
|
+
requestBody: { $ref: '#/components/requestBodies/SessionId' },
|
|
111
|
+
responses: { '200': { $ref: '#/components/responses/Ok' } },
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
'/v1/posts/{slug}/like': {
|
|
115
|
+
post: {
|
|
116
|
+
tags: ['content'],
|
|
117
|
+
summary: 'Toggle a like (one per session)',
|
|
118
|
+
parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }],
|
|
119
|
+
requestBody: { $ref: '#/components/requestBodies/SessionId' },
|
|
120
|
+
responses: {
|
|
121
|
+
'200': {
|
|
122
|
+
description: 'The new like state.',
|
|
123
|
+
content: {
|
|
124
|
+
'application/json': {
|
|
125
|
+
schema: okEnvelope({
|
|
126
|
+
liked: { type: 'boolean' },
|
|
127
|
+
likeCount: { type: 'integer' },
|
|
128
|
+
}),
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
'/v1/authors/{slug}': {
|
|
136
|
+
get: {
|
|
137
|
+
tags: ['content'],
|
|
138
|
+
summary: 'Get an author by slug',
|
|
139
|
+
parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }],
|
|
140
|
+
responses: {
|
|
141
|
+
'200': {
|
|
142
|
+
description: 'The author.',
|
|
143
|
+
content: {
|
|
144
|
+
'application/json': {
|
|
145
|
+
schema: okEnvelope({ author: { $ref: '#/components/schemas/Author' } }),
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
'404': { $ref: '#/components/responses/NotFound' },
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
'/v1/site': {
|
|
154
|
+
get: {
|
|
155
|
+
tags: ['site'],
|
|
156
|
+
summary: 'Get site identity and SEO/brand config',
|
|
157
|
+
responses: {
|
|
158
|
+
'200': {
|
|
159
|
+
description: 'The site config.',
|
|
160
|
+
content: {
|
|
161
|
+
'application/json': {
|
|
162
|
+
schema: okEnvelope({ site: { type: 'object', additionalProperties: true } }),
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
'/v1/documents/{kind}': {
|
|
170
|
+
get: {
|
|
171
|
+
tags: ['site'],
|
|
172
|
+
summary: 'Get a site document (design.md or llms.txt)',
|
|
173
|
+
description: 'The llms-txt document doubles as the manual override for GET /llms.txt: ' +
|
|
174
|
+
'when it has content, that content is served there verbatim.',
|
|
175
|
+
parameters: [
|
|
176
|
+
{
|
|
177
|
+
name: 'kind',
|
|
178
|
+
in: 'path',
|
|
179
|
+
required: true,
|
|
180
|
+
schema: { type: 'string', enum: ['design-md', 'llms-txt'] },
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
responses: {
|
|
184
|
+
'200': {
|
|
185
|
+
description: 'The document.',
|
|
186
|
+
content: {
|
|
187
|
+
'application/json': {
|
|
188
|
+
schema: okEnvelope({ document: { type: 'object', additionalProperties: true } }),
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
'404': { $ref: '#/components/responses/NotFound' },
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
'/v1/forms/{formKey}/submissions': {
|
|
197
|
+
post: {
|
|
198
|
+
tags: ['forms'],
|
|
199
|
+
summary: 'Submit a form',
|
|
200
|
+
description: 'Fields are passthrough; email is typical. Honeypot, Turnstile (if the ' +
|
|
201
|
+
'form enables it), and a short dedupe window are enforced server-side.',
|
|
202
|
+
parameters: [{ name: 'formKey', in: 'path', required: true, schema: { type: 'string' } }],
|
|
203
|
+
requestBody: {
|
|
204
|
+
required: true,
|
|
205
|
+
content: {
|
|
206
|
+
'application/json': {
|
|
207
|
+
schema: {
|
|
208
|
+
type: 'object',
|
|
209
|
+
properties: {
|
|
210
|
+
email: { type: 'string', format: 'email' },
|
|
211
|
+
name: { type: 'string' },
|
|
212
|
+
message: { type: 'string' },
|
|
213
|
+
sourcePage: { type: 'string' },
|
|
214
|
+
turnstileToken: { type: 'string' },
|
|
215
|
+
},
|
|
216
|
+
additionalProperties: true,
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
responses: {
|
|
222
|
+
'200': {
|
|
223
|
+
description: 'Accepted (id is null when the honeypot silently swallowed it).',
|
|
224
|
+
content: {
|
|
225
|
+
'application/json': {
|
|
226
|
+
schema: okEnvelope({ id: { type: 'string', nullable: true } }),
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
'/v1/events/visit': {
|
|
234
|
+
post: {
|
|
235
|
+
tags: ['analytics'],
|
|
236
|
+
summary: 'Record an anonymous page visit',
|
|
237
|
+
requestBody: {
|
|
238
|
+
required: true,
|
|
239
|
+
content: {
|
|
240
|
+
'application/json': {
|
|
241
|
+
schema: {
|
|
242
|
+
type: 'object',
|
|
243
|
+
required: ['pathname', 'sessionId'],
|
|
244
|
+
properties: {
|
|
245
|
+
pathname: { type: 'string' },
|
|
246
|
+
sessionId: { type: 'string' },
|
|
247
|
+
referrer: { type: 'string' },
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
responses: { '200': { $ref: '#/components/responses/Ok' } },
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
'/v1/events/consent': {
|
|
257
|
+
post: {
|
|
258
|
+
tags: ['analytics'],
|
|
259
|
+
summary: 'Record a cookie-consent decision',
|
|
260
|
+
requestBody: {
|
|
261
|
+
required: true,
|
|
262
|
+
content: {
|
|
263
|
+
'application/json': {
|
|
264
|
+
schema: {
|
|
265
|
+
type: 'object',
|
|
266
|
+
required: ['sessionId', 'decision', 'analytics', 'performance'],
|
|
267
|
+
properties: {
|
|
268
|
+
sessionId: { type: 'string' },
|
|
269
|
+
decision: { type: 'string', enum: [...CONSENT_DECISIONS] },
|
|
270
|
+
analytics: { type: 'boolean' },
|
|
271
|
+
performance: { type: 'boolean' },
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
responses: { '200': { $ref: '#/components/responses/Ok' } },
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
'/v1/media/{key}': {
|
|
281
|
+
get: {
|
|
282
|
+
tags: ['media'],
|
|
283
|
+
summary: 'Fetch an uploaded media object (keyless)',
|
|
284
|
+
security: [],
|
|
285
|
+
parameters: [{ name: 'key', in: 'path', required: true, schema: { type: 'string' } }],
|
|
286
|
+
responses: {
|
|
287
|
+
'200': {
|
|
288
|
+
description: 'The binary object.',
|
|
289
|
+
content: { '*/*': { schema: { type: 'string', format: 'binary' } } },
|
|
290
|
+
},
|
|
291
|
+
'404': { $ref: '#/components/responses/NotFound' },
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
'/v1/sitemap.xml': {
|
|
296
|
+
get: {
|
|
297
|
+
tags: ['site'],
|
|
298
|
+
// Keyless: a search crawler cannot present a key, and a sitemap
|
|
299
|
+
// behind one is a sitemap nothing reads.
|
|
300
|
+
summary: 'The sitemap (keyless)',
|
|
301
|
+
security: [],
|
|
302
|
+
responses: {
|
|
303
|
+
'200': { description: 'XML sitemap.', content: { 'application/xml': {} } },
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
'/llms.txt': {
|
|
308
|
+
get: {
|
|
309
|
+
tags: ['aeo'],
|
|
310
|
+
summary: 'The llms.txt index of this site (keyless)',
|
|
311
|
+
description: 'Generated from site settings and published content in the llmstxt.org ' +
|
|
312
|
+
'convention, or served verbatim when the site has authored its own. ' +
|
|
313
|
+
'Keyless for the same reason as the sitemap: the readers are crawlers. ' +
|
|
314
|
+
'Returns 404 when the site has turned generation off and authored nothing.',
|
|
315
|
+
security: [],
|
|
316
|
+
responses: {
|
|
317
|
+
'200': { description: 'The document.', content: { 'text/plain': {} } },
|
|
318
|
+
'404': { $ref: '#/components/responses/NotFound' },
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
'/v1/health': {
|
|
323
|
+
get: {
|
|
324
|
+
tags: ['meta'],
|
|
325
|
+
summary: 'CMS health and enabled modules (keyless)',
|
|
326
|
+
security: [],
|
|
327
|
+
responses: {
|
|
328
|
+
'200': {
|
|
329
|
+
description: 'Health.',
|
|
330
|
+
content: {
|
|
331
|
+
'application/json': {
|
|
332
|
+
schema: okEnvelope({
|
|
333
|
+
cmsVersion: { type: 'string' },
|
|
334
|
+
modules: { type: 'object', additionalProperties: { type: 'boolean' } },
|
|
335
|
+
}),
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
'/v1/openapi.json': {
|
|
343
|
+
get: {
|
|
344
|
+
tags: ['meta'],
|
|
345
|
+
summary: 'This OpenAPI document (keyless)',
|
|
346
|
+
security: [],
|
|
347
|
+
responses: {
|
|
348
|
+
'200': {
|
|
349
|
+
description: 'The spec.',
|
|
350
|
+
content: { 'application/json': { schema: { type: 'object' } } },
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
components: {
|
|
357
|
+
securitySchemes: {
|
|
358
|
+
publishableKey: {
|
|
359
|
+
type: 'apiKey',
|
|
360
|
+
in: 'header',
|
|
361
|
+
name: 'X-We8-Key',
|
|
362
|
+
description: 'Your publishable (pk_) key. Safe to ship in browser code.',
|
|
363
|
+
},
|
|
364
|
+
secretKey: {
|
|
365
|
+
type: 'http',
|
|
366
|
+
scheme: 'bearer',
|
|
367
|
+
description: 'Your secret (sk_) key, as a bearer token. Server-side only, and ' +
|
|
368
|
+
'accepted anywhere a publishable key is. It does NOT reach the admin ' +
|
|
369
|
+
'API, which is gated by a signed-in session instead.',
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
requestBodies: {
|
|
373
|
+
SessionId: {
|
|
374
|
+
required: true,
|
|
375
|
+
content: {
|
|
376
|
+
'application/json': {
|
|
377
|
+
schema: {
|
|
378
|
+
type: 'object',
|
|
379
|
+
required: ['sessionId'],
|
|
380
|
+
properties: { sessionId: { type: 'string' } },
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
responses: {
|
|
387
|
+
Ok: {
|
|
388
|
+
description: 'Success.',
|
|
389
|
+
content: {
|
|
390
|
+
'application/json': {
|
|
391
|
+
schema: {
|
|
392
|
+
type: 'object',
|
|
393
|
+
required: ['ok'],
|
|
394
|
+
properties: { ok: { type: 'boolean', enum: [true] } },
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
NotFound: {
|
|
400
|
+
description: 'Not found.',
|
|
401
|
+
content: {
|
|
402
|
+
'application/json': {
|
|
403
|
+
schema: {
|
|
404
|
+
type: 'object',
|
|
405
|
+
required: ['ok', 'error', 'code'],
|
|
406
|
+
properties: {
|
|
407
|
+
ok: { type: 'boolean', enum: [false] },
|
|
408
|
+
error: { type: 'string' },
|
|
409
|
+
code: { type: 'string' },
|
|
410
|
+
},
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
schemas: {
|
|
417
|
+
Post: {
|
|
418
|
+
type: 'object',
|
|
419
|
+
description: 'A published post (the frozen current version).',
|
|
420
|
+
properties: {
|
|
421
|
+
id: { type: 'string' },
|
|
422
|
+
postId: { type: 'string' },
|
|
423
|
+
slug: { type: 'string' },
|
|
424
|
+
type: { type: 'string', enum: [...POST_TYPES] },
|
|
425
|
+
title: { type: 'string' },
|
|
426
|
+
excerpt: { type: 'string', nullable: true },
|
|
427
|
+
content: { type: 'string', description: 'Sanitized HTML.' },
|
|
428
|
+
coverImageUrl: { type: 'string', nullable: true },
|
|
429
|
+
category: { type: 'string', nullable: true },
|
|
430
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
431
|
+
ogTitle: { type: 'string', nullable: true },
|
|
432
|
+
ogDescription: { type: 'string', nullable: true },
|
|
433
|
+
ogImageUrl: { type: 'string', nullable: true },
|
|
434
|
+
answerSummary: {
|
|
435
|
+
type: 'string',
|
|
436
|
+
nullable: true,
|
|
437
|
+
description: 'AEO: the answer this content gives, written to be quoted verbatim.',
|
|
438
|
+
},
|
|
439
|
+
questionHeading: {
|
|
440
|
+
type: 'string',
|
|
441
|
+
nullable: true,
|
|
442
|
+
description: 'AEO: the question this content answers, phrased as a question.',
|
|
443
|
+
},
|
|
444
|
+
authorIds: { type: 'array', items: { type: 'string' } },
|
|
445
|
+
wordCount: { type: 'integer' },
|
|
446
|
+
publishedAt: { type: 'string', nullable: true },
|
|
447
|
+
viewCount: { type: 'integer' },
|
|
448
|
+
likeCount: { type: 'integer' },
|
|
449
|
+
},
|
|
450
|
+
},
|
|
451
|
+
Author: {
|
|
452
|
+
type: 'object',
|
|
453
|
+
properties: {
|
|
454
|
+
id: { type: 'string' },
|
|
455
|
+
slug: { type: 'string' },
|
|
456
|
+
name: { type: 'string' },
|
|
457
|
+
type: { type: 'string' },
|
|
458
|
+
roleTitle: { type: 'string', nullable: true },
|
|
459
|
+
avatarUrl: { type: 'string', nullable: true },
|
|
460
|
+
bio: { type: 'string', nullable: true },
|
|
461
|
+
links: { type: 'array', items: { type: 'object', additionalProperties: true } },
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
//# sourceMappingURL=spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../../src/modules/openapi/spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AuthorRecord, PostType, PublisherSettings } from '../../shared/index.js';
|
|
2
|
+
export interface JsonLdPostInput {
|
|
3
|
+
slug: string;
|
|
4
|
+
type: PostType;
|
|
5
|
+
title: string;
|
|
6
|
+
excerpt: string | null;
|
|
7
|
+
ogDescription: string | null;
|
|
8
|
+
coverImageUrl: string | null;
|
|
9
|
+
ogImageUrl: string | null;
|
|
10
|
+
answerSummary: string | null;
|
|
11
|
+
questionHeading: string | null;
|
|
12
|
+
publishedAt: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Article-family JSON-LD, authors as Person, publisher from settings.
|
|
16
|
+
*
|
|
17
|
+
* 0.1 adds the AEO half. When the author wrote an answer summary it becomes
|
|
18
|
+
* the `description`, ahead of the excerpt, because the excerpt is a teaser and
|
|
19
|
+
* the summary is the sentence written to be quoted. When there is also a
|
|
20
|
+
* question heading, the page additionally declares a `mainEntity` Question
|
|
21
|
+
* with that answer, which is the structure an answer engine actually reads a
|
|
22
|
+
* question-and-answer page through.
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildPostJsonLd(post: JsonLdPostInput, authors: AuthorRecord[], siteUrl: string, postsPathPrefix: string, publisher: PublisherSettings | undefined): Record<string, unknown>;
|
|
25
|
+
//# sourceMappingURL=jsonld.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonld.d.ts","sourceRoot":"","sources":["../../../src/modules/seo/jsonld.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAEvF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;CACrB;AAgBD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,EAAE,MAAM,EAEf,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,iBAAiB,GAAG,SAAS,GACvC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0CzB"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* schema.org @type per content type: exactly the Article subtypes Google's
|
|
3
|
+
* article structured data supports; everything without a dedicated subtype is
|
|
4
|
+
* a plain Article.
|
|
5
|
+
*/
|
|
6
|
+
const SCHEMA_TYPE = {
|
|
7
|
+
blog: 'BlogPosting',
|
|
8
|
+
news: 'NewsArticle',
|
|
9
|
+
article: 'Article',
|
|
10
|
+
research: 'Article',
|
|
11
|
+
whitepaper: 'Article',
|
|
12
|
+
'case-study': 'Article',
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Article-family JSON-LD, authors as Person, publisher from settings.
|
|
16
|
+
*
|
|
17
|
+
* 0.1 adds the AEO half. When the author wrote an answer summary it becomes
|
|
18
|
+
* the `description`, ahead of the excerpt, because the excerpt is a teaser and
|
|
19
|
+
* the summary is the sentence written to be quoted. When there is also a
|
|
20
|
+
* question heading, the page additionally declares a `mainEntity` Question
|
|
21
|
+
* with that answer, which is the structure an answer engine actually reads a
|
|
22
|
+
* question-and-answer page through.
|
|
23
|
+
*/
|
|
24
|
+
export function buildPostJsonLd(post, authors, siteUrl,
|
|
25
|
+
// Already RESOLVED via resolveContentPath(post.type, settings); callers own that.
|
|
26
|
+
postsPathPrefix, publisher) {
|
|
27
|
+
const url = `${siteUrl}${postsPathPrefix}/${post.slug}`;
|
|
28
|
+
const description = post.answerSummary ?? post.excerpt ?? post.ogDescription ?? undefined;
|
|
29
|
+
const image = post.ogImageUrl ?? post.coverImageUrl ?? undefined;
|
|
30
|
+
const qa = post.questionHeading && post.answerSummary
|
|
31
|
+
? {
|
|
32
|
+
mainEntity: {
|
|
33
|
+
'@type': 'Question',
|
|
34
|
+
name: post.questionHeading,
|
|
35
|
+
acceptedAnswer: { '@type': 'Answer', text: post.answerSummary },
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
: {};
|
|
39
|
+
return {
|
|
40
|
+
'@context': 'https://schema.org',
|
|
41
|
+
'@type': SCHEMA_TYPE[post.type],
|
|
42
|
+
headline: post.title,
|
|
43
|
+
...(description ? { description } : {}),
|
|
44
|
+
...(image ? { image } : {}),
|
|
45
|
+
datePublished: post.publishedAt,
|
|
46
|
+
dateModified: post.publishedAt,
|
|
47
|
+
mainEntityOfPage: url,
|
|
48
|
+
...qa,
|
|
49
|
+
author: authors.map((author) => ({
|
|
50
|
+
'@type': 'Person',
|
|
51
|
+
name: author.name,
|
|
52
|
+
...(author.links[0] ? { url: author.links[0].url } : {}),
|
|
53
|
+
})),
|
|
54
|
+
...(publisher
|
|
55
|
+
? {
|
|
56
|
+
publisher: {
|
|
57
|
+
'@type': 'Organization',
|
|
58
|
+
name: publisher.name,
|
|
59
|
+
...(publisher.logoUrl
|
|
60
|
+
? { logo: { '@type': 'ImageObject', url: publisher.logoUrl } }
|
|
61
|
+
: {}),
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
: {}),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=jsonld.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonld.js","sourceRoot":"","sources":["../../../src/modules/seo/jsonld.ts"],"names":[],"mappings":"AAeA;;;;GAIG;AACH,MAAM,WAAW,GAA6B;IAC5C,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,aAAa;IACnB,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,SAAS;IACnB,UAAU,EAAE,SAAS;IACrB,YAAY,EAAE,SAAS;CACxB,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAqB,EACrB,OAAuB,EACvB,OAAe;AACf,kFAAkF;AAClF,eAAuB,EACvB,SAAwC;IAExC,MAAM,GAAG,GAAG,GAAG,OAAO,GAAG,eAAe,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;IACxD,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,aAAa,IAAI,SAAS,CAAC;IAC1F,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,aAAa,IAAI,SAAS,CAAC;IACjE,MAAM,EAAE,GACN,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,aAAa;QACxC,CAAC,CAAC;YACE,UAAU,EAAE;gBACV,OAAO,EAAE,UAAU;gBACnB,IAAI,EAAE,IAAI,CAAC,eAAe;gBAC1B,cAAc,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE;aAChE;SACF;QACH,CAAC,CAAC,EAAE,CAAC;IAET,OAAO;QACL,UAAU,EAAE,oBAAoB;QAChC,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QAC/B,QAAQ,EAAE,IAAI,CAAC,KAAK;QACpB,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3B,aAAa,EAAE,IAAI,CAAC,WAAW;QAC/B,YAAY,EAAE,IAAI,CAAC,WAAW;QAC9B,gBAAgB,EAAE,GAAG;QACrB,GAAG,EAAE;QACL,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC/B,OAAO,EAAE,QAAQ;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzD,CAAC,CAAC;QACH,GAAG,CAAC,SAAS;YACX,CAAC,CAAC;gBACE,SAAS,EAAE;oBACT,OAAO,EAAE,cAAc;oBACvB,IAAI,EAAE,SAAS,CAAC,IAAI;oBACpB,GAAG,CAAC,SAAS,CAAC,OAAO;wBACnB,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,CAAC,OAAO,EAAE,EAAE;wBAC9D,CAAC,CAAC,EAAE,CAAC;iBACR;aACF;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.public.d.ts","sourceRoot":"","sources":["../../../src/modules/seo/routes.public.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAI1D,eAAO,MAAM,eAAe;cAAwB,QAAQ;yCAAK,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ok, resolveAllContentPaths } from '../../shared/index.js';
|
|
2
|
+
import { Hono } from 'hono';
|
|
3
|
+
import { getSettings } from '../../env.js';
|
|
4
|
+
import { corsMiddleware } from '../../middleware/cors.js';
|
|
5
|
+
import { buildSitemap } from './sitemap.js';
|
|
6
|
+
export const seoPublicRoutes = new Hono();
|
|
7
|
+
seoPublicRoutes.use('/sitemap.xml', corsMiddleware('publicRead'));
|
|
8
|
+
seoPublicRoutes.get('/sitemap.xml', async (c) => {
|
|
9
|
+
const xml = await buildSitemap(c.env.DB, c.env.SITE_URL);
|
|
10
|
+
return c.body(xml, 200, {
|
|
11
|
+
'Content-Type': 'application/xml; charset=UTF-8',
|
|
12
|
+
'Cache-Control': 'public, max-age=900',
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
seoPublicRoutes.use('/site', corsMiddleware('publicRead'));
|
|
16
|
+
/**
|
|
17
|
+
* The site's identity card: name, canonical URL, SEO fallbacks, publisher, and
|
|
18
|
+
* the content paths. This only stores and serves; the code-first merge, where
|
|
19
|
+
* a template's own values win and these fill the gaps, lives in @we8/astro.
|
|
20
|
+
* Deliberately NOT module-gated: a template needs it at build time regardless
|
|
21
|
+
* of which modules the site runs. Cached like the sitemap.
|
|
22
|
+
*/
|
|
23
|
+
seoPublicRoutes.get('/site', async (c) => {
|
|
24
|
+
const settings = await getSettings(c.env.DB);
|
|
25
|
+
const site = {
|
|
26
|
+
name: settings.publisher?.name ?? null,
|
|
27
|
+
siteUrl: c.env.SITE_URL,
|
|
28
|
+
seo: settings.seo,
|
|
29
|
+
publisher: settings.publisher ?? null,
|
|
30
|
+
postsPathPrefix: settings.postsPathPrefix,
|
|
31
|
+
contentPaths: resolveAllContentPaths(settings),
|
|
32
|
+
// "" (unconfigured, the settings-side clear signal) must never leak as a
|
|
33
|
+
// truthy-looking empty string to templates; null is the honest absence.
|
|
34
|
+
gaMeasurementId: settings.gaMeasurementId || null,
|
|
35
|
+
brand: settings.brand,
|
|
36
|
+
};
|
|
37
|
+
return c.json(ok({ site }), 200, { 'Cache-Control': 'public, max-age=900' });
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=routes.public.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.public.js","sourceRoot":"","sources":["../../../src/modules/seo/routes.public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,sBAAsB,EAAmB,MAAM,uBAAuB,CAAC;AACpF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAiB,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,IAAI,EAA0B,CAAC;AAElE,eAAe,CAAC,GAAG,CAAC,cAAc,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;AAElE,eAAe,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC9C,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACzD,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE;QACtB,cAAc,EAAE,gCAAgC;QAChD,eAAe,EAAE,qBAAqB;KACvC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;AAE3D;;;;;;GAMG;AACH,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACvC,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAe;QACvB,IAAI,EAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,IAAI,IAAI;QACtC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ;QACvB,GAAG,EAAE,QAAQ,CAAC,GAAG;QACjB,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,IAAI;QACrC,eAAe,EAAE,QAAQ,CAAC,eAAe;QACzC,YAAY,EAAE,sBAAsB,CAAC,QAAQ,CAAC;QAC9C,yEAAyE;QACzE,wEAAwE;QACxE,eAAe,EAAE,QAAQ,CAAC,eAAe,IAAI,IAAI;QACjD,KAAK,EAAE,QAAQ,CAAC,KAAK;KACtB,CAAC;IACF,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,eAAe,EAAE,qBAAqB,EAAE,CAAC,CAAC;AAC/E,CAAC,CAAC,CAAC"}
|