effect-start 0.14.0 → 0.16.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.
Files changed (87) hide show
  1. package/package.json +8 -9
  2. package/src/Commander.test.ts +507 -245
  3. package/src/ContentNegotiation.test.ts +603 -0
  4. package/src/ContentNegotiation.ts +542 -0
  5. package/src/Entity.test.ts +592 -0
  6. package/src/Entity.ts +362 -0
  7. package/src/FileRouter.ts +16 -12
  8. package/src/{FileRouterCodegen.test.ts → FileRouterCodegen.todo.ts} +384 -219
  9. package/src/FileRouterCodegen.ts +6 -6
  10. package/src/FileRouterPattern.test.ts +93 -62
  11. package/src/FileRouter_files.test.ts +5 -5
  12. package/src/FileRouter_path.test.ts +121 -69
  13. package/src/FileRouter_tree.test.ts +62 -56
  14. package/src/FileSystemExtra.test.ts +46 -30
  15. package/src/Http.test.ts +319 -0
  16. package/src/Http.ts +167 -0
  17. package/src/HttpAppExtra.test.ts +39 -20
  18. package/src/HttpAppExtra.ts +0 -1
  19. package/src/HttpUtils.test.ts +35 -18
  20. package/src/HttpUtils.ts +2 -0
  21. package/src/PathPattern.test.ts +648 -0
  22. package/src/PathPattern.ts +485 -0
  23. package/src/Route.ts +266 -1069
  24. package/src/RouteBody.test.ts +234 -0
  25. package/src/RouteBody.ts +193 -0
  26. package/src/RouteHook.test.ts +40 -0
  27. package/src/RouteHook.ts +106 -0
  28. package/src/RouteHttp.test.ts +2906 -0
  29. package/src/RouteHttp.ts +427 -0
  30. package/src/RouteHttpTracer.ts +92 -0
  31. package/src/RouteMount.test.ts +481 -0
  32. package/src/RouteMount.ts +470 -0
  33. package/src/RouteSchema.test.ts +427 -0
  34. package/src/RouteSchema.ts +423 -0
  35. package/src/RouteTree.test.ts +494 -0
  36. package/src/RouteTree.ts +219 -0
  37. package/src/RouteTrie.test.ts +322 -0
  38. package/src/RouteTrie.ts +224 -0
  39. package/src/RouterPattern.test.ts +569 -548
  40. package/src/RouterPattern.ts +7 -7
  41. package/src/Start.ts +3 -3
  42. package/src/StreamExtra.ts +21 -1
  43. package/src/TuplePathPattern.ts +64 -0
  44. package/src/Values.test.ts +263 -0
  45. package/src/Values.ts +76 -0
  46. package/src/bun/BunBundle.test.ts +36 -42
  47. package/src/bun/BunBundle.ts +2 -2
  48. package/src/bun/BunBundle_imports.test.ts +4 -6
  49. package/src/bun/BunHttpServer.test.ts +183 -6
  50. package/src/bun/BunHttpServer.ts +72 -32
  51. package/src/bun/BunHttpServer_web.ts +18 -6
  52. package/src/bun/BunImportTrackerPlugin.test.ts +3 -3
  53. package/src/bun/BunRoute.test.ts +124 -442
  54. package/src/bun/BunRoute.ts +146 -286
  55. package/src/{BundleHttp.test.ts → bundler/BundleHttp.test.ts} +34 -60
  56. package/src/{BundleHttp.ts → bundler/BundleHttp.ts} +1 -2
  57. package/src/client/index.ts +1 -1
  58. package/src/{Effect_HttpRouter.test.ts → effect/HttpRouter.test.ts} +69 -90
  59. package/src/experimental/EncryptedCookies.test.ts +125 -64
  60. package/src/experimental/SseHttpResponse.ts +0 -1
  61. package/src/hyper/Hyper.ts +89 -0
  62. package/src/{HyperHtml.test.ts → hyper/HyperHtml.test.ts} +13 -13
  63. package/src/{HyperHtml.ts → hyper/HyperHtml.ts} +2 -2
  64. package/src/{jsx.d.ts → hyper/jsx.d.ts} +1 -1
  65. package/src/index.ts +3 -4
  66. package/src/middlewares/BasicAuthMiddleware.test.ts +29 -19
  67. package/src/{NodeFileSystem.ts → node/FileSystem.ts} +6 -2
  68. package/src/testing/TestHttpClient.test.ts +26 -26
  69. package/src/testing/TestLogger.test.ts +27 -14
  70. package/src/testing/TestLogger.ts +15 -9
  71. package/src/x/datastar/Datastar.test.ts +47 -48
  72. package/src/x/datastar/Datastar.ts +1 -1
  73. package/src/x/tailwind/TailwindPlugin.test.ts +56 -58
  74. package/src/x/tailwind/plugin.ts +1 -1
  75. package/src/FileHttpRouter.test.ts +0 -239
  76. package/src/FileHttpRouter.ts +0 -194
  77. package/src/Hyper.ts +0 -194
  78. package/src/Route.test.ts +0 -1370
  79. package/src/RouteRender.ts +0 -40
  80. package/src/Router.test.ts +0 -375
  81. package/src/Router.ts +0 -255
  82. package/src/bun/BunRoute_bundles.test.ts +0 -219
  83. /package/src/{Bundle.ts → bundler/Bundle.ts} +0 -0
  84. /package/src/{BundleFiles.ts → bundler/BundleFiles.ts} +0 -0
  85. /package/src/{HyperNode.ts → hyper/HyperNode.ts} +0 -0
  86. /package/src/{jsx-runtime.ts → hyper/jsx-runtime.ts} +0 -0
  87. /package/src/{NodeUtils.ts → node/Utils.ts} +0 -0
@@ -1,10 +1,6 @@
1
1
  import * as HttpServerRequest from "@effect/platform/HttpServerRequest"
2
2
  import * as HttpServerResponse from "@effect/platform/HttpServerResponse"
3
- import {
4
- describe,
5
- expect,
6
- it,
7
- } from "bun:test"
3
+ import * as test from "bun:test"
8
4
  import * as Effect from "effect/Effect"
9
5
  import * as BasicAuthMiddleware from "./BasicAuthMiddleware.js"
10
6
 
@@ -36,39 +32,53 @@ const runWithAuth = (authHeader: string | undefined) => {
36
32
  )
37
33
  }
38
34
 
39
- describe("BasicAuthMiddleware", () => {
40
- it("returns 401 when no authorization header is present", async () => {
35
+ test.describe("BasicAuthMiddleware", () => {
36
+ test.it("returns 401 when no authorization header is present", async () => {
41
37
  const response = await runWithAuth(undefined)
42
- expect(response.status).toBe(401)
43
- expect(response.headers["www-authenticate"]).toBe("Basic")
38
+ test
39
+ .expect(response.status)
40
+ .toBe(401)
41
+ test
42
+ .expect(response.headers["www-authenticate"])
43
+ .toBe("Basic")
44
44
  })
45
45
 
46
- it("returns 401 when authorization header does not start with Basic", async () => {
46
+ test.it("returns 401 when authorization header does not start with Basic", async () => {
47
47
  const response = await runWithAuth("Bearer token")
48
- expect(response.status).toBe(401)
48
+ test
49
+ .expect(response.status)
50
+ .toBe(401)
49
51
  })
50
52
 
51
- it("returns 401 when credentials are invalid", async () => {
53
+ test.it("returns 401 when credentials are invalid", async () => {
52
54
  const invalidCredentials = btoa("wrong:credentials")
53
55
  const response = await runWithAuth(`Basic ${invalidCredentials}`)
54
- expect(response.status).toBe(401)
56
+ test
57
+ .expect(response.status)
58
+ .toBe(401)
55
59
  })
56
60
 
57
- it("returns 401 when username is wrong", async () => {
61
+ test.it("returns 401 when username is wrong", async () => {
58
62
  const invalidCredentials = btoa("wronguser:secret")
59
63
  const response = await runWithAuth(`Basic ${invalidCredentials}`)
60
- expect(response.status).toBe(401)
64
+ test
65
+ .expect(response.status)
66
+ .toBe(401)
61
67
  })
62
68
 
63
- it("returns 401 when password is wrong", async () => {
69
+ test.it("returns 401 when password is wrong", async () => {
64
70
  const invalidCredentials = btoa("admin:wrongpassword")
65
71
  const response = await runWithAuth(`Basic ${invalidCredentials}`)
66
- expect(response.status).toBe(401)
72
+ test
73
+ .expect(response.status)
74
+ .toBe(401)
67
75
  })
68
76
 
69
- it("passes through to app when credentials are valid", async () => {
77
+ test.it("passes through to app when credentials are valid", async () => {
70
78
  const validCredentials = btoa("admin:secret")
71
79
  const response = await runWithAuth(`Basic ${validCredentials}`)
72
- expect(response.status).toBe(200)
80
+ test
81
+ .expect(response.status)
82
+ .toBe(200)
73
83
  })
74
84
  })
@@ -243,15 +243,19 @@ const makeFile = (() => {
243
243
 
244
244
  class FileImpl implements FileSystem.File {
245
245
  readonly [FileSystem.FileTypeId]: FileSystem.FileTypeId
246
+ readonly fd: FileSystem.File.Descriptor
247
+ private readonly append: boolean
246
248
 
247
249
  private readonly semaphore = Effect.unsafeMakeSemaphore(1)
248
250
  private position: bigint = 0n
249
251
 
250
252
  constructor(
251
- readonly fd: FileSystem.File.Descriptor,
252
- private readonly append: boolean,
253
+ fd: FileSystem.File.Descriptor,
254
+ append: boolean,
253
255
  ) {
254
256
  this[FileSystem.FileTypeId] = FileSystem.FileTypeId
257
+ this.fd = fd
258
+ this.append = append
255
259
  }
256
260
 
257
261
  get stat() {
@@ -1,6 +1,6 @@
1
1
  import * as HttpServerRequest from "@effect/platform/HttpServerRequest"
2
2
  import * as HttpServerResponse from "@effect/platform/HttpServerResponse"
3
- import * as t from "bun:test"
3
+ import * as test from "bun:test"
4
4
  import * as Effect from "effect/Effect"
5
5
  import { effectFn } from "./index.ts"
6
6
  import * as TestHttpClient from "./TestHttpClient.ts"
@@ -21,49 +21,45 @@ const AppClient = TestHttpClient.make(App)
21
21
 
22
22
  const effect = effectFn()
23
23
 
24
- t.it("ok", () =>
24
+ test.it("ok", () =>
25
25
  effect(function*() {
26
26
  const res = yield* AppClient.get("/")
27
27
 
28
- t
29
- .expect(
30
- res.status,
31
- )
28
+ test
29
+ .expect(res.status)
32
30
  .toEqual(200)
33
- t
34
- .expect(
35
- yield* res.text,
36
- )
31
+ test
32
+ .expect(yield* res.text)
37
33
  .toEqual("Hello, World!")
38
34
  }))
39
35
 
40
- t.it("not found", () =>
36
+ test.it("not found", () =>
41
37
  effect(function*() {
42
38
  const res = yield* AppClient.get("/nope")
43
39
 
44
- t
45
- .expect(
46
- res.status,
47
- )
40
+ test
41
+ .expect(res.status)
48
42
  .toEqual(404)
49
- t
50
- .expect(
51
- yield* res.text,
52
- )
43
+ test
44
+ .expect(yield* res.text)
53
45
  .toEqual("Not Found")
54
46
  }))
55
47
 
56
- t.describe("FetchHandler", () => {
48
+ test.describe("FetchHandler", () => {
57
49
  const FetchClient = TestHttpClient.make((req) =>
58
50
  new Response(`Hello from ${req.url}`, { status: 200 })
59
51
  )
60
52
 
61
- t.it("works with sync handler", () =>
53
+ test.it("works with sync handler", () =>
62
54
  effect(function*() {
63
55
  const res = yield* FetchClient.get("/test")
64
56
 
65
- t.expect(res.status).toEqual(200)
66
- t.expect(yield* res.text).toContain("/test")
57
+ test
58
+ .expect(res.status)
59
+ .toEqual(200)
60
+ test
61
+ .expect(yield* res.text)
62
+ .toContain("/test")
67
63
  }))
68
64
 
69
65
  const AsyncFetchClient = TestHttpClient.make(async (req) => {
@@ -73,11 +69,15 @@ t.describe("FetchHandler", () => {
73
69
  })
74
70
  })
75
71
 
76
- t.it("works with async handler", () =>
72
+ test.it("works with async handler", () =>
77
73
  effect(function*() {
78
74
  const res = yield* AsyncFetchClient.post("/async-path")
79
75
 
80
- t.expect(res.status).toEqual(201)
81
- t.expect(yield* res.text).toEqual("Async: POST /async-path")
76
+ test
77
+ .expect(res.status)
78
+ .toEqual(201)
79
+ test
80
+ .expect(yield* res.text)
81
+ .toEqual("Async: POST /async-path")
82
82
  }))
83
83
  })
@@ -1,38 +1,51 @@
1
- import * as t from "bun:test"
1
+ import * as test from "bun:test"
2
2
  import * as Effect from "effect/Effect"
3
- import * as Logger from "effect/Logger"
4
3
  import * as Ref from "effect/Ref"
5
4
  import * as TestLogger from "./TestLogger.ts"
6
5
 
7
- t.it("TestLogger captures log messages", () =>
6
+ test.it("TestLogger captures log messages", () =>
8
7
  Effect
9
8
  .gen(function*() {
10
9
  const logger = yield* TestLogger.TestLogger
11
10
 
12
- // Log some messages
13
11
  yield* Effect.logError("This is an error")
14
12
  yield* Effect.logWarning("This is a warning")
15
13
  yield* Effect.logInfo("This is info")
16
14
 
17
- // Read captured messages
18
15
  const messages = yield* Ref.get(logger.messages)
19
16
 
20
- t.expect(messages).toHaveLength(3)
21
- t.expect(messages[0]).toContain("[Error]")
22
- t.expect(messages[0]).toContain("This is an error")
23
- t.expect(messages[1]).toContain("[Warning]")
24
- t.expect(messages[1]).toContain("This is a warning")
25
- t.expect(messages[2]).toContain("[Info]")
26
- t.expect(messages[2]).toContain("This is info")
17
+ test
18
+ .expect(messages)
19
+ .toHaveLength(3)
20
+ test
21
+ .expect(messages[0])
22
+ .toContain("[Error]")
23
+ test
24
+ .expect(messages[0])
25
+ .toContain("This is an error")
26
+ test
27
+ .expect(messages[1])
28
+ .toContain("[Warning]")
29
+ test
30
+ .expect(messages[1])
31
+ .toContain("This is a warning")
32
+ test
33
+ .expect(messages[2])
34
+ .toContain("[Info]")
35
+ test
36
+ .expect(messages[2])
37
+ .toContain("This is info")
27
38
  })
28
39
  .pipe(Effect.provide(TestLogger.layer()), Effect.runPromise))
29
40
 
30
- t.it("TestLogger starts with empty messages", () =>
41
+ test.it("TestLogger starts with empty messages", () =>
31
42
  Effect
32
43
  .gen(function*() {
33
44
  const logger = yield* TestLogger.TestLogger
34
45
  const messages = yield* Ref.get(logger.messages)
35
46
 
36
- t.expect(messages).toHaveLength(0)
47
+ test
48
+ .expect(messages)
49
+ .toHaveLength(0)
37
50
  })
38
51
  .pipe(Effect.provide(TestLogger.layer()), Effect.runPromise))
@@ -1,9 +1,11 @@
1
+ import * as Cause from "effect/Cause"
1
2
  import * as Context from "effect/Context"
2
3
  import * as Effect from "effect/Effect"
3
4
  import * as FiberRef from "effect/FiberRef"
4
5
  import * as HashSet from "effect/HashSet"
5
6
  import * as Layer from "effect/Layer"
6
7
  import * as Logger from "effect/Logger"
8
+ import * as MutableRef from "effect/MutableRef"
7
9
  import * as Ref from "effect/Ref"
8
10
 
9
11
  export type TestLoggerContext = {
@@ -20,13 +22,19 @@ export function layer(): Layer.Layer<TestLogger> {
20
22
  TestLogger,
21
23
  Effect.gen(function*() {
22
24
  const messages = yield* Ref.make<Array<string>>([])
25
+ const mutableRef = (messages as any).ref as MutableRef.MutableRef<
26
+ Array<string>
27
+ >
23
28
 
24
- const customLogger = Logger.make(({ message, logLevel }) => {
25
- Effect.runSync(
26
- Ref.update(
27
- messages,
28
- (msgs) => [...msgs, `[${logLevel._tag}] ${String(message)}`],
29
- ),
29
+ const customLogger = Logger.make(({ message, logLevel, cause }) => {
30
+ const causeStr = !Cause.isEmpty(cause)
31
+ ? ` ${Cause.pretty(cause)}`
32
+ : ""
33
+ MutableRef.update(
34
+ mutableRef,
35
+ (
36
+ msgs,
37
+ ) => [...msgs, `[${logLevel._tag}] ${String(message)}${causeStr}`],
30
38
  )
31
39
  })
32
40
 
@@ -39,9 +47,7 @@ export function layer(): Layer.Layer<TestLogger> {
39
47
  ),
40
48
  )
41
49
 
42
- return {
43
- messages,
44
- }
50
+ return { messages }
45
51
  }),
46
52
  )
47
53
  }
@@ -1,50 +1,50 @@
1
- import * as t from "bun:test"
2
- import * as HyperHtml from "../../HyperHtml.ts"
3
- import * as HyperNode from "../../HyperNode.ts"
4
- import { jsx } from "../../jsx-runtime.ts"
1
+ import * as test from "bun:test"
2
+ import * as HyperHtml from "../../hyper/HyperHtml.ts"
3
+ import * as HyperNode from "../../hyper/HyperNode.ts"
4
+ import { jsx } from "../../hyper/jsx-runtime.ts"
5
5
  import * as Datastar from "./Datastar.ts"
6
6
 
7
- t.it("data-signals object serialization", () => {
7
+ test.it("data-signals object serialization", () => {
8
8
  const node = HyperNode.make("div", {
9
9
  "data-signals": { foo: 1, bar: { baz: "hello" } } as any,
10
10
  })
11
11
 
12
12
  const html = HyperHtml.renderToString(node, Datastar.HyperHooks)
13
13
 
14
- t
14
+ test
15
15
  .expect(html)
16
16
  .toBe(
17
17
  "<div data-signals=\"{&quot;foo&quot;:1,&quot;bar&quot;:{&quot;baz&quot;:&quot;hello&quot;}}\"></div>",
18
18
  )
19
19
  })
20
20
 
21
- t.it("data-signals string passthrough", () => {
21
+ test.it("data-signals string passthrough", () => {
22
22
  const node = HyperNode.make("div", {
23
23
  "data-signals": "$mySignal",
24
24
  })
25
25
 
26
26
  const html = HyperHtml.renderToString(node, Datastar.HyperHooks)
27
27
 
28
- t
28
+ test
29
29
  .expect(html)
30
30
  .toBe("<div data-signals=\"$mySignal\"></div>")
31
31
  })
32
32
 
33
- t.it("data-signals-* object serialization", () => {
33
+ test.it("data-signals-* object serialization", () => {
34
34
  const node = HyperNode.make("div", {
35
35
  "data-signals-user": { name: "John", age: 30 } as any,
36
36
  })
37
37
 
38
38
  const html = HyperHtml.renderToString(node, Datastar.HyperHooks)
39
39
 
40
- t
40
+ test
41
41
  .expect(html)
42
42
  .toBe(
43
43
  "<div data-signals-user=\"{&quot;name&quot;:&quot;John&quot;,&quot;age&quot;:30}\"></div>",
44
44
  )
45
45
  })
46
46
 
47
- t.it("non-data attributes unchanged", () => {
47
+ test.it("non-data attributes unchanged", () => {
48
48
  const node = HyperNode.make("div", {
49
49
  id: "test",
50
50
  class: "my-class",
@@ -54,21 +54,21 @@ t.it("non-data attributes unchanged", () => {
54
54
 
55
55
  const html = HyperHtml.renderToString(node, Datastar.HyperHooks)
56
56
 
57
- t
57
+ test
58
58
  .expect(html)
59
59
  .toContain("id=\"test\"")
60
- t
60
+ test
61
61
  .expect(html)
62
62
  .toContain("class=\"my-class\"")
63
- t
63
+ test
64
64
  .expect(html)
65
65
  .toContain("data-text=\"$count\"")
66
- t
66
+ test
67
67
  .expect(html)
68
68
  .toContain("data-signals=\"{&quot;count&quot;:0}\"")
69
69
  })
70
70
 
71
- t.it("null and undefined values ignored", () => {
71
+ test.it("null and undefined values ignored", () => {
72
72
  const node = HyperNode.make("div", {
73
73
  "data-signals": null,
74
74
  "data-other": undefined,
@@ -76,12 +76,12 @@ t.it("null and undefined values ignored", () => {
76
76
 
77
77
  const html = HyperHtml.renderToString(node, Datastar.HyperHooks)
78
78
 
79
- t
79
+ test
80
80
  .expect(html)
81
81
  .toBe("<div></div>")
82
82
  })
83
83
 
84
- t.it("complex nested objects serialization", () => {
84
+ test.it("complex nested objects serialization", () => {
85
85
  const complexObject = {
86
86
  user: { name: "John Doe", preferences: { theme: "dark" } },
87
87
  items: [1, 2, 3],
@@ -93,15 +93,15 @@ t.it("complex nested objects serialization", () => {
93
93
 
94
94
  const html = HyperHtml.renderToString(node, Datastar.HyperHooks)
95
95
 
96
- t
96
+ test
97
97
  .expect(html)
98
98
  .toContain("data-signals=")
99
- t
99
+ test
100
100
  .expect(html)
101
101
  .toContain("John Doe")
102
102
  })
103
103
 
104
- t.it("non-signals data attributes serialized", () => {
104
+ test.it("non-signals data attributes serialized", () => {
105
105
  const node = HyperNode.make("div", {
106
106
  "data-class": { hidden: true, visible: false } as any,
107
107
  "data-style": { color: "red", display: "none" } as any,
@@ -111,39 +111,39 @@ t.it("non-signals data attributes serialized", () => {
111
111
 
112
112
  const html = HyperHtml.renderToString(node, Datastar.HyperHooks)
113
113
 
114
- t
114
+ test
115
115
  .expect(html)
116
116
  .toContain(
117
117
  "data-class=\"{&quot;hidden&quot;:true,&quot;visible&quot;:false}\"",
118
118
  )
119
- t
119
+ test
120
120
  .expect(html)
121
121
  .toContain(
122
122
  "data-style=\"{&quot;color&quot;:&quot;red&quot;,&quot;display&quot;:&quot;none&quot;}\"",
123
123
  )
124
- t
124
+ test
125
125
  .expect(html)
126
126
  .toContain("data-show=\"true\"")
127
- t
127
+ test
128
128
  .expect(html)
129
129
  .toContain("data-text=\"$count\"")
130
130
  })
131
131
 
132
- t.it("data-attr object serialization", () => {
132
+ test.it("data-attr object serialization", () => {
133
133
  const node = HyperNode.make("div", {
134
134
  "data-attr": { disabled: true, tabindex: 0 } as any,
135
135
  })
136
136
 
137
137
  const html = HyperHtml.renderToString(node, Datastar.HyperHooks)
138
138
 
139
- t
139
+ test
140
140
  .expect(html)
141
141
  .toBe(
142
142
  "<div data-attr=\"{&quot;disabled&quot;:true,&quot;tabindex&quot;:0}\"></div>",
143
143
  )
144
144
  })
145
145
 
146
- t.it("boolean attributes converted to strings", () => {
146
+ test.it("boolean attributes converted to strings", () => {
147
147
  const node = HyperNode.make("div", {
148
148
  "data-ignore": false as any,
149
149
  "data-ignore-morph": true as any,
@@ -151,20 +151,20 @@ t.it("boolean attributes converted to strings", () => {
151
151
 
152
152
  const html = HyperHtml.renderToString(node, Datastar.HyperHooks)
153
153
 
154
- t
154
+ test
155
155
  .expect(html)
156
156
  .not
157
157
  .toContain("data-ignore=\"")
158
- t
158
+ test
159
159
  .expect(html)
160
160
  .toContain("data-ignore-morph")
161
- t
161
+ test
162
162
  .expect(html)
163
163
  .not
164
164
  .toContain("data-ignore-morph=")
165
165
  })
166
166
 
167
- t.it("data-ignore attributes only present when true", () => {
167
+ test.it("data-ignore attributes only present when true", () => {
168
168
  const nodeTrue = HyperNode.make("div", {
169
169
  "data-ignore": true as any,
170
170
  })
@@ -176,20 +176,20 @@ t.it("data-ignore attributes only present when true", () => {
176
176
  const htmlTrue = HyperHtml.renderToString(nodeTrue, Datastar.HyperHooks)
177
177
  const htmlFalse = HyperHtml.renderToString(nodeFalse, Datastar.HyperHooks)
178
178
 
179
- t
179
+ test
180
180
  .expect(htmlTrue)
181
181
  .toContain("data-ignore")
182
- t
182
+ test
183
183
  .expect(htmlTrue)
184
184
  .not
185
185
  .toContain("data-ignore=")
186
- t
186
+ test
187
187
  .expect(htmlFalse)
188
188
  .not
189
189
  .toContain("data-ignore")
190
190
  })
191
191
 
192
- t.it("dynamic attributes with suffixes", () => {
192
+ test.it("dynamic attributes with suffixes", () => {
193
193
  const node = HyperNode.make("div", {
194
194
  "data-class-active": "hidden" as any,
195
195
  "data-attr-tabindex": "5" as any,
@@ -198,18 +198,18 @@ t.it("dynamic attributes with suffixes", () => {
198
198
 
199
199
  const html = HyperHtml.renderToString(node, Datastar.HyperHooks)
200
200
 
201
- t
201
+ test
202
202
  .expect(html)
203
203
  .toContain("data-class-active=\"hidden\"")
204
- t
204
+ test
205
205
  .expect(html)
206
206
  .toContain("data-attr-tabindex=\"5\"")
207
- t
207
+ test
208
208
  .expect(html)
209
209
  .toContain("data-style-opacity=\"0.5\"")
210
210
  })
211
211
 
212
- t.it("JSX with data-signals object", () => {
212
+ test.it("JSX with data-signals object", () => {
213
213
  const node = jsx("div", {
214
214
  "data-signals": { isOpen: false, count: 42 } as any,
215
215
  children: "content",
@@ -217,18 +217,18 @@ t.it("JSX with data-signals object", () => {
217
217
 
218
218
  const html = HyperHtml.renderToString(node, Datastar.HyperHooks)
219
219
 
220
- t
220
+ test
221
221
  .expect(html)
222
222
  .toBe(
223
223
  "<div data-signals=\"{&quot;isOpen&quot;:false,&quot;count&quot;:42}\">content</div>",
224
224
  )
225
- t
225
+ test
226
226
  .expect(html)
227
227
  .not
228
228
  .toContain("[object Object]")
229
229
  })
230
230
 
231
- t.it("JSX component returning element with data-signals", () => {
231
+ test.it("JSX component returning element with data-signals", () => {
232
232
  function TestComponent() {
233
233
  return jsx("div", {
234
234
  "data-signals": { isOpen: false } as any,
@@ -240,27 +240,26 @@ t.it("JSX component returning element with data-signals", () => {
240
240
 
241
241
  const html = HyperHtml.renderToString(node, Datastar.HyperHooks)
242
242
 
243
- t
243
+ test
244
244
  .expect(html)
245
245
  .toBe(
246
246
  "<div data-signals=\"{&quot;isOpen&quot;:false}\"><span>nested content</span></div>",
247
247
  )
248
- t
248
+ test
249
249
  .expect(html)
250
250
  .not
251
251
  .toContain("[object Object]")
252
252
  })
253
253
 
254
- t.it("debug hook execution", () => {
254
+ test.it("debug hook execution", () => {
255
255
  const node = jsx("div", {
256
256
  "data-signals": { isOpen: false, count: 42 } as any,
257
257
  children: "content",
258
258
  })
259
259
 
260
260
  const html = HyperHtml.renderToString(node, Datastar.HyperHooks)
261
- console.log("Final HTML:", html)
262
261
 
263
- t
262
+ test
264
263
  .expect(html)
265
264
  .not
266
265
  .toContain("[object Object]")
@@ -1,4 +1,4 @@
1
- import * as HyperNode from "../../HyperNode.ts"
1
+ import * as HyperNode from "../../hyper/HyperNode.ts"
2
2
 
3
3
  export const HyperHooks = {
4
4
  onNode,