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,223 @@
1
+ import * as Effect from "effect/Effect"
2
+ import * as Exit from "effect/Exit"
3
+ import * as FiberRef from "effect/FiberRef"
4
+ import * as GlobalValue from "effect/GlobalValue"
5
+ import * as Layer from "effect/Layer"
6
+ import * as Option from "effect/Option"
7
+ import type * as Mssql from "mssql"
8
+ import * as Sql from "../../Sql.ts"
9
+
10
+ export interface MssqlConfig {
11
+ readonly server: string
12
+ readonly database?: string
13
+ readonly user?: string
14
+ readonly password?: string
15
+ readonly port?: number
16
+ readonly pool?: {
17
+ readonly max?: number
18
+ readonly min?: number
19
+ readonly idleTimeoutMillis?: number
20
+ }
21
+ readonly options?: {
22
+ readonly encrypt?: boolean
23
+ readonly trustServerCertificate?: boolean
24
+ readonly requestTimeout?: number
25
+ readonly connectionTimeout?: number
26
+ }
27
+ }
28
+
29
+ const wrapError = (error: unknown): Sql.SqlError =>
30
+ new Sql.SqlError({
31
+ code:
32
+ (error as any)?.code ??
33
+ ((error as any)?.number != null ? String((error as any).number) : "UNKNOWN"),
34
+ message: error instanceof Error ? error.message : String(error),
35
+ cause: error,
36
+ })
37
+
38
+ const makeValues: Sql.SqlQuery["values"] = (obj: any, ...columns: Array<string>) => {
39
+ const items = Array.isArray(obj) ? obj : [obj]
40
+ const cols = columns.length > 0 ? columns : Object.keys(items[0])
41
+ return { value: items, columns: cols }
42
+ }
43
+
44
+ const buildQuery = (strings: TemplateStringsArray, values: Array<unknown>) => {
45
+ let text = strings[0]
46
+ for (let i = 0; i < values.length; i++) text += `@p${i + 1}` + strings[i + 1]
47
+ return { text, values }
48
+ }
49
+
50
+ const addInputs = (request: Mssql.Request, values: Array<unknown>) => {
51
+ for (let i = 0; i < values.length; i++) {
52
+ request.input(`p${i + 1}`, values[i])
53
+ }
54
+ }
55
+
56
+ interface TxState {
57
+ readonly transaction: Mssql.Transaction
58
+ readonly depth: number
59
+ }
60
+
61
+ type MssqlModule = {
62
+ ConnectionPool: new (config: Mssql.config) => Mssql.ConnectionPool
63
+ }
64
+
65
+ const loadMssql = () => import("mssql") as Promise<MssqlModule>
66
+
67
+ const currentTransaction = GlobalValue.globalValue(
68
+ Symbol.for("effect-start/sql/mssql/currentTransaction"),
69
+ () => FiberRef.unsafeMake<Option.Option<TxState>>(Option.none()),
70
+ )
71
+
72
+ const executeQuery = <T>(
73
+ pool: Mssql.ConnectionPool,
74
+ text: string,
75
+ values: Array<unknown>,
76
+ ): Effect.Effect<ReadonlyArray<T>, Sql.SqlError> =>
77
+ Effect.flatMap(FiberRef.get(currentTransaction), (txOpt) => {
78
+ const request = Option.isSome(txOpt) ? txOpt.value.transaction.request() : pool.request()
79
+ addInputs(request, values)
80
+ return Effect.tryPromise({
81
+ try: () => request.query<T>(text),
82
+ catch: wrapError,
83
+ }).pipe(Effect.map((result) => result.recordset ?? []))
84
+ })
85
+
86
+ const runQuery = <T>(
87
+ pool: Mssql.ConnectionPool,
88
+ strings: TemplateStringsArray,
89
+ values: Array<unknown>,
90
+ ): Effect.Effect<ReadonlyArray<T>, Sql.SqlError> => {
91
+ const { text, values: params } = buildQuery(strings, values)
92
+ return executeQuery(pool, text, params)
93
+ }
94
+
95
+ const runUnsafe = <T>(
96
+ pool: Mssql.ConnectionPool,
97
+ query: string,
98
+ values?: Array<unknown>,
99
+ ): Effect.Effect<ReadonlyArray<T>, Sql.SqlError> =>
100
+ Effect.flatMap(FiberRef.get(currentTransaction), (txOpt) => {
101
+ const request = Option.isSome(txOpt) ? txOpt.value.transaction.request() : pool.request()
102
+ if (values) addInputs(request, values)
103
+ return Effect.tryPromise({
104
+ try: () => request.query<T>(query),
105
+ catch: wrapError,
106
+ }).pipe(Effect.map((result) => result.recordset ?? []))
107
+ })
108
+
109
+ const makeWithTransaction =
110
+ (pool: Mssql.ConnectionPool) =>
111
+ <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, Sql.SqlError | E, R> =>
112
+ Effect.uninterruptibleMask((restore) =>
113
+ Effect.flatMap(FiberRef.get(currentTransaction), (txOpt) => {
114
+ if (Option.isSome(txOpt)) {
115
+ const { transaction, depth } = txOpt.value
116
+ const name = `sp_${depth}`
117
+ return Effect.gen(function* () {
118
+ const req = transaction.request()
119
+ yield* Effect.tryPromise({
120
+ try: () => req.query(`SAVE TRANSACTION ${name}`),
121
+ catch: wrapError,
122
+ })
123
+ const exit = yield* Effect.exit(
124
+ restore(
125
+ Effect.locally(
126
+ self,
127
+ currentTransaction,
128
+ Option.some({ transaction, depth: depth + 1 }),
129
+ ),
130
+ ),
131
+ )
132
+ if (Exit.isSuccess(exit)) {
133
+ return exit.value
134
+ }
135
+ const rbReq = transaction.request()
136
+ yield* Effect.tryPromise({
137
+ try: () => rbReq.query(`ROLLBACK TRANSACTION ${name}`),
138
+ catch: wrapError,
139
+ }).pipe(Effect.orDie)
140
+ return yield* exit
141
+ })
142
+ }
143
+
144
+ return Effect.gen(function* () {
145
+ const transaction = pool.transaction()
146
+ yield* Effect.tryPromise({ try: () => transaction.begin(), catch: wrapError })
147
+ const exit = yield* Effect.exit(
148
+ restore(
149
+ Effect.locally(self, currentTransaction, Option.some({ transaction, depth: 1 })),
150
+ ),
151
+ )
152
+ if (Exit.isSuccess(exit)) {
153
+ yield* Effect.tryPromise({ try: () => transaction.commit(), catch: wrapError })
154
+ return exit.value
155
+ }
156
+ yield* Effect.tryPromise({ try: () => transaction.rollback(), catch: wrapError }).pipe(
157
+ Effect.orDie,
158
+ )
159
+ return yield* exit
160
+ })
161
+ }),
162
+ )
163
+
164
+ export const layer = (config: MssqlConfig): Layer.Layer<Sql.SqlClient, Sql.SqlError> =>
165
+ Layer.scoped(
166
+ Sql.SqlClient,
167
+ Effect.acquireRelease(
168
+ Effect.tryPromise({
169
+ try: async () => {
170
+ const mssql = await loadMssql()
171
+ const pool = await new mssql.ConnectionPool(config as Mssql.config).connect()
172
+ return { mssql, pool }
173
+ },
174
+ catch: wrapError,
175
+ }).pipe(
176
+ Effect.map(({ mssql, pool }) => {
177
+ const use: Sql.SqlClient["use"] = (fn) =>
178
+ Effect.tryPromise({ try: () => Promise.resolve(fn(pool)), catch: wrapError })
179
+ return Object.assign(
180
+ <T = any>(strings: TemplateStringsArray, ...values: Array<unknown>) =>
181
+ runQuery<T>(pool, strings, values),
182
+ {
183
+ unsafe: <T = any>(query: string, values?: Array<unknown>) =>
184
+ runUnsafe<T>(pool, query, values),
185
+ values: makeValues,
186
+ withTransaction: makeWithTransaction(pool),
187
+ reserve: Effect.acquireRelease(
188
+ Effect.tryPromise({
189
+ try: () =>
190
+ new mssql.ConnectionPool({
191
+ ...config,
192
+ pool: { max: 1, min: 1 },
193
+ } as Mssql.config).connect(),
194
+ catch: wrapError,
195
+ }),
196
+ (reserved: Mssql.ConnectionPool) =>
197
+ Effect.tryPromise({ try: () => reserved.close(), catch: () => void 0 }).pipe(
198
+ Effect.asVoid,
199
+ Effect.orDie,
200
+ ),
201
+ ).pipe(
202
+ Effect.map(
203
+ (reserved): Sql.SqlQuery =>
204
+ Object.assign(
205
+ <T = any>(strings: TemplateStringsArray, ...values: Array<unknown>) =>
206
+ runQuery<T>(reserved, strings, values),
207
+ {
208
+ unsafe: <T = any>(query: string, values?: Array<unknown>) =>
209
+ runUnsafe<T>(reserved, query, values),
210
+ values: makeValues,
211
+ },
212
+ ),
213
+ ),
214
+ ),
215
+ close: () => use((pool) => pool.close()),
216
+ use,
217
+ },
218
+ ) satisfies Sql.SqlClient
219
+ }),
220
+ ),
221
+ (client) => client.close().pipe(Effect.orDie),
222
+ ),
223
+ )
@@ -0,0 +1,41 @@
1
+ declare module "mssql" {
2
+ export interface config {
3
+ readonly server: string
4
+ readonly database?: string
5
+ readonly user?: string
6
+ readonly password?: string
7
+ readonly port?: number
8
+ readonly pool?: {
9
+ readonly max?: number
10
+ readonly min?: number
11
+ readonly idleTimeoutMillis?: number
12
+ }
13
+ readonly options?: {
14
+ readonly encrypt?: boolean
15
+ readonly trustServerCertificate?: boolean
16
+ readonly requestTimeout?: number
17
+ readonly connectionTimeout?: number
18
+ readonly connectTimeout?: number
19
+ }
20
+ }
21
+
22
+ export class ConnectionPool {
23
+ constructor(config: config)
24
+ connect(): Promise<ConnectionPool>
25
+ close(): Promise<void>
26
+ request(): Request
27
+ transaction(): Transaction
28
+ }
29
+
30
+ export class Request {
31
+ input(name: string, value: unknown): Request
32
+ query<T>(query: string): Promise<{ recordset?: ReadonlyArray<T> }>
33
+ }
34
+
35
+ export class Transaction {
36
+ begin(): Promise<void>
37
+ commit(): Promise<void>
38
+ rollback(): Promise<void>
39
+ request(): Request
40
+ }
41
+ }
@@ -1,19 +1,5 @@
1
- import {
2
- Config,
3
- Data,
4
- Effect,
5
- identity,
6
- Layer,
7
- LogLevel,
8
- Option,
9
- pipe,
10
- Stream,
11
- String,
12
- } from "effect"
13
-
14
- export class CloudflareTunnelSpawnError extends Data.TaggedError("CloudflareTunnelSpawnError")<{
15
- cause: unknown
16
- }> {}
1
+ import * as System from "../../System.ts"
2
+ import { Config, Effect, Layer, LogLevel, Option, pipe, Stream, String } from "effect"
17
3
 
18
4
  export const start = (opts: {
19
5
  command?: string
@@ -24,6 +10,8 @@ export const start = (opts: {
24
10
  logPrefix?: string
25
11
  }) =>
26
12
  Effect.gen(function* () {
13
+ const command = opts.command ?? "cloudflared"
14
+ yield* System.which(command)
27
15
  const logPrefix = String.isString(opts.logPrefix) ? opts.logPrefix : "CloudflareTunnel: "
28
16
  const args: Array<string> = [
29
17
  "tunnel",
@@ -32,20 +20,7 @@ export const start = (opts: {
32
20
  opts.tunnelName,
33
21
  ].flatMap((v) => v)
34
22
 
35
- const proc = yield* Effect.try({
36
- try: () =>
37
- Bun.spawn([opts.command ?? "cloudflared", ...args], {
38
- stderr: "pipe",
39
- stdout: "pipe",
40
- }),
41
- catch: (err) => new CloudflareTunnelSpawnError({ cause: err }),
42
- })
43
-
44
- yield* Effect.addFinalizer(() =>
45
- Effect.sync(() => {
46
- proc.kill()
47
- }),
48
- )
23
+ const proc = yield* System.spawn(command, args)
49
24
 
50
25
  yield* Effect.logInfo(
51
26
  `Cloudflare tunnel started name=${opts.tunnelName} pid=${proc.pid} tunnelUrl=${
@@ -54,16 +29,13 @@ export const start = (opts: {
54
29
  )
55
30
 
56
31
  yield* pipe(
57
- Stream.merge(
58
- Stream.fromReadableStream(() => proc.stdout, identity),
59
- Stream.fromReadableStream(() => proc.stderr, identity),
60
- ),
32
+ Stream.merge(proc.stdout, proc.stderr),
61
33
  Stream.decodeText("utf-8"),
62
34
  Stream.splitLines,
63
35
  (opts.cleanLogs ?? true)
64
36
  ? Stream.map((v) => v.replace(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z\s\w+\s/, ""))
65
- : identity,
66
- logPrefix ? Stream.map((v) => logPrefix + v) : identity,
37
+ : (s) => s,
38
+ logPrefix ? Stream.map((v) => logPrefix + v) : (s) => s,
67
39
  Stream.runForEach((v) => Effect.logWithLevel(opts.logLevel ?? LogLevel.Debug, v)),
68
40
  )
69
41
  })
@@ -0,0 +1,113 @@
1
+ import * as BunServer from "../../bun/BunServer.ts"
2
+ import * as PlatformError from "../../PlatformError.ts"
3
+ import * as System from "../../System.ts"
4
+ import * as Effect from "effect/Effect"
5
+ import * as Layer from "effect/Layer"
6
+ import * as LogLevel from "effect/LogLevel"
7
+ import * as Stream from "effect/Stream"
8
+ import * as Function from "effect/Function"
9
+
10
+ interface TailscaleStatus {
11
+ readonly BackendState: string
12
+ readonly Self?: {
13
+ readonly DNSName?: string
14
+ readonly TailscaleIPs?: ReadonlyArray<string>
15
+ }
16
+ }
17
+
18
+ const getStatus = (command: string) =>
19
+ Effect.gen(function* () {
20
+ const proc = yield* System.spawn(command, ["status", "--json"])
21
+ const exitCode = yield* proc.exitCode
22
+
23
+ if (exitCode !== 0) {
24
+ const stderr = yield* proc.stderr.pipe(Stream.decodeText("utf-8"), Stream.mkString)
25
+ return yield* new PlatformError.SystemError({
26
+ reason: "Unknown",
27
+ module: "TailscaleTunnel",
28
+ method: "getStatus",
29
+ description: `tailscale status exited with code ${exitCode}: ${stderr}`,
30
+ })
31
+ }
32
+
33
+ const stdout = yield* proc.stdout.pipe(Stream.decodeText("utf-8"), Stream.mkString)
34
+ const json: TailscaleStatus = JSON.parse(stdout)
35
+
36
+ if (json.BackendState !== "Running") {
37
+ return yield* new PlatformError.SystemError({
38
+ reason: "Unknown",
39
+ module: "TailscaleTunnel",
40
+ method: "getStatus",
41
+ description: `tailscale is in state "${json.BackendState}", expected "Running"`,
42
+ })
43
+ }
44
+
45
+ return json
46
+ })
47
+
48
+ const serve = (opts: {
49
+ command: string
50
+ port: number
51
+ dnsName?: string
52
+ public?: boolean
53
+ logLevel?: LogLevel.LogLevel
54
+ logPrefix?: string
55
+ }) =>
56
+ Effect.gen(function* () {
57
+ const logPrefix = opts.logPrefix ?? "TailscaleTunnel: "
58
+ const args = [opts.public ? "funnel" : "serve", String(opts.port)]
59
+
60
+ const proc = yield* System.spawn(opts.command, args)
61
+
62
+ yield* Function.pipe(
63
+ Stream.merge(proc.stdout, proc.stderr),
64
+ Stream.decodeText("utf-8"),
65
+ Stream.splitLines,
66
+ logPrefix ? Stream.map((v) => logPrefix + v) : (s) => s,
67
+ Stream.runForEach((v) => Effect.logWithLevel(opts.logLevel ?? LogLevel.Debug, v)),
68
+ )
69
+ })
70
+
71
+ export const start = (opts: {
72
+ command?: string
73
+ port: number
74
+ public?: boolean
75
+ logLevel?: LogLevel.LogLevel
76
+ logPrefix?: string
77
+ }) =>
78
+ Effect.gen(function* () {
79
+ const command = opts.command ?? "tailscale"
80
+ yield* System.which(command)
81
+ const status = yield* getStatus(command)
82
+ const dnsName = status.Self?.DNSName?.replace(/\.$/, "")
83
+ yield* serve({ ...opts, command, dnsName })
84
+ })
85
+
86
+ export const layer = (opts?: { public?: boolean }) =>
87
+ Layer.scopedDiscard(
88
+ Effect.gen(function* () {
89
+ const { server } = yield* BunServer.BunServer
90
+ const port = server.port!
91
+ const command = "tailscale"
92
+
93
+ yield* Effect.forkScoped(
94
+ Effect.gen(function* () {
95
+ yield* System.which(command)
96
+ const status = yield* getStatus(command)
97
+ const dnsName = status.Self?.DNSName?.replace(/\.$/, "")
98
+
99
+ const serveUrl = dnsName ? `https://${dnsName}` : undefined
100
+ yield* Effect.logInfo(
101
+ `Tailscale ${opts?.public ? "funnel" : "serve"}${serveUrl ? ` url=${serveUrl}` : ""}`,
102
+ )
103
+
104
+ yield* serve({
105
+ command,
106
+ port,
107
+ dnsName,
108
+ public: opts?.public,
109
+ })
110
+ }).pipe(Effect.tapError((e) => Effect.logError(`Tailscale: ${e.description}`))),
111
+ )
112
+ }),
113
+ )
@@ -0,0 +1 @@
1
+ export * as TailscaleTunnel from "./TailscaleTunnel.ts"
@@ -1,61 +0,0 @@
1
- import type * as HyperNode from "../../hyper/HyperNode.ts"
2
-
3
- export const HyperHooks = {
4
- onNode,
5
- } as const
6
-
7
- function onNode(node: HyperNode.HyperNode) {
8
- const {
9
- "data-signals": dataSignals,
10
- "data-class": dataClass,
11
- "data-attr": dataAttr,
12
- "data-style": dataStyle,
13
- "data-show": dataShow,
14
- "data-ignore": dataIgnore,
15
- "data-ignore-morph": dataIgnoreMorph,
16
- } = node.props as any
17
-
18
- if (typeof dataSignals === "object" && dataSignals !== null) {
19
- node.props["data-signals"] = JSON.stringify(dataSignals)
20
- }
21
-
22
- if (typeof dataClass === "function") {
23
- node.props["data-class"] = `(${dataClass.toString()})()`
24
- } else if (typeof dataClass === "object" && dataClass !== null) {
25
- node.props["data-class"] = JSON.stringify(dataClass)
26
- }
27
-
28
- if (typeof dataAttr === "object" && dataAttr !== null) {
29
- node.props["data-attr"] = JSON.stringify(dataAttr)
30
- }
31
-
32
- if (typeof dataStyle === "function") {
33
- node.props["data-style"] = `(${dataStyle.toString()})()`
34
- } else if (typeof dataStyle === "object" && dataStyle !== null) {
35
- node.props["data-style"] = JSON.stringify(dataStyle)
36
- }
37
-
38
- if (typeof dataShow === "boolean") {
39
- node.props["data-show"] = dataShow.toString()
40
- }
41
-
42
- if (dataIgnore !== true && dataIgnore !== undefined) {
43
- delete node.props["data-ignore"]
44
- }
45
-
46
- if (dataIgnoreMorph !== true && dataIgnoreMorph !== undefined) {
47
- delete node.props["data-ignore-morph"]
48
- }
49
-
50
- // Handle dynamic attributes with suffixes
51
- for (const [key, value] of Object.entries(node.props)) {
52
- if (key.startsWith("data-signals-") && typeof value === "object" && value !== null) {
53
- node.props[key] = JSON.stringify(value)
54
- }
55
-
56
- if (key.startsWith("data-on-") && typeof value === "function") {
57
- // @ts-ignore
58
- node.props[key] = `(${value.toString()})()`
59
- }
60
- }
61
- }
@@ -1,2 +0,0 @@
1
- export * as Datastar from "./Datastar.ts"
2
- export { HyperHooks } from "./Datastar.ts"
@@ -1,60 +0,0 @@
1
- // Datastar object types for specific attributes
2
- type DatastarSignalsObject = Record<string, any>
3
- type DatastarClassObject = Record<string, boolean | string>
4
- type DatastarAttrObject = Record<string, string | boolean | number>
5
- type DatastarStyleObject = Record<string, string | number | boolean | null | undefined>
6
-
7
- /**
8
- * Datastar attributes for reactive web applications
9
- * @see https://data-star.dev/reference/attributes
10
- */
11
- export interface DatastarAttributes {
12
- // Core attributes that can accept objects (but also strings)
13
- "data-signals"?: string | DatastarSignalsObject | undefined
14
- "data-class"?: string | DatastarClassObject | undefined
15
- "data-attr"?: string | DatastarAttrObject | undefined
16
- "data-style"?: Function | string | DatastarStyleObject | undefined
17
-
18
- // Boolean/presence attributes (but also strings)
19
- "data-show"?: string | boolean | undefined
20
- "data-ignore"?: string | boolean | undefined
21
- "data-ignore-morph"?: string | boolean | undefined
22
-
23
- // All other Datastar attributes as strings only
24
- "data-bind"?: string | undefined
25
- "data-computed"?: string | undefined
26
- "data-effect"?: string | undefined
27
- "data-indicator"?: string | undefined
28
- "data-json-signals"?: string | undefined
29
- "data-on"?: string | undefined
30
- "data-on-intersect"?: string | undefined
31
- "data-on-interval"?: string | undefined
32
- "data-on-load"?: string | undefined
33
- "data-on-signal-patch"?: string | undefined
34
- "data-on-signal-patch-filter"?: string | undefined
35
- "data-preserve-attr"?: string | undefined
36
- "data-ref"?: string | undefined
37
- "data-text"?: string | undefined
38
-
39
- // Pro attributes (strings only)
40
- "data-animate"?: string | undefined
41
- "data-custom-validity"?: string | undefined
42
- "data-on-raf"?: string | undefined
43
- "data-on-resize"?: string | undefined
44
- "data-persist"?: string | undefined
45
- "data-query-string"?: string | undefined
46
- "data-replace-url"?: string | undefined
47
- "data-scroll-into-view"?: string | undefined
48
- "data-view-transition"?: string | undefined
49
-
50
- // Dynamic attributes with suffixes
51
- [key: `data-signals-${string}`]: string | undefined
52
- [key: `data-class-${string}`]: string | undefined
53
- [key: `data-attr-${string}`]: string | undefined
54
- [key: `data-style-${string}`]: string | undefined
55
- [key: `data-bind-${string}`]: string | undefined
56
- [key: `data-computed-${string}`]: string | undefined
57
- [key: `data-indicator-${string}`]: string | undefined
58
- [key: `data-ref-${string}`]: string | undefined
59
- [key: `data-on-${string}`]: Function | string | undefined
60
- }