@thomasfosterau/effect-drizzle-ext 0.0.0 → 0.1.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/LICENSE +21 -0
- package/README.md +508 -2
- package/dist/columns.d.ts +113 -0
- package/dist/columns.d.ts.map +1 -0
- package/dist/columns.js +146 -0
- package/dist/columns.js.map +1 -0
- package/dist/constraints.d.ts +117 -0
- package/dist/constraints.d.ts.map +1 -0
- package/dist/constraints.js +93 -0
- package/dist/constraints.js.map +1 -0
- package/dist/database.d.ts +189 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +51 -0
- package/dist/database.js.map +1 -0
- package/dist/derive.d.ts +97 -0
- package/dist/derive.d.ts.map +1 -0
- package/dist/derive.js +142 -0
- package/dist/derive.js.map +1 -0
- package/dist/errors.d.ts +157 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +287 -0
- package/dist/errors.js.map +1 -0
- package/dist/index-CFhgcF4N.d.ts +418 -0
- package/dist/index-CFhgcF4N.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/jsonapi/derive.d.ts +28 -0
- package/dist/jsonapi/derive.d.ts.map +1 -0
- package/dist/jsonapi/derive.js +28 -0
- package/dist/jsonapi/derive.js.map +1 -0
- package/dist/jsonapi/index.d.ts +189 -0
- package/dist/jsonapi/index.d.ts.map +1 -0
- package/dist/jsonapi/index.js +164 -0
- package/dist/jsonapi/index.js.map +1 -0
- package/dist/query.d.ts +111 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +142 -0
- package/dist/query.js.map +1 -0
- package/dist/references.d.ts +38 -0
- package/dist/references.d.ts.map +1 -0
- package/dist/references.js +60 -0
- package/dist/references.js.map +1 -0
- package/dist/sort.d.ts +129 -0
- package/dist/sort.d.ts.map +1 -0
- package/dist/sort.js +225 -0
- package/dist/sort.js.map +1 -0
- package/dist/src-CBeuhy5b.js +478 -0
- package/dist/src-CBeuhy5b.js.map +1 -0
- package/dist/update.d.ts +61 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +64 -0
- package/dist/update.js.map +1 -0
- package/dist/versioned-chain.d.ts +524 -0
- package/dist/versioned-chain.d.ts.map +1 -0
- package/dist/versioned-chain.js +298 -0
- package/dist/versioned-chain.js.map +1 -0
- package/package.json +102 -4
- package/src/columns.ts +186 -0
- package/src/constraints.ts +225 -0
- package/src/database.ts +273 -0
- package/src/derivation-error.ts +27 -0
- package/src/derive.ts +320 -0
- package/src/errors.ts +466 -0
- package/src/index.ts +653 -0
- package/src/jsonapi/derive.ts +74 -0
- package/src/jsonapi/index.ts +355 -0
- package/src/query.ts +183 -0
- package/src/references.ts +103 -0
- package/src/sort.ts +368 -0
- package/src/tree.ts +367 -0
- package/src/update.ts +88 -0
- package/src/versioned-chain.ts +1027 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","names":[],"sources":["../src/errors.ts"],"mappings":";;;;;;;;;;;iBAqGiB;;WAEN;;WAEA;;WAEA,YAAY,OAAO;;WAEnB,OAAO,OAAO;;WAEd,QAAQ,OAAO;;WAEf,QAAQ,OAAO;;WAEf,QAAQ,OAAO;;;;;;;;;;;;qBAuFb,cAAW,mBAAqB,OAAO,OAAO;;;;;;;;;;;;qBAc9C,wBAAwB;;;;;;;;qBAQxB,4BAA4B;;;;;;;qBAW5B,yBAAyB;;;;;;;qBAOzB,uBAAuB;;;;;;;qBAOvB,2BAA2B;;;;;;;;qBAa3B,6BAA6B;;;;;;;;qBAS7B,yBAAyB;;;;;;YAS1B,sBACR,kBACA,sBACA,mBACA,iBACA;;;;;YAMQ,kBAAkB,sBAAsB,uBAAuB;;;;;;;;qBAmE9D,gBAAa,mBAAqB,OAAO,OAAO;;;;;;;;;;;qBA4ChD,oBAAiB;;;;;qBASjB,wBAAqB;;;;;;;qBAUrB,gCAA6B;;;;;;;;;qBAkB7B,2BACV,IAAI,IAAI,IAAE,IAAM,WAAW,wBAAwB,OAAO,OAAO,IAAI,IAAI,SACzE,GAAG,GAAG,GAAC,MAAQ,OAAO,OAAO,GAAG,GAAG,OAAK,OAAO,OAAO,IAAI,IAAI,IAAI,IAAI,IAAI;;;;;;;;;qBAgBhE,uBACV,IAAI,IAAI,IAAE,IAAM,WAAW,oBAAoB,OAAO,OAAO,IAAI,IAAI,SACrE,GAAG,GAAG,GAAC,MAAQ,OAAO,OAAO,GAAG,GAAG,OAAK,OAAO,OAAO,IAAI,IAAI,IAAI,IAAI,IAAI"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import * as Array from "effect/Array";
|
|
2
|
+
import * as Option from "effect/Option";
|
|
3
|
+
import * as Predicate from "effect/Predicate";
|
|
4
|
+
import * as Record from "effect/Record";
|
|
5
|
+
import * as Schema from "effect/Schema";
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
// src/errors.ts
|
|
8
|
+
/**
|
|
9
|
+
* @copyright Thomas Foster
|
|
10
|
+
*
|
|
11
|
+
* Typed Postgres error classification.
|
|
12
|
+
*
|
|
13
|
+
* Effect already classifies SQLSTATE: `@effect/sql-pg` maps a driver error
|
|
14
|
+
* into `SqlError.reason` (`UniqueViolation{constraint}`, `ConstraintError`,
|
|
15
|
+
* `DeadlockError`, `SerializationError`, `ConnectionError`, …). It keeps the
|
|
16
|
+
* violated constraint for `23505` only — every other `23xxx` becomes a bare
|
|
17
|
+
* `ConstraintError` with no constraint / table / column — and drizzle then
|
|
18
|
+
* wraps the whole thing inside `EffectDrizzleQueryError.cause`, which is an
|
|
19
|
+
* Effect `Cause`, not the driver error. So the facts a caller needs to say
|
|
20
|
+
* *which* constraint failed are still in the graph, just not on the failure
|
|
21
|
+
* it is handed.
|
|
22
|
+
*
|
|
23
|
+
* This module recovers them: {@link findPgError} walks the error graph for the
|
|
24
|
+
* driver's Postgres error (the node carrying a SQLSTATE `code`; under
|
|
25
|
+
* `@effect/sql-pg` an `Error` carrying the server's ErrorResponse fields) and
|
|
26
|
+
* reads its `code` / `constraint` / `table` / `column` / `detail` / `schema`,
|
|
27
|
+
* and {@link classifyError} turns those facts into one of seven tagged errors
|
|
28
|
+
* a consumer can `catchTag`.
|
|
29
|
+
*
|
|
30
|
+
* Nothing here is thrown: these are runtime query failures and they travel in
|
|
31
|
+
* the Effect error channel. (Construction-time failures are the thrown
|
|
32
|
+
* `DerivationError` in `./derive`.)
|
|
33
|
+
*
|
|
34
|
+
* The module imports neither `drizzle-orm` nor `@effect/sql-pg`, at runtime or
|
|
35
|
+
* as types: it recognises those shapes structurally, so it works the same on a
|
|
36
|
+
* bare `SqlError`, a bare Postgres error and the drizzle-wrapped shape, and
|
|
37
|
+
* a consumer holding any of them classifies it without pulling a driver into
|
|
38
|
+
* the bundle.
|
|
39
|
+
*
|
|
40
|
+
* @module errors
|
|
41
|
+
*/
|
|
42
|
+
/** SQLSTATE `23505` — unique (or primary key) constraint violated. */
|
|
43
|
+
const UNIQUE_VIOLATION = "23505";
|
|
44
|
+
/** SQLSTATE `23503` — foreign key constraint violated. */
|
|
45
|
+
const FOREIGN_KEY_VIOLATION = "23503";
|
|
46
|
+
/** SQLSTATE `23502` — NOT NULL constraint violated. */
|
|
47
|
+
const NOT_NULL_VIOLATION = "23502";
|
|
48
|
+
/** SQLSTATE `23514` — CHECK constraint violated. */
|
|
49
|
+
const CHECK_VIOLATION = "23514";
|
|
50
|
+
/** SQLSTATE `23P01` — EXCLUDE constraint violated. */
|
|
51
|
+
const EXCLUSION_VIOLATION = "23P01";
|
|
52
|
+
/** SQLSTATE `40001` — serialization failure; the transaction may be retried. */
|
|
53
|
+
const SERIALIZATION_FAILURE = "40001";
|
|
54
|
+
/** SQLSTATE `40P01` — deadlock detected; the transaction may be retried. */
|
|
55
|
+
const DEADLOCK_DETECTED = "40P01";
|
|
56
|
+
/**
|
|
57
|
+
* The stable Postgres message fragment for a unique violation, kept as a
|
|
58
|
+
* belt-and-suspenders fallback for {@link isUniqueViolation} (see its note).
|
|
59
|
+
*/
|
|
60
|
+
const PG_UNIQUE_VIOLATION_MESSAGE = "duplicate key value violates unique constraint";
|
|
61
|
+
/**
|
|
62
|
+
* The shape of a Postgres SQLSTATE: five uppercase alphanumerics (`23505`,
|
|
63
|
+
* `23P01`, `40001`). This is what tells the driver error apart from a wrapper
|
|
64
|
+
* that carries a `code` of its own — an `SqlError` or a Node `ErrnoException`
|
|
65
|
+
* both have a `code`, neither looks like this — so the walk descends past
|
|
66
|
+
* them instead of stopping at the first `code` it meets.
|
|
67
|
+
*/
|
|
68
|
+
const PG_SQLSTATE = /^[0-9A-Z]{5}$/;
|
|
69
|
+
/** How deep into the error graph to search for the driver error. */
|
|
70
|
+
const MAX_ERROR_DEPTH = 8;
|
|
71
|
+
/** Reads a string-valued property off an error node as an `Option`. */
|
|
72
|
+
const readString = (node, key) => {
|
|
73
|
+
const value = node[key];
|
|
74
|
+
return Predicate.isString(value) ? Option.some(value) : Option.none();
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* The SQLSTATE a node declares, under either `code` (node-postgres) or
|
|
78
|
+
* `sqlState` (the field name other drivers and some wrappers use), and only
|
|
79
|
+
* when it actually looks like a SQLSTATE.
|
|
80
|
+
*/
|
|
81
|
+
const sqlStateOf = (node) => Option.filter(Option.orElse(readString(node, "code"), () => readString(node, "sqlState")), (code) => PG_SQLSTATE.test(code));
|
|
82
|
+
/** The driver error's facts, when this node *is* the driver error. */
|
|
83
|
+
const pgErrorFactsOf = (node) => Option.map(sqlStateOf(node), (code) => ({
|
|
84
|
+
code,
|
|
85
|
+
message: Option.getOrElse(readString(node, "message"), () => ""),
|
|
86
|
+
constraint: readString(node, "constraint"),
|
|
87
|
+
table: readString(node, "table"),
|
|
88
|
+
column: readString(node, "column"),
|
|
89
|
+
detail: readString(node, "detail"),
|
|
90
|
+
schema: readString(node, "schema")
|
|
91
|
+
}));
|
|
92
|
+
/** True when `error` is a fresh object worth descending into (within depth, not yet visited). */
|
|
93
|
+
const isSearchable = (error, depth, seen) => Predicate.isObjectOrArray(error) && depth < MAX_ERROR_DEPTH && !seen.has(error);
|
|
94
|
+
/**
|
|
95
|
+
* The child error nodes reachable from a node: its `.cause` (read explicitly,
|
|
96
|
+
* as it is often a NON-enumerable field on `SqlError` and on drizzle's
|
|
97
|
+
* `EffectDrizzleQueryError`) plus its enumerable values, with arrays flattened
|
|
98
|
+
* (an Effect `Cause`'s `reasons`).
|
|
99
|
+
*/
|
|
100
|
+
const childErrorNodes = (node) => [node["cause"], ...Array.flatMap(Record.values(node), (value) => Array.isArray(value) ? value : [value])];
|
|
101
|
+
/**
|
|
102
|
+
* Bounded, cycle-guarded depth-first search of an error graph for the first
|
|
103
|
+
* node `match` accepts.
|
|
104
|
+
*
|
|
105
|
+
* A failed write reaches a caller deeply wrapped, and NOT on a simple `.cause`
|
|
106
|
+
* chain: drizzle's `EffectDrizzleQueryError` holds an Effect `Cause` under a
|
|
107
|
+
* (non-enumerable) `.cause`, and the driver's Postgres error carrying the SQLSTATE
|
|
108
|
+
* sits inside that Cause's `reasons`. Hence a search over the whole reachable
|
|
109
|
+
* graph — reading `.cause` explicitly (for the non-enumerable wrappers) and
|
|
110
|
+
* sweeping enumerable values / arrays (for the Cause `reasons`) — rather than
|
|
111
|
+
* a cause chain.
|
|
112
|
+
*/
|
|
113
|
+
const searchErrorGraph = (cause, match, depth, seen) => {
|
|
114
|
+
if (!isSearchable(cause, depth, seen)) return Option.none();
|
|
115
|
+
seen.add(cause);
|
|
116
|
+
return Option.orElse(match(cause), () => Array.findFirst(childErrorNodes(cause), (child) => searchErrorGraph(child, match, depth + 1, seen)));
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* The driver's Postgres error facts, recovered from anywhere in `error`'s graph:
|
|
120
|
+
* a bare Postgres error, a bare `SqlError` (whose `reason` holds the driver
|
|
121
|
+
* error as its `cause`), or drizzle's `EffectDrizzleQueryError` wrapping an
|
|
122
|
+
* Effect `Cause` that holds the `SqlError`. `Option.none()` when the graph
|
|
123
|
+
* holds no node declaring a SQLSTATE, including for a non-object input.
|
|
124
|
+
*
|
|
125
|
+
* The walk is bounded (depth 8) and cycle-guarded, so a self-referential or
|
|
126
|
+
* pathologically deep graph terminates.
|
|
127
|
+
*/
|
|
128
|
+
const findPgError = (error) => searchErrorGraph(error, pgErrorFactsOf, 0, /* @__PURE__ */ new Set());
|
|
129
|
+
/**
|
|
130
|
+
* SQLSTATE `23505`: a unique or primary key constraint was violated.
|
|
131
|
+
* `cause` is the value classification started from, so the wrapping graph
|
|
132
|
+
* (drizzle's query text and params, the `SqlError`) survives the recovery.
|
|
133
|
+
*/
|
|
134
|
+
var UniqueViolation = class extends Schema.TaggedError()("UniqueViolation", {
|
|
135
|
+
constraint: Schema.Option(Schema.String),
|
|
136
|
+
table: Schema.Option(Schema.String),
|
|
137
|
+
detail: Schema.Option(Schema.String),
|
|
138
|
+
cause: Schema.Defect()
|
|
139
|
+
}) {};
|
|
140
|
+
/** SQLSTATE `23503`: a foreign key constraint was violated. `cause` as in {@link UniqueViolation}. */
|
|
141
|
+
var ForeignKeyViolation = class extends Schema.TaggedError()("ForeignKeyViolation", {
|
|
142
|
+
constraint: Schema.Option(Schema.String),
|
|
143
|
+
table: Schema.Option(Schema.String),
|
|
144
|
+
detail: Schema.Option(Schema.String),
|
|
145
|
+
cause: Schema.Defect()
|
|
146
|
+
}) {};
|
|
147
|
+
/** SQLSTATE `23502`: a NOT NULL constraint was violated. `column` names the offending column. */
|
|
148
|
+
var NotNullViolation = class extends Schema.TaggedError()("NotNullViolation", {
|
|
149
|
+
column: Schema.Option(Schema.String),
|
|
150
|
+
table: Schema.Option(Schema.String),
|
|
151
|
+
cause: Schema.Defect()
|
|
152
|
+
}) {};
|
|
153
|
+
/** SQLSTATE `23514`: a CHECK constraint was violated — including the bounds checks `./derive` writes. */
|
|
154
|
+
var CheckViolation = class extends Schema.TaggedError()("CheckViolation", {
|
|
155
|
+
constraint: Schema.Option(Schema.String),
|
|
156
|
+
table: Schema.Option(Schema.String),
|
|
157
|
+
cause: Schema.Defect()
|
|
158
|
+
}) {};
|
|
159
|
+
/** SQLSTATE `23P01`: an EXCLUDE constraint was violated. */
|
|
160
|
+
var ExclusionViolation = class extends Schema.TaggedError()("ExclusionViolation", {
|
|
161
|
+
constraint: Schema.Option(Schema.String),
|
|
162
|
+
table: Schema.Option(Schema.String),
|
|
163
|
+
cause: Schema.Defect()
|
|
164
|
+
}) {};
|
|
165
|
+
/**
|
|
166
|
+
* SQLSTATE `40001`: the transaction lost a serialization conflict. Retryable:
|
|
167
|
+
* the same transaction re-run from the top may commit.
|
|
168
|
+
*/
|
|
169
|
+
var SerializationFailure = class extends Schema.TaggedError()("SerializationFailure", { cause: Schema.Defect() }) {};
|
|
170
|
+
/**
|
|
171
|
+
* SQLSTATE `40P01`: the transaction was chosen as a deadlock victim.
|
|
172
|
+
* Retryable, like {@link SerializationFailure}.
|
|
173
|
+
*/
|
|
174
|
+
var DeadlockDetected = class extends Schema.TaggedError()("DeadlockDetected", { cause: Schema.Defect() }) {};
|
|
175
|
+
/** Builds the `23505` classification; shared by `classifyError` and `catchUniqueViolation`. */
|
|
176
|
+
const makeUniqueViolation = (facts, cause) => new UniqueViolation({
|
|
177
|
+
constraint: facts.constraint,
|
|
178
|
+
table: facts.table,
|
|
179
|
+
detail: facts.detail,
|
|
180
|
+
cause
|
|
181
|
+
});
|
|
182
|
+
/**
|
|
183
|
+
* SQLSTATE → constraint-family constructor. A table rather than a `switch`:
|
|
184
|
+
* the SQLSTATE is the key the whole module dispatches on, and a lookup that
|
|
185
|
+
* misses is exactly the `Option.none()` an unclassified code should produce.
|
|
186
|
+
*/
|
|
187
|
+
const CONSTRAINT_VIOLATION_BY_CODE = {
|
|
188
|
+
[UNIQUE_VIOLATION]: makeUniqueViolation,
|
|
189
|
+
[FOREIGN_KEY_VIOLATION]: (facts, cause) => new ForeignKeyViolation({
|
|
190
|
+
constraint: facts.constraint,
|
|
191
|
+
table: facts.table,
|
|
192
|
+
detail: facts.detail,
|
|
193
|
+
cause
|
|
194
|
+
}),
|
|
195
|
+
[NOT_NULL_VIOLATION]: (facts, cause) => new NotNullViolation({
|
|
196
|
+
column: facts.column,
|
|
197
|
+
table: facts.table,
|
|
198
|
+
cause
|
|
199
|
+
}),
|
|
200
|
+
[CHECK_VIOLATION]: (facts, cause) => new CheckViolation({
|
|
201
|
+
constraint: facts.constraint,
|
|
202
|
+
table: facts.table,
|
|
203
|
+
cause
|
|
204
|
+
}),
|
|
205
|
+
[EXCLUSION_VIOLATION]: (facts, cause) => new ExclusionViolation({
|
|
206
|
+
constraint: facts.constraint,
|
|
207
|
+
table: facts.table,
|
|
208
|
+
cause
|
|
209
|
+
})
|
|
210
|
+
};
|
|
211
|
+
/** SQLSTATE → retryable-transaction-failure constructor; a table, as above. */
|
|
212
|
+
const TRANSACTION_FAILURE_BY_CODE = {
|
|
213
|
+
[SERIALIZATION_FAILURE]: (cause) => new SerializationFailure({ cause }),
|
|
214
|
+
[DEADLOCK_DETECTED]: (cause) => new DeadlockDetected({ cause })
|
|
215
|
+
};
|
|
216
|
+
/** The constraint-family classification for these facts, if the SQLSTATE is one of the five. */
|
|
217
|
+
const makeConstraintViolation = (facts, cause) => Option.map(Record.get(CONSTRAINT_VIOLATION_BY_CODE, facts.code), (make) => make(facts, cause));
|
|
218
|
+
/** The retryable-transaction classification for these facts, if the SQLSTATE is one of the two. */
|
|
219
|
+
const makeTransactionFailure = (facts, cause) => Option.map(Record.get(TRANSACTION_FAILURE_BY_CODE, facts.code), (make) => make(cause));
|
|
220
|
+
/**
|
|
221
|
+
* Classifies any value into one of the seven tagged errors, by finding the
|
|
222
|
+
* driver's Postgres error in its graph ({@link findPgError}) and dispatching on the
|
|
223
|
+
* SQLSTATE. `Option.none()` when the graph holds no driver error, or holds one
|
|
224
|
+
* whose SQLSTATE is outside the classified families (a syntax error, a
|
|
225
|
+
* connection failure — `SqlError.reason` already covers those well).
|
|
226
|
+
*/
|
|
227
|
+
const classifyError = (error) => Option.flatMap(findPgError(error), (facts) => Option.orElse(makeConstraintViolation(facts, error), () => makeTransactionFailure(facts, error)));
|
|
228
|
+
/** The `23505` classification for `error`, if that is what it is. */
|
|
229
|
+
const uniqueViolationOf = (cause) => Option.map(Option.filter(findPgError(cause), (facts) => facts.code === UNIQUE_VIOLATION), (facts) => makeUniqueViolation(facts, cause));
|
|
230
|
+
/** The constraint-family classification for `error`, if that is what it is. */
|
|
231
|
+
const constraintViolationOf = (cause) => Option.flatMap(findPgError(cause), (facts) => makeConstraintViolation(facts, cause));
|
|
232
|
+
/** True when a node declares `23505` by SQLSTATE, or by the stable Postgres message fragment. */
|
|
233
|
+
const uniqueViolationNode = (node) => {
|
|
234
|
+
const code = Option.orElse(readString(node, "code"), () => readString(node, "sqlState"));
|
|
235
|
+
if (Option.contains(code, UNIQUE_VIOLATION)) return Option.some(true);
|
|
236
|
+
return Option.isSome(Option.filter(readString(node, "message"), (message) => message.includes(PG_UNIQUE_VIOLATION_MESSAGE))) ? Option.some(true) : Option.none();
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* True when `error` is (or wraps) a unique-constraint violation.
|
|
240
|
+
*
|
|
241
|
+
* Kept as its own predicate, with its own walk, for adoption parity: this is
|
|
242
|
+
* the name and the semantics the consuming applications already call, and the
|
|
243
|
+
* semantics include a fallback the typed classification deliberately does not
|
|
244
|
+
* have — matching the stable Postgres message fragment when no `code` survived the
|
|
245
|
+
* wrapping. It also matches a `23505` declared under a `code` that is not
|
|
246
|
+
* SQLSTATE-shaped, which {@link classifyError} skips.
|
|
247
|
+
*/
|
|
248
|
+
const isUniqueViolation = (error) => Option.isSome(searchErrorGraph(error, uniqueViolationNode, 0, /* @__PURE__ */ new Set()));
|
|
249
|
+
/**
|
|
250
|
+
* True when `error` is (or wraps) an integrity-constraint violation — one of
|
|
251
|
+
* the five `23xxx` classes {@link classifyError} recognises.
|
|
252
|
+
*/
|
|
253
|
+
const isConstraintViolation = (error) => Option.isSome(constraintViolationOf(error));
|
|
254
|
+
/**
|
|
255
|
+
* True when `error` is (or wraps) a transaction failure that re-running the
|
|
256
|
+
* whole transaction may clear: a serialization failure (`40001`) or a deadlock
|
|
257
|
+
* (`40P01`). Retrying a {@link ConstraintViolation} is pointless; retrying
|
|
258
|
+
* these is the documented remedy.
|
|
259
|
+
*/
|
|
260
|
+
const isRetryableTransactionFailure = (error) => Option.isSome(Option.filter(findPgError(error), (facts) => facts.code === SERIALIZATION_FAILURE || facts.code === DEADLOCK_DETECTED));
|
|
261
|
+
/**
|
|
262
|
+
* Recovers from a constraint violation in the error channel, leaving every
|
|
263
|
+
* other failure untouched — the failure is re-failed unchanged, with its
|
|
264
|
+
* original type, so a handler for one Postgres conflict does not swallow the
|
|
265
|
+
* rest of the channel.
|
|
266
|
+
*
|
|
267
|
+
* Data-last only: `self.pipe(catchConstraintViolation(handler))`.
|
|
268
|
+
*/
|
|
269
|
+
const catchConstraintViolation = (f) => (self) => Effect.catch(self, (error) => Option.match(constraintViolationOf(error), {
|
|
270
|
+
onNone: () => Effect.fail(error),
|
|
271
|
+
onSome: f
|
|
272
|
+
}));
|
|
273
|
+
/**
|
|
274
|
+
* {@link catchConstraintViolation} narrowed to `23505`: recovers only a unique
|
|
275
|
+
* violation, passing everything else — including other constraint violations —
|
|
276
|
+
* through unchanged. This is the duplicate-key conflict a consumer maps to a
|
|
277
|
+
* domain "already exists".
|
|
278
|
+
*
|
|
279
|
+
* Data-last only: `self.pipe(catchUniqueViolation(handler))`.
|
|
280
|
+
*/
|
|
281
|
+
const catchUniqueViolation = (f) => (self) => Effect.catch(self, (error) => Option.match(uniqueViolationOf(error), {
|
|
282
|
+
onNone: () => Effect.fail(error),
|
|
283
|
+
onSome: f
|
|
284
|
+
}));
|
|
285
|
+
export { CheckViolation, DeadlockDetected, ExclusionViolation, ForeignKeyViolation, NotNullViolation, SerializationFailure, UniqueViolation, catchConstraintViolation, catchUniqueViolation, classifyError, findPgError, isConstraintViolation, isRetryableTransactionFailure, isUniqueViolation };
|
|
286
|
+
|
|
287
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"mappings":"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"}
|