@kestack/kabuki 0.0.0 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/README.md +156 -33
  2. package/dist/core/actor/actor.d.ts +24 -13
  3. package/dist/core/actor/actor.d.ts.map +1 -1
  4. package/dist/core/actor/actor.js +37 -26
  5. package/dist/core/actor/index.d.ts +2 -2
  6. package/dist/core/actor/index.d.ts.map +1 -1
  7. package/dist/core/actor/types.d.ts +91 -47
  8. package/dist/core/actor/types.d.ts.map +1 -1
  9. package/dist/core/history/history.d.ts +11 -3
  10. package/dist/core/history/history.d.ts.map +1 -1
  11. package/dist/core/history/history.js +106 -27
  12. package/dist/core/history/replay.d.ts +2 -0
  13. package/dist/core/history/replay.d.ts.map +1 -1
  14. package/dist/core/history/replay.js +1 -0
  15. package/dist/core/history/saved.d.ts +1 -1
  16. package/dist/core/history/saved.d.ts.map +1 -1
  17. package/dist/core/history/saved.js +13 -9
  18. package/dist/core/index.d.ts +1 -1
  19. package/dist/core/index.d.ts.map +1 -1
  20. package/dist/core/snapshot/invoke.d.ts +2 -3
  21. package/dist/core/snapshot/invoke.d.ts.map +1 -1
  22. package/dist/core/snapshot/invoke.js +42 -49
  23. package/dist/core/snapshot/restore.js +8 -7
  24. package/dist/core/snapshot/tree.d.ts +1 -1
  25. package/dist/core/snapshot/tree.d.ts.map +1 -1
  26. package/dist/core/snapshot/tree.js +1 -1
  27. package/dist/react/app.d.ts +30 -3
  28. package/dist/react/app.d.ts.map +1 -1
  29. package/dist/react/app.js +119 -40
  30. package/dist/react/drawn.d.ts +1 -1
  31. package/dist/react/drawn.d.ts.map +1 -1
  32. package/dist/react/drawn.js +2 -1
  33. package/dist/react/index.d.ts +3 -0
  34. package/dist/react/index.d.ts.map +1 -1
  35. package/dist/react/index.js +2 -0
  36. package/dist/react/lazy.d.ts +30 -0
  37. package/dist/react/lazy.d.ts.map +1 -0
  38. package/dist/react/lazy.js +56 -0
  39. package/dist/react/live.d.ts +7 -0
  40. package/dist/react/live.d.ts.map +1 -0
  41. package/dist/react/live.js +13 -0
  42. package/dist/react/view.d.ts +26 -6
  43. package/dist/react/view.d.ts.map +1 -1
  44. package/dist/react/view.js +17 -5
  45. package/dist/routing/adapter/adapter.d.ts +38 -0
  46. package/dist/routing/adapter/adapter.d.ts.map +1 -0
  47. package/dist/routing/adapter/adapter.js +10 -0
  48. package/dist/routing/adapter/browser/browser.d.ts +8 -0
  49. package/dist/routing/adapter/browser/browser.d.ts.map +1 -0
  50. package/dist/routing/adapter/browser/browser.js +33 -0
  51. package/dist/routing/adapter/browser/index.d.ts +2 -0
  52. package/dist/routing/adapter/browser/index.d.ts.map +1 -0
  53. package/dist/routing/adapter/browser/index.js +1 -0
  54. package/dist/routing/adapter/index.d.ts +3 -0
  55. package/dist/routing/adapter/index.d.ts.map +1 -0
  56. package/dist/routing/adapter/index.js +1 -0
  57. package/dist/routing/adapter/tanstack/index.d.ts +3 -0
  58. package/dist/routing/adapter/tanstack/index.d.ts.map +1 -0
  59. package/dist/routing/adapter/tanstack/index.js +1 -0
  60. package/dist/routing/adapter/tanstack/tanstack.d.ts +27 -0
  61. package/dist/routing/adapter/tanstack/tanstack.d.ts.map +1 -0
  62. package/dist/routing/adapter/tanstack/tanstack.js +38 -0
  63. package/dist/routing/capability/cache.d.ts +12 -0
  64. package/dist/routing/capability/cache.d.ts.map +1 -0
  65. package/dist/routing/capability/cache.js +170 -0
  66. package/dist/routing/capability/index.d.ts +6 -0
  67. package/dist/routing/capability/index.d.ts.map +1 -0
  68. package/dist/routing/capability/index.js +3 -0
  69. package/dist/routing/capability/loading.d.ts +82 -0
  70. package/dist/routing/capability/loading.d.ts.map +1 -0
  71. package/dist/routing/capability/loading.js +53 -0
  72. package/dist/routing/capability/navigation.d.ts +66 -0
  73. package/dist/routing/capability/navigation.d.ts.map +1 -0
  74. package/dist/routing/capability/navigation.js +65 -0
  75. package/dist/routing/index.d.ts +10 -0
  76. package/dist/routing/index.d.ts.map +1 -0
  77. package/dist/routing/index.js +4 -0
  78. package/dist/routing/page/index.d.ts +5 -0
  79. package/dist/routing/page/index.d.ts.map +1 -0
  80. package/dist/routing/page/index.js +2 -0
  81. package/dist/routing/page/page.d.ts +151 -0
  82. package/dist/routing/page/page.d.ts.map +1 -0
  83. package/dist/routing/page/page.js +121 -0
  84. package/dist/routing/page/status.d.ts +121 -0
  85. package/dist/routing/page/status.d.ts.map +1 -0
  86. package/dist/routing/page/status.js +69 -0
  87. package/dist/routing/route/index.d.ts +11 -0
  88. package/dist/routing/route/index.d.ts.map +1 -0
  89. package/dist/routing/route/index.js +6 -0
  90. package/dist/routing/route/loader.d.ts +98 -0
  91. package/dist/routing/route/loader.d.ts.map +1 -0
  92. package/dist/routing/route/loader.js +17 -0
  93. package/dist/routing/route/metadata.d.ts +44 -0
  94. package/dist/routing/route/metadata.d.ts.map +1 -0
  95. package/dist/routing/route/metadata.js +53 -0
  96. package/dist/routing/route/node.d.ts +162 -0
  97. package/dist/routing/route/node.d.ts.map +1 -0
  98. package/dist/routing/route/node.js +3 -0
  99. package/dist/routing/route/places.d.ts +15 -0
  100. package/dist/routing/route/places.d.ts.map +1 -0
  101. package/dist/routing/route/places.js +87 -0
  102. package/dist/routing/route/route.d.ts +53 -0
  103. package/dist/routing/route/route.d.ts.map +1 -0
  104. package/dist/routing/route/route.js +148 -0
  105. package/dist/routing/route/url.d.ts +13 -0
  106. package/dist/routing/route/url.d.ts.map +1 -0
  107. package/dist/routing/route/url.js +79 -0
  108. package/dist/routing/route/values.d.ts +12 -0
  109. package/dist/routing/route/values.d.ts.map +1 -0
  110. package/dist/routing/route/values.js +47 -0
  111. package/dist/routing/router/context.d.ts +123 -0
  112. package/dist/routing/router/context.d.ts.map +1 -0
  113. package/dist/routing/router/context.js +156 -0
  114. package/dist/routing/router/data.d.ts +117 -0
  115. package/dist/routing/router/data.d.ts.map +1 -0
  116. package/dist/routing/router/data.js +247 -0
  117. package/dist/routing/router/define.d.ts +52 -0
  118. package/dist/routing/router/define.d.ts.map +1 -0
  119. package/dist/routing/router/define.js +48 -0
  120. package/dist/routing/router/frame.d.ts +10 -0
  121. package/dist/routing/router/frame.d.ts.map +1 -0
  122. package/dist/routing/router/frame.js +10 -0
  123. package/dist/routing/router/index.d.ts +7 -0
  124. package/dist/routing/router/index.d.ts.map +1 -0
  125. package/dist/routing/router/index.js +3 -0
  126. package/dist/routing/router/router.d.ts +165 -0
  127. package/dist/routing/router/router.d.ts.map +1 -0
  128. package/dist/routing/router/router.js +801 -0
  129. package/dist/routing/routing.d.ts +72 -0
  130. package/dist/routing/routing.d.ts.map +1 -0
  131. package/dist/routing/routing.js +53 -0
  132. package/dist/routing/scroll/index.d.ts +4 -0
  133. package/dist/routing/scroll/index.d.ts.map +1 -0
  134. package/dist/routing/scroll/index.js +2 -0
  135. package/dist/routing/scroll/script.d.ts +6 -0
  136. package/dist/routing/scroll/script.d.ts.map +1 -0
  137. package/dist/routing/scroll/script.js +52 -0
  138. package/dist/routing/scroll/scroll.d.ts +75 -0
  139. package/dist/routing/scroll/scroll.d.ts.map +1 -0
  140. package/dist/routing/scroll/scroll.js +201 -0
  141. package/dist/routing/scroll/selector.d.ts +14 -0
  142. package/dist/routing/scroll/selector.d.ts.map +1 -0
  143. package/dist/routing/scroll/selector.js +40 -0
  144. package/dist/routing/scroll/session.d.ts +6 -0
  145. package/dist/routing/scroll/session.d.ts.map +1 -0
  146. package/dist/routing/scroll/session.js +23 -0
  147. package/dist/start/client/client.d.ts +11 -0
  148. package/dist/start/client/client.d.ts.map +1 -0
  149. package/dist/start/client/client.js +24 -0
  150. package/dist/start/client/index.d.ts +3 -0
  151. package/dist/start/client/index.d.ts.map +1 -0
  152. package/dist/start/client/index.js +2 -0
  153. package/dist/start/client/rpc.d.ts +14 -0
  154. package/dist/start/client/rpc.d.ts.map +1 -0
  155. package/dist/start/client/rpc.js +70 -0
  156. package/dist/start/common/app.d.ts +66 -0
  157. package/dist/start/common/app.d.ts.map +1 -0
  158. package/dist/start/common/app.js +23 -0
  159. package/dist/start/common/common.d.ts +26 -0
  160. package/dist/start/common/common.d.ts.map +1 -0
  161. package/dist/start/common/common.js +19 -0
  162. package/dist/start/common/document.d.ts +44 -0
  163. package/dist/start/common/document.d.ts.map +1 -0
  164. package/dist/start/common/document.js +58 -0
  165. package/dist/start/common/index.d.ts +9 -0
  166. package/dist/start/common/index.d.ts.map +1 -0
  167. package/dist/start/common/index.js +5 -0
  168. package/dist/start/common/page.d.ts +67 -0
  169. package/dist/start/common/page.d.ts.map +1 -0
  170. package/dist/start/common/page.js +29 -0
  171. package/dist/start/common/wire.d.ts +37 -0
  172. package/dist/start/common/wire.d.ts.map +1 -0
  173. package/dist/start/common/wire.js +73 -0
  174. package/dist/start/platform/cloudflare/cloudflare.d.ts +8 -0
  175. package/dist/start/platform/cloudflare/cloudflare.d.ts.map +1 -0
  176. package/dist/start/platform/cloudflare/cloudflare.js +31 -0
  177. package/dist/start/platform/cloudflare/index.d.ts +2 -0
  178. package/dist/start/platform/cloudflare/index.d.ts.map +1 -0
  179. package/dist/start/platform/cloudflare/index.js +1 -0
  180. package/dist/start/platform/index.d.ts +2 -0
  181. package/dist/start/platform/index.d.ts.map +1 -0
  182. package/dist/start/platform/index.js +1 -0
  183. package/dist/start/platform/platform.d.ts +31 -0
  184. package/dist/start/platform/platform.d.ts.map +1 -0
  185. package/dist/start/platform/platform.js +13 -0
  186. package/dist/start/server/cache.d.ts +4 -0
  187. package/dist/start/server/cache.d.ts.map +1 -0
  188. package/dist/start/server/cache.js +26 -0
  189. package/dist/start/server/draw.d.ts +10 -0
  190. package/dist/start/server/draw.d.ts.map +1 -0
  191. package/dist/start/server/draw.js +75 -0
  192. package/dist/start/server/index.d.ts +3 -0
  193. package/dist/start/server/index.d.ts.map +1 -0
  194. package/dist/start/server/index.js +2 -0
  195. package/dist/start/server/layers.d.ts +97 -0
  196. package/dist/start/server/layers.d.ts.map +1 -0
  197. package/dist/start/server/layers.js +37 -0
  198. package/dist/start/server/respond.d.ts +15 -0
  199. package/dist/start/server/respond.d.ts.map +1 -0
  200. package/dist/start/server/respond.js +35 -0
  201. package/dist/start/server/rpc.d.ts +11 -0
  202. package/dist/start/server/rpc.d.ts.map +1 -0
  203. package/dist/start/server/rpc.js +51 -0
  204. package/dist/start/server/server.d.ts +13 -0
  205. package/dist/start/server/server.d.ts.map +1 -0
  206. package/dist/start/server/server.js +138 -0
  207. package/dist/start/server/tiers.d.ts +14 -0
  208. package/dist/start/server/tiers.d.ts.map +1 -0
  209. package/dist/start/server/tiers.js +31 -0
  210. package/dist/start/vite/dev.d.ts +5 -0
  211. package/dist/start/vite/dev.d.ts.map +1 -0
  212. package/dist/start/vite/dev.js +56 -0
  213. package/dist/start/vite/entries.d.ts +27 -0
  214. package/dist/start/vite/entries.d.ts.map +1 -0
  215. package/dist/start/vite/entries.js +66 -0
  216. package/dist/start/vite/files.d.ts +22 -0
  217. package/dist/start/vite/files.d.ts.map +1 -0
  218. package/dist/start/vite/files.js +23 -0
  219. package/dist/start/vite/index.d.ts +2 -0
  220. package/dist/start/vite/index.d.ts.map +1 -0
  221. package/dist/start/vite/index.js +1 -0
  222. package/dist/start/vite/lazy.d.ts +4 -0
  223. package/dist/start/vite/lazy.d.ts.map +1 -0
  224. package/dist/start/vite/lazy.js +30 -0
  225. package/dist/start/vite/manifest.d.ts +18 -0
  226. package/dist/start/vite/manifest.d.ts.map +1 -0
  227. package/dist/start/vite/manifest.js +42 -0
  228. package/dist/start/vite/styles.d.ts +7 -0
  229. package/dist/start/vite/styles.d.ts.map +1 -0
  230. package/dist/start/vite/styles.js +58 -0
  231. package/dist/start/vite/vite.d.ts +11 -0
  232. package/dist/start/vite/vite.d.ts.map +1 -0
  233. package/dist/start/vite/vite.js +217 -0
  234. package/package.json +53 -3
package/README.md CHANGED
@@ -11,7 +11,8 @@ changes, and its State decides which Children it Invokes, which Capabilities
11
11
  it Provides to them and which Workers run. Leaving a State stops all of it.
12
12
  Any fact in the Model can own a Worker too: an upload runs for as long as its
13
13
  row says Uploading.
14
- Keyed Children follow the Model: a list of items can be a list of Actors.
14
+ Children are written the way Workers are: always, `while` a test holds, or
15
+ one per key `each` names, so a list of items can be a list of Actors.
15
16
  It is declarative, as React is: a parent says what should be, never what to
16
17
  do. It controls its Children only by whether they exist and by their Props,
17
18
  and what it must control it owns, as React lifts state up.
@@ -35,6 +36,26 @@ move its Head, and start again, and new Messages grow a new Branch. A History
35
36
  is also what an app is saved as and drawn from before it runs: on a server,
36
37
  at build time, and across a hot reload.
37
38
 
39
+ Routing is a layer on top, in `@kestack/kabuki/routing`, that core never
40
+ imports: a page is an Actor with a place in the URL. The router is read down
41
+ from the pages' definitions, so any build can import it and name a Route by
42
+ type. One Router Actor above the pages holds the history and the data of
43
+ every page on screen, and hands each page its own as Props, so a page move
44
+ is one Message and a page is a Child coming and going. It routes in memory
45
+ by default; the browser's history and TanStack Router's are Adapters, each
46
+ its own subpath. How it fits together is in
47
+ [docs/routing.md](./docs/routing.md).
48
+
49
+ Start, in `@kestack/kabuki/start` and its Vite plugin, serves a routed app
50
+ from a Cloudflare Worker: for a URL it runs the Loaders of the places it
51
+ names at once, starts every page from what its Loader gave, and sends the HTML with the
52
+ Snapshot beside it, which the browser hydrates and carries on from. It never
53
+ runs a Runtime on the server. An app writes three files: its pages, its app
54
+ with its Document and what it needs in the browser, and its Loaders with what
55
+ they need on the server, in three tiers; the plugin writes every entry. Each
56
+ platform is an adapter of its own subpath, Cloudflare Workers for now. How it works is in
57
+ [docs/start.md](./docs/start.md).
58
+
38
59
  Read the language in [CONTEXT.md](./CONTEXT.md), the decisions in
39
60
  [docs/adr/](./docs/adr/), and how the History works in
40
61
  [docs/history.md](./docs/history.md). A live demo, Opening an app, is at `/demos/opening-an-app` in the docs app: every concept in one story, drawn as the tree.
@@ -49,6 +70,8 @@ pnpm add @kestack/kabuki effect react
49
70
  one is checked against its Schema as it is made; Workers, Commands and
50
71
  Capabilities are Effect values and Layers.
51
72
  - `react`: `@kestack/kabuki/react` draws the tree with React components.
73
+ - `react-dom`, optional: Start draws pages with `react-dom/server` and hydrates them with `react-dom/client`.
74
+ - `vite`, optional: `@kestack/kabuki/start/vite` is a Vite plugin.
52
75
 
53
76
  ## Exports
54
77
 
@@ -56,13 +79,14 @@ pnpm add @kestack/kabuki effect react
56
79
 
57
80
  | Export | What it does |
58
81
  | ------------------ | -------------------------------------------------------------------------------------------------------------------- |
59
- | `Actor.make` | Defines an Actor from its Requires and Schemas. `.build` adds how it behaves, at the top and in one block per State. |
60
- | `Actor.many` | Declares a keyed Child slot: one Instance of an Actor per key the parent Invokes. |
82
+ | `Actor.define` | Says what an Actor is: its name, Requires and Schemas, which fix every type. It runs nothing. |
83
+ | `Actor.build` | Says how a defined Actor behaves, at the top and in one block per State: the build is what runs and is drawn. |
61
84
  | `Command.make` | Defines a Command from its name, the Schema of its args and the Effect it runs; an Update calls it with the args. |
62
85
  | `Runtime.start` | Runs an Actor, or carries a History on, inside a Scope, with the app's Layer; gives back `send`, `start` and `stop`. |
63
86
  | `History.make` | A new, empty History for an Actor, with the root's Input. |
64
87
  | `History.load` | A History carrying on from one saved before, read with the Actor's code as it is now. |
65
88
  | `History.restored` | The lightest History an app can be saved as: one Restore of a Snapshot at a Time, right after init. |
89
+ | `history.keep` | Sets the History's Window, how many entries it keeps; older ones Compact into a Restore. Works while it runs. |
66
90
  | `Replay.make` | Plays Branches of one app from init, remembering Snapshots so playing again starts from the nearest one. |
67
91
  | `Replay.fold` | The Snapshot right after a Branch, played now from init with the root's Input, with no yielding. |
68
92
  | `restore` | The Restore Message: given to the root, it replaces the whole Snapshot with a saved one, checked against the Actors. |
@@ -72,16 +96,111 @@ pnpm add @kestack/kabuki effect react
72
96
  | `handle` | Applies one Envelope to a Snapshot and gives the next one, purely. |
73
97
  | `outcomeOf` | Works out what came of one Envelope on a Snapshot: handled, ignored or dropped. The History never keeps it. |
74
98
  | `instanceAt` | Finds the Instance with an ID in a Snapshot. |
75
- | `isMany` | Tells a keyed Child slot from a fixed one in an Instance's Children. |
99
+ | `isMany` | Tells the list of an `each` Child from one Instance in an Instance's Children. |
76
100
 
77
101
  ### `@kestack/kabuki/react`
78
102
 
79
- | Export | What it does |
80
- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
81
- | `View.make` | Defines how one Actor is drawn, one function for every State, as a React component that takes the Instance, and a `ref` and `style`, from its parent. |
82
- | `toReact` | Turns a root Actor, its View and a Layer into one React component that runs the whole app, one Runtime for every mount; `useRuntime` reads its History, shows any Step, and stops and starts it. Drawn before it runs, on a server too, from a saved History if given one. |
83
- | `useChild` | Reads one fixed Child's Model, State and Props from its parent's View, to draw, or only what an optional selector picks; an escape hatch that can never Send. |
84
- | `useChildren` | Reads a slot of keyed Children the same way, in order; only the component that calls it re-renders, as they change or as what the selector picks does. |
103
+ | Export | What it does |
104
+ | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
105
+ | `View.make` | Defines how one built Actor is drawn, one function for every State, as a React component that takes the Instance, and a `ref` and `style`, from its parent; the View carries its Actor as `.actor`. |
106
+ | `toReact` | Turns a root Actor, its View and a Layer into one React component that runs the whole app, one Runtime for every mount; `useRuntime` reads its History, shows any Step, and stops and starts it. Drawn before it runs, on a server too, from a saved History if given one. |
107
+ | `View.lazy` | A View of the Actor it is given first, whose code is loaded the first time it is drawn, or on `preload()`; a server waits for it before it sends, and tells the App's `onLazyView`. |
108
+ | `View.preload` | Loads the lazy Views made with these ids, so a browser hydrating a page a server drew never waits on their code. |
109
+ | `useChild` | Reads one Child's Model, State and Props from its parent's View, to draw, or only what an optional selector picks; an escape hatch that can never Send. |
110
+ | `useChildren` | Reads the Instances of an `each` Child the same way, in order; only the component that calls it re-renders, as they change or as what the selector picks does. |
111
+ | `lazyOf` | Finds the lazy View made for an Actor, if one was, to load its code before it is drawn. |
112
+ | `useLive` | Says whether the app is drawn as it is now, not at a past Step, so an effect that touches the page around it can stay still under Time Travel. |
113
+
114
+ ### `@kestack/kabuki/routing`
115
+
116
+ | Export | What it does |
117
+ | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
118
+ | `Page.define` | Says what a page is: an Actor definition with a place in the URL, its params, query, data, Render Mode, Metadata and the definitions of the pages under it. |
119
+ | `Page.build` | Says how a page behaves, as `Actor.build` takes it, with the build of each page under it in `pages`; a page is drawn with `View.make`. |
120
+ | `Page.notFound` | What a Loader fails with when its place is not found. |
121
+ | `Page.redirect` | What a Loader fails with to send the app to another of its Routes, or to a whole URL outside it; `{ permanent: true }` makes a server answer `308` rather than `302`. |
122
+ | `Page.NotFound` | The Schema of a Loader's not-found failure, to carry it over the wire. |
123
+ | `Page.Redirect` | The Schema of a Loader's Redirect, to carry it over the wire. |
124
+ | `Router.define` | Reads the app's router down from the root page's definition: a constructor per place, the URL both ways, each place's Metadata and Render Mode, every path, the typing of the Loaders, and how the Router behaves in the browser. |
125
+ | `Router.app` | Puts the Router above the root page's View: it holds the history, every move and every page's data; gives the Actor, its View, `startAt` and `href`. With `scrollRestoration: true` on the router it restores scroll as TanStack Router does. |
126
+ | `Router.Link` | Draws a plain `<a href>` to a Route, preloading it on hover, once in view, or never, going to an element on the page with `hash`, and leaving every scroll as it is with `resetScroll={false}`; the Router catches a plain click and moves the app. |
127
+ | `Router.Retry` | A button that loads every page on screen again, for a page whose Loader broke. |
128
+ | `Router.memory` | A `Loading` that runs the Loaders in place, for tests, stories and the server. |
129
+ | `Router.cached` | Puts the Data cache in front of a `Loading`: the last data of each place, shown at once on Back, a link or a preload. |
130
+ | `Router.push` | A Command that moves the app to a Route, as a new entry. |
131
+ | `Router.replace` | A Command that puts a Route in place of the current entry, so Back skips it. |
132
+ | `Router.back` | A Command that goes Back. |
133
+ | `Router.forward` | A Command that goes Forward. |
134
+ | `Router.backTo` | A Command that goes Back when the app came from a Route, and replaces the entry with it otherwise: closing a dialog with a Route of its own. |
135
+ | `Router.reload` | A Command that loads every page on screen again, as after a save; the pages and their Models stay. |
136
+ | `Router.preload` | A Command that warms the Data cache, and the code of the lazy Views, for a Route. |
137
+ | `Navigation` | The Capability the Router Provides to every page, which an Actor under a page that moves the app lists in its Requires. |
138
+ | `Loading` | The Capability the Router uses, if the Layer has it, to load the data of places. |
139
+ | `useRouter` | Reads the Router from a component drawn inside the app: the current Route and URL, the history, the move it holds while it loads as `pending`, the title, Back, Forward, reload and preload; `useRouter<Route>()` types its Routes as the app's. |
140
+ | `useElementScrollRestoration` | Reads where an element, or the window, was scrolled on the entry drawn, as scroll restoration kept it: for a virtual list that puts itself back. |
141
+
142
+ ### `@kestack/kabuki/routing/adapter`
143
+
144
+ | Export | What it does |
145
+ | --------- | ---------------------------------------------------------------------------------------------------------- |
146
+ | `Adapter` | The service where an app's address lives, which each adapter below gives: write one for any other history. |
147
+ | `KEY` | The key the Router keeps in a history entry's state, so Back and Forward land on an entry it knows. |
148
+ | `keyIn` | Reads that key from a history entry's state, if the Router wrote one. |
149
+
150
+ ### `@kestack/kabuki/routing/adapter/browser`
151
+
152
+ | Export | What it does |
153
+ | --------- | ----------------------------------------------------------------------------------------------------------------------------------- |
154
+ | `browser` | A Layer that puts the app's address in the browser's own history, for an app that owns the whole site or everything under its base. |
155
+
156
+ ### `@kestack/kabuki/routing/adapter/tanstack`
157
+
158
+ | Export | What it does |
159
+ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
160
+ | `tanstack` | A Layer that puts the app's address in TanStack Router's history, for an app on a TanStack Start catch-all route; TanStack gets back every URL outside the base. |
161
+
162
+ ### `@kestack/kabuki/start`
163
+
164
+ | Export | What it does |
165
+ | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
166
+ | `Start.app` | Gives the app's router and its root page's View their Document and what the Actors Require in the browser, checked against them: what `src/app` default-exports. |
167
+ | `Start.Document` | The plainest Document, Start's parts in an English page: what an app that gives none is drawn in. |
168
+ | `Start.Head` | Draws, in the Document's `<head>`, the charset and viewport, the Metadata, and the styles and chunks the page needs. |
169
+ | `Start.Scripts` | Draws, at the end of the Document's `<body>`, the saved History as JSON and the script that hydrates the page. |
170
+ | `Start.useDrawn` | Reads when and by which build the server drew the page, and whether the component asking was in that drawing or drawn later by the browser. |
171
+ | `Start.useRuntime` | Reads the running app from the Document, for devtools drawn around it; `null` on the server. |
172
+
173
+ ### `@kestack/kabuki/start/platform`
174
+
175
+ The port each platform's adapter fills, in types only: no runtime value.
176
+
177
+ ### `@kestack/kabuki/start/platform/cloudflare`
178
+
179
+ | Export | What it does |
180
+ | ------------ | --------------------------------------------------------------------------------------------------------------------------------- |
181
+ | `cloudflare` | Cloudflare Workers, for `start({ platform: cloudflare() })`: the server built as one module in its edge form. |
182
+ | `serve` | Start's handler as a Worker's `fetch`, handed the Worker's env and the Cloudflare Cache: what the server's entry default-exports. |
183
+
184
+ ### `@kestack/kabuki/start/vite`
185
+
186
+ | Export | What it does |
187
+ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
188
+ | `start` | The Vite plugin: builds for the platform its adapter names, finds the app's two files by name, writes Start's handler, the server's and the browser's entries, names every lazy View by its module, and serves SSR in dev; works under Alchemy's `Website.Vite`. |
189
+
190
+ ### `@kestack/kabuki/start/server`
191
+
192
+ | Export | What it does |
193
+ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
194
+ | `server` | Makes Start's handler, which knows no platform, from what the app's two files export: what the plugin's handler module runs; an app never calls it. |
195
+ | `Start.layers` | Gives the Loaders what they Require on the server, in three tiers, a call each (`instance`, `request`, `visitor`), each checked against the tiers before it, and the Loaders checked last: what `src/loaders.server` default-exports. |
196
+ | `Start.ResponseHeaders` | The service a dynamic or client Loader, or the visitor tier, adds headers to its response with, as a refreshed session's `set-cookie`. |
197
+
198
+ ### `@kestack/kabuki/start/client`
199
+
200
+ | Export | What it does |
201
+ | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
202
+ | `client` | Hydrates a page the Worker drew, from the History it saved in it: what the plugin's browser entry runs; an app never calls it. |
203
+ | `loading` | The `Loading` that asks the server for the data of places at `POST /_kabuki/load`, each answered as it comes: what `client` hydrates with, behind the Data cache. |
85
204
 
86
205
  ## Usage
87
206
 
@@ -91,7 +210,7 @@ This root signs a user in. While `Anonymous` it Provides `SignIn` and Invokes
91
210
  `login`; while `Authenticated` it Provides `Session` and Invokes `todos`.
92
211
 
93
212
  ```ts
94
- export const Auth = Actor.make('Auth', {
213
+ export const Auth = Actor.define('Auth', {
95
214
  requires: [Server],
96
215
  state: Schema.TaggedUnion({
97
216
  Checking: {},
@@ -103,7 +222,9 @@ export const Auth = Actor.make('Auth', {
103
222
  LoggedIn: { user: Schema.String },
104
223
  LoggedOut: {},
105
224
  }),
106
- }).build({
225
+ });
226
+
227
+ export const AuthLive = Actor.build(Auth, {
107
228
  init: () => ({ state: { _tag: 'Checking' } }),
108
229
  state: {
109
230
  Checking: {
@@ -123,7 +244,7 @@ export const Auth = Actor.make('Auth', {
123
244
  },
124
245
  },
125
246
  Anonymous: {
126
- children: { login: Login },
247
+ children: { login: { actor: LoginLive } },
127
248
  provides: (self) =>
128
249
  Layer.succeed(SignIn, {
129
250
  complete: (user) => self.send({ _tag: 'LoggedIn', user }),
@@ -133,7 +254,7 @@ export const Auth = Actor.make('Auth', {
133
254
  },
134
255
  },
135
256
  Authenticated: {
136
- children: { todos: Todos },
257
+ children: { todos: { actor: TodosLive } },
137
258
  provides: (self) =>
138
259
  Layer.succeed(Session, {
139
260
  user: self.get.pipe(Effect.map(({ state }) => state.user)),
@@ -145,8 +266,8 @@ export const Auth = Actor.make('Auth', {
145
266
  });
146
267
  ```
147
268
 
148
- - `make` takes only the Requires and the Schemas, which fix every type. `build` is checked against them: an Update that returns a State the Schema does not have, or a `state.user` read where there is none, does not compile.
149
- - `build` has two Levels. What is written at the top holds for as long as the Instance lives; what is written in a State's block holds while that State lasts. Each Level can hold `provides`, `children`, `invoke`, `on` and `workers`.
269
+ - `Actor.define` takes only the name, the Requires and the Schemas, which fix every type, and imports nothing but other definitions. `Actor.build` is checked against them: an Update that returns a State the Schema does not have, or a `state.user` read where there is none, does not compile. The definition is `Auth`, the build `AuthLive`, side by side in one file.
270
+ - A build has two Levels. What is written at the top holds for as long as the Instance lives; what is written in a State's block holds while that State lasts. Each Level can hold `provides`, `children`, `on` and `workers`.
150
271
  - An Update that returns a different `_tag` is a Transition: the old State's Children, Workers and Capabilities stop, the new State's start. A Child written at the top lasts through it.
151
272
  - A Worker is a named, scoped Effect given `self`: `send` to its own Instance, `get` and `changes` for its current data, and `now` for the app's Time. Written in the `Checking` block, `check` runs while that State lasts.
152
273
  - Provides is one Layer per Level, built each time its Level starts. A Capability that reads the Model reads it through `self`, so it never goes stale. It cancels out what the Children below it need; a need nothing cancels bubbles up to the app's Layer.
@@ -161,7 +282,7 @@ const save = Command.make('save', {
161
282
  Effect.sleep('1 second').pipe(Effect.as({ _tag: 'Saved' as const })),
162
283
  });
163
284
 
164
- const List = Actor.make('List', {
285
+ const List = Actor.define('List', {
165
286
  model: Schema.Struct({
166
287
  ids: Schema.Array(Schema.String),
167
288
  uploading: Schema.Array(Schema.String),
@@ -173,16 +294,18 @@ const List = Actor.make('List', {
173
294
  Saved: {},
174
295
  Uploaded: { id: Schema.String },
175
296
  }),
176
- }).build({
297
+ });
298
+
299
+ const ListLive = Actor.build(List, {
177
300
  init: () => ({ model: { ids: [], uploading: [], next: 0 } }),
178
- children: { rows: Actor.many(Row) },
179
- invoke: ({ model }) => ({
180
- rows: model.ids.map((id) => ({
181
- key: id,
182
- input: { text: `#${id}` },
183
- props: { uploading: model.uploading.includes(id) },
184
- })),
185
- }),
301
+ children: {
302
+ rows: {
303
+ actor: RowLive,
304
+ each: ({ model }) => model.ids,
305
+ input: (_, id) => ({ text: `#${id}` }),
306
+ props: ({ model }, id) => ({ uploading: model.uploading.includes(id) }),
307
+ },
308
+ },
186
309
  on: {
187
310
  Added: (_, { model }) => {
188
311
  const id = `${model.next}`;
@@ -219,7 +342,7 @@ const List = Actor.make('List', {
219
342
  });
220
343
  ```
221
344
 
222
- - `invoke` sits beside the `children` it feeds, and says which keys exist, the Input each new Child starts from, and the Props each is handed. After every Update, a new key Invokes a Row, a key gone stops it, and a key kept keeps its Instance. From then on the Row owns its data.
345
+ - A Child is written as a Worker is: its `actor`, then always, `while` a test is true, or `each` key a function names, one Instance per key. Its `input` and `props` are worked out from the parent's data and the Child's key, `''` unless it is one of `each`. After every Update, a new key Invokes a Row, a key gone stops it, and a key kept keeps its Instance. From then on the Row owns its data. A Child written with `while` stops when its test turns false and comes back as a fresh Instance.
223
346
  - Props are what the parent says now, worked out again after each of its Updates: the Row declares them with `props` beside `input`, and its Update, its Workers' Conditions and its View read them. It never writes them, and a change runs none of its rules. Props equal to the last ones keep the Instance; new ones are not in the History, since Replay works them out again from the parent.
224
347
  - Instance IDs are deterministic: `List/rows[0]#1` is the first `rows` keyed `0`. A key Invoked again gets `#2`, so a Message meant for the old Instance is dropped.
225
348
  - A Command is an errand, made once with `Command.make`: a name, the Schema of its args and the Effect it runs from them, ending with at most one Message. The Update asks for it with its args, `save({ id })`, which is plain data a test can compare; the args are checked when it runs. Nothing stops it but its Instance stopping, and there is no cancel. An Update may return a list of Commands; they run concurrently.
@@ -229,7 +352,7 @@ const List = Actor.make('List', {
229
352
  ### Drawing it with React
230
353
 
231
354
  ```tsx
232
- export const AuthView = View.make(Auth, ({ _tag, state, children }) => {
355
+ export const AuthView = View.make(AuthLive, ({ _tag, state, children }) => {
233
356
  switch (_tag) {
234
357
  case 'Checking':
235
358
  return <Spinner />;
@@ -245,17 +368,17 @@ export const AuthView = View.make(Auth, ({ _tag, state, children }) => {
245
368
  }
246
369
  });
247
370
 
248
- const RowView = View.make(Row, ({ model, props, root }) => (
371
+ const RowView = View.make(RowLive, ({ model, props, root }) => (
249
372
  <li {...root} data-uploading={props.uploading}>
250
373
  {model.text}
251
374
  </li>
252
375
  ));
253
376
  const MotionRow = motion.create(RowView);
254
377
 
255
- const DemoApp = toReact(Auth, AuthView, ServerLive);
378
+ const DemoApp = toReact(AuthLive, AuthView, ServerLive);
256
379
  ```
257
380
 
258
- - One function draws every State. It gets `_tag`, `model`, `state`, `props`, `children` (Handles; arrays for keyed Children, each with its `key`), `send` and `root`; a `switch` on `_tag` narrows `state` and `children`. The DOM stays across a Transition. It never sees Capabilities, so it draws a Replay exactly like the live app.
381
+ - One function draws every State. It gets `_tag`, `model`, `state`, `props`, `children` (Handles: one for a Child that is always there, one or `undefined` for a `while` Child, a list for an `each` Child, each with its `key`), `send` and `root`; a `switch` on `_tag` narrows `state` and `children`. The DOM stays across a Transition. It never sees Capabilities, so it draws a Replay exactly like the live app.
259
382
  - A Child is placed with `<RowView instance={handle} />`. A parent View hands it only where to draw; data from the parent is the Row's Props, which the parent Actor hands it, so its Update and Workers see the same.
260
383
  - Spreading `root` on the View's own element hands it the parent's `ref` and `style`, so `motion.create(RowView)` animates it, with no wrapper element, and it stays memoized. A View whose Instance has stopped keeps drawing its last data, so `AnimatePresence` can play its exit.
261
384
  - A View re-renders only when its own Instance's Model, State, Props or set of Children changes, or its `ref` or `style` does. Many Messages handled in a row make one render.
@@ -267,9 +390,9 @@ const DemoApp = toReact(Auth, AuthView, ServerLive);
267
390
  ### Drawing it before it runs
268
391
 
269
392
  ```tsx
270
- const DemoApp = toReact(Auth, AuthView, ServerLive, { saved });
393
+ const DemoApp = toReact(AuthLive, AuthView, ServerLive, { saved });
271
394
  ```
272
395
 
273
396
  - The app is drawn before any Runtime exists: with no History, right after init; with a saved one, at its Head, replayed through Suspense. A server or a static build gets the same HTML the client hydrates, and `useRuntime` reads the saved History from the start, so a Timeline is drawn there too. Until the Runtime starts, a Send is dropped.
274
- - `saved` is what `history.save()` gives: its entries and its Head, each Message, and each Instance of a Restore's Snapshot, written through its Actor's Schemas and read back through them on load. So the encoded side of every Schema must be JSON-safe, and then it is plain JSON: a `Date` as `Schema.DateFromString`, an `Option` as `Schema.OptionFromNullOr`. A saved History never changes, and one whose Head is not one of its entries fails to load. The Runtime carries on live at the Head, with Time going on from the Head's. `History.restored(Auth, snapshot, at).save()` makes the lightest one, a History of one Restore right after init, for an app that saves only its Snapshot; init stays the first Step. Where the History is kept is the app's business.
397
+ - `saved` is what `history.save()` gives: its entries and its Head, each Message, and each Instance of a Restore's Snapshot, written through its Actor's Schemas and read back through them on load. So the encoded side of every Schema must be JSON-safe, and then it is plain JSON: a `Date` as `Schema.DateFromString`, an `Option` as `Schema.OptionFromNullOr`. A saved History never changes, and one whose Head is not one of its entries fails to load. The Runtime carries on live at the Head, with Time going on from the Head's. `History.restored(AuthLive, snapshot, at).save()` makes the lightest one, a History of one Restore right after init, for an app that saves only its Snapshot; init stays the first Step. Where the History is kept is the app's business. Give `window` to keep only that many entries on the Head's Branch: the oldest kept becomes a Restore of the Snapshot right after it, and Time Travel reaches nothing before it. `history.keep(n)` changes it at any time, `history.keep(null)` stops Compacting. An app made with `toReact` remembers a Window changed that way in `localStorage` under its name, and starts from it after a reload, over the `window` it was given.
275
398
  - When the last mount closes, the History is left under the app's name, the root Actor's by default, and the next mount of an app with that name carries on from it: the same component mounted again, or a new one after a hot reload, whose code replays the old Messages. A Message the new code handles differently warns and goes on. Give `name` when two apps share a root Actor and must not share a History; two apps of one name mounted at once is a console error.
@@ -1,13 +1,20 @@
1
- import type { Actor as ActorOf, AnyActor, Behavior, KidsByState, Many, OpenOfBehavior, Requires, Single, Tagged } from './types.ts';
1
+ import type { Actor as ActorOf, Behavior, KidsByState, OpenOfBehavior, Requires, Single, Tagged } from './types.ts';
2
2
  import { Schema } from 'effect';
3
- /** An Actor's Schemas, waiting for the behavior that runs it. */
3
+ /**
4
+ * What an Actor is, as `Actor.define` gives it: its name, and the Schemas
5
+ * and Requires every type is fixed by. It runs nothing: `Actor.build` adds
6
+ * how it behaves.
7
+ */
4
8
  export interface Defined<Name extends string, Input, Props, Model, State extends Tagged, Msg extends Tagged, R extends Requires> {
5
- readonly build: <const B extends Behavior<Input, Props, Model, State, Msg, R, B>>(behavior: B) => ActorOf<Name, Input, Props, Model, State, Msg, KidsByState<State, B>, OpenOfBehavior<R, B>>;
9
+ readonly name: Name;
10
+ readonly shape: Shape<Input, Props, Model, State, Msg, R>;
6
11
  }
12
+ /** Any Actor's definition, loosely. */
13
+ export type AnyDefined = Defined<string, any, any, any, any, any, any>;
7
14
  /** A Schema Kabuki can read and write without Capabilities and at once. */
8
15
  type Codec<T> = Schema.Codec<T, unknown, never, never>;
9
16
  /**
10
- * What `make` takes: every type the behavior is checked against, as codecs,
17
+ * What `define` takes: every type the behavior is checked against, as codecs,
11
18
  * and the Capabilities the Actor's own code may use. Every value is checked
12
19
  * against them too, as it is made: each Input and Props, each Model and
13
20
  * State from init or an Update, and each Message as it is Sent. A saved
@@ -25,18 +32,22 @@ export interface Shape<Input, Props, Model, State, Msg, R extends Requires> {
25
32
  readonly message?: Codec<Msg>;
26
33
  readonly state?: Codec<State>;
27
34
  }
28
- declare function make<const Name extends string, State extends Tagged = Single, Model = {}, Msg extends Tagged = never, const R extends Requires = readonly [], Input = void, Props = void>(name: Name, shape: Shape<Input, Props, Model, State, Msg, R>): Defined<Name, Input, Props, Model, State, Msg, R>;
29
- /** A keyed Child slot: the parent Invokes one Instance of `actor` per key. */
30
- declare const many: <A extends AnyActor>(actor: A) => Many<A>;
35
+ declare function define<const Name extends string, State extends Tagged = Single, Model = {}, Msg extends Tagged = never, const R extends Requires = readonly [], Input = void, Props = void>(name: Name, shape: Shape<Input, Props, Model, State, Msg, R>): Defined<Name, Input, Props, Model, State, Msg, R>;
36
+ /** How the Actor `D` defines may be built, as written in `B`. */
37
+ export type BehaviorOf<D, B> = D extends Defined<any, infer Input, infer Props, infer Model, infer State, infer Msg, infer R> ? Behavior<Input, Props, Model, State, Msg, R, B> : never;
38
+ /** The Actor `D` defines, built with `B`. */
39
+ export type BuiltOf<D, B> = D extends Defined<infer Name, infer Input, infer Props, infer Model, infer State, infer Msg, infer R> ? ActorOf<Name, Input, Props, Model, State, Msg, KidsByState<State, B>, OpenOfBehavior<R, B>> : never;
40
+ declare function build<D extends AnyDefined, const B extends BehaviorOf<D, B>>(definition: D, behavior: B): BuiltOf<D, B>;
31
41
  /**
32
- * An Actor, in two steps. `make` takes its Schemas and Requires, which fixes
33
- * every type. `build` takes how it behaves, at the top for as long as the
34
- * Instance lives and in one block per State for as long as that State lasts:
35
- * its Provides, Children, Invocation, Updates under `on`, and Workers.
42
+ * An Actor, in two steps. `define` takes what it is: its Schemas and
43
+ * Requires, which fix every type. `build` takes a definition and how it
44
+ * behaves, at the top for as long as the Instance lives and in one block per
45
+ * State for as long as that State lasts: its Provides, Children, Updates
46
+ * under `on`, and Workers.
36
47
  */
37
48
  export declare const Actor: {
38
- make: typeof make;
39
- many: typeof many;
49
+ define: typeof define;
50
+ build: typeof build;
40
51
  };
41
52
  export {};
42
53
  //# sourceMappingURL=actor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"actor.d.ts","sourceRoot":"","sources":["../../../src/core/actor/actor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,IAAI,OAAO,EAChB,QAAQ,EACR,QAAQ,EAKR,WAAW,EACX,IAAI,EACJ,cAAc,EACd,QAAQ,EACR,MAAM,EAGN,MAAM,EAEP,MAAM,YAAY,CAAC;AACpB,OAAO,EAAU,MAAM,EAAa,MAAM,QAAQ,CAAC;AAEnD,iEAAiE;AACjE,MAAM,WAAW,OAAO,CACtB,IAAI,SAAS,MAAM,EACnB,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,SAAS,MAAM,EACpB,GAAG,SAAS,MAAM,EAClB,CAAC,SAAS,QAAQ;IAElB,QAAQ,CAAC,KAAK,EAAE,CACd,KAAK,CAAC,CAAC,SAAS,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAE/D,QAAQ,EAAE,CAAC,KACR,OAAO,CACV,IAAI,EACJ,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,GAAG,EACH,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,EACrB,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CACrB,CAAC;CACH;AAED,2EAA2E;AAC3E,KAAK,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAEvD;;;;;;;GAOG;AACH,MAAM,WAAW,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS,QAAQ;IACxE,6FAA6F;IAC7F,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACtB,iFAAiF;IACjF,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,mHAAmH;IACnH,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;CAC/B;AAED,iBAAS,IAAI,CACX,KAAK,CAAC,IAAI,SAAS,MAAM,EACzB,KAAK,SAAS,MAAM,GAAG,MAAM,EAC7B,KAAK,GAAG,EAAE,EACV,GAAG,SAAS,MAAM,GAAG,KAAK,EAC1B,KAAK,CAAC,CAAC,SAAS,QAAQ,GAAG,SAAS,EAAE,EACtC,KAAK,GAAG,IAAI,EACZ,KAAK,GAAG,IAAI,EAEZ,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,GAC/C,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AAmNrD,8EAA8E;AAC9E,QAAA,MAAM,IAAI,GAAI,CAAC,SAAS,QAAQ,SAAS,CAAC,KAAG,IAAI,CAAC,CAAC,CAGjD,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,KAAK;;;CAAiB,CAAC"}
1
+ {"version":3,"file":"actor.d.ts","sourceRoot":"","sources":["../../../src/core/actor/actor.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,11 @@
1
1
  import { Effect, Schema, SchemaAST } from 'effect';
2
- function make(name, shape) {
2
+ function define(name, shape) {
3
+ return { name, shape };
4
+ }
5
+ function build(definition, behavior) {
3
6
  return {
4
- build: (behavior) => ({
5
- name,
6
- definition: definitionOf(name, shape, behavior),
7
- }),
7
+ name: definition.name,
8
+ definition: definitionOf(definition.name, definition.shape, behavior),
8
9
  };
9
10
  }
10
11
  /** The plain definition the engine works from, out of the Schemas and the levels. */
@@ -14,7 +15,6 @@ const definitionOf = (name, shape, behavior) => {
14
15
  const top = slots(behavior.children);
15
16
  const lasting = Object.keys(top);
16
17
  const children = {};
17
- const invoke = {};
18
18
  const update = {};
19
19
  const stateProvides = {};
20
20
  const workers = {};
@@ -35,7 +35,6 @@ const definitionOf = (name, shape, behavior) => {
35
35
  if (slot in top)
36
36
  throw new Error(`[@kestack/kabuki] ${name}: Child "${slot}" is written at the top and in ${tag}`);
37
37
  children[tag] = { ...top, ...own };
38
- invoke[tag] = merged(behavior.invoke, block.invoke);
39
38
  if (block.on)
40
39
  update[tag] = block.on;
41
40
  stateProvides[tag] = block.provides;
@@ -70,17 +69,36 @@ const definitionOf = (name, shape, behavior) => {
70
69
  stateProvides,
71
70
  children,
72
71
  lasting,
73
- invoke,
74
72
  };
75
73
  };
76
74
  const slots = (children) => Object.fromEntries(Object.entries(children ?? {}).map(([slot, child]) => [
77
75
  slot,
78
- isMany(child)
79
- ? { definition: child.actor.definition, many: true }
80
- : { definition: child.definition, many: false },
76
+ slotOf(child),
81
77
  ]));
82
- /** The top-level Invocation and a State's own, as one. */
83
- const merged = (top, own) => !top ? own : !own ? top : (data) => ({ ...top(data), ...own(data) });
78
+ const ONE = [''];
79
+ const NONE = [];
80
+ const NOTHING = () => undefined;
81
+ /**
82
+ * A Child as the keys its Condition names, the way a Worker is: one, `''`,
83
+ * for every kind but `each`, or its `key` if it names one.
84
+ */
85
+ const slotOf = (child) => {
86
+ const exists = child.while;
87
+ const key = child.key;
88
+ const one = key ? (data) => [key(data)] : () => ONE;
89
+ return {
90
+ definition: child.actor.definition,
91
+ kind: child.each ? 'each' : exists ? 'while' : 'always',
92
+ keyed: key !== undefined,
93
+ keys: child.each
94
+ ? child.each
95
+ : exists
96
+ ? (data) => (exists(data) ? one(data) : NONE)
97
+ : one,
98
+ input: (child.input ?? NOTHING),
99
+ props: (child.props ?? NOTHING),
100
+ };
101
+ };
84
102
  /**
85
103
  * The State tags: a tagged union's cases, else every State a block is
86
104
  * written for. An Actor without States has the one, `Single`.
@@ -124,8 +142,6 @@ const tagsOf = (schema) => {
124
142
  : [])
125
143
  : []);
126
144
  };
127
- const ONE = [''];
128
- const NONE = [];
129
145
  /**
130
146
  * A Worker's Condition as the keys it names: one, `''`, for every kind but
131
147
  * `each`. Written in a State's block, it names none outside that State.
@@ -153,16 +169,11 @@ const workerOf = (worker, state) => {
153
169
  run,
154
170
  };
155
171
  };
156
- const isMany = (slot) => '_tag' in slot && slot._tag === 'Many';
157
- /** A keyed Child slot: the parent Invokes one Instance of `actor` per key. */
158
- const many = (actor) => ({
159
- _tag: 'Many',
160
- actor,
161
- });
162
172
  /**
163
- * An Actor, in two steps. `make` takes its Schemas and Requires, which fixes
164
- * every type. `build` takes how it behaves, at the top for as long as the
165
- * Instance lives and in one block per State for as long as that State lasts:
166
- * its Provides, Children, Invocation, Updates under `on`, and Workers.
173
+ * An Actor, in two steps. `define` takes what it is: its Schemas and
174
+ * Requires, which fix every type. `build` takes a definition and how it
175
+ * behaves, at the top for as long as the Instance lives and in one block per
176
+ * State for as long as that State lasts: its Provides, Children, Updates
177
+ * under `on`, and Workers.
167
178
  */
168
- export const Actor = { make, many };
179
+ export const Actor = { define, build };
@@ -1,6 +1,6 @@
1
1
  export { Actor } from './actor.ts';
2
2
  export { Command } from './command.ts';
3
3
  export { RUN } from './types.ts';
4
- export type { Defined } from './actor.ts';
5
- export type { ActorOf, AnyActor, Data, ActorDefinition, Encoding, Many, Only, Self, SlotDefinition, Tagged, Types, Worker, WorkerDefinition, Workers, } from './types.ts';
4
+ export type { AnyDefined, Defined } from './actor.ts';
5
+ export type { ActorOf, ActorType, AnyActor, Behavior, Child, Data, ActorDefinition, Encoding, KidsByState, Only, OpenOfBehavior, Requires, Self, SlotDefinition, Tagged, Types, Worker, WorkerDefinition, Workers, } from './types.ts';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/actor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACjC,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EACV,OAAO,EACP,QAAQ,EACR,IAAI,EACJ,eAAe,EACf,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,cAAc,EACd,MAAM,EACN,KAAK,EACL,MAAM,EACN,gBAAgB,EAChB,OAAO,GACR,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/actor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACjC,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACtD,YAAY,EACV,OAAO,EACP,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,IAAI,EACJ,eAAe,EACf,QAAQ,EACR,WAAW,EACX,IAAI,EACJ,cAAc,EACd,QAAQ,EACR,IAAI,EACJ,cAAc,EACd,MAAM,EACN,KAAK,EACL,MAAM,EACN,gBAAgB,EAChB,OAAO,GACR,MAAM,YAAY,CAAC"}