@morphika/andami 0.2.8 → 0.2.10

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.
@@ -0,0 +1,35 @@
1
+ import { NextResponse } from "next/server";
2
+ import { isAdminAuthenticated } from "../../../../../lib/auth";
3
+ import { jsonError } from "../../../../../lib/security";
4
+ import { getBackupStatus } from "../../../../../lib/backup/export";
5
+ import { logger } from "../../../../../lib/logger";
6
+
7
+ /**
8
+ * GET /api/admin/backups/status — Backup readiness check.
9
+ *
10
+ * Returns:
11
+ * - R2 connection status
12
+ * - Asset count and total size
13
+ * - Sanity document counts by type
14
+ *
15
+ * Used by the admin Backups page to show what will be included
16
+ * in the backup before the user clicks "Create Backup".
17
+ *
18
+ * Auth required. No CSRF (GET request).
19
+ */
20
+ export async function GET() {
21
+ if (!(await isAdminAuthenticated())) {
22
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
23
+ }
24
+
25
+ try {
26
+ const status = await getBackupStatus();
27
+ return NextResponse.json(status);
28
+ } catch (err) {
29
+ logger.error("[Admin:Backup]", "Status check failed", err);
30
+ return jsonError(
31
+ err instanceof Error ? err.message : "Status check failed",
32
+ 500
33
+ );
34
+ }
35
+ }
@@ -1,15 +1,20 @@
1
1
  import { NextRequest, NextResponse } from "next/server";
2
- import { client } from "../../../../lib/sanity/client";
2
+ import { adminClient } from "../../../../lib/sanity/client";
3
3
  import { customSectionByIdQuery } from "../../../../lib/sanity/queries";
4
4
  import { logger } from "../../../../lib/logger";
5
5
 
6
6
  type RouteContext = { params: Promise<{ id: string }> };
7
7
 
8
8
  /**
9
- * GET /api/custom-sections/[id] — Public: section data only (cached 1h CDN)
9
+ * GET /api/custom-sections/[id] — Public: section data only
10
10
  *
11
11
  * Returns only the `section` field (PageSectionV2 data) for rendering
12
12
  * custom section instances on the public site.
13
+ *
14
+ * Uses adminClient (useCdn: false) so data is always fresh after
15
+ * revalidatePath() is called from the admin PATCH endpoint.
16
+ * Cache is controlled via ISR revalidation on-demand, not via
17
+ * Cache-Control headers — this avoids stale CDN responses after edits.
13
18
  */
14
19
  export async function GET(_request: NextRequest, context: RouteContext) {
15
20
  try {
@@ -19,7 +24,7 @@ export async function GET(_request: NextRequest, context: RouteContext) {
19
24
  return NextResponse.json({ error: "Missing section ID" }, { status: 400 });
20
25
  }
21
26
 
22
- const result = await client.fetch(customSectionByIdQuery, { id });
27
+ const result = await adminClient.fetch(customSectionByIdQuery, { id });
23
28
  if (!result?.section) {
24
29
  return NextResponse.json({ error: "Custom section not found" }, { status: 404 });
25
30
  }
@@ -28,8 +33,7 @@ export async function GET(_request: NextRequest, context: RouteContext) {
28
33
  { section: result.section },
29
34
  {
30
35
  headers: {
31
- "Cache-Control": "public, s-maxage=3600, stale-while-revalidate=1800",
32
- "CDN-Cache-Control": "public, s-maxage=3600",
36
+ "Cache-Control": "public, s-maxage=60, stale-while-revalidate=30",
33
37
  },
34
38
  }
35
39
  );