15#include "../core/backend.hpp"
16#include "../core/bridge.hpp"
17#include "../core/executor.hpp"
19#include "../session/session.hpp"
35namespace morph::client {
50 std::function<std::expected<std::shared_ptr<ui::ServedBundle const>,
ui::Refusal>()>
bundle;
86 [[nodiscard]] std::vector<std::string>
screens()
const;
91 [[nodiscard]]
bool isPublic(std::string_view screenId)
const;
96 void open(
ui::AppContext& context, std::function<
void(std::expected<ui::Bundle, ui::ConnectError>)> ready)
final;
112 void signIn(std::
string principal, std::
string token, std::function<
void(
bool)> done);
125 [[nodiscard]] std::function<std::shared_ptr<ui::Document const>(std::string_view)>
documents(
126 std::function<
void(ui::Refusal const&)> onRefused = {});
130 [[nodiscard]]
ui::Bundle const*
bundle() const noexcept {
return _loaded ? &_loaded->bundle :
nullptr; }
135 return _loaded ? &_loaded->catalog :
nullptr;
145 [[nodiscard]] std::string
const&
principal() const noexcept {
return _session.principal; }
150 [[nodiscard]] std::optional<ui::FileTransfer>
files()
const;
156 void poll(std::function<
void(std::vector<std::string> changed)> changed);
182 std::unique_ptr<backend::detail::IBackend>
backend;
197 [[nodiscard]]
virtual std::chrono::milliseconds
openTimeout()
const {
return std::chrono::milliseconds{0}; }
207 std::function<
void(std::expected<std::string, std::string>)> done);
215 struct LoadedDocument {
217 std::uint64_t catalogLoad = 0;
218 std::shared_ptr<ui::Document const> document;
220 std::map<std::string, LoadedDocument, std::less<>> _documents;
222 std::uint64_t _catalogLoads = 0;
224 std::shared_ptr<bool> _alive;
225 std::unique_ptr<bridge::Bridge> _bridge;
226 std::unique_ptr<ui::BridgeDispatcher> _dispatcher;
228 std::unique_ptr<ui::QueueingDispatcher> _queue;
230 std::optional<reactive::TimerHandle> _replay;
233 bool _serverEvents =
false;
235 std::vector<std::function<void()>> _connectListeners;
236 std::vector<std::function<void(
wire::EventBody const&)>> _eventListeners;
240 void loadSchemas(std::shared_ptr<bool>
const& alive, std::function<
void()> done);
242 [[nodiscard]] std::vector<std::string> modelTypes()
const;
244 void recordSchemas(std::string
const& document);
246 std::map<std::string, std::string, std::less<>> _schemas;
249 std::optional<ui::LoadedBundle> _loaded;
252 struct CurrentCatalog {
254 std::map<std::string, std::string, std::less<>> schemas;
256 std::shared_ptr<CurrentCatalog> _current = std::make_shared<CurrentCatalog>();
258 std::shared_ptr<ui::IBundleStore> _store;
260 void reload(std::shared_ptr<bool>
const& alive, std::function<
void(std::expected<void, ui::ConnectError>)> done);
261 reactive::TimerHandle _timeout;
263 bool _polling =
false;
272 explicit RemoteSource(std::string url, std::chrono::milliseconds timeout = std::chrono::seconds{10});
276 [[nodiscard]] std::chrono::milliseconds
openTimeout()
const override {
return _timeout; }
280 std::chrono::milliseconds _timeout;
305 std::function<
void(std::expected<std::string, std::string>)> done)
override;
311 std::unique_ptr<exec::ThreadPoolExecutor> _workers;
312 std::shared_ptr<ui::UiService> _service;
319[[nodiscard]] std::expected<std::unique_ptr<Source>, std::string>
makeSource(
Args const& args,
320 std::vector<LocalApp>
const& apps);
The generic client's command line: which source it opens and how it starts. Spec 4 §3.
std::string signedOutPrincipal() const override
The development user, from --user.
std::expected< Transport, ui::ConnectError > connect(ui::AppContext &context) override
Makes the transport on context.
LocalSource(LocalApp app, LocalSetup setup)
A source for app.
void fetchSchemas(std::string const &modelType, std::function< void(std::expected< std::string, std::string >)> done) override
Fetches the {actionType: schema} document of one model type, which a form, collection or wizard node ...
void disconnect() override
Releases what connect made beside the backend; called by close, after the bridge is gone.
std::expected< Transport, ui::ConnectError > connect(ui::AppContext &context) override
Makes the transport on context.
std::chrono::milliseconds openTimeout() const override
How long open waits for the bundle before it reports the source unreachable; zero waits forever.
RemoteSource(std::string url, std::chrono::milliseconds timeout=std::chrono::seconds{10})
A source for url.
An AppSource that also hands the shell what it mounts screens with, once it delivered a bundle.
virtual void fetchSchemas(std::string const &modelType, std::function< void(std::expected< std::string, std::string >)> done)
Fetches the {actionType: schema} document of one model type, which a form, collection or wizard node ...
bool isPublic(std::string_view screenId) const
Whether the catalog marks screenId public: a screen served before sign-in, such as a login screen.
std::optional< ui::FileTransfer > files() const
The file side channel (files/1) over the source's exchange, carrying its session: what a screen's upl...
ui::Catalog catalog() const
The catalog facts the screens load with.
std::function< std::shared_ptr< ui::Document const >(std::string_view)> documents(std::function< void(ui::Refusal const &)> onRefused={})
The lookup a DocumentScreenHost takes (DocumentScreenHostOptions::documents), over the loaded bundle:...
void onConnected(std::function< void()> const &listener) final
Adds a listener called on the owner after each successful connect, the first included....
std::vector< std::string > screens() const
The screens the principal may open, in catalog order: each catalog entry that is available or public ...
void switchBackend(ui::Backend backend, std::function< void(std::expected< void, std::string >)> done) final
Refused: a switch between backends is the hosting layer's (spec 6 §9).
virtual void disconnect()
Releases what connect made beside the backend; called by close, after the bridge is gone.
virtual std::expected< Transport, ui::ConnectError > connect(ui::AppContext &context)=0
Makes the transport on context.
void poll(std::function< void(std::vector< std::string > changed)> changed)
One step of development reload (spec 5 §12): sends ui-hello, and when the manifest digest changed,...
void open(ui::AppContext &context, std::function< void(std::expected< ui::Bundle, ui::ConnectError >)> ready) final
Opens the source: the transport, the bridge and the bundle, verified.
virtual std::string signedOutPrincipal() const
The principal before any sign-in, which signOut returns to.
ui::SchemasByModel const & schemasByModel() const noexcept
The schemas document of every model the catalog names, by model type, or why it did not arrive: what ...
void onEvent(std::function< void(wire::EventBody const &)> listener)
Adds a listener for the events the server sends: what a shell hands to Session::deliverEvent.
void close() final
Drops a ready not yet delivered and releases the bridge, the transport and the bundle.
ui::Bundle const * bundle() const noexcept
The bundle the catalog currently lists.
virtual std::chrono::milliseconds openTimeout() const
How long open waits for the bundle before it reports the source unreachable; zero waits forever.
ui::CatalogReply const * catalogReply() const noexcept
The catalog for the current principal: its entries, what the principal may run, and the facts.
void signOut(std::function< void(bool)> done)
Ends the session: back to the principal before any sign-in, with no token, and the catalog reloaded f...
std::string const & principal() const noexcept
The principal the source's session carries now.
ui::Dispatcher & dispatcher()
Where the screens' model calls go.
session::Context & requestSession() noexcept
The session every request carries, for a source to fill before open sends anything.
void signIn(std::string principal, std::string token, std::function< void(bool)> done)
Installs a sign-in (spec 6 §5): a session built from the current one with principal and token replace...
ui::Watcher watcher()
What the session's SessionOptions::watcher sends the cache's watch changes through: watcherOver the s...
What a frontend lends the source it opens and the screens it mounts.
Where the screens and the models are: a server (remote) or the application linked in-process (local).
The interpreter's view of the bridge: binds a model by its type id, privately or to a shared instance...
The UI document (spec 5 §3): its model — declarations, commands, view nodes, components and customiza...
The app explorer: what a morph application is made of — its screens, the models they use with every a...
std::map< std::string, ModelSchemas, std::less<> > SchemasByModel
The schemas documents of the models, by model type.
The UI document interpreter: Interpreter::mount turns a loaded Document into reactive state and a vie...
std::function< async::Completion< std::string >(std::string const &kind, std::string const &bodyJson)> Watcher
Sends a watch or unwatch request for a session's cache (spec 8 §7): the kind, and the WatchBody as JS...
morph::reactive::Scheduler: timers a frontend runs on the runtime's owner executor.
The server side of the UI service (spec 5 §12, §12b, §13): UiRegistry collects an application's scree...
The client side of the UI service (spec 5 §12, "Content addressing"): UiClient runs ui-hello,...
std::function< void(::morph::wire::Envelope request, std::function< void(ExchangeReply reply)> done)> Exchange
Sends one request and calls its callback once with the reply. The transport assigns the request's cal...
ui::HelloRequest clientHello()
The ui-hello the generic client opens with, and sends again on each poll: its vocabularies,...
std::vector< std::string > clientVocabularies()
The vocabularies the generic client speaks.
std::expected< std::unique_ptr< Source >, std::string > makeSource(Args const &args, std::vector< LocalApp > const &apps)
The source the client's arguments name: remote for --server, local for --app.
What the generic client reads from its command line.
An application the client links and runs in-process.
std::string name
The name --app selects it by.
std::function< std::expected< std::shared_ptr< ui::ServedBundle const >, ui::Refusal >()> bundle
Builds its bundle: the same function its server calls.
std::function< std::shared_ptr< session::IAuthorizer >()> serverAuthorizer
The authorizer the application's own server checks requests with, for an in-process server to check t...
std::function< void(LocalSetup const &)> setUp
Run once before the first model call, with the client's options; empty for none.
What a local application is set up with.
std::string db
The database path, from --db; empty for the application's default.
std::string user
The development principal, from --user.
What a concrete source opens with: the bridge's backend and the exchange the UI service is reached by...
ui::Exchange exchange
The exchange; it may borrow the backend, which the source guards.
std::unique_ptr< backend::detail::IBackend > backend
The backend; owned by the bridge from here on.
bool serverEvents
Whether the server behind the transport sends events and handles watch: true for a server,...
Per-call session context carried through the bridge to the model.
The application's opaque handle for one of its backends. Its name is what {"env": "backend"}...
What an open source hands the frontend: the application's screens, verified.
The body of a ui-catalog reply: the catalog filtered for the principal, and the facts a client's load...
The facts load-time validation needs from the application's catalog. Local mode answers them from the...
The body of a ui-hello request: what the client speaks and carries.
Why a document, an expression or a value was refused: where, and the reason.
The decoded body of an event envelope.
The frontend seam: main picks a frontend at runtime, and the frontend runs whatever an AppSource open...