foldkit 0.156.0 → 0.157.0

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 (201) hide show
  1. package/README.md +3 -3
  2. package/dist/asyncData/asyncData.d.ts +7 -7
  3. package/dist/asyncData/asyncData.d.ts.map +1 -1
  4. package/dist/asyncData/asyncData.js +12 -12
  5. package/dist/calendar/calendarDate.d.ts +15 -15
  6. package/dist/calendar/calendarDate.d.ts.map +1 -1
  7. package/dist/calendar/calendarDate.js +14 -14
  8. package/dist/calendar/comparison.d.ts +2 -2
  9. package/dist/calendar/comparison.d.ts.map +1 -1
  10. package/dist/calendar/comparison.js +5 -5
  11. package/dist/calendar/info.d.ts +2 -2
  12. package/dist/calendar/info.d.ts.map +1 -1
  13. package/dist/calendar/info.js +2 -2
  14. package/dist/calendar/locale.d.ts +7 -7
  15. package/dist/calendar/locale.d.ts.map +1 -1
  16. package/dist/calendar/locale.js +23 -23
  17. package/dist/canvas/shape.d.ts +89 -89
  18. package/dist/canvas/shape.d.ts.map +1 -1
  19. package/dist/canvas/shape.js +65 -53
  20. package/dist/command/index.d.ts +3 -3
  21. package/dist/customElement/index.d.ts +2 -2
  22. package/dist/customElement/index.js +2 -2
  23. package/dist/devTools/protocol.d.ts +278 -278
  24. package/dist/devTools/protocol.d.ts.map +1 -1
  25. package/dist/devTools/protocol.js +98 -92
  26. package/dist/devTools/schemaSummarize.d.ts.map +1 -1
  27. package/dist/devTools/schemaSummarize.js +24 -24
  28. package/dist/devTools/serialize.d.ts +1 -1
  29. package/dist/devTools/serialize.d.ts.map +1 -1
  30. package/dist/devTools/serialize.js +10 -10
  31. package/dist/devTools/store.d.ts.map +1 -1
  32. package/dist/devTools/store.js +52 -28
  33. package/dist/devTools/submodelPath.d.ts.map +1 -1
  34. package/dist/devTools/submodelPath.js +3 -3
  35. package/dist/devTools/summarize.d.ts +6 -6
  36. package/dist/devTools/summarize.d.ts.map +1 -1
  37. package/dist/devTools/summarize.js +13 -13
  38. package/dist/devTools/webSocketBridge.d.ts +3 -3
  39. package/dist/devTools/webSocketBridge.d.ts.map +1 -1
  40. package/dist/devTools/webSocketBridge.js +8 -8
  41. package/dist/dom/dom.d.ts +2 -0
  42. package/dist/dom/dom.d.ts.map +1 -1
  43. package/dist/dom/dom.js +47 -13
  44. package/dist/experimental/machine/machine.d.ts +29 -6
  45. package/dist/experimental/machine/machine.d.ts.map +1 -1
  46. package/dist/experimental/machine/machine.js +9 -8
  47. package/dist/experimental/server/entry.js +2 -2
  48. package/dist/experimental/server/serialize.js +2 -2
  49. package/dist/experimental/server/server.js +4 -4
  50. package/dist/fieldValidation/fieldValidation.d.ts +12 -12
  51. package/dist/fieldValidation/fieldValidation.d.ts.map +1 -1
  52. package/dist/fieldValidation/fieldValidation.js +9 -9
  53. package/dist/fieldValidation/rule.d.ts +2 -2
  54. package/dist/fieldValidation/rule.d.ts.map +1 -1
  55. package/dist/fieldValidation/rule.js +6 -6
  56. package/dist/file/file.d.ts +3 -3
  57. package/dist/file/file.d.ts.map +1 -1
  58. package/dist/file/file.js +3 -3
  59. package/dist/html/boundary.d.ts +93 -36
  60. package/dist/html/boundary.d.ts.map +1 -1
  61. package/dist/html/boundary.js +242 -75
  62. package/dist/html/childAttribute.d.ts +6 -4
  63. package/dist/html/childAttribute.d.ts.map +1 -1
  64. package/dist/html/childAttribute.js +7 -1
  65. package/dist/html/index.d.ts +31 -16
  66. package/dist/html/index.d.ts.map +1 -1
  67. package/dist/html/index.js +97 -40
  68. package/dist/html/lazy.d.ts +6 -6
  69. package/dist/html/lazy.d.ts.map +1 -1
  70. package/dist/html/lazy.js +37 -15
  71. package/dist/html/public.d.ts +1 -1
  72. package/dist/html/public.d.ts.map +1 -1
  73. package/dist/html/runtimeSingleton.d.ts +27 -6
  74. package/dist/html/runtimeSingleton.d.ts.map +1 -1
  75. package/dist/html/runtimeSingleton.js +46 -29
  76. package/dist/html/submodel.d.ts.map +1 -1
  77. package/dist/html/submodel.js +28 -39
  78. package/dist/http/http.d.ts +1 -1
  79. package/dist/http/http.js +1 -1
  80. package/dist/managedResource/managedResource.d.ts +5 -5
  81. package/dist/managedResource/managedResource.js +3 -3
  82. package/dist/mount/index.d.ts +92 -39
  83. package/dist/mount/index.d.ts.map +1 -1
  84. package/dist/mount/index.js +28 -8
  85. package/dist/mount/public.d.ts +1 -1
  86. package/dist/mount/public.d.ts.map +1 -1
  87. package/dist/mount/public.js +1 -1
  88. package/dist/navigation/urlRequest.d.ts +9 -9
  89. package/dist/navigation/urlRequest.d.ts.map +1 -1
  90. package/dist/navigation/urlRequest.js +2 -2
  91. package/dist/onUnmountModule.d.ts +19 -0
  92. package/dist/onUnmountModule.d.ts.map +1 -0
  93. package/dist/onUnmountModule.js +80 -0
  94. package/dist/port/port.d.ts +5 -5
  95. package/dist/port/port.js +5 -5
  96. package/dist/route/parser.d.ts +2 -2
  97. package/dist/route/parser.js +2 -2
  98. package/dist/runtime/hmrProtocol.d.ts +10 -10
  99. package/dist/runtime/hmrProtocol.d.ts.map +1 -1
  100. package/dist/runtime/hmrProtocol.js +10 -10
  101. package/dist/runtime/runtime.d.ts +4 -4
  102. package/dist/runtime/runtime.d.ts.map +1 -1
  103. package/dist/runtime/runtime.js +168 -51
  104. package/dist/schema/index.d.ts +41 -29
  105. package/dist/schema/index.d.ts.map +1 -1
  106. package/dist/schema/index.js +9 -9
  107. package/dist/snabbdom/init.d.ts +1 -1
  108. package/dist/snabbdom/init.d.ts.map +1 -1
  109. package/dist/snabbdom/init.js +5 -1
  110. package/dist/snabbdom/vnode.d.ts +1 -0
  111. package/dist/snabbdom/vnode.d.ts.map +1 -1
  112. package/dist/snabbdom/vnode.js +1 -0
  113. package/dist/subscription/animationFrame.d.ts +3 -3
  114. package/dist/subscription/animationFrame.d.ts.map +1 -1
  115. package/dist/subscription/animationFrame.js +2 -2
  116. package/dist/subscription/fromEvent.d.ts +2 -2
  117. package/dist/subscription/fromEvent.js +2 -2
  118. package/dist/subscription/subscription.d.ts +3 -3
  119. package/dist/subscription/subscription.js +1 -1
  120. package/dist/test/apps/bubbling.d.ts +6 -6
  121. package/dist/test/apps/bubbling.d.ts.map +1 -1
  122. package/dist/test/apps/bubbling.js +6 -6
  123. package/dist/test/apps/colorPicker.d.ts +7 -7
  124. package/dist/test/apps/colorPicker.d.ts.map +1 -1
  125. package/dist/test/apps/colorPicker.js +5 -5
  126. package/dist/test/apps/contextMenu.d.ts +5 -5
  127. package/dist/test/apps/contextMenu.d.ts.map +1 -1
  128. package/dist/test/apps/contextMenu.js +4 -4
  129. package/dist/test/apps/counter.d.ts +8 -8
  130. package/dist/test/apps/counter.d.ts.map +1 -1
  131. package/dist/test/apps/counter.js +8 -8
  132. package/dist/test/apps/crashOnRender.d.ts +18 -18
  133. package/dist/test/apps/crashOnRender.d.ts.map +1 -1
  134. package/dist/test/apps/crashOnRender.js +11 -11
  135. package/dist/test/apps/drafts.d.ts +9 -9
  136. package/dist/test/apps/drafts.d.ts.map +1 -1
  137. package/dist/test/apps/drafts.js +6 -6
  138. package/dist/test/apps/feedSocket.d.ts +6 -6
  139. package/dist/test/apps/feedSocket.d.ts.map +1 -1
  140. package/dist/test/apps/feedSocket.js +8 -8
  141. package/dist/test/apps/fileUpload.d.ts +2 -2
  142. package/dist/test/apps/fileUpload.d.ts.map +1 -1
  143. package/dist/test/apps/fileUpload.js +2 -2
  144. package/dist/test/apps/focusBoundary.d.ts +3 -3
  145. package/dist/test/apps/focusBoundary.d.ts.map +1 -1
  146. package/dist/test/apps/focusBoundary.js +3 -3
  147. package/dist/test/apps/formChild.d.ts +11 -11
  148. package/dist/test/apps/formChild.d.ts.map +1 -1
  149. package/dist/test/apps/formChild.js +13 -12
  150. package/dist/test/apps/interactions.d.ts +8 -8
  151. package/dist/test/apps/interactions.d.ts.map +1 -1
  152. package/dist/test/apps/interactions.js +8 -8
  153. package/dist/test/apps/keypress.d.ts +6 -6
  154. package/dist/test/apps/keypress.d.ts.map +1 -1
  155. package/dist/test/apps/keypress.js +6 -6
  156. package/dist/test/apps/login.d.ts +11 -11
  157. package/dist/test/apps/login.d.ts.map +1 -1
  158. package/dist/test/apps/login.js +15 -15
  159. package/dist/test/apps/logoutButton.d.ts +3 -3
  160. package/dist/test/apps/logoutButton.d.ts.map +1 -1
  161. package/dist/test/apps/logoutButton.js +2 -2
  162. package/dist/test/apps/mountPanel.d.ts +9 -9
  163. package/dist/test/apps/mountPanel.d.ts.map +1 -1
  164. package/dist/test/apps/mountPanel.js +9 -9
  165. package/dist/test/apps/multiRole.d.ts +3 -3
  166. package/dist/test/apps/multiRole.d.ts.map +1 -1
  167. package/dist/test/apps/multiRole.js +2 -2
  168. package/dist/test/apps/pointer.d.ts +7 -7
  169. package/dist/test/apps/pointer.d.ts.map +1 -1
  170. package/dist/test/apps/pointer.js +7 -7
  171. package/dist/test/apps/resumeUpload.d.ts +8 -8
  172. package/dist/test/apps/resumeUpload.d.ts.map +1 -1
  173. package/dist/test/apps/resumeUpload.js +7 -7
  174. package/dist/test/apps/scorePanel.d.ts +3 -3
  175. package/dist/test/apps/scorePanel.d.ts.map +1 -1
  176. package/dist/test/apps/scorePanel.js +2 -2
  177. package/dist/test/apps/selectiveKeys.d.ts +3 -3
  178. package/dist/test/apps/selectiveKeys.d.ts.map +1 -1
  179. package/dist/test/apps/selectiveKeys.js +3 -3
  180. package/dist/test/apps/uploads.d.ts +18 -18
  181. package/dist/test/apps/uploads.d.ts.map +1 -1
  182. package/dist/test/apps/uploads.js +13 -13
  183. package/dist/test/matchers.d.ts.map +1 -1
  184. package/dist/test/matchers.js +4 -4
  185. package/dist/test/query.d.ts.map +1 -1
  186. package/dist/test/query.js +28 -28
  187. package/dist/test/scene.d.ts +37 -8
  188. package/dist/test/scene.d.ts.map +1 -1
  189. package/dist/test/scene.js +58 -15
  190. package/dist/test/story.d.ts +35 -8
  191. package/dist/test/story.d.ts.map +1 -1
  192. package/dist/test/story.js +44 -22
  193. package/dist/update/update.d.ts +17 -20
  194. package/dist/update/update.d.ts.map +1 -1
  195. package/dist/url/index.d.ts +8 -8
  196. package/dist/url/index.d.ts.map +1 -1
  197. package/dist/url/index.js +19 -19
  198. package/dist/vdom.d.ts +3 -2
  199. package/dist/vdom.d.ts.map +1 -1
  200. package/dist/vdom.js +16 -6
  201. package/package.json +1 -1
@@ -1,15 +1,15 @@
1
1
  import { type VNode } from '../vdom.js';
2
2
  /** Creates a memoization slot for a view function. On each render, if the
3
- * function reference, dispatch, and all arguments are referentially equal
4
- * (`===`) to the previous call, the cached VNode is returned without
3
+ * function reference, dispatchers, Mount render owner, and all arguments are
4
+ * equal to the previous call, the cached VNode is returned without
5
5
  * re-running the view function. Snabbdom's `patchVnode` short-circuits when
6
6
  * it sees the same VNode reference, so both VNode construction and subtree
7
7
  * diffing are skipped.
8
8
  *
9
- * Dispatch is part of the cache key because event handlers in the cached
10
- * VNode close over the dispatch active when the VNode was built. Returning
11
- * a VNode built under a different dispatch would silently misroute every
12
- * event from that subtree.
9
+ * Dispatchers and Mount render ownership are part of the cache key because
10
+ * event handlers and Mounts in the cached VNode close over the frame active
11
+ * when the VNode was built. Returning a VNode built under a different frame
12
+ * would silently misroute events or retain the wrong Mount lifecycle owner.
13
13
  *
14
14
  * The cached VNode must be rendered at a single position in the tree.
15
15
  * Snabbdom tracks the real DOM through each VNode's mutable `.elm` field
@@ -1 +1 @@
1
- {"version":3,"file":"lazy.d.ts","sourceRoot":"","sources":["../../src/html/lazy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,KAAK,EAAwC,MAAM,YAAY,CAAA;AAmF7E;;;;;;;;;;;;;;;;;oCAiBoC;AACpC,eAAO,MAAM,UAAU,QAAO,CAAC,CAAC,IAAI,SAAS,aAAa,CAAC,OAAO,CAAC,EACjE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,KAAK,GAAG,IAAI,EACnC,IAAI,EAAE,IAAI,KACP,KAAK,GAAG,IAAI,CAUhB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;iDAsBiD;AACjD,eAAO,MAAM,eAAe,QAAO,CAAC,CAAC,IAAI,SAAS,aAAa,CAAC,OAAO,CAAC,EACtE,GAAG,EAAE,WAAW,EAChB,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,KAAK,GAAG,IAAI,EACnC,IAAI,EAAE,IAAI,KACP,KAAK,GAAG,IAAI,CAWhB,CAAA"}
1
+ {"version":3,"file":"lazy.d.ts","sourceRoot":"","sources":["../../src/html/lazy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,KAAK,EAAwC,MAAM,YAAY,CAAA;AAyG7E;;;;;;;;;;;;;;;;;oCAiBoC;AACpC,eAAO,MAAM,UAAU,QAAO,CAAC,CAAC,IAAI,SAAS,aAAa,CAAC,OAAO,CAAC,EACjE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,KAAK,GAAG,IAAI,EACnC,IAAI,EAAE,IAAI,KACP,KAAK,GAAG,IAAI,CAUhB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;iDAsBiD;AACjD,eAAO,MAAM,eAAe,QAAO,CAAC,CAAC,IAAI,SAAS,aAAa,CAAC,OAAO,CAAC,EACtE,GAAG,EAAE,WAAW,EAChB,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,KAAK,GAAG,IAAI,EACnC,IAAI,EAAE,IAAI,KACP,KAAK,GAAG,IAAI,CAehB,CAAA"}
package/dist/html/lazy.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Predicate } from 'effect';
2
2
  import { dedupeMemoizedResult, memoizedVNodes } from '../vdom.js';
3
- import { beginLazyTracking, endLazyTracking, markSeenForLazyHit, } from './boundary.js';
4
- import { requireBoundary, requireDispatch, } from './runtimeSingleton.js';
3
+ import { beginLazyTracking, endLazyTracking, registerBoundaryWrapTransactionRollback, restoreBoundaryWrapsForLazyHit, } from './boundary.js';
4
+ import { requireBoundary, requireDispatch, requireMountDispatch, requireMountRenderOwner, } from './runtimeSingleton.js';
5
5
  const argsEqual = (previous, current) => {
6
6
  if (previous.length !== current.length) {
7
7
  return false;
@@ -15,16 +15,24 @@ const argsEqual = (previous, current) => {
15
15
  };
16
16
  const resolveOrCache = (previousEntry, fn, args, onCache) => {
17
17
  const dispatch = requireDispatch();
18
+ const mountDispatch = requireMountDispatch();
19
+ const mountRenderOwner = requireMountRenderOwner();
18
20
  const { registry } = requireBoundary();
19
- // NOTE: dispatch identity in the cache key matters for the DevTools
20
- // jumpTo path: a replay render installs `noOpDispatch`, and without
21
- // this check a subsequent live render could return a vnode whose
22
- // handlers still reference the noOp.
21
+ // NOTE: dispatcher identities and Mount render ownership belong in the
22
+ // cache key because the cached VNode closes over them. Current frame
23
+ // construction makes the Mount dispatcher identity derivable from the
24
+ // ordinary dispatcher's owner and boundary, so the second identity cannot
25
+ // change a cache decision today. Keeping both roles explicit prevents a
26
+ // future renderer that separates them from retaining stale handler or Mount
27
+ // lifecycle closures. Custom renderers can also use one dispatcher for both
28
+ // owners, so the owner remains a separate key member.
23
29
  if (Predicate.isNotUndefined(previousEntry) &&
24
30
  previousEntry.fn === fn &&
25
31
  previousEntry.dispatch === dispatch &&
32
+ previousEntry.mountDispatch === mountDispatch &&
33
+ previousEntry.mountRenderOwner === mountRenderOwner &&
26
34
  argsEqual(previousEntry.args, args)) {
27
- markSeenForLazyHit(registry, previousEntry.trackedBoundaries);
35
+ restoreBoundaryWrapsForLazyHit(registry, previousEntry.trackedBoundaries);
28
36
  return previousEntry.vnode;
29
37
  }
30
38
  const trackedBoundaries = beginLazyTracking(registry);
@@ -45,20 +53,29 @@ const resolveOrCache = (previousEntry, fn, args, onCache) => {
45
53
  if (Predicate.isNotNull(deduped)) {
46
54
  memoizedVNodes.add(deduped);
47
55
  }
48
- onCache({ fn, args, dispatch, vnode: deduped, trackedBoundaries });
56
+ onCache({
57
+ fn,
58
+ args,
59
+ dispatch,
60
+ mountDispatch,
61
+ mountRenderOwner,
62
+ vnode: deduped,
63
+ trackedBoundaries,
64
+ });
65
+ registerBoundaryWrapTransactionRollback(registry, previousEntry, onCache);
49
66
  return deduped;
50
67
  };
51
68
  /** Creates a memoization slot for a view function. On each render, if the
52
- * function reference, dispatch, and all arguments are referentially equal
53
- * (`===`) to the previous call, the cached VNode is returned without
69
+ * function reference, dispatchers, Mount render owner, and all arguments are
70
+ * equal to the previous call, the cached VNode is returned without
54
71
  * re-running the view function. Snabbdom's `patchVnode` short-circuits when
55
72
  * it sees the same VNode reference, so both VNode construction and subtree
56
73
  * diffing are skipped.
57
74
  *
58
- * Dispatch is part of the cache key because event handlers in the cached
59
- * VNode close over the dispatch active when the VNode was built. Returning
60
- * a VNode built under a different dispatch would silently misroute every
61
- * event from that subtree.
75
+ * Dispatchers and Mount render ownership are part of the cache key because
76
+ * event handlers and Mounts in the cached VNode close over the frame active
77
+ * when the VNode was built. Returning a VNode built under a different frame
78
+ * would silently misroute events or retain the wrong Mount lifecycle owner.
62
79
  *
63
80
  * The cached VNode must be rendered at a single position in the tree.
64
81
  * Snabbdom tracks the real DOM through each VNode's mutable `.elm` field
@@ -98,6 +115,11 @@ export const createLazy = () => {
98
115
  export const createKeyedLazy = () => {
99
116
  const cache = new Map();
100
117
  return (key, fn, args) => resolveOrCache(cache.get(key), fn, args, entry => {
101
- cache.set(key, entry);
118
+ if (entry === undefined) {
119
+ cache.delete(key);
120
+ }
121
+ else {
122
+ cache.set(key, entry);
123
+ }
102
124
  });
103
125
  };
@@ -1,3 +1,3 @@
1
1
  export { childAttributes, ClickOptions, createKeyedLazy, createLazy, DefaultAction, EventPropagation, inertHtml, TextDirection, } from './index.js';
2
- export type { Attribute, ChildAttribute, Document, Html, HtmlBuilder, KeyboardModifiers, TagName, } from './index.js';
2
+ export type { Attribute, ChildAttribute, Document, Html, HtmlBuilder, KeyboardModifiers, TagName, TextareaAttribute, } from './index.js';
3
3
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/html/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,YAAY,EACZ,eAAe,EACf,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,SAAS,EACT,aAAa,GACd,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,IAAI,EACJ,WAAW,EACX,iBAAiB,EACjB,OAAO,GACR,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/html/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,YAAY,EACZ,eAAe,EACf,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,SAAS,EACT,aAAa,GACd,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,IAAI,EACJ,WAAW,EACX,iBAAiB,EACjB,OAAO,EACP,iBAAiB,GAClB,MAAM,YAAY,CAAA"}
@@ -2,8 +2,17 @@ import type { Context } from 'effect';
2
2
  import { type BoundaryId, type BoundaryRegistry } from './boundary.js';
3
3
  /** Synchronous message dispatcher provided to view-time element constructors. */
4
4
  export type DispatchSync = (message: unknown) => void;
5
+ /** Identifies which kind of render acquired a Mount. */
6
+ export type MountRenderOwner = 'Live' | 'Replay';
7
+ /** Resolves the render-owned dispatcher for a Mount at insertion time. */
8
+ export type MountDispatchResolver = Readonly<{
9
+ owner: MountRenderOwner;
10
+ resolve: () => DispatchSync;
11
+ }>;
5
12
  export type Frame = Readonly<{
6
13
  outerDispatch: DispatchSync;
14
+ mountOuterDispatch: DispatchSync;
15
+ mountRenderOwner: MountRenderOwner;
7
16
  runtimeContext: Context.Context<never>;
8
17
  boundaryRegistry: BoundaryRegistry;
9
18
  boundaryId: BoundaryId;
@@ -19,7 +28,7 @@ export type Frame = Readonly<{
19
28
  * omitted (e.g. crash views, test helpers that don't use Submodels), a
20
29
  * fresh empty registry is created. The frame starts in the root
21
30
  * boundary. */
22
- export declare const setRuntime: (dispatch: DispatchSync, runtimeContext: Context.Context<never>, boundaryRegistry?: BoundaryRegistry) => void;
31
+ export declare const setRuntime: (dispatch: DispatchSync, runtimeContext: Context.Context<never>, boundaryRegistry?: BoundaryRegistry, mountRenderOwner?: MountRenderOwner) => void;
23
32
  /** Pushes a new frame that inherits the current frame's dispatch, context,
24
33
  * and registry, but uses a different boundary. Used by `h.submodel` to
25
34
  * enter a child Submodel's wrapping context. Must be paired with
@@ -52,6 +61,12 @@ export declare const clearRuntime: () => void;
52
61
  * is a cached per-boundary dispatcher that applies the wrapping chain at
53
62
  * event-fire time. Throws when called outside of a runtime frame. */
54
63
  export declare const requireDispatch: () => DispatchSync;
64
+ /** Returns the render-owned root dispatcher for Mount results. A live render
65
+ * supplies live dispatch, while a historical render supplies no-op dispatch
66
+ * for acquisitions owned by that replay. */
67
+ export declare const requireMountDispatch: () => DispatchSync;
68
+ /** Returns whether the current frame is rendering the live or replayed view. */
69
+ export declare const requireMountRenderOwner: () => MountRenderOwner;
55
70
  /** A function that, given a message, resolves it through the current
56
71
  * boundary's wrapping chain immediately and returns a thunk that dispatches
57
72
  * the fully wrapped root message. */
@@ -62,12 +77,18 @@ export type UnmountResolver = (message: unknown) => () => void;
62
77
  * patch. Throws when called outside of a runtime frame. */
63
78
  export declare const requireUnmountResolver: () => UnmountResolver;
64
79
  /** Returns the current frame's Submodel wrapping chain (innermost first), or an
65
- * empty array at the root boundary. `OnMount` calls this at build time to
66
- * snapshot the lift a Submodel-embedded mount's result travels through in
67
- * production (via `ctx.dispatch`), so the Scene test harness can replay it when
68
- * the mount is resolved. Returns `[]` when there is no active frame, mirroring
69
- * the lazy tolerance of handler-free Html built outside a render. */
80
+ * empty array at the root boundary. `OnMount` records this build-time snapshot
81
+ * for the Scene test harness, which replays the chain when the Mount is
82
+ * resolved. Production Mount dispatch uses the ownership-aware resolver below.
83
+ * Returns `[]` when there is no active frame, mirroring the lazy tolerance of
84
+ * handler-free Html built outside a render. */
70
85
  export declare const requireBoundaryMappers: () => ReadonlyArray<(message: unknown) => unknown>;
86
+ /** Returns a resolver bound to the current frame's render owner and Submodel
87
+ * boundary. Mounts invoke it from their insert hook, so a cached VNode uses
88
+ * the dispatcher for the render that acquires it. That dispatcher follows
89
+ * later wrapper registrations from the same owner without crossing between
90
+ * live and replay renders. */
91
+ export declare const requireMountDispatchResolver: () => MountDispatchResolver;
71
92
  /** Returns the current runtime Effect Context, used by Mount integrations
72
93
  * that fork message-producing Effects against the live runtime services. */
73
94
  export declare const requireRuntimeContext: () => Context.Context<never>;
@@ -1 +1 @@
1
- {"version":3,"file":"runtimeSingleton.d.ts","sourceRoot":"","sources":["../../src/html/runtimeSingleton.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAErC,OAAO,EACL,KAAK,UAAU,EACf,KAAK,gBAAgB,EAMtB,MAAM,eAAe,CAAA;AAEtB,iFAAiF;AACjF,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;AAErD,MAAM,MAAM,KAAK,GAAG,QAAQ,CAAC;IAC3B,aAAa,EAAE,YAAY,CAAA;IAC3B,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACtC,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,UAAU,EAAE,UAAU,CAAA;CACvB,CAAC,CAAA;AAIF;;;;;;;;;;gBAUgB;AAChB,eAAO,MAAM,UAAU,aACX,YAAY,kBACN,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,qBACpB,gBAAgB,KACjC,IAOF,CAAA;AAED;;;4BAG4B;AAC5B,eAAO,MAAM,YAAY,eAAgB,UAAU,KAAG,IAarD,CAAA;AAED;;;;;;;;;;;0DAW0D;AAC1D,eAAO,MAAM,SAAS,UAAW,KAAK,KAAG,IAExC,CAAA;AAED;;;;;;;6BAO6B;AAC7B,eAAO,MAAM,YAAY,QAAO,IAU/B,CAAA;AAED;;;sEAGsE;AACtE,eAAO,MAAM,eAAe,QAAO,YAelC,CAAA;AAED;;sCAEsC;AACtC,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,IAAI,CAAA;AAE9D;;;4DAG4D;AAC5D,eAAO,MAAM,sBAAsB,QAAO,eAiBzC,CAAA;AAED;;;;;sEAKsE;AACtE,eAAO,MAAM,sBAAsB,QAAO,aAAa,CACrD,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAO9B,CAAA;AAED;6EAC6E;AAC7E,eAAO,MAAM,qBAAqB,QAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAW7D,CAAA;AAED;;mEAEmE;AACnE,eAAO,MAAM,eAAe,QAAO,QAAQ,CAAC;IAC1C,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,UAAU,EAAE,UAAU,CAAA;CACvB,CAQA,CAAA;AAED;;;;;8CAK8C;AAC9C,eAAO,MAAM,eAAe,QAAO,KAQlC,CAAA"}
1
+ {"version":3,"file":"runtimeSingleton.d.ts","sourceRoot":"","sources":["../../src/html/runtimeSingleton.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAErC,OAAO,EACL,KAAK,UAAU,EACf,KAAK,gBAAgB,EAOtB,MAAM,eAAe,CAAA;AAEtB,iFAAiF;AACjF,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;AAErD,wDAAwD;AACxD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEhD,0EAA0E;AAC1E,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,KAAK,EAAE,gBAAgB,CAAA;IACvB,OAAO,EAAE,MAAM,YAAY,CAAA;CAC5B,CAAC,CAAA;AAEF,MAAM,MAAM,KAAK,GAAG,QAAQ,CAAC;IAC3B,aAAa,EAAE,YAAY,CAAA;IAC3B,kBAAkB,EAAE,YAAY,CAAA;IAChC,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACtC,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,UAAU,EAAE,UAAU,CAAA;CACvB,CAAC,CAAA;AAiBF;;;;;;;;;;gBAUgB;AAChB,eAAO,MAAM,UAAU,aACX,YAAY,kBACN,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,qBACpB,gBAAgB,qBAChB,gBAAgB,KACjC,IASF,CAAA;AAED;;;4BAG4B;AAC5B,eAAO,MAAM,YAAY,eAAgB,UAAU,KAAG,IAerD,CAAA;AAED;;;;;;;;;;;0DAW0D;AAC1D,eAAO,MAAM,SAAS,UAAW,KAAK,KAAG,IAExC,CAAA;AAED;;;;;;;6BAO6B;AAC7B,eAAO,MAAM,YAAY,QAAO,IAU/B,CAAA;AAED;;;sEAGsE;AACtE,eAAO,MAAM,eAAe,QAAO,YAOlC,CAAA;AAED;;6CAE6C;AAC7C,eAAO,MAAM,oBAAoB,QAAO,YAEvC,CAAA;AAED,gFAAgF;AAChF,eAAO,MAAM,uBAAuB,QAAO,gBAE1C,CAAA;AAED;;sCAEsC;AACtC,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,IAAI,CAAA;AAE9D;;;4DAG4D;AAC5D,eAAO,MAAM,sBAAsB,QAAO,eASzC,CAAA;AAED;;;;;gDAKgD;AAChD,eAAO,MAAM,sBAAsB,QAAO,aAAa,CACrD,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAO9B,CAAA;AAED;;;;+BAI+B;AAC/B,eAAO,MAAM,4BAA4B,QAAO,qBAW/C,CAAA;AAED;6EAC6E;AAC7E,eAAO,MAAM,qBAAqB,QAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAE7D,CAAA;AAED;;mEAEmE;AACnE,eAAO,MAAM,eAAe,QAAO,QAAQ,CAAC;IAC1C,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,UAAU,EAAE,UAAU,CAAA;CACvB,CAQA,CAAA;AAED;;;;;8CAK8C;AAC9C,eAAO,MAAM,eAAe,QAAO,KAQlC,CAAA"}
@@ -1,5 +1,15 @@
1
- import { ROOT_BOUNDARY, boundaryMappers, createBoundaryRegistry, getOrCreateBoundaryDispatch, resolveBoundaryDispatchThunk, } from './boundary.js';
1
+ import { ROOT_BOUNDARY, boundaryMappers, createBoundaryRegistry, getOrCreateBoundaryDispatch, resolveBoundaryDispatchThunk, resolveMountBoundaryDispatch, } from './boundary.js';
2
2
  const stack = [];
3
+ const requireFrame = () => {
4
+ const frame = stack[stack.length - 1];
5
+ if (frame === undefined) {
6
+ throw new Error('Foldkit: html element constructors must be called inside a runtime-driven ' +
7
+ 'render. The element was built outside a view, or foldkit was loaded as ' +
8
+ 'more than one instance (a bundler split foldkit and @foldkit/ui into ' +
9
+ 'separate copies).');
10
+ }
11
+ return frame;
12
+ };
3
13
  /** Pushes a new dispatch and runtime context onto the singleton stack. The
4
14
  * runtime calls this before invoking a user `view`, and any test or
5
15
  * framework helper that builds VNodes outside of a normal render uses the
@@ -11,9 +21,11 @@ const stack = [];
11
21
  * omitted (e.g. crash views, test helpers that don't use Submodels), a
12
22
  * fresh empty registry is created. The frame starts in the root
13
23
  * boundary. */
14
- export const setRuntime = (dispatch, runtimeContext, boundaryRegistry = createBoundaryRegistry()) => {
24
+ export const setRuntime = (dispatch, runtimeContext, boundaryRegistry = createBoundaryRegistry(), mountRenderOwner = 'Live') => {
15
25
  stack.push({
16
26
  outerDispatch: dispatch,
27
+ mountOuterDispatch: dispatch,
28
+ mountRenderOwner,
17
29
  runtimeContext,
18
30
  boundaryRegistry,
19
31
  boundaryId: ROOT_BOUNDARY,
@@ -30,6 +42,8 @@ export const pushBoundary = (boundaryId) => {
30
42
  }
31
43
  stack.push({
32
44
  outerDispatch: parent.outerDispatch,
45
+ mountOuterDispatch: parent.mountOuterDispatch,
46
+ mountRenderOwner: parent.mountRenderOwner,
33
47
  runtimeContext: parent.runtimeContext,
34
48
  boundaryRegistry: parent.boundaryRegistry,
35
49
  boundaryId,
@@ -72,35 +86,33 @@ export const clearRuntime = () => {
72
86
  * is a cached per-boundary dispatcher that applies the wrapping chain at
73
87
  * event-fire time. Throws when called outside of a runtime frame. */
74
88
  export const requireDispatch = () => {
75
- const frame = stack[stack.length - 1];
76
- if (frame === undefined) {
77
- throw new Error('Foldkit: html element constructors must be called inside a runtime-driven ' +
78
- 'render. The element was built outside a view, or foldkit was loaded as ' +
79
- 'more than one instance (a bundler split foldkit and @foldkit/ui into ' +
80
- 'separate copies).');
81
- }
89
+ const frame = requireFrame();
82
90
  return getOrCreateBoundaryDispatch(frame.boundaryRegistry, frame.outerDispatch, frame.boundaryId);
83
91
  };
92
+ /** Returns the render-owned root dispatcher for Mount results. A live render
93
+ * supplies live dispatch, while a historical render supplies no-op dispatch
94
+ * for acquisitions owned by that replay. */
95
+ export const requireMountDispatch = () => {
96
+ return requireFrame().mountOuterDispatch;
97
+ };
98
+ /** Returns whether the current frame is rendering the live or replayed view. */
99
+ export const requireMountRenderOwner = () => {
100
+ return requireFrame().mountRenderOwner;
101
+ };
84
102
  /** Returns an {@link UnmountResolver} bound to the current frame's boundary.
85
103
  * `OnUnmount` calls the resolver at build time (boundary alive) to capture a
86
104
  * dispatch thunk that survives the boundary being torn down during the same
87
105
  * patch. Throws when called outside of a runtime frame. */
88
106
  export const requireUnmountResolver = () => {
89
- const frame = stack[stack.length - 1];
90
- if (frame === undefined) {
91
- throw new Error('Foldkit: html element constructors must be called inside a runtime-driven ' +
92
- 'render. The element was built outside a view, or foldkit was loaded as ' +
93
- 'more than one instance (a bundler split foldkit and @foldkit/ui into ' +
94
- 'separate copies).');
95
- }
107
+ const frame = requireFrame();
96
108
  return message => resolveBoundaryDispatchThunk(frame.boundaryRegistry, frame.outerDispatch, frame.boundaryId, message);
97
109
  };
98
110
  /** Returns the current frame's Submodel wrapping chain (innermost first), or an
99
- * empty array at the root boundary. `OnMount` calls this at build time to
100
- * snapshot the lift a Submodel-embedded mount's result travels through in
101
- * production (via `ctx.dispatch`), so the Scene test harness can replay it when
102
- * the mount is resolved. Returns `[]` when there is no active frame, mirroring
103
- * the lazy tolerance of handler-free Html built outside a render. */
111
+ * empty array at the root boundary. `OnMount` records this build-time snapshot
112
+ * for the Scene test harness, which replays the chain when the Mount is
113
+ * resolved. Production Mount dispatch uses the ownership-aware resolver below.
114
+ * Returns `[]` when there is no active frame, mirroring the lazy tolerance of
115
+ * handler-free Html built outside a render. */
104
116
  export const requireBoundaryMappers = () => {
105
117
  const frame = stack[stack.length - 1];
106
118
  if (frame === undefined) {
@@ -108,17 +120,22 @@ export const requireBoundaryMappers = () => {
108
120
  }
109
121
  return boundaryMappers(frame.boundaryRegistry, frame.boundaryId);
110
122
  };
123
+ /** Returns a resolver bound to the current frame's render owner and Submodel
124
+ * boundary. Mounts invoke it from their insert hook, so a cached VNode uses
125
+ * the dispatcher for the render that acquires it. That dispatcher follows
126
+ * later wrapper registrations from the same owner without crossing between
127
+ * live and replay renders. */
128
+ export const requireMountDispatchResolver = () => {
129
+ const frame = requireFrame();
130
+ return {
131
+ owner: frame.mountRenderOwner,
132
+ resolve: () => resolveMountBoundaryDispatch(frame.boundaryRegistry, frame.mountOuterDispatch, frame.boundaryId),
133
+ };
134
+ };
111
135
  /** Returns the current runtime Effect Context, used by Mount integrations
112
136
  * that fork message-producing Effects against the live runtime services. */
113
137
  export const requireRuntimeContext = () => {
114
- const frame = stack[stack.length - 1];
115
- if (frame === undefined) {
116
- throw new Error('Foldkit: html element constructors must be called inside a runtime-driven ' +
117
- 'render. The element was built outside a view, or foldkit was loaded as ' +
118
- 'more than one instance (a bundler split foldkit and @foldkit/ui into ' +
119
- 'separate copies).');
120
- }
121
- return frame.runtimeContext;
138
+ return requireFrame().runtimeContext;
122
139
  };
123
140
  /** Returns the current frame's boundary registry and boundary id. Used by
124
141
  * `h.submodel` to register wrapping descriptors and compute child
@@ -1 +1 @@
1
- {"version":3,"file":"submodel.d.ts","sourceRoot":"","sources":["../../src/html/submodel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"submodel.d.ts","sourceRoot":"","sources":["../../src/html/submodel.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { memoizedVNodes } from '../vdom.js';
2
- import { composeBoundary, deregisterBoundaryWrap, registerBoundaryWrap, } from './boundary.js';
2
+ import { beginBoundaryWrapTransaction, commitBoundaryWrapTransaction, composeBoundary, deregisterBoundaryWrap, registerBoundaryWrap, rollbackBoundaryWrapTransaction, } from './boundary.js';
3
3
  import { isChildAttribute } from './childAttribute.js';
4
4
  import { clearRuntime, getCurrentFrame, pushBoundary, pushFrame, } from './runtimeSingleton.js';
5
5
  // NOTE: string key (not Symbol) so SubmodelView types from different
@@ -136,23 +136,12 @@ const wrapViewInputsForOuterBoundary = (viewInputs, outerFrame) => {
136
136
  *
137
137
  * See `submodel.test.ts` for the cache-hit-survival and
138
138
  * destroy-deregisters-wrap assertions. */
139
- const withBoundaryCleanup = (vnode, registry, boundaryId) => {
139
+ const withBoundaryCleanup = (vnode, registry, boundaryId, descriptor, mountOuterDispatch) => {
140
140
  const data = vnode.data ?? {};
141
141
  const hook = data.hook ?? {};
142
142
  const previousDestroy = hook.destroy;
143
143
  const compositeDestroy = (removed) => {
144
- // NOTE: a Submodel whose root vnode changes snabbdom identity across
145
- // renders (e.g. a keyed root whose key changed) re-registers its
146
- // boundary in the new view phase, then snabbdom destroys the OLD root
147
- // vnode in the following patch phase. That destroy must not evict the
148
- // freshly re-registered wrap. `seenThisRender` is cleared in
149
- // `beginRender`, so during patch it still reflects the just-completed
150
- // view phase: the boundary's presence there means it is live this cycle
151
- // (a remount), not a true unmount. Deleting it here would surface later
152
- // as `dispatchAcrossBoundary missing wrap`.
153
- if (!registry.seenThisRender.has(boundaryId)) {
154
- deregisterBoundaryWrap(registry, boundaryId);
155
- }
144
+ deregisterBoundaryWrap(registry, boundaryId, descriptor, mountOuterDispatch);
156
145
  if (previousDestroy !== undefined) {
157
146
  previousDestroy(removed);
158
147
  }
@@ -184,21 +173,23 @@ export const submodel = (config, htmlBuilderSingleton) => {
184
173
  const parentFrame = getCurrentFrame();
185
174
  const registry = parentFrame.boundaryRegistry;
186
175
  const childBoundaryId = composeBoundary(parentFrame.boundaryId, config.slotId);
187
- registerBoundaryWrap(registry, childBoundaryId, {
176
+ const descriptor = {
188
177
  toParentMessage:
189
178
  /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
190
179
  config.toParentMessage,
191
- });
192
- // NOTE: the builder handed to the child view is the process-wide
193
- // singleton retyped to the child's Message. The value carries no
194
- // Message state (dispatch resolves from the frame pushed below), so
195
- // the cast is the entire mechanism, exactly like the brand cast in
196
- // `defineView`.
197
- /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
198
- const childBuilder = htmlBuilderSingleton;
199
- let vnode;
200
- pushBoundary(childBoundaryId);
180
+ };
181
+ const transaction = beginBoundaryWrapTransaction(registry);
201
182
  try {
183
+ registerBoundaryWrap(registry, childBoundaryId, descriptor, parentFrame.mountOuterDispatch);
184
+ // NOTE: the builder handed to the child view is the process-wide
185
+ // singleton retyped to the child's Message. The value carries no
186
+ // Message state (dispatch resolves from the frame pushed below), so
187
+ // the cast is the entire mechanism, exactly like the brand cast in
188
+ // `defineView`.
189
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
190
+ const childBuilder = htmlBuilderSingleton;
191
+ let vnode;
192
+ pushBoundary(childBoundaryId);
202
193
  try {
203
194
  if (!Object.hasOwn(config, 'viewInputs')) {
204
195
  /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
@@ -214,21 +205,19 @@ export const submodel = (config, htmlBuilderSingleton) => {
214
205
  vnode = view(config.model, wrappedViewInputs, childBuilder);
215
206
  }
216
207
  }
217
- catch (error) {
218
- // The view threw; the registered wrap would otherwise leak with
219
- // no destroy hook ever firing. Drop it before propagating.
220
- deregisterBoundaryWrap(registry, childBoundaryId);
221
- throw error;
208
+ finally {
209
+ clearRuntime();
222
210
  }
211
+ if (vnode === null) {
212
+ rollbackBoundaryWrapTransaction(registry, transaction);
213
+ return null;
214
+ }
215
+ const vnodeWithCleanup = withBoundaryCleanup(vnode, registry, childBoundaryId, descriptor, parentFrame.mountOuterDispatch);
216
+ commitBoundaryWrapTransaction(registry, transaction);
217
+ return vnodeWithCleanup;
223
218
  }
224
- finally {
225
- clearRuntime();
226
- }
227
- if (vnode === null) {
228
- // No vnode means no destroy hook will ever fire; deregister now so
229
- // the wrap doesn't leak.
230
- deregisterBoundaryWrap(registry, childBoundaryId);
231
- return null;
219
+ catch (error) {
220
+ rollbackBoundaryWrapTransaction(registry, transaction);
221
+ throw error;
232
222
  }
233
- return withBoundaryCleanup(vnode, registry, childBoundaryId);
234
223
  };
@@ -29,7 +29,7 @@ import { HttpClient } from 'effect/unstable/http';
29
29
  * execute: Effect.gen(function* () {
30
30
  * const client = yield* HttpClient.HttpClient
31
31
  * const response = yield* client.get('/api/count')
32
- * const { count } = yield* S.decodeUnknownEffect(CountResponse)(
32
+ * const { count } = yield* Schema.decodeUnknownEffect(CountResponse)(
33
33
  * yield* response.json,
34
34
  * )
35
35
  * return SucceededFetchCount({ count })
package/dist/http/http.js CHANGED
@@ -29,7 +29,7 @@ import { FetchHttpClient, HttpClient } from 'effect/unstable/http';
29
29
  * execute: Effect.gen(function* () {
30
30
  * const client = yield* HttpClient.HttpClient
31
31
  * const response = yield* client.get('/api/count')
32
- * const { count } = yield* S.decodeUnknownEffect(CountResponse)(
32
+ * const { count } = yield* Schema.decodeUnknownEffect(CountResponse)(
33
33
  * yield* response.json,
34
34
  * )
35
35
  * return SucceededFetchCount({ count })
@@ -54,7 +54,7 @@ type EntryBrand<Model, Message> = {
54
54
  };
55
55
  /**
56
56
  * The requirements value the runtime hands to `acquire`. When the requirements
57
- * schema is wrapped in `S.Option`, the runtime unwraps the `Some` before
57
+ * schema is wrapped in `Schema.Option`, the runtime unwraps the `Some` before
58
58
  * calling `acquire`, so the parameter is the inner type.
59
59
  */
60
60
  type AcquireParams<Requirements> = Requirements extends Option.Option<infer Params> ? Params : Requirements;
@@ -99,7 +99,7 @@ export type ServicesOf<Resources> = {
99
99
  * on the config literal) lets TypeScript fully resolve the requirements type
100
100
  * before contextually typing `modelToMaybeRequirements` and `acquire`, so
101
101
  * destructuring patterns are inferred correctly even when the schema uses
102
- * transforms like `S.Option`.
102
+ * transforms like `Schema.Option`.
103
103
  *
104
104
  * The `onAcquired` field is typed as `OnAcquired` intersected with the
105
105
  * concrete `(value: Value) => Message` signature: the concrete member keeps
@@ -153,7 +153,7 @@ export type EntryBuilder<Model, Message> = <RequirementsSchema extends Schema.Sc
153
153
  * - `modelToMaybeRequirements` — Extracts requirements from the model.
154
154
  * `Option.none()` means "release", `Option.some(params)` means
155
155
  * "acquire/re-acquire if params changed". For resources with no
156
- * parameters, use `S.Option(S.Null)` and return `Option.some(null)`.
156
+ * parameters, use `Schema.Option(Schema.Null)` and return `Option.some(null)`.
157
157
  * - `acquire` — Creates the resource from the unwrapped params. The returned
158
158
  * Effect should fail when acquisition fails: errors in the error channel
159
159
  * flow to `onAcquireError` as a message instead of crashing the runtime.
@@ -179,7 +179,7 @@ export type EntryBuilder<Model, Message> = <RequirementsSchema extends Schema.Sc
179
179
  * const CameraStream = ManagedResource.tag<MediaStream>()('CameraStream')
180
180
  *
181
181
  * const managedResources = ManagedResource.make<Model, Message>()(entry => ({
182
- * camera: entry(S.Option(S.Struct({ facingMode: S.String })), {
182
+ * camera: entry(Schema.Option(Schema.Struct({ facingMode: Schema.String })), {
183
183
  * resource: CameraStream,
184
184
  * modelToMaybeRequirements: model =>
185
185
  * pipe(
@@ -218,7 +218,7 @@ type ChildMessageOf<Resources> = Resources[keyof Resources] extends Entry<any, i
218
218
  * `Option.none()` to release), and a child Submodel that owns a managed
219
219
  * resource is itself something that mounts and unmounts. A missing child is
220
220
  * just another `None` and flows through the same acquire/release channel, so
221
- * each lifted entry's requirements must be `S.Option`-wrapped.
221
+ * each lifted entry's requirements must be `Schema.Option`-wrapped.
222
222
  */
223
223
  export declare const lift: <Resources extends Record<string, Entry<any, any, Option.Option<any>, any, any>>>(resources: Resources) => <ParentModel, ParentMessage>(config: {
224
224
  readonly toChildModel: (parentModel: ParentModel) => Option.Option<ChildModelOf<Resources>>;
@@ -55,7 +55,7 @@ export const tag = () => (key) => {
55
55
  * - `modelToMaybeRequirements` — Extracts requirements from the model.
56
56
  * `Option.none()` means "release", `Option.some(params)` means
57
57
  * "acquire/re-acquire if params changed". For resources with no
58
- * parameters, use `S.Option(S.Null)` and return `Option.some(null)`.
58
+ * parameters, use `Schema.Option(Schema.Null)` and return `Option.some(null)`.
59
59
  * - `acquire` — Creates the resource from the unwrapped params. The returned
60
60
  * Effect should fail when acquisition fails: errors in the error channel
61
61
  * flow to `onAcquireError` as a message instead of crashing the runtime.
@@ -81,7 +81,7 @@ export const tag = () => (key) => {
81
81
  * const CameraStream = ManagedResource.tag<MediaStream>()('CameraStream')
82
82
  *
83
83
  * const managedResources = ManagedResource.make<Model, Message>()(entry => ({
84
- * camera: entry(S.Option(S.Struct({ facingMode: S.String })), {
84
+ * camera: entry(Schema.Option(Schema.Struct({ facingMode: Schema.String })), {
85
85
  * resource: CameraStream,
86
86
  * modelToMaybeRequirements: model =>
87
87
  * pipe(
@@ -130,7 +130,7 @@ export const make = () =>
130
130
  * `Option.none()` to release), and a child Submodel that owns a managed
131
131
  * resource is itself something that mounts and unmounts. A missing child is
132
132
  * just another `None` and flows through the same acquire/release channel, so
133
- * each lifted entry's requirements must be `S.Option`-wrapped.
133
+ * each lifted entry's requirements must be `Schema.Option`-wrapped.
134
134
  */
135
135
  export const lift = (resources) => (config) =>
136
136
  /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */