@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,22 +1,26 @@
1
1
  import type { APIRoute } from 'astro'
2
+ import { listAllWebsites } from './_website-resolver'
2
3
 
3
4
  // Vite-define injected by @setzkasten-cms/astro at build time. Available
4
5
  // in API-only Vercel cold-starts where the page-ssr injectScript that
5
6
  // writes globalThis.__SETZKASTEN_CONFIG__ does not fire.
6
- declare const __SETZKASTEN_BUILD_CONFIG__: {
7
- adminPath?: string
8
- updaterUrl?: string
9
- version?: string
10
- websiteUrl?: string
11
- hasGitHub?: boolean
12
- storage?: {
13
- owner?: string
14
- repo?: string
15
- branch?: string
16
- contentPath?: string
17
- assetsPath?: string
18
- }
19
- } | null | undefined
7
+ declare const __SETZKASTEN_BUILD_CONFIG__:
8
+ | {
9
+ adminPath?: string
10
+ updaterUrl?: string
11
+ version?: string
12
+ websiteUrl?: string
13
+ hasGitHub?: boolean
14
+ storage?: {
15
+ owner?: string
16
+ repo?: string
17
+ branch?: string
18
+ contentPath?: string
19
+ assetsPath?: string
20
+ }
21
+ }
22
+ | null
23
+ | undefined
20
24
 
21
25
  /**
22
26
  * Registers this Setzkasten instance with the central updater backend.
@@ -45,9 +49,9 @@ export const POST: APIRoute = async ({ cookies, request }) => {
45
49
  websiteUrl?: string
46
50
  storage?: { owner?: string; repo?: string }
47
51
  }
48
- const buildConfig = (typeof __SETZKASTEN_BUILD_CONFIG__ !== 'undefined'
49
- ? __SETZKASTEN_BUILD_CONFIG__
50
- : null) as ConfigShape | null
52
+ const buildConfig = (
53
+ typeof __SETZKASTEN_BUILD_CONFIG__ !== 'undefined' ? __SETZKASTEN_BUILD_CONFIG__ : null
54
+ ) as ConfigShape | null
51
55
  const runtimeConfig = (globalThis as any).__SETZKASTEN_CONFIG__ as ConfigShape | undefined
52
56
  const config: ConfigShape | null = runtimeConfig ?? buildConfig
53
57
 
@@ -74,7 +78,7 @@ export const POST: APIRoute = async ({ cookies, request }) => {
74
78
  let licenseKey: string | undefined
75
79
  try {
76
80
  if (request.headers.get('content-type')?.includes('application/json')) {
77
- const parsed = await request.json() as { licenseEmail?: string; licenseKey?: string }
81
+ const parsed = (await request.json()) as { licenseEmail?: string; licenseKey?: string }
78
82
  licenseEmail = parsed.licenseEmail?.trim() || undefined
79
83
  licenseKey = parsed.licenseKey?.trim() || undefined
80
84
  }
@@ -82,6 +86,13 @@ export const POST: APIRoute = async ({ cookies, request }) => {
82
86
  // Empty / malformed body — treat as no UI input
83
87
  }
84
88
 
89
+ // Pull the current website list from the resolver so the updater backend
90
+ // sees every website this instance manages (multi-mode) — or the single
91
+ // synthesized entry in single-repo mode. Errors fall through to [] so a
92
+ // resolver glitch doesn't break the heartbeat itself.
93
+ const websitesResult = await listAllWebsites()
94
+ const managedWebsites = websitesResult.ok ? websitesResult.value.map((w) => w.id) : []
95
+
85
96
  try {
86
97
  const response = await fetch(`${updaterUrl}/api/register`, {
87
98
  method: 'POST',
@@ -93,7 +104,7 @@ export const POST: APIRoute = async ({ cookies, request }) => {
93
104
  licenseEmail,
94
105
  licenseKey,
95
106
  telemetryEnabled: true,
96
- managedWebsites: [],
107
+ managedWebsites,
97
108
  }),
98
109
  signal: AbortSignal.timeout(5000),
99
110
  })
@@ -102,7 +113,10 @@ export const POST: APIRoute = async ({ cookies, request }) => {
102
113
  throw new Error(`HTTP ${response.status}`)
103
114
  }
104
115
 
105
- const data = await response.json() as { firebaseConfig?: { apiKey: string; authDomain: string; projectId: string }; [key: string]: unknown }
116
+ const data = (await response.json()) as {
117
+ firebaseConfig?: { apiKey: string; authDomain: string; projectId: string }
118
+ [key: string]: unknown
119
+ }
106
120
 
107
121
  return Response.json({ ...data, currentVersion, _firebaseConfig: data.firebaseConfig ?? null })
108
122
  } catch {
@@ -1,5 +1,5 @@
1
- import type { APIRoute } from 'astro'
2
1
  import { createHash } from 'node:crypto'
2
+ import type { APIRoute } from 'astro'
3
3
 
4
4
  /**
5
5
  * Transfer a license to the current Setzkasten instance.
@@ -13,11 +13,13 @@ export const POST: APIRoute = async ({ cookies }) => {
13
13
  return new Response('Unauthorized', { status: 401 })
14
14
  }
15
15
 
16
- const config = (globalThis as any).__SETZKASTEN_CONFIG__ as {
17
- updaterUrl?: string
18
- websiteUrl?: string
19
- storage?: { owner?: string; repo?: string }
20
- } | undefined
16
+ const config = (globalThis as any).__SETZKASTEN_CONFIG__ as
17
+ | {
18
+ updaterUrl?: string
19
+ websiteUrl?: string
20
+ storage?: { owner?: string; repo?: string }
21
+ }
22
+ | undefined
21
23
 
22
24
  const updaterUrl = config?.updaterUrl
23
25
  if (!updaterUrl) {
@@ -1,5 +1,5 @@
1
- import type { APIRoute } from 'astro'
2
1
  import { createHash } from 'node:crypto'
2
+ import type { APIRoute } from 'astro'
3
3
 
4
4
  /**
5
5
  * Release the license binding for this Setzkasten instance.
@@ -19,15 +19,19 @@ export const POST: APIRoute = async ({ cookies, request }) => {
19
19
  return new Response('Unauthorized', { status: 401 })
20
20
  }
21
21
 
22
- const config = (globalThis as any).__SETZKASTEN_CONFIG__ as {
23
- updaterUrl?: string
24
- websiteUrl?: string
25
- storage?: { owner?: string; repo?: string }
26
- } | undefined
27
-
28
- const fullConfig = (globalThis as any).__SETZKASTEN_FULL_CONFIG__ as {
29
- license?: { email?: string; key?: string }
30
- } | undefined
22
+ const config = (globalThis as any).__SETZKASTEN_CONFIG__ as
23
+ | {
24
+ updaterUrl?: string
25
+ websiteUrl?: string
26
+ storage?: { owner?: string; repo?: string }
27
+ }
28
+ | undefined
29
+
30
+ const fullConfig = (globalThis as any).__SETZKASTEN_FULL_CONFIG__ as
31
+ | {
32
+ license?: { email?: string; key?: string }
33
+ }
34
+ | undefined
31
35
 
32
36
  const updaterUrl = config?.updaterUrl
33
37
  if (!updaterUrl) {
@@ -1,15 +1,11 @@
1
+ import { type WebhookConfig, type WebhookPayload, parseWebhooksFile } from '@setzkasten-cms/core'
1
2
  import type { APIRoute } from 'astro'
2
- import {
3
- parseWebhooksFile,
4
- type WebhookConfig,
5
- type WebhookPayload,
6
- } from '@setzkasten-cms/core'
7
- import { resolveStorageConfigForRequest } from './_storage-config'
8
- import { resolveGitHubTokenForRequest } from './_github-token'
9
3
  import { parseSession, requireAdmin } from './_auth-guard'
10
4
  import { gateFeature } from './_feature-gate'
11
- import { recordWebhookFire } from './_webhook-status-store'
5
+ import { resolveGitHubTokenForRequest } from './_github-token'
6
+ import { resolveStorageConfigForRequest } from './_storage-config'
12
7
  import { signPayload } from './_webhook-signing'
8
+ import { recordWebhookFire } from './_webhook-status-store'
13
9
 
14
10
  const WEBHOOKS_FILE = (contentPath: string) => `${contentPath}/_webhooks.json`
15
11
  const TEST_TIMEOUT_MS = 10_000
@@ -51,9 +47,11 @@ export const POST: APIRoute = async ({ request, cookies }) => {
51
47
  }
52
48
  const { owner, repo, branch } = storage
53
49
 
54
- const serverConfig = (globalThis as {
55
- __SETZKASTEN_CONFIG__?: { storage?: { contentPath?: string } }
56
- }).__SETZKASTEN_CONFIG__
50
+ const serverConfig = (
51
+ globalThis as {
52
+ __SETZKASTEN_CONFIG__?: { storage?: { contentPath?: string } }
53
+ }
54
+ ).__SETZKASTEN_CONFIG__
57
55
  const contentPath = serverConfig?.storage?.contentPath ?? 'content'
58
56
 
59
57
  // Read webhooks file directly (no cache — we want the freshly-saved value)
@@ -1,15 +1,11 @@
1
+ import { type WebhookConfig, parseWebhooksFile, validateWebhookConfig } from '@setzkasten-cms/core'
1
2
  import type { APIRoute } from 'astro'
2
- import {
3
- parseWebhooksFile,
4
- validateWebhookConfig,
5
- type WebhookConfig,
6
- } from '@setzkasten-cms/core'
7
- import { resolveStorageConfigForRequest } from './_storage-config'
8
- import { resolveGitHubTokenForRequest } from './_github-token'
9
3
  import { parseSession, requireAdmin } from './_auth-guard'
10
- import { cachedFetch, invalidateCache } from './_github-cache'
11
4
  import { withTrailers } from './_commit-trailers'
12
5
  import { gateFeature } from './_feature-gate'
6
+ import { cachedFetch, invalidateCache } from './_github-cache'
7
+ import { resolveGitHubTokenForRequest } from './_github-token'
8
+ import { resolveStorageConfigForRequest } from './_storage-config'
13
9
 
14
10
  const WEBHOOKS_FILE = (contentPath: string) => `${contentPath}/_webhooks.json`
15
11
 
@@ -89,10 +85,7 @@ export const PUT: APIRoute = async ({ request, cookies }) => {
89
85
  for (let i = 0; i < body.webhooks.length; i++) {
90
86
  const result = validateWebhookConfig(body.webhooks[i])
91
87
  if (!result.ok) {
92
- return Response.json(
93
- { error: result.error.message, index: i },
94
- { status: 400 },
95
- )
88
+ return Response.json({ error: result.error.message, index: i }, { status: 400 })
96
89
  }
97
90
  if (seenIds.has(result.value.id)) {
98
91
  return Response.json(
@@ -141,10 +134,11 @@ export const PUT: APIRoute = async ({ request, cookies }) => {
141
134
  }
142
135
  if (currentSha) putBody.sha = currentSha
143
136
 
144
- const putRes = await fetch(
145
- `https://api.github.com/repos/${owner}/${repo}/contents/${filePath}`,
146
- { method: 'PUT', headers, body: JSON.stringify(putBody) },
147
- )
137
+ const putRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/contents/${filePath}`, {
138
+ method: 'PUT',
139
+ headers,
140
+ body: JSON.stringify(putBody),
141
+ })
148
142
 
149
143
  if (!putRes.ok) {
150
144
  const text = await putRes.text()
@@ -156,8 +150,10 @@ export const PUT: APIRoute = async ({ request, cookies }) => {
156
150
  }
157
151
 
158
152
  function resolveContentPath(): string {
159
- const serverConfig = (globalThis as {
160
- __SETZKASTEN_CONFIG__?: { storage?: { contentPath?: string } }
161
- }).__SETZKASTEN_CONFIG__
153
+ const serverConfig = (
154
+ globalThis as {
155
+ __SETZKASTEN_CONFIG__?: { storage?: { contentPath?: string } }
156
+ }
157
+ ).__SETZKASTEN_CONFIG__
162
158
  return serverConfig?.storage?.contentPath ?? 'content'
163
159
  }