@typed/template 0.6.0 → 0.8.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.
- package/dist/cjs/ElementRef.js.map +1 -1
- package/dist/cjs/ElementSource.js.map +1 -1
- package/dist/cjs/Html.js +12 -2
- package/dist/cjs/Html.js.map +1 -1
- package/dist/cjs/Hydrate.js +15 -7
- package/dist/cjs/Hydrate.js.map +1 -1
- package/dist/cjs/Many.js.map +1 -1
- package/dist/cjs/Render.js +17 -7
- package/dist/cjs/Render.js.map +1 -1
- package/dist/cjs/RenderTemplate.js.map +1 -1
- package/dist/cjs/Test.js +10 -5
- package/dist/cjs/Test.js.map +1 -1
- package/dist/cjs/internal/hydrate.js +10 -5
- package/dist/cjs/internal/hydrate.js.map +1 -1
- package/dist/cjs/internal/parts.js.map +1 -1
- package/dist/cjs/internal/render.js +8 -5
- package/dist/cjs/internal/render.js.map +1 -1
- package/dist/cjs/internal/server.js +2 -6
- package/dist/cjs/internal/server.js.map +1 -1
- package/dist/dts/Directive.d.ts +13 -13
- package/dist/dts/Directive.d.ts.map +1 -1
- package/dist/dts/ElementRef.d.ts +2 -2
- package/dist/dts/ElementRef.d.ts.map +1 -1
- package/dist/dts/ElementSource.d.ts +4 -4
- package/dist/dts/ElementSource.d.ts.map +1 -1
- package/dist/dts/EventHandler.d.ts +11 -11
- package/dist/dts/EventHandler.d.ts.map +1 -1
- package/dist/dts/Html.d.ts +13 -3
- package/dist/dts/Html.d.ts.map +1 -1
- package/dist/dts/Hydrate.d.ts +12 -4
- package/dist/dts/Hydrate.d.ts.map +1 -1
- package/dist/dts/Many.d.ts +8 -8
- package/dist/dts/Many.d.ts.map +1 -1
- package/dist/dts/Part.d.ts +1 -1
- package/dist/dts/Part.d.ts.map +1 -1
- package/dist/dts/Placeholder.d.ts +6 -6
- package/dist/dts/Placeholder.d.ts.map +1 -1
- package/dist/dts/Platform.d.ts +1 -1
- package/dist/dts/Platform.d.ts.map +1 -1
- package/dist/dts/Render.d.ts +16 -5
- package/dist/dts/Render.d.ts.map +1 -1
- package/dist/dts/RenderTemplate.d.ts +2 -2
- package/dist/dts/RenderTemplate.d.ts.map +1 -1
- package/dist/dts/Renderable.d.ts +3 -3
- package/dist/dts/Renderable.d.ts.map +1 -1
- package/dist/dts/Test.d.ts +10 -14
- package/dist/dts/Test.d.ts.map +1 -1
- package/dist/dts/internal/EventSource.d.ts +1 -1
- package/dist/dts/internal/EventSource.d.ts.map +1 -1
- package/dist/dts/internal/hydrate.d.ts.map +1 -1
- package/dist/dts/internal/module-augmentation.d.ts +13 -13
- package/dist/dts/internal/module-augmentation.d.ts.map +1 -1
- package/dist/dts/internal/parts.d.ts +2 -2
- package/dist/dts/internal/parts.d.ts.map +1 -1
- package/dist/dts/internal/render.d.ts.map +1 -1
- package/dist/dts/internal/server.d.ts.map +1 -1
- package/dist/esm/ElementRef.js.map +1 -1
- package/dist/esm/ElementSource.js.map +1 -1
- package/dist/esm/Html.js +13 -2
- package/dist/esm/Html.js.map +1 -1
- package/dist/esm/Hydrate.js +11 -5
- package/dist/esm/Hydrate.js.map +1 -1
- package/dist/esm/Many.js.map +1 -1
- package/dist/esm/Render.js +13 -5
- package/dist/esm/Render.js.map +1 -1
- package/dist/esm/RenderTemplate.js.map +1 -1
- package/dist/esm/Test.js +12 -7
- package/dist/esm/Test.js.map +1 -1
- package/dist/esm/internal/hydrate.js +9 -6
- package/dist/esm/internal/hydrate.js.map +1 -1
- package/dist/esm/internal/parts.js.map +1 -1
- package/dist/esm/internal/render.js +7 -6
- package/dist/esm/internal/render.js.map +1 -1
- package/dist/esm/internal/server.js +2 -6
- package/dist/esm/internal/server.js.map +1 -1
- package/package.json +5 -5
- package/src/Directive.ts +19 -19
- package/src/ElementRef.ts +6 -6
- package/src/ElementSource.ts +16 -16
- package/src/EventHandler.ts +11 -11
- package/src/Html.ts +56 -37
- package/src/Hydrate.ts +41 -14
- package/src/Many.ts +26 -26
- package/src/Part.ts +1 -1
- package/src/Placeholder.ts +13 -13
- package/src/Platform.ts +3 -3
- package/src/Render.ts +52 -15
- package/src/RenderTemplate.ts +2 -6
- package/src/Renderable.ts +5 -5
- package/src/Test.ts +30 -20
- package/src/internal/EventSource.ts +1 -1
- package/src/internal/hydrate.ts +10 -11
- package/src/internal/module-augmentation.ts +15 -15
- package/src/internal/parts.ts +1 -1
- package/src/internal/render.ts +15 -16
- package/src/internal/server.ts +0 -2
package/src/Html.ts
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
* @since 1.0.0
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import type { CurrentEnvironment } from "@typed/environment"
|
|
5
6
|
import * as Fx from "@typed/fx/Fx"
|
|
6
7
|
import * as Sink from "@typed/fx/Sink"
|
|
7
8
|
import { TypeId } from "@typed/fx/TypeId"
|
|
8
9
|
import * as Effect from "effect/Effect"
|
|
10
|
+
import * as Layer from "effect/Layer"
|
|
9
11
|
import * as Option from "effect/Option"
|
|
10
12
|
import { join } from "effect/ReadonlyArray"
|
|
11
13
|
import type * as Scope from "effect/Scope"
|
|
@@ -18,7 +20,7 @@ import { partNodeToPart } from "./internal/server.js"
|
|
|
18
20
|
import { TEXT_START, TYPED_END, TYPED_HOLE, TYPED_START } from "./Meta.js"
|
|
19
21
|
import type { Placeholder } from "./Placeholder.js"
|
|
20
22
|
import type { Renderable } from "./Renderable.js"
|
|
21
|
-
import
|
|
23
|
+
import * as RenderContext from "./RenderContext.js"
|
|
22
24
|
import { HtmlRenderEvent, isRenderEvent } from "./RenderEvent.js"
|
|
23
25
|
import type { RenderEvent } from "./RenderEvent.js"
|
|
24
26
|
import { RenderTemplate } from "./RenderTemplate.js"
|
|
@@ -30,13 +32,30 @@ const [padStart, padEnd] = [[TYPED_START], [TYPED_END]] as const
|
|
|
30
32
|
/**
|
|
31
33
|
* @since 1.0.0
|
|
32
34
|
*/
|
|
33
|
-
export
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
export const serverLayer: Layer.Layer<RenderContext.RenderContext | RenderTemplate | CurrentEnvironment> = Layer
|
|
36
|
+
.provideMerge(
|
|
37
|
+
RenderTemplate.layer(RenderContext.RenderContext.with(renderHtml)),
|
|
38
|
+
RenderContext.server
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @since 1.0.0
|
|
43
|
+
*/
|
|
44
|
+
export const staticLayer: Layer.Layer<RenderContext.RenderContext | RenderTemplate | CurrentEnvironment> = Layer
|
|
45
|
+
.provideMerge(
|
|
46
|
+
RenderTemplate.layer(RenderContext.RenderContext.with(renderHtml)),
|
|
47
|
+
RenderContext.static
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @since 1.0.0
|
|
52
|
+
*/
|
|
53
|
+
export function renderToHtml<E, R>(
|
|
54
|
+
fx: Fx.Fx<RenderEvent, E, R>
|
|
55
|
+
): Fx.Fx<string, E, R | RenderTemplate | RenderContext.RenderContext> {
|
|
36
56
|
return Fx.fromFxEffect(
|
|
37
|
-
RenderContext.with((ctx) =>
|
|
57
|
+
RenderContext.RenderContext.with((ctx) =>
|
|
38
58
|
fx.pipe(
|
|
39
|
-
Fx.provide(RenderTemplate.layer(renderHtml(ctx))),
|
|
40
59
|
Fx.map(toHtml),
|
|
41
60
|
(x) => ctx.environment === "static" ? x : Fx.padWith(x, padStart, padEnd)
|
|
42
61
|
)
|
|
@@ -47,20 +66,20 @@ export function renderToHtml<R, E>(
|
|
|
47
66
|
/**
|
|
48
67
|
* @since 1.0.0
|
|
49
68
|
*/
|
|
50
|
-
export function renderToHtmlString<
|
|
51
|
-
fx: Fx.Fx<
|
|
52
|
-
): Effect.Effect<string, E,
|
|
69
|
+
export function renderToHtmlString<E, R>(
|
|
70
|
+
fx: Fx.Fx<RenderEvent, E, R>
|
|
71
|
+
): Effect.Effect<string, E, R | RenderTemplate | RenderContext.RenderContext> {
|
|
53
72
|
return Effect.map(Fx.toReadonlyArray(renderToHtml(fx)), join(""))
|
|
54
73
|
}
|
|
55
74
|
|
|
56
|
-
function renderHtml(ctx: RenderContext) {
|
|
75
|
+
function renderHtml(ctx: RenderContext.RenderContext) {
|
|
57
76
|
return <Values extends ReadonlyArray<Renderable<any, any>>>(
|
|
58
77
|
templateStrings: TemplateStringsArray,
|
|
59
78
|
values: Values
|
|
60
79
|
): Fx.Fx<
|
|
61
|
-
|
|
80
|
+
RenderEvent,
|
|
62
81
|
Placeholder.Error<Values[number]>,
|
|
63
|
-
|
|
82
|
+
Scope.Scope | Placeholder.Context<readonly [] extends Values ? never : Values[number]>
|
|
64
83
|
> => {
|
|
65
84
|
const isStatic = ctx.environment === "static"
|
|
66
85
|
const entry = getServerEntry(templateStrings, ctx.templateCache, isStatic)
|
|
@@ -71,8 +90,8 @@ function renderHtml(ctx: RenderContext) {
|
|
|
71
90
|
Fx.mergeOrdered(
|
|
72
91
|
entry.chunks.map((chunk) =>
|
|
73
92
|
renderChunk<
|
|
74
|
-
Placeholder.
|
|
75
|
-
Placeholder.
|
|
93
|
+
Placeholder.Error<Values[number]>,
|
|
94
|
+
Placeholder.Context<readonly [] extends Values ? never : Values[number]>
|
|
76
95
|
>(chunk, values, isStatic)
|
|
77
96
|
)
|
|
78
97
|
),
|
|
@@ -82,21 +101,21 @@ function renderHtml(ctx: RenderContext) {
|
|
|
82
101
|
}
|
|
83
102
|
}
|
|
84
103
|
|
|
85
|
-
function renderChunk<
|
|
104
|
+
function renderChunk<E, R>(
|
|
86
105
|
chunk: HtmlChunk,
|
|
87
106
|
values: ReadonlyArray<Renderable<any, any>>,
|
|
88
107
|
isStatic: boolean
|
|
89
|
-
): Fx.Fx<
|
|
108
|
+
): Fx.Fx<RenderEvent, E, R> {
|
|
90
109
|
if (chunk._tag === "text") {
|
|
91
110
|
return Fx.succeed(HtmlRenderEvent(chunk.value))
|
|
92
111
|
} else if (chunk._tag === "part") {
|
|
93
|
-
return renderPart<
|
|
112
|
+
return renderPart<E, R>(chunk, values, isStatic)
|
|
94
113
|
} else {
|
|
95
|
-
return renderSparsePart<
|
|
114
|
+
return renderSparsePart<E, R>(chunk, values) as Fx.Fx<RenderEvent, E, R>
|
|
96
115
|
}
|
|
97
116
|
}
|
|
98
117
|
|
|
99
|
-
function renderNode<
|
|
118
|
+
function renderNode<E, R>(renderable: Renderable<any, any>, isStatic: boolean): Fx.Fx<RenderEvent, E, R> {
|
|
100
119
|
switch (typeof renderable) {
|
|
101
120
|
case "string":
|
|
102
121
|
case "number":
|
|
@@ -111,7 +130,7 @@ function renderNode<R, E>(renderable: Renderable<any, any>, isStatic: boolean):
|
|
|
111
130
|
}
|
|
112
131
|
}
|
|
113
132
|
|
|
114
|
-
function renderObject<
|
|
133
|
+
function renderObject<E, R>(renderable: object | null | undefined, isStatic: boolean) {
|
|
115
134
|
if (renderable === null || renderable === undefined) {
|
|
116
135
|
return isStatic ? Fx.empty : Fx.succeed(HtmlRenderEvent(TEXT_START))
|
|
117
136
|
} else if (Array.isArray(renderable)) {
|
|
@@ -122,7 +141,7 @@ function renderObject<R, E>(renderable: object | null | undefined, isStatic: boo
|
|
|
122
141
|
} else if (Effect.isEffect(renderable)) {
|
|
123
142
|
return Fx.switchMap(
|
|
124
143
|
Fx.fromEffect(renderable as Effect.Effect<Renderable, E, R>),
|
|
125
|
-
(r) => renderNode<
|
|
144
|
+
(r) => renderNode<E, R>(r, isStatic)
|
|
126
145
|
)
|
|
127
146
|
} else if (isRenderEvent(renderable)) {
|
|
128
147
|
return Fx.succeed(renderable)
|
|
@@ -131,17 +150,17 @@ function renderObject<R, E>(renderable: object | null | undefined, isStatic: boo
|
|
|
131
150
|
}
|
|
132
151
|
}
|
|
133
152
|
|
|
134
|
-
function renderPart<
|
|
153
|
+
function renderPart<E, R>(
|
|
135
154
|
chunk: PartChunk,
|
|
136
155
|
values: ReadonlyArray<Renderable<any, any>>,
|
|
137
156
|
isStatic: boolean
|
|
138
|
-
): Fx.Fx<
|
|
157
|
+
): Fx.Fx<RenderEvent, E, R> {
|
|
139
158
|
const { node, render } = chunk
|
|
140
159
|
const renderable: Renderable<any, any> = values[node.index]
|
|
141
160
|
|
|
142
161
|
// Refs and events are not rendered into HTML
|
|
143
|
-
if (isDirective<
|
|
144
|
-
return Fx.make((sink: Sink.Sink<
|
|
162
|
+
if (isDirective<E, R>(renderable)) {
|
|
163
|
+
return Fx.make<RenderEvent, E, R>((sink: Sink.Sink<RenderEvent, E>) => {
|
|
145
164
|
const part = partNodeToPart(
|
|
146
165
|
node,
|
|
147
166
|
(value) => sink.onSuccess(HtmlRenderEvent(render(value)))
|
|
@@ -150,8 +169,8 @@ function renderPart<R, E>(
|
|
|
150
169
|
return Effect.catchAllCause(renderable(part), sink.onFailure)
|
|
151
170
|
})
|
|
152
171
|
} else if (node._tag === "node") {
|
|
153
|
-
if (isStatic) return renderNode<
|
|
154
|
-
return Fx.append(renderNode<
|
|
172
|
+
if (isStatic) return renderNode<E, R>(renderable, isStatic)
|
|
173
|
+
return Fx.append(renderNode<E, R>(renderable, isStatic), HtmlRenderEvent(TYPED_HOLE(node.index)))
|
|
155
174
|
} else if (node._tag === "properties") {
|
|
156
175
|
if (renderable == null) return Fx.empty
|
|
157
176
|
return Fx.map(
|
|
@@ -166,7 +185,7 @@ function renderPart<R, E>(
|
|
|
166
185
|
} else {
|
|
167
186
|
if (renderable === null) return Fx.succeed(HtmlRenderEvent(render(renderable)))
|
|
168
187
|
|
|
169
|
-
const html = Fx.filterMap(Fx.take(unwrapRenderable<
|
|
188
|
+
const html = Fx.filterMap(Fx.take(unwrapRenderable<E, R>(renderable), 1), (value) => {
|
|
170
189
|
const s = render(value)
|
|
171
190
|
|
|
172
191
|
return s ? Option.some(HtmlRenderEvent(s)) : Option.none()
|
|
@@ -180,10 +199,10 @@ function renderPart<R, E>(
|
|
|
180
199
|
}
|
|
181
200
|
}
|
|
182
201
|
|
|
183
|
-
function renderSparsePart<
|
|
202
|
+
function renderSparsePart<E, R>(
|
|
184
203
|
chunk: SparsePartChunk,
|
|
185
204
|
values: ReadonlyArray<Renderable<any, any>>
|
|
186
|
-
): Fx.Fx<
|
|
205
|
+
): Fx.Fx<RenderEvent, E, R> {
|
|
187
206
|
const { node, render } = chunk
|
|
188
207
|
|
|
189
208
|
return Fx.map(
|
|
@@ -194,8 +213,8 @@ function renderSparsePart<R, E>(
|
|
|
194
213
|
|
|
195
214
|
const renderable: Renderable<any, any> = (values as any)[node.index]
|
|
196
215
|
|
|
197
|
-
if (isDirective<
|
|
198
|
-
return Fx.make<
|
|
216
|
+
if (isDirective<E, R>(renderable)) {
|
|
217
|
+
return Fx.make<unknown, E, R>((sink: Sink.Sink<unknown, E>) =>
|
|
199
218
|
Effect.catchAllCause(
|
|
200
219
|
renderable(partNodeToPart(node, (value) => sink.onSuccess(value))),
|
|
201
220
|
sink.onFailure
|
|
@@ -203,7 +222,7 @@ function renderSparsePart<R, E>(
|
|
|
203
222
|
)
|
|
204
223
|
}
|
|
205
224
|
|
|
206
|
-
return unwrapRenderable<
|
|
225
|
+
return unwrapRenderable<E, R>(renderable)
|
|
207
226
|
})
|
|
208
227
|
),
|
|
209
228
|
1
|
|
@@ -212,8 +231,8 @@ function renderSparsePart<R, E>(
|
|
|
212
231
|
)
|
|
213
232
|
}
|
|
214
233
|
|
|
215
|
-
function takeOneIfNotRenderEvent<
|
|
216
|
-
return Fx.make<
|
|
234
|
+
function takeOneIfNotRenderEvent<A, E, R>(fx: Fx.Fx<A, E, R>): Fx.Fx<A, E, R> {
|
|
235
|
+
return Fx.make<A, E, R>((sink) =>
|
|
217
236
|
Sink.withEarlyExit(sink, (sink) =>
|
|
218
237
|
fx.run(
|
|
219
238
|
Sink.make(
|
|
@@ -227,7 +246,7 @@ function takeOneIfNotRenderEvent<R, E, A>(fx: Fx.Fx<R, E, A>): Fx.Fx<R, E, A> {
|
|
|
227
246
|
|
|
228
247
|
function getServerEntry(
|
|
229
248
|
templateStrings: TemplateStringsArray,
|
|
230
|
-
templateCache: RenderContext["templateCache"],
|
|
249
|
+
templateCache: RenderContext.RenderContext["templateCache"],
|
|
231
250
|
isStatic: boolean
|
|
232
251
|
): ServerEntry {
|
|
233
252
|
const cached = templateCache.get(templateStrings)
|
|
@@ -249,7 +268,7 @@ function getServerEntry(
|
|
|
249
268
|
}
|
|
250
269
|
}
|
|
251
270
|
|
|
252
|
-
function unwrapRenderable<
|
|
271
|
+
function unwrapRenderable<E, R>(renderable: Renderable<any, any>): Fx.Fx<any, E, R> {
|
|
253
272
|
switch (typeof renderable) {
|
|
254
273
|
case "undefined":
|
|
255
274
|
case "object": {
|
package/src/Hydrate.ts
CHANGED
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Context from "@typed/context"
|
|
6
6
|
import { Document } from "@typed/dom/Document"
|
|
7
|
+
import type { DomServices, DomServicesElementParams } from "@typed/dom/DomServices"
|
|
8
|
+
import type { GlobalThis } from "@typed/dom/GlobalThis"
|
|
7
9
|
import { RootElement } from "@typed/dom/RootElement"
|
|
10
|
+
import type { CurrentEnvironment } from "@typed/environment"
|
|
8
11
|
import * as Fx from "@typed/fx/Fx"
|
|
9
12
|
import * as Effect from "effect/Effect"
|
|
10
13
|
import * as Layer from "effect/Layer"
|
|
@@ -12,18 +15,47 @@ import { findRootParentChildNodes, hydrateTemplate } from "./internal/hydrate.js
|
|
|
12
15
|
import { HydrateContext } from "./internal/HydrateContext.js"
|
|
13
16
|
import { attachRoot } from "./internal/render.js"
|
|
14
17
|
import type { ToRendered } from "./Render.js"
|
|
15
|
-
import
|
|
18
|
+
import * as RenderContext from "./RenderContext.js"
|
|
16
19
|
import { type RenderEvent } from "./RenderEvent.js"
|
|
17
20
|
import { RenderTemplate } from "./RenderTemplate.js"
|
|
18
21
|
|
|
22
|
+
/**
|
|
23
|
+
* @since 1.0.0
|
|
24
|
+
*/
|
|
25
|
+
export const hydrateLayer = (
|
|
26
|
+
window: Window & GlobalThis,
|
|
27
|
+
options?: DomServicesElementParams & { readonly skipRenderScheduling?: boolean }
|
|
28
|
+
): Layer.Layer<
|
|
29
|
+
| RenderTemplate
|
|
30
|
+
| RenderContext.RenderContext
|
|
31
|
+
| CurrentEnvironment
|
|
32
|
+
| DomServices
|
|
33
|
+
> =>
|
|
34
|
+
Layer.provideMerge(
|
|
35
|
+
RenderTemplate.layer(Effect.contextWith((context: Context.Context<Document | RenderContext.RenderContext>) => {
|
|
36
|
+
const [document, ctx] = Context.getMany(
|
|
37
|
+
context,
|
|
38
|
+
Document,
|
|
39
|
+
RenderContext.RenderContext
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
return hydrateTemplate(document, ctx)
|
|
43
|
+
})),
|
|
44
|
+
RenderContext.dom(window, options)
|
|
45
|
+
)
|
|
46
|
+
|
|
19
47
|
/**
|
|
20
48
|
* @since 1.0.0
|
|
21
49
|
*/
|
|
22
50
|
export function hydrate<R, E, T extends RenderEvent | null>(
|
|
23
|
-
rendered: Fx.Fx<
|
|
24
|
-
): Fx.Fx<
|
|
51
|
+
rendered: Fx.Fx<T, E, R>
|
|
52
|
+
): Fx.Fx<ToRendered<T>, E, R | RenderTemplate | RenderContext.RenderContext | RootElement> {
|
|
25
53
|
return Fx.fromFxEffect(Effect.contextWith((context) => {
|
|
26
|
-
const [
|
|
54
|
+
const [renderContext, { rootElement }] = Context.getMany(
|
|
55
|
+
context,
|
|
56
|
+
RenderContext.RenderContext,
|
|
57
|
+
RootElement
|
|
58
|
+
)
|
|
27
59
|
const ctx: HydrateContext = {
|
|
28
60
|
where: findRootParentChildNodes(rootElement),
|
|
29
61
|
rootIndex: -1,
|
|
@@ -31,23 +63,18 @@ export function hydrate<R, E, T extends RenderEvent | null>(
|
|
|
31
63
|
hydrate: true
|
|
32
64
|
}
|
|
33
65
|
|
|
34
|
-
const layer = Layer.provideMerge(
|
|
35
|
-
HydrateContext.layer(ctx),
|
|
36
|
-
RenderTemplate.layer(hydrateTemplate(document, renderContext))
|
|
37
|
-
)
|
|
38
|
-
|
|
39
66
|
return Fx.provide(
|
|
40
67
|
Fx.mapEffect(rendered, (what) => attachRoot(renderContext.renderCache, rootElement, what)),
|
|
41
|
-
layer
|
|
68
|
+
HydrateContext.layer(ctx)
|
|
42
69
|
)
|
|
43
|
-
}))
|
|
70
|
+
}))
|
|
44
71
|
}
|
|
45
72
|
|
|
46
73
|
/**
|
|
47
74
|
* @since 1.0.0
|
|
48
75
|
*/
|
|
49
|
-
export function
|
|
50
|
-
rendered: Fx.Fx<
|
|
51
|
-
) {
|
|
76
|
+
export function hydrateToLayer<R, E, T extends RenderEvent | null>(
|
|
77
|
+
rendered: Fx.Fx<T, E, R>
|
|
78
|
+
): Layer.Layer<never, never, R | RenderTemplate | RenderContext.RenderContext | RootElement> {
|
|
52
79
|
return Fx.drainLayer(Fx.switchMapCause(hydrate(rendered), (cause) => Fx.fromEffect(Effect.logError(cause))))
|
|
53
80
|
}
|
package/src/Many.ts
CHANGED
|
@@ -20,14 +20,14 @@ import { HtmlRenderEvent, type RenderEvent } from "./RenderEvent.js"
|
|
|
20
20
|
/**
|
|
21
21
|
* @since 1.0.0
|
|
22
22
|
*/
|
|
23
|
-
export function many<
|
|
24
|
-
values: Fx.Fx<
|
|
23
|
+
export function many<A, E, R, B extends PropertyKey, R2, E2>(
|
|
24
|
+
values: Fx.Fx<ReadonlyArray<A>, E, R>,
|
|
25
25
|
getKey: (a: NoInfer<A>) => B,
|
|
26
|
-
f: (a: RefSubject.RefSubject<
|
|
27
|
-
): Fx.Fx<
|
|
26
|
+
f: (a: RefSubject.RefSubject<NoInfer<A>>, key: B) => Fx.Fx<RenderEvent, E2, R2>
|
|
27
|
+
): Fx.Fx<RenderEvent | ReadonlyArray<RenderEvent>, E | E2, R | R2 | Scope.Scope | RenderContext> {
|
|
28
28
|
return Fx.fromFxEffect(
|
|
29
29
|
Effect.contextWith(
|
|
30
|
-
(context): Fx.Fx<
|
|
30
|
+
(context): Fx.Fx<RenderEvent | ReadonlyArray<RenderEvent>, E | E2, R | R2 | RenderContext | Scope.Scope> => {
|
|
31
31
|
const ctx = get(context, RenderContext)
|
|
32
32
|
const hydrateContext = getOption(context, HydrateContext)
|
|
33
33
|
|
|
@@ -87,15 +87,15 @@ export const manyAsyncData: {
|
|
|
87
87
|
matchers: {
|
|
88
88
|
NoData: () => NoData
|
|
89
89
|
Loading: (todo: TODO) => Loading
|
|
90
|
-
Failure: (data: RefSubject.Computed<
|
|
91
|
-
Success: (value: RefSubject.Computed<
|
|
90
|
+
Failure: (data: RefSubject.Computed<E1>, computed: TODO) => Failure
|
|
91
|
+
Success: (value: RefSubject.Computed<A>, computed: TODO) => Success
|
|
92
92
|
}
|
|
93
|
-
): <
|
|
94
|
-
fx: Fx.Fx<
|
|
93
|
+
): <E, R>(
|
|
94
|
+
fx: Fx.Fx<AsyncData.AsyncData<ReadonlyArray<A>, E1>, E, R>
|
|
95
95
|
) => Fx.Fx<
|
|
96
|
-
|
|
96
|
+
Fx.Fx.Success<NoData | Loading | Failure | Success>,
|
|
97
97
|
E | Fx.Fx.Error<NoData | Loading | Failure | Success>,
|
|
98
|
-
Fx.Fx.
|
|
98
|
+
R | Fx.Fx.Context<NoData | Loading | Failure | Success>
|
|
99
99
|
>
|
|
100
100
|
|
|
101
101
|
<
|
|
@@ -109,18 +109,18 @@ export const manyAsyncData: {
|
|
|
109
109
|
Failure extends Fx.Fx<any, any, any>,
|
|
110
110
|
Success extends Fx.Fx<any, any, any>
|
|
111
111
|
>(
|
|
112
|
-
fx: Fx.Fx<
|
|
112
|
+
fx: Fx.Fx<AsyncData.AsyncData<ReadonlyArray<A>, E1>, E, R>,
|
|
113
113
|
getKey: (a: A) => B,
|
|
114
114
|
matchers: {
|
|
115
115
|
NoData: () => NoData
|
|
116
116
|
Loading: (data: TODO) => Loading
|
|
117
|
-
Failure: (data: RefSubject.Computed<
|
|
118
|
-
Success: (value: RefSubject.Computed<
|
|
117
|
+
Failure: (data: RefSubject.Computed<E1>, computed: TODO) => Failure
|
|
118
|
+
Success: (value: RefSubject.Computed<A>, computed: TODO) => Success
|
|
119
119
|
}
|
|
120
120
|
): Fx.Fx<
|
|
121
|
-
|
|
121
|
+
Fx.Fx.Success<NoData | Loading | Failure | Success>,
|
|
122
122
|
E | Fx.Fx.Error<NoData | Loading | Failure | Success>,
|
|
123
|
-
Fx.Fx.
|
|
123
|
+
R | Fx.Fx.Context<NoData | Loading | Failure | Success>
|
|
124
124
|
>
|
|
125
125
|
} = dual(
|
|
126
126
|
3,
|
|
@@ -130,23 +130,23 @@ export const manyAsyncData: {
|
|
|
130
130
|
E1,
|
|
131
131
|
A,
|
|
132
132
|
B extends PropertyKey,
|
|
133
|
-
NoData extends Fx.Fx<
|
|
134
|
-
Loading extends Fx.Fx<
|
|
135
|
-
Failure extends Fx.Fx<
|
|
136
|
-
Success extends Fx.Fx<
|
|
133
|
+
NoData extends Fx.Fx<RenderEvent, any, any>,
|
|
134
|
+
Loading extends Fx.Fx<RenderEvent, any, any>,
|
|
135
|
+
Failure extends Fx.Fx<RenderEvent, any, any>,
|
|
136
|
+
Success extends Fx.Fx<RenderEvent, any, any>
|
|
137
137
|
>(
|
|
138
|
-
fx: Fx.Fx<
|
|
138
|
+
fx: Fx.Fx<AsyncData.AsyncData<ReadonlyArray<A>, E1>, E, R>,
|
|
139
139
|
getKey: (a: A) => B,
|
|
140
140
|
matchers: {
|
|
141
141
|
NoData: NoData
|
|
142
|
-
Loading: (data: RefSubject.Filtered<
|
|
143
|
-
Failure: (data: RefSubject.Computed<
|
|
144
|
-
Success: (value: RefSubject.Computed<
|
|
142
|
+
Loading: (data: RefSubject.Filtered<Progress>) => Loading
|
|
143
|
+
Failure: (data: RefSubject.Computed<E1>) => Failure
|
|
144
|
+
Success: (value: RefSubject.Computed<A>, key: B) => Success
|
|
145
145
|
}
|
|
146
146
|
): Fx.Fx<
|
|
147
|
-
|
|
147
|
+
RenderEvent | ReadonlyArray<RenderEvent>,
|
|
148
148
|
E | Fx.Fx.Error<NoData | Loading | Failure | Success>,
|
|
149
|
-
|
|
149
|
+
R | Fx.Fx.Context<NoData | Loading | Failure | Success>
|
|
150
150
|
> => {
|
|
151
151
|
return RefAsyncData.matchAsyncData(fx, {
|
|
152
152
|
NoData: matchers.NoData,
|
package/src/Part.ts
CHANGED
|
@@ -80,7 +80,7 @@ export interface EventPart {
|
|
|
80
80
|
readonly value: null
|
|
81
81
|
readonly index: number
|
|
82
82
|
readonly onCause: (cause: Cause<unknown>) => Effect<unknown>
|
|
83
|
-
readonly addEventListener: (handler: EventHandler<
|
|
83
|
+
readonly addEventListener: (handler: EventHandler<Event>) => void
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/**
|
package/src/Placeholder.ts
CHANGED
|
@@ -21,7 +21,7 @@ export type PlaceholderTypeId = typeof PlaceholderTypeId
|
|
|
21
21
|
/**
|
|
22
22
|
* @since 1.0.0
|
|
23
23
|
*/
|
|
24
|
-
export interface Placeholder<
|
|
24
|
+
export interface Placeholder<A = unknown, E = never, R = never> {
|
|
25
25
|
readonly [PlaceholderTypeId]: {
|
|
26
26
|
readonly _R: (_: never) => R
|
|
27
27
|
readonly _E: (_: never) => E
|
|
@@ -37,32 +37,32 @@ export namespace Placeholder {
|
|
|
37
37
|
* @since 1.0.0
|
|
38
38
|
*/
|
|
39
39
|
export type Any<A = any> =
|
|
40
|
-
| Placeholder<
|
|
41
|
-
| Placeholder<
|
|
42
|
-
| Placeholder<
|
|
43
|
-
| Placeholder<
|
|
40
|
+
| Placeholder<A, any, any>
|
|
41
|
+
| Placeholder<A, never, any>
|
|
42
|
+
| Placeholder<A>
|
|
43
|
+
| Placeholder<A, any>
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* @since 1.0.0
|
|
47
47
|
*/
|
|
48
|
-
export type Context<T> = [T] extends [never] ? never : T extends Placeholder<infer
|
|
48
|
+
export type Context<T> = [T] extends [never] ? never : T extends Placeholder<infer _A, infer _E, infer R> ? R : never
|
|
49
49
|
/**
|
|
50
50
|
* @since 1.0.0
|
|
51
51
|
*/
|
|
52
|
-
export type Error<T> = [T] extends [never] ? never : T extends Placeholder<infer
|
|
52
|
+
export type Error<T> = [T] extends [never] ? never : T extends Placeholder<infer _A, infer E, infer _R> ? E : never
|
|
53
53
|
/**
|
|
54
54
|
* @since 1.0.0
|
|
55
55
|
*/
|
|
56
|
-
export type Success<T> = [T] extends [never] ? never : T extends Placeholder<infer
|
|
56
|
+
export type Success<T> = [T] extends [never] ? never : T extends Placeholder<infer A, infer _E, infer _R> ? A : never
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
59
|
* @since 1.0.0
|
|
60
60
|
*/
|
|
61
|
-
export function asRef<
|
|
62
|
-
placeholder: Placeholder<
|
|
63
|
-
): Effect.Effect<RefSubject.RefSubject<
|
|
64
|
-
if (isFx<
|
|
65
|
-
return RefSubject.make(placeholder as Fx<
|
|
61
|
+
export function asRef<A = never, E = never, R = never>(
|
|
62
|
+
placeholder: Placeholder<A, E, R> | Fx<A, E, R> | Effect.Effect<A, E, R> | A
|
|
63
|
+
): Effect.Effect<RefSubject.RefSubject<A, E>, never, R | Scope.Scope> {
|
|
64
|
+
if (isFx<A, E, R>(placeholder) || Effect.isEffect(placeholder)) {
|
|
65
|
+
return RefSubject.make(placeholder as Fx<A, E, R>)
|
|
66
66
|
} else {
|
|
67
67
|
return RefSubject.of<A, E>(placeholder as A)
|
|
68
68
|
}
|
package/src/Platform.ts
CHANGED
|
@@ -20,10 +20,10 @@ const HYPHENATED_CONTENT_TYPE = { "content-type": HTML_CONTENT_TYPE }
|
|
|
20
20
|
/**
|
|
21
21
|
* @since 1.0.0
|
|
22
22
|
*/
|
|
23
|
-
export function htmlResponse<
|
|
24
|
-
fx: Fx.Fx<
|
|
23
|
+
export function htmlResponse<E, R>(
|
|
24
|
+
fx: Fx.Fx<RenderEvent, E, R>,
|
|
25
25
|
options?: HttpServer.response.Options
|
|
26
|
-
): Effect.Effect<HttpServer.response.ServerResponse, E,
|
|
26
|
+
): Effect.Effect<HttpServer.response.ServerResponse, E, R | RenderTemplate | RenderContext.RenderContext> {
|
|
27
27
|
return Effect.contextWithEffect((ctx) =>
|
|
28
28
|
HttpServer.response.stream(
|
|
29
29
|
Stream.provideContext(Stream.encodeText(toStream(renderToHtml(fx))), ctx),
|
package/src/Render.ts
CHANGED
|
@@ -4,13 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Context from "@typed/context"
|
|
6
6
|
import { Document } from "@typed/dom/Document"
|
|
7
|
+
import type { DomServices, DomServicesElementParams } from "@typed/dom/DomServices"
|
|
8
|
+
import type { GlobalThis } from "@typed/dom/GlobalThis"
|
|
7
9
|
import { RootElement } from "@typed/dom/RootElement"
|
|
10
|
+
import type { CurrentEnvironment } from "@typed/environment"
|
|
8
11
|
import * as Fx from "@typed/fx/Fx"
|
|
9
12
|
import { type Rendered } from "@typed/wire"
|
|
10
|
-
import type {
|
|
13
|
+
import type { Scope } from "effect"
|
|
14
|
+
import { Layer } from "effect"
|
|
11
15
|
import * as Effect from "effect/Effect"
|
|
12
16
|
import { attachRoot, renderTemplate } from "./internal/render.js"
|
|
13
|
-
import
|
|
17
|
+
import * as RenderContext from "./RenderContext.js"
|
|
14
18
|
import { type RenderEvent } from "./RenderEvent.js"
|
|
15
19
|
import { RenderTemplate } from "./RenderTemplate.js"
|
|
16
20
|
|
|
@@ -19,32 +23,65 @@ import { RenderTemplate } from "./RenderTemplate.js"
|
|
|
19
23
|
*/
|
|
20
24
|
export type ToRendered<T extends RenderEvent | null> = T extends null ? Rendered | null : Rendered
|
|
21
25
|
|
|
26
|
+
/**
|
|
27
|
+
* @since 1.0.0
|
|
28
|
+
*/
|
|
29
|
+
export const renderLayer = (
|
|
30
|
+
window: Window & GlobalThis,
|
|
31
|
+
options?: DomServicesElementParams & { readonly skipRenderScheduling?: boolean }
|
|
32
|
+
): Layer.Layer<
|
|
33
|
+
| RenderTemplate
|
|
34
|
+
| RenderContext.RenderContext
|
|
35
|
+
| CurrentEnvironment
|
|
36
|
+
| DomServices
|
|
37
|
+
> =>
|
|
38
|
+
Layer.provideMerge(
|
|
39
|
+
RenderTemplate.layer(Effect.contextWith((context: Context.Context<Document | RenderContext.RenderContext>) => {
|
|
40
|
+
const [document, ctx] = Context.getMany(
|
|
41
|
+
context,
|
|
42
|
+
Document,
|
|
43
|
+
RenderContext.RenderContext
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
return renderTemplate(document, ctx)
|
|
47
|
+
})),
|
|
48
|
+
RenderContext.dom(window, options)
|
|
49
|
+
)
|
|
50
|
+
|
|
22
51
|
/**
|
|
23
52
|
* @since 1.0.0
|
|
24
53
|
*/
|
|
25
54
|
export function render<R, E, T extends RenderEvent | null>(
|
|
26
|
-
rendered: Fx.Fx<
|
|
27
|
-
): Fx.Fx<
|
|
55
|
+
rendered: Fx.Fx<T, E, R>
|
|
56
|
+
): Fx.Fx<ToRendered<T>, E, R | RenderTemplate | RenderContext.RenderContext | RootElement> {
|
|
28
57
|
return Fx.fromFxEffect(Effect.contextWith((context) => {
|
|
29
|
-
const [
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
RenderTemplate,
|
|
34
|
-
renderTemplate(document, ctx)
|
|
58
|
+
const [ctx, { rootElement }] = Context.getMany(
|
|
59
|
+
context,
|
|
60
|
+
RenderContext.RenderContext,
|
|
61
|
+
RootElement
|
|
35
62
|
)
|
|
63
|
+
|
|
64
|
+
return Fx.mapEffect(rendered, (what) => attachRoot(ctx.renderCache, rootElement, what))
|
|
36
65
|
}))
|
|
37
66
|
}
|
|
38
67
|
|
|
39
68
|
/**
|
|
40
69
|
* @since 1.0.0
|
|
41
70
|
*/
|
|
42
|
-
export function
|
|
43
|
-
rendered: Fx.Fx<
|
|
71
|
+
export function renderToLayer<R, E, T extends RenderEvent | null>(
|
|
72
|
+
rendered: Fx.Fx<T, E, R>,
|
|
73
|
+
window: Window & GlobalThis = globalThis.window,
|
|
74
|
+
options?: DomServicesElementParams & { readonly skipRenderScheduling?: boolean }
|
|
44
75
|
): Layer.Layer<
|
|
76
|
+
RenderTemplate | RenderContext.RenderContext | CurrentEnvironment | DomServices,
|
|
45
77
|
never,
|
|
46
|
-
|
|
47
|
-
|
|
78
|
+
Exclude<
|
|
79
|
+
Exclude<R, Scope.Scope>,
|
|
80
|
+
RenderTemplate | RenderContext.RenderContext | CurrentEnvironment | DomServices
|
|
81
|
+
>
|
|
48
82
|
> {
|
|
49
|
-
return
|
|
83
|
+
return Layer.provideMerge(
|
|
84
|
+
Fx.drainLayer(Fx.switchMapCause(render(rendered), (e) => Fx.fromEffect(Effect.logError(e)))),
|
|
85
|
+
renderLayer(window, options)
|
|
86
|
+
)
|
|
50
87
|
}
|
package/src/RenderTemplate.ts
CHANGED
|
@@ -16,11 +16,7 @@ export interface RenderTemplate {
|
|
|
16
16
|
<Values extends ReadonlyArray<Renderable<any, any>>>(
|
|
17
17
|
templateStrings: TemplateStringsArray,
|
|
18
18
|
values: Values
|
|
19
|
-
): Fx.Fx<
|
|
20
|
-
Scope | Placeholder.Context<Values[number]>,
|
|
21
|
-
Placeholder.Error<Values[number]>,
|
|
22
|
-
RenderEvent
|
|
23
|
-
>
|
|
19
|
+
): Fx.Fx<RenderEvent, Placeholder.Error<Values[number]>, Scope | Placeholder.Context<Values[number]>>
|
|
24
20
|
}
|
|
25
21
|
|
|
26
22
|
/**
|
|
@@ -38,6 +34,6 @@ export const RenderTemplate: Context.Tagged<RenderTemplate, RenderTemplate> = Co
|
|
|
38
34
|
export function html<const Values extends ReadonlyArray<Renderable<any, any>>>(
|
|
39
35
|
template: TemplateStringsArray,
|
|
40
36
|
...values: Values
|
|
41
|
-
): Fx.Fx<
|
|
37
|
+
): Fx.Fx<RenderEvent, Placeholder.Error<Values[number]>, RenderTemplate | Scope | Placeholder.Context<Values[number]>> {
|
|
42
38
|
return Fx.fromFxEffect(RenderTemplate.with((render) => render(template, values)))
|
|
43
39
|
}
|
package/src/Renderable.ts
CHANGED
|
@@ -12,12 +12,12 @@ import type { RenderEvent } from "./RenderEvent.js"
|
|
|
12
12
|
*/
|
|
13
13
|
export type Renderable<R = never, E = never> =
|
|
14
14
|
| Renderable.Value
|
|
15
|
-
| Placeholder<
|
|
16
|
-
| { readonly [key: string]: Renderable<
|
|
17
|
-
| Placeholder<
|
|
15
|
+
| Placeholder<any, E, R>
|
|
16
|
+
| { readonly [key: string]: Renderable<E, R> | Placeholder<any, E, R> | unknown } // TODO: Should we manage data attributes this way?
|
|
17
|
+
| Placeholder<any, E, R>
|
|
18
18
|
| Effect<any, E, R>
|
|
19
|
-
| Fx<
|
|
20
|
-
| ReadonlyArray<Renderable<
|
|
19
|
+
| Fx<any, E, R>
|
|
20
|
+
| ReadonlyArray<Renderable<E, R>>
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* @since 1.0.0
|