Summary#
osy compose answers the question to ask after choosing kits and before writing code: what do these give together,
and what is left for me? Named kits are composed as a dry run — with every kit they use, and every bridge that
completes a pair among them. Run inside an app (or with --app <dir>), it composes what the app uses together with the
app's own code, so what is left is what the app has not done yet.
$ osy compose Osysharp.SatisfactionSurveys Osysharp.Notifications
Composing Osysharp.SatisfactionSurveys, Osysharp.Notifications — 8 kit(s) with what they use
kits Osysharp.Identity · Osysharp.Ui · Osysharp.Workflow · Osysharp.TimeZone · Osysharp.EmailTemplates · Osysharp.Mail · Osysharp.SatisfactionSurveys (vertical) · Osysharp.Notifications
events — handlers in the order they run, after the commit
heard by no handler of its own (1) — `[On] void H(TheEvent e) { … }` hears one: FeedbackAnswered (Osysharp.SatisfactionSurveys)
left for you
define policy ManagesFeedback (Osysharp.SatisfactionSurveys) — Who decides whether, when and for how long people are asked — the settings page.
its test app: policy ManagesFeedback => IsOwner;
define policy ReadsFeedback (Osysharp.SatisfactionSurveys) — Who reads the answers and the results — the people who did the work, and whoever looks after how it goes.
its test app: policy ReadsFeedback => IsMechanic;
define policy ReceivesNotifications (Osysharp.Notifications) — Who has a bell and notification preferences — the people the app tells things.
its test app: policy ReceivesNotifications => IsWriter;
may define policy ManagesClock (Osysharp.TimeZone; has a default) — Who may move the app's clock — the app's admins, unless the app says otherwise: …
its test app: policy ManagesClock => IsOwner;Signature#
osy compose <kits…> # a dry run over these kits, what they use, and the bridges among them
osy compose [--app <dir>] # what this app uses, with its own code (the default inside an app)
--diff +<kit> # what one more kit adds
--effects # what each handler can create, change, delete, raise or send (always on in an app)
--project <dir> # where to look for kits — the workspace above it, its lock
--offline # only kits on this machine: no newest release from GitHub, no bridge search there
--json # { composition: { packages, events, slots, extensions, records, actions, settings, nav, left } }Description#
What it prints#
- kits — every kit in the composition, a product kit marked
(vertical), and each included bridge with why it arrived (completes Osysharp.WorkQueues + Osysharp.Notifications) and how to keep it out (without …;). - records — each record type with a title, the page that opens it and the actions offered on it.
- events — each event with who raises it and its handlers in the order they run:
[Order](default 100), then the package — a kit before the kits built on it, your app last — then the name. The handlers that hear every event (automations, webhooks, a timeline) are said once. Events nothing hears specifically are listed on one line. - slots — each slot with its contributions in drawing order; a slot nothing fills is shown, not an error.
- extension members — the members a bridge (or your app) adds to another kit's record.
- nav and settings pages — the entries each kit adds.
- left for you — what the composition still needs from your app: each policy a kit asks for and the app has not defined (with the kit's test app's line that defines it), each setting whose fields have no default, each abstract base with no type of your own.
Two kinds of account#
An app has ONE [Principal] (who signs in is one table), one [Role] enum, and one sign-in. A set of kits that brings
two of any of them is said FIRST, before everything else, because it is not one app: the compile refuses the first two,
and of two kits that each wire a sign-in only one is ever reached. The line names both declarers — and a kit you never
named by the kit that brought it, so the use to drop is the one in your app. In an app that declares its own roles and
uses the shop, whose roles are the shop's:
$ osy compose
⚠ two role vocabularies: `AppRole` (this app) and `ShopRole` (Osysharp.Shop). An app has only ONE `[Role]` enum — the roles a sign-in carries, counted across the app and every kit it uses, so this set does not compile as one app. Keep one kit's accounts: drop `Osysharp.Shop` (or your own) from the set, or use a kit that builds on the other's.Kits that BUILD ON one another share one identity and are not a clash: the shop's ShopAccount is an Osysharp.UserAccounts
User, itself an Osysharp.Identity Principal, so the shop composes with every kit on that identity — feedback,
invitations, the people kit.
--diff +<kit> says it when the kit it adds is what brings the second; --json carries the lines as clashes.
What a handler can change#
--effects resolves the composition and prints, beside each handler, what it — and everything it calls — can create,
change, delete, raise or send out. In an app it is always on. It is the review to make before a kit's handler runs on
your data:
events — handlers in the order they run, after the commit
every event is heard by RunRules (Osysharp.Automations, only what its [Interest] names), SendOut (Osysharp.Webhooks, only what its [Interest] names), InboxOnTheTimeline (this app, only what its [Interest] names)
RunRules · creates AutomationFire; changes AutomationFire; and calls whose effects are not known here
SendOut · creates WebhookDelivery; and calls whose effects are not known here
InboxOnTheTimeline · creates ConversationEvent; changes Conversation
FeedbackAnswered (Osysharp.SatisfactionSurveys raised by ApplyFeedbackReply)
→ TicketAnswered (this app) · creates ConversationEvent, Notification; changes Conversation, Ticket; Policy.CheckForOne more kit#
--diff +<kit> composes once without the kit and once with it, and prints only what it adds: the kits (with any bridge
it completes), the handlers it brings to events already there, contributions, nav, extension members, and the policies
and settings it leaves for you.
The same data in osy model#
osy model --json carries the app's composition as composition — the same shape osy compose --app . --json prints —
for a tool (Understanding your app).
See also#
- Connecting a kit — each seam with the code that connects it — each seam of one kit, with the code that connects it
- Finding a kit, and learning one from its tests —
osy kits find: kits by what they do - Bridges — a package that arrives when an app uses the two it completes —
completes, and how a bridge arrives by itself - [On] — hear an event, after the commit that raised it — hearing an event, and the order handlers run in
- Slot (child content) — slots and contributions