@prenta/core 8.9.2 → 8.11.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/CHANGELOG.md +105 -0
- package/dist/actions.d.ts +25 -0
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +51 -4
- package/dist/actions.js.map +1 -1
- package/dist/ai/batch-links.d.ts +105 -0
- package/dist/ai/batch-links.d.ts.map +1 -0
- package/dist/ai/batch-links.js +667 -0
- package/dist/ai/batch-links.js.map +1 -0
- package/dist/ai/batch-list.d.ts +127 -4
- package/dist/ai/batch-list.d.ts.map +1 -1
- package/dist/ai/batch-list.js +250 -14
- package/dist/ai/batch-list.js.map +1 -1
- package/dist/ai/providers/http.d.ts +4 -0
- package/dist/ai/providers/http.d.ts.map +1 -1
- package/dist/ai/providers/http.js +9 -8
- package/dist/ai/providers/http.js.map +1 -1
- package/dist/ai/tasks/editor-text.d.ts +39 -0
- package/dist/ai/tasks/editor-text.d.ts.map +1 -0
- package/dist/ai/tasks/editor-text.js +45 -0
- package/dist/ai/tasks/editor-text.js.map +1 -0
- package/dist/ai/tasks/link-embeddings.d.ts +22 -0
- package/dist/ai/tasks/link-embeddings.d.ts.map +1 -1
- package/dist/ai/tasks/link-embeddings.js +24 -10
- package/dist/ai/tasks/link-embeddings.js.map +1 -1
- package/dist/ai/usage.d.ts +7 -0
- package/dist/ai/usage.d.ts.map +1 -1
- package/dist/ai/usage.js +11 -0
- package/dist/ai/usage.js.map +1 -1
- package/dist/api/guarded-db.d.ts +6 -0
- package/dist/api/guarded-db.d.ts.map +1 -1
- package/dist/api/guarded-db.js +13 -1
- package/dist/api/guarded-db.js.map +1 -1
- package/dist/api/handlers.d.ts.map +1 -1
- package/dist/api/handlers.js +2 -0
- package/dist/api/handlers.js.map +1 -1
- package/dist/api/openapi.d.ts.map +1 -1
- package/dist/api/openapi.js +103 -0
- package/dist/api/openapi.js.map +1 -1
- package/dist/api/route-helpers/forms.d.ts.map +1 -1
- package/dist/api/route-helpers/forms.js +7 -1
- package/dist/api/route-helpers/forms.js.map +1 -1
- package/dist/api/routes/ai-authoring.d.ts.map +1 -1
- package/dist/api/routes/ai-authoring.js +1 -0
- package/dist/api/routes/ai-authoring.js.map +1 -1
- package/dist/api/routes/ai-seo.d.ts.map +1 -1
- package/dist/api/routes/ai-seo.js +20 -18
- package/dist/api/routes/ai-seo.js.map +1 -1
- package/dist/api/routes/media.d.ts.map +1 -1
- package/dist/api/routes/media.js +3 -1
- package/dist/api/routes/media.js.map +1 -1
- package/dist/api/routes/scheduling.d.ts.map +1 -1
- package/dist/api/routes/scheduling.js +33 -2
- package/dist/api/routes/scheduling.js.map +1 -1
- package/dist/appearance/color.d.ts +17 -0
- package/dist/appearance/color.d.ts.map +1 -1
- package/dist/appearance/color.js +162 -1
- package/dist/appearance/color.js.map +1 -1
- package/dist/appearance/index.d.ts +3 -3
- package/dist/appearance/index.d.ts.map +1 -1
- package/dist/appearance/index.js +2 -2
- package/dist/appearance/index.js.map +1 -1
- package/dist/appearance/resolve.d.ts.map +1 -1
- package/dist/appearance/resolve.js +4 -2
- package/dist/appearance/resolve.js.map +1 -1
- package/dist/appearance/theme-tokens.d.ts +60 -11
- package/dist/appearance/theme-tokens.d.ts.map +1 -1
- package/dist/appearance/theme-tokens.js +184 -175
- package/dist/appearance/theme-tokens.js.map +1 -1
- package/dist/appearance/types.d.ts +16 -2
- package/dist/appearance/types.d.ts.map +1 -1
- package/dist/astro-site.d.ts +1 -11
- package/dist/astro-site.d.ts.map +1 -1
- package/dist/astro-site.js +4 -0
- package/dist/astro-site.js.map +1 -1
- package/dist/auth/team.d.ts +1 -0
- package/dist/auth/team.d.ts.map +1 -1
- package/dist/auth/team.js +1 -1
- package/dist/auth/team.js.map +1 -1
- package/dist/cache/http.d.ts +20 -0
- package/dist/cache/http.d.ts.map +1 -1
- package/dist/cache/http.js +42 -0
- package/dist/cache/http.js.map +1 -1
- package/dist/chrome/announcement.d.ts +30 -0
- package/dist/chrome/announcement.d.ts.map +1 -0
- package/dist/chrome/announcement.js +190 -0
- package/dist/chrome/announcement.js.map +1 -0
- package/dist/chrome/codegen.d.ts +17 -0
- package/dist/chrome/codegen.d.ts.map +1 -0
- package/dist/chrome/codegen.js +96 -0
- package/dist/chrome/codegen.js.map +1 -0
- package/dist/chrome/contract.d.ts +161 -0
- package/dist/chrome/contract.d.ts.map +1 -0
- package/dist/chrome/contract.js +2 -0
- package/dist/chrome/contract.js.map +1 -0
- package/dist/chrome/memory-store.d.ts +15 -0
- package/dist/chrome/memory-store.d.ts.map +1 -0
- package/dist/chrome/memory-store.js +54 -0
- package/dist/chrome/memory-store.js.map +1 -0
- package/dist/chrome/overrides.d.ts +25 -0
- package/dist/chrome/overrides.d.ts.map +1 -0
- package/dist/chrome/overrides.js +180 -0
- package/dist/chrome/overrides.js.map +1 -0
- package/dist/chrome/parse.d.ts +36 -0
- package/dist/chrome/parse.d.ts.map +1 -0
- package/dist/chrome/parse.js +277 -0
- package/dist/chrome/parse.js.map +1 -0
- package/dist/chrome/prisma-store.d.ts +11 -0
- package/dist/chrome/prisma-store.d.ts.map +1 -0
- package/dist/chrome/prisma-store.js +48 -0
- package/dist/chrome/prisma-store.js.map +1 -0
- package/dist/chrome/public.d.ts +22 -0
- package/dist/chrome/public.d.ts.map +1 -0
- package/dist/chrome/public.js +181 -0
- package/dist/chrome/public.js.map +1 -0
- package/dist/chrome/resolve.d.ts +36 -0
- package/dist/chrome/resolve.d.ts.map +1 -0
- package/dist/chrome/resolve.js +165 -0
- package/dist/chrome/resolve.js.map +1 -0
- package/dist/chrome/revalidate.d.ts +9 -0
- package/dist/chrome/revalidate.d.ts.map +1 -0
- package/dist/chrome/revalidate.js +51 -0
- package/dist/chrome/revalidate.js.map +1 -0
- package/dist/chrome/routes.d.ts +14 -0
- package/dist/chrome/routes.d.ts.map +1 -0
- package/dist/chrome/routes.js +349 -0
- package/dist/chrome/routes.js.map +1 -0
- package/dist/chrome/schema.d.ts +231 -0
- package/dist/chrome/schema.d.ts.map +1 -0
- package/dist/chrome/schema.js +73 -0
- package/dist/chrome/schema.js.map +1 -0
- package/dist/chrome/service.d.ts +76 -0
- package/dist/chrome/service.d.ts.map +1 -0
- package/dist/chrome/service.js +286 -0
- package/dist/chrome/service.js.map +1 -0
- package/dist/chrome/settings.d.ts +14 -0
- package/dist/chrome/settings.d.ts.map +1 -0
- package/dist/chrome/settings.js +142 -0
- package/dist/chrome/settings.js.map +1 -0
- package/dist/chrome/store.d.ts +48 -0
- package/dist/chrome/store.d.ts.map +1 -0
- package/dist/chrome/store.js +26 -0
- package/dist/chrome/store.js.map +1 -0
- package/dist/chrome/values.d.ts +98 -0
- package/dist/chrome/values.d.ts.map +1 -0
- package/dist/chrome/values.js +491 -0
- package/dist/chrome/values.js.map +1 -0
- package/dist/config/define.d.ts +2 -0
- package/dist/config/define.d.ts.map +1 -1
- package/dist/config/define.js +2 -0
- package/dist/config/define.js.map +1 -1
- package/dist/db/model-types.d.ts +62 -0
- package/dist/db/model-types.d.ts.map +1 -1
- package/dist/forms/attribution-settings.d.ts +23 -0
- package/dist/forms/attribution-settings.d.ts.map +1 -0
- package/dist/forms/attribution-settings.js +42 -0
- package/dist/forms/attribution-settings.js.map +1 -0
- package/dist/forms/attribution.d.ts +5 -1
- package/dist/forms/attribution.d.ts.map +1 -1
- package/dist/forms/attribution.js +6 -4
- package/dist/forms/attribution.js.map +1 -1
- package/dist/forms/client-validation.d.ts.map +1 -1
- package/dist/forms/client-validation.js +3 -0
- package/dist/forms/client-validation.js.map +1 -1
- package/dist/forms/form-model.d.ts +109 -0
- package/dist/forms/form-model.d.ts.map +1 -0
- package/dist/forms/form-model.js +192 -0
- package/dist/forms/form-model.js.map +1 -0
- package/dist/forms/index.d.ts +2 -2
- package/dist/forms/index.d.ts.map +1 -1
- package/dist/forms/index.js +1 -1
- package/dist/forms/index.js.map +1 -1
- package/dist/forms/service.d.ts +19 -1
- package/dist/forms/service.d.ts.map +1 -1
- package/dist/forms/service.js +152 -0
- package/dist/forms/service.js.map +1 -1
- package/dist/forms/spam.d.ts +0 -12
- package/dist/forms/spam.d.ts.map +1 -1
- package/dist/forms/spam.js +30 -0
- package/dist/forms/spam.js.map +1 -1
- package/dist/forms/submission.d.ts +7 -0
- package/dist/forms/submission.d.ts.map +1 -1
- package/dist/forms/submission.js +33 -0
- package/dist/forms/submission.js.map +1 -1
- package/dist/forms/types.d.ts +26 -1
- package/dist/forms/types.d.ts.map +1 -1
- package/dist/forms/types.js +9 -1
- package/dist/forms/types.js.map +1 -1
- package/dist/generated/browser.d.ts +35 -3
- package/dist/generated/client.d.ts +35 -3
- package/dist/generated/internal/class.d.ts +44 -0
- package/dist/generated/internal/class.js +4 -4
- package/dist/generated/internal/prismaNamespace.d.ts +403 -1
- package/dist/generated/internal/prismaNamespace.js +95 -1
- package/dist/generated/internal/prismaNamespaceBrowser.d.ts +102 -0
- package/dist/generated/internal/prismaNamespaceBrowser.js +95 -1
- package/dist/generated/models/ChromeRegion.d.ts +1203 -0
- package/dist/generated/models/ChromeRegion.js +1 -0
- package/dist/generated/models/Job.d.ts +732 -5
- package/dist/generated/models/JobEvent.d.ts +1339 -0
- package/dist/generated/models/JobEvent.js +1 -0
- package/dist/generated/models/JobReviewItem.d.ts +1470 -0
- package/dist/generated/models/JobReviewItem.js +1 -0
- package/dist/generated/models/SystemSetting.d.ts +952 -0
- package/dist/generated/models/SystemSetting.js +1 -0
- package/dist/generated/models.d.ts +4 -0
- package/dist/index.d.ts +12 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/jobs/batch-ai.d.ts +53 -0
- package/dist/jobs/batch-ai.d.ts.map +1 -0
- package/dist/jobs/batch-ai.js +314 -0
- package/dist/jobs/batch-ai.js.map +1 -0
- package/dist/jobs/contract.d.ts +193 -0
- package/dist/jobs/contract.d.ts.map +1 -0
- package/dist/jobs/contract.js +2 -0
- package/dist/jobs/contract.js.map +1 -0
- package/dist/jobs/error-text.d.ts +23 -0
- package/dist/jobs/error-text.d.ts.map +1 -0
- package/dist/jobs/error-text.js +110 -0
- package/dist/jobs/error-text.js.map +1 -0
- package/dist/jobs/handlers.d.ts.map +1 -1
- package/dist/jobs/handlers.js +48 -7
- package/dist/jobs/handlers.js.map +1 -1
- package/dist/jobs/memory-store.d.ts +26 -2
- package/dist/jobs/memory-store.d.ts.map +1 -1
- package/dist/jobs/memory-store.js +157 -3
- package/dist/jobs/memory-store.js.map +1 -1
- package/dist/jobs/outcomes.d.ts +46 -0
- package/dist/jobs/outcomes.d.ts.map +1 -0
- package/dist/jobs/outcomes.js +251 -0
- package/dist/jobs/outcomes.js.map +1 -0
- package/dist/jobs/prisma-store.d.ts +14 -2
- package/dist/jobs/prisma-store.d.ts.map +1 -1
- package/dist/jobs/prisma-store.js +257 -15
- package/dist/jobs/prisma-store.js.map +1 -1
- package/dist/jobs/queue.d.ts +62 -2
- package/dist/jobs/queue.d.ts.map +1 -1
- package/dist/jobs/queue.js +412 -36
- package/dist/jobs/queue.js.map +1 -1
- package/dist/jobs/retention.d.ts +11 -0
- package/dist/jobs/retention.d.ts.map +1 -0
- package/dist/jobs/retention.js +18 -0
- package/dist/jobs/retention.js.map +1 -0
- package/dist/jobs/review.d.ts +111 -0
- package/dist/jobs/review.d.ts.map +1 -0
- package/dist/jobs/review.js +461 -0
- package/dist/jobs/review.js.map +1 -0
- package/dist/jobs/routes.d.ts.map +1 -1
- package/dist/jobs/routes.js +491 -16
- package/dist/jobs/routes.js.map +1 -1
- package/dist/jobs/serialize.d.ts +40 -0
- package/dist/jobs/serialize.d.ts.map +1 -0
- package/dist/jobs/serialize.js +275 -0
- package/dist/jobs/serialize.js.map +1 -0
- package/dist/jobs/types.d.ts +141 -2
- package/dist/jobs/types.d.ts.map +1 -1
- package/dist/jobs/worker-status.d.ts +27 -0
- package/dist/jobs/worker-status.d.ts.map +1 -0
- package/dist/jobs/worker-status.js +66 -0
- package/dist/jobs/worker-status.js.map +1 -0
- package/dist/media/optimize.d.ts.map +1 -1
- package/dist/media/optimize.js +4 -2
- package/dist/media/optimize.js.map +1 -1
- package/dist/next-site.d.ts +1 -0
- package/dist/next-site.d.ts.map +1 -1
- package/dist/next-site.js +3 -0
- package/dist/next-site.js.map +1 -1
- package/dist/seo/audit-runner.d.ts.map +1 -1
- package/dist/seo/audit-runner.js +23 -2
- package/dist/seo/audit-runner.js.map +1 -1
- package/dist/seo/issue-fix-link-insert.d.ts +11 -0
- package/dist/seo/issue-fix-link-insert.d.ts.map +1 -1
- package/dist/seo/issue-fix-link-insert.js +122 -8
- package/dist/seo/issue-fix-link-insert.js.map +1 -1
- package/dist/server-site.d.ts.map +1 -1
- package/dist/server-site.js +15 -0
- package/dist/server-site.js.map +1 -1
- package/dist/site.d.ts +8 -0
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +6 -0
- package/dist/site.js.map +1 -1
- package/dist/webhooks/index.d.ts +3 -1
- package/dist/webhooks/index.d.ts.map +1 -1
- package/dist/webhooks/index.js.map +1 -1
- package/package.json +6 -1
- package/prisma/migrations/0025_job_cancel_review/down.sql +60 -0
- package/prisma/migrations/0025_job_cancel_review/migration.sql +56 -0
- package/prisma/migrations/0026_job_creator_system_settings/down.sql +30 -0
- package/prisma/migrations/0026_job_creator_system_settings/migration.sql +14 -0
- package/prisma/migrations/0027_chrome_regions/down.sql +24 -0
- package/prisma/migrations/0027_chrome_regions/migration.sql +16 -0
- package/prisma/schema.prisma +105 -15
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `/public/chrome` sends for a path. A region resolves in three steps,
|
|
3
|
+
* each over the last: the site default, the nearest ancestor page's override,
|
|
4
|
+
* then the page's own. An override of `null` hides the region; a later
|
|
5
|
+
* override that isn't null shows it again.
|
|
6
|
+
*/
|
|
7
|
+
import { createHash } from 'node:crypto';
|
|
8
|
+
import { cleanFieldValue, effectiveVariant, hasVariant, isRecord, ownField, ownValue, } from './values.js';
|
|
9
|
+
/** Read one region's override from a page's `_layout`. Strings are legacy variant-document ids, not overrides. */
|
|
10
|
+
export function readRegionOverride(value) {
|
|
11
|
+
if (value === null)
|
|
12
|
+
return null;
|
|
13
|
+
if (!isRecord(value))
|
|
14
|
+
return undefined;
|
|
15
|
+
const out = {};
|
|
16
|
+
if (typeof value.variant === 'string')
|
|
17
|
+
out.variant = value.variant;
|
|
18
|
+
if (isRecord(value.fields))
|
|
19
|
+
out.fields = value.fields;
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Keep the values that fit their field and pass a save's checks; the rest are
|
|
24
|
+
* ignored. Page overrides come from `_layout`, which no chrome save checked,
|
|
25
|
+
* so a `javascript:` link or an over-long text there never reaches the site.
|
|
26
|
+
*/
|
|
27
|
+
function fittingValues(schema, values) {
|
|
28
|
+
const out = {};
|
|
29
|
+
for (const [key, value] of Object.entries(values ?? {})) {
|
|
30
|
+
const def = ownField(schema, key);
|
|
31
|
+
if (!def)
|
|
32
|
+
continue;
|
|
33
|
+
const fit = cleanFieldValue(def, value);
|
|
34
|
+
if (fit.ok)
|
|
35
|
+
out[key] = fit.value;
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Apply the overrides in order (nearest ancestor, then the page) over the
|
|
41
|
+
* site default. `undefined` means "no override at this level".
|
|
42
|
+
*/
|
|
43
|
+
export function effectiveRegion(schema, site, overrides) {
|
|
44
|
+
const base = {
|
|
45
|
+
variant: effectiveVariant(schema, site.variant),
|
|
46
|
+
values: fittingValues(schema, site.values),
|
|
47
|
+
};
|
|
48
|
+
let current = base;
|
|
49
|
+
for (const override of overrides) {
|
|
50
|
+
if (override === undefined)
|
|
51
|
+
continue;
|
|
52
|
+
if (override === null) {
|
|
53
|
+
current = null;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const from = current ?? base;
|
|
57
|
+
current = {
|
|
58
|
+
variant: override.variant !== undefined && hasVariant(schema, override.variant)
|
|
59
|
+
? override.variant
|
|
60
|
+
: from.variant,
|
|
61
|
+
values: { ...from.values, ...fittingValues(schema, override.fields) },
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return current;
|
|
65
|
+
}
|
|
66
|
+
/** The menu slugs a region's values point at, defaults included. */
|
|
67
|
+
export function menuSlugs(schema, values) {
|
|
68
|
+
const slugs = new Set();
|
|
69
|
+
for (const [key, def] of Object.entries(schema.fields)) {
|
|
70
|
+
if (def.type !== 'menu')
|
|
71
|
+
continue;
|
|
72
|
+
const value = ownValue(values, key);
|
|
73
|
+
if (def.list) {
|
|
74
|
+
const list = Array.isArray(value) ? value : def.default ? [def.default] : [];
|
|
75
|
+
for (const slug of list)
|
|
76
|
+
if (typeof slug === 'string' && slug)
|
|
77
|
+
slugs.add(slug);
|
|
78
|
+
}
|
|
79
|
+
else if (def.optional) {
|
|
80
|
+
if (isRecord(value) && value.on === true && typeof value.value === 'string' && value.value) {
|
|
81
|
+
slugs.add(value.value);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const slug = typeof value === 'string' && value ? value : def.default;
|
|
86
|
+
if (slug)
|
|
87
|
+
slugs.add(slug);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return [...slugs];
|
|
91
|
+
}
|
|
92
|
+
/** Fill the placeholders the CMS owns. `{year}` is the current UTC year. */
|
|
93
|
+
function fillTokens(text, def, now) {
|
|
94
|
+
if (!def.tokens?.includes('{year}'))
|
|
95
|
+
return text;
|
|
96
|
+
return text.split('{year}').join(String(now.getUTCFullYear()));
|
|
97
|
+
}
|
|
98
|
+
function toggleOn(value) {
|
|
99
|
+
return isRecord(value) && value.on === true;
|
|
100
|
+
}
|
|
101
|
+
/** One field as the site receives it. */
|
|
102
|
+
function publicField(def, value, ctx) {
|
|
103
|
+
switch (def.type) {
|
|
104
|
+
case 'brand':
|
|
105
|
+
return def.key === 'logo' ? ctx.brand.logo : ctx.brand.name;
|
|
106
|
+
case 'menu': {
|
|
107
|
+
if (def.list) {
|
|
108
|
+
const list = Array.isArray(value) ? value : def.default ? [def.default] : [];
|
|
109
|
+
return list
|
|
110
|
+
.map((slug) => (typeof slug === 'string' ? ctx.menus.get(slug) : undefined))
|
|
111
|
+
.filter((menu) => menu !== undefined);
|
|
112
|
+
}
|
|
113
|
+
const slug = def.optional
|
|
114
|
+
? toggleOn(value) && typeof value.value === 'string'
|
|
115
|
+
? value.value
|
|
116
|
+
: null
|
|
117
|
+
: typeof value === 'string' && value
|
|
118
|
+
? value
|
|
119
|
+
: (def.default ?? null);
|
|
120
|
+
return slug ? (ctx.menus.get(slug) ?? null) : null;
|
|
121
|
+
}
|
|
122
|
+
case 'link': {
|
|
123
|
+
if (def.optional && !toggleOn(value))
|
|
124
|
+
return null;
|
|
125
|
+
if (!isRecord(value) || typeof value.url !== 'string' || value.url === '')
|
|
126
|
+
return null;
|
|
127
|
+
return { label: typeof value.label === 'string' ? value.label : '', url: value.url };
|
|
128
|
+
}
|
|
129
|
+
case 'text': {
|
|
130
|
+
if (def.optional) {
|
|
131
|
+
return toggleOn(value) && typeof value.value === 'string'
|
|
132
|
+
? fillTokens(value.value, def, ctx.now)
|
|
133
|
+
: null;
|
|
134
|
+
}
|
|
135
|
+
return fillTokens(typeof value === 'string' ? value : '', def, ctx.now);
|
|
136
|
+
}
|
|
137
|
+
case 'textarea':
|
|
138
|
+
return typeof value === 'string' ? value : '';
|
|
139
|
+
case 'select':
|
|
140
|
+
return typeof value === 'string' ? value : (def.default ?? def.options[0] ?? '');
|
|
141
|
+
case 'boolean':
|
|
142
|
+
return typeof value === 'boolean' ? value : (def.default ?? false);
|
|
143
|
+
case 'social':
|
|
144
|
+
return Array.isArray(value) ? value : [];
|
|
145
|
+
default:
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/** A region as the site receives it, every field filled in, in schema order. */
|
|
150
|
+
export function publicRegion(schema, region, ctx) {
|
|
151
|
+
const fields = {};
|
|
152
|
+
for (const [key, def] of Object.entries(schema.fields)) {
|
|
153
|
+
fields[key] = publicField(def, ownValue(region.values, key), ctx);
|
|
154
|
+
}
|
|
155
|
+
return { variant: region.variant, fields };
|
|
156
|
+
}
|
|
157
|
+
/** Weak ETag over the response body, so an unchanged chrome answers 304. */
|
|
158
|
+
function chromeEtag(body) {
|
|
159
|
+
const hash = createHash('sha256').update(JSON.stringify(body)).digest('hex').slice(0, 20);
|
|
160
|
+
return `W/"chrome-${hash}"`;
|
|
161
|
+
}
|
|
162
|
+
export function withEtag(body) {
|
|
163
|
+
return { ...body, etag: chromeEtag(body) };
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/chrome/resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tell the site its chrome changed, after the write has committed: the signed
|
|
3
|
+
* `chrome.updated` webhook (to the Developer tab's revalidate URL and any other
|
|
4
|
+
* endpoint subscribed to it) and the `prenta:chrome` cache tag. Chrome is on
|
|
5
|
+
* every page, so the wholesale `prenta` tag goes too, as for a global write.
|
|
6
|
+
* Never throws: the write already succeeded.
|
|
7
|
+
*/
|
|
8
|
+
export declare function revalidateChrome(region: string): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=revalidate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revalidate.d.ts","sourceRoot":"","sources":["../../src/chrome/revalidate.ts"],"names":[],"mappings":"AAMA;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCpE"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { PRENTA_CHROME_TAG, PRENTA_TAG_ROOT } from '../cache/http.js';
|
|
2
|
+
import { getPrentaConfig } from '../config/runtime.js';
|
|
3
|
+
import { createLogger } from '../diagnostics/logger.js';
|
|
4
|
+
const logger = createLogger('chrome');
|
|
5
|
+
/**
|
|
6
|
+
* Tell the site its chrome changed, after the write has committed: the signed
|
|
7
|
+
* `chrome.updated` webhook (to the Developer tab's revalidate URL and any other
|
|
8
|
+
* endpoint subscribed to it) and the `prenta:chrome` cache tag. Chrome is on
|
|
9
|
+
* every page, so the wholesale `prenta` tag goes too, as for a global write.
|
|
10
|
+
* Never throws: the write already succeeded.
|
|
11
|
+
*/
|
|
12
|
+
export async function revalidateChrome(region) {
|
|
13
|
+
const tags = [PRENTA_TAG_ROOT, PRENTA_CHROME_TAG];
|
|
14
|
+
const config = getPrentaConfig();
|
|
15
|
+
const adapter = config?.platform?.cache;
|
|
16
|
+
await Promise.all([
|
|
17
|
+
...tags.map(async (tag) => {
|
|
18
|
+
try {
|
|
19
|
+
await adapter?.invalidateTag(tag);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
logger.error('platform.cache invalidateTag failed, chrome may be stale until TTL', {
|
|
23
|
+
error: err instanceof Error ? err.message : String(err),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}),
|
|
27
|
+
(async () => {
|
|
28
|
+
try {
|
|
29
|
+
await config?.cache?.onInvalidate?.(tags);
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
logger.error('cache.onInvalidate failed, chrome may be stale until TTL', {
|
|
33
|
+
error: err instanceof Error ? err.message : String(err),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
})(),
|
|
37
|
+
(async () => {
|
|
38
|
+
try {
|
|
39
|
+
const { dispatch } = await import('../webhooks/index.js');
|
|
40
|
+
await dispatch('chrome.updated', { region });
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
logger.error('chrome.updated webhook dispatch failed', {
|
|
44
|
+
region,
|
|
45
|
+
error: err instanceof Error ? err.message : String(err),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
})(),
|
|
49
|
+
]);
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=revalidate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revalidate.js","sourceRoot":"","sources":["../../src/chrome/revalidate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEvD,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;AAErC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAc;IACnD,MAAM,IAAI,GAAG,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAA;IACjD,MAAM,MAAM,GAAG,eAAe,EAAE,CAAA;IAChC,MAAM,OAAO,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAA;IACvC,MAAM,OAAO,CAAC,GAAG,CAAC;QAChB,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACxB,IAAI,CAAC;gBACH,MAAM,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,CAAA;YACnC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,oEAAoE,EAAE;oBACjF,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;iBACxD,CAAC,CAAA;YACJ,CAAC;QACH,CAAC,CAAC;QACF,CAAC,KAAK,IAAI,EAAE;YACV,IAAI,CAAC;gBACH,MAAM,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,IAAI,CAAC,CAAA;YAC3C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,0DAA0D,EAAE;oBACvE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;iBACxD,CAAC,CAAA;YACJ,CAAC;QACH,CAAC,CAAC,EAAE;QACJ,CAAC,KAAK,IAAI,EAAE;YACV,IAAI,CAAC;gBACH,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAA;gBACzD,MAAM,QAAQ,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;YAC9C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,wCAAwC,EAAE;oBACrD,MAAM;oBACN,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;iBACxD,CAAC,CAAA;YACJ,CAAC;QACH,CAAC,CAAC,EAAE;KACL,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Site chrome endpoints (DATA_CONTRACTS §2). Admin endpoints live at
|
|
3
|
+
* `/chrome/*`; the site reads `/public/chrome?path=`.
|
|
4
|
+
*
|
|
5
|
+
* Access: anyone signed in may read; saving values, the announcement or
|
|
6
|
+
* "Remove now" needs a role that can publish (a save goes live at once);
|
|
7
|
+
* pushing the schema and the Developer tab's settings need an admin. API keys
|
|
8
|
+
* also need the `chrome` global scope (or admin scope), and for a write the
|
|
9
|
+
* action it takes (`update` or `create`; `delete` for "Remove now"), so a
|
|
10
|
+
* read-only key can't save.
|
|
11
|
+
*/
|
|
12
|
+
import type { ApiRouter } from '../api/router.js';
|
|
13
|
+
export declare function registerChromeRoutes(router: ApiRouter): void;
|
|
14
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/chrome/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AA4IjD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAgP5D"}
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
import { guardedDb } from '../api/guarded-db.js';
|
|
2
|
+
import { ADMIN_ROLES, errorResponse, internalError, json, jsonWithCache, requireAuth, requireCollectionScope, requireGlobalScope, requireRole, requireStaffAccess, } from '../api/route-helpers.js';
|
|
3
|
+
import { cachedRead } from '../cache/http.js';
|
|
4
|
+
import { getPrentaConfig } from '../config/runtime.js';
|
|
5
|
+
import { loadUserRefs } from '../jobs/serialize.js';
|
|
6
|
+
import { logEvent } from '../security/audit.js';
|
|
7
|
+
import { listChromeOverrides } from './overrides.js';
|
|
8
|
+
import { parseSchemaRead } from './parse.js';
|
|
9
|
+
import { PrismaChromeStore } from './prisma-store.js';
|
|
10
|
+
import { chromeReadTags, loadPublicChrome, normalizeChromePath } from './public.js';
|
|
11
|
+
import { revalidateChrome } from './revalidate.js';
|
|
12
|
+
import { CHROME_REGIONS } from './schema.js';
|
|
13
|
+
import { announcementEtag, getAnnouncement, getChromeSchema, getRegion, readChromeSchema, readIfMatch, regionEtag, removeOrphan, saveAnnouncement, saveRegion, } from './service.js';
|
|
14
|
+
import { getChromeSettings, saveChromeSettings } from './settings.js';
|
|
15
|
+
/** The API key global scope that covers `/chrome/*`. */
|
|
16
|
+
const CHROME_SCOPE = 'chrome';
|
|
17
|
+
/** Who can save chrome: a save is live at once, so the roles that can publish. */
|
|
18
|
+
const EDIT_ROLES = new Set(['OWNER', 'ADMIN', 'EDITOR']);
|
|
19
|
+
function isFailure(value) {
|
|
20
|
+
return typeof value === 'object' && value !== null && value.ok === false;
|
|
21
|
+
}
|
|
22
|
+
function failure(result) {
|
|
23
|
+
return errorResponse(result.error, result.status);
|
|
24
|
+
}
|
|
25
|
+
function withHeader(response, name, value) {
|
|
26
|
+
response.headers.set(name, value);
|
|
27
|
+
return response;
|
|
28
|
+
}
|
|
29
|
+
function regionParam(value) {
|
|
30
|
+
return CHROME_REGIONS.includes(value ?? '')
|
|
31
|
+
? value
|
|
32
|
+
: null;
|
|
33
|
+
}
|
|
34
|
+
function decodeParam(value) {
|
|
35
|
+
try {
|
|
36
|
+
return decodeURIComponent(value ?? '');
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return value ?? '';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function readSession(request) {
|
|
43
|
+
const auth = await requireAuth(request);
|
|
44
|
+
if (auth.error)
|
|
45
|
+
return auth.error;
|
|
46
|
+
return requireGlobalScope(auth.session, CHROME_SCOPE) ?? auth.session;
|
|
47
|
+
}
|
|
48
|
+
async function writeSession(request, roles) {
|
|
49
|
+
const session = await readSession(request);
|
|
50
|
+
if (session instanceof Response)
|
|
51
|
+
return session;
|
|
52
|
+
// An API key's actions must allow the method, as on every other staff write.
|
|
53
|
+
return requireStaffAccess(session, request) ?? requireRole(session.role, roles) ?? session;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Whether the session may list a collection's pages: an API key needs the
|
|
57
|
+
* collection's read scope, and a collection's own `access.read` rule applies,
|
|
58
|
+
* as it does to `GET /collections/:slug`. Published pages are readable by
|
|
59
|
+
* every role otherwise.
|
|
60
|
+
*/
|
|
61
|
+
async function canReadCollection(session, config, collection) {
|
|
62
|
+
if (requireCollectionScope(session, collection, 'read'))
|
|
63
|
+
return false;
|
|
64
|
+
// A collection the config no longer has: its pages don't resolve, so their
|
|
65
|
+
// overrides never apply and their editor links go nowhere.
|
|
66
|
+
const collections = config?.collections ?? {};
|
|
67
|
+
if (Object.keys(collections).length > 0 && !Object.hasOwn(collections, collection)) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
const read = config?.collections?.[collection]?.access?.read;
|
|
71
|
+
if (!read)
|
|
72
|
+
return true;
|
|
73
|
+
try {
|
|
74
|
+
return Boolean(await read({ user: { id: session.userId, role: session.role } }));
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function serializeRegion(region, view, refs) {
|
|
81
|
+
const { row } = view;
|
|
82
|
+
return {
|
|
83
|
+
region,
|
|
84
|
+
variant: view.variant,
|
|
85
|
+
fields: row.values,
|
|
86
|
+
orphans: view.orphans,
|
|
87
|
+
updatedBy: row.updatedById ? (refs.get(row.updatedById) ?? null) : null,
|
|
88
|
+
updatedAt: row.updatedAt ? row.updatedAt.toISOString() : null,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function weakMatch(header, etag) {
|
|
92
|
+
if (!header)
|
|
93
|
+
return false;
|
|
94
|
+
return header.split(',').some((tag) => {
|
|
95
|
+
const value = tag.trim();
|
|
96
|
+
return value === '*' || value === etag || value.replace(/^W\//, '') === etag.replace(/^W\//, '');
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
export function registerChromeRoutes(router) {
|
|
100
|
+
const db = guardedDb;
|
|
101
|
+
const store = () => new PrismaChromeStore(db());
|
|
102
|
+
async function regionResponse(region, view, now) {
|
|
103
|
+
const refs = await loadUserRefs(db(), view.row.updatedById ? [view.row.updatedById] : []);
|
|
104
|
+
return withHeader(json({ data: serializeRegion(region, view, refs) }), 'ETag', regionEtag(view.row, now));
|
|
105
|
+
}
|
|
106
|
+
router.get('/chrome/schema', async (request) => {
|
|
107
|
+
try {
|
|
108
|
+
const session = await readSession(request);
|
|
109
|
+
if (session instanceof Response)
|
|
110
|
+
return session;
|
|
111
|
+
return json({ data: await getChromeSchema(store()) });
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
return internalError(err, 'chrome schema');
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
router.put('/chrome/schema', async (request) => {
|
|
118
|
+
try {
|
|
119
|
+
const session = await writeSession(request, ADMIN_ROLES);
|
|
120
|
+
if (session instanceof Response)
|
|
121
|
+
return session;
|
|
122
|
+
const body = await request.json().catch(() => null);
|
|
123
|
+
const input = parseSchemaRead(body);
|
|
124
|
+
if (!input.ok)
|
|
125
|
+
return errorResponse(input.error, 400);
|
|
126
|
+
const result = await readChromeSchema(store(), input.value, {
|
|
127
|
+
userId: session.userId,
|
|
128
|
+
now: new Date(),
|
|
129
|
+
});
|
|
130
|
+
if (isFailure(result)) {
|
|
131
|
+
// A region before the one that failed may already be written, and pushing
|
|
132
|
+
// again won't see it as changed. Revalidating an unchanged region is harmless.
|
|
133
|
+
for (const region of CHROME_REGIONS)
|
|
134
|
+
await revalidateChrome(region);
|
|
135
|
+
return failure(result);
|
|
136
|
+
}
|
|
137
|
+
for (const region of result.regions) {
|
|
138
|
+
if (region.changed)
|
|
139
|
+
await revalidateChrome(region.region);
|
|
140
|
+
}
|
|
141
|
+
await logEvent({
|
|
142
|
+
event: 'settings_changed',
|
|
143
|
+
userId: session.userId,
|
|
144
|
+
details: {
|
|
145
|
+
action: 'chrome_schema_read',
|
|
146
|
+
commit: result.source.commit,
|
|
147
|
+
regions: result.regions.filter((region) => region.changed).map((region) => region.region),
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
return json({ data: result });
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
return internalError(err, 'chrome schema read');
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
router.get('/chrome/settings', async (request) => {
|
|
157
|
+
try {
|
|
158
|
+
const session = await readSession(request);
|
|
159
|
+
if (session instanceof Response)
|
|
160
|
+
return session;
|
|
161
|
+
return json({
|
|
162
|
+
data: await getChromeSettings(db(), { admin: ADMIN_ROLES.has(session.role) }),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
return internalError(err, 'chrome settings');
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
router.put('/chrome/settings', async (request) => {
|
|
170
|
+
try {
|
|
171
|
+
const session = await writeSession(request, ADMIN_ROLES);
|
|
172
|
+
if (session instanceof Response)
|
|
173
|
+
return session;
|
|
174
|
+
const body = await request.json().catch(() => null);
|
|
175
|
+
const result = await saveChromeSettings(db(), body);
|
|
176
|
+
if (isFailure(result))
|
|
177
|
+
return failure(result);
|
|
178
|
+
await logEvent({
|
|
179
|
+
event: 'settings_changed',
|
|
180
|
+
userId: session.userId,
|
|
181
|
+
details: {
|
|
182
|
+
action: 'chrome_settings_changed',
|
|
183
|
+
revalidateUrl: result.settings.revalidateUrl,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
return json({
|
|
187
|
+
data: { ...result.settings, ...(result.secret ? { secret: result.secret } : {}) },
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
return internalError(err, 'chrome settings save');
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
router.get('/chrome/announcement', async (request) => {
|
|
195
|
+
try {
|
|
196
|
+
const session = await readSession(request);
|
|
197
|
+
if (session instanceof Response)
|
|
198
|
+
return session;
|
|
199
|
+
const { announcement } = await getAnnouncement(store());
|
|
200
|
+
return withHeader(json({ data: announcement }), 'ETag', announcementEtag(announcement));
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
return internalError(err, 'chrome announcement');
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
router.put('/chrome/announcement', async (request) => {
|
|
207
|
+
try {
|
|
208
|
+
const session = await writeSession(request, EDIT_ROLES);
|
|
209
|
+
if (session instanceof Response)
|
|
210
|
+
return session;
|
|
211
|
+
const body = await request.json().catch(() => null);
|
|
212
|
+
const result = await saveAnnouncement(store(), body, {
|
|
213
|
+
userId: session.userId,
|
|
214
|
+
ifMatch: readIfMatch(request),
|
|
215
|
+
now: new Date(),
|
|
216
|
+
});
|
|
217
|
+
if (isFailure(result))
|
|
218
|
+
return failure(result);
|
|
219
|
+
await revalidateChrome('announcement');
|
|
220
|
+
return withHeader(json({ data: result.announcement }), 'ETag', announcementEtag(result.announcement));
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
return internalError(err, 'chrome announcement save');
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
// The pages whose `_layout` overrides a region, for the "Page overrides"
|
|
227
|
+
// card. A page shows only when the reader may read its collection.
|
|
228
|
+
router.get('/chrome/overrides', async (request) => {
|
|
229
|
+
try {
|
|
230
|
+
const session = await readSession(request);
|
|
231
|
+
if (session instanceof Response)
|
|
232
|
+
return session;
|
|
233
|
+
const config = getPrentaConfig() ?? null;
|
|
234
|
+
const list = await listChromeOverrides(db(), config, {
|
|
235
|
+
canRead: (collection) => canReadCollection(session, config, collection),
|
|
236
|
+
});
|
|
237
|
+
return json({ data: list });
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
return internalError(err, 'chrome overrides');
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
router.get('/chrome/:region', async (request, params) => {
|
|
244
|
+
try {
|
|
245
|
+
const session = await readSession(request);
|
|
246
|
+
if (session instanceof Response)
|
|
247
|
+
return session;
|
|
248
|
+
const region = regionParam(params.region);
|
|
249
|
+
if (!region)
|
|
250
|
+
return errorResponse('Unknown chrome region', 404);
|
|
251
|
+
const now = new Date();
|
|
252
|
+
const view = await getRegion(store(), region, now);
|
|
253
|
+
if (isFailure(view))
|
|
254
|
+
return failure(view);
|
|
255
|
+
return regionResponse(region, view, now);
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
return internalError(err, 'chrome region');
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
router.put('/chrome/:region', async (request, params) => {
|
|
262
|
+
try {
|
|
263
|
+
const session = await writeSession(request, EDIT_ROLES);
|
|
264
|
+
if (session instanceof Response)
|
|
265
|
+
return session;
|
|
266
|
+
const region = regionParam(params.region);
|
|
267
|
+
if (!region)
|
|
268
|
+
return errorResponse('Unknown chrome region', 404);
|
|
269
|
+
const body = await request.json().catch(() => null);
|
|
270
|
+
const now = new Date();
|
|
271
|
+
const view = await saveRegion(store(), region, body, {
|
|
272
|
+
userId: session.userId,
|
|
273
|
+
ifMatch: readIfMatch(request),
|
|
274
|
+
now,
|
|
275
|
+
});
|
|
276
|
+
if (isFailure(view))
|
|
277
|
+
return failure(view);
|
|
278
|
+
await revalidateChrome(region);
|
|
279
|
+
return regionResponse(region, view, now);
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
return internalError(err, 'chrome region save');
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
router.delete('/chrome/:region/orphans/:key', async (request, params) => {
|
|
286
|
+
try {
|
|
287
|
+
const session = await writeSession(request, EDIT_ROLES);
|
|
288
|
+
if (session instanceof Response)
|
|
289
|
+
return session;
|
|
290
|
+
const region = regionParam(params.region);
|
|
291
|
+
if (!region)
|
|
292
|
+
return errorResponse('Unknown chrome region', 404);
|
|
293
|
+
const now = new Date();
|
|
294
|
+
const view = await removeOrphan(store(), region, decodeParam(params.key), {
|
|
295
|
+
userId: session.userId,
|
|
296
|
+
now,
|
|
297
|
+
});
|
|
298
|
+
if (isFailure(view))
|
|
299
|
+
return failure(view);
|
|
300
|
+
// Orphans never reach the site, so there is nothing to revalidate.
|
|
301
|
+
return regionResponse(region, view, now);
|
|
302
|
+
}
|
|
303
|
+
catch (err) {
|
|
304
|
+
return internalError(err, 'chrome orphan remove');
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
// Public, for the site: site defaults, page overrides and the announcement
|
|
308
|
+
// schedule, resolved for one path. Cached like the other public reads, with
|
|
309
|
+
// an ETag so an unchanged chrome answers 304.
|
|
310
|
+
router.get('/public/chrome', async (request) => {
|
|
311
|
+
try {
|
|
312
|
+
const path = normalizeChromePath(new URL(request.url).searchParams.get('path'));
|
|
313
|
+
if (!path) {
|
|
314
|
+
return errorResponse('Send the page path, like ?path=/about', 400);
|
|
315
|
+
}
|
|
316
|
+
const config = getPrentaConfig();
|
|
317
|
+
return cachedRead(request, {
|
|
318
|
+
cache: config?.cache,
|
|
319
|
+
tags: chromeReadTags(config ?? null, path),
|
|
320
|
+
wrap: (payload, req) => {
|
|
321
|
+
const body = payload;
|
|
322
|
+
const etag = body.data.etag;
|
|
323
|
+
if (weakMatch(req.headers.get('if-none-match'), etag)) {
|
|
324
|
+
const notModified = new Response(null, { status: 304 });
|
|
325
|
+
const cacheControl = jsonWithCache(null, req).headers.get('Cache-Control');
|
|
326
|
+
if (cacheControl)
|
|
327
|
+
notModified.headers.set('Cache-Control', cacheControl);
|
|
328
|
+
notModified.headers.set('ETag', etag);
|
|
329
|
+
return notModified;
|
|
330
|
+
}
|
|
331
|
+
return withHeader(jsonWithCache(body, req), 'ETag', etag);
|
|
332
|
+
},
|
|
333
|
+
build: async () => ({
|
|
334
|
+
data: await loadPublicChrome({
|
|
335
|
+
db: db(),
|
|
336
|
+
store: store(),
|
|
337
|
+
config: config ?? null,
|
|
338
|
+
path,
|
|
339
|
+
now: new Date(),
|
|
340
|
+
}),
|
|
341
|
+
}),
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
catch (err) {
|
|
345
|
+
return internalError(err, 'public chrome');
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/chrome/routes.ts"],"names":[],"mappings":"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"}
|