@setzkasten-cms/astro-admin 1.4.2 → 1.5.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.
Files changed (166) hide show
  1. package/dist/api-routes/_auth-guard.d.ts +27 -3
  2. package/dist/api-routes/_auth-guard.js +5 -2
  3. package/dist/api-routes/_dev-session-secret.d.ts +8 -0
  4. package/dist/api-routes/_dev-session-secret.js +8 -0
  5. package/dist/api-routes/_github-token.js +1 -1
  6. package/dist/api-routes/_role-resolver.js +6 -3
  7. package/dist/api-routes/_session-secret.d.ts +19 -0
  8. package/dist/api-routes/_session-secret.js +7 -0
  9. package/dist/api-routes/_session-signing.d.ts +45 -0
  10. package/dist/api-routes/_session-signing.js +8 -0
  11. package/dist/api-routes/_webhook-dispatcher.js +4 -4
  12. package/dist/api-routes/asset-proxy.js +1 -1
  13. package/dist/api-routes/auth-callback.js +12 -5
  14. package/dist/api-routes/auth-logout.d.ts +4 -4
  15. package/dist/api-routes/auth-logout.js +8 -2
  16. package/dist/api-routes/auth-session.d.ts +6 -0
  17. package/dist/api-routes/auth-session.js +19 -19
  18. package/dist/api-routes/auth-setzkasten-login.js +14 -7
  19. package/dist/api-routes/catalog-add.js +59 -17
  20. package/dist/api-routes/catalog-export.js +14 -4
  21. package/dist/api-routes/config.d.ts +10 -3
  22. package/dist/api-routes/config.js +26 -4
  23. package/dist/api-routes/deploy-hook.js +8 -8
  24. package/dist/api-routes/editors.d.ts +1 -1
  25. package/dist/api-routes/editors.js +5 -2
  26. package/dist/api-routes/github-proxy.js +30 -8
  27. package/dist/api-routes/global-config.js +6 -3
  28. package/dist/api-routes/history-rollback.js +31 -14
  29. package/dist/api-routes/history-version.js +8 -6
  30. package/dist/api-routes/history.js +5 -2
  31. package/dist/api-routes/icons-local.js +1 -1
  32. package/dist/api-routes/init-add-section.js +150 -48
  33. package/dist/api-routes/init-apply.js +56 -42
  34. package/dist/api-routes/init-migrate.js +43 -36
  35. package/dist/api-routes/init-scan-page.d.ts +1 -1
  36. package/dist/api-routes/init-scan-page.js +59 -13
  37. package/dist/api-routes/init-scan.js +22 -7
  38. package/dist/api-routes/migrate-to-multi.js +5 -2
  39. package/dist/api-routes/pages.js +15 -4
  40. package/dist/api-routes/section-add.js +68 -16
  41. package/dist/api-routes/section-commit-pending.js +70 -22
  42. package/dist/api-routes/section-delete.js +49 -14
  43. package/dist/api-routes/section-duplicate.js +65 -16
  44. package/dist/api-routes/section-prepare-copy.js +15 -2
  45. package/dist/api-routes/section-prepare.js +25 -4
  46. package/dist/api-routes/setup-github-app-bounce.js +15 -1
  47. package/dist/api-routes/setup-github-app-branches.js +9 -6
  48. package/dist/api-routes/setup-github-app-callback.js +24 -1
  49. package/dist/api-routes/setup-github-app-credentials.d.ts +27 -0
  50. package/dist/api-routes/setup-github-app-credentials.js +43 -0
  51. package/dist/api-routes/setup-github-app-installed.js +22 -1
  52. package/dist/api-routes/setup-github-app-repos.js +5 -2
  53. package/dist/api-routes/setup-github-app.d.ts +4 -0
  54. package/dist/api-routes/setup-github-app.js +19 -2
  55. package/dist/api-routes/updater-register.js +7 -1
  56. package/dist/api-routes/webhooks-status.js +5 -2
  57. package/dist/api-routes/webhooks-test.js +9 -8
  58. package/dist/api-routes/webhooks.js +12 -14
  59. package/dist/api-routes/websites-add.js +5 -2
  60. package/dist/api-routes/websites-remove.js +5 -2
  61. package/dist/{chunk-ZQDGGWJP.js → chunk-5KMGSFCZ.js} +2 -2
  62. package/dist/{chunk-RHJONMLK.js → chunk-CDXCYYQR.js} +222 -5
  63. package/dist/{chunk-NKDATSPA.js → chunk-DP6RTINQ.js} +1 -1
  64. package/dist/chunk-KENFINT4.js +76 -0
  65. package/dist/chunk-ONP6BRZO.js +47 -0
  66. package/dist/{chunk-INIWFKQ3.js → chunk-Q5HV47DW.js} +33 -19
  67. package/dist/chunk-QVCW6EF3.js +26 -0
  68. package/dist/{chunk-K22A4ZBS.js → chunk-UHI6323G.js} +293 -174
  69. package/dist/{chunk-AM4DZXXM.js → chunk-UJAFZEX2.js} +76 -9
  70. package/package.json +12 -6
  71. package/src/api-routes/__tests__/_session-signing.test.ts +114 -0
  72. package/src/api-routes/__tests__/_session-test-helper.ts +27 -0
  73. package/src/api-routes/__tests__/add-section-helpers.test.ts +91 -97
  74. package/src/api-routes/__tests__/auth-guard.test.ts +46 -7
  75. package/src/api-routes/__tests__/catalog-api.test.ts +14 -6
  76. package/src/api-routes/__tests__/commit-trailers.test.ts +5 -5
  77. package/src/api-routes/__tests__/deferred-operations.test.ts +9 -12
  78. package/src/api-routes/__tests__/deploy-hook.test.ts +3 -8
  79. package/src/api-routes/__tests__/feature-gate.test.ts +1 -1
  80. package/src/api-routes/__tests__/github-cache.test.ts +1 -1
  81. package/src/api-routes/__tests__/github-token.test.ts +1 -1
  82. package/src/api-routes/__tests__/global-config-theme.test.ts +4 -4
  83. package/src/api-routes/__tests__/history-rollback.test.ts +6 -3
  84. package/src/api-routes/__tests__/history.test.ts +9 -6
  85. package/src/api-routes/__tests__/init-scan-page-resolve-config.test.ts +11 -3
  86. package/src/api-routes/__tests__/migrate-to-multi.test.ts +5 -1
  87. package/src/api-routes/__tests__/pages-meta-store.test.ts +10 -5
  88. package/src/api-routes/__tests__/pages.test.ts +7 -2
  89. package/src/api-routes/__tests__/patch-page-file.test.ts +71 -19
  90. package/src/api-routes/__tests__/route-registry.test.ts +11 -18
  91. package/src/api-routes/__tests__/scan-page-helpers.test.ts +13 -10
  92. package/src/api-routes/__tests__/section-management.test.ts +28 -28
  93. package/src/api-routes/__tests__/setup-github-app-callback.test.ts +58 -16
  94. package/src/api-routes/__tests__/setup-github-app-repos.test.ts +4 -5
  95. package/src/api-routes/__tests__/setup-github-app.test.ts +27 -7
  96. package/src/api-routes/__tests__/storage-config-for-request.test.ts +83 -0
  97. package/src/api-routes/__tests__/updater-register.test.ts +230 -0
  98. package/src/api-routes/__tests__/webhook-signing.test.ts +1 -1
  99. package/src/api-routes/__tests__/webhooks.test.ts +19 -7
  100. package/src/api-routes/__tests__/websites-add.test.ts +2 -1
  101. package/src/api-routes/__tests__/websites-remove.test.ts +2 -1
  102. package/src/api-routes/_auth-guard.ts +47 -15
  103. package/src/api-routes/_commit-trailers.ts +3 -2
  104. package/src/api-routes/_dev-session-secret.ts +79 -0
  105. package/src/api-routes/_github-token.ts +1 -1
  106. package/src/api-routes/_pages-meta-store.ts +2 -2
  107. package/src/api-routes/_role-resolver.ts +7 -5
  108. package/src/api-routes/_session-secret.ts +46 -0
  109. package/src/api-routes/_session-signing.ts +135 -0
  110. package/src/api-routes/_vercel-origin.ts +2 -6
  111. package/src/api-routes/_webhook-dispatcher.ts +12 -16
  112. package/src/api-routes/_website-resolver.ts +3 -10
  113. package/src/api-routes/auth-callback.ts +9 -5
  114. package/src/api-routes/auth-login.ts +5 -3
  115. package/src/api-routes/auth-logout.ts +18 -1
  116. package/src/api-routes/auth-session.ts +13 -21
  117. package/src/api-routes/auth-setzkasten-login.ts +12 -9
  118. package/src/api-routes/catalog-add.ts +89 -31
  119. package/src/api-routes/catalog-export.ts +30 -10
  120. package/src/api-routes/config.ts +39 -6
  121. package/src/api-routes/deploy-hook.ts +13 -11
  122. package/src/api-routes/editors.ts +33 -22
  123. package/src/api-routes/github-proxy.ts +25 -11
  124. package/src/api-routes/global-config.ts +103 -18
  125. package/src/api-routes/history-rollback.ts +41 -14
  126. package/src/api-routes/history-version.ts +5 -6
  127. package/src/api-routes/history.ts +3 -3
  128. package/src/api-routes/icons-local.ts +2 -2
  129. package/src/api-routes/init-add-section.ts +218 -88
  130. package/src/api-routes/init-apply.ts +71 -56
  131. package/src/api-routes/init-migrate.ts +54 -48
  132. package/src/api-routes/init-scan-page.ts +77 -30
  133. package/src/api-routes/init-scan.ts +19 -11
  134. package/src/api-routes/pages.ts +16 -11
  135. package/src/api-routes/section-add.ts +98 -27
  136. package/src/api-routes/section-commit-pending.ts +87 -34
  137. package/src/api-routes/section-delete.ts +76 -27
  138. package/src/api-routes/section-duplicate.ts +95 -28
  139. package/src/api-routes/section-management.ts +3 -7
  140. package/src/api-routes/section-prepare-copy.ts +29 -8
  141. package/src/api-routes/section-prepare.ts +38 -10
  142. package/src/api-routes/setup-github-app-bounce.ts +7 -1
  143. package/src/api-routes/setup-github-app-branches.ts +6 -7
  144. package/src/api-routes/setup-github-app-callback.ts +18 -1
  145. package/src/api-routes/setup-github-app-credentials.ts +55 -0
  146. package/src/api-routes/setup-github-app-installed.ts +12 -1
  147. package/src/api-routes/setup-github-app-repos.ts +2 -3
  148. package/src/api-routes/setup-github-app.ts +14 -5
  149. package/src/api-routes/updater-check.ts +6 -4
  150. package/src/api-routes/updater-register.ts +34 -20
  151. package/src/api-routes/updater-transfer.ts +8 -6
  152. package/src/api-routes/updater-unbind.ts +14 -10
  153. package/src/api-routes/webhooks-test.ts +9 -11
  154. package/src/api-routes/webhooks.ts +15 -19
  155. package/src/init/__tests__/page-level.test.ts +279 -105
  156. package/src/init/__tests__/page-list-coverage.test.ts +70 -70
  157. package/src/init/__tests__/patcher-child-component.test.ts +126 -0
  158. package/src/init/__tests__/patcher-edge-cases.test.ts +47 -23
  159. package/src/init/__tests__/patcher-mixed-content-wrapper.test.ts +16 -6
  160. package/src/init/__tests__/patcher-page-mode.test.ts +30 -20
  161. package/src/init/__tests__/section-pipeline.test.ts +102 -16
  162. package/src/init/astro-config-patcher.ts +4 -18
  163. package/src/init/astro-detector.ts +2 -7
  164. package/src/init/astro-section-analyzer-v2.ts +475 -193
  165. package/src/init/field-label-enricher.ts +6 -6
  166. package/src/init/template-patcher-v2.ts +490 -56
@@ -1,15 +1,27 @@
1
1
  import {
2
2
  patchTemplateForFields
3
- } from "../chunk-RHJONMLK.js";
3
+ } from "../chunk-CDXCYYQR.js";
4
+ import {
5
+ requireAdmin
6
+ } from "../chunk-Q5HV47DW.js";
7
+ import "../chunk-QVCW6EF3.js";
8
+ import "../chunk-KENFINT4.js";
9
+ import "../chunk-6UIKVKED.js";
10
+ import "../chunk-ONP6BRZO.js";
11
+ import "../chunk-5PIMDP4N.js";
12
+ import "../chunk-45ARVNT3.js";
4
13
  import {
5
14
  resolveGitHubTokenForRequest
6
- } from "../chunk-NKDATSPA.js";
15
+ } from "../chunk-DP6RTINQ.js";
16
+ import "../chunk-TJNJKPUL.js";
7
17
  import {
8
18
  withTrailers
9
19
  } from "../chunk-KH22FJO5.js";
10
20
 
11
21
  // src/api-routes/init-apply.ts
12
- import { generateConfigFile } from "@setzkasten-cms/core/init";
22
+ import {
23
+ generateConfigFile
24
+ } from "@setzkasten-cms/core/init";
13
25
 
14
26
  // src/init/astro-config-patcher.ts
15
27
  function patchAstroConfig(source) {
@@ -59,10 +71,8 @@ function addToIntegrations(source) {
59
71
 
60
72
  // src/api-routes/init-apply.ts
61
73
  var POST = async ({ request, cookies }) => {
62
- const session = cookies.get("setzkasten_session")?.value;
63
- if (!session) {
64
- return new Response("Unauthorized", { status: 401 });
65
- }
74
+ const denied = requireAdmin(cookies.get("setzkasten_session")?.value);
75
+ if (denied) return denied;
66
76
  const tokenResult = await resolveGitHubTokenForRequest(request);
67
77
  if (!tokenResult.ok) {
68
78
  return new Response(tokenResult.error.message, { status: 500 });
@@ -82,7 +92,13 @@ var POST = async ({ request, cookies }) => {
82
92
  const configPath = projectRoot ? `${projectRoot}/setzkasten.config.ts` : "setzkasten.config.ts";
83
93
  filesToCommit.push({ path: configPath, content: configContent });
84
94
  if (astroConfigPath) {
85
- const astroConfigSource = await fetchFileContent(owner, repo, branch, astroConfigPath, githubToken);
95
+ const astroConfigSource = await fetchFileContent(
96
+ owner,
97
+ repo,
98
+ branch,
99
+ astroConfigPath,
100
+ githubToken
101
+ );
86
102
  if (astroConfigSource) {
87
103
  const patched = patchAstroConfig(astroConfigSource);
88
104
  if (patched) {
@@ -103,7 +119,13 @@ var POST = async ({ request, cookies }) => {
103
119
  }
104
120
  for (const section of sections) {
105
121
  if (!section.componentPath) continue;
106
- const componentSource = await fetchFileContent(owner, repo, branch, section.componentPath, githubToken);
122
+ const componentSource = await fetchFileContent(
123
+ owner,
124
+ repo,
125
+ branch,
126
+ section.componentPath,
127
+ githubToken
128
+ );
107
129
  if (!componentSource) continue;
108
130
  const patched = await patchTemplateForFields(componentSource, section.key, section.fields);
109
131
  if (patched !== componentSource) {
@@ -134,10 +156,7 @@ var POST = async ({ request, cookies }) => {
134
156
  githubToken
135
157
  );
136
158
  if (!commitResult.ok) {
137
- return Response.json(
138
- { error: commitResult.error },
139
- { status: 500 }
140
- );
159
+ return Response.json({ error: commitResult.error }, { status: 500 });
141
160
  }
142
161
  return Response.json({
143
162
  success: true,
@@ -215,37 +234,32 @@ async function batchCommit(owner, repo, branch, files, message, token) {
215
234
  if (!commitRes.ok) return { ok: false, error: `Failed to get commit: ${commitRes.status}` };
216
235
  const commitData = await commitRes.json();
217
236
  const baseTreeSha = commitData.tree.sha;
218
- const treeRes = await fetch(
219
- `https://api.github.com/repos/${owner}/${repo}/git/trees`,
220
- {
221
- method: "POST",
222
- headers,
223
- body: JSON.stringify({
224
- base_tree: baseTreeSha,
225
- tree: files.map((f) => ({
226
- path: f.path,
227
- mode: "100644",
228
- type: "blob",
229
- content: f.content
230
- }))
231
- })
232
- }
233
- );
237
+ const treeRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/git/trees`, {
238
+ method: "POST",
239
+ headers,
240
+ body: JSON.stringify({
241
+ base_tree: baseTreeSha,
242
+ tree: files.map((f) => ({
243
+ path: f.path,
244
+ mode: "100644",
245
+ type: "blob",
246
+ content: f.content
247
+ }))
248
+ })
249
+ });
234
250
  if (!treeRes.ok) return { ok: false, error: `Failed to create tree: ${treeRes.status}` };
235
251
  const treeData = await treeRes.json();
236
- const newCommitRes = await fetch(
237
- `https://api.github.com/repos/${owner}/${repo}/git/commits`,
238
- {
239
- method: "POST",
240
- headers,
241
- body: JSON.stringify({
242
- tree: treeData.sha,
243
- parents: [headSha],
244
- message
245
- })
246
- }
247
- );
248
- if (!newCommitRes.ok) return { ok: false, error: `Failed to create commit: ${newCommitRes.status}` };
252
+ const newCommitRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/git/commits`, {
253
+ method: "POST",
254
+ headers,
255
+ body: JSON.stringify({
256
+ tree: treeData.sha,
257
+ parents: [headSha],
258
+ message
259
+ })
260
+ });
261
+ if (!newCommitRes.ok)
262
+ return { ok: false, error: `Failed to create commit: ${newCommitRes.status}` };
249
263
  const newCommitData = await newCommitRes.json();
250
264
  const updateRes = await fetch(
251
265
  `https://api.github.com/repos/${owner}/${repo}/git/refs/heads/${branch}`,
@@ -1,23 +1,30 @@
1
1
  import {
2
2
  patchTemplateForFields
3
- } from "../chunk-RHJONMLK.js";
3
+ } from "../chunk-CDXCYYQR.js";
4
+ import {
5
+ requireAdmin
6
+ } from "../chunk-Q5HV47DW.js";
7
+ import "../chunk-QVCW6EF3.js";
8
+ import "../chunk-KENFINT4.js";
4
9
  import {
5
10
  prefixPath,
6
11
  resolveStorageConfigForRequest
7
12
  } from "../chunk-6UIKVKED.js";
13
+ import "../chunk-ONP6BRZO.js";
14
+ import "../chunk-5PIMDP4N.js";
15
+ import "../chunk-45ARVNT3.js";
8
16
  import {
9
17
  resolveGitHubTokenForRequest
10
- } from "../chunk-NKDATSPA.js";
18
+ } from "../chunk-DP6RTINQ.js";
19
+ import "../chunk-TJNJKPUL.js";
11
20
  import {
12
21
  withTrailers
13
22
  } from "../chunk-KH22FJO5.js";
14
23
 
15
24
  // src/api-routes/init-migrate.ts
16
25
  var POST = async ({ request, cookies }) => {
17
- const session = cookies.get("setzkasten_session")?.value;
18
- if (!session) {
19
- return new Response("Unauthorized", { status: 401 });
20
- }
26
+ const denied = requireAdmin(cookies.get("setzkasten_session")?.value);
27
+ if (denied) return denied;
21
28
  const tokenResult = await resolveGitHubTokenForRequest(request);
22
29
  if (!tokenResult.ok) {
23
30
  return new Response(tokenResult.error.message, { status: 500 });
@@ -27,7 +34,12 @@ var POST = async ({ request, cookies }) => {
27
34
  const body = await request.json();
28
35
  const storage = await resolveStorageConfigForRequest(request, body);
29
36
  if (!storage) {
30
- return Response.json({ error: "Could not resolve owner/repo. Set SETZKASTEN_OWNER and SETZKASTEN_REPO env vars." }, { status: 400 });
37
+ return Response.json(
38
+ {
39
+ error: "Could not resolve owner/repo. Set SETZKASTEN_OWNER and SETZKASTEN_REPO env vars."
40
+ },
41
+ { status: 400 }
42
+ );
31
43
  }
32
44
  const { owner, repo, branch, projectPrefix } = storage;
33
45
  const { sectionKey } = body;
@@ -154,37 +166,32 @@ async function batchCommit(owner, repo, branch, files, message, headers) {
154
166
  );
155
167
  if (!commitRes.ok) return { ok: false, error: `Failed to get commit: ${commitRes.status}` };
156
168
  const commitData = await commitRes.json();
157
- const treeRes = await fetch(
158
- `https://api.github.com/repos/${owner}/${repo}/git/trees`,
159
- {
160
- method: "POST",
161
- headers,
162
- body: JSON.stringify({
163
- base_tree: commitData.tree.sha,
164
- tree: files.map((f) => ({
165
- path: f.path,
166
- mode: "100644",
167
- type: "blob",
168
- content: f.content
169
- }))
170
- })
171
- }
172
- );
169
+ const treeRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/git/trees`, {
170
+ method: "POST",
171
+ headers,
172
+ body: JSON.stringify({
173
+ base_tree: commitData.tree.sha,
174
+ tree: files.map((f) => ({
175
+ path: f.path,
176
+ mode: "100644",
177
+ type: "blob",
178
+ content: f.content
179
+ }))
180
+ })
181
+ });
173
182
  if (!treeRes.ok) return { ok: false, error: `Failed to create tree: ${treeRes.status}` };
174
183
  const treeData = await treeRes.json();
175
- const newCommitRes = await fetch(
176
- `https://api.github.com/repos/${owner}/${repo}/git/commits`,
177
- {
178
- method: "POST",
179
- headers,
180
- body: JSON.stringify({
181
- tree: treeData.sha,
182
- parents: [headSha],
183
- message
184
- })
185
- }
186
- );
187
- if (!newCommitRes.ok) return { ok: false, error: `Failed to create commit: ${newCommitRes.status}` };
184
+ const newCommitRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/git/commits`, {
185
+ method: "POST",
186
+ headers,
187
+ body: JSON.stringify({
188
+ tree: treeData.sha,
189
+ parents: [headSha],
190
+ message
191
+ })
192
+ });
193
+ if (!newCommitRes.ok)
194
+ return { ok: false, error: `Failed to create commit: ${newCommitRes.status}` };
188
195
  const newCommitData = await newCommitRes.json();
189
196
  const updateRes = await fetch(
190
197
  `https://api.github.com/repos/${owner}/${repo}/git/refs/heads/${branch}`,
@@ -1,5 +1,5 @@
1
- import { APIRoute } from 'astro';
2
1
  import { SetzKastenConfig } from '@setzkasten-cms/core';
2
+ import { APIRoute } from 'astro';
3
3
 
4
4
  /**
5
5
  * Resolves the full Setzkasten config.
@@ -2,14 +2,24 @@ import {
2
2
  analyzeAstroSection,
3
3
  extractLayoutImport,
4
4
  extractSectionImports
5
- } from "../chunk-K22A4ZBS.js";
5
+ } from "../chunk-UHI6323G.js";
6
+ import {
7
+ requireAdmin
8
+ } from "../chunk-Q5HV47DW.js";
9
+ import "../chunk-QVCW6EF3.js";
10
+ import "../chunk-KENFINT4.js";
6
11
  import {
7
12
  prefixPath,
8
13
  resolveStorageConfigForRequest
9
14
  } from "../chunk-6UIKVKED.js";
15
+ import "../chunk-ONP6BRZO.js";
16
+ import "../chunk-5PIMDP4N.js";
17
+ import "../chunk-45ARVNT3.js";
10
18
  import {
11
19
  resolveGitHubTokenForRequest
12
- } from "../chunk-NKDATSPA.js";
20
+ } from "../chunk-DP6RTINQ.js";
21
+ import "../chunk-TJNJKPUL.js";
22
+ import "../chunk-KH22FJO5.js";
13
23
 
14
24
  // src/api-routes/init-scan-page.ts
15
25
  function resolveFullConfig() {
@@ -17,10 +27,8 @@ function resolveFullConfig() {
17
27
  return buildConfig ?? globalThis.__SETZKASTEN_FULL_CONFIG__;
18
28
  }
19
29
  var POST = async ({ request, cookies }) => {
20
- const session = cookies.get("setzkasten_session")?.value;
21
- if (!session) {
22
- return new Response("Unauthorized", { status: 401 });
23
- }
30
+ const denied = requireAdmin(cookies.get("setzkasten_session")?.value);
31
+ if (denied) return denied;
24
32
  const tokenResult = await resolveGitHubTokenForRequest(request);
25
33
  if (!tokenResult.ok) {
26
34
  return new Response(tokenResult.error.message, { status: 500 });
@@ -30,7 +38,12 @@ var POST = async ({ request, cookies }) => {
30
38
  const body = await request.json();
31
39
  const storage = await resolveStorageConfigForRequest(request, body);
32
40
  if (!storage) {
33
- return Response.json({ error: "Could not resolve owner/repo. Set SETZKASTEN_OWNER and SETZKASTEN_REPO env vars." }, { status: 400 });
41
+ return Response.json(
42
+ {
43
+ error: "Could not resolve owner/repo. Set SETZKASTEN_OWNER and SETZKASTEN_REPO env vars."
44
+ },
45
+ { status: 400 }
46
+ );
34
47
  }
35
48
  const { owner, repo, branch, projectPrefix } = storage;
36
49
  const { pagePath } = body;
@@ -69,7 +82,10 @@ var POST = async ({ request, cookies }) => {
69
82
  pageSource = await fetchFileContent(owner, repo, branch, fullPagePath, githubToken);
70
83
  }
71
84
  if (!pageSource) {
72
- return Response.json({ error: `Could not read page source: ${fullPagePath}` }, { status: 404 });
85
+ return Response.json(
86
+ { error: `Could not read page source: ${fullPagePath}` },
87
+ { status: 404 }
88
+ );
73
89
  }
74
90
  const imports = extractSectionImports(pageSource, fullPagePath, files, projectPrefix);
75
91
  const serverConfig = globalThis.__SETZKASTEN_CONFIG__;
@@ -79,7 +95,13 @@ var POST = async ({ request, cookies }) => {
79
95
  for (const imp of imports) {
80
96
  if (!imp.resolvedPath) continue;
81
97
  if (!managedSections.has(imp.sectionKey)) {
82
- const sectionSource = await fetchFileContent(owner, repo, branch, imp.resolvedPath, githubToken);
98
+ const sectionSource = await fetchFileContent(
99
+ owner,
100
+ repo,
101
+ branch,
102
+ imp.resolvedPath,
103
+ githubToken
104
+ );
83
105
  if (!sectionSource) continue;
84
106
  const section = await analyzeAstroSection(
85
107
  sectionSource,
@@ -90,7 +112,13 @@ var POST = async ({ request, cookies }) => {
90
112
  unmanagedSections.push(section);
91
113
  } else {
92
114
  const existingFieldKeys = managedSections.get(imp.sectionKey);
93
- const sectionSource = await fetchFileContent(owner, repo, branch, imp.resolvedPath, githubToken);
115
+ const sectionSource = await fetchFileContent(
116
+ owner,
117
+ repo,
118
+ branch,
119
+ imp.resolvedPath,
120
+ githubToken
121
+ );
94
122
  if (!sectionSource) continue;
95
123
  const inferred = await analyzeAstroSection(
96
124
  sectionSource,
@@ -99,7 +127,13 @@ var POST = async ({ request, cookies }) => {
99
127
  imp.resolvedPath
100
128
  );
101
129
  const sectionJsonPath = `${contentPath}/_sections/${imp.sectionKey}.json`;
102
- const sectionJson = await fetchFileContent(owner, repo, branch, sectionJsonPath, githubToken);
130
+ const sectionJson = await fetchFileContent(
131
+ owner,
132
+ repo,
133
+ branch,
134
+ sectionJsonPath,
135
+ githubToken
136
+ );
103
137
  const existingValues = /* @__PURE__ */ new Set();
104
138
  if (sectionJson) {
105
139
  try {
@@ -144,7 +178,13 @@ var POST = async ({ request, cookies }) => {
144
178
  } else {
145
179
  const existingFieldKeys = managedSections.get(sectionKey);
146
180
  const sectionJsonPath = `${contentPath}/_sections/${sectionKey}.json`;
147
- const sectionJson = await fetchFileContent(owner, repo, branch, sectionJsonPath, githubToken);
181
+ const sectionJson = await fetchFileContent(
182
+ owner,
183
+ repo,
184
+ branch,
185
+ sectionJsonPath,
186
+ githubToken
187
+ );
148
188
  const existingValues = /* @__PURE__ */ new Set();
149
189
  if (sectionJson) {
150
190
  try {
@@ -174,7 +214,13 @@ var POST = async ({ request, cookies }) => {
174
214
  {
175
215
  const layoutImport = extractLayoutImport(pageSource, fullPagePath, files, projectPrefix);
176
216
  if (layoutImport?.resolvedPath) {
177
- const layoutSource = await fetchFileContent(owner, repo, branch, layoutImport.resolvedPath, githubToken);
217
+ const layoutSource = await fetchFileContent(
218
+ owner,
219
+ repo,
220
+ branch,
221
+ layoutImport.resolvedPath,
222
+ githubToken
223
+ );
178
224
  if (layoutSource) {
179
225
  for (const region of extractLayoutRegions(layoutSource)) {
180
226
  const sectionKey = `_layout_${region.name}`;
@@ -2,18 +2,27 @@ import {
2
2
  analyzeAstroSection,
3
3
  extractSectionImports,
4
4
  findAstroPages
5
- } from "../chunk-K22A4ZBS.js";
5
+ } from "../chunk-UHI6323G.js";
6
+ import {
7
+ requireAdmin
8
+ } from "../chunk-Q5HV47DW.js";
9
+ import "../chunk-QVCW6EF3.js";
10
+ import "../chunk-KENFINT4.js";
11
+ import "../chunk-6UIKVKED.js";
12
+ import "../chunk-ONP6BRZO.js";
13
+ import "../chunk-5PIMDP4N.js";
14
+ import "../chunk-45ARVNT3.js";
6
15
  import {
7
16
  resolveGitHubTokenForRequest
8
- } from "../chunk-NKDATSPA.js";
17
+ } from "../chunk-DP6RTINQ.js";
18
+ import "../chunk-TJNJKPUL.js";
19
+ import "../chunk-KH22FJO5.js";
9
20
 
10
21
  // src/api-routes/init-scan.ts
11
22
  import { analyzeProject } from "@setzkasten-cms/core/init";
12
23
  var POST = async ({ request, cookies }) => {
13
- const session = cookies.get("setzkasten_session")?.value;
14
- if (!session) {
15
- return new Response("Unauthorized", { status: 401 });
16
- }
24
+ const denied = requireAdmin(cookies.get("setzkasten_session")?.value);
25
+ if (denied) return denied;
17
26
  const tokenResult = await resolveGitHubTokenForRequest(request);
18
27
  if (!tokenResult.ok) {
19
28
  return new Response(tokenResult.error.message, { status: 500 });
@@ -62,7 +71,13 @@ var POST = async ({ request, cookies }) => {
62
71
  for (const imp of imports) {
63
72
  if (allSections.has(imp.sectionKey)) continue;
64
73
  if (!imp.resolvedPath) continue;
65
- const sectionSource = await fetchFileContent(owner, repo, branch, imp.resolvedPath, githubToken);
74
+ const sectionSource = await fetchFileContent(
75
+ owner,
76
+ repo,
77
+ branch,
78
+ imp.resolvedPath,
79
+ githubToken
80
+ );
66
81
  if (!sectionSource) continue;
67
82
  const section = await analyzeAstroSection(
68
83
  sectionSource,
@@ -1,14 +1,17 @@
1
1
  import {
2
2
  parseSession
3
- } from "../chunk-INIWFKQ3.js";
3
+ } from "../chunk-Q5HV47DW.js";
4
+ import "../chunk-QVCW6EF3.js";
5
+ import "../chunk-KENFINT4.js";
4
6
  import {
5
7
  resolveStorageConfig
6
8
  } from "../chunk-6UIKVKED.js";
9
+ import "../chunk-ONP6BRZO.js";
7
10
  import "../chunk-5PIMDP4N.js";
8
11
  import "../chunk-45ARVNT3.js";
9
12
  import {
10
13
  resolveConfigRepoToken
11
- } from "../chunk-NKDATSPA.js";
14
+ } from "../chunk-DP6RTINQ.js";
12
15
  import {
13
16
  resolveLicenseTier
14
17
  } from "../chunk-TJNJKPUL.js";
@@ -1,15 +1,23 @@
1
1
  import {
2
- readPagesMeta
3
- } from "../chunk-FXNOTESI.js";
2
+ parseSession
3
+ } from "../chunk-Q5HV47DW.js";
4
+ import "../chunk-QVCW6EF3.js";
5
+ import "../chunk-KENFINT4.js";
4
6
  import {
5
7
  resolveStorageConfigForRequest
6
8
  } from "../chunk-6UIKVKED.js";
9
+ import "../chunk-ONP6BRZO.js";
10
+ import "../chunk-5PIMDP4N.js";
7
11
  import {
8
12
  cachedFetch
9
13
  } from "../chunk-45ARVNT3.js";
10
14
  import {
11
15
  resolveGitHubTokenForRequest
12
- } from "../chunk-NKDATSPA.js";
16
+ } from "../chunk-DP6RTINQ.js";
17
+ import "../chunk-TJNJKPUL.js";
18
+ import {
19
+ readPagesMeta
20
+ } from "../chunk-FXNOTESI.js";
13
21
  import "../chunk-KH22FJO5.js";
14
22
 
15
23
  // src/api-routes/pages.ts
@@ -17,7 +25,10 @@ function resolvePages() {
17
25
  const buildPages = typeof __SETZKASTEN_PAGES__ !== "undefined" ? __SETZKASTEN_PAGES__ : null;
18
26
  return buildPages ?? globalThis.__SETZKASTEN_PAGES__ ?? [];
19
27
  }
20
- var GET = async ({ request }) => {
28
+ var GET = async ({ request, cookies }) => {
29
+ if (!parseSession(cookies.get("setzkasten_session")?.value)) {
30
+ return new Response("Unauthorized", { status: 401 });
31
+ }
21
32
  const isMulti = request.headers.get("x-sk-website") !== null;
22
33
  const pages = isMulti ? await fetchPagesFromGitHub(request).catch(() => []) : resolvePages();
23
34
  const enriched = await enrichWithLastModified(pages, request).catch(() => pages);
@@ -5,21 +5,25 @@ import {
5
5
  import {
6
6
  guardPageAccess,
7
7
  parseSession
8
- } from "../chunk-INIWFKQ3.js";
8
+ } from "../chunk-Q5HV47DW.js";
9
+ import "../chunk-QVCW6EF3.js";
10
+ import "../chunk-KENFINT4.js";
9
11
  import {
10
12
  resolveStorageConfigForRequest
11
13
  } from "../chunk-6UIKVKED.js";
14
+ import "../chunk-ONP6BRZO.js";
12
15
  import "../chunk-5PIMDP4N.js";
13
16
  import "../chunk-45ARVNT3.js";
14
17
  import {
15
18
  resolveGitHubTokenForRequest
16
- } from "../chunk-NKDATSPA.js";
19
+ } from "../chunk-DP6RTINQ.js";
17
20
  import "../chunk-TJNJKPUL.js";
18
21
  import {
19
22
  withTrailers
20
23
  } from "../chunk-KH22FJO5.js";
21
24
 
22
25
  // src/api-routes/section-add.ts
26
+ import { isSafeKey } from "@setzkasten-cms/core";
23
27
  var POST = async ({ request, cookies }) => {
24
28
  const session = cookies.get("setzkasten_session")?.value;
25
29
  if (!session) return new Response("Unauthorized", { status: 401 });
@@ -40,7 +44,24 @@ var POST = async ({ request, cookies }) => {
40
44
  if (!pageKey || !sectionType) {
41
45
  return Response.json({ error: "pageKey and sectionType are required" }, { status: 400 });
42
46
  }
43
- const denied = await guardPageAccess(parseSession(cookies.get("setzkasten_session")?.value), pageKey, fullConfig, request);
47
+ if (!isSafeKey(pageKey)) {
48
+ return Response.json({ error: "invalid pageKey" }, { status: 400 });
49
+ }
50
+ if (!isSafeKey(sectionType)) {
51
+ return Response.json({ error: "invalid sectionType" }, { status: 400 });
52
+ }
53
+ if (body.sectionKey !== void 0 && !isSafeKey(body.sectionKey)) {
54
+ return Response.json({ error: "invalid sectionKey" }, { status: 400 });
55
+ }
56
+ if (sourcePage !== void 0 && !isSafeKey(sourcePage)) {
57
+ return Response.json({ error: "invalid sourcePage" }, { status: 400 });
58
+ }
59
+ const denied = await guardPageAccess(
60
+ parseSession(cookies.get("setzkasten_session")?.value),
61
+ pageKey,
62
+ fullConfig,
63
+ request
64
+ );
44
65
  if (denied) return denied;
45
66
  const headers = {
46
67
  Authorization: `Bearer ${githubToken}`,
@@ -56,7 +77,10 @@ var POST = async ({ request, cookies }) => {
56
77
  const existingKeys = (pageConfig.sections ?? []).map((s) => s.key);
57
78
  const newKey = body.sectionKey ?? generateAddKey(existingKeys, sectionType);
58
79
  if (existingKeys.includes(newKey)) {
59
- return Response.json({ error: `Key "${newKey}" already exists on this page` }, { status: 409 });
80
+ return Response.json(
81
+ { error: `Key "${newKey}" already exists on this page` },
82
+ { status: 409 }
83
+ );
60
84
  }
61
85
  let defaultContent = {};
62
86
  if (sourcePage) {
@@ -126,7 +150,13 @@ async function fetchFileContent(owner, repo, branch, path, token) {
126
150
  try {
127
151
  const res = await fetch(
128
152
  `https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=${branch}`,
129
- { headers: { Authorization: `Bearer ${token}`, Accept: "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28" } }
153
+ {
154
+ headers: {
155
+ Authorization: `Bearer ${token}`,
156
+ Accept: "application/vnd.github+json",
157
+ "X-GitHub-Api-Version": "2022-11-28"
158
+ }
159
+ }
130
160
  );
131
161
  if (!res.ok) return null;
132
162
  const data = await res.json();
@@ -137,16 +167,34 @@ async function fetchFileContent(owner, repo, branch, path, token) {
137
167
  }
138
168
  async function batchCommit(owner, repo, branch, files, message, headers) {
139
169
  try {
140
- const refRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/git/refs/heads/${branch}`, { headers });
170
+ const refRes = await fetch(
171
+ `https://api.github.com/repos/${owner}/${repo}/git/refs/heads/${branch}`,
172
+ { headers }
173
+ );
141
174
  if (!refRes.ok) return { ok: false, error: `Failed to get HEAD: ${refRes.status}` };
142
- const { object: { sha: headSha } } = await refRes.json();
143
- const commitRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/git/commits/${headSha}`, { headers });
175
+ const {
176
+ object: { sha: headSha }
177
+ } = await refRes.json();
178
+ const commitRes = await fetch(
179
+ `https://api.github.com/repos/${owner}/${repo}/git/commits/${headSha}`,
180
+ { headers }
181
+ );
144
182
  if (!commitRes.ok) return { ok: false, error: `Failed to get commit: ${commitRes.status}` };
145
- const { tree: { sha: baseSha } } = await commitRes.json();
183
+ const {
184
+ tree: { sha: baseSha }
185
+ } = await commitRes.json();
146
186
  const treeRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/git/trees`, {
147
187
  method: "POST",
148
188
  headers,
149
- body: JSON.stringify({ base_tree: baseSha, tree: files.map((f) => ({ path: f.path, mode: "100644", type: "blob", content: f.content })) })
189
+ body: JSON.stringify({
190
+ base_tree: baseSha,
191
+ tree: files.map((f) => ({
192
+ path: f.path,
193
+ mode: "100644",
194
+ type: "blob",
195
+ content: f.content
196
+ }))
197
+ })
150
198
  });
151
199
  if (!treeRes.ok) return { ok: false, error: `Failed to create tree: ${treeRes.status}` };
152
200
  const { sha: treeSha } = await treeRes.json();
@@ -155,13 +203,17 @@ async function batchCommit(owner, repo, branch, files, message, headers) {
155
203
  headers,
156
204
  body: JSON.stringify({ tree: treeSha, parents: [headSha], message })
157
205
  });
158
- if (!newCommitRes.ok) return { ok: false, error: `Failed to create commit: ${newCommitRes.status}` };
206
+ if (!newCommitRes.ok)
207
+ return { ok: false, error: `Failed to create commit: ${newCommitRes.status}` };
159
208
  const { sha: newSha } = await newCommitRes.json();
160
- const updateRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/git/refs/heads/${branch}`, {
161
- method: "PATCH",
162
- headers,
163
- body: JSON.stringify({ sha: newSha })
164
- });
209
+ const updateRes = await fetch(
210
+ `https://api.github.com/repos/${owner}/${repo}/git/refs/heads/${branch}`,
211
+ {
212
+ method: "PATCH",
213
+ headers,
214
+ body: JSON.stringify({ sha: newSha })
215
+ }
216
+ );
165
217
  if (!updateRes.ok) return { ok: false, error: `Failed to update ref: ${updateRes.status}` };
166
218
  return { ok: true, sha: newSha };
167
219
  } catch (error) {