@s3p/server-ui
v0.2.0
Published
The auto-generated /server admin console for an s3p project (object browser, users, roles, secrets, email, functions).
Readme
@s3p/server-ui
Framework-agnostic UI for a project's /server route (the
operator-facing admin console of an S3-Native App Platform project).
Embeds into any host page (Vue, React, Svelte, vanilla HTML) via a
web component or a programmatic mount API. See
../../RUNTIME.md for the design.
s3p dev and s3p build auto-mount this package at /server/ for
any project that has an s3p.config.json and hasn't shipped its
own /server/index.html. You normally don't import it directly —
the CLI wires it up for you.
Cards (today)
Rendered in this order when the host passes a project and the
matching SDK facade:
| Card | Always shown | Requires |
|---|---|---|
| Identity | yes | active STS session — surfaces sub, role, raw claims |
| Project | when project is passed | s3p.config.json |
| Users | when platform.users set | app.users (Cognito User Pool admin perms) |
| Roles | when platform.roleAdmin set | app.roleAdmin (IAM + Identity Pool perms) |
| Database | when project set | nothing extra — uses S3 client |
| Scratchpad | when project set | nothing extra — REPL over app.* |
| Functions | when project set | server runtime registered handlers |
| Object browser | yes | S3 client + bucket name |
| Secrets | when project set | lists ciphertext only; decrypting needs server-role KMS perms |
| Inbox / Outputs | yes | S3 client — lists data/inbox/* and data/outputs/* |
| Body inspector | yes | populated by selection in browser or outputs |
All S3 calls go through the caller-supplied app.getS3Client() so
the panel shares the host's STS session and credential refresh path
— no second OIDC dance.
The panel uses refresh buttons everywhere (no auto-poll) so the UI doesn't churn while operators are typing.
Usage
Web component (drop-in HTML)
<script type="module">
import { connect } from "@s3p/sdk";
import "@s3p/server-ui"; // side-effect: defines <s3p-server-ui>
const app = await connect();
if (!app.signedIn) { app.signIn(); throw new Error("redirecting"); }
const el = document.querySelector("s3p-server-ui");
el.platform = app; // pass the configured SDK client
el.project = app.project; // optional — enables Project/Users/Roles/etc cards
</script>
<s3p-server-ui></s3p-server-ui>Programmatic mount
import { mountServerUi } from "@s3p/server-ui";
const unmount = mountServerUi(document.getElementById("server-root"), {
platform: app, // anything that exposes getS3Client()
defaultBucket: app.bucket,
defaultPrefix: "data/",
project: app.project, // optional — enables Project + Secrets cards
});
// later
unmount();Host shape
interface ServerUiHost {
getS3Client(): Promise<S3Client>;
getClaims?: () => { sub?, role?, preferred_username? } | null;
users?: UsersFacade; // enables Users card
roleAdmin?: RolesFacade; // enables Roles card
}The PlatformClient returned by @s3p/sdk matches this
shape; any equivalent object works.
Style isolation
The web component attaches a shadow root, so the panel's CSS doesn't leak into the host page and vice versa. Safe to drop into any layout.
Internals are vanilla TypeScript + DOM — no framework dependency, embedders pay nothing for it.
Dev loop
From the workspace root:
npm run build --workspace=@s3p/server-ui
npm test --workspace=@s3p/server-ui
npm run typecheck --workspace=@s3p/server-ui
npm run lint --workspace=@s3p/server-uiTests
Vitest covers:
- Database card classifier (collection / log / doc detection from storage layout).
- Scratchpad eval loop (REPL invariants, output formatting).
