effect-start 0.32.0 → 0.34.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/Entity.d.ts +6 -1
- package/dist/Entity.d.ts.map +1 -1
- package/dist/Entity.js +43 -5
- package/dist/Entity.js.map +1 -1
- package/dist/Fetch.js.map +1 -1
- package/dist/FileRouterCodegen.js +2 -2
- package/dist/FileRouterCodegen.js.map +1 -1
- package/dist/Html.d.ts +5 -11
- package/dist/Html.d.ts.map +1 -1
- package/dist/Html.js +21 -1
- package/dist/Html.js.map +1 -1
- package/dist/KeyValueStore.d.ts +37 -0
- package/dist/KeyValueStore.d.ts.map +1 -0
- package/dist/KeyValueStore.js +99 -0
- package/dist/KeyValueStore.js.map +1 -0
- package/dist/Route.d.ts +2 -2
- package/dist/Route.d.ts.map +1 -1
- package/dist/Route.js +1 -1
- package/dist/Route.js.map +1 -1
- package/dist/RouteBody.d.ts +2 -2
- package/dist/RouteBody.d.ts.map +1 -1
- package/dist/RouteHttp.d.ts.map +1 -1
- package/dist/RouteHttp.js +45 -35
- package/dist/RouteHttp.js.map +1 -1
- package/dist/RouteMount.d.ts +20 -31
- package/dist/RouteMount.d.ts.map +1 -1
- package/dist/RouteMount.js +0 -15
- package/dist/RouteMount.js.map +1 -1
- package/dist/Start.d.ts.map +1 -1
- package/dist/Start.js +4 -0
- package/dist/Start.js.map +1 -1
- package/dist/StaticFiles.d.ts +2 -2
- package/dist/StaticFiles.d.ts.map +1 -1
- package/dist/StaticFiles.js +7 -8
- package/dist/StaticFiles.js.map +1 -1
- package/dist/bun/BunRoute.d.ts.map +1 -1
- package/dist/bun/BunRoute.js +90 -78
- package/dist/bun/BunRoute.js.map +1 -1
- package/dist/bun/BunServer.d.ts +1 -1
- package/dist/bun/BunServer.d.ts.map +1 -1
- package/dist/bun/BunServer.js +8 -1
- package/dist/bun/BunServer.js.map +1 -1
- package/dist/bundler/BundleRoute.d.ts +4 -4
- package/dist/bundler/BundleRoute.d.ts.map +1 -1
- package/dist/datastar/attributes/computed.js +3 -3
- package/dist/datastar/attributes/computed.js.map +1 -1
- package/dist/datastar/attributes/on.js +11 -36
- package/dist/datastar/attributes/on.js.map +1 -1
- package/dist/datastar/engine.d.ts +9 -7
- package/dist/datastar/engine.d.ts.map +1 -1
- package/dist/datastar/engine.js +45 -29
- package/dist/datastar/engine.js.map +1 -1
- package/dist/datastar/jsx.d.ts +70 -0
- package/dist/datastar/jsx.d.ts.map +1 -0
- package/dist/datastar/jsx.js +2 -0
- package/dist/datastar/jsx.js.map +1 -0
- package/dist/datastar/window.d.ts +8 -0
- package/dist/datastar/window.d.ts.map +1 -0
- package/dist/datastar/window.js +4 -0
- package/dist/datastar/window.js.map +1 -0
- package/dist/experimental/KeyValueStore.d.ts +37 -0
- package/dist/experimental/KeyValueStore.d.ts.map +1 -0
- package/dist/experimental/KeyValueStore.js +99 -0
- package/dist/experimental/KeyValueStore.js.map +1 -0
- package/dist/experimental/SqlCache.d.ts +19 -0
- package/dist/experimental/SqlCache.d.ts.map +1 -0
- package/dist/experimental/SqlCache.js +35 -0
- package/dist/experimental/SqlCache.js.map +1 -0
- package/dist/experimental/SqlIntrospect.d.ts +92 -0
- package/dist/experimental/SqlIntrospect.d.ts.map +1 -0
- package/dist/experimental/SqlIntrospect.js +478 -0
- package/dist/experimental/SqlIntrospect.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/jsx-runtime.d.ts +2 -2
- package/dist/jsx-runtime.d.ts.map +1 -1
- package/dist/jsx.d.ts +3216 -0
- package/dist/jsx.d.ts.map +1 -0
- package/dist/jsx.js +6 -0
- package/dist/jsx.js.map +1 -0
- package/dist/lint/plugin.d.ts +4 -3
- package/dist/lint/plugin.js +56 -17
- package/dist/lint/plugin.js.map +1 -1
- package/dist/sql/index.d.ts +0 -2
- package/dist/sql/index.d.ts.map +1 -1
- package/dist/sql/index.js +0 -2
- package/dist/sql/index.js.map +1 -1
- package/dist/studio/StudioLogger.d.ts.map +1 -1
- package/dist/studio/StudioLogger.js +2 -1
- package/dist/studio/StudioLogger.js.map +1 -1
- package/dist/studio/StudioStore.d.ts +3 -0
- package/dist/studio/StudioStore.d.ts.map +1 -1
- package/dist/studio/StudioStore.js +13 -0
- package/dist/studio/StudioStore.js.map +1 -1
- package/dist/studio/_Pretty.d.ts +4 -0
- package/dist/studio/_Pretty.d.ts.map +1 -0
- package/dist/studio/_Pretty.js +56 -0
- package/dist/studio/_Pretty.js.map +1 -0
- package/dist/studio/routes/errors/route.d.ts +2 -2
- package/dist/studio/routes/fiberDetail.d.ts +2 -2
- package/dist/studio/routes/fibers/route.d.ts +2 -2
- package/dist/studio/routes/layout.d.ts +2 -0
- package/dist/studio/routes/layout.d.ts.map +1 -1
- package/dist/studio/routes/layout.html +3 -12
- package/dist/studio/routes/layout.js +6 -1
- package/dist/studio/routes/layout.js.map +1 -1
- package/dist/studio/routes/logs/route.d.ts +2 -2
- package/dist/studio/routes/metrics/route.d.ts +2 -2
- package/dist/studio/routes/route.d.ts +2 -2
- package/dist/studio/routes/routes/route.d.ts +2 -2
- package/dist/studio/routes/services/route.d.ts +2 -2
- package/dist/studio/routes/system/route.d.ts +2 -2
- package/dist/studio/routes/traceDetail.d.ts +2 -2
- package/dist/studio/routes/traces/route.d.ts +2 -2
- package/dist/studio/routes/traces/route.d.ts.map +1 -1
- package/dist/studio/routes/traces/route.js +5 -2
- package/dist/studio/routes/traces/route.js.map +1 -1
- package/dist/studio/routes/tree.d.ts +22 -0
- package/dist/studio/routes/tree.d.ts.map +1 -1
- package/dist/studio/ui/Errors.d.ts +1 -1
- package/dist/studio/ui/Errors.js +1 -1
- package/dist/studio/ui/Errors.js.map +1 -1
- package/dist/studio/ui/Fibers.d.ts +2 -2
- package/dist/studio/ui/Fibers.d.ts.map +1 -1
- package/dist/studio/ui/Fibers.js +4 -3
- package/dist/studio/ui/Fibers.js.map +1 -1
- package/dist/studio/ui/Logs.d.ts +1 -1
- package/dist/studio/ui/Logs.d.ts.map +1 -1
- package/dist/studio/ui/Logs.js +2 -1
- package/dist/studio/ui/Logs.js.map +1 -1
- package/dist/studio/ui/Metrics.d.ts +1 -1
- package/dist/studio/ui/Routes.d.ts +1 -1
- package/dist/studio/ui/Routes.d.ts.map +1 -1
- package/dist/studio/ui/Services.d.ts +1 -1
- package/dist/studio/ui/Services.d.ts.map +1 -1
- package/dist/studio/ui/Shell.d.ts +2 -2
- package/dist/studio/ui/Shell.d.ts.map +1 -1
- package/dist/studio/ui/System.d.ts +1 -1
- package/dist/studio/ui/Traces.d.ts +3 -3
- package/dist/studio/ui/Traces.d.ts.map +1 -1
- package/dist/studio/ui/Traces.js +5 -11
- package/dist/studio/ui/Traces.js.map +1 -1
- package/dist/studio/ui/_PrettyValue.d.ts +10 -0
- package/dist/studio/ui/_PrettyValue.d.ts.map +1 -0
- package/dist/studio/ui/_PrettyValue.js +27 -0
- package/dist/studio/ui/_PrettyValue.js.map +1 -0
- package/dist/tailwind/TailwindPlugin.d.ts.map +1 -1
- package/dist/tailwind/TailwindPlugin.js +89 -62
- package/dist/tailwind/TailwindPlugin.js.map +1 -1
- package/dist/ts/import-plugin.cjs +388 -0
- package/dist/ts/import-plugin.cjs.map +1 -0
- package/dist/ts/import-plugin.d.cts +87 -0
- package/dist/ts/import-plugin.d.cts.map +1 -0
- package/dist/ts/import-plugin.d.ts +87 -0
- package/dist/ts/import-plugin.d.ts.map +1 -0
- package/dist/ts/import-plugin.js +390 -0
- package/dist/ts/import-plugin.js.map +1 -0
- package/package.json +109 -8
- package/src/Entity.ts +62 -8
- package/src/Fetch.ts +1 -1
- package/src/FileRouterCodegen.ts +2 -2
- package/src/Html.ts +28 -21
- package/src/Route.ts +2 -2
- package/src/RouteBody.ts +2 -2
- package/src/RouteHttp.ts +45 -47
- package/src/RouteMount.ts +23 -65
- package/src/Start.ts +4 -0
- package/src/StaticFiles.ts +7 -10
- package/src/bun/BunRoute.ts +117 -95
- package/src/bun/BunServer.ts +9 -2
- package/src/datastar/README.md +24 -8
- package/src/datastar/attributes/computed.ts +3 -3
- package/src/datastar/attributes/on.ts +11 -37
- package/src/datastar/engine.ts +61 -37
- package/src/datastar/jsx.d.ts +12 -26
- package/src/datastar/types.d.ts +8 -0
- package/src/experimental/KeyValueStore.ts +161 -0
- package/src/{sql → experimental}/SqlCache.ts +1 -1
- package/src/{sql → experimental}/SqlIntrospect.ts +1 -1
- package/src/index.ts +1 -0
- package/src/jsx-runtime.ts +1 -1
- package/src/jsx.d.ts +17 -2
- package/src/lint/plugin.js +54 -19
- package/src/sql/index.ts +0 -2
- package/src/studio/StudioLogger.ts +2 -1
- package/src/studio/StudioStore.ts +18 -0
- package/src/studio/_Pretty.ts +59 -0
- package/src/studio/routes/layout.html +3 -12
- package/src/studio/routes/layout.tsx +9 -1
- package/src/studio/routes/traces/route.tsx +5 -1
- package/src/studio/ui/Errors.tsx +1 -1
- package/src/studio/ui/Fibers.tsx +14 -10
- package/src/studio/ui/Logs.tsx +15 -10
- package/src/studio/ui/Traces.tsx +40 -68
- package/src/studio/ui/_PrettyValue.tsx +34 -0
- package/src/tailwind/TailwindPlugin.ts +102 -75
- package/src/RouteTrie.ts +0 -205
- package/src/experimental/index.ts +0 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import * as Context from "effect/Context"
|
|
2
|
+
import * as Data from "effect/Data"
|
|
3
|
+
import * as Effect from "effect/Effect"
|
|
4
|
+
import * as Either from "effect/Either"
|
|
5
|
+
import * as Encoding from "effect/Encoding"
|
|
6
|
+
import * as Function from "effect/Function"
|
|
7
|
+
import * as Layer from "effect/Layer"
|
|
8
|
+
import * as Predicate from "effect/Predicate"
|
|
9
|
+
|
|
10
|
+
const TypeId = "effect-start/KeyValueStore" as const
|
|
11
|
+
|
|
12
|
+
export interface KeyValueStore {
|
|
13
|
+
readonly [TypeId]: typeof TypeId
|
|
14
|
+
readonly get: (key: string) => Effect.Effect<string | undefined, KeyValueStoreError>
|
|
15
|
+
readonly getUint8Array: (key: string) => Effect.Effect<Uint8Array | undefined, KeyValueStoreError>
|
|
16
|
+
readonly set: (key: string, value: string | Uint8Array) => Effect.Effect<void, KeyValueStoreError>
|
|
17
|
+
readonly remove: (key: string) => Effect.Effect<void, KeyValueStoreError>
|
|
18
|
+
readonly clear: Effect.Effect<void, KeyValueStoreError>
|
|
19
|
+
readonly size: Effect.Effect<number, KeyValueStoreError>
|
|
20
|
+
readonly modify: (
|
|
21
|
+
key: string,
|
|
22
|
+
f: (value: string) => string,
|
|
23
|
+
) => Effect.Effect<string | undefined, KeyValueStoreError>
|
|
24
|
+
readonly modifyUint8Array: (
|
|
25
|
+
key: string,
|
|
26
|
+
f: (value: Uint8Array) => Uint8Array,
|
|
27
|
+
) => Effect.Effect<Uint8Array | undefined, KeyValueStoreError>
|
|
28
|
+
readonly has: (key: string) => Effect.Effect<boolean, KeyValueStoreError>
|
|
29
|
+
readonly isEmpty: Effect.Effect<boolean, KeyValueStoreError>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type MakeOptions = Partial<KeyValueStore> & {
|
|
33
|
+
readonly get: (key: string) => Effect.Effect<string | undefined, KeyValueStoreError>
|
|
34
|
+
readonly getUint8Array: (key: string) => Effect.Effect<Uint8Array | undefined, KeyValueStoreError>
|
|
35
|
+
readonly set: (key: string, value: string | Uint8Array) => Effect.Effect<void, KeyValueStoreError>
|
|
36
|
+
readonly remove: (key: string) => Effect.Effect<void, KeyValueStoreError>
|
|
37
|
+
readonly clear: Effect.Effect<void, KeyValueStoreError>
|
|
38
|
+
readonly size: Effect.Effect<number, KeyValueStoreError>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type MakeStringOptions = Partial<Omit<KeyValueStore, "set">> & {
|
|
42
|
+
readonly get: (key: string) => Effect.Effect<string | undefined, KeyValueStoreError>
|
|
43
|
+
readonly set: (key: string, value: string) => Effect.Effect<void, KeyValueStoreError>
|
|
44
|
+
readonly remove: (key: string) => Effect.Effect<void, KeyValueStoreError>
|
|
45
|
+
readonly clear: Effect.Effect<void, KeyValueStoreError>
|
|
46
|
+
readonly size: Effect.Effect<number, KeyValueStoreError>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export class KeyValueStoreError extends Data.TaggedError("KeyValueStoreError")<{
|
|
50
|
+
message: string
|
|
51
|
+
method: string
|
|
52
|
+
key?: string
|
|
53
|
+
cause?: unknown
|
|
54
|
+
}> {}
|
|
55
|
+
|
|
56
|
+
export const KeyValueStore: Context.Tag<KeyValueStore, KeyValueStore> = Context.GenericTag<KeyValueStore>(
|
|
57
|
+
"effect-start/KeyValueStore",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
const make = (options: MakeOptions): KeyValueStore => ({
|
|
61
|
+
[TypeId]: TypeId,
|
|
62
|
+
has: (key) => Effect.map(options.get(key), Predicate.isNotUndefined),
|
|
63
|
+
isEmpty: Effect.map(options.size, (size) => size === 0),
|
|
64
|
+
modify: (key, f) =>
|
|
65
|
+
Effect.flatMap(options.get(key), (o) => {
|
|
66
|
+
if (o === undefined) return Effect.succeed(undefined)
|
|
67
|
+
const newValue = f(o)
|
|
68
|
+
return Effect.as(options.set(key, newValue), newValue)
|
|
69
|
+
}),
|
|
70
|
+
modifyUint8Array: (key, f) =>
|
|
71
|
+
Effect.flatMap(options.getUint8Array(key), (o) => {
|
|
72
|
+
if (o === undefined) return Effect.succeed(undefined)
|
|
73
|
+
const newValue = f(o)
|
|
74
|
+
return Effect.as(options.set(key, newValue), newValue)
|
|
75
|
+
}),
|
|
76
|
+
...options,
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
const makeStringOnly = (options: MakeStringOptions): KeyValueStore => {
|
|
80
|
+
const encoder = new TextEncoder()
|
|
81
|
+
return make({
|
|
82
|
+
...options,
|
|
83
|
+
getUint8Array: (key) =>
|
|
84
|
+
Effect.map(options.get(key), (value) => {
|
|
85
|
+
if (value === undefined) return undefined
|
|
86
|
+
const decoded = Encoding.decodeBase64(value)
|
|
87
|
+
return Either.isRight(decoded) ? decoded.right : encoder.encode(value)
|
|
88
|
+
}),
|
|
89
|
+
set: (key, value) =>
|
|
90
|
+
typeof value === "string"
|
|
91
|
+
? options.set(key, value)
|
|
92
|
+
: Effect.suspend(() => options.set(key, Encoding.encodeBase64(value))),
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const prefix: {
|
|
97
|
+
(prefix: string): (self: KeyValueStore) => KeyValueStore
|
|
98
|
+
(self: KeyValueStore, prefix: string): KeyValueStore
|
|
99
|
+
} = Function.dual(2, (self: KeyValueStore, prefix: string): KeyValueStore => ({
|
|
100
|
+
...self,
|
|
101
|
+
get: (key) => self.get(`${prefix}${key}`),
|
|
102
|
+
getUint8Array: (key) => self.getUint8Array(`${prefix}${key}`),
|
|
103
|
+
set: (key, value) => self.set(`${prefix}${key}`, value),
|
|
104
|
+
remove: (key) => self.remove(`${prefix}${key}`),
|
|
105
|
+
has: (key) => self.has(`${prefix}${key}`),
|
|
106
|
+
modify: (key, f) => self.modify(`${prefix}${key}`, f),
|
|
107
|
+
modifyUint8Array: (key, f) => self.modifyUint8Array(`${prefix}${key}`, f),
|
|
108
|
+
}))
|
|
109
|
+
|
|
110
|
+
export const layerMemory: Layer.Layer<KeyValueStore> = Layer.sync(KeyValueStore, () => {
|
|
111
|
+
const store = new Map<string, string | Uint8Array>()
|
|
112
|
+
const encoder = new TextEncoder()
|
|
113
|
+
|
|
114
|
+
return make({
|
|
115
|
+
get: (key: string) =>
|
|
116
|
+
Effect.sync(() => {
|
|
117
|
+
const value = store.get(key)
|
|
118
|
+
return value === undefined ? undefined : typeof value === "string" ? value : Encoding.encodeBase64(value)
|
|
119
|
+
}),
|
|
120
|
+
getUint8Array: (key: string) =>
|
|
121
|
+
Effect.sync(() => {
|
|
122
|
+
const value = store.get(key)
|
|
123
|
+
return value === undefined ? undefined : typeof value === "string" ? encoder.encode(value) : value
|
|
124
|
+
}),
|
|
125
|
+
set: (key: string, value: string | Uint8Array) => Effect.sync(() => store.set(key, value)),
|
|
126
|
+
remove: (key: string) => Effect.sync(() => store.delete(key)),
|
|
127
|
+
clear: Effect.sync(() => store.clear()),
|
|
128
|
+
size: Effect.sync(() => store.size),
|
|
129
|
+
})
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
export const layerStorage = (evaluate: Function.LazyArg<Storage>): Layer.Layer<KeyValueStore> =>
|
|
133
|
+
Layer.sync(KeyValueStore, () => {
|
|
134
|
+
const storage = evaluate()
|
|
135
|
+
return makeStringOnly({
|
|
136
|
+
get: (key: string) =>
|
|
137
|
+
Effect.try({
|
|
138
|
+
try: () => storage.getItem(key) ?? undefined,
|
|
139
|
+
catch: () => new KeyValueStoreError({ key, method: "get", message: `Unable to get item with key ${key}` }),
|
|
140
|
+
}),
|
|
141
|
+
set: (key: string, value: string) =>
|
|
142
|
+
Effect.try({
|
|
143
|
+
try: () => storage.setItem(key, value),
|
|
144
|
+
catch: () => new KeyValueStoreError({ key, method: "set", message: `Unable to set item with key ${key}` }),
|
|
145
|
+
}),
|
|
146
|
+
remove: (key: string) =>
|
|
147
|
+
Effect.try({
|
|
148
|
+
try: () => storage.removeItem(key),
|
|
149
|
+
catch: () =>
|
|
150
|
+
new KeyValueStoreError({ key, method: "remove", message: `Unable to remove item with key ${key}` }),
|
|
151
|
+
}),
|
|
152
|
+
clear: Effect.try({
|
|
153
|
+
try: () => storage.clear(),
|
|
154
|
+
catch: () => new KeyValueStoreError({ method: "clear", message: `Unable to clear storage` }),
|
|
155
|
+
}),
|
|
156
|
+
size: Effect.try({
|
|
157
|
+
try: () => storage.length,
|
|
158
|
+
catch: () => new KeyValueStoreError({ method: "size", message: `Unable to get size` }),
|
|
159
|
+
}),
|
|
160
|
+
})
|
|
161
|
+
})
|
|
@@ -3,7 +3,7 @@ import * as Context from "effect/Context"
|
|
|
3
3
|
import type * as Duration from "effect/Duration"
|
|
4
4
|
import * as Effect from "effect/Effect"
|
|
5
5
|
import * as Layer from "effect/Layer"
|
|
6
|
-
import type * as SqlClient from "
|
|
6
|
+
import type * as SqlClient from "../sql/SqlClient.ts"
|
|
7
7
|
|
|
8
8
|
type SqlCacheInstance = Cache.Cache<string, ReadonlyArray<any>>
|
|
9
9
|
|
package/src/index.ts
CHANGED
package/src/jsx-runtime.ts
CHANGED
package/src/jsx.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type * as Html from "./Html.ts"
|
|
2
1
|
import type { DatastarAttributes } from "./datastar/jsx.d.ts"
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -16,8 +15,24 @@ import type { DatastarAttributes } from "./datastar/jsx.d.ts"
|
|
|
16
15
|
*/
|
|
17
16
|
type DOMElement = never
|
|
18
17
|
|
|
18
|
+
type HtmlPrimitive = string | number | boolean | null | undefined
|
|
19
|
+
export type HtmlElementType = string | HtmlComponent
|
|
20
|
+
export type HtmlElemenetProps = {
|
|
21
|
+
[key: string]:
|
|
22
|
+
| HtmlPrimitive
|
|
23
|
+
| HtmlElement
|
|
24
|
+
| Iterable<HtmlPrimitive | HtmlElement>
|
|
25
|
+
| Record<string, unknown>
|
|
26
|
+
| ((window: Window) => void)
|
|
27
|
+
}
|
|
28
|
+
export type HtmlComponent = (props: HtmlElemenetProps) => HtmlElement | HtmlPrimitive
|
|
29
|
+
export interface HtmlElement {
|
|
30
|
+
type: HtmlElementType
|
|
31
|
+
props: HtmlElemenetProps
|
|
32
|
+
}
|
|
33
|
+
|
|
19
34
|
export namespace JSX {
|
|
20
|
-
type Element =
|
|
35
|
+
type Element = HtmlElement
|
|
21
36
|
type Child = Element | string | number | bigint
|
|
22
37
|
type Children = Child | SilentChild | Iterable<Children>
|
|
23
38
|
|
package/src/lint/plugin.js
CHANGED
|
@@ -146,35 +146,39 @@ export default {
|
|
|
146
146
|
},
|
|
147
147
|
},
|
|
148
148
|
|
|
149
|
-
|
|
150
|
-
"export-default-before-functions": {
|
|
149
|
+
"schema-type-helpers": {
|
|
151
150
|
meta: {
|
|
152
151
|
type: "suggestion",
|
|
153
152
|
docs: {
|
|
154
|
-
description:
|
|
153
|
+
description:
|
|
154
|
+
"Prefer `typeof User.Type` over `Schema.Schema.Type<typeof User>`",
|
|
155
155
|
},
|
|
156
|
+
fixable: "code",
|
|
156
157
|
schema: [],
|
|
157
158
|
messages: {
|
|
158
|
-
|
|
159
|
+
preferTypeof:
|
|
160
|
+
'Use `typeof {{name}}.Type` instead of `Schema.Schema.Type<typeof {{name}}>`',
|
|
159
161
|
},
|
|
160
162
|
},
|
|
161
163
|
create(context) {
|
|
164
|
+
function walk(node) {
|
|
165
|
+
if (!node || typeof node !== "object") return
|
|
166
|
+
if (Array.isArray(node)) {
|
|
167
|
+
for (const child of node) walk(child)
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
if (node.type === "TSTypeReference") {
|
|
171
|
+
checkTypeRef(context, node)
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
for (const key of Object.keys(node)) {
|
|
175
|
+
if (key === "parent") continue
|
|
176
|
+
walk(node[key])
|
|
177
|
+
}
|
|
178
|
+
}
|
|
162
179
|
return {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
for (const stmt of node.body) {
|
|
167
|
-
if (!seenFunction && isFunction(stmt)) {
|
|
168
|
-
seenFunction = true
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (seenFunction && stmt.type === "ExportDefaultDeclaration") {
|
|
172
|
-
context.report({
|
|
173
|
-
node: stmt,
|
|
174
|
-
messageId: "defaultAfterFunction",
|
|
175
|
-
})
|
|
176
|
-
}
|
|
177
|
-
}
|
|
180
|
+
TSTypeAliasDeclaration(node) {
|
|
181
|
+
walk(node.typeAnnotation)
|
|
178
182
|
},
|
|
179
183
|
}
|
|
180
184
|
},
|
|
@@ -579,6 +583,37 @@ export default {
|
|
|
579
583
|
},
|
|
580
584
|
}
|
|
581
585
|
|
|
586
|
+
function checkTypeRef(context, node) {
|
|
587
|
+
const typeName = node.typeName
|
|
588
|
+
if (typeName.type !== "TSQualifiedName") return
|
|
589
|
+
if (typeName.right.type !== "Identifier" || typeName.right.name !== "Type") return
|
|
590
|
+
|
|
591
|
+
const mid = typeName.left
|
|
592
|
+
if (mid.type !== "TSQualifiedName") return
|
|
593
|
+
if (mid.right.type !== "Identifier" || mid.right.name !== "Schema") return
|
|
594
|
+
if (mid.left.type !== "Identifier" || mid.left.name !== "Schema") return
|
|
595
|
+
|
|
596
|
+
const args = node.typeArguments
|
|
597
|
+
if (!args || args.params.length !== 1) return
|
|
598
|
+
|
|
599
|
+
const param = args.params[0]
|
|
600
|
+
if (param.type !== "TSTypeQuery") return
|
|
601
|
+
|
|
602
|
+
const exprName = param.exprName
|
|
603
|
+
if (exprName.type !== "Identifier") return
|
|
604
|
+
|
|
605
|
+
const name = exprName.name
|
|
606
|
+
|
|
607
|
+
context.report({
|
|
608
|
+
node,
|
|
609
|
+
messageId: "preferTypeof",
|
|
610
|
+
data: { name },
|
|
611
|
+
fix(fixer) {
|
|
612
|
+
return fixer.replaceTextRange(node.range, "typeof " + name + ".Type")
|
|
613
|
+
},
|
|
614
|
+
})
|
|
615
|
+
}
|
|
616
|
+
|
|
582
617
|
function getBaseName(source) {
|
|
583
618
|
// Handle node: and bun: protocols
|
|
584
619
|
if (source.startsWith("node:")) {
|
package/src/sql/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import * as HashMap from "effect/HashMap"
|
|
|
5
5
|
import * as List from "effect/List"
|
|
6
6
|
import * as Logger from "effect/Logger"
|
|
7
7
|
import * as PubSub from "effect/PubSub"
|
|
8
|
+
import * as Pretty from "./_Pretty.ts"
|
|
8
9
|
import * as StudioStore from "./StudioStore.ts"
|
|
9
10
|
|
|
10
11
|
const studioLogger = Logger.make((options) => {
|
|
@@ -32,7 +33,7 @@ const studioLogger = Logger.make((options) => {
|
|
|
32
33
|
const log: StudioStore.StudioLog = {
|
|
33
34
|
id: StudioStore.nextLogId(),
|
|
34
35
|
level,
|
|
35
|
-
message:
|
|
36
|
+
message: Pretty.formatLogMessage(options.message),
|
|
36
37
|
fiberId: FiberId.threadName(options.fiberId),
|
|
37
38
|
cause: causeStr,
|
|
38
39
|
spans: spanNames,
|
|
@@ -32,6 +32,24 @@ export const nextSpanId = () => nextPackedId()
|
|
|
32
32
|
|
|
33
33
|
export const nextTraceId = () => nextPackedId()
|
|
34
34
|
|
|
35
|
+
export const studioTraceAttribute = "effect-start.studio.internal"
|
|
36
|
+
|
|
37
|
+
export function isStudioTrace(spans: Array<StudioSpan>): boolean {
|
|
38
|
+
return spans.some((span) => span.attributes[studioTraceAttribute] === true)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function filterOutStudioSpans(spans: Array<StudioSpan>): Array<StudioSpan> {
|
|
42
|
+
const hiddenTraceIds = new Set<bigint>()
|
|
43
|
+
|
|
44
|
+
for (const span of spans) {
|
|
45
|
+
if (span.attributes[studioTraceAttribute] === true) {
|
|
46
|
+
hiddenTraceIds.add(span.traceId)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return spans.filter((span) => !hiddenTraceIds.has(span.traceId))
|
|
51
|
+
}
|
|
52
|
+
|
|
35
53
|
export interface StudioSpan {
|
|
36
54
|
readonly spanId: bigint
|
|
37
55
|
readonly traceId: bigint
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
function jsonReplacer() {
|
|
2
|
+
const seen = new WeakSet<object>()
|
|
3
|
+
|
|
4
|
+
return (_key: string, value: unknown): unknown => {
|
|
5
|
+
if (typeof value === "bigint") return String(value)
|
|
6
|
+
if (value instanceof Error) {
|
|
7
|
+
return {
|
|
8
|
+
name: value.name,
|
|
9
|
+
message: value.message,
|
|
10
|
+
stack: value.stack,
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
if (value !== null && typeof value === "object") {
|
|
14
|
+
if (seen.has(value)) return "[Circular]"
|
|
15
|
+
seen.add(value)
|
|
16
|
+
}
|
|
17
|
+
return value
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function isStructuredValue(value: unknown): value is object {
|
|
22
|
+
return value !== null && typeof value === "object"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function prettyPrintJson(value: unknown): string {
|
|
26
|
+
try {
|
|
27
|
+
const json = JSON.stringify(value, jsonReplacer(), 2)
|
|
28
|
+
return json ?? String(value)
|
|
29
|
+
} catch {
|
|
30
|
+
return String(value)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function formatLogMessage(message: unknown): string {
|
|
35
|
+
if (!Array.isArray(message)) {
|
|
36
|
+
return isStructuredValue(message) ? prettyPrintJson(message) : String(message)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const lines: Array<string> = []
|
|
40
|
+
let inlineParts: Array<string> = []
|
|
41
|
+
|
|
42
|
+
for (const part of message) {
|
|
43
|
+
if (isStructuredValue(part)) {
|
|
44
|
+
if (inlineParts.length > 0) {
|
|
45
|
+
lines.push(inlineParts.join(" "))
|
|
46
|
+
inlineParts = []
|
|
47
|
+
}
|
|
48
|
+
lines.push(prettyPrintJson(part))
|
|
49
|
+
} else {
|
|
50
|
+
inlineParts.push(String(part))
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (inlineParts.length > 0) {
|
|
55
|
+
lines.push(inlineParts.join(" "))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return lines.join("\n")
|
|
59
|
+
}
|
|
@@ -261,21 +261,12 @@
|
|
|
261
261
|
}
|
|
262
262
|
.tl-row {
|
|
263
263
|
border-bottom: 1px solid #1e293b;
|
|
264
|
+
color: inherit;
|
|
265
|
+
text-decoration: none;
|
|
264
266
|
}
|
|
265
|
-
.tl-row
|
|
267
|
+
.tl-row:hover {
|
|
266
268
|
background: #111827;
|
|
267
269
|
}
|
|
268
|
-
.tl-summary {
|
|
269
|
-
cursor: pointer;
|
|
270
|
-
user-select: none;
|
|
271
|
-
list-style: none;
|
|
272
|
-
}
|
|
273
|
-
.tl-summary::-webkit-details-marker {
|
|
274
|
-
display: none;
|
|
275
|
-
}
|
|
276
|
-
.tl-summary:hover {
|
|
277
|
-
background: #1e293b;
|
|
278
|
-
}
|
|
279
270
|
.tl-cell {
|
|
280
271
|
padding: 6px 8px;
|
|
281
272
|
display: flex;
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect"
|
|
1
2
|
import * as BunRoute from "../../bun/BunRoute.ts"
|
|
2
3
|
import * as Route from "../../Route.ts"
|
|
4
|
+
import * as StudioStore from "../StudioStore.ts"
|
|
3
5
|
|
|
4
|
-
export default Route.use(
|
|
6
|
+
export default Route.use(
|
|
7
|
+
Route.filter(function* () {
|
|
8
|
+
yield* Effect.annotateCurrentSpan(StudioStore.studioTraceAttribute, true)
|
|
9
|
+
return { context: {} }
|
|
10
|
+
}),
|
|
11
|
+
BunRoute.htmlBundle(() => import("./layout.html")),
|
|
12
|
+
)
|
|
@@ -12,7 +12,7 @@ export default Route.get(
|
|
|
12
12
|
Route.html(function* (ctx) {
|
|
13
13
|
const url = new URL(ctx.request.url)
|
|
14
14
|
const search = url.searchParams.get("traceSearch") || ""
|
|
15
|
-
const allSpans = yield* StudioStore.allSpans()
|
|
15
|
+
const allSpans = StudioStore.filterOutStudioSpans(yield* StudioStore.allSpans())
|
|
16
16
|
const names = Array.from(new Set(allSpans.map((s) => s.name))).sort()
|
|
17
17
|
let spans = allSpans
|
|
18
18
|
if (search) {
|
|
@@ -56,6 +56,9 @@ export default Route.get(
|
|
|
56
56
|
Stream.mapEffect((e) =>
|
|
57
57
|
Effect.gen(function* () {
|
|
58
58
|
const traceSpans = yield* StudioStore.spansByTraceId(e.traceId)
|
|
59
|
+
if (StudioStore.isStudioTrace(traceSpans)) {
|
|
60
|
+
return undefined
|
|
61
|
+
}
|
|
59
62
|
const traceHtml = Html.renderToString(
|
|
60
63
|
<Traces.TraceGroup id={e.traceId} spans={traceSpans} />,
|
|
61
64
|
)
|
|
@@ -66,6 +69,7 @@ export default Route.get(
|
|
|
66
69
|
}
|
|
67
70
|
}),
|
|
68
71
|
),
|
|
72
|
+
Stream.filter((event): event is { event: string; data: string } => event !== undefined),
|
|
69
73
|
),
|
|
70
74
|
),
|
|
71
75
|
)
|
package/src/studio/ui/Errors.tsx
CHANGED
|
@@ -31,7 +31,7 @@ export function ErrorLine(options: { error: StudioStore.StudioError }) {
|
|
|
31
31
|
<span style="color:#64748b">tag </span>
|
|
32
32
|
<span
|
|
33
33
|
style="color:#fca5a5;text-decoration:underline;cursor:copy"
|
|
34
|
-
data-on:click={`(e) => { e.signals.errorTag
|
|
34
|
+
data-on:click={`(e) => { e.signals.errorTag = '${t}'; e.actions.get(location.href, { contentType: 'form' }) }`}
|
|
35
35
|
>
|
|
36
36
|
{t}
|
|
37
37
|
</span>
|
package/src/studio/ui/Fibers.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as Unique from "../../Unique.ts"
|
|
2
2
|
import * as StudioStore from "../StudioStore.ts"
|
|
3
3
|
import * as Logs from "./Logs.tsx"
|
|
4
|
+
import * as PrettyValue from "./_PrettyValue.tsx"
|
|
4
5
|
|
|
5
6
|
function formatDuration(ms: number | undefined): string {
|
|
6
7
|
if (ms == null) return "..."
|
|
@@ -9,14 +10,20 @@ function formatDuration(ms: number | undefined): string {
|
|
|
9
10
|
return `${(ms / 1000).toFixed(2)}s`
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
function KeyValue(options: { label: string; value:
|
|
13
|
+
function KeyValue(options: { label: string; value: unknown }) {
|
|
13
14
|
if (options.value == null) return null
|
|
14
15
|
return (
|
|
15
|
-
<div
|
|
16
|
+
<div
|
|
17
|
+
style="display:flex;align-items:flex-start;gap:8px;padding:4px 0;border-bottom:1px solid #1e293b;font-size:12px"
|
|
18
|
+
>
|
|
16
19
|
<span style="color:#64748b;min-width:120px">{options.label}</span>
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
<div style="flex:1;min-width:0">
|
|
21
|
+
<PrettyValue.PrettyValue
|
|
22
|
+
value={options.value}
|
|
23
|
+
style="color:#e2e8f0;font-family:monospace;word-break:break-all"
|
|
24
|
+
preStyle="color:#e2e8f0;font-family:monospace;word-break:break-all;white-space:pre-wrap;margin:0"
|
|
25
|
+
/>
|
|
26
|
+
</div>
|
|
20
27
|
</div>
|
|
21
28
|
)
|
|
22
29
|
}
|
|
@@ -276,10 +283,7 @@ export function FiberDetail(options: {
|
|
|
276
283
|
</div>
|
|
277
284
|
)}
|
|
278
285
|
{Object.entries(options.context.annotations).map(([k, v]) => (
|
|
279
|
-
<KeyValue
|
|
280
|
-
label={k}
|
|
281
|
-
value={typeof v === "object" ? JSON.stringify(v) : String(v)}
|
|
282
|
-
/>
|
|
286
|
+
<KeyValue label={k} value={v} />
|
|
283
287
|
))}
|
|
284
288
|
</div>
|
|
285
289
|
</div>
|
|
@@ -310,7 +314,7 @@ export function FiberDetail(options: {
|
|
|
310
314
|
{Object.entries(s.attributes)
|
|
311
315
|
.filter(([k]) => k !== "code.stacktrace")
|
|
312
316
|
.map(([k, v]) => (
|
|
313
|
-
<KeyValue label={k} value={
|
|
317
|
+
<KeyValue label={k} value={v} />
|
|
314
318
|
))}
|
|
315
319
|
</div>
|
|
316
320
|
)
|
package/src/studio/ui/Logs.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as Unique from "../../Unique.ts"
|
|
2
2
|
import * as StudioStore from "../StudioStore.ts"
|
|
3
|
+
import * as PrettyValue from "./_PrettyValue.tsx"
|
|
3
4
|
|
|
4
5
|
function levelColor(level: string): string {
|
|
5
6
|
if (level === "DEBUG") return "#94a3b8"
|
|
@@ -25,26 +26,30 @@ export function LogLine(options: { log: StudioStore.StudioLog }) {
|
|
|
25
26
|
return (
|
|
26
27
|
<div
|
|
27
28
|
id={`log-${options.log.id}`}
|
|
28
|
-
style="padding:
|
|
29
|
+
style="padding:6px 8px;border-bottom:1px solid #1f2937;font-family:monospace;font-size:12px;display:flex;align-items:flex-start;gap:8px"
|
|
29
30
|
>
|
|
30
31
|
<span style="color:#6b7280;white-space:nowrap">{time}</span>
|
|
31
32
|
<span style={`color:${color};font-weight:600;width:56px;text-align:center;flex-shrink:0`}>
|
|
32
33
|
{options.log.level}
|
|
33
34
|
</span>
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:4px">
|
|
36
|
+
<PrettyValue.PreformattedText
|
|
37
|
+
text={options.log.message}
|
|
38
|
+
style="color:#e5e7eb;margin:0;white-space:pre-wrap;word-break:break-word;font:inherit"
|
|
39
|
+
/>
|
|
40
|
+
{options.log.cause && (
|
|
41
|
+
<PrettyValue.PreformattedText
|
|
42
|
+
text={options.log.cause}
|
|
43
|
+
style="color:#ef4444;font-size:11px;margin:0;white-space:pre-wrap;word-break:break-word;font:inherit"
|
|
44
|
+
/>
|
|
45
|
+
)}
|
|
46
|
+
</div>
|
|
37
47
|
<a
|
|
38
48
|
href={`${StudioStore.store.prefix}/fibers/${options.log.fiberId.replace("#", "")}`}
|
|
39
|
-
style="color:#6b7280;white-space:nowrap;
|
|
49
|
+
style="color:#6b7280;white-space:nowrap;text-decoration:none;flex-shrink:0"
|
|
40
50
|
>
|
|
41
51
|
{options.log.fiberId}
|
|
42
52
|
</a>
|
|
43
|
-
{options.log.cause && (
|
|
44
|
-
<div style="color:#ef4444;font-size:11px;padding:2px 0 0 0;white-space:pre-wrap;width:100%">
|
|
45
|
-
{options.log.cause}
|
|
46
|
-
</div>
|
|
47
|
-
)}
|
|
48
53
|
</div>
|
|
49
54
|
)
|
|
50
55
|
}
|