Skip to content
Source
Sign inSign up

HeldHooks.test.ts

122 lines4.2 KB

1import { describe, expect, it } from "@effect/vitest";
2import * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";
4import * as Redacted from "effect/Redacted";
5​
6import * as RelayConfiguration from "../Config.ts";
7import * as EnvironmentLinks from "../environments/EnvironmentLinks.ts";
8import * as ManagedEndpointAllocations from "../environments/ManagedEndpointAllocations.ts";
9import * as HeldHooks from "./HeldHooks.ts";
10import * as HookInbox from "./HookInbox.ts";
11​
12const settings = {
13 managedEndpointBaseDomain: "example.test",
14 managedEndpointNamespace: "dev",
15 cloudMintPrivateKey: Redacted.make("unused"),
16} as RelayConfiguration.RelayConfiguration["Service"];
17​
18const environmentId = "env-hook";
19const ownKey = "0123456789abcdef";
20const otherKey = "fedcba9876543210";
21​
22const allocationFor = (
23 userId: string,
24 key: string,
25 ready: boolean,
26): ManagedEndpointAllocations.ManagedEndpointAllocation => ({
27 userId,
28 environmentId,
29 hostname: `${key}.example.test`,
30 tunnelId: `tunnel-${key}`,
31 tunnelName: `t3coderelay-managedendpoint-dev-${key}`,
32 dnsRecordId: "dns-record-id",
33 readyAt: ready ? "2026-05-25T00:00:00.000Z" : null,
34 tunnelReleasedAt: null,
35 origin: { localHttpHost: "127.0.0.1", localHttpPort: 3773 },
36 updatedAt: "2026-05-25T00:00:00.000Z",
37 generation: 1,
38});
39​
40const linkFor = (userId: string, key: string, environmentPublicKey: string) => ({
41 userId,
42 environmentId: environmentId as never,
43 label: "Hook env",
44 endpoint: {
45 httpBaseUrl: `https://${key}.example.test/`,
46 wsBaseUrl: `wss://${key}.example.test/ws`,
47 providerKind: "cloudflare_tunnel" as const,
48 },
49 environmentPublicKey,
50 linkedAt: "2026-05-25T00:00:00.000Z",
51 holdWebhooksWhileOffline: true,
52});
53​
54const withService = <A, E>(
55 options: { readonly ownReady?: boolean; readonly pendingKeys?: ReadonlyArray<string> },
56 body: (input: {
57 readonly heldHooks: HeldHooks.HeldHooks["Service"];
58 readonly cleared: Array<string>;
59 readonly woken: Array<string>;
60 }) => Effect.Effect<A, E>,
61) => {
62 const cleared: Array<string> = [];
63 const woken: Array<string> = [];
64 const links = [linkFor("user_1", ownKey, "own-key"), linkFor("user_2", otherKey, "other-key")];
65 const allocations = [
66 allocationFor("user_1", ownKey, options.ownReady ?? true),
67 allocationFor("user_2", otherKey, true),
68 ];
69 const layerDependencies = Layer.mergeAll(
70 Layer.succeed(RelayConfiguration.RelayConfiguration, settings),
71 Layer.mock(EnvironmentLinks.EnvironmentLinks, {
72 findActiveManagedForEnvironment: (input) =>
73 Effect.succeed(
74 links.filter(
75 (link) =>
76 link.environmentId === input.environmentId &&
77 (input.userId === undefined || link.userId === input.userId) &&
78 (input.environmentPublicKey === undefined ||
79 link.environmentPublicKey === input.environmentPublicKey),
80 ),
81 ),
82 setHoldWebhooksWhileOffline: () => Effect.void,
83 }),
84 Layer.mock(ManagedEndpointAllocations.ManagedEndpointAllocations, {
85 get: (input) =>
86 Effect.succeed(
87 allocations.find((allocation) => allocation.userId === input.userId) ?? null,
88 ),
89 getByTunnelName: (tunnelName) =>
90 Effect.succeed(
91 allocations.find((allocation) => allocation.tunnelName === tunnelName) ?? null,
92 ),
93 }),
94 Layer.mock(HookInbox.HookInbox, {
95 clear: ({ endpointKey }) => Effect.sync(() => void cleared.push(endpointKey)),
96 wake: ({ endpointKey }) =>
97 Effect.sync(() => {
98 woken.push(endpointKey);
99 return (options.pendingKeys ?? []).includes(endpointKey);
100 }),
101 }),
102 );
103 return Effect.gen(function* () {
104 const heldHooks = yield* HeldHooks.HeldHooks;
105 return yield* body({ heldHooks, cleared, woken });
106 }).pipe(Effect.provide(HeldHooks.layer.pipe(Layer.provide(layerDependencies))));
107};
108​
109describe("HeldHooks", () => {
110 it.effect("opting out clears only the caller's own endpoints", () =>
111 withService({}, ({ heldHooks, cleared }) =>
112 Effect.gen(function* () {
113 yield* heldHooks.setHoldWhileOffline({
114 environmentId,
115 environmentPublicKey: "own-key",
116 holdWebhooksWhileOffline: false,
117 });
118 expect(cleared).toEqual([ownKey]);
119 }),
120 ),
121 );
122});