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.
Files changed (313) hide show
  1. package/dist/BlobStore.d.ts +80 -0
  2. package/dist/BlobStore.js +19 -0
  3. package/dist/ChildProcess.d.ts +60 -0
  4. package/dist/ChildProcess.js +30 -0
  5. package/dist/Commander.d.ts +3 -6
  6. package/dist/Commander.js +6 -13
  7. package/dist/ContentNegotiation.d.ts +8 -9
  8. package/dist/ContentNegotiation.js +32 -37
  9. package/dist/Cookies.d.ts +47 -0
  10. package/dist/Cookies.js +273 -363
  11. package/dist/Development.d.ts +2 -2
  12. package/dist/Development.js +3 -4
  13. package/dist/Effectify.d.ts +1 -4
  14. package/dist/FilePathPattern.d.ts +3 -3
  15. package/dist/FileRouter.d.ts +5 -8
  16. package/dist/FileRouter.js +9 -10
  17. package/dist/FileRouterCodegen.d.ts +1 -1
  18. package/dist/FileRouterCodegen.js +33 -13
  19. package/dist/FileSystem.d.ts +158 -0
  20. package/dist/FileSystem.js +64 -125
  21. package/dist/Http.js +2 -6
  22. package/dist/PathPattern.d.ts +7 -7
  23. package/dist/PathPattern.js +1 -3
  24. package/dist/PlatformError.d.ts +24 -32
  25. package/dist/PlatformError.js +3 -21
  26. package/dist/PlatformRuntime.js +5 -10
  27. package/dist/Route.d.ts +14 -19
  28. package/dist/Route.js +8 -11
  29. package/dist/RouteBody.d.ts +6 -12
  30. package/dist/RouteBody.js +2 -2
  31. package/dist/RouteError.d.ts +98 -0
  32. package/dist/RouteError.js +55 -0
  33. package/dist/RouteHook.js +6 -11
  34. package/dist/RouteHttp.d.ts +3 -3
  35. package/dist/RouteHttp.js +27 -22
  36. package/dist/RouteMount.d.ts +16 -50
  37. package/dist/RouteMount.js +6 -20
  38. package/dist/RouteSchema.d.ts +22 -1
  39. package/dist/RouteSchema.js +33 -0
  40. package/dist/RouteSse.js +4 -10
  41. package/dist/RouteTree.d.ts +2 -1
  42. package/dist/RouteTree.js +17 -15
  43. package/dist/RouteTrie.d.ts +2 -2
  44. package/dist/RouteTrie.js +4 -9
  45. package/dist/SchemaExtra.d.ts +1 -1
  46. package/dist/Socket.d.ts +27 -0
  47. package/dist/Socket.js +20 -28
  48. package/dist/Sql.d.ts +34 -0
  49. package/dist/Sql.js +5 -0
  50. package/dist/SqlIntrospect.d.ts +91 -0
  51. package/dist/SqlIntrospect.js +466 -0
  52. package/dist/Start.d.ts +4 -6
  53. package/dist/Start.js +10 -2
  54. package/dist/StreamExtra.d.ts +1 -1
  55. package/dist/StreamExtra.js +9 -9
  56. package/dist/System.d.ts +7 -0
  57. package/dist/System.js +22 -0
  58. package/dist/TuplePathPattern.js +55 -50
  59. package/dist/Unique.js +7 -7
  60. package/dist/Values.d.ts +2 -1
  61. package/dist/Values.js +19 -13
  62. package/dist/bun/BunBlobStoreDisk.d.ts +6 -0
  63. package/dist/bun/BunBlobStoreDisk.js +116 -0
  64. package/dist/bun/BunBlobStoreS3.d.ts +11 -0
  65. package/dist/bun/BunBlobStoreS3.js +89 -0
  66. package/dist/bun/BunBlobWatcherDisk.d.ts +6 -0
  67. package/dist/bun/BunBlobWatcherDisk.js +60 -0
  68. package/dist/bun/BunBlobWatcherQueue.d.ts +6 -0
  69. package/dist/bun/BunBlobWatcherQueue.js +17 -0
  70. package/dist/bun/BunBundle.d.ts +5 -6
  71. package/dist/bun/BunBundle.js +7 -15
  72. package/dist/bun/BunChildProcessSpawner.d.ts +3 -0
  73. package/dist/bun/BunChildProcessSpawner.js +103 -0
  74. package/dist/bun/BunImportTrackerPlugin.d.ts +1 -1
  75. package/dist/bun/BunImportTrackerPlugin.js +3 -5
  76. package/dist/bun/BunRoute.d.ts +3 -2
  77. package/dist/bun/BunRoute.js +5 -7
  78. package/dist/bun/BunRuntime.js +1 -1
  79. package/dist/bun/BunServer.d.ts +11 -4
  80. package/dist/bun/BunServer.js +35 -11
  81. package/dist/bun/BunSql.d.ts +4 -0
  82. package/dist/bun/BunSql.js +81 -0
  83. package/dist/bun/_BunEnhancedResolve.d.ts +3 -3
  84. package/dist/bun/_BunEnhancedResolve.js +2 -4
  85. package/dist/bun/index.d.ts +1 -0
  86. package/dist/bun/index.js +1 -0
  87. package/dist/bundler/Bundle.d.ts +2 -1
  88. package/dist/bundler/Bundle.js +1 -1
  89. package/dist/bundler/BundleFiles.d.ts +5 -5
  90. package/dist/bundler/BundleFiles.js +10 -8
  91. package/dist/bundler/BundleRoute.d.ts +27 -0
  92. package/dist/bundler/BundleRoute.js +51 -0
  93. package/dist/client/ScrollState.js +2 -6
  94. package/dist/client/index.js +6 -8
  95. package/dist/console/Console.d.ts +6 -0
  96. package/dist/console/Console.js +26 -0
  97. package/dist/console/ConsoleErrors.d.ts +3 -0
  98. package/dist/console/ConsoleErrors.js +200 -0
  99. package/dist/console/ConsoleLogger.d.ts +3 -0
  100. package/dist/console/ConsoleLogger.js +47 -0
  101. package/dist/console/ConsoleMetrics.d.ts +3 -0
  102. package/dist/console/ConsoleMetrics.js +61 -0
  103. package/dist/console/ConsoleProcess.d.ts +3 -0
  104. package/dist/console/ConsoleProcess.js +49 -0
  105. package/dist/console/ConsoleStore.d.ts +144 -0
  106. package/dist/console/ConsoleStore.js +61 -0
  107. package/dist/console/ConsoleTracer.d.ts +3 -0
  108. package/dist/console/ConsoleTracer.js +94 -0
  109. package/dist/console/Simulation.d.ts +2 -0
  110. package/dist/console/Simulation.js +633 -0
  111. package/dist/console/index.d.ts +3 -0
  112. package/dist/console/index.js +3 -0
  113. package/dist/console/routes/errors/route.d.ts +10 -0
  114. package/dist/console/routes/errors/route.js +47 -0
  115. package/dist/console/routes/fiberDetail.d.ts +16 -0
  116. package/dist/console/routes/fiberDetail.js +38 -0
  117. package/dist/console/routes/fibers/route.d.ts +10 -0
  118. package/dist/console/routes/fibers/route.js +19 -0
  119. package/dist/console/routes/git/route.d.ts +11 -0
  120. package/dist/console/routes/git/route.js +33 -0
  121. package/dist/console/routes/layout.d.ts +9 -0
  122. package/dist/console/routes/layout.js +3 -0
  123. package/dist/console/routes/logs/route.d.ts +10 -0
  124. package/dist/console/routes/logs/route.js +32 -0
  125. package/dist/console/routes/metrics/route.d.ts +10 -0
  126. package/dist/console/routes/metrics/route.js +17 -0
  127. package/dist/console/routes/route.d.ts +6 -0
  128. package/dist/console/routes/route.js +5 -0
  129. package/dist/console/routes/routes/route.d.ts +6 -0
  130. package/dist/console/routes/routes/route.js +20 -0
  131. package/dist/console/routes/services/route.d.ts +6 -0
  132. package/dist/console/routes/services/route.js +12 -0
  133. package/dist/console/routes/system/route.d.ts +10 -0
  134. package/dist/console/routes/system/route.js +18 -0
  135. package/dist/console/routes/traceDetail.d.ts +16 -0
  136. package/dist/console/routes/traceDetail.js +14 -0
  137. package/dist/console/routes/traces/route.d.ts +10 -0
  138. package/dist/console/routes/traces/route.js +39 -0
  139. package/dist/console/routes/tree.d.ts +153 -0
  140. package/dist/console/routes/tree.js +29 -0
  141. package/dist/console/ui/Errors.d.ts +4 -0
  142. package/dist/console/ui/Errors.js +15 -0
  143. package/dist/console/ui/Fibers.d.ts +24 -0
  144. package/dist/console/ui/Fibers.js +121 -0
  145. package/dist/console/ui/Git.d.ts +20 -0
  146. package/dist/console/ui/Git.js +95 -0
  147. package/dist/console/ui/Logs.d.ts +4 -0
  148. package/dist/console/ui/Logs.js +25 -0
  149. package/dist/console/ui/Metrics.d.ts +4 -0
  150. package/dist/console/ui/Metrics.js +26 -0
  151. package/dist/console/ui/Routes.d.ts +8 -0
  152. package/dist/console/ui/Routes.js +70 -0
  153. package/dist/console/ui/Services.d.ts +10 -0
  154. package/dist/console/ui/Services.js +246 -0
  155. package/dist/console/ui/Shell.d.ts +10 -0
  156. package/dist/console/ui/Shell.js +7 -0
  157. package/dist/console/ui/System.d.ts +4 -0
  158. package/dist/console/ui/System.js +35 -0
  159. package/dist/console/ui/Traces.d.ts +12 -0
  160. package/dist/console/ui/Traces.js +179 -0
  161. package/dist/datastar/actions/fetch.d.ts +1 -1
  162. package/dist/datastar/actions/fetch.js +10 -18
  163. package/dist/datastar/actions/peek.js +1 -2
  164. package/dist/datastar/actions/setAll.js +1 -2
  165. package/dist/datastar/actions/toggleAll.js +1 -2
  166. package/dist/datastar/attributes/attr.js +1 -2
  167. package/dist/datastar/attributes/bind.js +10 -18
  168. package/dist/datastar/attributes/class.js +2 -5
  169. package/dist/datastar/attributes/computed.js +2 -3
  170. package/dist/datastar/attributes/effect.js +1 -2
  171. package/dist/datastar/attributes/indicator.js +2 -4
  172. package/dist/datastar/attributes/init.js +2 -3
  173. package/dist/datastar/attributes/jsonSignals.js +1 -2
  174. package/dist/datastar/attributes/on.js +41 -22
  175. package/dist/datastar/attributes/onIntersect.js +2 -3
  176. package/dist/datastar/attributes/onInterval.js +2 -3
  177. package/dist/datastar/attributes/onSignalPatch.js +2 -4
  178. package/dist/datastar/attributes/ref.js +1 -2
  179. package/dist/datastar/attributes/show.js +1 -2
  180. package/dist/datastar/attributes/signals.js +1 -2
  181. package/dist/datastar/attributes/style.js +6 -12
  182. package/dist/datastar/attributes/text.js +1 -2
  183. package/dist/datastar/engine.d.ts +13 -7
  184. package/dist/datastar/engine.js +76 -48
  185. package/dist/datastar/happydom.d.ts +1 -0
  186. package/dist/datastar/happydom.js +8 -0
  187. package/dist/datastar/index.d.ts +1 -1
  188. package/dist/datastar/index.js +1 -1
  189. package/dist/datastar/utils.js +4 -7
  190. package/dist/datastar/watchers/patchElements.js +24 -45
  191. package/dist/datastar/watchers/patchSignals.js +1 -2
  192. package/dist/experimental/EncryptedCookies.d.ts +2 -5
  193. package/dist/experimental/EncryptedCookies.js +17 -48
  194. package/dist/experimental/index.d.ts +0 -1
  195. package/dist/experimental/index.js +0 -1
  196. package/dist/hyper/Hyper.d.ts +2 -9
  197. package/dist/hyper/Hyper.js +1 -12
  198. package/dist/hyper/HyperHtml.d.ts +1 -1
  199. package/dist/hyper/HyperHtml.js +18 -12
  200. package/dist/hyper/HyperHtml.test.d.ts +1 -0
  201. package/dist/hyper/HyperHtml.test.js +197 -0
  202. package/dist/hyper/HyperRoute.test.js +14 -3
  203. package/dist/hyper/html.d.ts +11 -0
  204. package/dist/hyper/html.js +30 -0
  205. package/dist/hyper/index.d.ts +2 -0
  206. package/dist/hyper/index.js +1 -0
  207. package/dist/hyper/jsx-runtime.d.ts +1 -1
  208. package/dist/hyper/jsx-runtime.js +1 -1
  209. package/dist/index.d.ts +1 -0
  210. package/dist/index.js +1 -0
  211. package/dist/lint/plugin.d.ts +86 -0
  212. package/dist/lint/plugin.js +341 -0
  213. package/dist/node/NodeFileSystem.d.ts +2 -2
  214. package/dist/node/NodeFileSystem.js +4 -14
  215. package/dist/sql/bun/index.d.ts +3 -0
  216. package/dist/sql/bun/index.js +75 -0
  217. package/dist/sql/mssql/docker.d.ts +2 -0
  218. package/dist/sql/mssql/docker.js +67 -0
  219. package/dist/sql/mssql/index.d.ts +21 -0
  220. package/dist/sql/mssql/index.js +113 -0
  221. package/dist/testing/TestLogger.js +4 -1
  222. package/dist/testing/index.d.ts +0 -1
  223. package/dist/testing/index.js +0 -1
  224. package/dist/testing/utils.d.ts +3 -3
  225. package/dist/testing/utils.js +4 -4
  226. package/dist/x/cloudflare/CloudflareTunnel.d.ts +2 -5
  227. package/dist/x/cloudflare/CloudflareTunnel.js +14 -27
  228. package/dist/x/datastar/Datastar.d.ts +1 -1
  229. package/dist/x/datastar/Datastar.js +13 -12
  230. package/dist/x/datastar/index.d.ts +1 -2
  231. package/dist/x/datastar/index.js +1 -2
  232. package/dist/x/tailscale/TailscaleTunnel.d.ts +15 -0
  233. package/dist/x/tailscale/TailscaleTunnel.js +68 -0
  234. package/dist/x/tailscale/index.d.ts +1 -0
  235. package/dist/x/tailscale/index.js +1 -0
  236. package/dist/x/tailwind/TailwindPlugin.js +19 -19
  237. package/dist/x/tailwind/compile.d.ts +2 -2
  238. package/dist/x/tailwind/compile.js +2 -4
  239. package/package.json +22 -10
  240. package/src/ChildProcess.ts +145 -0
  241. package/src/PlatformError.ts +27 -50
  242. package/src/Route.ts +2 -2
  243. package/src/RouteError.ts +76 -0
  244. package/src/RouteHttp.ts +13 -5
  245. package/src/RouteSchema.ts +96 -1
  246. package/src/RouteTree.ts +12 -0
  247. package/src/Sql.ts +51 -0
  248. package/src/SqlIntrospect.ts +620 -0
  249. package/src/Start.ts +15 -3
  250. package/src/System.ts +43 -0
  251. package/src/Values.ts +7 -0
  252. package/src/bun/BunChildProcessSpawner.ts +143 -0
  253. package/src/bun/BunRoute.ts +5 -2
  254. package/src/bun/BunServer.ts +22 -1
  255. package/src/bun/index.ts +1 -0
  256. package/src/bundler/BundleRoute.ts +66 -0
  257. package/src/console/Console.ts +42 -0
  258. package/src/console/ConsoleErrors.ts +213 -0
  259. package/src/console/ConsoleLogger.ts +56 -0
  260. package/src/console/ConsoleMetrics.ts +72 -0
  261. package/src/console/ConsoleProcess.ts +59 -0
  262. package/src/console/ConsoleStore.ts +187 -0
  263. package/src/console/ConsoleTracer.ts +107 -0
  264. package/src/console/Simulation.ts +814 -0
  265. package/src/console/console.html +340 -0
  266. package/src/console/index.ts +3 -0
  267. package/src/console/routes/errors/route.tsx +97 -0
  268. package/src/console/routes/fiberDetail.tsx +54 -0
  269. package/src/console/routes/fibers/route.tsx +45 -0
  270. package/src/console/routes/git/route.tsx +64 -0
  271. package/src/console/routes/layout.tsx +4 -0
  272. package/src/console/routes/logs/route.tsx +77 -0
  273. package/src/console/routes/metrics/route.tsx +36 -0
  274. package/src/console/routes/route.tsx +8 -0
  275. package/src/console/routes/routes/route.tsx +30 -0
  276. package/src/console/routes/services/route.tsx +21 -0
  277. package/src/console/routes/system/route.tsx +43 -0
  278. package/src/console/routes/traceDetail.tsx +22 -0
  279. package/src/console/routes/traces/route.tsx +81 -0
  280. package/src/console/routes/tree.ts +30 -0
  281. package/src/console/ui/Errors.tsx +76 -0
  282. package/src/console/ui/Fibers.tsx +321 -0
  283. package/src/console/ui/Git.tsx +182 -0
  284. package/src/console/ui/Logs.tsx +46 -0
  285. package/src/console/ui/Metrics.tsx +78 -0
  286. package/src/console/ui/Routes.tsx +125 -0
  287. package/src/console/ui/Services.tsx +273 -0
  288. package/src/console/ui/Shell.tsx +62 -0
  289. package/src/console/ui/System.tsx +131 -0
  290. package/src/console/ui/Traces.tsx +426 -0
  291. package/src/datastar/README.md +6 -1
  292. package/src/datastar/actions/fetch.ts +0 -1
  293. package/src/datastar/attributes/on.ts +40 -20
  294. package/src/datastar/engine.ts +51 -0
  295. package/src/datastar/jsx.d.ts +79 -0
  296. package/src/hyper/Hyper.ts +1 -16
  297. package/src/hyper/HyperHtml.ts +6 -4
  298. package/src/hyper/HyperRoute.ts +2 -1
  299. package/src/hyper/html.ts +47 -0
  300. package/src/hyper/index.ts +2 -0
  301. package/src/hyper/jsx.d.ts +5 -3
  302. package/src/index.ts +1 -0
  303. package/src/lint/plugin.js +129 -0
  304. package/src/sql/bun/index.ts +147 -0
  305. package/src/sql/mssql/docker.ts +117 -0
  306. package/src/sql/mssql/index.ts +223 -0
  307. package/src/sql/mssql/mssql.d.ts +41 -0
  308. package/src/x/cloudflare/CloudflareTunnel.ts +8 -36
  309. package/src/x/tailscale/TailscaleTunnel.ts +113 -0
  310. package/src/x/tailscale/index.ts +1 -0
  311. package/src/x/datastar/Datastar.ts +0 -61
  312. package/src/x/datastar/index.ts +0 -2
  313. package/src/x/datastar/jsx-datastar.d.ts +0 -60
@@ -0,0 +1,197 @@
1
+ import { jsx as _jsx } from "effect-start/jsx-runtime";
2
+ /** @jsxImportSource effect-start */
3
+ import * as test from "bun:test";
4
+ import * as HyperHtml from "./HyperHtml.js";
5
+ import * as HyperNode from "./HyperNode.js";
6
+ test.it("boolean true attributes render without value (React-like)", () => {
7
+ const node = HyperNode.make("div", {
8
+ hidden: true,
9
+ disabled: true,
10
+ "data-active": true,
11
+ });
12
+ const html = HyperHtml.renderToString(node);
13
+ test.expect(html).toBe("<div hidden disabled data-active></div>");
14
+ });
15
+ test.it("boolean false attributes are omitted", () => {
16
+ const node = HyperNode.make("div", {
17
+ hidden: false,
18
+ disabled: false,
19
+ "data-active": false,
20
+ });
21
+ const html = HyperHtml.renderToString(node);
22
+ test.expect(html).toBe("<div></div>");
23
+ });
24
+ test.it("string attributes render with values", () => {
25
+ const node = HyperNode.make("div", {
26
+ id: "test",
27
+ class: "my-class",
28
+ "data-value": "hello",
29
+ });
30
+ const html = HyperHtml.renderToString(node);
31
+ test.expect(html).toBe('<div id="test" class="my-class" data-value="hello"></div>');
32
+ });
33
+ test.it("number attributes render with values", () => {
34
+ const node = HyperNode.make("input", {
35
+ type: "number",
36
+ min: 0,
37
+ max: 100,
38
+ value: 50,
39
+ });
40
+ const html = HyperHtml.renderToString(node);
41
+ test.expect(html).toBe('<input type="number" min="0" max="100" value="50">');
42
+ });
43
+ test.it("null and undefined attributes are omitted", () => {
44
+ const node = HyperNode.make("div", {
45
+ id: null,
46
+ class: undefined,
47
+ "data-test": "value",
48
+ });
49
+ const html = HyperHtml.renderToString(node);
50
+ test.expect(html).toBe('<div data-test="value"></div>');
51
+ });
52
+ test.it("mixed boolean and string attributes", () => {
53
+ const node = HyperNode.make("input", {
54
+ type: "checkbox",
55
+ checked: true,
56
+ disabled: false,
57
+ name: "test",
58
+ value: "on",
59
+ });
60
+ const html = HyperHtml.renderToString(node);
61
+ test.expect(html).toBe('<input type="checkbox" checked name="test" value="on">');
62
+ });
63
+ test.it("data-* attributes with object values use single-quoted JSON", () => {
64
+ const node = HyperNode.make("div", {
65
+ "data-signals": {
66
+ draft: "",
67
+ pendingDraft: "",
68
+ username: "User123",
69
+ },
70
+ });
71
+ const html = HyperHtml.renderToString(node);
72
+ test
73
+ .expect(html)
74
+ .toBe(`<div data-signals='{"draft":"","pendingDraft":"","username":"User123"}'></div>`);
75
+ });
76
+ test.it("data-* attributes with array values use single-quoted JSON", () => {
77
+ const node = HyperNode.make("div", {
78
+ "data-items": [1, 2, 3],
79
+ });
80
+ const html = HyperHtml.renderToString(node);
81
+ test.expect(html).toBe("<div data-items='[1,2,3]'></div>");
82
+ });
83
+ test.it("data-* attributes with nested object values use single-quoted JSON", () => {
84
+ const node = HyperNode.make("div", {
85
+ "data-config": {
86
+ user: { name: "John", active: true },
87
+ settings: { theme: "dark" },
88
+ },
89
+ });
90
+ const html = HyperHtml.renderToString(node);
91
+ test
92
+ .expect(html)
93
+ .toBe(`<div data-config='{"user":{"name":"John","active":true},"settings":{"theme":"dark"}}'></div>`);
94
+ });
95
+ test.it("data-* object values with single quotes in values are escaped", () => {
96
+ const node = HyperNode.make("div", {
97
+ "data-signals": {
98
+ message: "it's a test",
99
+ name: "O'Brien",
100
+ },
101
+ });
102
+ const html = HyperHtml.renderToString(node);
103
+ test
104
+ .expect(html)
105
+ .toBe(`<div data-signals='{"message":"it&#39;s a test","name":"O&#39;Brien"}'></div>`);
106
+ });
107
+ test.it("data-* string values are not JSON stringified", () => {
108
+ const node = HyperNode.make("div", {
109
+ "data-value": "hello world",
110
+ });
111
+ const html = HyperHtml.renderToString(node);
112
+ test.expect(html).toBe('<div data-value="hello world"></div>');
113
+ });
114
+ test.it("non-data attributes with object values are not JSON stringified", () => {
115
+ const node = HyperNode.make("div", {
116
+ style: "color: red",
117
+ });
118
+ const html = HyperHtml.renderToString(node);
119
+ test.expect(html).toBe('<div style="color: red"></div>');
120
+ });
121
+ test.it("script with function child renders as IIFE", () => {
122
+ const handler = (window) => {
123
+ console.log("Hello from", window.document.title);
124
+ };
125
+ const node = HyperNode.make("script", {
126
+ children: handler,
127
+ });
128
+ const html = HyperHtml.renderToString(node);
129
+ test.expect(html).toBe(`<script>(${handler.toString()})(window)</script>`);
130
+ });
131
+ test.it("script with arrow function child renders as IIFE", () => {
132
+ const node = HyperNode.make("script", {
133
+ children: (window) => {
134
+ window.alert("test");
135
+ },
136
+ });
137
+ const html = HyperHtml.renderToString(node);
138
+ test.expect(html).toContain("<script>(");
139
+ test.expect(html).toContain(")(window)</script>");
140
+ test.expect(html).toContain("window.alert");
141
+ });
142
+ test.it("script with string child renders without escaping", () => {
143
+ const node = HyperNode.make("script", {
144
+ children: "console.log('hello')",
145
+ });
146
+ const html = HyperHtml.renderToString(node);
147
+ test.expect(html).toBe("<script>console.log('hello')</script>");
148
+ });
149
+ test.it("script with string child preserves ampersands and quotes", () => {
150
+ const node = HyperNode.make("script", {
151
+ children: 'if (a && b) { console.log("yes") }',
152
+ });
153
+ const html = HyperHtml.renderToString(node);
154
+ test.expect(html).toBe('<script>if (a && b) { console.log("yes") }</script>');
155
+ });
156
+ test.it("style tag content is not escaped", () => {
157
+ const node = HyperNode.make("style", {
158
+ children: ".foo > .bar { content: '&'; }",
159
+ });
160
+ const html = HyperHtml.renderToString(node);
161
+ test.expect(html).toBe("<style>.foo > .bar { content: '&'; }</style>");
162
+ });
163
+ test.it("script with attributes and no children", () => {
164
+ const node = HyperNode.make("script", {
165
+ type: "module",
166
+ src: "https://example.com/app.js",
167
+ });
168
+ const html = HyperHtml.renderToString(node);
169
+ test.expect(html).toBe('<script type="module" src="https://example.com/app.js"></script>');
170
+ });
171
+ test.it("normal tag string content is escaped", () => {
172
+ const node = HyperNode.make("div", {
173
+ children: "a && b",
174
+ });
175
+ const html = HyperHtml.renderToString(node);
176
+ test.expect(html).toBe("<div>a &amp;&amp; b</div>");
177
+ });
178
+ test.it("data-* function values are serialized with toString", () => {
179
+ const node = HyperNode.make("div", {
180
+ "data-on-click": () => console.log("clicked"),
181
+ });
182
+ const html = HyperHtml.renderToString(node);
183
+ test.expect(html).toContain("data-on-click=");
184
+ test.expect(html).toContain("console.log");
185
+ });
186
+ test.it("data-* object values don't render as [object Object]", () => {
187
+ const html = HyperHtml.renderToString(_jsx("div", { "data-signals": { isOpen: false, count: 42 }, children: "content" }));
188
+ test.expect(html).toBe(`<div data-signals='{"isOpen":false,"count":42}'>content</div>`);
189
+ test.expect(html).not.toContain("[object Object]");
190
+ });
191
+ test.it("JSX component with data-* object values", () => {
192
+ function TestComponent() {
193
+ return (_jsx("div", { "data-signals": { isOpen: false }, children: _jsx("span", { children: "nested" }) }));
194
+ }
195
+ const html = HyperHtml.renderToString(_jsx(TestComponent, {}));
196
+ test.expect(html).toBe(`<div data-signals='{"isOpen":false}'><span>nested</span></div>`);
197
+ });
@@ -18,7 +18,9 @@ test.describe("HyperRoute.html", () => {
18
18
  test.it("renders nested JSX elements", async () => {
19
19
  const handler = RouteHttp.toWebHandler(Route.get(HyperRoute.html(_jsxs("div", { class: "container", children: [_jsx("h1", { children: "Title" }), _jsx("p", { children: "Paragraph" })] }))));
20
20
  const response = await Http.fetch(handler, { path: "/" });
21
- test.expect(await response.text()).toBe("<div class=\"container\"><h1>Title</h1><p>Paragraph</p></div>");
21
+ test
22
+ .expect(await response.text())
23
+ .toBe('<div class="container"><h1>Title</h1><p>Paragraph</p></div>');
22
24
  });
23
25
  test.it("renders JSX from Effect", async () => {
24
26
  const handler = RouteHttp.toWebHandler(Route.get(HyperRoute.html(Effect.succeed(_jsx("span", { children: "From Effect" })))));
@@ -28,7 +30,7 @@ test.describe("HyperRoute.html", () => {
28
30
  test.it("renders JSX from generator function", async () => {
29
31
  const handler = RouteHttp.toWebHandler(Route.get(HyperRoute.html(Effect.gen(function* () {
30
32
  const name = yield* Effect.succeed("World");
31
- return (_jsxs("div", { children: ["Hello ", name] }));
33
+ return _jsxs("div", { children: ["Hello ", name] });
32
34
  }))));
33
35
  const response = await Http.fetch(handler, { path: "/" });
34
36
  test.expect(await response.text()).toBe("<div>Hello World</div>");
@@ -57,7 +59,16 @@ test.describe("HyperRoute.html", () => {
57
59
  username: "User123",
58
60
  }, children: "Content" }))));
59
61
  const response = await Http.fetch(handler, { path: "/" });
60
- test.expect(await response.text()).toBe("<div data-signals=\"{&quot;draft&quot;:&quot;&quot;,&quot;pendingDraft&quot;:&quot;&quot;,&quot;username&quot;:&quot;User123&quot;}\">Content</div>");
62
+ test
63
+ .expect(await response.text())
64
+ .toBe(`<div data-signals='{"draft":"","pendingDraft":"","username":"User123"}'>Content</div>`);
65
+ });
66
+ test.it("data-on-click function argument is typed as DataEvent", () => {
67
+ const node = (_jsx("button", { "data-on:click": (e) => {
68
+ test.expectTypeOf(e).toEqualTypeOf();
69
+ test.expectTypeOf(e.window).toEqualTypeOf();
70
+ } }));
71
+ test.expect(node).toBeDefined();
61
72
  });
62
73
  test.it("renders script with function child as IIFE", async () => {
63
74
  const handler = RouteHttp.toWebHandler(Route.get(HyperRoute.html(_jsx("script", { children: (window) => {
@@ -0,0 +1,11 @@
1
+ declare const HtmlStringSymbol: unique symbol;
2
+ export interface HtmlString {
3
+ readonly [HtmlStringSymbol]: true;
4
+ readonly value: string;
5
+ }
6
+ export type HtmlValue = string | number | bigint | boolean | null | undefined | HtmlString | Function | Record<string, unknown> | ReadonlyArray<HtmlValue>;
7
+ export declare const html: {
8
+ (strings: TemplateStringsArray, ...values: Array<HtmlValue>): HtmlString;
9
+ raw(value: string): HtmlString;
10
+ };
11
+ export {};
@@ -0,0 +1,30 @@
1
+ const HtmlStringSymbol = Symbol.for("HtmlString");
2
+ const makeHtmlString = (value) => ({
3
+ [HtmlStringSymbol]: true,
4
+ value,
5
+ });
6
+ const isHtmlString = (value) => typeof value === "object" && value !== null && HtmlStringSymbol in value;
7
+ const resolveValue = (value) => {
8
+ if (value === null || value === undefined || value === false || value === true)
9
+ return "";
10
+ if (isHtmlString(value))
11
+ return value.value;
12
+ if (Array.isArray(value))
13
+ return value.map(resolveValue).join("");
14
+ if (typeof value === "function")
15
+ return value.toString();
16
+ if (typeof value === "object")
17
+ return JSON.stringify(value);
18
+ if (typeof value === "string")
19
+ return value;
20
+ return String(value);
21
+ };
22
+ export const html = (strings, ...values) => {
23
+ let result = strings[0];
24
+ for (let i = 0; i < values.length; i++) {
25
+ result += resolveValue(values[i]);
26
+ result += strings[i + 1];
27
+ }
28
+ return makeHtmlString(result);
29
+ };
30
+ html.raw = (value) => makeHtmlString(value);
@@ -1,4 +1,6 @@
1
1
  export * as Hyper from "./Hyper.ts";
2
+ export { html } from "./html.ts";
3
+ export type { HtmlString, HtmlValue } from "./html.ts";
2
4
  export * as HyperHtml from "./HyperHtml.ts";
3
5
  export * as HyperNode from "./HyperNode.ts";
4
6
  export * as HyperRoute from "./HyperRoute.ts";
@@ -1,4 +1,5 @@
1
1
  export * as Hyper from "./Hyper.js";
2
+ export { html } from "./html.js";
2
3
  export * as HyperHtml from "./HyperHtml.js";
3
4
  export * as HyperNode from "./HyperNode.js";
4
5
  export * as HyperRoute from "./HyperRoute.js";
@@ -4,4 +4,4 @@ declare function Fragment(props: {
4
4
  children: JSX.Element;
5
5
  }): HyperNode.HyperNode;
6
6
  declare function jsx<T extends HyperNode.Type>(type: T, props: T extends string ? HyperNode.Props : T extends (props: infer P) => any ? P : never): HyperNode.HyperNode;
7
- export { Fragment, type JSX, jsx, jsx as jsxDEV, jsx as jsxs, };
7
+ export { Fragment, type JSX, jsx, jsx as jsxDEV, jsx as jsxs };
@@ -5,4 +5,4 @@ function Fragment(props) {
5
5
  function jsx(type, props) {
6
6
  return HyperNode.make(type, props);
7
7
  }
8
- export { Fragment, jsx, jsx as jsxDEV, jsx as jsxs, };
8
+ export { Fragment, jsx, jsx as jsxDEV, jsx as jsxs };
package/dist/index.d.ts CHANGED
@@ -4,4 +4,5 @@ export * as Entity from "./Entity.ts";
4
4
  export * as FileRouter from "./FileRouter.ts";
5
5
  export * as Route from "./Route.ts";
6
6
  export * as Start from "./Start.ts";
7
+ export * as System from "./System.ts";
7
8
  export * as Unique from "./Unique.ts";
package/dist/index.js CHANGED
@@ -4,4 +4,5 @@ export * as Entity from "./Entity.js";
4
4
  export * as FileRouter from "./FileRouter.js";
5
5
  export * as Route from "./Route.js";
6
6
  export * as Start from "./Start.js";
7
+ export * as System from "./System.js";
7
8
  export * as Unique from "./Unique.js";
@@ -0,0 +1,86 @@
1
+ declare namespace _default {
2
+ namespace meta {
3
+ let name: string;
4
+ let version: string;
5
+ }
6
+ let rules: {
7
+ "prefer-namespace-import": {
8
+ meta: {
9
+ type: string;
10
+ docs: {
11
+ description: string;
12
+ };
13
+ fixable: string;
14
+ hasSuggestions: boolean;
15
+ schema: never[];
16
+ messages: {
17
+ preferNamespace: string;
18
+ };
19
+ };
20
+ create(context: any): {
21
+ ImportDeclaration(node: any): void;
22
+ };
23
+ };
24
+ "test-space-around": {
25
+ meta: {
26
+ type: string;
27
+ docs: {
28
+ description: string;
29
+ };
30
+ fixable: string;
31
+ schema: never[];
32
+ messages: {
33
+ requireBlankBefore: string;
34
+ requireBlankAfter: string;
35
+ };
36
+ };
37
+ create(context: any): {
38
+ Program?: undefined;
39
+ BlockStatement?: undefined;
40
+ } | {
41
+ Program(node: any): void;
42
+ BlockStatement(node: any): void;
43
+ };
44
+ };
45
+ "export-default-before-functions": {
46
+ meta: {
47
+ type: string;
48
+ docs: {
49
+ description: string;
50
+ };
51
+ schema: never[];
52
+ messages: {
53
+ defaultAfterFunction: string;
54
+ };
55
+ };
56
+ create(context: any): {
57
+ Program(node: any): void;
58
+ };
59
+ };
60
+ "test-assertion-newline": {
61
+ meta: {
62
+ type: string;
63
+ docs: {
64
+ description: string;
65
+ };
66
+ fixable: string;
67
+ schema: never[];
68
+ messages: {
69
+ requireNewline: string;
70
+ requireBlankBefore: string;
71
+ requireBlankAfter: string;
72
+ };
73
+ };
74
+ create(context: any): {
75
+ ExpressionStatement?: undefined;
76
+ Program?: undefined;
77
+ BlockStatement?: undefined;
78
+ } | {
79
+ ExpressionStatement(node: any): void;
80
+ Program(node: any): void;
81
+ BlockStatement(node: any): void;
82
+ };
83
+ };
84
+ };
85
+ }
86
+ export default _default;