@statorjs/stator 1.2.2 → 1.4.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/package.json +2 -2
- package/src/client/css.d.ts +6 -0
- package/src/client/inspector-flash.css +50 -0
- package/src/client/inspector.css +196 -0
- package/src/client/inspector.ts +31 -72
- package/src/client/runtime.ts +5 -1
- package/src/compiler/compile.ts +35 -8
- package/src/compiler/lower.ts +0 -0
- package/src/compiler/virtual-code.ts +1 -1
- package/src/engine/actor.ts +59 -0
- package/src/engine/types.ts +33 -0
- package/src/server/api-route.ts +7 -1
- package/src/server/create-app.ts +3 -1
- package/src/server/dev.ts +3 -1
- package/src/server/effects.ts +36 -17
- package/src/server/http.ts +25 -4
- package/src/server/machine-store.ts +7 -0
- package/src/server/recompute.ts +97 -10
- package/src/server/render-context.ts +123 -6
- package/src/server/render.ts +77 -4
- package/src/server/session-runtime.ts +14 -0
- package/src/server/timers.ts +77 -0
- package/src/template/client-shell.ts +35 -9
- package/src/template/conditional.ts +2 -1
- package/src/template/defer.ts +72 -0
- package/src/template/directives/list-attr.ts +16 -0
- package/src/template/each.ts +89 -9
- package/src/template/html.ts +65 -1
- package/src/template/index.ts +3 -1
- package/src/template/read.ts +28 -4
- package/src/template/resource.ts +70 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export type ResourceStatus = 'pending' | 'fulfilled' | 'rejected'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A peekable async value. You cannot synchronously read a native promise's
|
|
5
|
+
* settled state (`.then` is always a microtask), so `defer` wraps a thunk's
|
|
6
|
+
* result in a resource that records its settlement as it happens — letting the
|
|
7
|
+
* fill pass read `status` synchronously ("peek") at the moment it splices HTML.
|
|
8
|
+
*
|
|
9
|
+
* A non-promise thunk result fulfills immediately, so `defer` degrades to plain
|
|
10
|
+
* inline render for synchronous data.
|
|
11
|
+
*/
|
|
12
|
+
export interface Resource<T = unknown> {
|
|
13
|
+
readonly status: ResourceStatus
|
|
14
|
+
readonly value?: T
|
|
15
|
+
readonly reason?: unknown
|
|
16
|
+
/**
|
|
17
|
+
* Resolves when the resource settles (fulfilled OR rejected). Never rejects —
|
|
18
|
+
* a rejection is recorded as `status: 'rejected'` + `reason`, and `settled`
|
|
19
|
+
* still resolves, so the resolve phase can `await` a batch of resources with a
|
|
20
|
+
* plain `Promise.all` and never has to catch.
|
|
21
|
+
*/
|
|
22
|
+
readonly settled: Promise<void>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function isPromiseLike(v: unknown): v is PromiseLike<unknown> {
|
|
26
|
+
return (
|
|
27
|
+
(typeof v === 'object' || typeof v === 'function') &&
|
|
28
|
+
v !== null &&
|
|
29
|
+
typeof (v as { then?: unknown }).then === 'function'
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Wrap a thunk's result in a peekable {@link Resource}. Synchronous values (and
|
|
35
|
+
* synchronous throws) settle immediately; a promise records its settlement on a
|
|
36
|
+
* single attached continuation.
|
|
37
|
+
*/
|
|
38
|
+
export function createResource<T>(produce: () => T | Promise<T>): Resource<T> {
|
|
39
|
+
let result: T | Promise<T>
|
|
40
|
+
try {
|
|
41
|
+
result = produce()
|
|
42
|
+
} catch (reason) {
|
|
43
|
+
// A thunk that throws synchronously is a rejected resource, not a crash.
|
|
44
|
+
return { status: 'rejected', reason, settled: Promise.resolve() }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!isPromiseLike(result)) {
|
|
48
|
+
return { status: 'fulfilled', value: result, settled: Promise.resolve() }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const resource: {
|
|
52
|
+
status: ResourceStatus
|
|
53
|
+
value?: T
|
|
54
|
+
reason?: unknown
|
|
55
|
+
settled: Promise<void>
|
|
56
|
+
} = { status: 'pending', settled: Promise.resolve() }
|
|
57
|
+
|
|
58
|
+
resource.settled = Promise.resolve(result).then(
|
|
59
|
+
(value) => {
|
|
60
|
+
resource.status = 'fulfilled'
|
|
61
|
+
resource.value = value
|
|
62
|
+
},
|
|
63
|
+
(reason) => {
|
|
64
|
+
resource.status = 'rejected'
|
|
65
|
+
resource.reason = reason
|
|
66
|
+
},
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
return resource
|
|
70
|
+
}
|