@setzkasten-cms/astro-admin 1.4.6 → 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.
- package/dist/api-routes/_auth-guard.d.ts +27 -3
- package/dist/api-routes/_auth-guard.js +5 -2
- package/dist/api-routes/_dev-session-secret.d.ts +8 -0
- package/dist/api-routes/_dev-session-secret.js +8 -0
- package/dist/api-routes/_github-token.js +1 -1
- package/dist/api-routes/_role-resolver.js +6 -3
- package/dist/api-routes/_session-secret.d.ts +19 -0
- package/dist/api-routes/_session-secret.js +7 -0
- package/dist/api-routes/_session-signing.d.ts +45 -0
- package/dist/api-routes/_session-signing.js +8 -0
- package/dist/api-routes/_webhook-dispatcher.js +4 -4
- package/dist/api-routes/asset-proxy.js +1 -1
- package/dist/api-routes/auth-callback.js +12 -5
- package/dist/api-routes/auth-logout.d.ts +4 -4
- package/dist/api-routes/auth-logout.js +8 -2
- package/dist/api-routes/auth-session.d.ts +6 -0
- package/dist/api-routes/auth-session.js +19 -19
- package/dist/api-routes/auth-setzkasten-login.js +14 -7
- package/dist/api-routes/catalog-add.js +59 -17
- package/dist/api-routes/catalog-export.js +14 -4
- package/dist/api-routes/config.d.ts +10 -3
- package/dist/api-routes/config.js +26 -4
- package/dist/api-routes/deploy-hook.js +8 -8
- package/dist/api-routes/editors.d.ts +1 -1
- package/dist/api-routes/editors.js +5 -2
- package/dist/api-routes/github-proxy.js +30 -8
- package/dist/api-routes/global-config.js +6 -3
- package/dist/api-routes/history-rollback.js +31 -14
- package/dist/api-routes/history-version.js +8 -6
- package/dist/api-routes/history.js +5 -2
- package/dist/api-routes/icons-local.js +1 -1
- package/dist/api-routes/init-add-section.js +113 -47
- package/dist/api-routes/init-apply.js +56 -42
- package/dist/api-routes/init-migrate.js +43 -36
- package/dist/api-routes/init-scan-page.d.ts +1 -1
- package/dist/api-routes/init-scan-page.js +59 -13
- package/dist/api-routes/init-scan.js +22 -7
- package/dist/api-routes/migrate-to-multi.js +5 -2
- package/dist/api-routes/pages.js +15 -4
- package/dist/api-routes/section-add.js +68 -16
- package/dist/api-routes/section-commit-pending.js +70 -22
- package/dist/api-routes/section-delete.js +49 -14
- package/dist/api-routes/section-duplicate.js +65 -16
- package/dist/api-routes/section-prepare-copy.js +15 -2
- package/dist/api-routes/section-prepare.js +25 -4
- package/dist/api-routes/setup-github-app-bounce.js +15 -1
- package/dist/api-routes/setup-github-app-branches.js +9 -6
- package/dist/api-routes/setup-github-app-callback.js +24 -1
- package/dist/api-routes/setup-github-app-credentials.d.ts +27 -0
- package/dist/api-routes/setup-github-app-credentials.js +43 -0
- package/dist/api-routes/setup-github-app-installed.js +22 -1
- package/dist/api-routes/setup-github-app-repos.js +5 -2
- package/dist/api-routes/setup-github-app.d.ts +4 -0
- package/dist/api-routes/setup-github-app.js +19 -2
- package/dist/api-routes/updater-register.js +7 -1
- package/dist/api-routes/webhooks-status.js +5 -2
- package/dist/api-routes/webhooks-test.js +9 -8
- package/dist/api-routes/webhooks.js +12 -14
- package/dist/api-routes/websites-add.js +5 -2
- package/dist/api-routes/websites-remove.js +5 -2
- package/dist/{chunk-ZQDGGWJP.js → chunk-5KMGSFCZ.js} +2 -2
- package/dist/{chunk-Q3N336KR.js → chunk-CDXCYYQR.js} +29 -24
- package/dist/{chunk-NKDATSPA.js → chunk-DP6RTINQ.js} +1 -1
- package/dist/chunk-KENFINT4.js +76 -0
- package/dist/chunk-ONP6BRZO.js +47 -0
- package/dist/{chunk-INIWFKQ3.js → chunk-Q5HV47DW.js} +33 -19
- package/dist/chunk-QVCW6EF3.js +26 -0
- package/dist/{chunk-TD76R3A6.js → chunk-UHI6323G.js} +293 -174
- package/dist/{chunk-AM4DZXXM.js → chunk-UJAFZEX2.js} +76 -9
- package/package.json +12 -6
- package/src/api-routes/__tests__/_session-signing.test.ts +114 -0
- package/src/api-routes/__tests__/_session-test-helper.ts +27 -0
- package/src/api-routes/__tests__/add-section-helpers.test.ts +59 -25
- package/src/api-routes/__tests__/auth-guard.test.ts +46 -7
- package/src/api-routes/__tests__/catalog-api.test.ts +14 -6
- package/src/api-routes/__tests__/commit-trailers.test.ts +5 -5
- package/src/api-routes/__tests__/deferred-operations.test.ts +9 -12
- package/src/api-routes/__tests__/deploy-hook.test.ts +3 -8
- package/src/api-routes/__tests__/feature-gate.test.ts +1 -1
- package/src/api-routes/__tests__/github-cache.test.ts +1 -1
- package/src/api-routes/__tests__/github-token.test.ts +1 -1
- package/src/api-routes/__tests__/global-config-theme.test.ts +4 -4
- package/src/api-routes/__tests__/history-rollback.test.ts +6 -3
- package/src/api-routes/__tests__/history.test.ts +9 -6
- package/src/api-routes/__tests__/init-scan-page-resolve-config.test.ts +11 -3
- package/src/api-routes/__tests__/migrate-to-multi.test.ts +5 -1
- package/src/api-routes/__tests__/pages-meta-store.test.ts +10 -5
- package/src/api-routes/__tests__/pages.test.ts +7 -2
- package/src/api-routes/__tests__/patch-page-file.test.ts +71 -19
- package/src/api-routes/__tests__/route-registry.test.ts +11 -18
- package/src/api-routes/__tests__/scan-page-helpers.test.ts +13 -10
- package/src/api-routes/__tests__/section-management.test.ts +28 -28
- package/src/api-routes/__tests__/setup-github-app-callback.test.ts +58 -16
- package/src/api-routes/__tests__/setup-github-app-repos.test.ts +4 -5
- package/src/api-routes/__tests__/setup-github-app.test.ts +27 -7
- package/src/api-routes/__tests__/storage-config-for-request.test.ts +83 -0
- package/src/api-routes/__tests__/updater-register.test.ts +230 -0
- package/src/api-routes/__tests__/webhook-signing.test.ts +1 -1
- package/src/api-routes/__tests__/webhooks.test.ts +19 -7
- package/src/api-routes/__tests__/websites-add.test.ts +2 -1
- package/src/api-routes/__tests__/websites-remove.test.ts +2 -1
- package/src/api-routes/_auth-guard.ts +47 -15
- package/src/api-routes/_commit-trailers.ts +3 -2
- package/src/api-routes/_dev-session-secret.ts +79 -0
- package/src/api-routes/_github-token.ts +1 -1
- package/src/api-routes/_pages-meta-store.ts +2 -2
- package/src/api-routes/_role-resolver.ts +7 -5
- package/src/api-routes/_session-secret.ts +46 -0
- package/src/api-routes/_session-signing.ts +135 -0
- package/src/api-routes/_vercel-origin.ts +2 -6
- package/src/api-routes/_webhook-dispatcher.ts +12 -16
- package/src/api-routes/_website-resolver.ts +3 -10
- package/src/api-routes/auth-callback.ts +9 -5
- package/src/api-routes/auth-login.ts +5 -3
- package/src/api-routes/auth-logout.ts +18 -1
- package/src/api-routes/auth-session.ts +13 -21
- package/src/api-routes/auth-setzkasten-login.ts +12 -9
- package/src/api-routes/catalog-add.ts +89 -31
- package/src/api-routes/catalog-export.ts +30 -10
- package/src/api-routes/config.ts +39 -6
- package/src/api-routes/deploy-hook.ts +13 -11
- package/src/api-routes/editors.ts +33 -22
- package/src/api-routes/github-proxy.ts +25 -11
- package/src/api-routes/global-config.ts +103 -18
- package/src/api-routes/history-rollback.ts +41 -14
- package/src/api-routes/history-version.ts +5 -6
- package/src/api-routes/history.ts +3 -3
- package/src/api-routes/icons-local.ts +2 -2
- package/src/api-routes/init-add-section.ts +174 -79
- package/src/api-routes/init-apply.ts +71 -56
- package/src/api-routes/init-migrate.ts +54 -48
- package/src/api-routes/init-scan-page.ts +77 -30
- package/src/api-routes/init-scan.ts +19 -11
- package/src/api-routes/pages.ts +16 -11
- package/src/api-routes/section-add.ts +98 -27
- package/src/api-routes/section-commit-pending.ts +87 -34
- package/src/api-routes/section-delete.ts +76 -27
- package/src/api-routes/section-duplicate.ts +95 -28
- package/src/api-routes/section-management.ts +3 -7
- package/src/api-routes/section-prepare-copy.ts +29 -8
- package/src/api-routes/section-prepare.ts +38 -10
- package/src/api-routes/setup-github-app-bounce.ts +7 -1
- package/src/api-routes/setup-github-app-branches.ts +6 -7
- package/src/api-routes/setup-github-app-callback.ts +18 -1
- package/src/api-routes/setup-github-app-credentials.ts +55 -0
- package/src/api-routes/setup-github-app-installed.ts +12 -1
- package/src/api-routes/setup-github-app-repos.ts +2 -3
- package/src/api-routes/setup-github-app.ts +14 -5
- package/src/api-routes/updater-check.ts +6 -4
- package/src/api-routes/updater-register.ts +34 -20
- package/src/api-routes/updater-transfer.ts +8 -6
- package/src/api-routes/updater-unbind.ts +14 -10
- package/src/api-routes/webhooks-test.ts +9 -11
- package/src/api-routes/webhooks.ts +15 -19
- package/src/init/__tests__/page-level.test.ts +279 -105
- package/src/init/__tests__/page-list-coverage.test.ts +70 -70
- package/src/init/__tests__/patcher-child-component.test.ts +12 -3
- package/src/init/__tests__/patcher-edge-cases.test.ts +47 -23
- package/src/init/__tests__/patcher-mixed-content-wrapper.test.ts +16 -6
- package/src/init/__tests__/patcher-page-mode.test.ts +30 -20
- package/src/init/__tests__/section-pipeline.test.ts +53 -19
- package/src/init/astro-config-patcher.ts +4 -18
- package/src/init/astro-detector.ts +2 -7
- package/src/init/astro-section-analyzer-v2.ts +475 -193
- package/src/init/field-label-enricher.ts +6 -6
- package/src/init/template-patcher-v2.ts +218 -97
|
@@ -30,10 +30,10 @@ var POST = async ({ cookies }) => {
|
|
|
30
30
|
});
|
|
31
31
|
if (!response.ok) {
|
|
32
32
|
console.warn(`[setzkasten] Deploy hook antwortete mit ${response.status}: ${url}`);
|
|
33
|
-
return new Response(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
);
|
|
33
|
+
return new Response(JSON.stringify({ ok: false, status: response.status }), {
|
|
34
|
+
status: 200,
|
|
35
|
+
headers: { "Content-Type": "application/json" }
|
|
36
|
+
});
|
|
37
37
|
}
|
|
38
38
|
return new Response(JSON.stringify({ ok: true }), {
|
|
39
39
|
status: 200,
|
|
@@ -41,10 +41,10 @@ var POST = async ({ cookies }) => {
|
|
|
41
41
|
});
|
|
42
42
|
} catch (error) {
|
|
43
43
|
console.error("[setzkasten] Deploy hook fehlgeschlagen:", error);
|
|
44
|
-
return new Response(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
);
|
|
44
|
+
return new Response(JSON.stringify({ ok: false, error: String(error) }), {
|
|
45
|
+
status: 200,
|
|
46
|
+
headers: { "Content-Type": "application/json" }
|
|
47
|
+
});
|
|
48
48
|
}
|
|
49
49
|
};
|
|
50
50
|
export {
|
|
@@ -3,11 +3,14 @@ import {
|
|
|
3
3
|
PUT,
|
|
4
4
|
readEditorsFile,
|
|
5
5
|
readEditorsFileStatus
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-Q5HV47DW.js";
|
|
7
|
+
import "../chunk-QVCW6EF3.js";
|
|
8
|
+
import "../chunk-KENFINT4.js";
|
|
7
9
|
import "../chunk-6UIKVKED.js";
|
|
10
|
+
import "../chunk-ONP6BRZO.js";
|
|
8
11
|
import "../chunk-5PIMDP4N.js";
|
|
9
12
|
import "../chunk-45ARVNT3.js";
|
|
10
|
-
import "../chunk-
|
|
13
|
+
import "../chunk-DP6RTINQ.js";
|
|
11
14
|
import "../chunk-TJNJKPUL.js";
|
|
12
15
|
import "../chunk-KH22FJO5.js";
|
|
13
16
|
export {
|
|
@@ -1,12 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parseSession
|
|
3
|
+
} from "../chunk-Q5HV47DW.js";
|
|
4
|
+
import "../chunk-QVCW6EF3.js";
|
|
5
|
+
import "../chunk-KENFINT4.js";
|
|
6
|
+
import {
|
|
7
|
+
resolveStorageConfigForRequest
|
|
8
|
+
} from "../chunk-6UIKVKED.js";
|
|
9
|
+
import "../chunk-ONP6BRZO.js";
|
|
10
|
+
import "../chunk-5PIMDP4N.js";
|
|
11
|
+
import "../chunk-45ARVNT3.js";
|
|
1
12
|
import {
|
|
2
13
|
resolveGitHubTokenForRequest
|
|
3
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-DP6RTINQ.js";
|
|
15
|
+
import "../chunk-TJNJKPUL.js";
|
|
16
|
+
import "../chunk-KH22FJO5.js";
|
|
4
17
|
|
|
5
18
|
// src/api-routes/github-proxy.ts
|
|
6
19
|
import { writeFile } from "fs/promises";
|
|
7
20
|
import { join } from "path";
|
|
8
21
|
var ALL = async ({ params, request, cookies }) => {
|
|
9
|
-
const session = cookies.get("setzkasten_session")?.value;
|
|
22
|
+
const session = parseSession(cookies.get("setzkasten_session")?.value);
|
|
10
23
|
if (!session) {
|
|
11
24
|
return new Response("Unauthorized", { status: 401 });
|
|
12
25
|
}
|
|
@@ -14,6 +27,17 @@ var ALL = async ({ params, request, cookies }) => {
|
|
|
14
27
|
if (!githubPath) {
|
|
15
28
|
return new Response("Missing path", { status: 400 });
|
|
16
29
|
}
|
|
30
|
+
const storage = await resolveStorageConfigForRequest(request);
|
|
31
|
+
if (!storage) {
|
|
32
|
+
return new Response("Could not resolve owner/repo", { status: 400 });
|
|
33
|
+
}
|
|
34
|
+
const allowedPrefix = `repos/${storage.owner}/${storage.repo}/`;
|
|
35
|
+
const allowedExact = `repos/${storage.owner}/${storage.repo}`;
|
|
36
|
+
if (githubPath !== allowedExact && !githubPath.startsWith(allowedPrefix)) {
|
|
37
|
+
return new Response(`Forbidden: proxy is scoped to ${storage.owner}/${storage.repo}`, {
|
|
38
|
+
status: 403
|
|
39
|
+
});
|
|
40
|
+
}
|
|
17
41
|
const tokenResult = await resolveGitHubTokenForRequest(request);
|
|
18
42
|
if (!tokenResult.ok) {
|
|
19
43
|
return new Response(tokenResult.error.message, { status: 500 });
|
|
@@ -38,11 +62,7 @@ var ALL = async ({ params, request, cookies }) => {
|
|
|
38
62
|
});
|
|
39
63
|
const responseHeaders = new Headers();
|
|
40
64
|
responseHeaders.set("Content-Type", response.headers.get("content-type") ?? "application/json");
|
|
41
|
-
const rateLimitHeaders = [
|
|
42
|
-
"x-ratelimit-limit",
|
|
43
|
-
"x-ratelimit-remaining",
|
|
44
|
-
"x-ratelimit-reset"
|
|
45
|
-
];
|
|
65
|
+
const rateLimitHeaders = ["x-ratelimit-limit", "x-ratelimit-remaining", "x-ratelimit-reset"];
|
|
46
66
|
for (const header of rateLimitHeaders) {
|
|
47
67
|
const value = response.headers.get(header);
|
|
48
68
|
if (value) responseHeaders.set(header, value);
|
|
@@ -59,7 +79,9 @@ var ALL = async ({ params, request, cookies }) => {
|
|
|
59
79
|
const filePath = contentsMatch[1];
|
|
60
80
|
const parsed = JSON.parse(body);
|
|
61
81
|
if (parsed.content) {
|
|
62
|
-
const decoded = Buffer.from(parsed.content.replace(/\s/g, ""), "base64").toString(
|
|
82
|
+
const decoded = Buffer.from(parsed.content.replace(/\s/g, ""), "base64").toString(
|
|
83
|
+
"utf-8"
|
|
84
|
+
);
|
|
63
85
|
await writeFile(join(repoRoot, filePath), decoded, "utf-8").catch(() => {
|
|
64
86
|
});
|
|
65
87
|
}
|
|
@@ -3,12 +3,15 @@ import {
|
|
|
3
3
|
PUT,
|
|
4
4
|
readGlobalConfig,
|
|
5
5
|
writeGlobalConfig
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-UJAFZEX2.js";
|
|
7
|
+
import "../chunk-Q5HV47DW.js";
|
|
8
|
+
import "../chunk-QVCW6EF3.js";
|
|
9
|
+
import "../chunk-KENFINT4.js";
|
|
8
10
|
import "../chunk-6UIKVKED.js";
|
|
11
|
+
import "../chunk-ONP6BRZO.js";
|
|
9
12
|
import "../chunk-5PIMDP4N.js";
|
|
10
13
|
import "../chunk-45ARVNT3.js";
|
|
11
|
-
import "../chunk-
|
|
14
|
+
import "../chunk-DP6RTINQ.js";
|
|
12
15
|
import "../chunk-TJNJKPUL.js";
|
|
13
16
|
import "../chunk-KH22FJO5.js";
|
|
14
17
|
export {
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseSession,
|
|
3
3
|
requireAdmin
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-Q5HV47DW.js";
|
|
5
|
+
import "../chunk-QVCW6EF3.js";
|
|
6
|
+
import "../chunk-KENFINT4.js";
|
|
5
7
|
import {
|
|
6
8
|
resolveStorageConfigForRequest
|
|
7
9
|
} from "../chunk-6UIKVKED.js";
|
|
10
|
+
import "../chunk-ONP6BRZO.js";
|
|
8
11
|
import "../chunk-5PIMDP4N.js";
|
|
9
12
|
import {
|
|
10
13
|
invalidateCache
|
|
11
14
|
} from "../chunk-45ARVNT3.js";
|
|
12
15
|
import {
|
|
13
16
|
resolveGitHubTokenForRequest
|
|
14
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-DP6RTINQ.js";
|
|
15
18
|
import "../chunk-TJNJKPUL.js";
|
|
16
19
|
import {
|
|
17
20
|
withTrailers
|
|
@@ -40,6 +43,14 @@ var POST = async ({ request, cookies }) => {
|
|
|
40
43
|
return Response.json({ error: "Could not resolve owner/repo" }, { status: 400 });
|
|
41
44
|
}
|
|
42
45
|
const { owner, repo, branch } = storage;
|
|
46
|
+
const serverConfig = globalThis.__SETZKASTEN_CONFIG__;
|
|
47
|
+
const contentPath = serverConfig?.storage?.contentPath ?? "content";
|
|
48
|
+
if (!isPathInsideContent(path, contentPath)) {
|
|
49
|
+
return Response.json(
|
|
50
|
+
{ error: `Rollback restricted to the content folder (${contentPath}/...)` },
|
|
51
|
+
{ status: 400 }
|
|
52
|
+
);
|
|
53
|
+
}
|
|
43
54
|
const headers = {
|
|
44
55
|
Authorization: `Bearer ${tokenResult.value}`,
|
|
45
56
|
Accept: "application/vnd.github+json",
|
|
@@ -57,10 +68,7 @@ var POST = async ({ request, cookies }) => {
|
|
|
57
68
|
);
|
|
58
69
|
}
|
|
59
70
|
if (!versionRes.ok) {
|
|
60
|
-
return Response.json(
|
|
61
|
-
{ error: `Failed to read version: ${versionRes.status}` },
|
|
62
|
-
{ status: 502 }
|
|
63
|
-
);
|
|
71
|
+
return Response.json({ error: `Failed to read version: ${versionRes.status}` }, { status: 502 });
|
|
64
72
|
}
|
|
65
73
|
const versionData = await versionRes.json();
|
|
66
74
|
const targetContent = versionData.encoding === "base64" ? Buffer.from(versionData.content, "base64").toString("utf-8") : versionData.content;
|
|
@@ -84,20 +92,18 @@ var POST = async ({ request, cookies }) => {
|
|
|
84
92
|
}
|
|
85
93
|
const shortSha = sha.slice(0, 7);
|
|
86
94
|
const fileName = path.split("/").pop() ?? path;
|
|
87
|
-
const message = withTrailers(
|
|
88
|
-
`revert(${fileName}): rollback to ${shortSha}`,
|
|
89
|
-
session.user.email
|
|
90
|
-
);
|
|
95
|
+
const message = withTrailers(`revert(${fileName}): rollback to ${shortSha}`, session.user.email);
|
|
91
96
|
const putBody = {
|
|
92
97
|
message,
|
|
93
98
|
content: Buffer.from(targetContent).toString("base64"),
|
|
94
99
|
branch
|
|
95
100
|
};
|
|
96
101
|
if (currentSha) putBody.sha = currentSha;
|
|
97
|
-
const putRes = await fetch(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
102
|
+
const putRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/contents/${path}`, {
|
|
103
|
+
method: "PUT",
|
|
104
|
+
headers,
|
|
105
|
+
body: JSON.stringify(putBody)
|
|
106
|
+
});
|
|
101
107
|
if (!putRes.ok) {
|
|
102
108
|
const text = await putRes.text();
|
|
103
109
|
return Response.json({ error: `Rollback write failed: ${text}` }, { status: 502 });
|
|
@@ -106,6 +112,17 @@ var POST = async ({ request, cookies }) => {
|
|
|
106
112
|
const putData = await putRes.json();
|
|
107
113
|
return Response.json({ ok: true, commitSha: putData.commit.sha });
|
|
108
114
|
};
|
|
115
|
+
function isPathInsideContent(target, base) {
|
|
116
|
+
if (typeof target !== "string" || target.length === 0) return false;
|
|
117
|
+
if (target.includes("\0") || target.includes("\\")) return false;
|
|
118
|
+
if (target.startsWith("/")) return false;
|
|
119
|
+
const segments = target.split("/");
|
|
120
|
+
for (const seg of segments) {
|
|
121
|
+
if (seg === "" || seg === "." || seg === "..") return false;
|
|
122
|
+
}
|
|
123
|
+
const normalizedBase = base.replace(/^\/+|\/+$/g, "");
|
|
124
|
+
return target === normalizedBase || target.startsWith(`${normalizedBase}/`);
|
|
125
|
+
}
|
|
109
126
|
export {
|
|
110
127
|
POST
|
|
111
128
|
};
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
requireAdmin
|
|
3
|
-
} from "../chunk-
|
|
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";
|
|
7
10
|
import "../chunk-5PIMDP4N.js";
|
|
8
11
|
import {
|
|
9
12
|
cachedFetch
|
|
10
13
|
} from "../chunk-45ARVNT3.js";
|
|
11
14
|
import {
|
|
12
15
|
resolveGitHubTokenForRequest
|
|
13
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-DP6RTINQ.js";
|
|
14
17
|
import "../chunk-TJNJKPUL.js";
|
|
15
18
|
import "../chunk-KH22FJO5.js";
|
|
16
19
|
|
|
@@ -32,9 +35,7 @@ var GET = async ({ request, url, cookies }) => {
|
|
|
32
35
|
const { owner, repo } = storage;
|
|
33
36
|
const cacheKey = `history-version:${owner}/${repo}:${path}:${sha}`;
|
|
34
37
|
const result = await cachedFetch(cacheKey, 5 * 6e4, async () => {
|
|
35
|
-
const u = new URL(
|
|
36
|
-
`https://api.github.com/repos/${owner}/${repo}/contents/${path}`
|
|
37
|
-
);
|
|
38
|
+
const u = new URL(`https://api.github.com/repos/${owner}/${repo}/contents/${path}`);
|
|
38
39
|
u.searchParams.set("ref", sha);
|
|
39
40
|
const res = await fetch(u, {
|
|
40
41
|
headers: {
|
|
@@ -43,7 +44,8 @@ var GET = async ({ request, url, cookies }) => {
|
|
|
43
44
|
"X-GitHub-Api-Version": "2022-11-28"
|
|
44
45
|
}
|
|
45
46
|
});
|
|
46
|
-
if (res.status === 404)
|
|
47
|
+
if (res.status === 404)
|
|
48
|
+
return { ok: false, status: 404, error: "File not found at given sha" };
|
|
47
49
|
if (!res.ok) return { ok: false, status: 502, error: `GitHub returned ${res.status}` };
|
|
48
50
|
const data = await res.json();
|
|
49
51
|
const raw = data.encoding === "base64" ? Buffer.from(data.content, "base64").toString("utf-8") : data.content;
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
requireAdmin
|
|
3
|
-
} from "../chunk-
|
|
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";
|
|
7
10
|
import "../chunk-5PIMDP4N.js";
|
|
8
11
|
import {
|
|
9
12
|
cachedFetch
|
|
10
13
|
} from "../chunk-45ARVNT3.js";
|
|
11
14
|
import {
|
|
12
15
|
resolveGitHubTokenForRequest
|
|
13
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-DP6RTINQ.js";
|
|
14
17
|
import "../chunk-TJNJKPUL.js";
|
|
15
18
|
import "../chunk-KH22FJO5.js";
|
|
16
19
|
|
|
@@ -3,25 +3,33 @@ import {
|
|
|
3
3
|
patchChildComponentForFieldPrefix,
|
|
4
4
|
patchTemplateForFields,
|
|
5
5
|
stripTemplateFallbacks
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-CDXCYYQR.js";
|
|
7
|
+
import {
|
|
8
|
+
requireAdmin
|
|
9
|
+
} from "../chunk-Q5HV47DW.js";
|
|
10
|
+
import "../chunk-QVCW6EF3.js";
|
|
11
|
+
import "../chunk-KENFINT4.js";
|
|
7
12
|
import {
|
|
8
13
|
prefixPath,
|
|
9
14
|
resolveStorageConfigForRequest
|
|
10
15
|
} from "../chunk-6UIKVKED.js";
|
|
16
|
+
import "../chunk-ONP6BRZO.js";
|
|
17
|
+
import "../chunk-5PIMDP4N.js";
|
|
18
|
+
import "../chunk-45ARVNT3.js";
|
|
11
19
|
import {
|
|
12
20
|
resolveGitHubTokenForRequest
|
|
13
|
-
} from "../chunk-
|
|
21
|
+
} from "../chunk-DP6RTINQ.js";
|
|
22
|
+
import "../chunk-TJNJKPUL.js";
|
|
14
23
|
import {
|
|
15
24
|
withTrailers
|
|
16
25
|
} from "../chunk-KH22FJO5.js";
|
|
17
26
|
|
|
18
27
|
// src/api-routes/init-add-section.ts
|
|
28
|
+
import { isSafeKey } from "@setzkasten-cms/core";
|
|
19
29
|
import { addSectionToConfig } from "@setzkasten-cms/core/init";
|
|
20
30
|
var POST = async ({ request, cookies }) => {
|
|
21
|
-
const
|
|
22
|
-
if (
|
|
23
|
-
return new Response("Unauthorized", { status: 401 });
|
|
24
|
-
}
|
|
31
|
+
const denied = requireAdmin(cookies.get("setzkasten_session")?.value);
|
|
32
|
+
if (denied) return denied;
|
|
25
33
|
const tokenResult = await resolveGitHubTokenForRequest(request);
|
|
26
34
|
if (!tokenResult.ok) {
|
|
27
35
|
return new Response(tokenResult.error.message, { status: 500 });
|
|
@@ -31,7 +39,12 @@ var POST = async ({ request, cookies }) => {
|
|
|
31
39
|
const body = await request.json();
|
|
32
40
|
const storage = await resolveStorageConfigForRequest(request, body);
|
|
33
41
|
if (!storage) {
|
|
34
|
-
return Response.json(
|
|
42
|
+
return Response.json(
|
|
43
|
+
{
|
|
44
|
+
error: "Could not resolve owner/repo. Set SETZKASTEN_OWNER and SETZKASTEN_REPO env vars."
|
|
45
|
+
},
|
|
46
|
+
{ status: 400 }
|
|
47
|
+
);
|
|
35
48
|
}
|
|
36
49
|
const { owner, repo, branch, projectPrefix } = storage;
|
|
37
50
|
const serverConfig = globalThis.__SETZKASTEN_CONFIG__;
|
|
@@ -40,6 +53,12 @@ var POST = async ({ request, cookies }) => {
|
|
|
40
53
|
if (!section || !pageKey) {
|
|
41
54
|
return Response.json({ error: "section and pageKey are required" }, { status: 400 });
|
|
42
55
|
}
|
|
56
|
+
if (!isSafeKey(pageKey)) {
|
|
57
|
+
return Response.json({ error: "invalid pageKey" }, { status: 400 });
|
|
58
|
+
}
|
|
59
|
+
if (!isSafeKey(section.key)) {
|
|
60
|
+
return Response.json({ error: "invalid section key" }, { status: 400 });
|
|
61
|
+
}
|
|
43
62
|
const headers = {
|
|
44
63
|
Authorization: `Bearer ${githubToken}`,
|
|
45
64
|
Accept: "application/vnd.github+json",
|
|
@@ -50,13 +69,24 @@ var POST = async ({ request, cookies }) => {
|
|
|
50
69
|
const configPath = prefixPath("setzkasten.config.ts", projectPrefix);
|
|
51
70
|
const existingConfig = await fetchFileContent(owner, repo, branch, configPath, githubToken);
|
|
52
71
|
if (existingConfig) {
|
|
53
|
-
const updatedConfig = addSectionToConfig(
|
|
72
|
+
const updatedConfig = addSectionToConfig(
|
|
73
|
+
existingConfig,
|
|
74
|
+
section.key,
|
|
75
|
+
section,
|
|
76
|
+
section.allFields
|
|
77
|
+
);
|
|
54
78
|
if (updatedConfig) {
|
|
55
79
|
filesToCommit.push({ path: configPath, content: updatedConfig });
|
|
56
80
|
}
|
|
57
81
|
}
|
|
58
82
|
const sectionJsonPath = `${contentPath}/_sections/${section.key}.json`;
|
|
59
|
-
const existingSectionJson = await fetchFileContent(
|
|
83
|
+
const existingSectionJson = await fetchFileContent(
|
|
84
|
+
owner,
|
|
85
|
+
repo,
|
|
86
|
+
branch,
|
|
87
|
+
sectionJsonPath,
|
|
88
|
+
githubToken
|
|
89
|
+
);
|
|
60
90
|
let sectionData = {};
|
|
61
91
|
if (existingSectionJson) {
|
|
62
92
|
try {
|
|
@@ -89,7 +119,13 @@ var POST = async ({ request, cookies }) => {
|
|
|
89
119
|
});
|
|
90
120
|
const configKey = "_" + pageKey.replace(/\//g, "_");
|
|
91
121
|
const pageConfigPath = `${contentPath}/pages/${configKey}.json`;
|
|
92
|
-
const existingPageConfig = await fetchFileContent(
|
|
122
|
+
const existingPageConfig = await fetchFileContent(
|
|
123
|
+
owner,
|
|
124
|
+
repo,
|
|
125
|
+
branch,
|
|
126
|
+
pageConfigPath,
|
|
127
|
+
githubToken
|
|
128
|
+
);
|
|
93
129
|
let pageConfig;
|
|
94
130
|
if (existingPageConfig) {
|
|
95
131
|
pageConfig = JSON.parse(existingPageConfig);
|
|
@@ -163,7 +199,9 @@ import Page from '${importDepth}${relativePage}';
|
|
|
163
199
|
for (const g of repeatedGroups) {
|
|
164
200
|
const topField = fields.find((f) => f.key === g.fieldKey);
|
|
165
201
|
if (!topField || !Array.isArray(topField.defaultValue)) continue;
|
|
166
|
-
sectionData[g.fieldKey] = topField.defaultValue.filter(
|
|
202
|
+
sectionData[g.fieldKey] = topField.defaultValue.filter(
|
|
203
|
+
(item) => item != null
|
|
204
|
+
);
|
|
167
205
|
const jsonIdx = filesToCommit.findIndex((f) => f.path === sectionJsonPath);
|
|
168
206
|
if (jsonIdx !== -1) {
|
|
169
207
|
filesToCommit[jsonIdx].content = JSON.stringify(sectionData, null, 2);
|
|
@@ -171,10 +209,21 @@ import Page from '${importDepth}${relativePage}';
|
|
|
171
209
|
}
|
|
172
210
|
}
|
|
173
211
|
} else if (section.componentPath) {
|
|
174
|
-
const componentSource = await fetchFileContent(
|
|
212
|
+
const componentSource = await fetchFileContent(
|
|
213
|
+
owner,
|
|
214
|
+
repo,
|
|
215
|
+
branch,
|
|
216
|
+
section.componentPath,
|
|
217
|
+
githubToken
|
|
218
|
+
);
|
|
175
219
|
if (componentSource) {
|
|
176
220
|
const repeatedGroups = section._analyzerResult?.repeatedGroups ?? [];
|
|
177
|
-
const patchedSource = await patchTemplateForFields(
|
|
221
|
+
const patchedSource = await patchTemplateForFields(
|
|
222
|
+
componentSource,
|
|
223
|
+
section.key,
|
|
224
|
+
section.allFields ?? section.fields,
|
|
225
|
+
repeatedGroups
|
|
226
|
+
);
|
|
178
227
|
if (patchedSource !== componentSource) {
|
|
179
228
|
filesToCommit.push({ path: section.componentPath, content: patchedSource });
|
|
180
229
|
}
|
|
@@ -182,7 +231,9 @@ import Page from '${importDepth}${relativePage}';
|
|
|
182
231
|
for (const g of repeatedGroups) {
|
|
183
232
|
const topField = fields.find((f) => f.key === g.fieldKey);
|
|
184
233
|
if (!topField || !Array.isArray(topField.defaultValue)) continue;
|
|
185
|
-
const items = topField.defaultValue.filter(
|
|
234
|
+
const items = topField.defaultValue.filter(
|
|
235
|
+
(item) => item != null
|
|
236
|
+
);
|
|
186
237
|
sectionData[g.fieldKey] = items;
|
|
187
238
|
const jsonIdx = filesToCommit.findIndex((f) => f.path === sectionJsonPath);
|
|
188
239
|
if (jsonIdx !== -1) {
|
|
@@ -195,7 +246,13 @@ import Page from '${importDepth}${relativePage}';
|
|
|
195
246
|
const sectionDir = section.componentPath.replace(/\/[^/]+$/, "");
|
|
196
247
|
const resolvedChildPath = resolveRelativePath(sectionDir, child.importPath);
|
|
197
248
|
if (!resolvedChildPath) continue;
|
|
198
|
-
const childSource = await fetchFileContent(
|
|
249
|
+
const childSource = await fetchFileContent(
|
|
250
|
+
owner,
|
|
251
|
+
repo,
|
|
252
|
+
branch,
|
|
253
|
+
resolvedChildPath,
|
|
254
|
+
githubToken
|
|
255
|
+
);
|
|
199
256
|
if (!childSource) continue;
|
|
200
257
|
const patchedChild = patchChildComponentForFieldPrefix(childSource, child.innerFields);
|
|
201
258
|
if (patchedChild !== childSource) {
|
|
@@ -207,7 +264,13 @@ import Page from '${importDepth}${relativePage}';
|
|
|
207
264
|
const fullPagePath = prefixPath(body.pagePath, projectPrefix);
|
|
208
265
|
const pageSource = await fetchFileContent(owner, repo, branch, fullPagePath, githubToken);
|
|
209
266
|
if (pageSource) {
|
|
210
|
-
const patched = patchPageFile(
|
|
267
|
+
const patched = patchPageFile(
|
|
268
|
+
pageSource,
|
|
269
|
+
section.key,
|
|
270
|
+
section.componentName,
|
|
271
|
+
section.componentPath,
|
|
272
|
+
body.pagePath
|
|
273
|
+
);
|
|
211
274
|
if (patched && patched !== pageSource) {
|
|
212
275
|
filesToCommit.push({ path: fullPagePath, content: patched });
|
|
213
276
|
}
|
|
@@ -216,7 +279,13 @@ import Page from '${importDepth}${relativePage}';
|
|
|
216
279
|
const previewPath = prefixPath(`${pageDir}/sk-preview/[...page].astro`, projectPrefix);
|
|
217
280
|
const previewSource = await fetchFileContent(owner, repo, branch, previewPath, githubToken);
|
|
218
281
|
if (previewSource) {
|
|
219
|
-
const patchedPreview = patchPageFile(
|
|
282
|
+
const patchedPreview = patchPageFile(
|
|
283
|
+
previewSource,
|
|
284
|
+
section.key,
|
|
285
|
+
section.componentName,
|
|
286
|
+
section.componentPath,
|
|
287
|
+
`${pageDir}/sk-preview/[...page].astro`
|
|
288
|
+
);
|
|
220
289
|
if (patchedPreview && patchedPreview !== previewSource) {
|
|
221
290
|
filesToCommit.push({ path: previewPath, content: patchedPreview });
|
|
222
291
|
}
|
|
@@ -231,7 +300,9 @@ import Page from '${importDepth}${relativePage}';
|
|
|
231
300
|
repo,
|
|
232
301
|
branch,
|
|
233
302
|
filesToCommit,
|
|
234
|
-
withTrailers(
|
|
303
|
+
withTrailers(
|
|
304
|
+
existingSectionJson ? `content: update ${section.key} section \u2014 add new fields` : `content: add ${section.key} section to Setzkasten`
|
|
305
|
+
),
|
|
235
306
|
headers
|
|
236
307
|
);
|
|
237
308
|
if (!commitResult.ok) {
|
|
@@ -379,37 +450,32 @@ async function batchCommit(owner, repo, branch, files, message, headers) {
|
|
|
379
450
|
);
|
|
380
451
|
if (!commitRes.ok) return { ok: false, error: `Failed to get commit: ${commitRes.status}` };
|
|
381
452
|
const commitData = await commitRes.json();
|
|
382
|
-
const treeRes = await fetch(
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
})
|
|
396
|
-
}
|
|
397
|
-
);
|
|
453
|
+
const treeRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/git/trees`, {
|
|
454
|
+
method: "POST",
|
|
455
|
+
headers,
|
|
456
|
+
body: JSON.stringify({
|
|
457
|
+
base_tree: commitData.tree.sha,
|
|
458
|
+
tree: files.map((f) => ({
|
|
459
|
+
path: f.path,
|
|
460
|
+
mode: "100644",
|
|
461
|
+
type: "blob",
|
|
462
|
+
content: f.content
|
|
463
|
+
}))
|
|
464
|
+
})
|
|
465
|
+
});
|
|
398
466
|
if (!treeRes.ok) return { ok: false, error: `Failed to create tree: ${treeRes.status}` };
|
|
399
467
|
const treeData = await treeRes.json();
|
|
400
|
-
const newCommitRes = await fetch(
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
}
|
|
411
|
-
);
|
|
412
|
-
if (!newCommitRes.ok) return { ok: false, error: `Failed to create commit: ${newCommitRes.status}` };
|
|
468
|
+
const newCommitRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/git/commits`, {
|
|
469
|
+
method: "POST",
|
|
470
|
+
headers,
|
|
471
|
+
body: JSON.stringify({
|
|
472
|
+
tree: treeData.sha,
|
|
473
|
+
parents: [headSha],
|
|
474
|
+
message
|
|
475
|
+
})
|
|
476
|
+
});
|
|
477
|
+
if (!newCommitRes.ok)
|
|
478
|
+
return { ok: false, error: `Failed to create commit: ${newCommitRes.status}` };
|
|
413
479
|
const newCommitData = await newCommitRes.json();
|
|
414
480
|
const updateRes = await fetch(
|
|
415
481
|
`https://api.github.com/repos/${owner}/${repo}/git/refs/heads/${branch}`,
|