Add page management system: shim layer + API routes for pages/posts/sites CRUD

This commit is contained in:
cawcenter
2025-12-16 12:14:08 -05:00
parent 8fcd5353c7
commit 35632f87b8
10 changed files with 859 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
// API: Update/Delete page by ID
import type { APIRoute } from 'astro';
import { updatePage, deletePage, getPageById } from '@/lib/shim/pages';
export const GET: APIRoute = async ({ params, request }) => {
try {
const authHeader = request.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const godToken = import.meta.env.GOD_MODE_TOKEN;
if (godToken && token !== godToken) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 });
}
const page = await getPageById(params.id!);
if (!page) {
return new Response(JSON.stringify({ error: 'Page not found' }), { status: 404 });
}
return new Response(JSON.stringify(page), { status: 200 });
} catch (error: any) {
return new Response(JSON.stringify({ error: error.message }), { status: 500 });
}
};
export const PUT: APIRoute = async ({ params, request }) => {
try {
const authHeader = request.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const godToken = import.meta.env.GOD_MODE_TOKEN;
if (godToken && token !== godToken) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
}
const data = await request.json();
const page = await updatePage(params.id!, data);
return new Response(JSON.stringify(page), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
} catch (error: any) {
return new Response(JSON.stringify({
error: 'Failed to update page',
message: error.message
}), {
status: 400,
headers: { 'Content-Type': 'application/json' }
});
}
};
export const DELETE: APIRoute = async ({ params, request }) => {
try {
const authHeader = request.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const godToken = import.meta.env.GOD_MODE_TOKEN;
if (godToken && token !== godToken) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
}
const success = await deletePage(params.id!);
if (!success) {
return new Response(JSON.stringify({ error: 'Page not found' }), { status: 404 });
}
return new Response(JSON.stringify({ success: true }), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
} catch (error: any) {
return new Response(JSON.stringify({
error: 'Failed to delete page',
message: error.message
}), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
};

View File

@@ -0,0 +1,37 @@
// API: Create new page
import type { APIRoute } from 'astro';
import { createPage } from '@/lib/shim/pages';
export const POST: APIRoute = async ({ request }) => {
try {
// Token validation
const authHeader = request.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const godToken = import.meta.env.GOD_MODE_TOKEN;
if (godToken && token !== godToken) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
}
const data = await request.json();
const page = await createPage(data);
return new Response(JSON.stringify(page), {
status: 201,
headers: { 'Content-Type': 'application/json' }
});
} catch (error: any) {
console.error('Create page error:', error);
return new Response(JSON.stringify({
error: 'Failed to create page',
message: error.message
}), {
status: 400,
headers: { 'Content-Type': 'application/json' }
});
}
};

View File

@@ -0,0 +1,44 @@
// API: List pages with filtering
import type { APIRoute } from 'astro';
import { getPages } from '@/lib/shim/pages';
export const GET: APIRoute = async ({ request }) => {
try {
// Token validation
const authHeader = request.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const godToken = import.meta.env.GOD_MODE_TOKEN;
if (godToken && token !== godToken) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
}
// Parse query parameters
const url = new URL(request.url);
const limit = parseInt(url.searchParams.get('limit') || '50');
const offset = parseInt(url.searchParams.get('offset') || '0');
const status = url.searchParams.get('status') || undefined;
const siteId = url.searchParams.get('siteId') || undefined;
const search = url.searchParams.get('search') || undefined;
const result = await getPages({ limit, offset, status, siteId, search });
return new Response(JSON.stringify(result), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
} catch (error: any) {
console.error('Pages list error:', error);
return new Response(JSON.stringify({
error: 'Failed to fetch pages',
message: error.message
}), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
};

View File

@@ -0,0 +1,92 @@
// API: Update/Delete post by ID
import type { APIRoute } from 'astro';
import { updatePost, deletePost, getPostById } from '@/lib/shim/posts';
export const GET: APIRoute = async ({ params, request }) => {
try {
const authHeader = request.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const godToken = import.meta.env.GOD_MODE_TOKEN;
if (godToken && token !== godToken) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 });
}
const post = await getPostById(params.id!);
if (!post) {
return new Response(JSON.stringify({ error: 'Post not found' }), { status: 404 });
}
return new Response(JSON.stringify(post), { status: 200 });
} catch (error: any) {
return new Response(JSON.stringify({ error: error.message }), { status: 500 });
}
};
export const PUT: APIRoute = async ({ params, request }) => {
try {
const authHeader = request.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const godToken = import.meta.env.GOD_MODE_TOKEN;
if (godToken && token !== godToken) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
}
const data = await request.json();
const post = await updatePost(params.id!, data);
return new Response(JSON.stringify(post), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
} catch (error: any) {
return new Response(JSON.stringify({
error: 'Failed to update post',
message: error.message
}), {
status: 400,
headers: { 'Content-Type': 'application/json' }
});
}
};
export const DELETE: APIRoute = async ({ params, request }) => {
try {
const authHeader = request.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const godToken = import.meta.env.GOD_MODE_TOKEN;
if (godToken && token !== godToken) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
}
const success = await deletePost(params.id!);
if (!success) {
return new Response(JSON.stringify({ error: 'Post not found' }), { status: 404 });
}
return new Response(JSON.stringify({ success: true }), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
} catch (error: any) {
return new Response(JSON.stringify({
error: 'Failed to delete post',
message: error.message
}), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
};

View File

@@ -0,0 +1,37 @@
// API: Create new post
import type { APIRoute } from 'astro';
import { createPost } from '@/lib/shim/posts';
export const POST: APIRoute = async ({ request }) => {
try {
// Token validation
const authHeader = request.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const godToken = import.meta.env.GOD_MODE_TOKEN;
if (godToken && token !== godToken) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
}
const data = await request.json();
const post = await createPost(data);
return new Response(JSON.stringify(post), {
status: 201,
headers: { 'Content-Type': 'application/json' }
});
} catch (error: any) {
console.error('Create post error:', error);
return new Response(JSON.stringify({
error: 'Failed to create post',
message: error.message
}), {
status: 400,
headers: { 'Content-Type': 'application/json' }
});
}
};

View File

@@ -0,0 +1,44 @@
// API: List posts with filtering
import type { APIRoute } from 'astro';
import { getPosts } from '@/lib/shim/posts';
export const GET: APIRoute = async ({ request }) => {
try {
// Token validation
const authHeader = request.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const godToken = import.meta.env.GOD_MODE_TOKEN;
if (godToken && token !== godToken) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
}
// Parse query parameters
const url = new URL(request.url);
const limit = parseInt(url.searchParams.get('limit') || '50');
const offset = parseInt(url.searchParams.get('offset') || '0');
const status = url.searchParams.get('status') || undefined;
const siteId = url.searchParams.get('siteId') || undefined;
const search = url.searchParams.get('search') || undefined;
const result = await getPosts({ limit, offset, status, siteId, search });
return new Response(JSON.stringify(result), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
} catch (error: any) {
console.error('Posts list error:', error);
return new Response(JSON.stringify({
error: 'Failed to fetch posts',
message: error.message
}), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
};

View File

@@ -0,0 +1,35 @@
// API: Update site by ID
import type { APIRoute } from 'astro';
import { updateSite } from '@/lib/shim/sites';
export const PUT: APIRoute = async ({ params, request }) => {
try {
const authHeader = request.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const godToken = import.meta.env.GOD_MODE_TOKEN;
if (godToken && token !== godToken) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
}
const data = await request.json();
const site = await updateSite(params.id!, data);
return new Response(JSON.stringify(site), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
} catch (error: any) {
return new Response(JSON.stringify({
error: 'Failed to update site',
message: error.message
}), {
status: 400,
headers: { 'Content-Type': 'application/json' }
});
}
};