effect-start 0.25.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +20 -86
- package/src/Entity.ts +6 -6
- package/src/FileRouterCodegen.ts +4 -4
- package/src/FileSystem.ts +4 -8
- package/src/RouteHook.ts +1 -1
- package/src/RouteSse.ts +3 -3
- package/src/SqlIntrospect.ts +2 -2
- package/src/Start.ts +102 -2
- package/src/Values.ts +11 -0
- package/src/bun/BunRoute.ts +1 -1
- package/src/bun/BunRuntime.ts +5 -5
- package/src/hyper/HyperHtml.ts +11 -7
- package/src/hyper/jsx.d.ts +1 -1
- package/src/lint/plugin.js +174 -4
- package/src/sql/SqlClient.ts +355 -0
- package/src/sql/bun/index.ts +117 -50
- package/src/sql/index.ts +1 -1
- package/src/sql/libsql/index.ts +91 -77
- package/src/sql/libsql/libsql.d.ts +4 -1
- package/src/sql/mssql/index.ts +141 -108
- package/src/sql/mssql/mssql.d.ts +1 -0
- package/src/testing/TestLogger.ts +4 -4
- package/src/x/tailwind/compile.ts +6 -14
- package/dist/ChildProcess.js +0 -42
- package/dist/Commander.js +0 -410
- package/dist/ContentNegotiation.js +0 -465
- package/dist/Cookies.js +0 -371
- package/dist/Development.js +0 -94
- package/dist/Effectify.js +0 -27
- package/dist/Entity.js +0 -289
- package/dist/Fetch.js +0 -192
- package/dist/FilePathPattern.js +0 -97
- package/dist/FileRouter.js +0 -204
- package/dist/FileRouterCodegen.js +0 -298
- package/dist/FileSystem.js +0 -132
- package/dist/Http.js +0 -107
- package/dist/PathPattern.js +0 -451
- package/dist/PlatformError.js +0 -40
- package/dist/PlatformRuntime.js +0 -71
- package/dist/Route.js +0 -143
- package/dist/RouteBody.js +0 -92
- package/dist/RouteError.js +0 -76
- package/dist/RouteHook.js +0 -64
- package/dist/RouteHttp.js +0 -367
- package/dist/RouteHttpTracer.js +0 -90
- package/dist/RouteMount.js +0 -86
- package/dist/RouteSchema.js +0 -271
- package/dist/RouteSse.js +0 -94
- package/dist/RouteTree.js +0 -119
- package/dist/RouteTrie.js +0 -179
- package/dist/SchemaExtra.js +0 -99
- package/dist/Socket.js +0 -40
- package/dist/SqlIntrospect.js +0 -515
- package/dist/Start.js +0 -79
- package/dist/StartApp.js +0 -3
- package/dist/StreamExtra.js +0 -135
- package/dist/System.js +0 -38
- package/dist/TuplePathPattern.js +0 -74
- package/dist/Unique.js +0 -226
- package/dist/Values.js +0 -52
- package/dist/bun/BunBundle.js +0 -186
- package/dist/bun/BunChildProcessSpawner.js +0 -142
- package/dist/bun/BunImportTrackerPlugin.js +0 -91
- package/dist/bun/BunRoute.js +0 -157
- package/dist/bun/BunRuntime.js +0 -41
- package/dist/bun/BunServer.js +0 -285
- package/dist/bun/BunVirtualFilesPlugin.js +0 -54
- package/dist/bun/_BunEnhancedResolve.js +0 -127
- package/dist/bun/index.js +0 -5
- package/dist/bundler/Bundle.js +0 -92
- package/dist/bundler/BundleFiles.js +0 -154
- package/dist/bundler/BundleRoute.js +0 -62
- package/dist/client/Overlay.js +0 -33
- package/dist/client/ScrollState.js +0 -106
- package/dist/client/index.js +0 -97
- package/dist/console/Console.js +0 -42
- package/dist/console/ConsoleErrors.js +0 -211
- package/dist/console/ConsoleLogger.js +0 -56
- package/dist/console/ConsoleMetrics.js +0 -72
- package/dist/console/ConsoleProcess.js +0 -59
- package/dist/console/ConsoleStore.js +0 -72
- package/dist/console/ConsoleTracer.js +0 -107
- package/dist/console/Simulation.js +0 -784
- package/dist/console/index.js +0 -3
- package/dist/console/routes/tree.js +0 -30
- package/dist/datastar/actions/fetch.js +0 -536
- package/dist/datastar/actions/peek.js +0 -13
- package/dist/datastar/actions/setAll.js +0 -19
- package/dist/datastar/actions/toggleAll.js +0 -19
- package/dist/datastar/attributes/attr.js +0 -49
- package/dist/datastar/attributes/bind.js +0 -194
- package/dist/datastar/attributes/class.js +0 -54
- package/dist/datastar/attributes/computed.js +0 -25
- package/dist/datastar/attributes/effect.js +0 -10
- package/dist/datastar/attributes/indicator.js +0 -33
- package/dist/datastar/attributes/init.js +0 -27
- package/dist/datastar/attributes/jsonSignals.js +0 -33
- package/dist/datastar/attributes/on.js +0 -81
- package/dist/datastar/attributes/onIntersect.js +0 -53
- package/dist/datastar/attributes/onInterval.js +0 -31
- package/dist/datastar/attributes/onSignalPatch.js +0 -51
- package/dist/datastar/attributes/ref.js +0 -11
- package/dist/datastar/attributes/show.js +0 -32
- package/dist/datastar/attributes/signals.js +0 -18
- package/dist/datastar/attributes/style.js +0 -57
- package/dist/datastar/attributes/text.js +0 -29
- package/dist/datastar/engine.js +0 -1145
- package/dist/datastar/index.js +0 -25
- package/dist/datastar/utils.js +0 -250
- package/dist/datastar/watchers/patchElements.js +0 -486
- package/dist/datastar/watchers/patchSignals.js +0 -14
- package/dist/experimental/EncryptedCookies.js +0 -328
- package/dist/experimental/index.js +0 -1
- package/dist/hyper/Hyper.js +0 -28
- package/dist/hyper/HyperHtml.js +0 -165
- package/dist/hyper/HyperNode.js +0 -13
- package/dist/hyper/HyperRoute.js +0 -45
- package/dist/hyper/html.js +0 -30
- package/dist/hyper/index.js +0 -5
- package/dist/hyper/jsx-runtime.js +0 -14
- package/dist/index.js +0 -8
- package/dist/node/NodeFileSystem.js +0 -675
- package/dist/node/NodeUtils.js +0 -23
- package/dist/sql/Sql.js +0 -8
- package/dist/sql/bun/index.js +0 -142
- package/dist/sql/index.js +0 -1
- package/dist/sql/libsql/index.js +0 -156
- package/dist/sql/mssql/docker.js +0 -110
- package/dist/sql/mssql/index.js +0 -194
- package/dist/testing/TestLogger.js +0 -42
- package/dist/testing/index.js +0 -2
- package/dist/testing/utils.js +0 -61
- package/dist/x/cloudflare/CloudflareTunnel.js +0 -63
- package/dist/x/cloudflare/index.js +0 -1
- package/dist/x/tailscale/TailscaleTunnel.js +0 -94
- package/dist/x/tailscale/index.js +0 -1
- package/dist/x/tailwind/TailwindPlugin.js +0 -294
- package/dist/x/tailwind/compile.js +0 -210
- package/dist/x/tailwind/plugin.js +0 -17
- package/src/console/Console.ts +0 -42
- package/src/console/ConsoleErrors.ts +0 -213
- package/src/console/ConsoleLogger.ts +0 -56
- package/src/console/ConsoleMetrics.ts +0 -72
- package/src/console/ConsoleProcess.ts +0 -59
- package/src/console/ConsoleStore.ts +0 -187
- package/src/console/ConsoleTracer.ts +0 -107
- package/src/console/Simulation.ts +0 -814
- package/src/console/console.html +0 -340
- package/src/console/index.ts +0 -3
- package/src/console/routes/errors/route.tsx +0 -97
- package/src/console/routes/fiberDetail.tsx +0 -54
- package/src/console/routes/fibers/route.tsx +0 -45
- package/src/console/routes/git/route.tsx +0 -64
- package/src/console/routes/layout.tsx +0 -4
- package/src/console/routes/logs/route.tsx +0 -77
- package/src/console/routes/metrics/route.tsx +0 -36
- package/src/console/routes/route.tsx +0 -8
- package/src/console/routes/routes/route.tsx +0 -30
- package/src/console/routes/services/route.tsx +0 -21
- package/src/console/routes/system/route.tsx +0 -43
- package/src/console/routes/traceDetail.tsx +0 -22
- package/src/console/routes/traces/route.tsx +0 -81
- package/src/console/routes/tree.ts +0 -30
- package/src/console/ui/Errors.tsx +0 -76
- package/src/console/ui/Fibers.tsx +0 -321
- package/src/console/ui/Git.tsx +0 -182
- package/src/console/ui/Logs.tsx +0 -46
- package/src/console/ui/Metrics.tsx +0 -78
- package/src/console/ui/Routes.tsx +0 -125
- package/src/console/ui/Services.tsx +0 -273
- package/src/console/ui/Shell.tsx +0 -62
- package/src/console/ui/System.tsx +0 -131
- package/src/console/ui/Traces.tsx +0 -426
- package/src/sql/Sql.ts +0 -51
package/src/sql/bun/index.ts
CHANGED
|
@@ -4,7 +4,8 @@ import * as FiberRef from "effect/FiberRef"
|
|
|
4
4
|
import * as GlobalValue from "effect/GlobalValue"
|
|
5
5
|
import * as Layer from "effect/Layer"
|
|
6
6
|
import * as Option from "effect/Option"
|
|
7
|
-
import * as Sql from "../
|
|
7
|
+
import * as Sql from "../SqlClient.ts"
|
|
8
|
+
import * as Values from "../../Values.ts"
|
|
8
9
|
|
|
9
10
|
const errorCode = (error: unknown): string => {
|
|
10
11
|
const e = error as any
|
|
@@ -22,20 +23,14 @@ const wrapError = (error: unknown): Sql.SqlError =>
|
|
|
22
23
|
const wrap = <T>(fn: () => PromiseLike<T>): Effect.Effect<T, Sql.SqlError> =>
|
|
23
24
|
Effect.tryPromise({ try: () => Promise.resolve(fn()), catch: wrapError })
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
const items = Array.isArray(obj) ? obj : [obj]
|
|
27
|
-
const cols = columns.length > 0 ? columns : Object.keys(items[0])
|
|
28
|
-
return { value: items, columns: cols }
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
interface TxState {
|
|
26
|
+
interface TransactionConnection {
|
|
32
27
|
readonly conn: any
|
|
33
28
|
readonly depth: number
|
|
34
29
|
}
|
|
35
30
|
|
|
36
31
|
const currentTransaction = GlobalValue.globalValue(
|
|
37
32
|
Symbol.for("effect-start/sql/bun/currentTransaction"),
|
|
38
|
-
() => FiberRef.unsafeMake<Option.Option<
|
|
33
|
+
() => FiberRef.unsafeMake<Option.Option<TransactionConnection>>(Option.none()),
|
|
39
34
|
)
|
|
40
35
|
|
|
41
36
|
const makeRun =
|
|
@@ -45,6 +40,72 @@ const makeRun =
|
|
|
45
40
|
wrap(() => fn(Option.isSome(txOpt) ? txOpt.value.conn : bunSql)),
|
|
46
41
|
)
|
|
47
42
|
|
|
43
|
+
const detectDialect = (bunSql: any): Sql.DialectConfig => {
|
|
44
|
+
const adapter = bunSql?.options?.adapter ?? bunSql?.adapter
|
|
45
|
+
if (adapter === "sqlite") return Sql.sqliteDialect
|
|
46
|
+
return Sql.postgresDialect
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const makeSpanAttributes = (config: ConstructorParameters<typeof Bun.SQL>[0]): Record<string, unknown> => {
|
|
50
|
+
const c = config as Record<string, unknown>
|
|
51
|
+
const adapter = c.adapter
|
|
52
|
+
if (adapter === "sqlite") {
|
|
53
|
+
return Values.compact({
|
|
54
|
+
...(c.spanAttributes as Record<string, unknown> | undefined),
|
|
55
|
+
"db.system.name": "sqlite",
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const parsed = (() => {
|
|
60
|
+
if (typeof c.url !== "string") return undefined
|
|
61
|
+
try {
|
|
62
|
+
return new URL(c.url)
|
|
63
|
+
} catch {
|
|
64
|
+
return undefined
|
|
65
|
+
}
|
|
66
|
+
})()
|
|
67
|
+
const dbFromPath = parsed?.pathname.replace(/^\/+/, "") || undefined
|
|
68
|
+
const parsedPort = parsed?.port ? Number(parsed.port) : undefined
|
|
69
|
+
|
|
70
|
+
return Values.compact({
|
|
71
|
+
...(c.spanAttributes as Record<string, unknown> | undefined),
|
|
72
|
+
"db.system.name": "postgresql",
|
|
73
|
+
"db.namespace": (c.database as string | undefined) ?? dbFromPath,
|
|
74
|
+
"server.address": ((c.hostname ?? c.host) as string | undefined) ?? parsed?.hostname,
|
|
75
|
+
"server.port": (c.port as number | undefined) ?? parsedPort,
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const makeTaggedTemplate = (
|
|
80
|
+
run: <T>(fn: (conn: any) => PromiseLike<T>) => Effect.Effect<T, Sql.SqlError>,
|
|
81
|
+
dialect: Sql.DialectConfig,
|
|
82
|
+
) => {
|
|
83
|
+
const unsafeFn = <T = any>(query: string, values?: Array<unknown>) =>
|
|
84
|
+
run<ReadonlyArray<T>>((conn) => conn.unsafe(query, values))
|
|
85
|
+
|
|
86
|
+
return <T = any>(
|
|
87
|
+
strings: TemplateStringsArray,
|
|
88
|
+
...values: Array<unknown>
|
|
89
|
+
): Effect.Effect<ReadonlyArray<T>, Sql.SqlError> => {
|
|
90
|
+
if (Sql.hasFragments(values)) {
|
|
91
|
+
const compiled = Sql.interpolate(dialect, strings, values)
|
|
92
|
+
return unsafeFn<T>(compiled.sql, compiled.parameters)
|
|
93
|
+
}
|
|
94
|
+
return run<ReadonlyArray<T>>((conn) => conn(strings, ...values))
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const makeQuery = (
|
|
99
|
+
run: <T>(fn: (conn: any) => PromiseLike<T>) => Effect.Effect<T, Sql.SqlError>,
|
|
100
|
+
dialect: Sql.DialectConfig,
|
|
101
|
+
spanAttributes: ReadonlyArray<readonly [string, unknown]>,
|
|
102
|
+
): Sql.Connection => {
|
|
103
|
+
const query = makeTaggedTemplate(run, dialect)
|
|
104
|
+
const unsafe: Sql.Connection["unsafe"] = <T = any>(query: string, values?: Array<unknown>) =>
|
|
105
|
+
run<ReadonlyArray<T>>((conn) => conn.unsafe(query, values))
|
|
106
|
+
return Sql.connection(query, unsafe, { spanAttributes, dialect })
|
|
107
|
+
}
|
|
108
|
+
|
|
48
109
|
const makeWithTransaction =
|
|
49
110
|
(bunSql: any) =>
|
|
50
111
|
<A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, Sql.SqlError | E, R> =>
|
|
@@ -98,50 +159,56 @@ const makeWithTransaction =
|
|
|
98
159
|
)
|
|
99
160
|
|
|
100
161
|
export const layer = (
|
|
101
|
-
config: ConstructorParameters<typeof Bun.SQL>[0]
|
|
162
|
+
config: ConstructorParameters<typeof Bun.SQL>[0] & {
|
|
163
|
+
readonly spanAttributes?: Record<string, unknown>
|
|
164
|
+
},
|
|
102
165
|
): Layer.Layer<Sql.SqlClient, Sql.SqlError> =>
|
|
103
166
|
Layer.scoped(
|
|
104
167
|
Sql.SqlClient,
|
|
105
|
-
Effect.
|
|
106
|
-
Effect.
|
|
107
|
-
try
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
168
|
+
Effect.map(
|
|
169
|
+
Effect.acquireRelease(
|
|
170
|
+
Effect.try({
|
|
171
|
+
try: () => {
|
|
172
|
+
const driverConfig = { ...config } as Record<string, unknown>
|
|
173
|
+
delete driverConfig.spanAttributes
|
|
174
|
+
const bunSql = new Bun.SQL(driverConfig as any)
|
|
175
|
+
const run = makeRun(bunSql)
|
|
176
|
+
const dialect = detectDialect(bunSql)
|
|
177
|
+
const spanAttributes = Object.entries(makeSpanAttributes(config))
|
|
178
|
+
const unsafeFn: Sql.Connection["unsafe"] = <T = any>(
|
|
179
|
+
query: string,
|
|
180
|
+
values?: Array<unknown>,
|
|
181
|
+
) => run<ReadonlyArray<T>>((conn) => conn.unsafe(query, values))
|
|
182
|
+
const query = makeTaggedTemplate(run, dialect)
|
|
183
|
+
const use: Sql.SqlClient["use"] = (fn) =>
|
|
184
|
+
Effect.tryPromise({ try: () => Promise.resolve(fn(bunSql)), catch: wrapError })
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
client: Sql.make({
|
|
188
|
+
query,
|
|
189
|
+
unsafe: unsafeFn,
|
|
190
|
+
withTransaction: makeWithTransaction(bunSql),
|
|
191
|
+
spanAttributes,
|
|
192
|
+
dialect,
|
|
193
|
+
reserve: Effect.acquireRelease(
|
|
194
|
+
wrap(() => bunSql.reserve()),
|
|
195
|
+
(reserved: any) => Effect.sync(() => reserved.release()),
|
|
196
|
+
).pipe(
|
|
197
|
+
Effect.map((reserved: any): Sql.Connection => {
|
|
198
|
+
const reservedRun = <T>(fn: (conn: any) => PromiseLike<T>) =>
|
|
199
|
+
wrap<T>(() => fn(reserved))
|
|
200
|
+
return makeQuery(reservedRun, dialect, spanAttributes)
|
|
201
|
+
}),
|
|
135
202
|
),
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
},
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
(
|
|
203
|
+
use,
|
|
204
|
+
}),
|
|
205
|
+
close: use((bunSql) => bunSql.close()),
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
catch: wrapError,
|
|
209
|
+
}),
|
|
210
|
+
(handle) => handle.close.pipe(Effect.orDie),
|
|
211
|
+
),
|
|
212
|
+
(handle) => handle.client,
|
|
146
213
|
),
|
|
147
214
|
)
|
package/src/sql/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * as
|
|
1
|
+
export * as SqlClient from "./SqlClient.ts"
|
package/src/sql/libsql/index.ts
CHANGED
|
@@ -5,7 +5,8 @@ import * as GlobalValue from "effect/GlobalValue"
|
|
|
5
5
|
import * as Layer from "effect/Layer"
|
|
6
6
|
import * as Option from "effect/Option"
|
|
7
7
|
import type * as Libsql from "@libsql/client"
|
|
8
|
-
import * as Sql from "../
|
|
8
|
+
import * as Sql from "../SqlClient.ts"
|
|
9
|
+
import * as Values from "../../Values.ts"
|
|
9
10
|
|
|
10
11
|
export interface LibsqlConfig {
|
|
11
12
|
readonly url: string
|
|
@@ -13,6 +14,7 @@ export interface LibsqlConfig {
|
|
|
13
14
|
readonly syncUrl?: string
|
|
14
15
|
readonly syncInterval?: number
|
|
15
16
|
readonly encryptionKey?: string
|
|
17
|
+
readonly spanAttributes?: Record<string, unknown>
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
const wrapError = (error: unknown): Sql.SqlError =>
|
|
@@ -25,12 +27,28 @@ const wrapError = (error: unknown): Sql.SqlError =>
|
|
|
25
27
|
const wrap = <T>(fn: () => PromiseLike<T>): Effect.Effect<T, Sql.SqlError> =>
|
|
26
28
|
Effect.tryPromise({ try: () => Promise.resolve(fn()), catch: wrapError })
|
|
27
29
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
30
|
+
const dialect = Sql.sqliteDialect
|
|
31
|
+
const makeSpanAttributes = (config: LibsqlConfig): ReadonlyArray<readonly [string, unknown]> => {
|
|
32
|
+
const parsed = (() => {
|
|
33
|
+
try {
|
|
34
|
+
return new URL(config.url)
|
|
35
|
+
} catch {
|
|
36
|
+
return undefined
|
|
37
|
+
}
|
|
38
|
+
})()
|
|
39
|
+
const dbFromPath = parsed?.pathname.replace(/^\/+/, "") || undefined
|
|
40
|
+
const parsedPort = parsed?.port ? Number(parsed.port) : undefined
|
|
41
|
+
|
|
42
|
+
return Object.entries(
|
|
43
|
+
Values.compact({
|
|
44
|
+
...(config.spanAttributes ?? {}),
|
|
45
|
+
"db.system.name": "sqlite",
|
|
46
|
+
"db.namespace": dbFromPath,
|
|
47
|
+
"server.address": parsed?.hostname,
|
|
48
|
+
"server.port": parsedPort,
|
|
49
|
+
}),
|
|
50
|
+
)
|
|
32
51
|
}
|
|
33
|
-
|
|
34
52
|
const resultSetToRows = <T>(result: Libsql.ResultSet): ReadonlyArray<T> => {
|
|
35
53
|
const { columns, rows } = result
|
|
36
54
|
return rows.map((row) => {
|
|
@@ -40,13 +58,14 @@ const resultSetToRows = <T>(result: Libsql.ResultSet): ReadonlyArray<T> => {
|
|
|
40
58
|
})
|
|
41
59
|
}
|
|
42
60
|
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
61
|
+
const executeQuery = <T>(
|
|
62
|
+
client: Libsql.Client,
|
|
63
|
+
sql: string,
|
|
64
|
+
args: Array<unknown>,
|
|
65
|
+
): Effect.Effect<ReadonlyArray<T>, Sql.SqlError> =>
|
|
66
|
+
wrap(() => client.execute({ sql, args })).pipe(Effect.map(resultSetToRows<T>))
|
|
48
67
|
|
|
49
|
-
interface
|
|
68
|
+
interface TransactionConnection {
|
|
50
69
|
readonly depth: number
|
|
51
70
|
}
|
|
52
71
|
|
|
@@ -58,34 +77,39 @@ const loadLibsql = () => import("@libsql/client") as Promise<LibsqlModule>
|
|
|
58
77
|
|
|
59
78
|
const currentTransaction = GlobalValue.globalValue(
|
|
60
79
|
Symbol.for("effect-start/sql/libsql/currentTransaction"),
|
|
61
|
-
() => FiberRef.unsafeMake<Option.Option<
|
|
80
|
+
() => FiberRef.unsafeMake<Option.Option<TransactionConnection>>(Option.none()),
|
|
62
81
|
)
|
|
63
82
|
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
const exec = (client: Libsql.Client, sql: string) => wrap(() => client.execute(sql))
|
|
84
|
+
|
|
85
|
+
const makeTaggedTemplate = (client: Libsql.Client) => {
|
|
86
|
+
const unsafeFn = <T = any>(query: string, values?: Array<unknown>) =>
|
|
87
|
+
executeQuery<T>(client, query, values ?? [])
|
|
88
|
+
|
|
89
|
+
return <T = any>(
|
|
90
|
+
strings: TemplateStringsArray,
|
|
91
|
+
...values: Array<unknown>
|
|
92
|
+
): Effect.Effect<ReadonlyArray<T>, Sql.SqlError> => {
|
|
93
|
+
if (Sql.hasFragments(values)) {
|
|
94
|
+
const compiled = Sql.interpolate(dialect, strings, values)
|
|
95
|
+
return unsafeFn<T>(compiled.sql, compiled.parameters)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let sqlText = strings[0]
|
|
99
|
+
for (let i = 0; i < values.length; i++) sqlText += "?" + strings[i + 1]
|
|
100
|
+
return executeQuery<T>(client, sqlText, values)
|
|
101
|
+
}
|
|
78
102
|
}
|
|
79
103
|
|
|
80
|
-
const
|
|
104
|
+
const makeQuery = (
|
|
81
105
|
client: Libsql.Client,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
106
|
+
spanAttributes: ReadonlyArray<readonly [string, unknown]>,
|
|
107
|
+
): Sql.Connection => {
|
|
108
|
+
const query = makeTaggedTemplate(client)
|
|
109
|
+
const unsafe: Sql.Connection["unsafe"] = <T = any>(query: string, values?: Array<unknown>) =>
|
|
110
|
+
executeQuery<T>(client, query, values ?? [])
|
|
111
|
+
return Sql.connection(query, unsafe, { spanAttributes, dialect })
|
|
112
|
+
}
|
|
89
113
|
|
|
90
114
|
const makeWithTransaction =
|
|
91
115
|
(client: Libsql.Client) =>
|
|
@@ -98,9 +122,7 @@ const makeWithTransaction =
|
|
|
98
122
|
return Effect.gen(function* () {
|
|
99
123
|
yield* exec(client, `SAVEPOINT ${name}`)
|
|
100
124
|
const exit = yield* Effect.exit(
|
|
101
|
-
restore(
|
|
102
|
-
Effect.locally(self, currentTransaction, Option.some({ depth: depth + 1 })),
|
|
103
|
-
),
|
|
125
|
+
restore(Effect.locally(self, currentTransaction, Option.some({ depth: depth + 1 }))),
|
|
104
126
|
)
|
|
105
127
|
if (Exit.isSuccess(exit)) {
|
|
106
128
|
yield* exec(client, `RELEASE SAVEPOINT ${name}`)
|
|
@@ -129,45 +151,37 @@ const makeWithTransaction =
|
|
|
129
151
|
export const layer = (config: LibsqlConfig): Layer.Layer<Sql.SqlClient, Sql.SqlError> =>
|
|
130
152
|
Layer.scoped(
|
|
131
153
|
Sql.SqlClient,
|
|
132
|
-
Effect.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
<T = any>(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
),
|
|
163
|
-
),
|
|
164
|
-
),
|
|
165
|
-
close: () => Effect.sync(() => client.close()),
|
|
166
|
-
use,
|
|
167
|
-
},
|
|
168
|
-
) satisfies Sql.SqlClient
|
|
169
|
-
}),
|
|
154
|
+
Effect.map(
|
|
155
|
+
Effect.acquireRelease(
|
|
156
|
+
wrap(() => loadLibsql()).pipe(
|
|
157
|
+
Effect.map((libsql) => {
|
|
158
|
+
const client = libsql.createClient(config)
|
|
159
|
+
const spanAttributes = makeSpanAttributes(config)
|
|
160
|
+
const query = makeTaggedTemplate(client)
|
|
161
|
+
const unsafeFn: Sql.Connection["unsafe"] = <T = any>(
|
|
162
|
+
query: string,
|
|
163
|
+
values?: Array<unknown>,
|
|
164
|
+
) => executeQuery<T>(client, query, values ?? [])
|
|
165
|
+
const use: Sql.SqlClient["use"] = (fn) =>
|
|
166
|
+
Effect.tryPromise({ try: () => Promise.resolve(fn(client)), catch: wrapError })
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
client: Sql.make({
|
|
170
|
+
query,
|
|
171
|
+
unsafe: unsafeFn,
|
|
172
|
+
withTransaction: makeWithTransaction(client),
|
|
173
|
+
spanAttributes,
|
|
174
|
+
dialect,
|
|
175
|
+
// libsql has no connection pool — reuse the existing client
|
|
176
|
+
reserve: Effect.succeed(makeQuery(client, spanAttributes)),
|
|
177
|
+
use,
|
|
178
|
+
}),
|
|
179
|
+
close: Effect.sync(() => client.close()),
|
|
180
|
+
}
|
|
181
|
+
}),
|
|
182
|
+
),
|
|
183
|
+
(handle) => handle.close.pipe(Effect.orDie),
|
|
170
184
|
),
|
|
171
|
-
(
|
|
185
|
+
(handle) => handle.client,
|
|
172
186
|
),
|
|
173
187
|
)
|
|
@@ -21,7 +21,10 @@ declare module "@libsql/client" {
|
|
|
21
21
|
|
|
22
22
|
export interface Client {
|
|
23
23
|
execute(stmt: InStatement | string): Promise<ResultSet>
|
|
24
|
-
batch(
|
|
24
|
+
batch(
|
|
25
|
+
stmts: ReadonlyArray<InStatement | string>,
|
|
26
|
+
mode?: TransactionMode,
|
|
27
|
+
): Promise<ReadonlyArray<ResultSet>>
|
|
25
28
|
transaction(mode?: TransactionMode): Promise<Transaction>
|
|
26
29
|
close(): void
|
|
27
30
|
}
|