@typed/template 0.2.0 → 0.3.1

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 (227) hide show
  1. package/dist/cjs/Directive.js +1 -1
  2. package/dist/cjs/Directive.js.map +1 -1
  3. package/dist/cjs/ElementRef.js +23 -13
  4. package/dist/cjs/ElementRef.js.map +1 -1
  5. package/dist/cjs/ElementSource.js +16 -18
  6. package/dist/cjs/ElementSource.js.map +1 -1
  7. package/dist/cjs/EventHandler.js +1 -1
  8. package/dist/cjs/EventHandler.js.map +1 -1
  9. package/dist/cjs/Html.js +31 -32
  10. package/dist/cjs/Html.js.map +1 -1
  11. package/dist/cjs/HtmlChunk.js +4 -1
  12. package/dist/cjs/HtmlChunk.js.map +1 -1
  13. package/dist/cjs/Hydrate.js +1 -1
  14. package/dist/cjs/Hydrate.js.map +1 -1
  15. package/dist/cjs/Many.js +14 -13
  16. package/dist/cjs/Many.js.map +1 -1
  17. package/dist/cjs/Parser.js +11 -323
  18. package/dist/cjs/Parser.js.map +1 -1
  19. package/dist/cjs/Placeholder.js +3 -3
  20. package/dist/cjs/Placeholder.js.map +1 -1
  21. package/dist/cjs/Platform.js +4 -4
  22. package/dist/cjs/Platform.js.map +1 -1
  23. package/dist/cjs/Render.js +1 -1
  24. package/dist/cjs/Render.js.map +1 -1
  25. package/dist/cjs/RenderContext.js +48 -27
  26. package/dist/cjs/RenderContext.js.map +1 -1
  27. package/dist/cjs/RenderTemplate.js +2 -17
  28. package/dist/cjs/RenderTemplate.js.map +1 -1
  29. package/dist/cjs/Template.js +27 -1
  30. package/dist/cjs/Template.js.map +1 -1
  31. package/dist/cjs/TemplateInstance.js +2 -2
  32. package/dist/cjs/TemplateInstance.js.map +1 -1
  33. package/dist/cjs/Test.js +20 -7
  34. package/dist/cjs/Test.js.map +1 -1
  35. package/dist/cjs/index.js +0 -12
  36. package/dist/cjs/index.js.map +1 -1
  37. package/dist/cjs/internal/EventSource.js +95 -0
  38. package/dist/cjs/internal/EventSource.js.map +1 -0
  39. package/dist/cjs/internal/browser.js +11 -11
  40. package/dist/cjs/internal/browser.js.map +1 -1
  41. package/dist/cjs/internal/chunks.js +4 -1
  42. package/dist/cjs/internal/chunks.js.map +1 -1
  43. package/dist/cjs/internal/errors.js +4 -0
  44. package/dist/cjs/internal/errors.js.map +1 -1
  45. package/dist/cjs/internal/hydrate.js +113 -80
  46. package/dist/cjs/internal/hydrate.js.map +1 -1
  47. package/dist/cjs/internal/indexRefCounter.js +49 -2
  48. package/dist/cjs/internal/indexRefCounter.js.map +1 -1
  49. package/dist/cjs/internal/parser.js +72 -21
  50. package/dist/cjs/internal/parser.js.map +1 -1
  51. package/dist/cjs/internal/parts.js +128 -28
  52. package/dist/cjs/internal/parts.js.map +1 -1
  53. package/dist/cjs/internal/render.js +460 -161
  54. package/dist/cjs/internal/render.js.map +1 -1
  55. package/dist/cjs/internal/server.js +5 -2
  56. package/dist/cjs/internal/server.js.map +1 -1
  57. package/dist/dts/Directive.d.ts.map +1 -1
  58. package/dist/dts/ElementRef.d.ts +4 -2
  59. package/dist/dts/ElementRef.d.ts.map +1 -1
  60. package/dist/dts/ElementSource.d.ts +10 -5
  61. package/dist/dts/ElementSource.d.ts.map +1 -1
  62. package/dist/dts/EventHandler.d.ts.map +1 -1
  63. package/dist/dts/Html.d.ts +1 -1
  64. package/dist/dts/Html.d.ts.map +1 -1
  65. package/dist/dts/HtmlChunk.d.ts.map +1 -1
  66. package/dist/dts/Many.d.ts +13 -11
  67. package/dist/dts/Many.d.ts.map +1 -1
  68. package/dist/dts/Parser.d.ts +3 -6
  69. package/dist/dts/Parser.d.ts.map +1 -1
  70. package/dist/dts/Part.d.ts +13 -3
  71. package/dist/dts/Part.d.ts.map +1 -1
  72. package/dist/dts/Placeholder.d.ts +2 -2
  73. package/dist/dts/Placeholder.d.ts.map +1 -1
  74. package/dist/dts/Render.d.ts +2 -1
  75. package/dist/dts/Render.d.ts.map +1 -1
  76. package/dist/dts/RenderContext.d.ts +5 -4
  77. package/dist/dts/RenderContext.d.ts.map +1 -1
  78. package/dist/dts/RenderTemplate.d.ts +2 -16
  79. package/dist/dts/RenderTemplate.d.ts.map +1 -1
  80. package/dist/dts/Renderable.d.ts +2 -2
  81. package/dist/dts/Renderable.d.ts.map +1 -1
  82. package/dist/dts/Template.d.ts +21 -3
  83. package/dist/dts/Template.d.ts.map +1 -1
  84. package/dist/dts/TemplateInstance.d.ts +3 -2
  85. package/dist/dts/TemplateInstance.d.ts.map +1 -1
  86. package/dist/dts/Test.d.ts +4 -6
  87. package/dist/dts/Test.d.ts.map +1 -1
  88. package/dist/dts/index.d.ts +0 -4
  89. package/dist/dts/index.d.ts.map +1 -1
  90. package/dist/dts/internal/EventSource.d.ts +12 -0
  91. package/dist/dts/internal/EventSource.d.ts.map +1 -0
  92. package/dist/dts/internal/browser.d.ts.map +1 -1
  93. package/dist/dts/internal/chunks.d.ts +1 -0
  94. package/dist/dts/internal/chunks.d.ts.map +1 -1
  95. package/dist/dts/internal/errors.d.ts +1 -0
  96. package/dist/dts/internal/errors.d.ts.map +1 -1
  97. package/dist/dts/internal/hydrate.d.ts +9 -16
  98. package/dist/dts/internal/hydrate.d.ts.map +1 -1
  99. package/dist/dts/internal/indexRefCounter.d.ts +5 -0
  100. package/dist/dts/internal/indexRefCounter.d.ts.map +1 -1
  101. package/dist/dts/internal/module-augmentation.d.ts +0 -4
  102. package/dist/dts/internal/module-augmentation.d.ts.map +1 -1
  103. package/dist/dts/internal/parser.d.ts +8 -0
  104. package/dist/dts/internal/parser.d.ts.map +1 -1
  105. package/dist/dts/internal/parts.d.ts +66 -56
  106. package/dist/dts/internal/parts.d.ts.map +1 -1
  107. package/dist/dts/internal/render.d.ts +1 -15
  108. package/dist/dts/internal/render.d.ts.map +1 -1
  109. package/dist/dts/internal/server.d.ts.map +1 -1
  110. package/dist/esm/Directive.js +1 -1
  111. package/dist/esm/Directive.js.map +1 -1
  112. package/dist/esm/ElementRef.js +12 -7
  113. package/dist/esm/ElementRef.js.map +1 -1
  114. package/dist/esm/ElementSource.js +16 -13
  115. package/dist/esm/ElementSource.js.map +1 -1
  116. package/dist/esm/EventHandler.js +1 -1
  117. package/dist/esm/EventHandler.js.map +1 -1
  118. package/dist/esm/Html.js +29 -24
  119. package/dist/esm/Html.js.map +1 -1
  120. package/dist/esm/HtmlChunk.js +6 -1
  121. package/dist/esm/HtmlChunk.js.map +1 -1
  122. package/dist/esm/Hydrate.js +1 -1
  123. package/dist/esm/Hydrate.js.map +1 -1
  124. package/dist/esm/Many.js +14 -10
  125. package/dist/esm/Many.js.map +1 -1
  126. package/dist/esm/Parser.js +6 -335
  127. package/dist/esm/Parser.js.map +1 -1
  128. package/dist/esm/Placeholder.js +2 -2
  129. package/dist/esm/Placeholder.js.map +1 -1
  130. package/dist/esm/Platform.js +2 -2
  131. package/dist/esm/Platform.js.map +1 -1
  132. package/dist/esm/Render.js +1 -1
  133. package/dist/esm/Render.js.map +1 -1
  134. package/dist/esm/RenderContext.js +38 -17
  135. package/dist/esm/RenderContext.js.map +1 -1
  136. package/dist/esm/RenderTemplate.js +2 -12
  137. package/dist/esm/RenderTemplate.js.map +1 -1
  138. package/dist/esm/Template.js +24 -0
  139. package/dist/esm/Template.js.map +1 -1
  140. package/dist/esm/TemplateInstance.js +2 -2
  141. package/dist/esm/TemplateInstance.js.map +1 -1
  142. package/dist/esm/Test.js +20 -7
  143. package/dist/esm/Test.js.map +1 -1
  144. package/dist/esm/index.js +0 -4
  145. package/dist/esm/index.js.map +1 -1
  146. package/dist/esm/internal/EventSource.js +91 -0
  147. package/dist/esm/internal/EventSource.js.map +1 -0
  148. package/dist/esm/internal/browser.js +12 -12
  149. package/dist/esm/internal/browser.js.map +1 -1
  150. package/dist/esm/internal/chunks.js +2 -0
  151. package/dist/esm/internal/chunks.js.map +1 -1
  152. package/dist/esm/internal/errors.js +3 -0
  153. package/dist/esm/internal/errors.js.map +1 -1
  154. package/dist/esm/internal/hydrate.js +113 -76
  155. package/dist/esm/internal/hydrate.js.map +1 -1
  156. package/dist/esm/internal/indexRefCounter.js +50 -2
  157. package/dist/esm/internal/indexRefCounter.js.map +1 -1
  158. package/dist/esm/internal/parser.js +98 -22
  159. package/dist/esm/internal/parser.js.map +1 -1
  160. package/dist/esm/internal/parts.js +110 -27
  161. package/dist/esm/internal/parts.js.map +1 -1
  162. package/dist/esm/internal/render.js +446 -157
  163. package/dist/esm/internal/render.js.map +1 -1
  164. package/dist/esm/internal/server.js +5 -4
  165. package/dist/esm/internal/server.js.map +1 -1
  166. package/package.json +10 -26
  167. package/src/Directive.ts +1 -1
  168. package/src/ElementRef.ts +18 -14
  169. package/src/ElementSource.ts +62 -47
  170. package/src/EventHandler.ts +1 -1
  171. package/src/Html.ts +58 -57
  172. package/src/HtmlChunk.ts +15 -1
  173. package/src/Hydrate.ts +1 -1
  174. package/src/Many.ts +53 -43
  175. package/src/Parser.ts +10 -453
  176. package/src/Part.ts +15 -3
  177. package/src/Placeholder.ts +4 -4
  178. package/src/Platform.ts +2 -2
  179. package/src/Render.ts +7 -2
  180. package/src/RenderContext.ts +47 -19
  181. package/src/RenderTemplate.ts +9 -54
  182. package/src/Renderable.ts +2 -1
  183. package/src/Template.ts +26 -0
  184. package/src/TemplateInstance.ts +9 -9
  185. package/src/Test.ts +40 -21
  186. package/src/index.ts +0 -4
  187. package/src/internal/EventSource.ts +153 -0
  188. package/src/internal/browser.ts +26 -25
  189. package/src/internal/chunks.ts +4 -0
  190. package/src/internal/errors.ts +4 -0
  191. package/src/internal/hydrate.ts +161 -107
  192. package/src/internal/indexRefCounter.ts +63 -2
  193. package/src/internal/module-augmentation.ts +0 -4
  194. package/src/internal/parser.ts +107 -25
  195. package/src/internal/parts.ts +158 -73
  196. package/src/internal/render.ts +638 -289
  197. package/src/internal/server.ts +5 -3
  198. package/Token/package.json +0 -6
  199. package/Tokenizer/package.json +0 -6
  200. package/dist/cjs/Token.js +0 -270
  201. package/dist/cjs/Token.js.map +0 -1
  202. package/dist/cjs/Tokenizer.js +0 -18
  203. package/dist/cjs/Tokenizer.js.map +0 -1
  204. package/dist/cjs/internal/readAttribute.js +0 -34
  205. package/dist/cjs/internal/readAttribute.js.map +0 -1
  206. package/dist/cjs/internal/tokenizer.js +0 -264
  207. package/dist/cjs/internal/tokenizer.js.map +0 -1
  208. package/dist/dts/Token.d.ts +0 -202
  209. package/dist/dts/Token.d.ts.map +0 -1
  210. package/dist/dts/Tokenizer.d.ts +0 -6
  211. package/dist/dts/Tokenizer.d.ts.map +0 -1
  212. package/dist/dts/internal/readAttribute.d.ts +0 -9
  213. package/dist/dts/internal/readAttribute.d.ts.map +0 -1
  214. package/dist/dts/internal/tokenizer.d.ts +0 -3
  215. package/dist/dts/internal/tokenizer.d.ts.map +0 -1
  216. package/dist/esm/Token.js +0 -264
  217. package/dist/esm/Token.js.map +0 -1
  218. package/dist/esm/Tokenizer.js +0 -9
  219. package/dist/esm/Tokenizer.js.map +0 -1
  220. package/dist/esm/internal/readAttribute.js +0 -24
  221. package/dist/esm/internal/readAttribute.js.map +0 -1
  222. package/dist/esm/internal/tokenizer.js +0 -296
  223. package/dist/esm/internal/tokenizer.js.map +0 -1
  224. package/src/Token.ts +0 -269
  225. package/src/Tokenizer.ts +0 -10
  226. package/src/internal/readAttribute.ts +0 -28
  227. package/src/internal/tokenizer.ts +0 -338
@@ -1,23 +1,23 @@
1
1
  import * as Fx from "@typed/fx/Fx"
2
- import * as Subject from "@typed/fx/Subject"
3
- import type { Rendered } from "@typed/wire"
4
- import type { Cause } from "effect"
5
- import { Effect } from "effect"
6
- import * as ElementRef from "../ElementRef.js"
2
+ import * as Effect from "effect/Effect"
7
3
  import type { Placeholder } from "../Placeholder.js"
8
4
  import type { Renderable } from "../Renderable.js"
9
5
  import type { RenderContext } from "../RenderContext.js"
6
+ import type { RenderEvent } from "../RenderEvent.js"
10
7
  import { DomRenderEvent } from "../RenderEvent.js"
11
8
  import type { RenderTemplate } from "../RenderTemplate.js"
12
- import { TemplateInstance } from "../TemplateInstance.js"
13
- import { indexRefCounter } from "./indexRefCounter.js"
9
+ import { indexRefCounter2 } from "./indexRefCounter.js"
14
10
 
15
11
  import { unsafeGet } from "@typed/context"
16
12
 
13
+ import { Either } from "effect"
14
+ import { Scope } from "effect/Scope"
17
15
  import type { Template } from "../Template.js"
18
16
  import { CouldNotFindCommentError, CouldNotFindRootElement } from "./errors.js"
17
+ import { makeEventSource } from "./EventSource.js"
19
18
  import { HydrateContext } from "./HydrateContext.js"
20
- import { buildParts, getBrowserEntry, renderTemplate, renderValues } from "./render.js"
19
+ import type { RenderPartContext } from "./render.js"
20
+ import { getBrowserEntry, renderPart2, renderTemplate } from "./render.js"
21
21
  import {
22
22
  findPath,
23
23
  getPreviousNodes,
@@ -27,67 +27,105 @@ import {
27
27
  type ParentChildNodes
28
28
  } from "./utils.js"
29
29
 
30
- // TODO: Handle missing comment errors
31
-
32
30
  /**
33
31
  * Here for "standard" browser rendering, a TemplateInstance is effectively a live
34
32
  * view into the contents rendered by the Template.
35
33
  */
36
- export const hydrateTemplate: (document: Document, ctx: RenderContext) => RenderTemplate =
37
- (document, renderContext) =>
38
- <Values extends ReadonlyArray<Renderable<any, any>>, T extends Rendered = Rendered>(
39
- templateStrings: TemplateStringsArray,
40
- values: Values,
41
- providedRef?: ElementRef.ElementRef<T>
42
- ) => {
43
- return Effect.gen(function*(_) {
44
- const context = yield* _(Effect.context<never>())
45
- const hydrateCtx = unsafeGet(context, HydrateContext)
46
-
47
- // If we're not longer hydrating, just render normally
48
- if (!hydrateCtx.hydrate) {
49
- return yield* _(renderTemplate(document, renderContext)(templateStrings, values, providedRef))
50
- }
51
-
52
- const elementRef = providedRef || (yield* _(ElementRef.make<T>()))
53
- const events = Fx.map(elementRef, DomRenderEvent)
54
- const errors = Subject.make<Placeholder.Error<Values[number]>, never>()
55
-
56
- const { getParts, template, where, wire } = getHydrateEntry({
57
- ...hydrateCtx,
58
- document,
59
- renderContext,
60
- elementRef,
61
- strings: templateStrings,
62
- onCause: errors.onFailure
63
- })
64
- const parts = yield* _(getParts)
65
-
66
- // If there are parts we need to render them before constructing our Wire
67
- if (parts.length > 0) {
68
- const refCounter = yield* _(indexRefCounter(parts.length))
34
+ export const hydrateTemplate: (document: Document, ctx: RenderContext) => RenderTemplate = (
35
+ document,
36
+ renderContext
37
+ ) => {
38
+ const render_ = renderTemplate(document, renderContext)
69
39
 
70
- // Do the work
71
- yield* _(renderValues(values, parts, refCounter, errors.onFailure, (index: number): HydrateContext => ({
40
+ return <Values extends ReadonlyArray<Renderable<any, any>>>(
41
+ templateStrings: TemplateStringsArray,
42
+ values: Values
43
+ ): Fx.Fx<
44
+ Scope | Placeholder.Context<Values[number]>,
45
+ Placeholder.Error<Values[number]>,
46
+ RenderEvent
47
+ > => {
48
+ return Fx.make((sink) =>
49
+ Effect.gen(function*(_) {
50
+ const context = yield* _(Effect.context<Scope>())
51
+ const hydrateCtx = unsafeGet(context, HydrateContext)
52
+ const scope = unsafeGet(context, Scope)
53
+
54
+ // If we're not longer hydrating, just render normally
55
+ if (hydrateCtx.hydrate === false) {
56
+ return render_(templateStrings, values)
57
+ }
58
+
59
+ const either = getHydrateEntry({
60
+ ...hydrateCtx,
61
+ document,
62
+ renderContext,
63
+ strings: templateStrings
64
+ })
65
+
66
+ if (Either.isLeft(either)) {
67
+ hydrateCtx.hydrate = false
68
+ return render_(templateStrings, values)
69
+ }
70
+
71
+ const { template, where, wire } = either.right
72
+
73
+ if (values.length === 0) return yield* _(sink.onSuccess(DomRenderEvent(wire)), Effect.zipRight(Effect.never))
74
+
75
+ const makeHydrateContext = (index: number): HydrateContext => ({
72
76
  where,
73
77
  rootIndex: index,
74
78
  parentTemplate: template,
75
79
  hydrate: true
76
- })))
77
-
78
- // Wait for initial work to be completed
79
- yield* _(refCounter.wait)
80
- }
81
-
82
- hydrateCtx.hydrate = false
83
-
84
- // Set the element when it is ready
85
- yield* _(ElementRef.set(elementRef, wire as T))
86
-
87
- // Return the Template instance
88
- return TemplateInstance(Fx.merge([events, errors]), elementRef)
89
- })
80
+ })
81
+
82
+ const refCounter = yield* _(indexRefCounter2())
83
+ const ctx: RenderPartContext = {
84
+ context,
85
+ document,
86
+ eventSource: makeEventSource(),
87
+ expected: 0,
88
+ refCounter,
89
+ renderContext,
90
+ onCause: sink.onFailure,
91
+ values,
92
+ makeHydrateContext
93
+ }
94
+
95
+ // Connect our interpolated values to our template parts
96
+ const effects: Array<Effect.Effect<Scope | Placeholder.Context<Values[number]>, never, void>> = []
97
+ for (const [part, path] of template.parts) {
98
+ const eff = renderPart2(part, where, path, ctx)
99
+ if (eff !== null) {
100
+ effects.push(
101
+ ...(Array.isArray(eff) ? eff : [eff]) as Array<
102
+ Effect.Effect<Scope | Placeholder.Context<Values[number]>, never, void>
103
+ >
104
+ )
105
+ }
106
+ }
107
+
108
+ // Fork any effects necessary
109
+ if (effects.length > 0) {
110
+ yield* _(Effect.forkAll(effects))
111
+ }
112
+
113
+ // Set the element when it is ready
114
+ yield* _(ctx.eventSource.setup(wire, scope))
115
+
116
+ // Emit our DomRenderEvent
117
+ yield* _(sink.onSuccess(DomRenderEvent(wire)))
118
+
119
+ // Stop hydrating
120
+ hydrateCtx.hydrate = false
121
+
122
+ // Ensure our templates last forever in the DOM environment
123
+ // so event listeners are kept attached to the current Scope.
124
+ yield* _(Effect.never)
125
+ })
126
+ )
90
127
  }
128
+ }
91
129
 
92
130
  export function findRootParentChildNodes(where: HTMLElement): ParentChildNodes {
93
131
  const childNodes = findRootChildNodes(where)
@@ -103,65 +141,76 @@ const END = "typed-end"
103
141
 
104
142
  // Finds all of the childNodes between the "typed-start" and "typed-end" comments
105
143
  export function findRootChildNodes(where: HTMLElement): Array<Node> {
106
- const childNodes: Array<Node> = []
144
+ let start = -1
145
+ let end = -1
107
146
 
108
- let start = 0
109
- let end = childNodes.length
147
+ const { childNodes } = where
148
+ const length = childNodes.length
110
149
 
111
- for (let i = 0; i < where.childNodes.length; i++) {
112
- const node = where.childNodes[i]
150
+ for (let i = 0; i < length; i++) {
151
+ const node = childNodes[i]
113
152
 
114
- if (node.nodeType === node.COMMENT_NODE) {
115
- if (node.nodeValue === START) {
116
- start = i
117
- break
118
- }
153
+ if (node.nodeType === node.COMMENT_NODE && node.nodeValue === START) {
154
+ start = i
155
+ break
119
156
  }
120
157
  }
121
158
 
122
- for (let i = where.childNodes.length - 1; i >= start; i--) {
123
- const node = where.childNodes[i]
159
+ for (let i = length - 1; i >= start; i--) {
160
+ const node = childNodes[i]
124
161
 
125
- if (node.nodeType === node.COMMENT_NODE) {
126
- if (node.nodeValue === END) {
127
- end = i
128
- break
129
- }
162
+ if (node.nodeType === node.COMMENT_NODE && node.nodeValue === END) {
163
+ end = i
164
+ break
130
165
  }
131
166
  }
132
167
 
133
- for (let i = start + 1; i <= end; i++) {
134
- childNodes.push(where.childNodes[i])
168
+ // If we can't find the start and end comments, just return all childNodes
169
+ if (start === -1 && end === -1) {
170
+ return Array.from(childNodes)
171
+ }
172
+
173
+ start = start === -1 ? 0 : start
174
+ end = end === -1 ? length - 1 : end
175
+
176
+ const rootChildNodes: Array<Node> = Array(end - start)
177
+
178
+ for (let i = start + 1, j = 0; i <= end; i++) {
179
+ rootChildNodes[j++] = childNodes[i]
135
180
  }
136
181
 
137
- return childNodes
182
+ return rootChildNodes
138
183
  }
139
184
 
140
185
  export function findTemplateResultPartChildNodes(
141
186
  where: ParentChildNodes,
142
187
  parentTemplate: Template,
143
- childTemplate: Template | null,
188
+ childTemplate: Template,
144
189
  partIndex: number,
145
190
  childIndex?: number
146
- ) {
191
+ ): Either.Either<CouldNotFindRootElement | CouldNotFindCommentError, ParentChildNodes> {
147
192
  const [, path] = parentTemplate.parts[partIndex]
148
193
  const parentNode = findPath(where, path) as HTMLElement
149
- const childNodes = findPartChildNodes(parentNode, childTemplate?.hash, partIndex)
194
+ const childNodesEither = findPartChildNodes(parentNode, childTemplate.hash, partIndex)
195
+ if (Either.isLeft(childNodesEither)) return Either.left(childNodesEither.left)
196
+
197
+ const childNodes = childNodesEither.right
150
198
  const parentChildNodes = {
151
199
  parentNode,
152
200
  childNodes: childIndex !== undefined ? [childNodes[childIndex]] : childNodes
153
201
  }
154
202
 
155
- return parentChildNodes
203
+ return Either.right(parentChildNodes)
156
204
  }
157
205
 
158
206
  export function findPartChildNodes(
159
207
  { childNodes }: ParentChildNodes,
160
- hash: string | null | undefined,
208
+ hash: string,
161
209
  partIndex: number
162
- ) {
163
- const [comment, index] = findPartComment(childNodes, partIndex)
164
-
210
+ ): Either.Either<CouldNotFindRootElement | CouldNotFindCommentError, Array<Node>> {
211
+ const either = findPartComment(childNodes, partIndex)
212
+ if (Either.isLeft(either)) return Either.left(either.left)
213
+ const [comment, index] = either.right
165
214
  const nodes: Array<Node> = []
166
215
  const previousHoleValue = `hole${partIndex - 1}`
167
216
 
@@ -176,37 +225,38 @@ export function findPartChildNodes(
176
225
  }
177
226
  }
178
227
  } else {
179
- return [...getPreviousNodes(comment, partIndex), comment]
228
+ return Either.right([...getPreviousNodes(comment, partIndex), comment])
180
229
  }
181
230
 
182
231
  if (nodes.length === 0) {
183
- throw new CouldNotFindRootElement(partIndex)
232
+ return Either.left(new CouldNotFindRootElement(partIndex))
184
233
  }
185
234
 
186
235
  nodes.push(comment)
187
236
 
188
- return nodes
237
+ return Either.right(nodes)
189
238
  }
190
239
 
191
- export function findPartComment(childNodes: ArrayLike<Node>, partIndex: number) {
240
+ export function findPartComment(
241
+ childNodes: ArrayLike<Node>,
242
+ partIndex: number
243
+ ): Either.Either<CouldNotFindCommentError, readonly [Comment, number]> {
192
244
  const search = partIndex === -1 ? `typed-end` : `hole${partIndex}`
193
245
 
194
246
  for (let i = 0; i < childNodes.length; ++i) {
195
247
  const node = childNodes[i]
196
248
 
197
249
  if (isCommentWithValue(node, search)) {
198
- return [node, i] as const
250
+ return Either.right([node, i] as const)
199
251
  }
200
252
  }
201
253
 
202
- throw new CouldNotFindCommentError(partIndex)
254
+ return Either.left(new CouldNotFindCommentError(partIndex))
203
255
  }
204
256
 
205
257
  export function getHydrateEntry({
206
258
  childIndex,
207
259
  document,
208
- elementRef,
209
- onCause,
210
260
  parentTemplate,
211
261
  renderContext,
212
262
  rootIndex,
@@ -219,18 +269,21 @@ export function getHydrateEntry({
219
269
  rootIndex: number
220
270
  parentTemplate: Template | null
221
271
  strings: TemplateStringsArray
222
- elementRef: ElementRef.ElementRef<any>
223
- onCause: (cause: Cause.Cause<any>) => Effect.Effect<never, never, void>
224
272
  childIndex?: number
225
- }) {
273
+ }): Either.Either<
274
+ CouldNotFindRootElement | CouldNotFindCommentError,
275
+ { readonly template: Template; readonly wire: Node | Array<Node>; readonly where: ParentChildNodes }
276
+ > {
226
277
  const { template } = getBrowserEntry(document, renderContext, strings)
227
278
 
228
279
  if (parentTemplate) {
229
- where = findTemplateResultPartChildNodes(where, parentTemplate, template, rootIndex, childIndex)
280
+ const either = findTemplateResultPartChildNodes(where, parentTemplate, template, rootIndex, childIndex)
281
+ if (Either.isLeft(either)) {
282
+ return Either.left(either.left)
283
+ }
284
+ where = either.right
230
285
  }
231
286
 
232
- const getParts = buildParts(document, renderContext, template, where, elementRef, onCause, true)
233
-
234
287
  const wire = (() => {
235
288
  if (!parentTemplate) {
236
289
  const childNodes = Array.from(where.childNodes).filter((node) =>
@@ -253,10 +306,11 @@ export function getHydrateEntry({
253
306
  )
254
307
  })()
255
308
 
256
- return {
257
- template,
258
- wire,
259
- getParts,
260
- where
261
- } as const
309
+ return Either.right(
310
+ {
311
+ template,
312
+ wire,
313
+ where
314
+ } as const
315
+ )
262
316
  }
@@ -1,5 +1,6 @@
1
1
  import * as Deferred from "effect/Deferred"
2
2
  import * as Effect from "effect/Effect"
3
+ import * as Option from "effect/Option"
3
4
 
4
5
  export type IndexRefCounter = {
5
6
  release: (index: number) => Effect.Effect<never, never, void>
@@ -15,13 +16,16 @@ export function indexRefCounter(expected: number): Effect.Effect<
15
16
  IndexRefCounter
16
17
  > {
17
18
  return Effect.map(Deferred.make<never, void>(), (deferred) => {
19
+ const done = Deferred.succeed(deferred, undefined)
18
20
  const indexes = new Set<number>(Array.from({ length: expected }, (_, i) => i))
19
21
 
20
22
  function release(index: number) {
21
23
  return Effect.suspend(() => {
22
24
  if (indexes.delete(index) && indexes.size === 0) {
23
- return Deferred.succeed(deferred, undefined)
24
- } else return Effect.unit
25
+ return done
26
+ } else {
27
+ return Effect.unit
28
+ }
25
29
  })
26
30
  }
27
31
 
@@ -31,3 +35,60 @@ export function indexRefCounter(expected: number): Effect.Effect<
31
35
  }
32
36
  })
33
37
  }
38
+
39
+ export type IndexRefCounter2 = {
40
+ release: (index: number) => Effect.Effect<never, never, void>
41
+ expect: (count: number) => Effect.Effect<never, never, boolean>
42
+ wait: Effect.Effect<never, never, void>
43
+ }
44
+
45
+ /**
46
+ * @internal
47
+ */
48
+ export function indexRefCounter2(): Effect.Effect<
49
+ never,
50
+ never,
51
+ IndexRefCounter2
52
+ > {
53
+ return Effect.map(Deferred.make<never, void>(), (deferred) => {
54
+ let expected: Option.Option<number> = Option.none<number>()
55
+ const done = Deferred.succeed(deferred, undefined)
56
+ const indexes = new Set<number>()
57
+
58
+ function isDone() {
59
+ if (Option.isSome(expected)) {
60
+ return indexes.size === expected.value
61
+ } else {
62
+ return false
63
+ }
64
+ }
65
+
66
+ function release(index: number) {
67
+ return Effect.suspend(() => {
68
+ indexes.add(index)
69
+ if (isDone()) {
70
+ return done
71
+ } else {
72
+ return Effect.succeed(false)
73
+ }
74
+ })
75
+ }
76
+
77
+ function expect(count: number) {
78
+ return Effect.suspend(() => {
79
+ expected = Option.some(count)
80
+ if (isDone()) {
81
+ return Effect.as(done, false)
82
+ } else {
83
+ return Effect.succeed(true)
84
+ }
85
+ })
86
+ }
87
+
88
+ return {
89
+ release,
90
+ expect,
91
+ wait: Deferred.await(deferred)
92
+ }
93
+ })
94
+ }
@@ -42,7 +42,3 @@ declare global {
42
42
  declare module "@typed/fx/Fx" {
43
43
  export interface Fx<R, E, A> extends Placeholder<R, E, A> {}
44
44
  }
45
-
46
- declare module "effect/Effect" {
47
- export interface Effect<R, E, A> extends Placeholder<R, E, A> {}
48
- }