1import { ConfigError } from "@distilled.cloud/core/errors";
2import { Credentials } from "@distilled.cloud/neon";
3import * as Effect from "effect/Effect";
4import * as Layer from "effect/Layer";
5import {
6 deferUntilFirstUse,
7 orDieCredentialsUnavailable,
8 resolveProviderConfig,
9} from "../Auth/Resolve.ts";
10import {
11 NEON_AUTH_PROVIDER_NAME,
12 type NeonAuthConfig,
13 type NeonResolvedCredentials,
14} from "./AuthProvider.ts";
15
16export { Credentials } from "@distilled.cloud/neon";
17
18const DEFAULT_BASE_URL = "https://console.neon.tech/api/v2";
19
20export const fromAuthProvider = () =>
21 Layer.effect(
22 Credentials,
23 Effect.gen(function* () {
24 // Defer profile lookup and credential resolution until first use, so
25 // building the provider layers never requires a configured profile.
26 const resolve = yield* resolveProviderConfig<
27 NeonAuthConfig,
28 NeonResolvedCredentials
29 >(NEON_AUTH_PROVIDER_NAME).pipe(
30 Effect.flatMap(({ profileName, resolve }) =>
31 resolve.pipe(
32 Effect.map((creds) => ({
33 apiKey: creds.apiKey,
34 apiBaseUrl: DEFAULT_BASE_URL,
35 })),
36 Effect.mapError(
37 (e) =>
38 new ConfigError({
39 message: `Failed to resolve Neon credentials from ${profileName === undefined ? "the CI environment" : `profile '${profileName}'`}: ${(e as { message?: string }).message ?? String(e)}`,
40 }),
41 ),
42 ),
43 ),
44 deferUntilFirstUse,
45 );
46 return yield* resolve.pipe(
47 orDieCredentialsUnavailable(NEON_AUTH_PROVIDER_NAME),
48 Effect.cached,
49 );
50 }),
51 );