gazetta 0.4.0 → 0.6.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/admin-dist/assets/index-B6pVot0Y.css +1 -0
- package/admin-dist/assets/index-DniLwxJA.js +609 -0
- package/admin-dist/assets/{vendor-primevue-BnR1c_bQ.js → vendor-primevue-C0Q_YTCb.js} +330 -431
- package/admin-dist/assets/vendor-vue-D3wBSmDf.js +1 -0
- package/admin-dist/index.html +4 -4
- package/dist/admin-api/index.d.ts +26 -5
- package/dist/admin-api/index.d.ts.map +1 -1
- package/dist/admin-api/index.js +175 -13
- package/dist/admin-api/index.js.map +1 -1
- package/dist/admin-api/routes/compare.d.ts +3 -1
- package/dist/admin-api/routes/compare.d.ts.map +1 -1
- package/dist/admin-api/routes/compare.js +34 -24
- package/dist/admin-api/routes/compare.js.map +1 -1
- package/dist/admin-api/routes/fields.d.ts +2 -2
- package/dist/admin-api/routes/fields.d.ts.map +1 -1
- package/dist/admin-api/routes/fields.js +10 -3
- package/dist/admin-api/routes/fields.js.map +1 -1
- package/dist/admin-api/routes/fragments.d.ts +2 -2
- package/dist/admin-api/routes/fragments.d.ts.map +1 -1
- package/dist/admin-api/routes/fragments.js +94 -19
- package/dist/admin-api/routes/fragments.js.map +1 -1
- package/dist/admin-api/routes/history.d.ts +23 -0
- package/dist/admin-api/routes/history.d.ts.map +1 -0
- package/dist/admin-api/routes/history.js +143 -0
- package/dist/admin-api/routes/history.js.map +1 -0
- package/dist/admin-api/routes/pages.d.ts +2 -2
- package/dist/admin-api/routes/pages.d.ts.map +1 -1
- package/dist/admin-api/routes/pages.js +120 -20
- package/dist/admin-api/routes/pages.js.map +1 -1
- package/dist/admin-api/routes/preview.d.ts +2 -2
- package/dist/admin-api/routes/preview.d.ts.map +1 -1
- package/dist/admin-api/routes/preview.js +50 -15
- package/dist/admin-api/routes/preview.js.map +1 -1
- package/dist/admin-api/routes/publish.d.ts +3 -1
- package/dist/admin-api/routes/publish.d.ts.map +1 -1
- package/dist/admin-api/routes/publish.js +306 -65
- package/dist/admin-api/routes/publish.js.map +1 -1
- package/dist/admin-api/routes/site.d.ts +2 -2
- package/dist/admin-api/routes/site.d.ts.map +1 -1
- package/dist/admin-api/routes/site.js +27 -4
- package/dist/admin-api/routes/site.js.map +1 -1
- package/dist/admin-api/routes/templates.d.ts +2 -2
- package/dist/admin-api/routes/templates.d.ts.map +1 -1
- package/dist/admin-api/routes/templates.js +19 -9
- package/dist/admin-api/routes/templates.js.map +1 -1
- package/dist/admin-api/schemas/compare.d.ts +29 -0
- package/dist/admin-api/schemas/compare.d.ts.map +1 -0
- package/dist/admin-api/schemas/compare.js +30 -0
- package/dist/admin-api/schemas/compare.js.map +1 -0
- package/dist/admin-api/schemas/dependents.d.ts +15 -0
- package/dist/admin-api/schemas/dependents.d.ts.map +1 -0
- package/dist/admin-api/schemas/dependents.js +14 -0
- package/dist/admin-api/schemas/dependents.js.map +1 -0
- package/dist/admin-api/schemas/fetch.d.ts +12 -0
- package/dist/admin-api/schemas/fetch.d.ts.map +1 -0
- package/dist/admin-api/schemas/fetch.js +11 -0
- package/dist/admin-api/schemas/fetch.js.map +1 -0
- package/dist/admin-api/schemas/fields.d.ts +11 -0
- package/dist/admin-api/schemas/fields.d.ts.map +1 -0
- package/dist/admin-api/schemas/fields.js +11 -0
- package/dist/admin-api/schemas/fields.js.map +1 -0
- package/dist/admin-api/schemas/fragments.d.ts +27 -0
- package/dist/admin-api/schemas/fragments.d.ts.map +1 -0
- package/dist/admin-api/schemas/fragments.js +26 -0
- package/dist/admin-api/schemas/fragments.js.map +1 -0
- package/dist/admin-api/schemas/history.d.ts +73 -0
- package/dist/admin-api/schemas/history.d.ts.map +1 -0
- package/dist/admin-api/schemas/history.js +35 -0
- package/dist/admin-api/schemas/history.js.map +1 -0
- package/dist/admin-api/schemas/index.d.ts +32 -0
- package/dist/admin-api/schemas/index.d.ts.map +1 -0
- package/dist/admin-api/schemas/index.js +32 -0
- package/dist/admin-api/schemas/index.js.map +1 -0
- package/dist/admin-api/schemas/pages.d.ts +46 -0
- package/dist/admin-api/schemas/pages.d.ts.map +1 -0
- package/dist/admin-api/schemas/pages.js +47 -0
- package/dist/admin-api/schemas/pages.js.map +1 -0
- package/dist/admin-api/schemas/publish.d.ts +67 -0
- package/dist/admin-api/schemas/publish.d.ts.map +1 -0
- package/dist/admin-api/schemas/publish.js +60 -0
- package/dist/admin-api/schemas/publish.js.map +1 -0
- package/dist/admin-api/schemas/site.d.ts +28 -0
- package/dist/admin-api/schemas/site.d.ts.map +1 -0
- package/dist/admin-api/schemas/site.js +24 -0
- package/dist/admin-api/schemas/site.js.map +1 -0
- package/dist/admin-api/schemas/targets.d.ts +36 -0
- package/dist/admin-api/schemas/targets.d.ts.map +1 -0
- package/dist/admin-api/schemas/targets.js +19 -0
- package/dist/admin-api/schemas/targets.js.map +1 -0
- package/dist/admin-api/schemas/templates.d.ts +17 -0
- package/dist/admin-api/schemas/templates.d.ts.map +1 -0
- package/dist/admin-api/schemas/templates.js +16 -0
- package/dist/admin-api/schemas/templates.js.map +1 -0
- package/dist/admin-api/source-context.d.ts +165 -0
- package/dist/admin-api/source-context.d.ts.map +1 -0
- package/dist/admin-api/source-context.js +95 -0
- package/dist/admin-api/source-context.js.map +1 -0
- package/dist/app.js +1 -1
- package/dist/app.js.map +1 -1
- package/dist/assemble.d.ts.map +1 -1
- package/dist/assemble.js +4 -1
- package/dist/assemble.js.map +1 -1
- package/dist/cli/bootstrap.d.ts +48 -0
- package/dist/cli/bootstrap.d.ts.map +1 -0
- package/dist/cli/bootstrap.js +85 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/history.d.ts +45 -0
- package/dist/cli/history.d.ts.map +1 -0
- package/dist/cli/history.js +165 -0
- package/dist/cli/history.js.map +1 -0
- package/dist/cli/index.js +691 -113
- package/dist/cli/index.js.map +1 -1
- package/dist/compare.d.ts +15 -5
- package/dist/compare.d.ts.map +1 -1
- package/dist/compare.js +83 -45
- package/dist/compare.js.map +1 -1
- package/dist/concurrency.d.ts +63 -0
- package/dist/concurrency.d.ts.map +1 -0
- package/dist/concurrency.js +134 -0
- package/dist/concurrency.js.map +1 -0
- package/dist/content-root.d.ts +38 -0
- package/dist/content-root.d.ts.map +1 -0
- package/dist/content-root.js +29 -0
- package/dist/content-root.js.map +1 -0
- package/dist/editor/mount.d.ts +1 -1
- package/dist/editor/mount.d.ts.map +1 -1
- package/dist/editor/mount.js +61 -29
- package/dist/editor/mount.js.map +1 -1
- package/dist/hash.d.ts +47 -1
- package/dist/hash.d.ts.map +1 -1
- package/dist/hash.js +107 -10
- package/dist/hash.js.map +1 -1
- package/dist/history-provider.d.ts +49 -0
- package/dist/history-provider.d.ts.map +1 -0
- package/dist/history-provider.js +226 -0
- package/dist/history-provider.js.map +1 -0
- package/dist/history-recorder.d.ts +98 -0
- package/dist/history-recorder.d.ts.map +1 -0
- package/dist/history-recorder.js +160 -0
- package/dist/history-recorder.js.map +1 -0
- package/dist/history-restorer.d.ts +46 -0
- package/dist/history-restorer.d.ts.map +1 -0
- package/dist/history-restorer.js +105 -0
- package/dist/history-restorer.js.map +1 -0
- package/dist/history.d.ts +111 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +25 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +26 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -3
- package/dist/index.js.map +1 -1
- package/dist/locale.d.ts +74 -0
- package/dist/locale.d.ts.map +1 -0
- package/dist/locale.js +150 -0
- package/dist/locale.js.map +1 -0
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +16 -1
- package/dist/manifest.js.map +1 -1
- package/dist/providers/azure-blob.d.ts.map +1 -1
- package/dist/providers/azure-blob.js.map +1 -1
- package/dist/providers/r2.d.ts.map +1 -1
- package/dist/providers/r2.js +7 -4
- package/dist/providers/r2.js.map +1 -1
- package/dist/providers/s3.d.ts.map +1 -1
- package/dist/providers/s3.js +23 -15
- package/dist/providers/s3.js.map +1 -1
- package/dist/publish-locale.d.ts +44 -0
- package/dist/publish-locale.d.ts.map +1 -0
- package/dist/publish-locale.js +103 -0
- package/dist/publish-locale.js.map +1 -0
- package/dist/publish-rendered.d.ts +17 -5
- package/dist/publish-rendered.d.ts.map +1 -1
- package/dist/publish-rendered.js +114 -66
- package/dist/publish-rendered.js.map +1 -1
- package/dist/publish.d.ts +39 -3
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +166 -17
- package/dist/publish.js.map +1 -1
- package/dist/renderer.d.ts +14 -4
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +35 -23
- package/dist/renderer.js.map +1 -1
- package/dist/resolver.d.ts +7 -2
- package/dist/resolver.d.ts.map +1 -1
- package/dist/resolver.js +66 -15
- package/dist/resolver.js.map +1 -1
- package/dist/robots.d.ts +22 -0
- package/dist/robots.d.ts.map +1 -0
- package/dist/robots.js +25 -0
- package/dist/robots.js.map +1 -0
- package/dist/seo.d.ts +56 -0
- package/dist/seo.d.ts.map +1 -0
- package/dist/seo.js +72 -0
- package/dist/seo.js.map +1 -0
- package/dist/serve.d.ts +41 -3
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +206 -65
- package/dist/serve.js.map +1 -1
- package/dist/sidecars.d.ts +60 -0
- package/dist/sidecars.d.ts.map +1 -0
- package/dist/sidecars.js +231 -0
- package/dist/sidecars.js.map +1 -0
- package/dist/site-loader.d.ts +74 -6
- package/dist/site-loader.d.ts.map +1 -1
- package/dist/site-loader.js +149 -36
- package/dist/site-loader.js.map +1 -1
- package/dist/sitemap.d.ts +45 -0
- package/dist/sitemap.d.ts.map +1 -0
- package/dist/sitemap.js +67 -0
- package/dist/sitemap.js.map +1 -0
- package/dist/source-sidecars.d.ts +32 -0
- package/dist/source-sidecars.d.ts.map +1 -0
- package/dist/source-sidecars.js +98 -0
- package/dist/source-sidecars.js.map +1 -0
- package/dist/targets.d.ts +47 -1
- package/dist/targets.d.ts.map +1 -1
- package/dist/targets.js +78 -9
- package/dist/targets.js.map +1 -1
- package/dist/template-loader.d.ts +7 -3
- package/dist/template-loader.d.ts.map +1 -1
- package/dist/template-loader.js +27 -12
- package/dist/template-loader.js.map +1 -1
- package/dist/templates-scan-worker.js +1 -1
- package/dist/templates-scan-worker.js.map +1 -1
- package/dist/templates-scan.d.ts.map +1 -1
- package/dist/templates-scan.js +1 -1
- package/dist/templates-scan.js.map +1 -1
- package/dist/types.d.ts +116 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +28 -5
- package/dist/types.js.map +1 -1
- package/dist/workers/cloudflare-r2.d.ts +11 -2
- package/dist/workers/cloudflare-r2.d.ts.map +1 -1
- package/dist/workers/cloudflare-r2.js +120 -55
- package/dist/workers/cloudflare-r2.js.map +1 -1
- package/package.json +11 -2
- package/admin-dist/assets/index-Bh_y1d_l.css +0 -1
- package/admin-dist/assets/index-DjGNi6yy.js +0 -608
- package/admin-dist/assets/vendor-vue-DSjyxCX6.js +0 -1
|
@@ -1,22 +1,47 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { loadSiteFromSource } from '../source-context.js';
|
|
4
|
+
import { recordWrite } from '../../history-recorder.js';
|
|
5
|
+
import { CreateFragmentRequestSchema } from '../schemas/fragments.js';
|
|
6
|
+
import { isValidLocale } from '../../locale.js';
|
|
7
|
+
export function fragmentRoutes(resolve) {
|
|
5
8
|
const app = new Hono();
|
|
6
9
|
app.get('/api/fragments', async (c) => {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
const source = await resolve(c.req.query('target'));
|
|
11
|
+
// Empty target → empty list. See pages.ts for rationale.
|
|
12
|
+
try {
|
|
13
|
+
const site = await loadSiteFromSource(source);
|
|
14
|
+
const fragments = [...site.fragments.entries()].map(([name, frag]) => {
|
|
15
|
+
const localeEntry = site.fragmentLocales.get(name);
|
|
16
|
+
return {
|
|
17
|
+
name,
|
|
18
|
+
template: frag.template,
|
|
19
|
+
locales: localeEntry ? [...localeEntry.locales.keys()] : undefined,
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
return c.json(fragments);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
const msg = err.message;
|
|
26
|
+
if (msg.includes('No site.yaml found'))
|
|
27
|
+
return c.json([]);
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
13
30
|
});
|
|
14
31
|
app.post('/api/fragments', async (c) => {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
32
|
+
const source = await resolve(c.req.query('target'));
|
|
33
|
+
const { storage, sidecarWriter } = source;
|
|
34
|
+
// Schema-validate the body — same rationale as pages.ts.
|
|
35
|
+
const raw = await c.req.json();
|
|
36
|
+
const parsed = CreateFragmentRequestSchema.safeParse(raw);
|
|
37
|
+
if (!parsed.success) {
|
|
38
|
+
return c.json({
|
|
39
|
+
error: 'Invalid request body',
|
|
40
|
+
issues: parsed.error.issues.map(i => ({ path: i.path.join('.'), message: i.message })),
|
|
41
|
+
}, 400);
|
|
18
42
|
}
|
|
19
|
-
const
|
|
43
|
+
const body = parsed.data;
|
|
44
|
+
const fragDir = source.contentRoot.path('fragments', body.name);
|
|
20
45
|
const manifestPath = join(fragDir, 'fragment.json');
|
|
21
46
|
if (await storage.exists(manifestPath)) {
|
|
22
47
|
return c.json({ error: `Fragment "${body.name}" already exists` }, 409);
|
|
@@ -24,43 +49,93 @@ export function fragmentRoutes(siteDir, storage) {
|
|
|
24
49
|
await storage.mkdir(fragDir);
|
|
25
50
|
const manifest = { template: body.template, components: [] };
|
|
26
51
|
await storage.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
|
|
52
|
+
await sidecarWriter?.writeFor('fragment', body.name);
|
|
27
53
|
return c.json({ ok: true, name: body.name });
|
|
28
54
|
});
|
|
29
55
|
app.get('/api/fragments/:name', async (c) => {
|
|
30
56
|
const name = c.req.param('name');
|
|
31
|
-
const
|
|
32
|
-
const
|
|
57
|
+
const rawLocale = c.req.query('locale');
|
|
58
|
+
const locale = rawLocale && isValidLocale(rawLocale) ? rawLocale.toLowerCase() : undefined;
|
|
59
|
+
if (rawLocale && !locale)
|
|
60
|
+
return c.json({ error: `Invalid locale code: "${rawLocale}"` }, 400);
|
|
61
|
+
const source = await resolve(c.req.query('target'));
|
|
62
|
+
const site = await loadSiteFromSource(source);
|
|
63
|
+
let fragment = site.fragments.get(name);
|
|
64
|
+
if (locale) {
|
|
65
|
+
const localeEntry = site.fragmentLocales.get(name);
|
|
66
|
+
const localeVariant = localeEntry?.locales.get(locale);
|
|
67
|
+
if (localeVariant)
|
|
68
|
+
fragment = localeVariant;
|
|
69
|
+
else if (!fragment)
|
|
70
|
+
return c.json({ error: `Fragment "${name}" locale "${locale}" not found` }, 404);
|
|
71
|
+
}
|
|
33
72
|
if (!fragment)
|
|
34
73
|
return c.json({ error: `Fragment "${name}" not found` }, 404);
|
|
74
|
+
const localeEntry = site.fragmentLocales.get(name);
|
|
35
75
|
return c.json({
|
|
36
76
|
name,
|
|
37
77
|
template: fragment.template,
|
|
38
78
|
content: fragment.content,
|
|
39
79
|
components: fragment.components,
|
|
40
80
|
dir: fragment.dir,
|
|
81
|
+
locale: locale ?? undefined,
|
|
82
|
+
locales: localeEntry ? [...localeEntry.locales.keys()] : undefined,
|
|
41
83
|
});
|
|
42
84
|
});
|
|
43
85
|
app.put('/api/fragments/:name', async (c) => {
|
|
44
86
|
const name = c.req.param('name');
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
if (!
|
|
87
|
+
const rawLocale = c.req.query('locale');
|
|
88
|
+
const locale = rawLocale && isValidLocale(rawLocale) ? rawLocale.toLowerCase() : undefined;
|
|
89
|
+
if (rawLocale && !locale)
|
|
90
|
+
return c.json({ error: `Invalid locale code: "${rawLocale}"` }, 400);
|
|
91
|
+
const source = await resolve(c.req.query('target'));
|
|
92
|
+
const { storage, sidecarWriter } = source;
|
|
93
|
+
const site = await loadSiteFromSource(source);
|
|
94
|
+
const defaultFragment = site.fragments.get(name);
|
|
95
|
+
if (!defaultFragment)
|
|
48
96
|
return c.json({ error: `Fragment "${name}" not found` }, 404);
|
|
97
|
+
const localeVariant = locale ? site.fragmentLocales.get(name)?.locales.get(locale) : undefined;
|
|
98
|
+
const fragment = localeVariant ?? defaultFragment;
|
|
49
99
|
const body = await c.req.json();
|
|
50
100
|
const manifest = {
|
|
51
101
|
template: body.template ?? fragment.template,
|
|
52
102
|
content: body.content ?? fragment.content,
|
|
53
103
|
components: body.components ?? fragment.components,
|
|
54
104
|
};
|
|
55
|
-
|
|
105
|
+
const filename = locale ? `fragment.${locale}.json` : 'fragment.json';
|
|
106
|
+
const manifestPath = join(defaultFragment.dir, filename);
|
|
107
|
+
const serialized = JSON.stringify(manifest, null, 2) + '\n';
|
|
108
|
+
// History first — see pages.ts PUT handler rationale (baseline must
|
|
109
|
+
// capture pre-write state).
|
|
110
|
+
if (source.history) {
|
|
111
|
+
await recordWrite({
|
|
112
|
+
history: source.history,
|
|
113
|
+
contentRoot: source.contentRoot,
|
|
114
|
+
operation: 'save',
|
|
115
|
+
items: [{ path: source.contentRoot.relative(manifestPath), content: serialized }],
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
await storage.writeFile(manifestPath, serialized);
|
|
119
|
+
await sidecarWriter?.writeFor('fragment', name);
|
|
56
120
|
return c.json({ ok: true });
|
|
57
121
|
});
|
|
58
122
|
app.delete('/api/fragments/:name', async (c) => {
|
|
59
123
|
const name = c.req.param('name');
|
|
60
|
-
const
|
|
124
|
+
const source = await resolve(c.req.query('target'));
|
|
125
|
+
const { storage } = source;
|
|
126
|
+
const site = await loadSiteFromSource(source);
|
|
61
127
|
const fragment = site.fragments.get(name);
|
|
62
128
|
if (!fragment)
|
|
63
129
|
return c.json({ error: `Fragment "${name}" not found` }, 404);
|
|
130
|
+
const manifestPath = join(fragment.dir, 'fragment.json');
|
|
131
|
+
if (source.history) {
|
|
132
|
+
await recordWrite({
|
|
133
|
+
history: source.history,
|
|
134
|
+
contentRoot: source.contentRoot,
|
|
135
|
+
operation: 'save',
|
|
136
|
+
items: [{ path: source.contentRoot.relative(manifestPath), content: null }],
|
|
137
|
+
});
|
|
138
|
+
}
|
|
64
139
|
await storage.rm(fragment.dir);
|
|
65
140
|
return c.json({ ok: true });
|
|
66
141
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fragments.js","sourceRoot":"","sources":["../../../src/admin-api/routes/fragments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"fragments.js","sourceRoot":"","sources":["../../../src/admin-api/routes/fragments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* History endpoints.
|
|
3
|
+
*
|
|
4
|
+
* GET /api/history?target=<name> List revisions, newest first.
|
|
5
|
+
* POST /api/history/undo?target=<name> Restore the revision just before
|
|
6
|
+
* head — the "undo last write"
|
|
7
|
+
* affordance surfaced in the admin
|
|
8
|
+
* toolbar. Records a forward
|
|
9
|
+
* 'rollback' revision.
|
|
10
|
+
* POST /api/history/restore?target=<name>&id=<rev>
|
|
11
|
+
* Restore an arbitrary revision,
|
|
12
|
+
* used by the (future) history
|
|
13
|
+
* panel's per-row Restore button.
|
|
14
|
+
*
|
|
15
|
+
* Every write path routes through `restoreRevision` in core — soft undo
|
|
16
|
+
* only, forward-only history, operation='rollback' on the new
|
|
17
|
+
* revision. Route here just glues HTTP to the core.
|
|
18
|
+
*/
|
|
19
|
+
import { Hono } from 'hono';
|
|
20
|
+
import type { StorageProvider, TargetConfig } from '../../types.js';
|
|
21
|
+
import type { SourceContextResolver } from '../source-context.js';
|
|
22
|
+
export declare function historyRoutes(resolve: SourceContextResolver, preInitTargets?: Map<string, StorageProvider>, targetConfigs?: Record<string, TargetConfig>): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
23
|
+
//# sourceMappingURL=history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../../src/admin-api/routes/history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAKnE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAEjE,wBAAgB,aAAa,CAC3B,OAAO,EAAE,qBAAqB,EAC9B,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EAC7C,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,8EAiI7C"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* History endpoints.
|
|
3
|
+
*
|
|
4
|
+
* GET /api/history?target=<name> List revisions, newest first.
|
|
5
|
+
* POST /api/history/undo?target=<name> Restore the revision just before
|
|
6
|
+
* head — the "undo last write"
|
|
7
|
+
* affordance surfaced in the admin
|
|
8
|
+
* toolbar. Records a forward
|
|
9
|
+
* 'rollback' revision.
|
|
10
|
+
* POST /api/history/restore?target=<name>&id=<rev>
|
|
11
|
+
* Restore an arbitrary revision,
|
|
12
|
+
* used by the (future) history
|
|
13
|
+
* panel's per-row Restore button.
|
|
14
|
+
*
|
|
15
|
+
* Every write path routes through `restoreRevision` in core — soft undo
|
|
16
|
+
* only, forward-only history, operation='rollback' on the new
|
|
17
|
+
* revision. Route here just glues HTTP to the core.
|
|
18
|
+
*/
|
|
19
|
+
import { Hono } from 'hono';
|
|
20
|
+
import { isHistoryEnabled, getHistoryRetention } from '../../types.js';
|
|
21
|
+
import { createHistoryProvider } from '../../history-provider.js';
|
|
22
|
+
import { restoreRevision } from '../../history-restorer.js';
|
|
23
|
+
import { createContentRoot } from '../../content-root.js';
|
|
24
|
+
export function historyRoutes(resolve, preInitTargets, targetConfigs) {
|
|
25
|
+
const app = new Hono();
|
|
26
|
+
let targets = preInitTargets ?? null;
|
|
27
|
+
let targetsInitPromise = null;
|
|
28
|
+
/**
|
|
29
|
+
* Lazily build the cross-target registry on first call. Mirrors the
|
|
30
|
+
* pattern in publish.ts / compare.ts — the dev bootstrap pre-inits
|
|
31
|
+
* only the editable local target for startup speed; history endpoints
|
|
32
|
+
* can target any configured target (e.g. undo a publish on staging),
|
|
33
|
+
* so we lazy-init here on first use.
|
|
34
|
+
*/
|
|
35
|
+
async function getTargets(projectSiteDir) {
|
|
36
|
+
if (targets)
|
|
37
|
+
return targets;
|
|
38
|
+
if (!targetConfigs || Object.keys(targetConfigs).length === 0) {
|
|
39
|
+
targets = new Map();
|
|
40
|
+
return targets;
|
|
41
|
+
}
|
|
42
|
+
if (!targetsInitPromise) {
|
|
43
|
+
const { createTargetRegistry } = await import('../../targets.js');
|
|
44
|
+
targetsInitPromise = createTargetRegistry(targetConfigs, projectSiteDir)
|
|
45
|
+
.then(t => {
|
|
46
|
+
targets = t;
|
|
47
|
+
return t;
|
|
48
|
+
})
|
|
49
|
+
.catch(() => {
|
|
50
|
+
targets = new Map();
|
|
51
|
+
return new Map();
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return targetsInitPromise;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Resolve the target + config + history provider for this request.
|
|
58
|
+
* Returns an error object when the target isn't valid or has
|
|
59
|
+
* history disabled — callers pass the result through `respond`.
|
|
60
|
+
*/
|
|
61
|
+
async function resolveHistory(targetName, projectSiteDir) {
|
|
62
|
+
if (!targetName) {
|
|
63
|
+
return { kind: 'err', status: 400, body: { error: 'Missing "target" query parameter' } };
|
|
64
|
+
}
|
|
65
|
+
const t = await getTargets(projectSiteDir);
|
|
66
|
+
const storage = t.get(targetName);
|
|
67
|
+
const config = targetConfigs?.[targetName];
|
|
68
|
+
if (!storage || !config) {
|
|
69
|
+
return { kind: 'err', status: 400, body: { error: `Unknown target: ${targetName}` } };
|
|
70
|
+
}
|
|
71
|
+
if (!isHistoryEnabled(config)) {
|
|
72
|
+
return { kind: 'err', status: 409, body: { error: `History disabled for target "${targetName}"` } };
|
|
73
|
+
}
|
|
74
|
+
const history = createHistoryProvider({ storage, retention: getHistoryRetention(config) });
|
|
75
|
+
const contentRoot = createContentRoot(storage);
|
|
76
|
+
return { kind: 'ok', storage, config, history, contentRoot };
|
|
77
|
+
}
|
|
78
|
+
app.get('/api/history', async (c) => {
|
|
79
|
+
const source = await resolve(c.req.query('source'));
|
|
80
|
+
const targetName = c.req.query('target');
|
|
81
|
+
if (!targetName)
|
|
82
|
+
return c.json({ error: 'Missing "target" query parameter' }, 400);
|
|
83
|
+
const resolved = await resolveHistory(targetName, source.projectSiteDir);
|
|
84
|
+
if (resolved.kind === 'err')
|
|
85
|
+
return c.json(resolved.body, resolved.status);
|
|
86
|
+
const limit = Number(c.req.query('limit') ?? '50');
|
|
87
|
+
const revisions = await resolved.history.listRevisions(limit);
|
|
88
|
+
return c.json({ revisions });
|
|
89
|
+
});
|
|
90
|
+
app.post('/api/history/undo', async (c) => {
|
|
91
|
+
const source = await resolve(c.req.query('source'));
|
|
92
|
+
const targetName = c.req.query('target');
|
|
93
|
+
if (!targetName)
|
|
94
|
+
return c.json({ error: 'Missing "target" query parameter' }, 400);
|
|
95
|
+
const resolved = await resolveHistory(targetName, source.projectSiteDir);
|
|
96
|
+
if (resolved.kind === 'err')
|
|
97
|
+
return c.json(resolved.body, resolved.status);
|
|
98
|
+
const { history, contentRoot } = resolved;
|
|
99
|
+
// Undo = restore the revision just before head. Needs at least
|
|
100
|
+
// two revisions — one current + one to roll back to. No-op (with
|
|
101
|
+
// a clear 409) otherwise.
|
|
102
|
+
const list = await history.listRevisions(2);
|
|
103
|
+
if (list.length < 2) {
|
|
104
|
+
return c.json({ error: 'Nothing to undo — no prior revision on this target' }, 409);
|
|
105
|
+
}
|
|
106
|
+
const restored = await restoreRevision({
|
|
107
|
+
history,
|
|
108
|
+
contentRoot,
|
|
109
|
+
revisionId: list[1].id,
|
|
110
|
+
message: `Undo ${list[0].operation} (rev ${list[0].id})`,
|
|
111
|
+
});
|
|
112
|
+
return c.json({ revision: restored, restoredFrom: list[1].id });
|
|
113
|
+
});
|
|
114
|
+
app.post('/api/history/restore', async (c) => {
|
|
115
|
+
const source = await resolve(c.req.query('source'));
|
|
116
|
+
const targetName = c.req.query('target');
|
|
117
|
+
const revisionId = c.req.query('id');
|
|
118
|
+
if (!targetName)
|
|
119
|
+
return c.json({ error: 'Missing "target" query parameter' }, 400);
|
|
120
|
+
if (!revisionId)
|
|
121
|
+
return c.json({ error: 'Missing "id" query parameter' }, 400);
|
|
122
|
+
const resolved = await resolveHistory(targetName, source.projectSiteDir);
|
|
123
|
+
if (resolved.kind === 'err')
|
|
124
|
+
return c.json(resolved.body, resolved.status);
|
|
125
|
+
const { history, contentRoot } = resolved;
|
|
126
|
+
try {
|
|
127
|
+
const restored = await restoreRevision({
|
|
128
|
+
history,
|
|
129
|
+
contentRoot,
|
|
130
|
+
revisionId,
|
|
131
|
+
message: `Rollback to ${revisionId}`,
|
|
132
|
+
});
|
|
133
|
+
return c.json({ revision: restored, restoredFrom: revisionId });
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
// readRevision throws ENOENT-style errors when the id doesn't
|
|
137
|
+
// exist — treat as a 404 so clients can render a helpful message.
|
|
138
|
+
return c.json({ error: err.message }, 404);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
return app;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../../../src/admin-api/routes/history.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
|
-
import type {
|
|
3
|
-
export declare function pageRoutes(
|
|
2
|
+
import type { SourceContextResolver } from '../source-context.js';
|
|
3
|
+
export declare function pageRoutes(resolve: SourceContextResolver): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
4
4
|
//# sourceMappingURL=pages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../../src/admin-api/routes/pages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../../src/admin-api/routes/pages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAI3B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAIjE,wBAAgB,UAAU,CAAC,OAAO,EAAE,qBAAqB,8EA+KxD"}
|
|
@@ -1,23 +1,57 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { loadSiteFromSource } from '../source-context.js';
|
|
4
|
+
import { recordWrite } from '../../history-recorder.js';
|
|
5
|
+
import { CreatePageRequestSchema } from '../schemas/pages.js';
|
|
6
|
+
import { isValidLocale } from '../../locale.js';
|
|
7
|
+
export function pageRoutes(resolve) {
|
|
5
8
|
const app = new Hono();
|
|
6
9
|
app.get('/api/pages', async (c) => {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const source = await resolve(c.req.query('target'));
|
|
11
|
+
// Empty target (e.g. a publish-target that's never received any
|
|
12
|
+
// content) is valid per the stateless-CMS model — return an empty
|
|
13
|
+
// list rather than erroring. Callers checking item availability
|
|
14
|
+
// across targets (e.g. the target-switch missing-item banner) rely
|
|
15
|
+
// on this: a 404/500 would force them to choose between "fail
|
|
16
|
+
// open" (wrong, reports items as present) and "fail closed" (wrong,
|
|
17
|
+
// hides legitimate targets the user might want to switch to).
|
|
18
|
+
try {
|
|
19
|
+
const site = await loadSiteFromSource(source);
|
|
20
|
+
const pages = [...site.pages.entries()].map(([name, page]) => {
|
|
21
|
+
const localeEntry = site.pageLocales.get(name);
|
|
22
|
+
return {
|
|
23
|
+
name,
|
|
24
|
+
route: page.route,
|
|
25
|
+
template: page.template,
|
|
26
|
+
locales: localeEntry ? [...localeEntry.locales.keys()] : undefined,
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
return c.json(pages);
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
const msg = err.message;
|
|
33
|
+
if (msg.includes('No site.yaml found'))
|
|
34
|
+
return c.json([]);
|
|
35
|
+
throw err;
|
|
36
|
+
}
|
|
14
37
|
});
|
|
15
38
|
app.post('/api/pages', async (c) => {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
39
|
+
const source = await resolve(c.req.query('target'));
|
|
40
|
+
const { storage, sidecarWriter } = source;
|
|
41
|
+
// Schema-validate the body so drift between client and server
|
|
42
|
+
// can't silently accept malformed requests. The Zod schema is the
|
|
43
|
+
// single source of truth, shared with the client via
|
|
44
|
+
// `gazetta/admin-api/schemas` (see testing-plan.md Priority 3.2).
|
|
45
|
+
const raw = await c.req.json();
|
|
46
|
+
const parsed = CreatePageRequestSchema.safeParse(raw);
|
|
47
|
+
if (!parsed.success) {
|
|
48
|
+
return c.json({
|
|
49
|
+
error: 'Invalid request body',
|
|
50
|
+
issues: parsed.error.issues.map(i => ({ path: i.path.join('.'), message: i.message })),
|
|
51
|
+
}, 400);
|
|
19
52
|
}
|
|
20
|
-
const
|
|
53
|
+
const body = parsed.data;
|
|
54
|
+
const pageDir = source.contentRoot.path('pages', body.name);
|
|
21
55
|
const manifestPath = join(pageDir, 'page.json');
|
|
22
56
|
if (await storage.exists(manifestPath)) {
|
|
23
57
|
return c.json({ error: `Page "${body.name}" already exists` }, 409);
|
|
@@ -29,44 +63,110 @@ export function pageRoutes(siteDir, storage) {
|
|
|
29
63
|
components: [],
|
|
30
64
|
};
|
|
31
65
|
await storage.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
|
|
66
|
+
await sidecarWriter?.writeFor('page', body.name);
|
|
32
67
|
return c.json({ ok: true, name: body.name });
|
|
33
68
|
});
|
|
34
69
|
app.get('/api/pages/:name{.+}', async (c) => {
|
|
35
70
|
const name = c.req.param('name');
|
|
36
|
-
const
|
|
37
|
-
const
|
|
71
|
+
const rawLocale = c.req.query('locale');
|
|
72
|
+
const locale = rawLocale && isValidLocale(rawLocale) ? rawLocale.toLowerCase() : undefined;
|
|
73
|
+
if (rawLocale && !locale)
|
|
74
|
+
return c.json({ error: `Invalid locale code: "${rawLocale}"` }, 400);
|
|
75
|
+
const source = await resolve(c.req.query('target'));
|
|
76
|
+
const site = await loadSiteFromSource(source);
|
|
77
|
+
// If a locale is requested, return the locale variant
|
|
78
|
+
let page = site.pages.get(name);
|
|
79
|
+
if (locale) {
|
|
80
|
+
const localeEntry = site.pageLocales.get(name);
|
|
81
|
+
const localeVariant = localeEntry?.locales.get(locale);
|
|
82
|
+
if (localeVariant)
|
|
83
|
+
page = localeVariant;
|
|
84
|
+
else if (!page)
|
|
85
|
+
return c.json({ error: `Page "${name}" locale "${locale}" not found` }, 404);
|
|
86
|
+
}
|
|
38
87
|
if (!page)
|
|
39
88
|
return c.json({ error: `Page "${name}" not found` }, 404);
|
|
89
|
+
const localeEntry = site.pageLocales.get(name);
|
|
40
90
|
return c.json({
|
|
41
91
|
name,
|
|
42
92
|
route: page.route,
|
|
43
93
|
template: page.template,
|
|
44
94
|
content: page.content,
|
|
45
95
|
components: page.components,
|
|
96
|
+
metadata: page.metadata,
|
|
46
97
|
dir: page.dir,
|
|
98
|
+
locale: locale ?? undefined,
|
|
99
|
+
locales: localeEntry ? [...localeEntry.locales.keys()] : undefined,
|
|
47
100
|
});
|
|
48
101
|
});
|
|
49
102
|
app.put('/api/pages/:name{.+}', async (c) => {
|
|
50
103
|
const name = c.req.param('name');
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
if (!
|
|
104
|
+
const rawLocale = c.req.query('locale');
|
|
105
|
+
const locale = rawLocale && isValidLocale(rawLocale) ? rawLocale.toLowerCase() : undefined;
|
|
106
|
+
if (rawLocale && !locale)
|
|
107
|
+
return c.json({ error: `Invalid locale code: "${rawLocale}"` }, 400);
|
|
108
|
+
const source = await resolve(c.req.query('target'));
|
|
109
|
+
const { storage, sidecarWriter } = source;
|
|
110
|
+
const site = await loadSiteFromSource(source);
|
|
111
|
+
// Resolve the page to update — locale variant or default
|
|
112
|
+
const defaultPage = site.pages.get(name);
|
|
113
|
+
if (!defaultPage)
|
|
54
114
|
return c.json({ error: `Page "${name}" not found` }, 404);
|
|
115
|
+
const localeVariant = locale ? site.pageLocales.get(name)?.locales.get(locale) : undefined;
|
|
116
|
+
const page = localeVariant ?? defaultPage;
|
|
55
117
|
const body = await c.req.json();
|
|
56
118
|
const manifest = {
|
|
57
119
|
template: body.template ?? page.template,
|
|
58
120
|
content: body.content ?? page.content,
|
|
59
121
|
components: body.components ?? page.components,
|
|
60
122
|
};
|
|
61
|
-
|
|
123
|
+
if (body.metadata !== undefined)
|
|
124
|
+
manifest.metadata = body.metadata;
|
|
125
|
+
else if (page.metadata)
|
|
126
|
+
manifest.metadata = page.metadata;
|
|
127
|
+
// Locale variants store their route for preview resolution
|
|
128
|
+
if (locale && page.route)
|
|
129
|
+
manifest.route = page.route;
|
|
130
|
+
const filename = locale ? `page.${locale}.json` : 'page.json';
|
|
131
|
+
const manifestPath = join(defaultPage.dir, filename);
|
|
132
|
+
const serialized = JSON.stringify(manifest, null, 2) + '\n';
|
|
133
|
+
// Record the history revision BEFORE the disk write. recordWrite's
|
|
134
|
+
// first call scans the content tree to produce a pre-save baseline
|
|
135
|
+
// — if we wrote to disk first, the baseline would capture the
|
|
136
|
+
// post-save state and "undo my first save" would be a no-op.
|
|
137
|
+
// The baseline scan reads current disk state (pre-save); then
|
|
138
|
+
// recordWrite overlays the incoming delta (the post-save content)
|
|
139
|
+
// to build the save revision's snapshot.
|
|
140
|
+
if (source.history) {
|
|
141
|
+
await recordWrite({
|
|
142
|
+
history: source.history,
|
|
143
|
+
contentRoot: source.contentRoot,
|
|
144
|
+
operation: 'save',
|
|
145
|
+
items: [{ path: source.contentRoot.relative(manifestPath), content: serialized }],
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
await storage.writeFile(manifestPath, serialized);
|
|
149
|
+
await sidecarWriter?.writeFor('page', name);
|
|
62
150
|
return c.json({ ok: true });
|
|
63
151
|
});
|
|
64
152
|
app.delete('/api/pages/:name{.+}', async (c) => {
|
|
65
153
|
const name = c.req.param('name');
|
|
66
|
-
const
|
|
154
|
+
const source = await resolve(c.req.query('target'));
|
|
155
|
+
const { storage } = source;
|
|
156
|
+
const site = await loadSiteFromSource(source);
|
|
67
157
|
const page = site.pages.get(name);
|
|
68
158
|
if (!page)
|
|
69
159
|
return c.json({ error: `Page "${name}" not found` }, 404);
|
|
160
|
+
const manifestPath = join(page.dir, 'page.json');
|
|
161
|
+
// History first — see PUT handler rationale.
|
|
162
|
+
if (source.history) {
|
|
163
|
+
await recordWrite({
|
|
164
|
+
history: source.history,
|
|
165
|
+
contentRoot: source.contentRoot,
|
|
166
|
+
operation: 'save',
|
|
167
|
+
items: [{ path: source.contentRoot.relative(manifestPath), content: null }],
|
|
168
|
+
});
|
|
169
|
+
}
|
|
70
170
|
await storage.rm(page.dir);
|
|
71
171
|
return c.json({ ok: true });
|
|
72
172
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages.js","sourceRoot":"","sources":["../../../src/admin-api/routes/pages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"pages.js","sourceRoot":"","sources":["../../../src/admin-api/routes/pages.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
|
-
import type {
|
|
3
|
-
export declare function previewRoutes(
|
|
2
|
+
import type { SourceContextResolver } from '../source-context.js';
|
|
3
|
+
export declare function previewRoutes(resolve: SourceContextResolver, templatesDir?: string): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
4
4
|
//# sourceMappingURL=preview.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../../src/admin-api/routes/preview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../../src/admin-api/routes/preview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAA;AAMzC,OAAO,KAAK,EAAiB,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAEhF,wBAAgB,aAAa,CAAC,OAAO,EAAE,qBAAqB,EAAE,YAAY,CAAC,EAAE,MAAM,8EAqBlF"}
|