Add runtime storage and API/server wiring updates
This commit is contained in:
parent
56803bd7b2
commit
a2ce927d66
3 changed files with 117 additions and 6 deletions
|
|
@ -1,4 +1,5 @@
|
|||
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8080';
|
||||
// All API calls go through the server route gateway proxy
|
||||
const API_GATEWAY = '/api/gateway';
|
||||
|
||||
export type RuntimeRecordType = 'role' | 'dashboard' | 'onboarding';
|
||||
export type RuntimeRecordStatus = 'draft' | 'published';
|
||||
|
|
@ -28,12 +29,12 @@ export async function saveRuntimeConfig(type: RuntimeRecordType, key: string, pa
|
|||
try {
|
||||
// 1. Ensure the Role exists first. We lookup by key.
|
||||
// If it doesn't exist, we create it generically.
|
||||
let roleRes = await fetch(`${API_URL}/api/admin/roles/${normalizedKey}`);
|
||||
let roleRes = await fetch(`${API_GATEWAY}/api/admin/roles/${normalizedKey}`);
|
||||
let role: RoleRecord;
|
||||
|
||||
if (!roleRes.ok && roleRes.status === 404) {
|
||||
// Create it
|
||||
const createRes = await fetch(`${API_URL}/api/admin/roles`, {
|
||||
const createRes = await fetch(`${API_GATEWAY}/api/admin/roles`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
|
|
@ -68,7 +69,7 @@ export async function saveRuntimeConfig(type: RuntimeRecordType, key: string, pa
|
|||
bodyPayload.config_json = payload;
|
||||
}
|
||||
|
||||
const saveRes = await fetch(`${API_URL}${endpointMap[type]}`, {
|
||||
const saveRes = await fetch(`${API_GATEWAY}${endpointMap[type]}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(bodyPayload)
|
||||
|
|
@ -93,7 +94,7 @@ export async function listRuntimeConfigs<T>(type: RuntimeRecordType): Promise<Ar
|
|||
};
|
||||
|
||||
try {
|
||||
const res = await fetch(`${API_URL}${endpointMap[type]}`);
|
||||
const res = await fetch(`${API_GATEWAY}${endpointMap[type]}`);
|
||||
if (!res.ok) throw new Error(`Failed to list ${type} configs`);
|
||||
const data = await res.json();
|
||||
|
||||
|
|
@ -121,7 +122,7 @@ export async function getRuntimeConfig<T>(type: RuntimeRecordType, roleId: strin
|
|||
};
|
||||
|
||||
try {
|
||||
const res = await fetch(`${API_URL}${endpointMap[type]}`);
|
||||
const res = await fetch(`${API_GATEWAY}${endpointMap[type]}`);
|
||||
if (!res.ok) return null;
|
||||
const data = await res.json();
|
||||
|
||||
|
|
|
|||
34
src/lib/server/gateway.ts
Normal file
34
src/lib/server/gateway.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// Server-side helper: all backend calls go through the Rust gateway
|
||||
const GATEWAY_URL = (process.env.GATEWAY_URL || 'http://localhost:8000').replace(/\/+$/, '');
|
||||
|
||||
export function gatewayUrl(path: string): string {
|
||||
const normalized = path.startsWith('/') ? path : `/${path}`;
|
||||
return `${GATEWAY_URL}${normalized}`;
|
||||
}
|
||||
|
||||
/** Forward the Authorization header from an incoming browser request to the gateway */
|
||||
export function forwardAuth(request: Request): Record<string, string> {
|
||||
const auth = request.headers.get('Authorization');
|
||||
return auth ? { Authorization: auth } : {};
|
||||
}
|
||||
|
||||
/** Forward the Cookie header from an incoming browser request to the gateway */
|
||||
export function forwardCookies(request: Request): Record<string, string> {
|
||||
const cookie = request.headers.get('cookie');
|
||||
return cookie ? { cookie } : {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge auth + cookie headers from the incoming request with any extra headers provided.
|
||||
*/
|
||||
export function withAuthHeaders(
|
||||
request: Request,
|
||||
extra: Record<string, string> = {},
|
||||
): Record<string, string> {
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
...forwardAuth(request),
|
||||
...forwardCookies(request),
|
||||
...extra,
|
||||
};
|
||||
}
|
||||
76
src/routes/api/gateway/[...path].ts
Normal file
76
src/routes/api/gateway/[...path].ts
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
import { gatewayUrl, withAuthHeaders } from '~/lib/server/gateway';
|
||||
|
||||
/**
|
||||
* Generic gateway proxy endpoint for admin panel
|
||||
* Forwards all requests to the Rust backend gateway with proper auth headers
|
||||
*/
|
||||
export async function GET({ request, params }: { request: Request; params: any }) {
|
||||
return proxyRequest('GET', request, params);
|
||||
}
|
||||
|
||||
export async function POST({ request, params }: { request: Request; params: any }) {
|
||||
return proxyRequest('POST', request, params);
|
||||
}
|
||||
|
||||
export async function PUT({ request, params }: { request: Request; params: any }) {
|
||||
return proxyRequest('PUT', request, params);
|
||||
}
|
||||
|
||||
export async function DELETE({ request, params }: { request: Request; params: any }) {
|
||||
return proxyRequest('DELETE', request, params);
|
||||
}
|
||||
|
||||
export async function PATCH({ request, params }: { request: Request; params: any }) {
|
||||
return proxyRequest('PATCH', request, params);
|
||||
}
|
||||
|
||||
async function proxyRequest(method: string, request: Request, params: any) {
|
||||
try {
|
||||
// Handle different param structures
|
||||
let pathArray = params.path;
|
||||
if (!Array.isArray(pathArray)) {
|
||||
pathArray = [pathArray];
|
||||
}
|
||||
|
||||
const path = `/${pathArray.join('/')}`;
|
||||
const url = new URL(request.url);
|
||||
const queryString = url.search ? url.search : '';
|
||||
|
||||
let body: string | undefined;
|
||||
if (['POST', 'PUT', 'PATCH'].includes(method)) {
|
||||
body = await request.text();
|
||||
}
|
||||
|
||||
const upstreamUrl = gatewayUrl(path + queryString);
|
||||
const upstreamRequest = new Request(upstreamUrl, {
|
||||
method,
|
||||
headers: withAuthHeaders(request, {
|
||||
'Content-Type': request.headers.get('Content-Type') || 'application/json',
|
||||
}),
|
||||
body,
|
||||
cache: 'no-store',
|
||||
});
|
||||
|
||||
const response = await fetch(upstreamRequest);
|
||||
const responseHeaders = new Headers();
|
||||
response.headers.forEach((value, key) => {
|
||||
if (!['server', 'transfer-encoding', 'connection'].includes(key.toLowerCase())) {
|
||||
responseHeaders.set(key, value);
|
||||
}
|
||||
});
|
||||
responseHeaders.set('Content-Type', 'application/json');
|
||||
|
||||
const responseBody = await response.text();
|
||||
|
||||
return new Response(responseBody, {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
headers: responseHeaders,
|
||||
});
|
||||
} catch (error: any) {
|
||||
return new Response(
|
||||
JSON.stringify({ success: false, error: error?.message || 'Internal Server Error' }),
|
||||
{ status: 500, headers: { 'Content-Type': 'application/json' } },
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue