effect-start 0.26.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 +4 -2
- 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/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/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
|
}
|
package/src/sql/mssql/index.ts
CHANGED
|
@@ -5,26 +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 Mssql from "mssql"
|
|
8
|
-
import * as Sql from "../
|
|
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
|
-
}
|
|
8
|
+
import * as Sql from "../SqlClient.ts"
|
|
9
|
+
import * as Values from "../../Values.ts"
|
|
28
10
|
|
|
29
11
|
const wrapError = (error: unknown): Sql.SqlError =>
|
|
30
12
|
new Sql.SqlError({
|
|
@@ -35,17 +17,33 @@ const wrapError = (error: unknown): Sql.SqlError =>
|
|
|
35
17
|
cause: error,
|
|
36
18
|
})
|
|
37
19
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
20
|
+
const dialect = Sql.mssqlDialect
|
|
21
|
+
const makeSpanAttributes = (
|
|
22
|
+
config: Mssql.config & {
|
|
23
|
+
readonly url?: string
|
|
24
|
+
readonly spanAttributes?: Record<string, unknown>
|
|
25
|
+
},
|
|
26
|
+
): Record<string, unknown> =>
|
|
27
|
+
{
|
|
28
|
+
const parsed = (() => {
|
|
29
|
+
if (typeof config.url !== "string") return undefined
|
|
30
|
+
try {
|
|
31
|
+
return new URL(config.url)
|
|
32
|
+
} catch {
|
|
33
|
+
return undefined
|
|
34
|
+
}
|
|
35
|
+
})()
|
|
36
|
+
const dbFromPath = parsed?.pathname.replace(/^\/+/, "") || undefined
|
|
37
|
+
const parsedPort = parsed?.port ? Number(parsed.port) : undefined
|
|
43
38
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
return Values.compact({
|
|
40
|
+
...(config.spanAttributes ?? {}),
|
|
41
|
+
"db.system.name": "microsoft.sql_server",
|
|
42
|
+
"db.namespace": config.database ?? dbFromPath,
|
|
43
|
+
"server.address": config.server ?? parsed?.hostname,
|
|
44
|
+
"server.port": config.port ?? parsedPort,
|
|
45
|
+
})
|
|
46
|
+
}
|
|
49
47
|
|
|
50
48
|
const addInputs = (request: Mssql.Request, values: Array<unknown>) => {
|
|
51
49
|
for (let i = 0; i < values.length; i++) {
|
|
@@ -53,7 +51,7 @@ const addInputs = (request: Mssql.Request, values: Array<unknown>) => {
|
|
|
53
51
|
}
|
|
54
52
|
}
|
|
55
53
|
|
|
56
|
-
interface
|
|
54
|
+
interface TransactionConnection {
|
|
57
55
|
readonly transaction: Mssql.Transaction
|
|
58
56
|
readonly depth: number
|
|
59
57
|
}
|
|
@@ -66,45 +64,71 @@ const loadMssql = () => import("mssql") as Promise<MssqlModule>
|
|
|
66
64
|
|
|
67
65
|
const currentTransaction = GlobalValue.globalValue(
|
|
68
66
|
Symbol.for("effect-start/sql/mssql/currentTransaction"),
|
|
69
|
-
() => FiberRef.unsafeMake<Option.Option<
|
|
67
|
+
() => FiberRef.unsafeMake<Option.Option<TransactionConnection>>(Option.none()),
|
|
70
68
|
)
|
|
71
69
|
|
|
70
|
+
const makeRequest = (
|
|
71
|
+
pool: Mssql.ConnectionPool,
|
|
72
|
+
txOpt: Option.Option<TransactionConnection>,
|
|
73
|
+
values: Array<unknown>,
|
|
74
|
+
): Mssql.Request => {
|
|
75
|
+
const request = Option.isSome(txOpt) ? txOpt.value.transaction.request() : pool.request()
|
|
76
|
+
addInputs(request, values)
|
|
77
|
+
return request
|
|
78
|
+
}
|
|
79
|
+
|
|
72
80
|
const executeQuery = <T>(
|
|
73
81
|
pool: Mssql.ConnectionPool,
|
|
74
82
|
text: string,
|
|
75
83
|
values: Array<unknown>,
|
|
76
84
|
): Effect.Effect<ReadonlyArray<T>, Sql.SqlError> =>
|
|
77
|
-
Effect.flatMap(FiberRef.get(currentTransaction), (txOpt) =>
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return Effect.tryPromise({
|
|
81
|
-
try: () => request.query<T>(text),
|
|
85
|
+
Effect.flatMap(FiberRef.get(currentTransaction), (txOpt) =>
|
|
86
|
+
Effect.tryPromise({
|
|
87
|
+
try: () => makeRequest(pool, txOpt, values).query<T>(text),
|
|
82
88
|
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
|
-
}
|
|
89
|
+
}).pipe(Effect.map((result) => result.recordset ?? [])),
|
|
90
|
+
)
|
|
94
91
|
|
|
95
92
|
const runUnsafe = <T>(
|
|
96
93
|
pool: Mssql.ConnectionPool,
|
|
97
94
|
query: string,
|
|
98
95
|
values?: Array<unknown>,
|
|
99
96
|
): Effect.Effect<ReadonlyArray<T>, Sql.SqlError> =>
|
|
100
|
-
Effect.flatMap(FiberRef.get(currentTransaction), (txOpt) =>
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return Effect.tryPromise({
|
|
104
|
-
try: () => request.query<T>(query),
|
|
97
|
+
Effect.flatMap(FiberRef.get(currentTransaction), (txOpt) =>
|
|
98
|
+
Effect.tryPromise({
|
|
99
|
+
try: () => makeRequest(pool, txOpt, values ?? []).query<T>(query),
|
|
105
100
|
catch: wrapError,
|
|
106
|
-
}).pipe(Effect.map((result) => result.recordset ?? []))
|
|
107
|
-
|
|
101
|
+
}).pipe(Effect.map((result) => result.recordset ?? [])),
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
const makeTaggedTemplate = (pool: Mssql.ConnectionPool) => {
|
|
105
|
+
const unsafeFn = <T = any>(query: string, values?: Array<unknown>) =>
|
|
106
|
+
runUnsafe<T>(pool, query, values)
|
|
107
|
+
|
|
108
|
+
return <T = any>(
|
|
109
|
+
strings: TemplateStringsArray,
|
|
110
|
+
...values: Array<unknown>
|
|
111
|
+
): Effect.Effect<ReadonlyArray<T>, Sql.SqlError> => {
|
|
112
|
+
if (Sql.hasFragments(values)) {
|
|
113
|
+
const compiled = Sql.interpolate(dialect, strings, values)
|
|
114
|
+
return unsafeFn<T>(compiled.sql, compiled.parameters)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
let text = strings[0]
|
|
118
|
+
for (let i = 0; i < values.length; i++) text += `@p${i + 1}` + strings[i + 1]
|
|
119
|
+
return executeQuery<T>(pool, text, values)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const makeQuery = (
|
|
124
|
+
pool: Mssql.ConnectionPool,
|
|
125
|
+
spanAttributes: ReadonlyArray<readonly [string, unknown]>,
|
|
126
|
+
): Sql.Connection => {
|
|
127
|
+
const query = makeTaggedTemplate(pool)
|
|
128
|
+
const unsafe: Sql.Connection["unsafe"] = <T = any>(query: string, values?: Array<unknown>) =>
|
|
129
|
+
runUnsafe<T>(pool, query, values)
|
|
130
|
+
return Sql.connection(query, unsafe, { spanAttributes, dialect })
|
|
131
|
+
}
|
|
108
132
|
|
|
109
133
|
const makeWithTransaction =
|
|
110
134
|
(pool: Mssql.ConnectionPool) =>
|
|
@@ -161,63 +185,72 @@ const makeWithTransaction =
|
|
|
161
185
|
}),
|
|
162
186
|
)
|
|
163
187
|
|
|
164
|
-
export const layer = (
|
|
188
|
+
export const layer = (
|
|
189
|
+
config: Mssql.config & {
|
|
190
|
+
readonly url?: string
|
|
191
|
+
readonly spanAttributes?: Record<string, unknown>
|
|
192
|
+
},
|
|
193
|
+
): Layer.Layer<Sql.SqlClient, Sql.SqlError> =>
|
|
165
194
|
Layer.scoped(
|
|
166
195
|
Sql.SqlClient,
|
|
167
|
-
Effect.
|
|
168
|
-
Effect.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
196
|
+
Effect.map(
|
|
197
|
+
Effect.acquireRelease(
|
|
198
|
+
Effect.tryPromise({
|
|
199
|
+
try: async () => {
|
|
200
|
+
const mssql = await loadMssql()
|
|
201
|
+
const driverConfig = { ...config } as Record<string, unknown>
|
|
202
|
+
delete driverConfig.spanAttributes
|
|
203
|
+
delete driverConfig.url
|
|
204
|
+
const pool = await new mssql.ConnectionPool(driverConfig as unknown as Mssql.config).connect()
|
|
205
|
+
return { mssql, pool }
|
|
206
|
+
},
|
|
207
|
+
catch: wrapError,
|
|
208
|
+
}).pipe(
|
|
209
|
+
Effect.map((options) => {
|
|
210
|
+
const driverConfig = { ...config } as Record<string, unknown>
|
|
211
|
+
delete driverConfig.spanAttributes
|
|
212
|
+
delete driverConfig.url
|
|
213
|
+
const spanAttributes = Object.entries(makeSpanAttributes(config))
|
|
214
|
+
const query = makeTaggedTemplate(options.pool)
|
|
215
|
+
const unsafeFn: Sql.Connection["unsafe"] = <T = any>(
|
|
216
|
+
query: string,
|
|
217
|
+
values?: Array<unknown>,
|
|
218
|
+
) => runUnsafe<T>(options.pool, query, values)
|
|
219
|
+
const use: Sql.SqlClient["use"] = (fn) =>
|
|
220
|
+
Effect.tryPromise({ try: () => Promise.resolve(fn(options.pool)), catch: wrapError })
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
client: Sql.make({
|
|
224
|
+
query,
|
|
225
|
+
unsafe: unsafeFn,
|
|
226
|
+
withTransaction: makeWithTransaction(options.pool),
|
|
227
|
+
spanAttributes,
|
|
228
|
+
dialect,
|
|
229
|
+
reserve: Effect.acquireRelease(
|
|
230
|
+
Effect.tryPromise({
|
|
231
|
+
try: () =>
|
|
232
|
+
new options.mssql.ConnectionPool({
|
|
233
|
+
...driverConfig,
|
|
234
|
+
pool: { max: 1, min: 1 },
|
|
235
|
+
} as unknown as Mssql.config).connect(),
|
|
236
|
+
catch: wrapError,
|
|
237
|
+
}),
|
|
238
|
+
(reserved: Mssql.ConnectionPool) =>
|
|
239
|
+
Effect.tryPromise({ try: () => reserved.close(), catch: () => void 0 }).pipe(
|
|
240
|
+
Effect.asVoid,
|
|
241
|
+
Effect.orDie,
|
|
212
242
|
),
|
|
243
|
+
).pipe(
|
|
244
|
+
Effect.map((reserved): Sql.Connection => makeQuery(reserved, spanAttributes)),
|
|
213
245
|
),
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
use,
|
|
217
|
-
}
|
|
218
|
-
)
|
|
219
|
-
|
|
246
|
+
use,
|
|
247
|
+
}),
|
|
248
|
+
close: use((pool) => pool.close()),
|
|
249
|
+
}
|
|
250
|
+
}),
|
|
251
|
+
),
|
|
252
|
+
(handle) => handle.close.pipe(Effect.orDie),
|
|
220
253
|
),
|
|
221
|
-
(
|
|
254
|
+
(handle) => handle.client,
|
|
222
255
|
),
|
|
223
256
|
)
|
package/src/sql/mssql/mssql.d.ts
CHANGED
|
@@ -24,13 +24,13 @@ export function layer(): Layer.Layer<TestLogger> {
|
|
|
24
24
|
const messages = yield* Ref.make<Array<string>>([])
|
|
25
25
|
const mutableRef = (messages as any).ref as MutableRef.MutableRef<Array<string>>
|
|
26
26
|
|
|
27
|
-
const customLogger = Logger.make((
|
|
28
|
-
const causeStr = !Cause.isEmpty(cause)
|
|
29
|
-
? ` ${Cause.pretty(cause, { renderErrorCause: true })}`
|
|
27
|
+
const customLogger = Logger.make((options) => {
|
|
28
|
+
const causeStr = !Cause.isEmpty(options.cause)
|
|
29
|
+
? ` ${Cause.pretty(options.cause, { renderErrorCause: true })}`
|
|
30
30
|
: ""
|
|
31
31
|
MutableRef.update(mutableRef, (msgs) => [
|
|
32
32
|
...msgs,
|
|
33
|
-
`[${logLevel._tag}] ${String(message)}${causeStr}`,
|
|
33
|
+
`[${options.logLevel._tag}] ${String(options.message)}${causeStr}`,
|
|
34
34
|
])
|
|
35
35
|
})
|
|
36
36
|
|
|
@@ -20,24 +20,16 @@ export interface CompileOptions {
|
|
|
20
20
|
customJsResolver?: Resolver
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function createCompileOptions({
|
|
24
|
-
base,
|
|
25
|
-
from,
|
|
26
|
-
polyfills,
|
|
27
|
-
onDependency,
|
|
28
|
-
|
|
29
|
-
customCssResolver,
|
|
30
|
-
customJsResolver,
|
|
31
|
-
}: CompileOptions) {
|
|
23
|
+
function createCompileOptions(options: CompileOptions) {
|
|
32
24
|
return {
|
|
33
|
-
base,
|
|
34
|
-
polyfills,
|
|
35
|
-
from,
|
|
25
|
+
base: options.base,
|
|
26
|
+
polyfills: options.polyfills,
|
|
27
|
+
from: options.from,
|
|
36
28
|
async loadModule(id: string, base: string) {
|
|
37
|
-
return loadModule(id, base, onDependency, customJsResolver)
|
|
29
|
+
return loadModule(id, base, options.onDependency, options.customJsResolver)
|
|
38
30
|
},
|
|
39
31
|
async loadStylesheet(id: string, sheetBase: string) {
|
|
40
|
-
let sheet = await loadStylesheet(id, sheetBase, onDependency, customCssResolver)
|
|
32
|
+
let sheet = await loadStylesheet(id, sheetBase, options.onDependency, options.customCssResolver)
|
|
41
33
|
|
|
42
34
|
return sheet
|
|
43
35
|
},
|
package/src/console/Console.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import * as Effect from "effect/Effect"
|
|
2
|
-
import * as Layer from "effect/Layer"
|
|
3
|
-
import * as Route from "../Route.ts"
|
|
4
|
-
import * as RouteTree from "../RouteTree.ts"
|
|
5
|
-
import * as ConsoleErrors from "./ConsoleErrors.ts"
|
|
6
|
-
import * as ConsoleLogger from "./ConsoleLogger.ts"
|
|
7
|
-
import * as ConsoleMetrics from "./ConsoleMetrics.ts"
|
|
8
|
-
import * as ConsoleProcess from "./ConsoleProcess.ts"
|
|
9
|
-
import * as ConsoleStore from "./ConsoleStore.ts"
|
|
10
|
-
import * as ConsoleTracer from "./ConsoleTracer.ts"
|
|
11
|
-
import consoleRoutes from "./routes/tree.ts"
|
|
12
|
-
|
|
13
|
-
export { ConsoleStore } from "./ConsoleStore.ts"
|
|
14
|
-
|
|
15
|
-
export function layer(
|
|
16
|
-
options?: ConsoleStore.ConsoleStoreOptions,
|
|
17
|
-
): Layer.Layer<ConsoleStore.ConsoleStore> {
|
|
18
|
-
const store = ConsoleStore.layer(options)
|
|
19
|
-
return Layer.mergeAll(
|
|
20
|
-
ConsoleTracer.layer,
|
|
21
|
-
ConsoleLogger.layer,
|
|
22
|
-
ConsoleMetrics.layer,
|
|
23
|
-
ConsoleErrors.layer,
|
|
24
|
-
ConsoleProcess.layer,
|
|
25
|
-
).pipe(Layer.provideMerge(store))
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function routeLayer(
|
|
29
|
-
prefix: string,
|
|
30
|
-
): Layer.Layer<Route.Routes, never, Route.Routes | ConsoleStore.ConsoleStore> {
|
|
31
|
-
return Layer.effect(
|
|
32
|
-
Route.Routes,
|
|
33
|
-
Effect.gen(function* () {
|
|
34
|
-
const existing = yield* Route.Routes
|
|
35
|
-
ConsoleStore.store.prefix = prefix
|
|
36
|
-
const tree = Route.tree({
|
|
37
|
-
[prefix as "/"]: consoleRoutes,
|
|
38
|
-
})
|
|
39
|
-
return RouteTree.merge(existing, tree)
|
|
40
|
-
}),
|
|
41
|
-
)
|
|
42
|
-
}
|