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,11 +1,11 @@
1
1
  import * as Cookies from "@effect/platform/Cookies"
2
- import * as t from "bun:test"
2
+ import * as test from "bun:test"
3
3
  import * as ConfigProvider from "effect/ConfigProvider"
4
4
  import * as Effect from "effect/Effect"
5
5
  import * as EncryptedCookies from "./EncryptedCookies.ts"
6
6
 
7
- t.describe(`${EncryptedCookies.encrypt.name}`, () => {
8
- t.test("return encrypted string in correct format", async () => {
7
+ test.describe(`${EncryptedCookies.encrypt.name}`, () => {
8
+ test.test("return encrypted string in correct format", async () => {
9
9
  const value = "hello world"
10
10
 
11
11
  const result = await Effect.runPromise(
@@ -14,20 +14,28 @@ t.describe(`${EncryptedCookies.encrypt.name}`, () => {
14
14
 
15
15
  // Check format: three base64url segments separated by .
16
16
  const segments = result.split(".")
17
- t.expect(segments).toHaveLength(3)
17
+ test
18
+ .expect(segments)
19
+ .toHaveLength(3)
18
20
 
19
21
  // Each segment should be base64url (no +, /, or = characters
20
22
  // so cookie values are not escaped)
21
23
  segments.forEach((segment: string) => {
22
- t.expect(segment).not.toMatch(/[+/=]/)
24
+ test
25
+ .expect(segment)
26
+ .not
27
+ .toMatch(/[+/=]/)
23
28
  // Should be valid base64url that can be decoded
24
29
  const base64 = segment.replace(/-/g, "+").replace(/_/g, "/")
25
30
  const paddedBase64 = base64 + "=".repeat((4 - base64.length % 4) % 4)
26
- t.expect(() => atob(paddedBase64)).not.toThrow()
31
+ test
32
+ .expect(() => atob(paddedBase64))
33
+ .not
34
+ .toThrow()
27
35
  })
28
36
  })
29
37
 
30
- t.test("produce different results for same input due to random IV", async () => {
38
+ test.test("produce different results for same input due to random IV", async () => {
31
39
  const value = "same value"
32
40
 
33
41
  const result1 = await Effect.runPromise(
@@ -37,34 +45,45 @@ t.describe(`${EncryptedCookies.encrypt.name}`, () => {
37
45
  EncryptedCookies.encrypt(value, { secret: "test-secret" }),
38
46
  )
39
47
 
40
- t.expect(result1).not.toBe(result2)
48
+ test
49
+ .expect(result1)
50
+ .not
51
+ .toBe(result2)
41
52
 
42
53
  // But both should have correct format
43
- t.expect(result1.split(".")).toHaveLength(3)
44
- t.expect(result2.split(".")).toHaveLength(3)
54
+ test
55
+ .expect(result1.split("."))
56
+ .toHaveLength(3)
57
+ test
58
+ .expect(result2.split("."))
59
+ .toHaveLength(3)
45
60
  })
46
61
 
47
- t.test("handle empty string", async () => {
62
+ test.test("handle empty string", async () => {
48
63
  const value = ""
49
64
 
50
65
  const result = await Effect.runPromise(
51
66
  EncryptedCookies.encrypt(value, { secret: "test-secret" }),
52
67
  )
53
68
 
54
- t.expect(result.split(".")).toHaveLength(3)
69
+ test
70
+ .expect(result.split("."))
71
+ .toHaveLength(3)
55
72
  })
56
73
 
57
- t.test("handle special characters", async () => {
74
+ test.test("handle special characters", async () => {
58
75
  const value = "hello 世界! @#$%^&*()"
59
76
 
60
77
  const result = await Effect.runPromise(
61
78
  EncryptedCookies.encrypt(value, { secret: "test-secret" }),
62
79
  )
63
80
 
64
- t.expect(result.split(".")).toHaveLength(3)
81
+ test
82
+ .expect(result.split("."))
83
+ .toHaveLength(3)
65
84
  })
66
85
 
67
- t.test("handle object with undefined properties", async () => {
86
+ test.test("handle object with undefined properties", async () => {
68
87
  const value = { id: "some", optional: undefined }
69
88
 
70
89
  const encrypted = await Effect.runPromise(
@@ -75,12 +94,14 @@ t.describe(`${EncryptedCookies.encrypt.name}`, () => {
75
94
  )
76
95
 
77
96
  // JSON.stringify removes undefined properties
78
- t.expect(decrypted).toEqual({ id: "some" })
97
+ test
98
+ .expect(decrypted)
99
+ .toEqual({ id: "some" })
79
100
  })
80
101
  })
81
102
 
82
- t.describe(`${EncryptedCookies.decrypt.name}`, () => {
83
- t.test("decrypt encrypted string successfully", async () => {
103
+ test.describe(`${EncryptedCookies.decrypt.name}`, () => {
104
+ test.test("decrypt encrypted string successfully", async () => {
84
105
  const originalValue = "hello world"
85
106
 
86
107
  const encrypted = await Effect.runPromise(
@@ -90,10 +111,12 @@ t.describe(`${EncryptedCookies.decrypt.name}`, () => {
90
111
  EncryptedCookies.decrypt(encrypted, { secret: "test-secret" }),
91
112
  )
92
113
 
93
- t.expect(decrypted).toBe(originalValue)
114
+ test
115
+ .expect(decrypted)
116
+ .toBe(originalValue)
94
117
  })
95
118
 
96
- t.test("handle empty string round-trip", async () => {
119
+ test.test("handle empty string round-trip", async () => {
97
120
  const originalValue = ""
98
121
 
99
122
  const encrypted = await Effect.runPromise(
@@ -103,10 +126,12 @@ t.describe(`${EncryptedCookies.decrypt.name}`, () => {
103
126
  EncryptedCookies.decrypt(encrypted, { secret: "test-secret" }),
104
127
  )
105
128
 
106
- t.expect(decrypted).toBe(originalValue)
129
+ test
130
+ .expect(decrypted)
131
+ .toBe(originalValue)
107
132
  })
108
133
 
109
- t.test("handle special characters round-trip", async () => {
134
+ test.test("handle special characters round-trip", async () => {
110
135
  const originalValue = "hello 世界! @#$%^&*()"
111
136
 
112
137
  const encrypted = await Effect.runPromise(
@@ -116,13 +141,15 @@ t.describe(`${EncryptedCookies.decrypt.name}`, () => {
116
141
  EncryptedCookies.decrypt(encrypted, { secret: "test-secret" }),
117
142
  )
118
143
 
119
- t.expect(decrypted).toBe(originalValue)
144
+ test
145
+ .expect(decrypted)
146
+ .toBe(originalValue)
120
147
  })
121
148
 
122
- t.test("fail with invalid format", () => {
149
+ test.test("fail with invalid format", () => {
123
150
  const invalidValue = "not-encrypted"
124
151
 
125
- t
152
+ test
126
153
  .expect(
127
154
  Effect.runPromise(
128
155
  EncryptedCookies.decrypt(invalidValue, { secret: "test-secret" }),
@@ -132,10 +159,10 @@ t.describe(`${EncryptedCookies.decrypt.name}`, () => {
132
159
  .toThrow()
133
160
  })
134
161
 
135
- t.test("fail with wrong number of segments", () => {
162
+ test.test("fail with wrong number of segments", () => {
136
163
  const invalidValue = "one.two"
137
164
 
138
- t
165
+ test
139
166
  .expect(
140
167
  Effect.runPromise(
141
168
  EncryptedCookies.decrypt(invalidValue, { secret: "test-secret" }),
@@ -145,10 +172,10 @@ t.describe(`${EncryptedCookies.decrypt.name}`, () => {
145
172
  .toThrow()
146
173
  })
147
174
 
148
- t.test("fail with invalid base64", () => {
175
+ test.test("fail with invalid base64", () => {
149
176
  const invalidValue = "invalid.base64.data"
150
177
 
151
- t
178
+ test
152
179
  .expect(
153
180
  Effect.runPromise(
154
181
  EncryptedCookies.decrypt(invalidValue, { secret: "test-secret" }),
@@ -158,8 +185,8 @@ t.describe(`${EncryptedCookies.decrypt.name}`, () => {
158
185
  .toThrow()
159
186
  })
160
187
 
161
- t.test("fail with null value", () => {
162
- t
188
+ test.test("fail with null value", () => {
189
+ test
163
190
  .expect(
164
191
  Effect.runPromise(
165
192
  EncryptedCookies.encrypt(null, { secret: "test-secret" }),
@@ -169,8 +196,8 @@ t.describe(`${EncryptedCookies.decrypt.name}`, () => {
169
196
  .toThrow()
170
197
  })
171
198
 
172
- t.test("fail with undefined value", () => {
173
- t
199
+ test.test("fail with undefined value", () => {
200
+ test
174
201
  .expect(
175
202
  Effect.runPromise(
176
203
  EncryptedCookies.encrypt(undefined, { secret: "test-secret" }),
@@ -180,8 +207,8 @@ t.describe(`${EncryptedCookies.decrypt.name}`, () => {
180
207
  .toThrow()
181
208
  })
182
209
 
183
- t.test("fail with empty encrypted value", () => {
184
- t
210
+ test.test("fail with empty encrypted value", () => {
211
+ test
185
212
  .expect(
186
213
  Effect.runPromise(
187
214
  EncryptedCookies.decrypt("", { secret: "test-secret" }),
@@ -192,8 +219,8 @@ t.describe(`${EncryptedCookies.decrypt.name}`, () => {
192
219
  })
193
220
  })
194
221
 
195
- t.describe(`${EncryptedCookies.encryptCookie.name}`, () => {
196
- t.test("preserve cookie properties and encrypt value", async () => {
222
+ test.describe(`${EncryptedCookies.encryptCookie.name}`, () => {
223
+ test.test("preserve cookie properties and encrypt value", async () => {
197
224
  const cookie = Cookies.unsafeMakeCookie("test", "hello world")
198
225
 
199
226
  const result = await Effect.runPromise(
@@ -201,18 +228,25 @@ t.describe(`${EncryptedCookies.encryptCookie.name}`, () => {
201
228
  )
202
229
 
203
230
  // Cookie properties should be preserved
204
- t.expect(result.name).toBe("test")
231
+ test
232
+ .expect(result.name)
233
+ .toBe("test")
205
234
 
206
235
  // Value should be encrypted (different from original)
207
- t.expect(result.value).not.toBe("hello world")
236
+ test
237
+ .expect(result.value)
238
+ .not
239
+ .toBe("hello world")
208
240
 
209
241
  // Should be in encrypted format
210
- t.expect(result.value.split(".")).toHaveLength(3)
242
+ test
243
+ .expect(result.value.split("."))
244
+ .toHaveLength(3)
211
245
  })
212
246
  })
213
247
 
214
- t.describe(`${EncryptedCookies.decryptCookie.name}`, () => {
215
- t.test("preserve cookie properties and decrypt value", async () => {
248
+ test.describe(`${EncryptedCookies.decryptCookie.name}`, () => {
249
+ test.test("preserve cookie properties and decrypt value", async () => {
216
250
  const originalCookie = Cookies.unsafeMakeCookie("test", "hello world")
217
251
 
218
252
  const encrypted = await Effect.runPromise(
@@ -223,15 +257,19 @@ t.describe(`${EncryptedCookies.decryptCookie.name}`, () => {
223
257
  )
224
258
 
225
259
  // Cookie properties should be preserved
226
- t.expect(decrypted.name).toBe("test")
260
+ test
261
+ .expect(decrypted.name)
262
+ .toBe("test")
227
263
 
228
264
  // Value should be JSON stringified (string values are now always serialized)
229
- t.expect(decrypted.value).toBe("\"hello world\"")
265
+ test
266
+ .expect(decrypted.value)
267
+ .toBe("\"hello world\"")
230
268
  })
231
269
  })
232
270
 
233
- t.describe("service", () => {
234
- t.test("service uses pre-calculated key material", async () => {
271
+ test.describe("service", () => {
272
+ test.test("service uses pre-calculated key material", async () => {
235
273
  const testSecret = "test-secret-key"
236
274
  const testValue = "hello world"
237
275
 
@@ -250,12 +288,19 @@ t.describe("service", () => {
250
288
  ),
251
289
  )
252
290
 
253
- t.expect(result.decrypted).toBe(testValue)
254
- t.expect(result.encrypted).not.toBe(testValue)
255
- t.expect(result.encrypted.split(".")).toHaveLength(3)
291
+ test
292
+ .expect(result.decrypted)
293
+ .toBe(testValue)
294
+ test
295
+ .expect(result.encrypted)
296
+ .not
297
+ .toBe(testValue)
298
+ test
299
+ .expect(result.encrypted.split("."))
300
+ .toHaveLength(3)
256
301
  })
257
302
 
258
- t.test("service cookie functions work with pre-calculated key", async () => {
303
+ test.test("service cookie functions work with pre-calculated key", async () => {
259
304
  const testSecret = "test-secret-key"
260
305
  const originalCookie = Cookies.unsafeMakeCookie("test", "hello world")
261
306
 
@@ -274,12 +319,19 @@ t.describe("service", () => {
274
319
  ),
275
320
  )
276
321
 
277
- t.expect(result.decrypted.name).toBe("test")
278
- t.expect(result.decrypted.value).toBe("\"hello world\"")
279
- t.expect(result.encrypted.value).not.toBe("hello world")
322
+ test
323
+ .expect(result.decrypted.name)
324
+ .toBe("test")
325
+ test
326
+ .expect(result.decrypted.value)
327
+ .toBe("\"hello world\"")
328
+ test
329
+ .expect(result.encrypted.value)
330
+ .not
331
+ .toBe("hello world")
280
332
  })
281
333
 
282
- t.test("functions work with pre-derived keys passed as options", async () => {
334
+ test.test("functions work with pre-derived keys passed as options", async () => {
283
335
  const testSecret = "test-secret-key"
284
336
  const testValue = "hello world"
285
337
 
@@ -344,14 +396,21 @@ t.describe("service", () => {
344
396
 
345
397
  const result = await Effect.runPromise(program)
346
398
 
347
- t.expect(result.decrypted).toBe(testValue)
348
- t.expect(result.encrypted).not.toBe(testValue)
349
- t.expect(result.encrypted.split(".")).toHaveLength(3)
399
+ test
400
+ .expect(result.decrypted)
401
+ .toBe(testValue)
402
+ test
403
+ .expect(result.encrypted)
404
+ .not
405
+ .toBe(testValue)
406
+ test
407
+ .expect(result.encrypted.split("."))
408
+ .toHaveLength(3)
350
409
  })
351
410
  })
352
411
 
353
- t.describe("layerConfig", () => {
354
- t.test("succeed with valid SECRET_KEY_BASE", async () => {
412
+ test.describe("layerConfig", () => {
413
+ test.test("succeed with valid SECRET_KEY_BASE", async () => {
355
414
  const validSecret = "a".repeat(40)
356
415
 
357
416
  const program = Effect.gen(function*() {
@@ -374,10 +433,12 @@ t.describe("layerConfig", () => {
374
433
  ),
375
434
  )
376
435
 
377
- t.expect(result).toBe("test")
436
+ test
437
+ .expect(result)
438
+ .toBe("test")
378
439
  })
379
440
 
380
- t.test("fail with short SECRET_KEY_BASE", async () => {
441
+ test.test("fail with short SECRET_KEY_BASE", async () => {
381
442
  const shortSecret = "short"
382
443
 
383
444
  const program = Effect.gen(function*() {
@@ -385,7 +446,7 @@ t.describe("layerConfig", () => {
385
446
  return yield* service.encrypt("test")
386
447
  })
387
448
 
388
- t
449
+ test
389
450
  .expect(
390
451
  Effect.runPromise(
391
452
  program.pipe(
@@ -404,13 +465,13 @@ t.describe("layerConfig", () => {
404
465
  .toThrow("SECRET_KEY_BASE must be at least 40 characters")
405
466
  })
406
467
 
407
- t.test("fail with missing SECRET_KEY_BASE", async () => {
468
+ test.test("fail with missing SECRET_KEY_BASE", async () => {
408
469
  const program = Effect.gen(function*() {
409
470
  const service = yield* EncryptedCookies.EncryptedCookies
410
471
  return yield* service.encrypt("test")
411
472
  })
412
473
 
413
- t
474
+ test
414
475
  .expect(
415
476
  Effect.runPromise(
416
477
  program.pipe(
@@ -6,7 +6,6 @@ import * as Schedule from "effect/Schedule"
6
6
  import * as Stream from "effect/Stream"
7
7
  import * as StreamExtra from "../StreamExtra.ts"
8
8
 
9
-
10
9
  const DefaultHeartbeatInterval = Duration.seconds(5)
11
10
 
12
11
  export const make = <T = any>(stream: Stream.Stream<T, any>, options?: {
@@ -0,0 +1,89 @@
1
+ import * as Context from "effect/Context"
2
+ import * as Fiber from "effect/Fiber"
3
+ import * as Layer from "effect/Layer"
4
+ import * as Option from "effect/Option"
5
+ import { HyperHooks } from "../x/datastar/index.ts"
6
+ import type { JSX } from "./jsx.d.ts"
7
+
8
+ type Elements = JSX.IntrinsicElements
9
+
10
+ type Children = JSX.Children
11
+
12
+ export type {
13
+ Children,
14
+ Elements,
15
+ JSX,
16
+ }
17
+
18
+ export class Hyper extends Context.Tag("Hyper")<Hyper, {
19
+ hooks: typeof HyperHooks | undefined
20
+ }>() {}
21
+
22
+ export function layer(opts: {
23
+ hooks: typeof HyperHooks
24
+ }) {
25
+ return Layer.sync(Hyper, () => {
26
+ return {
27
+ hooks: opts.hooks,
28
+ }
29
+ })
30
+ }
31
+
32
+ const NoChildren: ReadonlyArray<never> = Object.freeze([])
33
+
34
+ type Primitive = string | number | boolean | null | undefined
35
+
36
+ export type HyperType = string | HyperComponent
37
+
38
+ export type HyperProps = {
39
+ [key: string]:
40
+ | Primitive
41
+ | ReadonlyArray<Primitive>
42
+ | HyperNode
43
+ | HyperNode[]
44
+ | null
45
+ | undefined
46
+ }
47
+
48
+ export type HyperComponent = (
49
+ props: HyperProps,
50
+ ) => HyperNode | Primitive
51
+
52
+ export interface HyperNode {
53
+ type: HyperType
54
+ props: HyperProps
55
+ }
56
+
57
+ export function h(
58
+ type: HyperType,
59
+ props: HyperProps,
60
+ ): HyperNode {
61
+ return {
62
+ type,
63
+ props: {
64
+ ...props,
65
+ children: props.children ?? NoChildren,
66
+ },
67
+ }
68
+ }
69
+
70
+ export function unsafeUse<Value>(tag: Context.Tag<any, Value>) {
71
+ const currentFiber = Option.getOrThrow(
72
+ Fiber.getCurrentFiber(),
73
+ )
74
+ const context = currentFiber.currentContext
75
+
76
+ return Context.unsafeGet(context, tag)
77
+ }
78
+
79
+ export type GenericJsxObject = {
80
+ type: any
81
+ props: any
82
+ }
83
+
84
+ export function isGenericJsxObject(value: unknown): value is GenericJsxObject {
85
+ return typeof value === "object"
86
+ && value !== null
87
+ && "type" in value
88
+ && "props" in value
89
+ }
@@ -1,8 +1,8 @@
1
- import * as t from "bun:test"
1
+ import * as test from "bun:test"
2
2
  import * as HyperHtml from "./HyperHtml.ts"
3
3
  import * as HyperNode from "./HyperNode.ts"
4
4
 
5
- t.it("boolean true attributes render without value (React-like)", () => {
5
+ test.it("boolean true attributes render without value (React-like)", () => {
6
6
  const node = HyperNode.make("div", {
7
7
  hidden: true,
8
8
  disabled: true,
@@ -11,12 +11,12 @@ t.it("boolean true attributes render without value (React-like)", () => {
11
11
 
12
12
  const html = HyperHtml.renderToString(node)
13
13
 
14
- t
14
+ test
15
15
  .expect(html)
16
16
  .toBe("<div hidden disabled data-active></div>")
17
17
  })
18
18
 
19
- t.it("boolean false attributes are omitted", () => {
19
+ test.it("boolean false attributes are omitted", () => {
20
20
  const node = HyperNode.make("div", {
21
21
  hidden: false,
22
22
  disabled: false,
@@ -25,12 +25,12 @@ t.it("boolean false attributes are omitted", () => {
25
25
 
26
26
  const html = HyperHtml.renderToString(node)
27
27
 
28
- t
28
+ test
29
29
  .expect(html)
30
30
  .toBe("<div></div>")
31
31
  })
32
32
 
33
- t.it("string attributes render with values", () => {
33
+ test.it("string attributes render with values", () => {
34
34
  const node = HyperNode.make("div", {
35
35
  id: "test",
36
36
  class: "my-class",
@@ -39,12 +39,12 @@ t.it("string attributes render with values", () => {
39
39
 
40
40
  const html = HyperHtml.renderToString(node)
41
41
 
42
- t
42
+ test
43
43
  .expect(html)
44
44
  .toBe("<div id=\"test\" class=\"my-class\" data-value=\"hello\"></div>")
45
45
  })
46
46
 
47
- t.it("number attributes render with values", () => {
47
+ test.it("number attributes render with values", () => {
48
48
  const node = HyperNode.make("input", {
49
49
  type: "number",
50
50
  min: 0,
@@ -54,12 +54,12 @@ t.it("number attributes render with values", () => {
54
54
 
55
55
  const html = HyperHtml.renderToString(node)
56
56
 
57
- t
57
+ test
58
58
  .expect(html)
59
59
  .toBe("<input type=\"number\" min=\"0\" max=\"100\" value=\"50\">")
60
60
  })
61
61
 
62
- t.it("null and undefined attributes are omitted", () => {
62
+ test.it("null and undefined attributes are omitted", () => {
63
63
  const node = HyperNode.make("div", {
64
64
  id: null,
65
65
  class: undefined,
@@ -68,12 +68,12 @@ t.it("null and undefined attributes are omitted", () => {
68
68
 
69
69
  const html = HyperHtml.renderToString(node)
70
70
 
71
- t
71
+ test
72
72
  .expect(html)
73
73
  .toBe("<div data-test=\"value\"></div>")
74
74
  })
75
75
 
76
- t.it("mixed boolean and string attributes", () => {
76
+ test.it("mixed boolean and string attributes", () => {
77
77
  const node = HyperNode.make("input", {
78
78
  type: "checkbox",
79
79
  checked: true,
@@ -84,7 +84,7 @@ t.it("mixed boolean and string attributes", () => {
84
84
 
85
85
  const html = HyperHtml.renderToString(node)
86
86
 
87
- t
87
+ test
88
88
  .expect(html)
89
89
  .toBe("<input type=\"checkbox\" checked name=\"test\" value=\"on\">")
90
90
  })
@@ -17,10 +17,10 @@
17
17
  * }
18
18
  */
19
19
 
20
- import type * as Hyper from "./Hyper.tsx"
20
+ import type * as Hyper from "./Hyper.ts"
21
21
  import * as HyperNode from "./HyperNode.ts"
22
- import { JSX } from "./jsx"
23
22
  import type * as JsxRuntime from "./jsx-runtime.ts"
23
+ import type { JSX } from "./jsx.d.ts"
24
24
 
25
25
  const EMPTY_TAGS = [
26
26
  "area",
@@ -1,4 +1,4 @@
1
- import * as HyperNode from "./HyperNode.ts"
1
+ import * as HyperNode from "./hyper/HyperNode.ts"
2
2
  import type { DatastarAttributes } from "./x/datastar/jsx-datastar.ts"
3
3
 
4
4
  /**
package/src/index.ts CHANGED
@@ -1,6 +1,5 @@
1
- export * as Start from "./Start.ts"
2
-
1
+ export * as Bundle from "./bundler/Bundle.ts"
2
+ export * as Entity from "./Entity.ts"
3
3
  export * as FileRouter from "./FileRouter.ts"
4
4
  export * as Route from "./Route.ts"
5
-
6
- export * as Bundle from "./Bundle.ts"
5
+ export * as Start from "./Start.ts"