Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 1x 4x 4x 4x 1x 1x | import { Context, Effect, Layer, Option } from 'effect';
/**
* Where `ApiClient` gets the bearer token, read again for every request so a sign-in or a
* sign-out takes effect on the next call. The template has no sign-in: `AuthToken.none` sends no
* `Authorization` header. An app with sign-in swaps it in `src/lib/runtime.ts` for
* `AuthToken.fromGetter(() => <the token your session holds>, onRejected)`; a 401 still reaches
* the UI as `UnauthorizedError`, and `rejected` is told which token the API refused, so the
* session can drop that token (and only that one: a sign-in may have replaced it meanwhile).
*/
export class AuthToken extends Context.Service<
AuthToken,
{
readonly get: Effect.Effect<Option.Option<string>>;
readonly rejected: (token: string) => Effect.Effect<void>;
}
>()('app/lib/api/AuthToken') {
static readonly none = Layer.succeed(AuthToken, {
get: Effect.succeed(Option.none()),
rejected: () => Effect.void,
});
static readonly fromGetter = (
getToken: () => string | null | undefined,
onRejected?: (token: string) => void,
) =>
Layer.succeed(AuthToken, {
get: Effect.sync(() => Option.fromNullishOr(getToken())),
rejected: (token) =>
Effect.sync(() => {
onRejected?.(token);
}),
});
}
|