-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocument-controller.ts
More file actions
45 lines (40 loc) · 1.98 KB
/
Copy pathdocument-controller.ts
File metadata and controls
45 lines (40 loc) · 1.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import { Context, Data, Effect, Layer, Schema } from "effect";
import { defineDirect } from "@hraness/direct";
import { createDirectEffectDriver, type DirectEffectDriverError, type DirectEffectOperation } from "@hraness/direct/effect";
import { createDirectSession } from "@hraness/direct/testing";
const DocumentWorld = Schema.Struct({ text: Schema.String });
type DocumentWorld = typeof DocumentWorld.Type;
const DocumentResponse = Schema.Struct({ text: Schema.String });
export class DocumentUnavailable extends Data.TaggedError("DocumentUnavailable")<{
readonly reason: unknown;
}> {}
/** The application owns this port. Direct knows nothing about documents. */
export class DocumentSource extends Context.Tag("@hraness/direct/example/DocumentSource")<
DocumentSource, { readonly read: Effect.Effect<unknown, DocumentUnavailable> }
>() {}
/** A complete application workflow whose boundary, time and commit are testable. */
export function loadDocument(
operation: DirectEffectOperation<DocumentWorld>,
): Effect.Effect<void, DocumentUnavailable | DirectEffectDriverError, DocumentSource> {
return Effect.gen(function* () {
const source = yield* DocumentSource;
const response = yield* source.read;
const document = yield* Schema.decodeUnknown(DocumentResponse)(response).pipe(
Effect.mapError(reason => new DocumentUnavailable({ reason })),
);
yield* operation.transact(() => ({ text: document.text }));
});
}
export function createDocumentTestSession(source: Layer.Layer<DocumentSource>) {
return createDirectSession({
definition: defineDirect({
parseWorld: Schema.decodeUnknownSync(DocumentWorld),
defaultScenario: "document.empty",
scenarios: [{ id: "document.empty", title: "Empty document", route: "/", world: { text: "" } }],
coverage: [],
}),
activation: { kind: "query", source: "" },
create: context => createDirectEffectDriver({ context, layer: source, clock: "deadline" }),
observe: driver => driver.observation,
});
}