effect-start 0.22.0 → 0.23.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/BlobStore.d.ts +80 -0
- package/dist/BlobStore.js +19 -0
- package/dist/ChildProcess.d.ts +60 -0
- package/dist/ChildProcess.js +30 -0
- package/dist/Commander.d.ts +3 -6
- package/dist/Commander.js +6 -13
- package/dist/ContentNegotiation.d.ts +8 -9
- package/dist/ContentNegotiation.js +32 -37
- package/dist/Cookies.d.ts +47 -0
- package/dist/Cookies.js +273 -363
- package/dist/Development.d.ts +2 -2
- package/dist/Development.js +3 -4
- package/dist/Effectify.d.ts +1 -4
- package/dist/FilePathPattern.d.ts +3 -3
- package/dist/FileRouter.d.ts +5 -8
- package/dist/FileRouter.js +9 -10
- package/dist/FileRouterCodegen.d.ts +1 -1
- package/dist/FileRouterCodegen.js +33 -13
- package/dist/FileSystem.d.ts +158 -0
- package/dist/FileSystem.js +64 -125
- package/dist/Http.js +2 -6
- package/dist/PathPattern.d.ts +7 -7
- package/dist/PathPattern.js +1 -3
- package/dist/PlatformError.d.ts +24 -32
- package/dist/PlatformError.js +3 -21
- package/dist/PlatformRuntime.js +5 -10
- package/dist/Route.d.ts +14 -19
- package/dist/Route.js +8 -11
- package/dist/RouteBody.d.ts +6 -12
- package/dist/RouteBody.js +2 -2
- package/dist/RouteError.d.ts +98 -0
- package/dist/RouteError.js +55 -0
- package/dist/RouteHook.js +6 -11
- package/dist/RouteHttp.d.ts +3 -3
- package/dist/RouteHttp.js +27 -22
- package/dist/RouteMount.d.ts +16 -50
- package/dist/RouteMount.js +6 -20
- package/dist/RouteSchema.d.ts +22 -1
- package/dist/RouteSchema.js +33 -0
- package/dist/RouteSse.js +4 -10
- package/dist/RouteTree.d.ts +2 -1
- package/dist/RouteTree.js +17 -15
- package/dist/RouteTrie.d.ts +2 -2
- package/dist/RouteTrie.js +4 -9
- package/dist/SchemaExtra.d.ts +1 -1
- package/dist/Socket.d.ts +27 -0
- package/dist/Socket.js +20 -28
- package/dist/Sql.d.ts +34 -0
- package/dist/Sql.js +5 -0
- package/dist/SqlIntrospect.d.ts +91 -0
- package/dist/SqlIntrospect.js +466 -0
- package/dist/Start.d.ts +4 -6
- package/dist/Start.js +10 -2
- package/dist/StreamExtra.d.ts +1 -1
- package/dist/StreamExtra.js +9 -9
- package/dist/System.d.ts +7 -0
- package/dist/System.js +22 -0
- package/dist/TuplePathPattern.js +55 -50
- package/dist/Unique.js +7 -7
- package/dist/Values.d.ts +2 -1
- package/dist/Values.js +19 -13
- package/dist/bun/BunBlobStoreDisk.d.ts +6 -0
- package/dist/bun/BunBlobStoreDisk.js +116 -0
- package/dist/bun/BunBlobStoreS3.d.ts +11 -0
- package/dist/bun/BunBlobStoreS3.js +89 -0
- package/dist/bun/BunBlobWatcherDisk.d.ts +6 -0
- package/dist/bun/BunBlobWatcherDisk.js +60 -0
- package/dist/bun/BunBlobWatcherQueue.d.ts +6 -0
- package/dist/bun/BunBlobWatcherQueue.js +17 -0
- package/dist/bun/BunBundle.d.ts +5 -6
- package/dist/bun/BunBundle.js +7 -15
- package/dist/bun/BunChildProcessSpawner.d.ts +3 -0
- package/dist/bun/BunChildProcessSpawner.js +103 -0
- package/dist/bun/BunImportTrackerPlugin.d.ts +1 -1
- package/dist/bun/BunImportTrackerPlugin.js +3 -5
- package/dist/bun/BunRoute.d.ts +3 -2
- package/dist/bun/BunRoute.js +5 -7
- package/dist/bun/BunRuntime.js +1 -1
- package/dist/bun/BunServer.d.ts +11 -4
- package/dist/bun/BunServer.js +35 -11
- package/dist/bun/BunSql.d.ts +4 -0
- package/dist/bun/BunSql.js +81 -0
- package/dist/bun/_BunEnhancedResolve.d.ts +3 -3
- package/dist/bun/_BunEnhancedResolve.js +2 -4
- package/dist/bun/index.d.ts +1 -0
- package/dist/bun/index.js +1 -0
- package/dist/bundler/Bundle.d.ts +2 -1
- package/dist/bundler/Bundle.js +1 -1
- package/dist/bundler/BundleFiles.d.ts +5 -5
- package/dist/bundler/BundleFiles.js +10 -8
- package/dist/bundler/BundleRoute.d.ts +27 -0
- package/dist/bundler/BundleRoute.js +51 -0
- package/dist/client/ScrollState.js +2 -6
- package/dist/client/index.js +6 -8
- package/dist/console/Console.d.ts +6 -0
- package/dist/console/Console.js +26 -0
- package/dist/console/ConsoleErrors.d.ts +3 -0
- package/dist/console/ConsoleErrors.js +200 -0
- package/dist/console/ConsoleLogger.d.ts +3 -0
- package/dist/console/ConsoleLogger.js +47 -0
- package/dist/console/ConsoleMetrics.d.ts +3 -0
- package/dist/console/ConsoleMetrics.js +61 -0
- package/dist/console/ConsoleProcess.d.ts +3 -0
- package/dist/console/ConsoleProcess.js +49 -0
- package/dist/console/ConsoleStore.d.ts +144 -0
- package/dist/console/ConsoleStore.js +61 -0
- package/dist/console/ConsoleTracer.d.ts +3 -0
- package/dist/console/ConsoleTracer.js +94 -0
- package/dist/console/Simulation.d.ts +2 -0
- package/dist/console/Simulation.js +633 -0
- package/dist/console/index.d.ts +3 -0
- package/dist/console/index.js +3 -0
- package/dist/console/routes/errors/route.d.ts +10 -0
- package/dist/console/routes/errors/route.js +47 -0
- package/dist/console/routes/fiberDetail.d.ts +16 -0
- package/dist/console/routes/fiberDetail.js +38 -0
- package/dist/console/routes/fibers/route.d.ts +10 -0
- package/dist/console/routes/fibers/route.js +19 -0
- package/dist/console/routes/git/route.d.ts +11 -0
- package/dist/console/routes/git/route.js +33 -0
- package/dist/console/routes/layout.d.ts +9 -0
- package/dist/console/routes/layout.js +3 -0
- package/dist/console/routes/logs/route.d.ts +10 -0
- package/dist/console/routes/logs/route.js +32 -0
- package/dist/console/routes/metrics/route.d.ts +10 -0
- package/dist/console/routes/metrics/route.js +17 -0
- package/dist/console/routes/route.d.ts +6 -0
- package/dist/console/routes/route.js +5 -0
- package/dist/console/routes/routes/route.d.ts +6 -0
- package/dist/console/routes/routes/route.js +20 -0
- package/dist/console/routes/services/route.d.ts +6 -0
- package/dist/console/routes/services/route.js +12 -0
- package/dist/console/routes/system/route.d.ts +10 -0
- package/dist/console/routes/system/route.js +18 -0
- package/dist/console/routes/traceDetail.d.ts +16 -0
- package/dist/console/routes/traceDetail.js +14 -0
- package/dist/console/routes/traces/route.d.ts +10 -0
- package/dist/console/routes/traces/route.js +39 -0
- package/dist/console/routes/tree.d.ts +153 -0
- package/dist/console/routes/tree.js +29 -0
- package/dist/console/ui/Errors.d.ts +4 -0
- package/dist/console/ui/Errors.js +15 -0
- package/dist/console/ui/Fibers.d.ts +24 -0
- package/dist/console/ui/Fibers.js +121 -0
- package/dist/console/ui/Git.d.ts +20 -0
- package/dist/console/ui/Git.js +95 -0
- package/dist/console/ui/Logs.d.ts +4 -0
- package/dist/console/ui/Logs.js +25 -0
- package/dist/console/ui/Metrics.d.ts +4 -0
- package/dist/console/ui/Metrics.js +26 -0
- package/dist/console/ui/Routes.d.ts +8 -0
- package/dist/console/ui/Routes.js +70 -0
- package/dist/console/ui/Services.d.ts +10 -0
- package/dist/console/ui/Services.js +246 -0
- package/dist/console/ui/Shell.d.ts +10 -0
- package/dist/console/ui/Shell.js +7 -0
- package/dist/console/ui/System.d.ts +4 -0
- package/dist/console/ui/System.js +35 -0
- package/dist/console/ui/Traces.d.ts +12 -0
- package/dist/console/ui/Traces.js +179 -0
- package/dist/datastar/actions/fetch.d.ts +1 -1
- package/dist/datastar/actions/fetch.js +10 -18
- package/dist/datastar/actions/peek.js +1 -2
- package/dist/datastar/actions/setAll.js +1 -2
- package/dist/datastar/actions/toggleAll.js +1 -2
- package/dist/datastar/attributes/attr.js +1 -2
- package/dist/datastar/attributes/bind.js +10 -18
- package/dist/datastar/attributes/class.js +2 -5
- package/dist/datastar/attributes/computed.js +2 -3
- package/dist/datastar/attributes/effect.js +1 -2
- package/dist/datastar/attributes/indicator.js +2 -4
- package/dist/datastar/attributes/init.js +2 -3
- package/dist/datastar/attributes/jsonSignals.js +1 -2
- package/dist/datastar/attributes/on.js +41 -22
- package/dist/datastar/attributes/onIntersect.js +2 -3
- package/dist/datastar/attributes/onInterval.js +2 -3
- package/dist/datastar/attributes/onSignalPatch.js +2 -4
- package/dist/datastar/attributes/ref.js +1 -2
- package/dist/datastar/attributes/show.js +1 -2
- package/dist/datastar/attributes/signals.js +1 -2
- package/dist/datastar/attributes/style.js +6 -12
- package/dist/datastar/attributes/text.js +1 -2
- package/dist/datastar/engine.d.ts +13 -7
- package/dist/datastar/engine.js +76 -48
- package/dist/datastar/happydom.d.ts +1 -0
- package/dist/datastar/happydom.js +8 -0
- package/dist/datastar/index.d.ts +1 -1
- package/dist/datastar/index.js +1 -1
- package/dist/datastar/utils.js +4 -7
- package/dist/datastar/watchers/patchElements.js +24 -45
- package/dist/datastar/watchers/patchSignals.js +1 -2
- package/dist/experimental/EncryptedCookies.d.ts +2 -5
- package/dist/experimental/EncryptedCookies.js +17 -48
- package/dist/experimental/index.d.ts +0 -1
- package/dist/experimental/index.js +0 -1
- package/dist/hyper/Hyper.d.ts +2 -9
- package/dist/hyper/Hyper.js +1 -12
- package/dist/hyper/HyperHtml.d.ts +1 -1
- package/dist/hyper/HyperHtml.js +18 -12
- package/dist/hyper/HyperHtml.test.d.ts +1 -0
- package/dist/hyper/HyperHtml.test.js +197 -0
- package/dist/hyper/HyperRoute.test.js +14 -3
- package/dist/hyper/html.d.ts +11 -0
- package/dist/hyper/html.js +30 -0
- package/dist/hyper/index.d.ts +2 -0
- package/dist/hyper/index.js +1 -0
- package/dist/hyper/jsx-runtime.d.ts +1 -1
- package/dist/hyper/jsx-runtime.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lint/plugin.d.ts +86 -0
- package/dist/lint/plugin.js +341 -0
- package/dist/node/NodeFileSystem.d.ts +2 -2
- package/dist/node/NodeFileSystem.js +4 -14
- package/dist/sql/bun/index.d.ts +3 -0
- package/dist/sql/bun/index.js +75 -0
- package/dist/sql/mssql/docker.d.ts +2 -0
- package/dist/sql/mssql/docker.js +67 -0
- package/dist/sql/mssql/index.d.ts +21 -0
- package/dist/sql/mssql/index.js +113 -0
- package/dist/testing/TestLogger.js +4 -1
- package/dist/testing/index.d.ts +0 -1
- package/dist/testing/index.js +0 -1
- package/dist/testing/utils.d.ts +3 -3
- package/dist/testing/utils.js +4 -4
- package/dist/x/cloudflare/CloudflareTunnel.d.ts +2 -5
- package/dist/x/cloudflare/CloudflareTunnel.js +14 -27
- package/dist/x/datastar/Datastar.d.ts +1 -1
- package/dist/x/datastar/Datastar.js +13 -12
- package/dist/x/datastar/index.d.ts +1 -2
- package/dist/x/datastar/index.js +1 -2
- package/dist/x/tailscale/TailscaleTunnel.d.ts +15 -0
- package/dist/x/tailscale/TailscaleTunnel.js +68 -0
- package/dist/x/tailscale/index.d.ts +1 -0
- package/dist/x/tailscale/index.js +1 -0
- package/dist/x/tailwind/TailwindPlugin.js +19 -19
- package/dist/x/tailwind/compile.d.ts +2 -2
- package/dist/x/tailwind/compile.js +2 -4
- package/package.json +22 -10
- package/src/ChildProcess.ts +145 -0
- package/src/PlatformError.ts +27 -50
- package/src/Route.ts +2 -2
- package/src/RouteError.ts +76 -0
- package/src/RouteHttp.ts +13 -5
- package/src/RouteSchema.ts +96 -1
- package/src/RouteTree.ts +12 -0
- package/src/Sql.ts +51 -0
- package/src/SqlIntrospect.ts +620 -0
- package/src/Start.ts +15 -3
- package/src/System.ts +43 -0
- package/src/Values.ts +7 -0
- package/src/bun/BunChildProcessSpawner.ts +143 -0
- package/src/bun/BunRoute.ts +5 -2
- package/src/bun/BunServer.ts +22 -1
- package/src/bun/index.ts +1 -0
- package/src/bundler/BundleRoute.ts +66 -0
- package/src/console/Console.ts +42 -0
- package/src/console/ConsoleErrors.ts +213 -0
- package/src/console/ConsoleLogger.ts +56 -0
- package/src/console/ConsoleMetrics.ts +72 -0
- package/src/console/ConsoleProcess.ts +59 -0
- package/src/console/ConsoleStore.ts +187 -0
- package/src/console/ConsoleTracer.ts +107 -0
- package/src/console/Simulation.ts +814 -0
- package/src/console/console.html +340 -0
- package/src/console/index.ts +3 -0
- package/src/console/routes/errors/route.tsx +97 -0
- package/src/console/routes/fiberDetail.tsx +54 -0
- package/src/console/routes/fibers/route.tsx +45 -0
- package/src/console/routes/git/route.tsx +64 -0
- package/src/console/routes/layout.tsx +4 -0
- package/src/console/routes/logs/route.tsx +77 -0
- package/src/console/routes/metrics/route.tsx +36 -0
- package/src/console/routes/route.tsx +8 -0
- package/src/console/routes/routes/route.tsx +30 -0
- package/src/console/routes/services/route.tsx +21 -0
- package/src/console/routes/system/route.tsx +43 -0
- package/src/console/routes/traceDetail.tsx +22 -0
- package/src/console/routes/traces/route.tsx +81 -0
- package/src/console/routes/tree.ts +30 -0
- package/src/console/ui/Errors.tsx +76 -0
- package/src/console/ui/Fibers.tsx +321 -0
- package/src/console/ui/Git.tsx +182 -0
- package/src/console/ui/Logs.tsx +46 -0
- package/src/console/ui/Metrics.tsx +78 -0
- package/src/console/ui/Routes.tsx +125 -0
- package/src/console/ui/Services.tsx +273 -0
- package/src/console/ui/Shell.tsx +62 -0
- package/src/console/ui/System.tsx +131 -0
- package/src/console/ui/Traces.tsx +426 -0
- package/src/datastar/README.md +6 -1
- package/src/datastar/actions/fetch.ts +0 -1
- package/src/datastar/attributes/on.ts +40 -20
- package/src/datastar/engine.ts +51 -0
- package/src/datastar/jsx.d.ts +79 -0
- package/src/hyper/Hyper.ts +1 -16
- package/src/hyper/HyperHtml.ts +6 -4
- package/src/hyper/HyperRoute.ts +2 -1
- package/src/hyper/html.ts +47 -0
- package/src/hyper/index.ts +2 -0
- package/src/hyper/jsx.d.ts +5 -3
- package/src/index.ts +1 -0
- package/src/lint/plugin.js +129 -0
- package/src/sql/bun/index.ts +147 -0
- package/src/sql/mssql/docker.ts +117 -0
- package/src/sql/mssql/index.ts +223 -0
- package/src/sql/mssql/mssql.d.ts +41 -0
- package/src/x/cloudflare/CloudflareTunnel.ts +8 -36
- package/src/x/tailscale/TailscaleTunnel.ts +113 -0
- package/src/x/tailscale/index.ts +1 -0
- package/src/x/datastar/Datastar.ts +0 -61
- package/src/x/datastar/index.ts +0 -2
- package/src/x/datastar/jsx-datastar.d.ts +0 -60
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import * as ConsoleStore from "../ConsoleStore.ts"
|
|
2
|
+
|
|
3
|
+
function formatDuration(ms: number | undefined): string {
|
|
4
|
+
if (ms == null) return "..."
|
|
5
|
+
if (ms < 1) return `${(ms * 1000).toFixed(0)}µs`
|
|
6
|
+
if (ms < 1000) return `${ms.toFixed(1)}ms`
|
|
7
|
+
return `${(ms / 1000).toFixed(2)}s`
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function statusColor(status: string): string {
|
|
11
|
+
if (status === "ok") return "#22c55e"
|
|
12
|
+
if (status === "error") return "#ef4444"
|
|
13
|
+
return "#eab308"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function KeyValue({ label, value }: { label: string; value: string | undefined | null }) {
|
|
17
|
+
if (value == null) return null
|
|
18
|
+
return (
|
|
19
|
+
<div style="display:flex;gap:8px;padding:4px 0;border-bottom:1px solid #1e293b;font-size:12px">
|
|
20
|
+
<span style="color:#64748b;min-width:120px">{label}</span>
|
|
21
|
+
<span style="color:#e2e8f0;font-family:monospace;word-break:break-all">{value}</span>
|
|
22
|
+
</div>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function StatusBadge({ status }: { status: string }) {
|
|
27
|
+
const bg = status === "ok" ? "#166534" : status === "error" ? "#7f1d1d" : "#713f12"
|
|
28
|
+
const fg = status === "ok" ? "#4ade80" : status === "error" ? "#fca5a5" : "#fde047"
|
|
29
|
+
return (
|
|
30
|
+
<span style={`font-size:11px;padding:2px 8px;border-radius:4px;background:${bg};color:${fg}`}>
|
|
31
|
+
{status}
|
|
32
|
+
</span>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// --- Tree building ---
|
|
37
|
+
|
|
38
|
+
interface TreeSpan {
|
|
39
|
+
span: ConsoleStore.ConsoleSpan
|
|
40
|
+
depth: number
|
|
41
|
+
childCount: number
|
|
42
|
+
isLastChild: boolean
|
|
43
|
+
ancestorHasNextSibling: Array<boolean>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function buildSpanTree(spans: Array<ConsoleStore.ConsoleSpan>): Array<TreeSpan> {
|
|
47
|
+
const byId = new Map<string, ConsoleStore.ConsoleSpan>()
|
|
48
|
+
const childrenOf = new Map<string, Array<ConsoleStore.ConsoleSpan>>()
|
|
49
|
+
|
|
50
|
+
for (const s of spans) {
|
|
51
|
+
byId.set(s.spanId, s)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const roots: Array<ConsoleStore.ConsoleSpan> = []
|
|
55
|
+
for (const s of spans) {
|
|
56
|
+
if (s.parentSpanId && byId.has(s.parentSpanId)) {
|
|
57
|
+
let children = childrenOf.get(s.parentSpanId)
|
|
58
|
+
if (!children) {
|
|
59
|
+
children = []
|
|
60
|
+
childrenOf.set(s.parentSpanId, children)
|
|
61
|
+
}
|
|
62
|
+
children.push(s)
|
|
63
|
+
} else {
|
|
64
|
+
roots.push(s)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const sortByStart = (a: ConsoleStore.ConsoleSpan, b: ConsoleStore.ConsoleSpan) =>
|
|
69
|
+
Number(a.startTime - b.startTime)
|
|
70
|
+
|
|
71
|
+
roots.sort(sortByStart)
|
|
72
|
+
for (const children of childrenOf.values()) {
|
|
73
|
+
children.sort(sortByStart)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const result: Array<TreeSpan> = []
|
|
77
|
+
|
|
78
|
+
function walk(
|
|
79
|
+
span: ConsoleStore.ConsoleSpan,
|
|
80
|
+
depth: number,
|
|
81
|
+
isLast: boolean,
|
|
82
|
+
ancestors: Array<boolean>,
|
|
83
|
+
) {
|
|
84
|
+
const children = childrenOf.get(span.spanId) ?? []
|
|
85
|
+
result.push({
|
|
86
|
+
span,
|
|
87
|
+
depth,
|
|
88
|
+
childCount: children.length,
|
|
89
|
+
isLastChild: isLast,
|
|
90
|
+
ancestorHasNextSibling: [...ancestors],
|
|
91
|
+
})
|
|
92
|
+
for (let i = 0; i < children.length; i++) {
|
|
93
|
+
walk(children[i], depth + 1, i === children.length - 1, [...ancestors, !isLast])
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for (let i = 0; i < roots.length; i++) {
|
|
98
|
+
walk(roots[i], 0, i === roots.length - 1, [])
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return result
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// --- Components ---
|
|
105
|
+
|
|
106
|
+
function TreeConnectors({ tree }: { tree: TreeSpan }) {
|
|
107
|
+
if (tree.depth === 0) return null
|
|
108
|
+
|
|
109
|
+
const indent = tree.depth * 20
|
|
110
|
+
const elements: Array<any> = []
|
|
111
|
+
|
|
112
|
+
for (let i = 0; i < tree.ancestorHasNextSibling.length; i++) {
|
|
113
|
+
if (tree.ancestorHasNextSibling[i]) {
|
|
114
|
+
elements.push(<div class="wf-vline" style={`left:${i * 20 + 6}px`} />)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (tree.isLastChild) {
|
|
119
|
+
elements.push(<div class="wf-elbow" style={`left:${(tree.depth - 1) * 20 + 6}px`} />)
|
|
120
|
+
} else {
|
|
121
|
+
elements.push(<div class="wf-vline" style={`left:${(tree.depth - 1) * 20 + 6}px`} />)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
elements.push(<div class="wf-hline" style={`left:${(tree.depth - 1) * 20 + 6}px;top:50%`} />)
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<div class="wf-tree" style={`width:${indent}px;position:relative`}>
|
|
128
|
+
{elements}
|
|
129
|
+
</div>
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function TimeAxis({ totalMs }: { totalMs: number }) {
|
|
134
|
+
const ticks = 5
|
|
135
|
+
const labels: Array<string> = []
|
|
136
|
+
for (let i = 0; i <= ticks; i++) {
|
|
137
|
+
labels.push(formatDuration((totalMs / ticks) * i))
|
|
138
|
+
}
|
|
139
|
+
return (
|
|
140
|
+
<div class="wf-axis">
|
|
141
|
+
<div style="padding:4px 8px;color:#64748b;font-size:11px">Span</div>
|
|
142
|
+
<div class="wf-axis-ticks">
|
|
143
|
+
{labels.map((l) => (
|
|
144
|
+
<span>{l}</span>
|
|
145
|
+
))}
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function WaterfallRow({
|
|
152
|
+
tree,
|
|
153
|
+
totalMs,
|
|
154
|
+
rootStart,
|
|
155
|
+
}: {
|
|
156
|
+
tree: TreeSpan
|
|
157
|
+
totalMs: number
|
|
158
|
+
rootStart: bigint
|
|
159
|
+
}) {
|
|
160
|
+
const s = tree.span
|
|
161
|
+
const offsetMs = Number(s.startTime - rootStart) / 1_000_000
|
|
162
|
+
const durMs = s.durationMs ?? 0
|
|
163
|
+
const leftPct = totalMs > 0 ? Math.min(100, (offsetMs / totalMs) * 100) : 0
|
|
164
|
+
const widthPct =
|
|
165
|
+
totalMs > 0 ? Math.max(0.5, Math.min(100 - leftPct, (durMs / totalMs) * 100)) : 100
|
|
166
|
+
const color = statusColor(s.status)
|
|
167
|
+
|
|
168
|
+
const durLabelLeft = leftPct + widthPct + 0.5
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<div class="wf-row">
|
|
172
|
+
<div class="wf-name">
|
|
173
|
+
<TreeConnectors tree={tree} />
|
|
174
|
+
<span style="overflow:hidden;text-overflow:ellipsis">{s.name}</span>
|
|
175
|
+
{tree.childCount > 0 && <span class="wf-badge">{tree.childCount}</span>}
|
|
176
|
+
</div>
|
|
177
|
+
<div class="wf-bar-cell">
|
|
178
|
+
<div class="wf-bar" style={`left:${leftPct}%;width:${widthPct}%;background:${color}`} />
|
|
179
|
+
<div class="wf-dur" style={`left:${durLabelLeft}%`}>
|
|
180
|
+
{formatDuration(s.durationMs)}
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function MiniWaterfall({
|
|
188
|
+
spans,
|
|
189
|
+
totalMs,
|
|
190
|
+
rootStart,
|
|
191
|
+
}: {
|
|
192
|
+
spans: Array<ConsoleStore.ConsoleSpan>
|
|
193
|
+
totalMs: number
|
|
194
|
+
rootStart: bigint
|
|
195
|
+
}) {
|
|
196
|
+
if (totalMs <= 0) return <div class="mini-wf" />
|
|
197
|
+
return (
|
|
198
|
+
<div class="mini-wf">
|
|
199
|
+
{spans.map((s) => {
|
|
200
|
+
const offsetMs = Number(s.startTime - rootStart) / 1_000_000
|
|
201
|
+
const durMs = s.durationMs ?? 0
|
|
202
|
+
const leftPct = Math.min(100, (offsetMs / totalMs) * 100)
|
|
203
|
+
const widthPct = Math.max(0.3, Math.min(100 - leftPct, (durMs / totalMs) * 100))
|
|
204
|
+
return (
|
|
205
|
+
<div
|
|
206
|
+
class="mini-wf-bar"
|
|
207
|
+
style={`left:${leftPct}%;width:${widthPct}%;background:${statusColor(s.status)}`}
|
|
208
|
+
/>
|
|
209
|
+
)
|
|
210
|
+
})}
|
|
211
|
+
</div>
|
|
212
|
+
)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// --- Exports ---
|
|
216
|
+
|
|
217
|
+
export function groupByTraceId(
|
|
218
|
+
spans: Array<ConsoleStore.ConsoleSpan>,
|
|
219
|
+
): Map<string, Array<ConsoleStore.ConsoleSpan>> {
|
|
220
|
+
const groups = new Map<string, Array<ConsoleStore.ConsoleSpan>>()
|
|
221
|
+
for (const span of spans) {
|
|
222
|
+
let group = groups.get(span.traceId)
|
|
223
|
+
if (!group) {
|
|
224
|
+
group = []
|
|
225
|
+
groups.set(span.traceId, group)
|
|
226
|
+
}
|
|
227
|
+
group.push(span)
|
|
228
|
+
}
|
|
229
|
+
return groups
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export function TraceGroup({ spans }: { spans: Array<ConsoleStore.ConsoleSpan> }) {
|
|
233
|
+
if (spans.length === 0) return null
|
|
234
|
+
const root = spans.find((s) => !s.parentSpanId) ?? spans[0]
|
|
235
|
+
const traceId = root.traceId
|
|
236
|
+
const totalMs = root.durationMs ?? 0
|
|
237
|
+
const rootStart = root.startTime
|
|
238
|
+
const hasError = spans.some((s) => s.status === "error")
|
|
239
|
+
const status = hasError ? "error" : root.status
|
|
240
|
+
|
|
241
|
+
return (
|
|
242
|
+
<details class="tl-row">
|
|
243
|
+
<summary class="tl-summary tl-cols">
|
|
244
|
+
<span class="tl-cell tl-cell-status">
|
|
245
|
+
<span
|
|
246
|
+
style={`width:8px;height:8px;border-radius:50%;background:${statusColor(status)};display:block`}
|
|
247
|
+
/>
|
|
248
|
+
</span>
|
|
249
|
+
<span class="tl-cell tl-cell-name">{root.name}</span>
|
|
250
|
+
<span class="tl-cell tl-cell-spans">{spans.length}</span>
|
|
251
|
+
<span class="tl-cell tl-cell-dur">{formatDuration(totalMs)}</span>
|
|
252
|
+
<span class="tl-cell tl-cell-id">{traceId.slice(0, 12)}</span>
|
|
253
|
+
</summary>
|
|
254
|
+
<div class="tl-body">
|
|
255
|
+
<div style="display:flex;gap:12px;align-items:center;margin-bottom:8px">
|
|
256
|
+
<a
|
|
257
|
+
href={`${ConsoleStore.store.prefix}/traces/${traceId}`}
|
|
258
|
+
style="color:#38bdf8;font-size:12px;text-decoration:none"
|
|
259
|
+
>
|
|
260
|
+
Full trace view
|
|
261
|
+
</a>
|
|
262
|
+
<StatusBadge status={status} />
|
|
263
|
+
<span style="color:#64748b;font-size:11px">
|
|
264
|
+
{spans.length} span{spans.length !== 1 ? "s" : ""}
|
|
265
|
+
</span>
|
|
266
|
+
<span style="color:#64748b;font-size:11px;font-family:monospace">
|
|
267
|
+
{formatDuration(totalMs)}
|
|
268
|
+
</span>
|
|
269
|
+
<span style="color:#475569;font-size:10px;font-family:monospace">{traceId}</span>
|
|
270
|
+
</div>
|
|
271
|
+
{spans.map((s) => {
|
|
272
|
+
const offsetMs = Number(s.startTime - rootStart) / 1_000_000
|
|
273
|
+
const leftPct = totalMs > 0 ? Math.min(100, (offsetMs / totalMs) * 100) : 0
|
|
274
|
+
const widthPct =
|
|
275
|
+
totalMs > 0
|
|
276
|
+
? Math.max(0.5, Math.min(100 - leftPct, ((s.durationMs ?? 0) / totalMs) * 100))
|
|
277
|
+
: 100
|
|
278
|
+
return (
|
|
279
|
+
<div style="display:flex;align-items:center;gap:8px;padding:2px 0;font-size:11px;font-family:monospace">
|
|
280
|
+
<span style={`color:${statusColor(s.status)};min-width:10px`}>
|
|
281
|
+
{s.parentSpanId ? " " : ""}
|
|
282
|
+
</span>
|
|
283
|
+
<span style="color:#d1d5db;min-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">
|
|
284
|
+
{s.name}
|
|
285
|
+
</span>
|
|
286
|
+
<div style="flex:1;height:10px;background:#1f2937;border-radius:2px;position:relative;overflow:hidden">
|
|
287
|
+
<div
|
|
288
|
+
style={`position:absolute;height:100%;border-radius:2px;background:${statusColor(s.status)};left:${leftPct}%;width:${widthPct}%`}
|
|
289
|
+
/>
|
|
290
|
+
</div>
|
|
291
|
+
<span style="color:#9ca3af;min-width:60px;text-align:right">
|
|
292
|
+
{formatDuration(s.durationMs)}
|
|
293
|
+
</span>
|
|
294
|
+
</div>
|
|
295
|
+
)
|
|
296
|
+
})}
|
|
297
|
+
</div>
|
|
298
|
+
</details>
|
|
299
|
+
)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export function TraceGroups({ spans }: { spans: Array<ConsoleStore.ConsoleSpan> }) {
|
|
303
|
+
const groups = groupByTraceId(spans)
|
|
304
|
+
const sorted = Array.from(groups.values())
|
|
305
|
+
.sort((a, b) => Number(b[0].startTime) - Number(a[0].startTime))
|
|
306
|
+
.slice(0, 50)
|
|
307
|
+
|
|
308
|
+
if (sorted.length === 0) {
|
|
309
|
+
return <div class="empty">Waiting for traces...</div>
|
|
310
|
+
}
|
|
311
|
+
return (
|
|
312
|
+
<div class="tl-grid">
|
|
313
|
+
<div class="tl-header tl-cols">
|
|
314
|
+
<span class="tl-cell tl-cell-status" />
|
|
315
|
+
<span class="tl-cell tl-cell-name">Name</span>
|
|
316
|
+
<span class="tl-cell tl-cell-spans">Spans</span>
|
|
317
|
+
<span class="tl-cell tl-cell-dur">Duration</span>
|
|
318
|
+
<span class="tl-cell tl-cell-id">Trace</span>
|
|
319
|
+
</div>
|
|
320
|
+
{sorted.map((group) => (
|
|
321
|
+
<TraceGroup spans={group} />
|
|
322
|
+
))}
|
|
323
|
+
</div>
|
|
324
|
+
)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export function TraceDetail({
|
|
328
|
+
prefix,
|
|
329
|
+
spans,
|
|
330
|
+
}: {
|
|
331
|
+
prefix: string
|
|
332
|
+
spans: Array<ConsoleStore.ConsoleSpan>
|
|
333
|
+
}) {
|
|
334
|
+
if (spans.length === 0) {
|
|
335
|
+
return <div class="empty">Trace not found</div>
|
|
336
|
+
}
|
|
337
|
+
const root = spans.find((s) => !s.parentSpanId) ?? spans[0]
|
|
338
|
+
const traceId = root.traceId
|
|
339
|
+
const totalMs = root.durationMs ?? 0
|
|
340
|
+
const rootStart = root.startTime
|
|
341
|
+
const startDate = new Date(Number(rootStart) / 1_000_000)
|
|
342
|
+
const tree = buildSpanTree(spans)
|
|
343
|
+
|
|
344
|
+
return (
|
|
345
|
+
<>
|
|
346
|
+
<div style="padding:12px 16px;border-bottom:1px solid #1e293b">
|
|
347
|
+
<div style="display:flex;align-items:center;gap:8px;margin-bottom:8px">
|
|
348
|
+
<a href={`${prefix}/traces`} style="color:#64748b;text-decoration:none;font-size:12px">
|
|
349
|
+
Traces
|
|
350
|
+
</a>
|
|
351
|
+
<span style="color:#475569">/</span>
|
|
352
|
+
<span style="color:#e2e8f0;font-size:13px;font-family:monospace">{root.name}</span>
|
|
353
|
+
</div>
|
|
354
|
+
<div style="display:flex;gap:16px;font-size:12px;color:#94a3b8;align-items:center">
|
|
355
|
+
<StatusBadge status={root.status} />
|
|
356
|
+
<span>
|
|
357
|
+
{spans.length} span{spans.length !== 1 ? "s" : ""}
|
|
358
|
+
</span>
|
|
359
|
+
<span>{formatDuration(totalMs)}</span>
|
|
360
|
+
<span>{startDate.toLocaleTimeString("en", { hour12: false })}</span>
|
|
361
|
+
<span style="color:#475569;font-family:monospace;font-size:10px">{traceId}</span>
|
|
362
|
+
</div>
|
|
363
|
+
</div>
|
|
364
|
+
|
|
365
|
+
<div style="padding:8px 16px">
|
|
366
|
+
<MiniWaterfall spans={spans} totalMs={totalMs} rootStart={rootStart} />
|
|
367
|
+
</div>
|
|
368
|
+
|
|
369
|
+
<div style="padding:0 8px">
|
|
370
|
+
<TimeAxis totalMs={totalMs} />
|
|
371
|
+
<div class="wf-grid">
|
|
372
|
+
{tree.map((t) => (
|
|
373
|
+
<WaterfallRow tree={t} totalMs={totalMs} rootStart={rootStart} />
|
|
374
|
+
))}
|
|
375
|
+
</div>
|
|
376
|
+
</div>
|
|
377
|
+
|
|
378
|
+
<div style="padding:8px">
|
|
379
|
+
{tree.map((t) => {
|
|
380
|
+
const s = t.span
|
|
381
|
+
const stacktrace = s.attributes["code.stacktrace"] as string | undefined
|
|
382
|
+
const customAttrs = Object.entries(s.attributes).filter(([k]) => k !== "code.stacktrace")
|
|
383
|
+
|
|
384
|
+
return (
|
|
385
|
+
<details class="span-panel" style="margin-bottom:4px">
|
|
386
|
+
<summary class="span-panel-header">
|
|
387
|
+
<span
|
|
388
|
+
style={`width:8px;height:8px;border-radius:50%;background:${statusColor(s.status)};flex-shrink:0`}
|
|
389
|
+
/>
|
|
390
|
+
<span style="color:#e2e8f0;font-family:monospace;font-size:12px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1">
|
|
391
|
+
{s.name}
|
|
392
|
+
</span>
|
|
393
|
+
<StatusBadge status={s.status} />
|
|
394
|
+
<span style="color:#64748b;font-size:11px;font-family:monospace;margin-left:auto">
|
|
395
|
+
{formatDuration(s.durationMs)}
|
|
396
|
+
</span>
|
|
397
|
+
</summary>
|
|
398
|
+
<div class="span-panel-body">
|
|
399
|
+
<KeyValue label="Span ID" value={s.spanId} />
|
|
400
|
+
<KeyValue label="Kind" value={s.kind} />
|
|
401
|
+
{s.parentSpanId && <KeyValue label="Parent" value={s.parentSpanId} />}
|
|
402
|
+
{stacktrace && <KeyValue label="Source" value={stacktrace} />}
|
|
403
|
+
{customAttrs.map(([k, v]) => (
|
|
404
|
+
<KeyValue label={k} value={String(v)} />
|
|
405
|
+
))}
|
|
406
|
+
{s.events.length > 0 && (
|
|
407
|
+
<div style="margin-top:4px">
|
|
408
|
+
<span style="color:#64748b;font-size:11px">Events:</span>
|
|
409
|
+
{s.events.map((ev) => (
|
|
410
|
+
<div style="padding:2px 0;font-size:11px;color:#94a3b8;font-family:monospace">
|
|
411
|
+
{ev.name}
|
|
412
|
+
{ev.attributes && (
|
|
413
|
+
<span style="color:#64748b"> {JSON.stringify(ev.attributes)}</span>
|
|
414
|
+
)}
|
|
415
|
+
</div>
|
|
416
|
+
))}
|
|
417
|
+
</div>
|
|
418
|
+
)}
|
|
419
|
+
</div>
|
|
420
|
+
</details>
|
|
421
|
+
)
|
|
422
|
+
})}
|
|
423
|
+
</div>
|
|
424
|
+
</>
|
|
425
|
+
)
|
|
426
|
+
}
|
package/src/datastar/README.md
CHANGED
|
@@ -6,7 +6,7 @@ We experimentally place it inside Effect Start to have tighter integration with
|
|
|
6
6
|
great out-of-the-box experience. After cleaning up the code, we're at around ~90kb of source code.
|
|
7
7
|
We can probably cut it down by another ~10kb if we remove DataStar expression and use JS functions directly.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
We made following changes:
|
|
10
10
|
|
|
11
11
|
- Path aliases converted to relative imports: `@engine/*` → `./engine/*`, etc.
|
|
12
12
|
- Flattened `plugins/` directory: `plugins/actions/` → `actions/`, etc.
|
|
@@ -16,3 +16,8 @@ Based on `812cbe9` (2025-02-05) following changes were made:
|
|
|
16
16
|
- Updated type declaration to conform to `erasableSyntaxOnly`:
|
|
17
17
|
- Converted `enum ReactiveFlags` and `enum EffectFlags` to `const` objects with `as const`
|
|
18
18
|
- Added type aliases `ReactiveFlags_X` to replace `ReactiveFlags.X` namespace types
|
|
19
|
+
- Extends expressions with function form handled by `genRx`
|
|
20
|
+
- `data-on` supports function form with optional config object:
|
|
21
|
+
- Function form: `data-on:click="(e) => { e.signals.count.value++ }"`
|
|
22
|
+
- Function form with config: `data-on:click="(e) => {...}, { debounce: 500, prevent: true }"`
|
|
23
|
+
- !! `__` attribute modifiers are no longer parsed by `on.ts` (now removed from imports)
|
|
@@ -285,7 +285,6 @@ const getLines = (onLine: (line: Uint8Array, fieldLength: number) => void) => {
|
|
|
285
285
|
}
|
|
286
286
|
break
|
|
287
287
|
// @ts-expect-error:7029
|
|
288
|
-
// biome-ignore lint/suspicious/noFallthroughSwitchClause: intentional fallthrough for CR to LF
|
|
289
288
|
case 13:
|
|
290
289
|
discardTrailingNewline = true
|
|
291
290
|
case 10:
|
|
@@ -4,46 +4,66 @@ import {
|
|
|
4
4
|
DATASTAR_FETCH_EVENT,
|
|
5
5
|
DATASTAR_SIGNAL_PATCH_EVENT,
|
|
6
6
|
endBatch,
|
|
7
|
+
type Modifiers,
|
|
7
8
|
} from "../engine.ts"
|
|
8
|
-
import {
|
|
9
|
+
import { modifyTiming, modifyViewTransition } from "../utils.ts"
|
|
10
|
+
|
|
11
|
+
// TODO: support leading/trailing options for debounce/throttle
|
|
12
|
+
// e.g. { debounce: { ms: 500, leading: true, noTrailing: true } }
|
|
13
|
+
const configToMods = (config: Record<string, any>): Modifiers => {
|
|
14
|
+
const mods: Modifiers = new Map()
|
|
15
|
+
for (const [k, v] of Object.entries(config)) {
|
|
16
|
+
if (v === true) {
|
|
17
|
+
mods.set(k, new Set())
|
|
18
|
+
} else if (typeof v === "number") {
|
|
19
|
+
mods.set(k, new Set([`${v}ms`]))
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return mods
|
|
23
|
+
}
|
|
9
24
|
|
|
10
25
|
attribute({
|
|
11
26
|
name: "on",
|
|
12
27
|
requirement: "must",
|
|
13
28
|
argNames: ["evt"],
|
|
14
|
-
apply({ el, key, mods, rx }) {
|
|
29
|
+
apply({ el, key, mods, rx, value }) {
|
|
30
|
+
let userFn: Function | undefined
|
|
31
|
+
let effectiveMods = mods
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const parts = Function(`return [${value}]`)()
|
|
35
|
+
if (typeof parts[0] === "function") {
|
|
36
|
+
userFn = parts[0]
|
|
37
|
+
if (parts[1]) effectiveMods = configToMods(parts[1])
|
|
38
|
+
}
|
|
39
|
+
} catch {}
|
|
40
|
+
|
|
15
41
|
let target: Element | Window | Document = el
|
|
16
|
-
if (
|
|
42
|
+
if (effectiveMods.has("window")) target = window
|
|
17
43
|
let callback = (evt?: Event) => {
|
|
18
44
|
if (evt) {
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
if (mods.has("stop")) {
|
|
23
|
-
evt.stopPropagation()
|
|
24
|
-
}
|
|
45
|
+
if (effectiveMods.has("prevent")) evt.preventDefault()
|
|
46
|
+
if (effectiveMods.has("stop")) evt.stopPropagation()
|
|
25
47
|
}
|
|
26
48
|
beginBatch()
|
|
27
|
-
rx(evt)
|
|
49
|
+
userFn ? userFn(evt) : rx(evt)
|
|
28
50
|
endBatch()
|
|
29
51
|
}
|
|
30
|
-
callback = modifyViewTransition(callback,
|
|
31
|
-
callback = modifyTiming(callback,
|
|
52
|
+
callback = modifyViewTransition(callback, effectiveMods)
|
|
53
|
+
callback = modifyTiming(callback, effectiveMods)
|
|
32
54
|
const evtListOpts: AddEventListenerOptions = {
|
|
33
|
-
capture:
|
|
34
|
-
passive:
|
|
35
|
-
once:
|
|
55
|
+
capture: effectiveMods.has("capture"),
|
|
56
|
+
passive: effectiveMods.has("passive"),
|
|
57
|
+
once: effectiveMods.has("once"),
|
|
36
58
|
}
|
|
37
|
-
if (
|
|
59
|
+
if (effectiveMods.has("outside")) {
|
|
38
60
|
target = document
|
|
39
61
|
const cb = callback
|
|
40
62
|
callback = (evt?: Event) => {
|
|
41
|
-
if (!el.contains(evt?.target as HTMLElement))
|
|
42
|
-
cb(evt)
|
|
43
|
-
}
|
|
63
|
+
if (!el.contains(evt?.target as HTMLElement)) cb(evt)
|
|
44
64
|
}
|
|
45
65
|
}
|
|
46
|
-
const eventName =
|
|
66
|
+
const eventName = key
|
|
47
67
|
if (eventName === DATASTAR_FETCH_EVENT || eventName === DATASTAR_SIGNAL_PATCH_EVENT) {
|
|
48
68
|
target = document
|
|
49
69
|
}
|
package/src/datastar/engine.ts
CHANGED
|
@@ -116,6 +116,14 @@ export type MergePatchArgs = {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
export type HTMLOrSVG = HTMLElement | SVGElement | MathMLElement
|
|
119
|
+
|
|
120
|
+
export type DataEvent = Event & {
|
|
121
|
+
signals: Record<string, any>
|
|
122
|
+
actions: Record<string, (...args: Array<any>) => any>
|
|
123
|
+
target: HTMLOrSVG
|
|
124
|
+
window: Window & typeof globalThis
|
|
125
|
+
}
|
|
126
|
+
|
|
119
127
|
export type Modifiers = Map<string, Set<string>>
|
|
120
128
|
|
|
121
129
|
export type EventCallbackHandler = (...args: Array<any>) => void
|
|
@@ -1187,6 +1195,49 @@ const genRx = (
|
|
|
1187
1195
|
value: string,
|
|
1188
1196
|
{ returnsValue = false, argNames = [], cleanups = new Map() }: GenRxOptions = {},
|
|
1189
1197
|
): GenRxFn => {
|
|
1198
|
+
if (/^\s*(?:async\s+)?(?:\(.*?\)\s*=>|[\w$]+\s*=>|function\s*[\w$]*\s*\()/.test(value)) {
|
|
1199
|
+
const userFn = Function(`return (${value.trim()})`)()
|
|
1200
|
+
|
|
1201
|
+
return (el: HTMLOrSVG, ...args: Array<any>) => {
|
|
1202
|
+
const actionsProxy = new Proxy({} as Record<string, any>, {
|
|
1203
|
+
get:
|
|
1204
|
+
(_, name: string) =>
|
|
1205
|
+
(...actionArgs: Array<any>) => {
|
|
1206
|
+
const err = error.bind(0, {
|
|
1207
|
+
plugin: { type: "action", name },
|
|
1208
|
+
element: { id: el.id, tag: el.tagName },
|
|
1209
|
+
expression: { fnContent: value, value },
|
|
1210
|
+
})
|
|
1211
|
+
const fn = actions[name]
|
|
1212
|
+
if (fn) return fn({ el, evt: undefined, error: err, cleanups }, ...actionArgs)
|
|
1213
|
+
throw err("UndefinedAction")
|
|
1214
|
+
},
|
|
1215
|
+
})
|
|
1216
|
+
|
|
1217
|
+
const dataEvt = args[0] instanceof Event ? args[0] : new Event("datastar:expression")
|
|
1218
|
+
Object.defineProperties(dataEvt, {
|
|
1219
|
+
target: { value: el },
|
|
1220
|
+
signals: { value: root },
|
|
1221
|
+
actions: { value: actionsProxy },
|
|
1222
|
+
window: { value: window },
|
|
1223
|
+
})
|
|
1224
|
+
|
|
1225
|
+
try {
|
|
1226
|
+
return userFn(dataEvt)
|
|
1227
|
+
} catch (e: any) {
|
|
1228
|
+
console.error(e)
|
|
1229
|
+
throw error(
|
|
1230
|
+
{
|
|
1231
|
+
element: { id: el.id, tag: el.tagName },
|
|
1232
|
+
expression: { fnContent: value, value },
|
|
1233
|
+
error: e.message,
|
|
1234
|
+
},
|
|
1235
|
+
"ExecuteExpression",
|
|
1236
|
+
)
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1190
1241
|
let expr = ""
|
|
1191
1242
|
if (returnsValue) {
|
|
1192
1243
|
const statementRe =
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { DataEvent } from "./engine.ts"
|
|
2
|
+
|
|
3
|
+
// Datastar object types for specific attributes
|
|
4
|
+
type DatastarSignalsObject = Record<string, any>
|
|
5
|
+
type DatastarClassObject = Record<string, boolean | string>
|
|
6
|
+
type DatastarAttrObject = Record<string, string | boolean | number>
|
|
7
|
+
type DatastarStyleObject = Record<string, string | number | boolean | null | undefined>
|
|
8
|
+
|
|
9
|
+
type DatastarFn = (e: DataEvent) => any
|
|
10
|
+
|
|
11
|
+
// TODO: support leading/trailing options
|
|
12
|
+
// e.g. { debounce: { ms: 500, leading: true, noTrailing: true } }
|
|
13
|
+
type DatastarOnConfig = {
|
|
14
|
+
prevent?: boolean
|
|
15
|
+
stop?: boolean
|
|
16
|
+
capture?: boolean
|
|
17
|
+
passive?: boolean
|
|
18
|
+
once?: boolean
|
|
19
|
+
outside?: boolean
|
|
20
|
+
window?: boolean
|
|
21
|
+
viewTransition?: boolean
|
|
22
|
+
} & ({ debounce?: number; throttle?: never } | { debounce?: never; throttle?: number })
|
|
23
|
+
|
|
24
|
+
type DatastarOnFn = DatastarFn | [handler: DatastarFn, config: DatastarOnConfig]
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Datastar attributes for reactive web applications
|
|
28
|
+
* @see https://data-star.dev/reference/attributes
|
|
29
|
+
*/
|
|
30
|
+
export interface DatastarAttributes {
|
|
31
|
+
// Core attributes that can accept objects (but also strings)
|
|
32
|
+
"data-signals"?: string | DatastarSignalsObject | undefined
|
|
33
|
+
"data-class"?: string | DatastarFn | DatastarClassObject | undefined
|
|
34
|
+
"data-attr"?: string | DatastarFn | DatastarAttrObject | undefined
|
|
35
|
+
"data-style"?: string | DatastarFn | DatastarStyleObject | undefined
|
|
36
|
+
|
|
37
|
+
// Boolean/presence attributes (but also strings)
|
|
38
|
+
"data-show"?: string | DatastarFn | boolean | undefined
|
|
39
|
+
"data-ignore"?: string | boolean | undefined
|
|
40
|
+
"data-ignore-morph"?: string | boolean | undefined
|
|
41
|
+
|
|
42
|
+
// Attributes that accept function expressions
|
|
43
|
+
"data-bind"?: string | undefined
|
|
44
|
+
"data-computed"?: string | DatastarFn | undefined
|
|
45
|
+
"data-effect"?: string | DatastarFn | undefined
|
|
46
|
+
"data-indicator"?: string | undefined
|
|
47
|
+
"data-json-signals"?: string | undefined
|
|
48
|
+
"data-on"?: string | DatastarOnFn | undefined
|
|
49
|
+
"data-on-intersect"?: string | DatastarOnFn | undefined
|
|
50
|
+
"data-on-interval"?: string | DatastarOnFn | undefined
|
|
51
|
+
"data-on-load"?: string | DatastarOnFn | undefined
|
|
52
|
+
"data-on-signal-patch"?: string | DatastarOnFn | undefined
|
|
53
|
+
"data-on-signal-patch-filter"?: string | undefined
|
|
54
|
+
"data-preserve-attr"?: string | undefined
|
|
55
|
+
"data-ref"?: string | undefined
|
|
56
|
+
"data-text"?: string | DatastarFn | undefined
|
|
57
|
+
|
|
58
|
+
// Pro attributes
|
|
59
|
+
"data-animate"?: string | undefined
|
|
60
|
+
"data-custom-validity"?: string | DatastarFn | undefined
|
|
61
|
+
"data-on-raf"?: string | DatastarOnFn | undefined
|
|
62
|
+
"data-on-resize"?: string | DatastarOnFn | undefined
|
|
63
|
+
"data-persist"?: string | undefined
|
|
64
|
+
"data-query-string"?: string | undefined
|
|
65
|
+
"data-replace-url"?: string | undefined
|
|
66
|
+
"data-scroll-into-view"?: string | undefined
|
|
67
|
+
"data-view-transition"?: string | undefined
|
|
68
|
+
|
|
69
|
+
// Dynamic attributes with suffixes
|
|
70
|
+
[key: `data-signals:${string}`]: string | undefined
|
|
71
|
+
[key: `data-class:${string}`]: string | DatastarFn | undefined
|
|
72
|
+
[key: `data-attr:${string}`]: string | DatastarFn | undefined
|
|
73
|
+
[key: `data-style:${string}`]: string | DatastarFn | undefined
|
|
74
|
+
[key: `data-bind:${string}`]: string | undefined
|
|
75
|
+
[key: `data-computed:${string}`]: string | DatastarFn | undefined
|
|
76
|
+
[key: `data-indicator:${string}`]: string | undefined
|
|
77
|
+
[key: `data-ref:${string}`]: string | undefined
|
|
78
|
+
[key: `data-on:${string}`]: string | DatastarOnFn | undefined
|
|
79
|
+
}
|