effect 4.0.0-beta.36 → 4.0.0-beta.37
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/dist/Cause.d.ts +31 -0
- package/dist/Cause.d.ts.map +1 -1
- package/dist/Cause.js +19 -0
- package/dist/Cause.js.map +1 -1
- package/dist/Channel.d.ts +2 -2
- package/dist/Channel.d.ts.map +1 -1
- package/dist/Effect.d.ts +1 -16
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js.map +1 -1
- package/dist/Schedule.d.ts.map +1 -1
- package/dist/Schedule.js +19 -1
- package/dist/Schedule.js.map +1 -1
- package/dist/Schema.d.ts +14 -42
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaParser.d.ts +22 -66
- package/dist/SchemaParser.d.ts.map +1 -1
- package/dist/SchemaParser.js.map +1 -1
- package/dist/Sink.d.ts +5 -2
- package/dist/Sink.d.ts.map +1 -1
- package/dist/Sink.js.map +1 -1
- package/dist/Stream.d.ts +1 -1
- package/dist/Stream.d.ts.map +1 -1
- package/dist/internal/effect.js +15 -1
- package/dist/internal/effect.js.map +1 -1
- package/dist/unstable/cli/Prompt.js +16 -6
- package/dist/unstable/cli/Prompt.js.map +1 -1
- package/dist/unstable/devtools/DevToolsClient.d.ts.map +1 -1
- package/dist/unstable/devtools/DevToolsClient.js +4 -3
- package/dist/unstable/devtools/DevToolsClient.js.map +1 -1
- package/dist/unstable/devtools/DevToolsSchema.d.ts +2 -3
- package/dist/unstable/devtools/DevToolsSchema.d.ts.map +1 -1
- package/dist/unstable/devtools/DevToolsSchema.js +11 -1
- package/dist/unstable/devtools/DevToolsSchema.js.map +1 -1
- package/dist/unstable/http/HttpClientRequest.d.ts +24 -2
- package/dist/unstable/http/HttpClientRequest.d.ts.map +1 -1
- package/dist/unstable/http/HttpClientRequest.js +97 -0
- package/dist/unstable/http/HttpClientRequest.js.map +1 -1
- package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerResponse.js +2 -1
- package/dist/unstable/http/HttpServerResponse.js.map +1 -1
- package/dist/unstable/sql/Migrator.d.ts.map +1 -1
- package/dist/unstable/sql/Migrator.js +2 -2
- package/dist/unstable/sql/Migrator.js.map +1 -1
- package/dist/unstable/sql/SqlError.d.ts +229 -9
- package/dist/unstable/sql/SqlError.d.ts.map +1 -1
- package/dist/unstable/sql/SqlError.js +256 -6
- package/dist/unstable/sql/SqlError.js.map +1 -1
- package/package.json +1 -1
- package/src/Cause.ts +35 -0
- package/src/Channel.ts +2 -2
- package/src/Effect.ts +1 -16
- package/src/Schedule.ts +20 -8
- package/src/Schema.ts +6 -10
- package/src/SchemaParser.ts +25 -29
- package/src/Sink.ts +5 -2
- package/src/Stream.ts +1 -1
- package/src/internal/effect.ts +27 -2
- package/src/unstable/cli/Prompt.ts +15 -6
- package/src/unstable/devtools/DevToolsClient.ts +23 -18
- package/src/unstable/devtools/DevToolsSchema.ts +13 -1
- package/src/unstable/http/HttpClientRequest.ts +104 -2
- package/src/unstable/http/HttpServerResponse.ts +8 -4
- package/src/unstable/sql/Migrator.ts +7 -5
- package/src/unstable/sql/SqlError.ts +360 -8
|
@@ -15,10 +15,11 @@ import type * as Redacted from "../../Redacted.ts"
|
|
|
15
15
|
import * as Result from "../../Result.ts"
|
|
16
16
|
import type * as Schema from "../../Schema.ts"
|
|
17
17
|
import type { ParseOptions } from "../../SchemaAST.ts"
|
|
18
|
-
import
|
|
18
|
+
import * as ServiceMap from "../../ServiceMap.ts"
|
|
19
|
+
import * as Stream from "../../Stream.ts"
|
|
19
20
|
import * as Headers from "./Headers.ts"
|
|
20
21
|
import * as HttpBody from "./HttpBody.ts"
|
|
21
|
-
import type
|
|
22
|
+
import { hasBody, type HttpMethod } from "./HttpMethod.ts"
|
|
22
23
|
import * as UrlParams from "./UrlParams.ts"
|
|
23
24
|
|
|
24
25
|
const TypeId = "~effect/http/HttpClientRequest"
|
|
@@ -954,3 +955,104 @@ export function toUrl(self: HttpClientRequest): Option.Option<URL> {
|
|
|
954
955
|
}
|
|
955
956
|
return Option.none()
|
|
956
957
|
}
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* @since 4.0.0
|
|
961
|
+
* @category conversions
|
|
962
|
+
*/
|
|
963
|
+
export const fromWeb = (request: globalThis.Request): HttpClientRequest => {
|
|
964
|
+
const method = request.method.toUpperCase() as HttpMethod
|
|
965
|
+
return modify(empty, {
|
|
966
|
+
method,
|
|
967
|
+
url: new URL(request.url),
|
|
968
|
+
headers: request.headers,
|
|
969
|
+
body: fromWebBody(request, method)
|
|
970
|
+
})
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
const fromWebBody = (request: globalThis.Request, method: HttpMethod): HttpBody.HttpBody => {
|
|
974
|
+
if (!hasBody(method) || request.body === null) {
|
|
975
|
+
return HttpBody.empty
|
|
976
|
+
}
|
|
977
|
+
return HttpBody.raw(request.body, {
|
|
978
|
+
contentType: request.headers.get("content-type") ?? undefined,
|
|
979
|
+
contentLength: parseContentLength(request.headers.get("content-length"))
|
|
980
|
+
})
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
const parseContentLength = (contentLength: string | null): number | undefined => {
|
|
984
|
+
if (contentLength === null) {
|
|
985
|
+
return undefined
|
|
986
|
+
}
|
|
987
|
+
const parsed = Number.parseInt(contentLength, 10)
|
|
988
|
+
return Number.isNaN(parsed) ? undefined : parsed
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* @since 4.0.0
|
|
993
|
+
* @category conversions
|
|
994
|
+
*/
|
|
995
|
+
export const toWebResult = (self: HttpClientRequest, options?: {
|
|
996
|
+
readonly signal?: AbortSignal | undefined
|
|
997
|
+
readonly services?: ServiceMap.ServiceMap<never> | undefined
|
|
998
|
+
}): Result.Result<Request, UrlParams.UrlParamsError> => {
|
|
999
|
+
const url = UrlParams.makeUrl(self.url, self.urlParams, Option.getOrUndefined(self.hash))
|
|
1000
|
+
if (Result.isFailure(url)) {
|
|
1001
|
+
return Result.fail(url.failure)
|
|
1002
|
+
}
|
|
1003
|
+
const requestInit: RequestInit = {
|
|
1004
|
+
method: self.method,
|
|
1005
|
+
headers: self.headers
|
|
1006
|
+
}
|
|
1007
|
+
if (options?.signal) {
|
|
1008
|
+
requestInit.signal = options.signal
|
|
1009
|
+
}
|
|
1010
|
+
if (hasBody(self.method)) {
|
|
1011
|
+
switch (self.body._tag) {
|
|
1012
|
+
case "Empty": {
|
|
1013
|
+
break
|
|
1014
|
+
}
|
|
1015
|
+
case "Raw": {
|
|
1016
|
+
requestInit.body = self.body.body as any
|
|
1017
|
+
if (isReadableStream(self.body.body)) {
|
|
1018
|
+
;(requestInit as any).duplex = "half"
|
|
1019
|
+
}
|
|
1020
|
+
break
|
|
1021
|
+
}
|
|
1022
|
+
case "Uint8Array": {
|
|
1023
|
+
requestInit.body = self.body.body as any
|
|
1024
|
+
break
|
|
1025
|
+
}
|
|
1026
|
+
case "FormData": {
|
|
1027
|
+
requestInit.body = self.body.formData
|
|
1028
|
+
break
|
|
1029
|
+
}
|
|
1030
|
+
case "Stream": {
|
|
1031
|
+
requestInit.body = Stream.toReadableStreamWith(self.body.stream, options?.services ?? ServiceMap.empty())
|
|
1032
|
+
;(requestInit as any).duplex = "half"
|
|
1033
|
+
break
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
return Result.try({
|
|
1038
|
+
try: () => new Request(url.success, requestInit),
|
|
1039
|
+
catch: (cause) => new UrlParams.UrlParamsError({ cause })
|
|
1040
|
+
})
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
const isReadableStream = (u: unknown): u is ReadableStream<Uint8Array> =>
|
|
1044
|
+
typeof ReadableStream !== "undefined" && u instanceof ReadableStream
|
|
1045
|
+
|
|
1046
|
+
/**
|
|
1047
|
+
* @since 4.0.0
|
|
1048
|
+
* @category conversions
|
|
1049
|
+
*/
|
|
1050
|
+
export const toWeb = (self: HttpClientRequest, options?: {
|
|
1051
|
+
readonly signal?: AbortSignal | undefined
|
|
1052
|
+
}): Effect.Effect<Request, UrlParams.UrlParamsError> =>
|
|
1053
|
+
Effect.servicesWith((services) =>
|
|
1054
|
+
toWebResult(self, {
|
|
1055
|
+
services,
|
|
1056
|
+
signal: options?.signal
|
|
1057
|
+
}).asEffect()
|
|
1058
|
+
)
|
|
@@ -1225,12 +1225,16 @@ export const fromWeb = (response: Response): HttpServerResponse => {
|
|
|
1225
1225
|
cookies: Cookies.fromSetCookie(setCookieHeaders)
|
|
1226
1226
|
})
|
|
1227
1227
|
if (response.body) {
|
|
1228
|
+
const contentType = response.headers.get("content-type")
|
|
1228
1229
|
self = setBody(
|
|
1229
1230
|
self,
|
|
1230
|
-
Body.stream(
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1231
|
+
Body.stream(
|
|
1232
|
+
Stream.fromReadableStream({
|
|
1233
|
+
evaluate: () => response.body!,
|
|
1234
|
+
onError: (e) => e
|
|
1235
|
+
}),
|
|
1236
|
+
contentType ?? undefined
|
|
1237
|
+
)
|
|
1234
1238
|
)
|
|
1235
1239
|
}
|
|
1236
1240
|
return self
|
|
@@ -236,11 +236,13 @@ export const make = <RD = never>({
|
|
|
236
236
|
if (required.length > 0) {
|
|
237
237
|
yield* pipe(
|
|
238
238
|
insertMigrations(required.map(([id, name]) => [id, name])),
|
|
239
|
-
Effect.mapError((
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
239
|
+
Effect.mapError((error): MigrationError | SqlError =>
|
|
240
|
+
error.reason._tag === "ConstraintError"
|
|
241
|
+
? new MigrationError({
|
|
242
|
+
kind: "Locked",
|
|
243
|
+
message: "Migrations already running"
|
|
244
|
+
})
|
|
245
|
+
: error
|
|
244
246
|
)
|
|
245
247
|
)
|
|
246
248
|
}
|
|
@@ -1,21 +1,378 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @since 4.0.0
|
|
3
3
|
*/
|
|
4
|
+
import * as Predicate from "../../Predicate.ts"
|
|
4
5
|
import * as Schema from "../../Schema.ts"
|
|
5
6
|
|
|
6
|
-
const TypeId = "~effect/sql/SqlError"
|
|
7
|
+
const TypeId = "~effect/sql/SqlError" as const
|
|
8
|
+
const ReasonTypeId = "~effect/sql/SqlError/Reason" as const
|
|
9
|
+
|
|
10
|
+
const ReasonFields = {
|
|
11
|
+
cause: Schema.Defect,
|
|
12
|
+
message: Schema.optional(Schema.String),
|
|
13
|
+
operation: Schema.optional(Schema.String)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @since 4.0.0
|
|
18
|
+
*/
|
|
19
|
+
export class ConnectionError extends Schema.TaggedErrorClass<ConnectionError>("effect/sql/SqlError/ConnectionError")(
|
|
20
|
+
"ConnectionError",
|
|
21
|
+
ReasonFields
|
|
22
|
+
) {
|
|
23
|
+
/**
|
|
24
|
+
* @since 4.0.0
|
|
25
|
+
*/
|
|
26
|
+
readonly [ReasonTypeId] = ReasonTypeId
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @since 4.0.0
|
|
30
|
+
*/
|
|
31
|
+
get isRetryable(): boolean {
|
|
32
|
+
return true
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @since 4.0.0
|
|
38
|
+
*/
|
|
39
|
+
export class AuthenticationError extends Schema.TaggedErrorClass<AuthenticationError>(
|
|
40
|
+
"effect/sql/SqlError/AuthenticationError"
|
|
41
|
+
)("AuthenticationError", ReasonFields) {
|
|
42
|
+
/**
|
|
43
|
+
* @since 4.0.0
|
|
44
|
+
*/
|
|
45
|
+
readonly [ReasonTypeId] = ReasonTypeId
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @since 4.0.0
|
|
49
|
+
*/
|
|
50
|
+
get isRetryable(): boolean {
|
|
51
|
+
return false
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @since 4.0.0
|
|
57
|
+
*/
|
|
58
|
+
export class AuthorizationError extends Schema.TaggedErrorClass<AuthorizationError>(
|
|
59
|
+
"effect/sql/SqlError/AuthorizationError"
|
|
60
|
+
)("AuthorizationError", ReasonFields) {
|
|
61
|
+
/**
|
|
62
|
+
* @since 4.0.0
|
|
63
|
+
*/
|
|
64
|
+
readonly [ReasonTypeId] = ReasonTypeId
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @since 4.0.0
|
|
68
|
+
*/
|
|
69
|
+
get isRetryable(): boolean {
|
|
70
|
+
return false
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @since 4.0.0
|
|
76
|
+
*/
|
|
77
|
+
export class SqlSyntaxError extends Schema.TaggedErrorClass<SqlSyntaxError>("effect/sql/SqlError/SqlSyntaxError")(
|
|
78
|
+
"SqlSyntaxError",
|
|
79
|
+
ReasonFields
|
|
80
|
+
) {
|
|
81
|
+
/**
|
|
82
|
+
* @since 4.0.0
|
|
83
|
+
*/
|
|
84
|
+
readonly [ReasonTypeId] = ReasonTypeId
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @since 4.0.0
|
|
88
|
+
*/
|
|
89
|
+
get isRetryable(): boolean {
|
|
90
|
+
return false
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @since 4.0.0
|
|
96
|
+
*/
|
|
97
|
+
export class ConstraintError extends Schema.TaggedErrorClass<ConstraintError>("effect/sql/SqlError/ConstraintError")(
|
|
98
|
+
"ConstraintError",
|
|
99
|
+
ReasonFields
|
|
100
|
+
) {
|
|
101
|
+
/**
|
|
102
|
+
* @since 4.0.0
|
|
103
|
+
*/
|
|
104
|
+
readonly [ReasonTypeId] = ReasonTypeId
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @since 4.0.0
|
|
108
|
+
*/
|
|
109
|
+
get isRetryable(): boolean {
|
|
110
|
+
return false
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @since 4.0.0
|
|
116
|
+
*/
|
|
117
|
+
export class DeadlockError extends Schema.TaggedErrorClass<DeadlockError>("effect/sql/SqlError/DeadlockError")(
|
|
118
|
+
"DeadlockError",
|
|
119
|
+
ReasonFields
|
|
120
|
+
) {
|
|
121
|
+
/**
|
|
122
|
+
* @since 4.0.0
|
|
123
|
+
*/
|
|
124
|
+
readonly [ReasonTypeId] = ReasonTypeId
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @since 4.0.0
|
|
128
|
+
*/
|
|
129
|
+
get isRetryable(): boolean {
|
|
130
|
+
return true
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @since 4.0.0
|
|
136
|
+
*/
|
|
137
|
+
export class SerializationError extends Schema.TaggedErrorClass<SerializationError>(
|
|
138
|
+
"effect/sql/SqlError/SerializationError"
|
|
139
|
+
)("SerializationError", ReasonFields) {
|
|
140
|
+
/**
|
|
141
|
+
* @since 4.0.0
|
|
142
|
+
*/
|
|
143
|
+
readonly [ReasonTypeId] = ReasonTypeId
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @since 4.0.0
|
|
147
|
+
*/
|
|
148
|
+
get isRetryable(): boolean {
|
|
149
|
+
return true
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @since 4.0.0
|
|
155
|
+
*/
|
|
156
|
+
export class LockTimeoutError extends Schema.TaggedErrorClass<LockTimeoutError>("effect/sql/SqlError/LockTimeoutError")(
|
|
157
|
+
"LockTimeoutError",
|
|
158
|
+
ReasonFields
|
|
159
|
+
) {
|
|
160
|
+
/**
|
|
161
|
+
* @since 4.0.0
|
|
162
|
+
*/
|
|
163
|
+
readonly [ReasonTypeId] = ReasonTypeId
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @since 4.0.0
|
|
167
|
+
*/
|
|
168
|
+
get isRetryable(): boolean {
|
|
169
|
+
return true
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @since 4.0.0
|
|
175
|
+
*/
|
|
176
|
+
export class StatementTimeoutError extends Schema.TaggedErrorClass<StatementTimeoutError>(
|
|
177
|
+
"effect/sql/SqlError/StatementTimeoutError"
|
|
178
|
+
)("StatementTimeoutError", ReasonFields) {
|
|
179
|
+
/**
|
|
180
|
+
* @since 4.0.0
|
|
181
|
+
*/
|
|
182
|
+
readonly [ReasonTypeId] = ReasonTypeId
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* @since 4.0.0
|
|
186
|
+
*/
|
|
187
|
+
get isRetryable(): boolean {
|
|
188
|
+
return true
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* @since 4.0.0
|
|
194
|
+
*/
|
|
195
|
+
export class UnknownError extends Schema.TaggedErrorClass<UnknownError>("effect/sql/SqlError/UnknownError")(
|
|
196
|
+
"UnknownError",
|
|
197
|
+
ReasonFields
|
|
198
|
+
) {
|
|
199
|
+
/**
|
|
200
|
+
* @since 4.0.0
|
|
201
|
+
*/
|
|
202
|
+
readonly [ReasonTypeId] = ReasonTypeId
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @since 4.0.0
|
|
206
|
+
*/
|
|
207
|
+
get isRetryable(): boolean {
|
|
208
|
+
return false
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @since 4.0.0
|
|
214
|
+
*/
|
|
215
|
+
export type SqlErrorReason =
|
|
216
|
+
| ConnectionError
|
|
217
|
+
| AuthenticationError
|
|
218
|
+
| AuthorizationError
|
|
219
|
+
| SqlSyntaxError
|
|
220
|
+
| ConstraintError
|
|
221
|
+
| DeadlockError
|
|
222
|
+
| SerializationError
|
|
223
|
+
| LockTimeoutError
|
|
224
|
+
| StatementTimeoutError
|
|
225
|
+
| UnknownError
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* @since 4.0.0
|
|
229
|
+
*/
|
|
230
|
+
export const SqlErrorReason: Schema.Union<[
|
|
231
|
+
typeof ConnectionError,
|
|
232
|
+
typeof AuthenticationError,
|
|
233
|
+
typeof AuthorizationError,
|
|
234
|
+
typeof SqlSyntaxError,
|
|
235
|
+
typeof ConstraintError,
|
|
236
|
+
typeof DeadlockError,
|
|
237
|
+
typeof SerializationError,
|
|
238
|
+
typeof LockTimeoutError,
|
|
239
|
+
typeof StatementTimeoutError,
|
|
240
|
+
typeof UnknownError
|
|
241
|
+
]> = Schema.Union([
|
|
242
|
+
ConnectionError,
|
|
243
|
+
AuthenticationError,
|
|
244
|
+
AuthorizationError,
|
|
245
|
+
SqlSyntaxError,
|
|
246
|
+
ConstraintError,
|
|
247
|
+
DeadlockError,
|
|
248
|
+
SerializationError,
|
|
249
|
+
LockTimeoutError,
|
|
250
|
+
StatementTimeoutError,
|
|
251
|
+
UnknownError
|
|
252
|
+
])
|
|
7
253
|
|
|
8
254
|
/**
|
|
9
255
|
* @since 4.0.0
|
|
10
256
|
*/
|
|
11
257
|
export class SqlError extends Schema.TaggedErrorClass<SqlError>("effect/sql/SqlError")("SqlError", {
|
|
12
|
-
|
|
13
|
-
message: Schema.optional(Schema.String)
|
|
258
|
+
reason: SqlErrorReason
|
|
14
259
|
}) {
|
|
15
260
|
/**
|
|
16
261
|
* @since 4.0.0
|
|
17
262
|
*/
|
|
18
263
|
readonly [TypeId] = TypeId
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* @since 4.0.0
|
|
267
|
+
*/
|
|
268
|
+
override readonly cause = this.reason
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* @since 4.0.0
|
|
272
|
+
*/
|
|
273
|
+
override get message(): string {
|
|
274
|
+
return this.reason.message || this.reason._tag
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* @since 4.0.0
|
|
279
|
+
*/
|
|
280
|
+
get isRetryable(): boolean {
|
|
281
|
+
return this.reason.isRetryable
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* @since 4.0.0
|
|
287
|
+
*/
|
|
288
|
+
export const isSqlError = (u: unknown): u is SqlError => Predicate.hasProperty(u, TypeId)
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* @since 4.0.0
|
|
292
|
+
*/
|
|
293
|
+
export const isSqlErrorReason = (u: unknown): u is SqlErrorReason => Predicate.hasProperty(u, ReasonTypeId)
|
|
294
|
+
|
|
295
|
+
type SqliteClassifyOptions = {
|
|
296
|
+
readonly message?: string | undefined
|
|
297
|
+
readonly operation?: string | undefined
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const sqliteCodeFromCause = (cause: unknown): string | number | undefined => {
|
|
301
|
+
if (!Predicate.hasProperty(cause, "code")) {
|
|
302
|
+
return undefined
|
|
303
|
+
}
|
|
304
|
+
const code = cause.code
|
|
305
|
+
return typeof code === "string" || typeof code === "number" ? code : undefined
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const sqliteNumericCodeFromCause = (cause: unknown): number | undefined => {
|
|
309
|
+
const code = sqliteCodeFromCause(cause)
|
|
310
|
+
if (typeof code === "number") {
|
|
311
|
+
return code
|
|
312
|
+
}
|
|
313
|
+
if (!Predicate.hasProperty(cause, "errno")) {
|
|
314
|
+
return undefined
|
|
315
|
+
}
|
|
316
|
+
const errno = cause.errno
|
|
317
|
+
return typeof errno === "number" ? errno : undefined
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const matchesSqliteCode = (code: string, expected: string): boolean =>
|
|
321
|
+
code === expected || code.startsWith(expected + "_")
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* @since 4.0.0
|
|
325
|
+
*/
|
|
326
|
+
export const classifySqliteError = (
|
|
327
|
+
cause: unknown,
|
|
328
|
+
{ message, operation }: SqliteClassifyOptions = {}
|
|
329
|
+
): SqlErrorReason => {
|
|
330
|
+
const props = {
|
|
331
|
+
cause,
|
|
332
|
+
message,
|
|
333
|
+
operation
|
|
334
|
+
}
|
|
335
|
+
const code = sqliteCodeFromCause(cause)
|
|
336
|
+
|
|
337
|
+
if (typeof code === "string") {
|
|
338
|
+
if (matchesSqliteCode(code, "SQLITE_AUTH")) {
|
|
339
|
+
return new AuthenticationError(props)
|
|
340
|
+
}
|
|
341
|
+
if (matchesSqliteCode(code, "SQLITE_PERM")) {
|
|
342
|
+
return new AuthorizationError(props)
|
|
343
|
+
}
|
|
344
|
+
if (matchesSqliteCode(code, "SQLITE_CONSTRAINT")) {
|
|
345
|
+
return new ConstraintError(props)
|
|
346
|
+
}
|
|
347
|
+
if (matchesSqliteCode(code, "SQLITE_BUSY") || matchesSqliteCode(code, "SQLITE_LOCKED")) {
|
|
348
|
+
return new LockTimeoutError(props)
|
|
349
|
+
}
|
|
350
|
+
if (matchesSqliteCode(code, "SQLITE_CANTOPEN")) {
|
|
351
|
+
return new ConnectionError(props)
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const numericCode = sqliteNumericCodeFromCause(cause)
|
|
356
|
+
if (typeof numericCode === "number") {
|
|
357
|
+
const code = numericCode & 0xff
|
|
358
|
+
switch (code) {
|
|
359
|
+
case 23:
|
|
360
|
+
return new AuthenticationError(props)
|
|
361
|
+
case 3:
|
|
362
|
+
return new AuthorizationError(props)
|
|
363
|
+
case 19:
|
|
364
|
+
return new ConstraintError(props)
|
|
365
|
+
case 5:
|
|
366
|
+
case 6:
|
|
367
|
+
return new LockTimeoutError(props)
|
|
368
|
+
case 14:
|
|
369
|
+
return new ConnectionError(props)
|
|
370
|
+
default:
|
|
371
|
+
return new UnknownError(props)
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return new UnknownError(props)
|
|
19
376
|
}
|
|
20
377
|
|
|
21
378
|
/**
|
|
@@ -27,11 +384,6 @@ export class ResultLengthMismatch
|
|
|
27
384
|
actual: Schema.Number
|
|
28
385
|
})
|
|
29
386
|
{
|
|
30
|
-
/**
|
|
31
|
-
* @since 4.0.0
|
|
32
|
-
*/
|
|
33
|
-
readonly [TypeId] = TypeId
|
|
34
|
-
|
|
35
387
|
/**
|
|
36
388
|
* @since 4.0.0
|
|
37
389
|
*/
|