feat(10-01): serve the embedded admin SPA at backend.uri with cookie login
- backend.uri prefix (default /backend) mounts the admin API at {prefix}/api/v1
and the embedded SPA shell at {prefix} with an api/ JSON 404 fallback
- cookie transport: an X-Requested-With login sets the HttpOnly summer_admin
cookie and returns no token; the backend guard reads the cookie after Bearer
- CSRF wrapper refuses cookie-only POST/PUT/DELETE without X-Requested-With
- boardwalk package embeds boardwalk/dist, rewrites index.html once per prefix
and sets cache and security headers
- framework admin OpenAPI pipeline (swag, swagger2openapi, openapi-typescript)
with prefix-relative paths and typed envelopes for the tracer routes
- admin/ Vite SPA: login, plugin rail, section panel and read-only list
through the openapi-fetch client typed by the generated schema
This commit is contained in:
23
admin/src/app/runtime.ts
Normal file
23
admin/src/app/runtime.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
// Runtime configuration read once from the served index.html. The Go server
|
||||
// (boardwalk) writes the configured backend.uri into the summer-admin-base
|
||||
// meta; the SPA derives its router base and API base from it (D-02, D-03).
|
||||
export const DEFAULT_BASE = '/backend'
|
||||
const TOKEN = '__SUMMER_ADMIN_BASE__'
|
||||
|
||||
export function readBase(doc: Document = document): string {
|
||||
const content = doc.querySelector<HTMLMetaElement>('meta[name="summer-admin-base"]')?.content.trim() ?? ''
|
||||
if (content === '' || content === TOKEN || !content.startsWith('/')) {
|
||||
return DEFAULT_BASE
|
||||
}
|
||||
const trimmed = content.replace(/\/+$/, '')
|
||||
return trimmed === '' ? DEFAULT_BASE : trimmed
|
||||
}
|
||||
|
||||
const base = readBase()
|
||||
|
||||
export const runtime = {
|
||||
/** Admin mount path, for example /backend. */
|
||||
base,
|
||||
/** Admin API root, the mount path plus /api/v1. */
|
||||
api: `${base}/api/v1`,
|
||||
} as const
|
||||
Reference in New Issue
Block a user