Expand description
umbral gen-client — a typed client generated from the REST surface
(gaps3 #38 / Kikosi #1).
umbral typegen gives a frontend the shapes. This gives it the client:
new Umbral(url).from("post").filter({ status: "published" }).list(), where
the filter object autocompletes to exactly this model’s filterable fields and
their value types — because the same model registry that renders the OpenAPI
document knows every column’s type, choices, FK target, and which lookups
(__gte, __in, __contains, __isnull) the REST list endpoint accepts.
§Two files, one runtime
client.js— a single-file, dependency-free ES module:Umbral,Query,UmbralError. Usable straight from a<script type="module">with no build step, and by any bundler.client.d.ts— every type: row interfaces, choice unions, per-modelFilters/Ordering/Create/Update, the paginator’s envelope, and the class declarations.
There is no .ts runtime: TypeScript’s types erase, so the row/filter
types produce no JavaScript at all. Emitting .js + .d.ts means the
runtime exists exactly once (no bundler, no transpile step, no second copy to
keep in step), while import { Umbral } from "./api/client" still type-checks
fully — TS resolves the .d.ts for types and the bundler resolves the .js
for code. It’s the shape every published SDK ships.
§Realtime is delegated, not reimplemented
Umbral.on(...) does NOT open its own EventSource. It loads the realtime
plugin’s already-served {realtimePath}/client.js and calls
umbral.realtime.model(...), inheriting the hard parts: ONE SSE connection
shared across every tab via SharedWorker (union-routed), presence, and
graceful degradation. A per-subscription EventSource would open one
connection per model — six subscriptions exhausts the browser’s per-origin
connection cap.
It reads the live registry + umbral-rest’s per-resource config
(filters_enabled_for, is_hidden, registered_base_path,
registered_pagination_style, registered_pagination_schema,
registered_security_schemes), which are populated when the plugins’ routes
are built — so gen-client runs as an offline CLI step with no server and no
database, and reflects the exact surface the app serves.
Structs§
- Generated
Client - The generated client: one runtime module + one declaration file.
Functions§
- generate
- Generate the client from the live registry + REST config.
- generate_
for generateover an explicit model list.allis every model the app knows (used to resolve FK value types); the REST-exposed subset is what gets emitted, decided byumbral_rest::is_exposed.- generate_
with generate_forwith the REST config passed explicitly rather than read from umbral-rest’sOnceLocks — the base path, the paginator’sPaginationStyleand (for a custom paginator) its declaredPaginationSchema, and the OpenAPI security schemes that drive the client’s auth. Exposure / hidden / filters-enabled are still read from the (gracefully-defaulting) readers.