@visiolab/effect-firebase 0.0.0-stage → 0.3.1
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 +81 -2
- package/dist/_virtual/_rolldown/runtime.mjs +12 -0
- package/dist/app/App.d.mts +27 -0
- package/dist/app/App.mjs +27 -0
- package/dist/app/index.d.mts +2 -0
- package/dist/app/index.mjs +1 -0
- package/dist/firestore/Collection.d.mts +423 -0
- package/dist/firestore/Collection.mjs +133 -0
- package/dist/firestore/CollectionGroup.d.mts +164 -0
- package/dist/firestore/CollectionGroup.mjs +84 -0
- package/dist/firestore/DocumentPath.d.mts +95 -0
- package/dist/firestore/DocumentPath.mjs +71 -0
- package/dist/firestore/DocumentSnapshot.d.mts +239 -0
- package/dist/firestore/DocumentSnapshot.mjs +134 -0
- package/dist/firestore/FieldValue.d.mts +332 -0
- package/dist/firestore/FieldValue.mjs +256 -0
- package/dist/firestore/Firestore.d.mts +1165 -0
- package/dist/firestore/Firestore.mjs +274 -0
- package/dist/firestore/FirestoreModel.d.mts +1232 -0
- package/dist/firestore/FirestoreModel.mjs +586 -0
- package/dist/firestore/FirestoreSchema.d.mts +567 -0
- package/dist/firestore/FirestoreSchema.mjs +419 -0
- package/dist/firestore/FirestoreValue.d.mts +145 -0
- package/dist/firestore/FirestoreValue.mjs +87 -0
- package/dist/firestore/GeoPoint.d.mts +90 -0
- package/dist/firestore/GeoPoint.mjs +75 -0
- package/dist/firestore/Patch.d.mts +73 -0
- package/dist/firestore/Patch.mjs +57 -0
- package/dist/firestore/QuerySnapshot.d.mts +107 -0
- package/dist/firestore/QuerySnapshot.mjs +43 -0
- package/dist/firestore/Timestamp.d.mts +273 -0
- package/dist/firestore/Timestamp.mjs +255 -0
- package/dist/firestore/index.d.mts +14 -0
- package/dist/firestore/index.mjs +14 -0
- package/dist/firestore/internal/collection.mjs +156 -0
- package/dist/firestore/internal/collectionGroup.mjs +64 -0
- package/dist/firestore/internal/documentPath.d.mts +4 -0
- package/dist/firestore/internal/documentPath.mjs +42 -0
- package/dist/firestore/internal/documentSnapshot.mjs +63 -0
- package/dist/firestore/internal/fieldValue.d.mts +11 -0
- package/dist/firestore/internal/fieldValue.mjs +88 -0
- package/dist/firestore/internal/firestore.mjs +145 -0
- package/dist/firestore/internal/firestoreError.d.mts +29 -0
- package/dist/firestore/internal/firestoreError.mjs +30 -0
- package/dist/firestore/internal/firestoreModel.mjs +719 -0
- package/dist/firestore/internal/firestoreSchema.mjs +123 -0
- package/dist/firestore/internal/firestoreValue.mjs +108 -0
- package/dist/firestore/internal/firestoreValueWalk.d.mts +58 -0
- package/dist/firestore/internal/firestoreValueWalk.mjs +223 -0
- package/dist/firestore/internal/geoPoint.d.mts +4 -0
- package/dist/firestore/internal/geoPoint.mjs +39 -0
- package/dist/firestore/internal/patch.mjs +19 -0
- package/dist/firestore/internal/querySnapshot.mjs +24 -0
- package/dist/firestore/internal/schemaAST.mjs +35 -0
- package/dist/firestore/internal/snapshotExtra.mjs +35 -0
- package/dist/firestore/internal/streamFromListener.mjs +12 -0
- package/dist/firestore/internal/timestamp.d.mts +4 -0
- package/dist/firestore/internal/timestamp.mjs +66 -0
- package/dist/firestore/internal/timestampSchema.mjs +31 -0
- package/dist/firestore/internal/transactionFromCallback.mjs +66 -0
- package/dist/functions/Callable.d.mts +654 -0
- package/dist/functions/Callable.mjs +450 -0
- package/dist/functions/CallableError.d.mts +297 -0
- package/dist/functions/CallableError.mjs +256 -0
- package/dist/functions/CallableMiddleware.d.mts +213 -0
- package/dist/functions/CallableMiddleware.mjs +52 -0
- package/dist/functions/CallableRequest.d.mts +166 -0
- package/dist/functions/CallableRequest.mjs +18 -0
- package/dist/functions/Caller.d.mts +103 -0
- package/dist/functions/Caller.mjs +115 -0
- package/dist/functions/DocumentTrigger.d.mts +795 -0
- package/dist/functions/DocumentTrigger.mjs +566 -0
- package/dist/functions/FirebaseFunction.d.mts +79 -0
- package/dist/functions/FirebaseFunction.mjs +4 -0
- package/dist/functions/FunctionGroup.d.mts +175 -0
- package/dist/functions/FunctionGroup.mjs +64 -0
- package/dist/functions/index.d.mts +9 -0
- package/dist/functions/index.mjs +9 -0
- package/dist/functions/internal/callable.mjs +167 -0
- package/dist/functions/internal/callableMiddleware.d.mts +19 -0
- package/dist/functions/internal/callableMiddleware.mjs +15 -0
- package/dist/functions/internal/callableRequest.mjs +6 -0
- package/dist/functions/internal/documentTrigger.d.mts +10 -0
- package/dist/functions/internal/documentTrigger.mjs +73 -0
- package/dist/functions/internal/firebaseFunction.d.mts +5 -0
- package/dist/functions/internal/firebaseFunction.mjs +24 -0
- package/dist/functions/internal/functionGroup.mjs +36 -0
- package/package.json +72 -3
- package/src/app/App.ts +24 -0
- package/src/app/index.ts +7 -0
- package/src/firestore/Collection.ts +520 -0
- package/src/firestore/CollectionGroup.ts +245 -0
- package/src/firestore/DocumentPath.ts +114 -0
- package/src/firestore/DocumentSnapshot.ts +308 -0
- package/src/firestore/FieldValue.ts +375 -0
- package/src/firestore/Firestore.ts +1432 -0
- package/src/firestore/FirestoreModel.ts +1884 -0
- package/src/firestore/FirestoreSchema.ts +643 -0
- package/src/firestore/FirestoreValue.ts +207 -0
- package/src/firestore/GeoPoint.ts +105 -0
- package/src/firestore/Patch.ts +117 -0
- package/src/firestore/QuerySnapshot.ts +150 -0
- package/src/firestore/Timestamp.ts +302 -0
- package/src/firestore/index.ts +67 -0
- package/src/firestore/internal/collection.ts +246 -0
- package/src/firestore/internal/collectionGroup.ts +81 -0
- package/src/firestore/internal/documentPath.ts +53 -0
- package/src/firestore/internal/documentSnapshot.ts +117 -0
- package/src/firestore/internal/fieldValue.ts +119 -0
- package/src/firestore/internal/firestore.ts +322 -0
- package/src/firestore/internal/firestoreError.ts +36 -0
- package/src/firestore/internal/firestoreModel.ts +1242 -0
- package/src/firestore/internal/firestoreSchema.ts +218 -0
- package/src/firestore/internal/firestoreValue.ts +202 -0
- package/src/firestore/internal/firestoreValueWalk.ts +349 -0
- package/src/firestore/internal/geoPoint.ts +59 -0
- package/src/firestore/internal/patch.ts +21 -0
- package/src/firestore/internal/querySnapshot.ts +39 -0
- package/src/firestore/internal/schemaAST.ts +83 -0
- package/src/firestore/internal/snapshotExtra.ts +47 -0
- package/src/firestore/internal/streamFromListener.ts +27 -0
- package/src/firestore/internal/timestamp.ts +119 -0
- package/src/firestore/internal/timestampSchema.ts +42 -0
- package/src/firestore/internal/transactionFromCallback.ts +106 -0
- package/src/functions/Callable.ts +855 -0
- package/src/functions/CallableError.ts +348 -0
- package/src/functions/CallableMiddleware.ts +279 -0
- package/src/functions/CallableRequest.ts +207 -0
- package/src/functions/Caller.ts +141 -0
- package/src/functions/DocumentTrigger.ts +927 -0
- package/src/functions/FirebaseFunction.ts +96 -0
- package/src/functions/FunctionGroup.ts +225 -0
- package/src/functions/index.ts +62 -0
- package/src/functions/internal/callable.ts +272 -0
- package/src/functions/internal/callableMiddleware.ts +54 -0
- package/src/functions/internal/callableRequest.ts +8 -0
- package/src/functions/internal/documentTrigger.ts +143 -0
- package/src/functions/internal/firebaseFunction.ts +58 -0
- package/src/functions/internal/functionGroup.ts +47 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DateTime,
|
|
3
|
+
Effect,
|
|
4
|
+
Equal,
|
|
5
|
+
Hash,
|
|
6
|
+
Inspectable,
|
|
7
|
+
Option,
|
|
8
|
+
Order as order,
|
|
9
|
+
Predicate,
|
|
10
|
+
} from "effect";
|
|
11
|
+
import type * as Timestamp from "../Timestamp.ts";
|
|
12
|
+
|
|
13
|
+
/** @internal */
|
|
14
|
+
export const TypeId = "~@visiolab/effect-firebase/firestore/Timestamp";
|
|
15
|
+
|
|
16
|
+
/** `0001-01-01T00:00:00Z`, the earliest instant Firestore addresses. */
|
|
17
|
+
const minSeconds = -62_135_596_800;
|
|
18
|
+
/** `9999-12-31T23:59:59Z`, the latest. */
|
|
19
|
+
const maxSeconds = 253_402_300_799;
|
|
20
|
+
const maxNanoseconds = 999_999_999;
|
|
21
|
+
const nanosecondsPerMillisecond = 1_000_000;
|
|
22
|
+
|
|
23
|
+
/** Kept apart from the guards below, which narrow a `number` to `never`. */
|
|
24
|
+
const inSecondsRange = (n: number): boolean =>
|
|
25
|
+
Number.isInteger(n) && n >= minSeconds && n <= maxSeconds;
|
|
26
|
+
|
|
27
|
+
const inNanosecondsRange = (n: number): boolean =>
|
|
28
|
+
Number.isInteger(n) && n >= 0 && n <= maxNanoseconds;
|
|
29
|
+
|
|
30
|
+
/** @internal */
|
|
31
|
+
export const isTimestamp = (u: unknown): u is Timestamp.Timestamp =>
|
|
32
|
+
Predicate.hasProperty(u, TypeId) &&
|
|
33
|
+
u[TypeId] === TypeId &&
|
|
34
|
+
Predicate.hasProperty(u, "seconds") &&
|
|
35
|
+
Predicate.hasProperty(u, "nanoseconds") &&
|
|
36
|
+
Predicate.isNumber(u.seconds) &&
|
|
37
|
+
Predicate.isNumber(u.nanoseconds) &&
|
|
38
|
+
inSecondsRange(u.seconds) &&
|
|
39
|
+
inNanosecondsRange(u.nanoseconds);
|
|
40
|
+
|
|
41
|
+
const Proto: Omit<Timestamp.Timestamp, "seconds" | "nanoseconds"> = {
|
|
42
|
+
...Inspectable.BaseProto,
|
|
43
|
+
[TypeId]: TypeId,
|
|
44
|
+
toJSON(this: Timestamp.Timestamp) {
|
|
45
|
+
return { _id: "Timestamp", seconds: this.seconds, nanoseconds: this.nanoseconds };
|
|
46
|
+
},
|
|
47
|
+
[Equal.symbol](this: Timestamp.Timestamp, that: unknown): boolean {
|
|
48
|
+
return (
|
|
49
|
+
isTimestamp(that) && this.seconds === that.seconds && this.nanoseconds === that.nanoseconds
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
[Hash.symbol](this: Timestamp.Timestamp): number {
|
|
53
|
+
return Hash.combine(Hash.number(this.seconds), Hash.number(this.nanoseconds));
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const makeUnchecked = (seconds: number, nanoseconds: number): Timestamp.Timestamp =>
|
|
58
|
+
Object.assign(Object.create(Proto) as typeof Proto, { seconds, nanoseconds });
|
|
59
|
+
|
|
60
|
+
/** @internal */
|
|
61
|
+
export const makeUnsafe = (seconds: number, nanoseconds: number): Timestamp.Timestamp => {
|
|
62
|
+
if (!inSecondsRange(seconds)) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`Invalid Firestore timestamp: seconds must be an integer between ${minSeconds} and ${maxSeconds}, got ${seconds}`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (!inNanosecondsRange(nanoseconds)) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`Invalid Firestore timestamp: nanoseconds must be an integer between 0 and ${maxNanoseconds}, got ${nanoseconds}`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return makeUnchecked(seconds, nanoseconds);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/** @internal */
|
|
76
|
+
export const make = (seconds: number, nanoseconds: number): Option.Option<Timestamp.Timestamp> =>
|
|
77
|
+
inSecondsRange(seconds) && inNanosecondsRange(nanoseconds)
|
|
78
|
+
? Option.some(makeUnchecked(seconds, nanoseconds))
|
|
79
|
+
: Option.none();
|
|
80
|
+
|
|
81
|
+
/** Splits milliseconds into the second and the fraction of it Firestore stores. */
|
|
82
|
+
const partsOfMillis = (millis: number): readonly [seconds: number, nanoseconds: number] => {
|
|
83
|
+
const seconds = Math.floor(millis / 1000);
|
|
84
|
+
return [seconds, Math.floor((millis - seconds * 1000) * nanosecondsPerMillisecond)];
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/** @internal */
|
|
88
|
+
export const fromMillisUnsafe = (millis: number): Timestamp.Timestamp =>
|
|
89
|
+
makeUnsafe(...partsOfMillis(millis));
|
|
90
|
+
|
|
91
|
+
/** @internal */
|
|
92
|
+
export const fromMillis = (millis: number): Option.Option<Timestamp.Timestamp> =>
|
|
93
|
+
make(...partsOfMillis(millis));
|
|
94
|
+
|
|
95
|
+
/** @internal */
|
|
96
|
+
export const fromDateTimeUnsafe = (dateTime: DateTime.Utc): Timestamp.Timestamp =>
|
|
97
|
+
fromMillisUnsafe(DateTime.toEpochMillis(dateTime));
|
|
98
|
+
|
|
99
|
+
/** @internal */
|
|
100
|
+
export const fromDateTime = (dateTime: DateTime.Utc): Option.Option<Timestamp.Timestamp> =>
|
|
101
|
+
fromMillis(DateTime.toEpochMillis(dateTime));
|
|
102
|
+
|
|
103
|
+
/** @internal */
|
|
104
|
+
export const now: Effect.Effect<Timestamp.Timestamp> = Effect.map(DateTime.now, fromDateTimeUnsafe);
|
|
105
|
+
|
|
106
|
+
/** @internal */
|
|
107
|
+
export const toMillis = (self: Timestamp.Timestamp): number =>
|
|
108
|
+
self.seconds * 1000 + Math.floor(self.nanoseconds / nanosecondsPerMillisecond);
|
|
109
|
+
|
|
110
|
+
/** @internal */
|
|
111
|
+
export const toDateTime = (self: Timestamp.Timestamp): DateTime.Utc =>
|
|
112
|
+
DateTime.makeUnsafe(toMillis(self));
|
|
113
|
+
|
|
114
|
+
/** @internal */
|
|
115
|
+
export const Order: order.Order<Timestamp.Timestamp> = order.make((self, that) =>
|
|
116
|
+
self.seconds === that.seconds
|
|
117
|
+
? order.Number(self.nanoseconds, that.nanoseconds)
|
|
118
|
+
: order.Number(self.seconds, that.seconds),
|
|
119
|
+
);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apart from the other Firestore schemas, so that deriving `toCodecFirestore`,
|
|
3
|
+
* which writes instants as timestamps, need not import the schemas that
|
|
4
|
+
* derive it in turn.
|
|
5
|
+
*/
|
|
6
|
+
import { Effect, Equal, Schema, SchemaGetter, SchemaIssue } from "effect";
|
|
7
|
+
import type * as FirestoreSchema from "../FirestoreSchema.ts";
|
|
8
|
+
import type * as Timestamp_ from "../Timestamp.ts";
|
|
9
|
+
import * as timestamp from "./timestamp.ts";
|
|
10
|
+
|
|
11
|
+
/** Writes a timestamp as JSON without losing the digits finer than a millisecond. */
|
|
12
|
+
const TimestampJson = Schema.Struct({ seconds: Schema.Int, nanoseconds: Schema.Int });
|
|
13
|
+
|
|
14
|
+
/** @internal */
|
|
15
|
+
export const Timestamp: FirestoreSchema.Timestamp = Schema.declare<Timestamp_.Timestamp>(
|
|
16
|
+
timestamp.isTimestamp,
|
|
17
|
+
{
|
|
18
|
+
representation: { id: "@visiolab/effect-firebase/firestore/Timestamp", payload: null },
|
|
19
|
+
expected: "a Firestore Timestamp",
|
|
20
|
+
toEquivalence: () => Equal.equals,
|
|
21
|
+
toCodecFirestore: () => undefined,
|
|
22
|
+
toCodecJson: () =>
|
|
23
|
+
Schema.link<Timestamp_.Timestamp>()(TimestampJson, {
|
|
24
|
+
decode: SchemaGetter.transformEffect((json: typeof TimestampJson.Type, options) =>
|
|
25
|
+
Effect.fromOption(timestamp.make(json.seconds, json.nanoseconds)).pipe(
|
|
26
|
+
Effect.mapError(
|
|
27
|
+
() =>
|
|
28
|
+
new SchemaIssue.InvalidValue(
|
|
29
|
+
{ message: "Expected an instant Firestore can store" },
|
|
30
|
+
json,
|
|
31
|
+
options,
|
|
32
|
+
),
|
|
33
|
+
),
|
|
34
|
+
),
|
|
35
|
+
),
|
|
36
|
+
encode: SchemaGetter.transform((value: Timestamp_.Timestamp) => ({
|
|
37
|
+
seconds: value.seconds,
|
|
38
|
+
nanoseconds: value.nanoseconds,
|
|
39
|
+
})),
|
|
40
|
+
}),
|
|
41
|
+
},
|
|
42
|
+
);
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Cause, Effect, Exit, Option } from "effect";
|
|
2
|
+
import { constVoid } from "effect/Function";
|
|
3
|
+
import type * as Firestore from "../Firestore.ts";
|
|
4
|
+
import { FirestoreError } from "./firestoreError.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* What the callback throws when the body fails with anything but a
|
|
8
|
+
* `FirestoreError` that carries its backend's cause.
|
|
9
|
+
*
|
|
10
|
+
* It carries no `code` on purpose: an SDK decides whether to retry by the code
|
|
11
|
+
* of what it caught, and a body's own error that happens to carry one would
|
|
12
|
+
* otherwise be retried as if Firestore had raised it.
|
|
13
|
+
*/
|
|
14
|
+
class BodyFailed {
|
|
15
|
+
readonly cause: Cause.Cause<unknown>;
|
|
16
|
+
constructor(cause: Cause.Cause<unknown>) {
|
|
17
|
+
this.cause = cause;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* What the callback throws for a body that failed with `cause`.
|
|
23
|
+
*
|
|
24
|
+
* A `FirestoreError` goes back as the SDK's own error behind it, so the SDK
|
|
25
|
+
* decides by its own rules whether to retry it - a read answered with ABORTED
|
|
26
|
+
* under contention, or an outage that passes - rather than by a copy of them
|
|
27
|
+
* kept here. Anything else goes back as {@link BodyFailed}, which it never
|
|
28
|
+
* retries.
|
|
29
|
+
*/
|
|
30
|
+
const thrownFor = (cause: Cause.Cause<unknown>): unknown => {
|
|
31
|
+
const error = Option.getOrUndefined(Cause.findErrorOption(cause));
|
|
32
|
+
return error instanceof FirestoreError && error.cause !== undefined
|
|
33
|
+
? error.cause
|
|
34
|
+
: new BodyFailed(cause);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/** @internal */
|
|
38
|
+
export const transactionFromCallback = <
|
|
39
|
+
T,
|
|
40
|
+
Operations extends Firestore.TransactionOperations,
|
|
41
|
+
TransactionServices = never,
|
|
42
|
+
>(
|
|
43
|
+
options: Firestore.TransactionFromCallbackOptions<T, Operations, TransactionServices>,
|
|
44
|
+
): Firestore.RunTransaction<Operations, TransactionServices> => ({
|
|
45
|
+
run: (body, hookOptions) => runOver(options, body, hookOptions),
|
|
46
|
+
context: options.context,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/** Runs `body` in a transaction through `options.run`, once per attempt. */
|
|
50
|
+
const runOver = <T, Operations extends Firestore.TransactionOperations, A, E>(
|
|
51
|
+
options: Pick<
|
|
52
|
+
Firestore.TransactionFromCallbackOptions<T, Operations>,
|
|
53
|
+
"run" | "operations" | "onError"
|
|
54
|
+
>,
|
|
55
|
+
body: (operations: Operations) => Effect.Effect<A, E>,
|
|
56
|
+
hookOptions: Firestore.TransactionHookOptions,
|
|
57
|
+
): Effect.Effect<A, E | FirestoreError> =>
|
|
58
|
+
Effect.uninterruptibleMask((restore) => {
|
|
59
|
+
const controller = new AbortController();
|
|
60
|
+
// The last thing the body failed with, and what was thrown for it, so
|
|
61
|
+
// that a failure the SDK hands back without retrying it comes back as
|
|
62
|
+
// the body's own rather than wrapped.
|
|
63
|
+
let failure: { readonly thrown: unknown; readonly cause: Cause.Cause<unknown> } | undefined;
|
|
64
|
+
const callback = async (transaction: unknown): Promise<A> => {
|
|
65
|
+
// The body has everything it needs provided, so it runs on a runtime
|
|
66
|
+
// of its own here, inside the SDK's callback. `run` hands this the
|
|
67
|
+
// SDK's transaction, which `operations` is typed by: `run`'s callback
|
|
68
|
+
// is not, so that `T` is inferred from `operations` alone.
|
|
69
|
+
const operations = options.operations(transaction as T);
|
|
70
|
+
const exit = await Effect.runPromiseExit(body(operations), {
|
|
71
|
+
signal: controller.signal,
|
|
72
|
+
});
|
|
73
|
+
if (Exit.isSuccess(exit)) return exit.value;
|
|
74
|
+
const thrown = thrownFor(exit.cause);
|
|
75
|
+
failure = { thrown, cause: exit.cause };
|
|
76
|
+
throw thrown;
|
|
77
|
+
};
|
|
78
|
+
let running: Promise<A>;
|
|
79
|
+
try {
|
|
80
|
+
running = options.run(callback, hookOptions);
|
|
81
|
+
} catch (cause) {
|
|
82
|
+
running = Promise.reject(cause);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return restore(
|
|
86
|
+
Effect.tryPromise({
|
|
87
|
+
try: () => running,
|
|
88
|
+
catch: (cause) =>
|
|
89
|
+
failure !== undefined && cause === failure.thrown
|
|
90
|
+
? new BodyFailed(failure.cause)
|
|
91
|
+
: options.onError(cause),
|
|
92
|
+
}),
|
|
93
|
+
).pipe(
|
|
94
|
+
// Interrupting the body is what makes the callback reject, and so what
|
|
95
|
+
// makes the SDK roll back - which is waited for, so that nothing of
|
|
96
|
+
// the transaction is left running once this is done.
|
|
97
|
+
Effect.onInterrupt(() => {
|
|
98
|
+
controller.abort();
|
|
99
|
+
return Effect.promise(() => running.then(constVoid, constVoid));
|
|
100
|
+
}),
|
|
101
|
+
Effect.catchIf(
|
|
102
|
+
(error): error is BodyFailed => error instanceof BodyFailed,
|
|
103
|
+
(failed) => Effect.failCause(failed.cause as Cause.Cause<E>),
|
|
104
|
+
),
|
|
105
|
+
);
|
|
106
|
+
});
|