alchemy 2.0.0-beta.34 → 2.0.0-beta.35
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/bin/cli.js +8 -7
- package/bin/exec.js +226 -52
- package/bin/exec.js.map +1 -1
- package/lib/AWS/AuthProvider.d.ts +7 -6
- package/lib/AWS/AuthProvider.d.ts.map +1 -1
- package/lib/AWS/AuthProvider.js +143 -134
- package/lib/AWS/AuthProvider.js.map +1 -1
- package/lib/AWS/Bootstrap.d.ts +2 -2
- package/lib/AWS/Bootstrap.d.ts.map +1 -1
- package/lib/AWS/EC2/hosted.d.ts +1 -1
- package/lib/AWS/Environment.d.ts +25 -3
- package/lib/AWS/Environment.d.ts.map +1 -1
- package/lib/AWS/Environment.js +47 -3
- package/lib/AWS/Environment.js.map +1 -1
- package/lib/AWS/IAM/OpenIDConnectProvider.d.ts +14 -6
- package/lib/AWS/IAM/OpenIDConnectProvider.d.ts.map +1 -1
- package/lib/AWS/IAM/OpenIDConnectProvider.js +6 -3
- package/lib/AWS/IAM/OpenIDConnectProvider.js.map +1 -1
- package/lib/AWS/IAM/Policy.d.ts +1 -1
- package/lib/AWS/IAM/Policy.d.ts.map +1 -1
- package/lib/AWS/IAM/Policy.js.map +1 -1
- package/lib/AWS/Lambda/BucketEventSource.d.ts +1 -1
- package/lib/AWS/Lambda/BucketEventSource.d.ts.map +1 -1
- package/lib/AWS/Lambda/EventBridgeEventSource.d.ts +1 -1
- package/lib/AWS/Lambda/EventBridgeEventSource.d.ts.map +1 -1
- package/lib/AWS/Lambda/QueueEventSource.d.ts +1 -1
- package/lib/AWS/Lambda/QueueEventSource.d.ts.map +1 -1
- package/lib/AWS/Lambda/StreamEventSource.d.ts +1 -1
- package/lib/AWS/Lambda/StreamEventSource.d.ts.map +1 -1
- package/lib/AWS/Lambda/TableEventSource.d.ts +1 -1
- package/lib/AWS/Lambda/TableEventSource.d.ts.map +1 -1
- package/lib/AWS/Lambda/TopicEventSource.d.ts +1 -1
- package/lib/AWS/Lambda/TopicEventSource.d.ts.map +1 -1
- package/lib/AWS/Providers.d.ts +1 -1
- package/lib/AWS/Providers.d.ts.map +1 -1
- package/lib/AWS/Providers.js +2 -1
- package/lib/AWS/Providers.js.map +1 -1
- package/lib/Auth/Credentials.d.ts +21 -6
- package/lib/Auth/Credentials.d.ts.map +1 -1
- package/lib/Auth/Credentials.js +30 -31
- package/lib/Auth/Credentials.js.map +1 -1
- package/lib/Auth/Profile.d.ts +31 -34
- package/lib/Auth/Profile.d.ts.map +1 -1
- package/lib/Auth/Profile.js +46 -31
- package/lib/Auth/Profile.js.map +1 -1
- package/lib/Axiom/AuthProvider.d.ts +2 -1
- package/lib/Axiom/AuthProvider.d.ts.map +1 -1
- package/lib/Axiom/AuthProvider.js +149 -143
- package/lib/Axiom/AuthProvider.js.map +1 -1
- package/lib/Axiom/Credentials.d.ts +2 -1
- package/lib/Axiom/Credentials.d.ts.map +1 -1
- package/lib/Axiom/Credentials.js +4 -4
- package/lib/Axiom/Credentials.js.map +1 -1
- package/lib/Axiom/Providers.d.ts +1 -1
- package/lib/Axiom/Providers.d.ts.map +1 -1
- package/lib/Axiom/Providers.js +3 -1
- package/lib/Axiom/Providers.js.map +1 -1
- package/lib/Cli/LoggingCli.d.ts.map +1 -1
- package/lib/Cli/LoggingCli.js +105 -7
- package/lib/Cli/LoggingCli.js.map +1 -1
- package/lib/Cli/checkVersion.d.ts +13 -0
- package/lib/Cli/checkVersion.d.ts.map +1 -0
- package/lib/Cli/checkVersion.js +47 -0
- package/lib/Cli/checkVersion.js.map +1 -0
- package/lib/Cli/commands/_shared.d.ts +2 -2
- package/lib/Cli/commands/_shared.d.ts.map +1 -1
- package/lib/Cli/commands/_shared.js +3 -3
- package/lib/Cli/commands/_shared.js.map +1 -1
- package/lib/Cli/commands/aws.d.ts +6 -0
- package/lib/Cli/commands/aws.d.ts.map +1 -0
- package/lib/Cli/commands/aws.js +63 -0
- package/lib/Cli/commands/aws.js.map +1 -0
- package/lib/Cli/commands/cloudflare.d.ts +17 -0
- package/lib/Cli/commands/cloudflare.d.ts.map +1 -0
- package/lib/Cli/commands/cloudflare.js +111 -0
- package/lib/Cli/commands/cloudflare.js.map +1 -0
- package/lib/Cli/commands/deploy.d.ts +6 -5
- package/lib/Cli/commands/deploy.d.ts.map +1 -1
- package/lib/Cli/commands/deploy.js +10 -10
- package/lib/Cli/commands/deploy.js.map +1 -1
- package/lib/Cli/commands/dev.d.ts.map +1 -1
- package/lib/Cli/commands/dev.js +16 -16
- package/lib/Cli/commands/dev.js.map +1 -1
- package/lib/Cli/commands/login.d.ts +2 -1
- package/lib/Cli/commands/login.d.ts.map +1 -1
- package/lib/Cli/commands/login.js +9 -8
- package/lib/Cli/commands/login.js.map +1 -1
- package/lib/Cli/commands/logs.d.ts +1 -1
- package/lib/Cli/commands/logs.d.ts.map +1 -1
- package/lib/Cli/commands/logs.js +7 -7
- package/lib/Cli/commands/logs.js.map +1 -1
- package/lib/Cli/commands/profile.d.ts +3 -1
- package/lib/Cli/commands/profile.d.ts.map +1 -1
- package/lib/Cli/commands/profile.js +14 -11
- package/lib/Cli/commands/profile.js.map +1 -1
- package/lib/Cli/commands/state.d.ts +1 -1
- package/lib/Cli/commands/state.d.ts.map +1 -1
- package/lib/Cli/commands/state.js +8 -8
- package/lib/Cli/commands/state.js.map +1 -1
- package/lib/Cli/commands/tail.d.ts +1 -1
- package/lib/Cli/commands/tail.d.ts.map +1 -1
- package/lib/Cli/commands/tail.js +7 -7
- package/lib/Cli/commands/tail.js.map +1 -1
- package/lib/Cli/exec.d.ts.map +1 -1
- package/lib/Cli/exec.js +5 -3
- package/lib/Cli/exec.js.map +1 -1
- package/lib/Cli/main.d.ts.map +1 -1
- package/lib/Cli/main.js +17 -5
- package/lib/Cli/main.js.map +1 -1
- package/lib/Cli/selectCli.d.ts +12 -0
- package/lib/Cli/selectCli.d.ts.map +1 -0
- package/lib/Cli/selectCli.js +32 -0
- package/lib/Cli/selectCli.js.map +1 -0
- package/lib/Cloudflare/Auth/AuthProvider.d.ts +2 -1
- package/lib/Cloudflare/Auth/AuthProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Auth/AuthProvider.js +235 -214
- package/lib/Cloudflare/Auth/AuthProvider.js.map +1 -1
- package/lib/Cloudflare/CloudflareEnvironment.d.ts +2 -1
- package/lib/Cloudflare/CloudflareEnvironment.d.ts.map +1 -1
- package/lib/Cloudflare/CloudflareEnvironment.js +3 -2
- package/lib/Cloudflare/CloudflareEnvironment.js.map +1 -1
- package/lib/Cloudflare/Credentials.d.ts +2 -1
- package/lib/Cloudflare/Credentials.d.ts.map +1 -1
- package/lib/Cloudflare/Credentials.js +4 -4
- package/lib/Cloudflare/Credentials.js.map +1 -1
- package/lib/Cloudflare/D1/D1Clone.d.ts +2 -1
- package/lib/Cloudflare/D1/D1Clone.d.ts.map +1 -1
- package/lib/Cloudflare/D1/D1Database.d.ts +2 -1
- package/lib/Cloudflare/D1/D1Database.d.ts.map +1 -1
- package/lib/Cloudflare/D1/D1Import.d.ts +3 -1
- package/lib/Cloudflare/D1/D1Import.d.ts.map +1 -1
- package/lib/Cloudflare/Local/Sidecar.d.ts +11 -4
- package/lib/Cloudflare/Local/Sidecar.d.ts.map +1 -1
- package/lib/Cloudflare/Local/Sidecar.js +8 -6
- package/lib/Cloudflare/Local/Sidecar.js.map +1 -1
- package/lib/Cloudflare/Local/SidecarHandlers.d.ts.map +1 -1
- package/lib/Cloudflare/Local/SidecarHandlers.js +1 -5
- package/lib/Cloudflare/Local/SidecarHandlers.js.map +1 -1
- package/lib/Cloudflare/Local/SidecarServer.js +5 -2
- package/lib/Cloudflare/Local/SidecarServer.js.map +1 -1
- package/lib/Cloudflare/Logs.d.ts +5 -0
- package/lib/Cloudflare/Logs.d.ts.map +1 -1
- package/lib/Cloudflare/Logs.js +70 -1
- package/lib/Cloudflare/Logs.js.map +1 -1
- package/lib/Cloudflare/Providers.d.ts +1 -1
- package/lib/Cloudflare/Providers.d.ts.map +1 -1
- package/lib/Cloudflare/Providers.js +4 -1
- package/lib/Cloudflare/Providers.js.map +1 -1
- package/lib/Cloudflare/Queue/Queue.d.ts +1 -1
- package/lib/Cloudflare/Queue/Queue.js +1 -1
- package/lib/Cloudflare/Queue/QueueConsumer.d.ts +6 -2
- package/lib/Cloudflare/Queue/QueueConsumer.d.ts.map +1 -1
- package/lib/Cloudflare/Queue/QueueConsumer.js +194 -53
- package/lib/Cloudflare/Queue/QueueConsumer.js.map +1 -1
- package/lib/Cloudflare/Queue/QueueEventSource.d.ts +106 -0
- package/lib/Cloudflare/Queue/QueueEventSource.d.ts.map +1 -0
- package/lib/Cloudflare/Queue/QueueEventSource.js +145 -0
- package/lib/Cloudflare/Queue/QueueEventSource.js.map +1 -0
- package/lib/Cloudflare/Queue/index.d.ts +1 -0
- package/lib/Cloudflare/Queue/index.d.ts.map +1 -1
- package/lib/Cloudflare/Queue/index.js +1 -0
- package/lib/Cloudflare/Queue/index.js.map +1 -1
- package/lib/Cloudflare/R2/R2Bucket.d.ts +94 -0
- package/lib/Cloudflare/R2/R2Bucket.d.ts.map +1 -1
- package/lib/Cloudflare/R2/R2Bucket.js +186 -2
- package/lib/Cloudflare/R2/R2Bucket.js.map +1 -1
- package/lib/Cloudflare/StateStore/State.d.ts +4 -3
- package/lib/Cloudflare/StateStore/State.d.ts.map +1 -1
- package/lib/Cloudflare/StateStore/State.js +16 -8
- package/lib/Cloudflare/StateStore/State.js.map +1 -1
- package/lib/Cloudflare/VpcService/VpcServiceRef.d.ts +1 -1
- package/lib/Cloudflare/VpcService/VpcServiceRef.d.ts.map +1 -1
- package/lib/Cloudflare/Website/StaticSite.d.ts.map +1 -1
- package/lib/Cloudflare/Website/StaticSite.js +10 -1
- package/lib/Cloudflare/Website/StaticSite.js.map +1 -1
- package/lib/Cloudflare/Workers/Assets.d.ts +1 -1
- package/lib/Cloudflare/Workers/Assets.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js +11 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
- package/lib/Cloudflare/Workers/Worker.d.ts +9 -7
- package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.js +62 -142
- package/lib/Cloudflare/Workers/Worker.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBundle.d.ts +2 -0
- package/lib/Cloudflare/Workers/WorkerBundle.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBundle.js +21 -7
- package/lib/Cloudflare/Workers/WorkerBundle.js.map +1 -1
- package/lib/Cloudflare/Zone.d.ts +14 -0
- package/lib/Cloudflare/Zone.d.ts.map +1 -0
- package/lib/Cloudflare/Zone.js +44 -0
- package/lib/Cloudflare/Zone.js.map +1 -0
- package/lib/Drizzle/Schema.d.ts.map +1 -1
- package/lib/Drizzle/Schema.js +20 -5
- package/lib/Drizzle/Schema.js.map +1 -1
- package/lib/GitHub/AuthProvider.d.ts +3 -1
- package/lib/GitHub/AuthProvider.d.ts.map +1 -1
- package/lib/GitHub/AuthProvider.js +114 -108
- package/lib/GitHub/AuthProvider.js.map +1 -1
- package/lib/GitHub/Credentials.d.ts +2 -1
- package/lib/GitHub/Credentials.d.ts.map +1 -1
- package/lib/GitHub/Credentials.js +4 -4
- package/lib/GitHub/Credentials.js.map +1 -1
- package/lib/GitHub/Providers.d.ts +1 -1
- package/lib/GitHub/Providers.d.ts.map +1 -1
- package/lib/GitHub/Providers.js +3 -1
- package/lib/GitHub/Providers.js.map +1 -1
- package/lib/GitHub/Secrets.d.ts.map +1 -1
- package/lib/GitHub/Secrets.js +14 -1
- package/lib/GitHub/Secrets.js.map +1 -1
- package/lib/GitHub/Variables.d.ts +40 -0
- package/lib/GitHub/Variables.d.ts.map +1 -0
- package/lib/GitHub/Variables.js +28 -0
- package/lib/GitHub/Variables.js.map +1 -0
- package/lib/GitHub/index.d.ts +1 -0
- package/lib/GitHub/index.d.ts.map +1 -1
- package/lib/GitHub/index.js +1 -0
- package/lib/GitHub/index.js.map +1 -1
- package/lib/Neon/AuthProvider.d.ts +3 -1
- package/lib/Neon/AuthProvider.d.ts.map +1 -1
- package/lib/Neon/AuthProvider.js +87 -80
- package/lib/Neon/AuthProvider.js.map +1 -1
- package/lib/Neon/Credentials.d.ts +2 -1
- package/lib/Neon/Credentials.d.ts.map +1 -1
- package/lib/Neon/Credentials.js +4 -4
- package/lib/Neon/Credentials.js.map +1 -1
- package/lib/Neon/NeonEnvironment.d.ts +2 -1
- package/lib/Neon/NeonEnvironment.d.ts.map +1 -1
- package/lib/Neon/NeonEnvironment.js +3 -2
- package/lib/Neon/NeonEnvironment.js.map +1 -1
- package/lib/Neon/Project.d.ts +16 -0
- package/lib/Neon/Project.d.ts.map +1 -1
- package/lib/Neon/Project.js +25 -0
- package/lib/Neon/Project.js.map +1 -1
- package/lib/Neon/Providers.d.ts +1 -1
- package/lib/Neon/Providers.d.ts.map +1 -1
- package/lib/Neon/Providers.js +3 -1
- package/lib/Neon/Providers.js.map +1 -1
- package/lib/Neon/api.d.ts +1 -0
- package/lib/Neon/api.d.ts.map +1 -1
- package/lib/Neon/api.js +1 -0
- package/lib/Neon/api.js.map +1 -1
- package/lib/Sidecar/RpcClient.d.ts.map +1 -1
- package/lib/Sidecar/RpcClient.js +8 -5
- package/lib/Sidecar/RpcClient.js.map +1 -1
- package/lib/Sidecar/RpcPaths.d.ts +5 -0
- package/lib/Sidecar/RpcPaths.d.ts.map +1 -1
- package/lib/Sidecar/RpcPaths.js +10 -1
- package/lib/Sidecar/RpcPaths.js.map +1 -1
- package/lib/Sidecar/RpcServer.d.ts +24 -4
- package/lib/Sidecar/RpcServer.d.ts.map +1 -1
- package/lib/Sidecar/RpcServer.js +70 -15
- package/lib/Sidecar/RpcServer.js.map +1 -1
- package/lib/Sidecar/RpcServerBun.d.ts +4 -0
- package/lib/Sidecar/RpcServerBun.d.ts.map +1 -0
- package/lib/Sidecar/RpcServerBun.js +28 -0
- package/lib/Sidecar/RpcServerBun.js.map +1 -0
- package/lib/Sidecar/RpcServerNode.d.ts +4 -0
- package/lib/Sidecar/RpcServerNode.d.ts.map +1 -0
- package/lib/Sidecar/RpcServerNode.js +39 -0
- package/lib/Sidecar/RpcServerNode.js.map +1 -0
- package/lib/Sidecar/RpcServices.d.ts +6 -0
- package/lib/Sidecar/RpcServices.d.ts.map +1 -0
- package/lib/Sidecar/RpcServices.js +29 -0
- package/lib/Sidecar/RpcServices.js.map +1 -0
- package/lib/Stack.d.ts +5 -3
- package/lib/Stack.d.ts.map +1 -1
- package/lib/Stack.js +3 -1
- package/lib/Stack.js.map +1 -1
- package/lib/Test/Core.d.ts.map +1 -1
- package/lib/Test/Core.js +5 -4
- package/lib/Test/Core.js.map +1 -1
- package/lib/Util/PlatformServices.js +1 -1
- package/lib/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +15 -12
- package/src/AWS/AuthProvider.ts +269 -259
- package/src/AWS/Environment.ts +57 -3
- package/src/AWS/IAM/OpenIDConnectProvider.ts +19 -8
- package/src/AWS/IAM/Policy.ts +1 -1
- package/src/AWS/Providers.ts +2 -0
- package/src/Auth/Credentials.ts +82 -46
- package/src/Auth/Profile.ts +123 -69
- package/src/Axiom/AuthProvider.ts +263 -255
- package/src/Axiom/Credentials.ts +3 -4
- package/src/Axiom/Providers.ts +4 -0
- package/src/Cli/LoggingCli.ts +127 -11
- package/src/Cli/checkVersion.ts +57 -0
- package/src/Cli/commands/_shared.ts +4 -4
- package/src/Cli/commands/aws.ts +127 -0
- package/src/Cli/commands/cloudflare.ts +222 -0
- package/src/Cli/commands/deploy.ts +11 -10
- package/src/Cli/commands/dev.ts +28 -33
- package/src/Cli/commands/login.ts +9 -12
- package/src/Cli/commands/logs.ts +8 -8
- package/src/Cli/commands/profile.ts +14 -16
- package/src/Cli/commands/state.ts +8 -8
- package/src/Cli/commands/tail.ts +8 -8
- package/src/Cli/exec.ts +7 -3
- package/src/Cli/main.ts +20 -5
- package/src/Cli/selectCli.ts +33 -0
- package/src/Cloudflare/Auth/AuthProvider.ts +445 -430
- package/src/Cloudflare/CloudflareEnvironment.ts +3 -2
- package/src/Cloudflare/Credentials.ts +3 -4
- package/src/Cloudflare/Local/Sidecar.ts +13 -10
- package/src/Cloudflare/Local/SidecarHandlers.ts +8 -13
- package/src/Cloudflare/Local/SidecarServer.ts +6 -1
- package/src/Cloudflare/Logs.ts +115 -1
- package/src/Cloudflare/Providers.ts +6 -0
- package/src/Cloudflare/Queue/Queue.ts +1 -1
- package/src/Cloudflare/Queue/QueueConsumer.ts +262 -60
- package/src/Cloudflare/Queue/QueueEventSource.ts +234 -0
- package/src/Cloudflare/Queue/index.ts +1 -0
- package/src/Cloudflare/R2/R2Bucket.ts +337 -2
- package/src/Cloudflare/StateStore/State.ts +25 -16
- package/src/Cloudflare/Website/StaticSite.ts +11 -1
- package/src/Cloudflare/Workers/LocalWorkerProvider.ts +9 -1
- package/src/Cloudflare/Workers/Worker.ts +83 -203
- package/src/Cloudflare/Workers/WorkerBundle.ts +38 -12
- package/src/Cloudflare/Zone.ts +88 -0
- package/src/Drizzle/Schema.ts +21 -5
- package/src/GitHub/AuthProvider.ts +221 -217
- package/src/GitHub/Credentials.ts +3 -4
- package/src/GitHub/Providers.ts +4 -0
- package/src/GitHub/Secrets.ts +25 -1
- package/src/GitHub/Variables.ts +54 -0
- package/src/GitHub/index.ts +1 -0
- package/src/Neon/AuthProvider.ts +160 -154
- package/src/Neon/Credentials.ts +3 -4
- package/src/Neon/NeonEnvironment.ts +3 -2
- package/src/Neon/Project.ts +42 -0
- package/src/Neon/Providers.ts +4 -0
- package/src/Neon/api.ts +2 -0
- package/src/Sidecar/RpcClient.ts +8 -7
- package/src/Sidecar/RpcPaths.ts +11 -1
- package/src/Sidecar/RpcServer.ts +97 -24
- package/src/Sidecar/RpcServerBun.ts +41 -0
- package/src/Sidecar/RpcServerNode.ts +51 -0
- package/src/Sidecar/RpcServices.ts +48 -0
- package/src/Stack.ts +8 -0
- package/src/Test/Core.ts +10 -4
- package/src/Util/PlatformServices.ts +1 -1
- package/lib/Cli/commands/bootstrap.d.ts +0 -20
- package/lib/Cli/commands/bootstrap.d.ts.map +0 -1
- package/lib/Cli/commands/bootstrap.js +0 -107
- package/lib/Cli/commands/bootstrap.js.map +0 -1
- package/lib/Sidecar/RpcTransport.d.ts +0 -22
- package/lib/Sidecar/RpcTransport.d.ts.map +0 -1
- package/lib/Sidecar/RpcTransport.js +0 -81
- package/lib/Sidecar/RpcTransport.js.map +0 -1
- package/lib/Test/TestCli.d.ts +0 -19
- package/lib/Test/TestCli.d.ts.map +0 -1
- package/lib/Test/TestCli.js +0 -175
- package/lib/Test/TestCli.js.map +0 -1
- package/src/Cli/commands/bootstrap.ts +0 -216
- package/src/Sidecar/RpcTransport.ts +0 -85
- package/src/Test/TestCli.ts +0 -221
package/src/AWS/Environment.ts
CHANGED
|
@@ -11,12 +11,17 @@ import * as Data from "effect/Data";
|
|
|
11
11
|
import * as Effect from "effect/Effect";
|
|
12
12
|
import * as Layer from "effect/Layer";
|
|
13
13
|
import * as Option from "effect/Option";
|
|
14
|
+
import * as Redacted from "effect/Redacted";
|
|
14
15
|
|
|
15
16
|
export const AWS_PROFILE = Config.string("AWS_PROFILE").pipe(
|
|
16
17
|
Config.withDefault("default"),
|
|
17
18
|
);
|
|
18
19
|
|
|
19
20
|
export const AWS_REGION = Config.string("AWS_REGION");
|
|
21
|
+
export const AWS_ACCOUNT_ID = Config.string("AWS_ACCOUNT_ID");
|
|
22
|
+
export const AWS_ACCESS_KEY_ID = Config.string("AWS_ACCESS_KEY_ID");
|
|
23
|
+
export const AWS_SECRET_ACCESS_KEY = Config.redacted("AWS_SECRET_ACCESS_KEY");
|
|
24
|
+
export const AWS_SESSION_TOKEN = Config.redacted("AWS_SESSION_TOKEN");
|
|
20
25
|
|
|
21
26
|
export type AccountID = string;
|
|
22
27
|
export type RegionID = string;
|
|
@@ -52,9 +57,18 @@ export class AWSEnvironment extends Context.Service<
|
|
|
52
57
|
>()("AWS::Environment") {}
|
|
53
58
|
|
|
54
59
|
/**
|
|
55
|
-
* Build an `AWSEnvironment` from
|
|
56
|
-
*
|
|
57
|
-
*
|
|
60
|
+
* Build an `AWSEnvironment` from one of two sources, in priority order:
|
|
61
|
+
*
|
|
62
|
+
* 1. **Environment variables** — used when `AWS_ACCESS_KEY_ID` is set, as
|
|
63
|
+
* it is on GitHub Actions runners after `aws-actions/configure-aws-credentials`
|
|
64
|
+
* runs (OIDC), or whenever the user has exported static creds. Requires
|
|
65
|
+
* `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`, and `AWS_ACCOUNT_ID`. The role
|
|
66
|
+
* ARN's account ID is exported by `configure-aws-credentials` as
|
|
67
|
+
* `AWS_ACCOUNT_ID` when invoked with `output-credentials: true`.
|
|
68
|
+
* 2. **SSO profile** (`AWS_PROFILE`, default `"default"`) — used locally
|
|
69
|
+
* when no static creds are exported. Reads the profile's
|
|
70
|
+
* `sso_account_id` / `region` from `~/.aws/config` and refreshes
|
|
71
|
+
* credentials lazily via `aws sso login`.
|
|
58
72
|
*/
|
|
59
73
|
export const Default = Layer.effect(
|
|
60
74
|
AWSEnvironment,
|
|
@@ -62,6 +76,46 @@ export const Default = Layer.effect(
|
|
|
62
76
|
).pipe(Layer.orDie);
|
|
63
77
|
|
|
64
78
|
export const loadDefault = () =>
|
|
79
|
+
Effect.gen(function* () {
|
|
80
|
+
// Env-credentials path only kicks in under CI (where
|
|
81
|
+
// `aws-actions/configure-aws-credentials` exports AWS_ACCESS_KEY_ID
|
|
82
|
+
// and friends). Locally we always go through SSO so a stray
|
|
83
|
+
// AWS_ACCESS_KEY_ID in the shell doesn't silently override the
|
|
84
|
+
// user's `~/.aws/config` profile.
|
|
85
|
+
const ci = yield* Config.boolean("CI").pipe(Config.withDefault(false));
|
|
86
|
+
if (ci) {
|
|
87
|
+
const accessKeyId = yield* AWS_ACCESS_KEY_ID.pipe(
|
|
88
|
+
Config.option,
|
|
89
|
+
Config.map(Option.getOrUndefined),
|
|
90
|
+
);
|
|
91
|
+
if (accessKeyId) {
|
|
92
|
+
return yield* loadFromEnv(accessKeyId);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return yield* loadFromSso();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const loadFromEnv = (accessKeyId: string) =>
|
|
99
|
+
Effect.gen(function* () {
|
|
100
|
+
const secretAccessKey = yield* AWS_SECRET_ACCESS_KEY;
|
|
101
|
+
const sessionToken = yield* AWS_SESSION_TOKEN.pipe(
|
|
102
|
+
Config.option,
|
|
103
|
+
Config.map(Option.getOrUndefined),
|
|
104
|
+
);
|
|
105
|
+
const region = yield* AWS_REGION;
|
|
106
|
+
const accountId = yield* AWS_ACCOUNT_ID;
|
|
107
|
+
return {
|
|
108
|
+
accountId,
|
|
109
|
+
region,
|
|
110
|
+
credentials: Effect.succeed({
|
|
111
|
+
accessKeyId: Redacted.make(accessKeyId),
|
|
112
|
+
secretAccessKey,
|
|
113
|
+
sessionToken,
|
|
114
|
+
} satisfies ResolvedCredentials),
|
|
115
|
+
} satisfies AWSEnvironmentShape;
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const loadFromSso = () =>
|
|
65
119
|
Effect.gen(function* () {
|
|
66
120
|
const profileName = yield* AWS_PROFILE;
|
|
67
121
|
const auth = yield* Auth.Default;
|
|
@@ -3,9 +3,9 @@ import * as Effect from "effect/Effect";
|
|
|
3
3
|
import { isResolved } from "../../Diff.ts";
|
|
4
4
|
import * as Provider from "../../Provider.ts";
|
|
5
5
|
import { Resource } from "../../Resource.ts";
|
|
6
|
-
import type { Providers } from "../Providers.ts";
|
|
7
6
|
import { diffTags } from "../../Tags.ts";
|
|
8
7
|
import { AWSEnvironment } from "../Environment.ts";
|
|
8
|
+
import type { Providers } from "../Providers.ts";
|
|
9
9
|
import { toTagRecord } from "./common.ts";
|
|
10
10
|
|
|
11
11
|
export interface OpenIDConnectProviderProps {
|
|
@@ -14,13 +14,17 @@ export interface OpenIDConnectProviderProps {
|
|
|
14
14
|
*/
|
|
15
15
|
url: string;
|
|
16
16
|
/**
|
|
17
|
-
* Client IDs allowed for the provider.
|
|
17
|
+
* Client IDs allowed for the provider. AWS rejects requests with an
|
|
18
|
+
* empty list, so the prop is typed as a non-empty tuple.
|
|
18
19
|
*/
|
|
19
|
-
clientIDList?: string[];
|
|
20
|
+
clientIDList?: [string, ...string[]];
|
|
20
21
|
/**
|
|
21
|
-
* Certificate thumbprints for the provider.
|
|
22
|
+
* Certificate thumbprints for the provider. AWS auto-manages thumbprints
|
|
23
|
+
* for well-known IdPs (e.g. GitHub Actions), so this is optional — but
|
|
24
|
+
* `iam.updateOpenIDConnectProviderThumbprint` rejects an empty list, so
|
|
25
|
+
* the prop is typed as a non-empty tuple when supplied.
|
|
22
26
|
*/
|
|
23
|
-
thumbprintList?: string[];
|
|
27
|
+
thumbprintList?: [string, ...string[]];
|
|
24
28
|
/**
|
|
25
29
|
* User-defined tags to apply to the provider.
|
|
26
30
|
*/
|
|
@@ -34,7 +38,11 @@ export interface OpenIDConnectProvider extends Resource<
|
|
|
34
38
|
openIDConnectProviderArn: string;
|
|
35
39
|
url: string;
|
|
36
40
|
clientIDList: string[];
|
|
37
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Reflects the desired state — `undefined` when the user opted out of
|
|
43
|
+
* managing thumbprints (AWS auto-manages them for well-known IdPs).
|
|
44
|
+
*/
|
|
45
|
+
thumbprintList: string[] | undefined;
|
|
38
46
|
tags: Record<string, string>;
|
|
39
47
|
},
|
|
40
48
|
never,
|
|
@@ -181,10 +189,13 @@ export const OpenIDConnectProviderProvider = () =>
|
|
|
181
189
|
|
|
182
190
|
// Sync thumbprints — `updateOpenIDConnectProviderThumbprint`
|
|
183
191
|
// replaces the entire list, so call it whenever the set differs.
|
|
184
|
-
|
|
192
|
+
// When the user didn't request a list we leave the cloud-managed
|
|
193
|
+
// thumbprints alone (AWS auto-manages for well-known IdPs).
|
|
194
|
+
const desiredThumbprints = news.thumbprintList;
|
|
185
195
|
if (
|
|
196
|
+
desiredThumbprints &&
|
|
186
197
|
JSON.stringify([...observedThumbprints].sort()) !==
|
|
187
|
-
|
|
198
|
+
JSON.stringify([...desiredThumbprints].sort())
|
|
188
199
|
) {
|
|
189
200
|
yield* iam.updateOpenIDConnectProviderThumbprint({
|
|
190
201
|
OpenIDConnectProviderArn: providerArn,
|
package/src/AWS/IAM/Policy.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { isResolved } from "../../Diff.ts";
|
|
|
4
4
|
import { createPhysicalName } from "../../PhysicalName.ts";
|
|
5
5
|
import * as Provider from "../../Provider.ts";
|
|
6
6
|
import { Resource } from "../../Resource.ts";
|
|
7
|
-
import type { Providers } from "../Providers.ts";
|
|
8
7
|
import {
|
|
9
8
|
createInternalTags,
|
|
10
9
|
createTagsList,
|
|
@@ -13,6 +12,7 @@ import {
|
|
|
13
12
|
} from "../../Tags.ts";
|
|
14
13
|
import type { AccountID } from "../Environment.ts";
|
|
15
14
|
import { AWSEnvironment } from "../Environment.ts";
|
|
15
|
+
import type { Providers } from "../Providers.ts";
|
|
16
16
|
import {
|
|
17
17
|
oldestNondefaultPolicyVersion,
|
|
18
18
|
parsePolicyDocument,
|
package/src/AWS/Providers.ts
CHANGED
|
@@ -21,6 +21,7 @@ import { Random, RandomProvider } from "../Random.ts";
|
|
|
21
21
|
import * as ACM from "./ACM/index.ts";
|
|
22
22
|
import * as ApiGateway from "./ApiGateway/index.ts";
|
|
23
23
|
import * as Assets from "./Assets.ts";
|
|
24
|
+
import { CredentialsStoreLive } from "../Auth/Credentials.ts";
|
|
24
25
|
import { AwsAuth } from "./AuthProvider.ts";
|
|
25
26
|
import * as AutoScaling from "./AutoScaling/index.ts";
|
|
26
27
|
import * as CloudFront from "./CloudFront/index.ts";
|
|
@@ -578,6 +579,7 @@ export const providers = () =>
|
|
|
578
579
|
Layer.provideMerge(Endpoint.fromEnvironment),
|
|
579
580
|
Layer.provideMerge(DefaultEnvironment),
|
|
580
581
|
Layer.provideMerge(AwsAuth),
|
|
582
|
+
Layer.provideMerge(CredentialsStoreLive),
|
|
581
583
|
// Apply a blanket retry policy to every AWS SDK call. Like distilled's
|
|
582
584
|
// `makeDefault` it retries throttling, 5xx, and Smithy `@retryable`
|
|
583
585
|
// errors with exponential backoff + jitter + `RetryAfter` header
|
package/src/Auth/Credentials.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import * as Context from "effect/Context";
|
|
1
2
|
import * as Effect from "effect/Effect";
|
|
2
3
|
import * as FileSystem from "effect/FileSystem";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import type { PlatformError } from "effect/PlatformError";
|
|
3
6
|
import * as Redacted from "effect/Redacted";
|
|
4
7
|
import path from "pathe";
|
|
5
8
|
import { rootDir } from "./Profile.ts";
|
|
@@ -12,55 +15,88 @@ export const profileCredentialsDirPath = (profile: string) =>
|
|
|
12
15
|
export const credentialsFilePath = (profile: string, provider: string) =>
|
|
13
16
|
path.join(profileCredentialsDirPath(profile), `${provider}.json`);
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Service exposing per-profile credential file helpers. All methods have
|
|
20
|
+
* `R = never` — the {@link FileSystem.FileSystem} requirement is captured
|
|
21
|
+
* by {@link CredentialsStoreLive} when the layer is built.
|
|
22
|
+
*/
|
|
23
|
+
export interface CredentialsStoreService {
|
|
24
|
+
readonly read: <T>(
|
|
25
|
+
profile: string,
|
|
26
|
+
provider: string,
|
|
27
|
+
) => Effect.Effect<T | undefined>;
|
|
28
|
+
readonly write: <T>(
|
|
29
|
+
profile: string,
|
|
30
|
+
provider: string,
|
|
31
|
+
credentials: T,
|
|
32
|
+
) => Effect.Effect<void, PlatformError>;
|
|
33
|
+
readonly delete: (profile: string, provider: string) => Effect.Effect<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Recursively remove the `~/.alchemy/credentials/{profile}` directory
|
|
36
|
+
* containing all per-provider secrets for `profile`. No-op if it doesn't exist.
|
|
37
|
+
*/
|
|
38
|
+
readonly deleteProfile: (profile: string) => Effect.Effect<void>;
|
|
39
|
+
}
|
|
30
40
|
|
|
31
|
-
export
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
) {
|
|
36
|
-
const fs = yield* FileSystem.FileSystem;
|
|
37
|
-
const filePath = credentialsFilePath(profile, provider);
|
|
38
|
-
yield* fs.makeDirectory(path.dirname(filePath), { recursive: true });
|
|
39
|
-
yield* fs.writeFileString(filePath, JSON.stringify(credentials, null, 2));
|
|
40
|
-
});
|
|
41
|
+
export class CredentialsStore extends Context.Service<
|
|
42
|
+
CredentialsStore,
|
|
43
|
+
CredentialsStoreService
|
|
44
|
+
>()("Alchemy::CredentialsStore") {}
|
|
41
45
|
|
|
42
|
-
export const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const fs = yield* FileSystem.FileSystem;
|
|
47
|
-
yield* fs
|
|
48
|
-
.remove(credentialsFilePath(profile, provider))
|
|
49
|
-
.pipe(Effect.catch(() => Effect.void));
|
|
50
|
-
});
|
|
46
|
+
export const CredentialsStoreLive = Layer.effect(
|
|
47
|
+
CredentialsStore,
|
|
48
|
+
Effect.gen(function* () {
|
|
49
|
+
const fs = yield* FileSystem.FileSystem;
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
51
|
+
const read = <T>(
|
|
52
|
+
profile: string,
|
|
53
|
+
provider: string,
|
|
54
|
+
): Effect.Effect<T | undefined> =>
|
|
55
|
+
fs.readFileString(credentialsFilePath(profile, provider)).pipe(
|
|
56
|
+
Effect.catch(() => Effect.succeed(undefined as string | undefined)),
|
|
57
|
+
Effect.map((data) => {
|
|
58
|
+
if (data === undefined) return undefined as T | undefined;
|
|
59
|
+
try {
|
|
60
|
+
return JSON.parse(data) as T;
|
|
61
|
+
} catch {
|
|
62
|
+
return undefined as T | undefined;
|
|
63
|
+
}
|
|
64
|
+
}),
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const write = <T>(
|
|
68
|
+
profile: string,
|
|
69
|
+
provider: string,
|
|
70
|
+
credentials: T,
|
|
71
|
+
): Effect.Effect<void, PlatformError> => {
|
|
72
|
+
const filePath = credentialsFilePath(profile, provider);
|
|
73
|
+
return fs
|
|
74
|
+
.makeDirectory(path.dirname(filePath), { recursive: true })
|
|
75
|
+
.pipe(
|
|
76
|
+
Effect.flatMap(() =>
|
|
77
|
+
fs.writeFileString(filePath, JSON.stringify(credentials, null, 2)),
|
|
78
|
+
),
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const remove_ = (profile: string, provider: string): Effect.Effect<void> =>
|
|
83
|
+
fs
|
|
84
|
+
.remove(credentialsFilePath(profile, provider))
|
|
85
|
+
.pipe(Effect.catch(() => Effect.void));
|
|
86
|
+
|
|
87
|
+
const deleteProfile = (profile: string): Effect.Effect<void> =>
|
|
88
|
+
fs
|
|
89
|
+
.remove(profileCredentialsDirPath(profile), { recursive: true })
|
|
90
|
+
.pipe(Effect.catch(() => Effect.void));
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
read,
|
|
94
|
+
write,
|
|
95
|
+
delete: remove_,
|
|
96
|
+
deleteProfile,
|
|
97
|
+
} satisfies CredentialsStoreService;
|
|
98
|
+
}),
|
|
99
|
+
);
|
|
64
100
|
|
|
65
101
|
export function displayRedacted(
|
|
66
102
|
r: Redacted.Redacted<string>,
|
package/src/Auth/Profile.ts
CHANGED
|
@@ -3,9 +3,15 @@ import * as ConfigProvider from "effect/ConfigProvider";
|
|
|
3
3
|
import * as Context from "effect/Context";
|
|
4
4
|
import * as Effect from "effect/Effect";
|
|
5
5
|
import * as FileSystem from "effect/FileSystem";
|
|
6
|
+
import * as Layer from "effect/Layer";
|
|
7
|
+
import type { PlatformError } from "effect/PlatformError";
|
|
6
8
|
import os from "node:os";
|
|
7
9
|
import path from "pathe";
|
|
8
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
AuthError,
|
|
12
|
+
AuthProvider,
|
|
13
|
+
ConfigureContext,
|
|
14
|
+
} from "./AuthProvider.ts";
|
|
9
15
|
|
|
10
16
|
export const rootDir = path.join(os.homedir(), ".alchemy");
|
|
11
17
|
export const configFilePath = path.join(rootDir, "profiles.json");
|
|
@@ -52,59 +58,126 @@ const emptyConfig = (): AlchemyConfig["Service"] => ({
|
|
|
52
58
|
profiles: {},
|
|
53
59
|
});
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Service exposing on-disk profile helpers. All methods have `R = never` —
|
|
63
|
+
* the {@link FileSystem.FileSystem} requirement is captured by
|
|
64
|
+
* {@link ProfileLive} when the layer is built, freeing call sites from
|
|
65
|
+
* having to thread `FileSystem` through their own Effects.
|
|
66
|
+
*
|
|
67
|
+
* Use {@link Profile} directly when you need profile helpers — yield it
|
|
68
|
+
* from your `Effect.gen` and call its methods (each has `R = never`).
|
|
69
|
+
*/
|
|
70
|
+
export interface ProfileService {
|
|
71
|
+
readonly readConfig: Effect.Effect<AlchemyConfig["Service"]>;
|
|
72
|
+
readonly writeConfig: (
|
|
73
|
+
config: AlchemyConfig["Service"],
|
|
74
|
+
) => Effect.Effect<void, PlatformError>;
|
|
75
|
+
readonly getProfile: (
|
|
76
|
+
name: string,
|
|
77
|
+
) => Effect.Effect<AlchemyProfile | undefined>;
|
|
78
|
+
readonly setProfile: (
|
|
79
|
+
name: string,
|
|
80
|
+
profile: AlchemyProfile,
|
|
81
|
+
) => Effect.Effect<void, PlatformError>;
|
|
82
|
+
readonly deleteProfile: (
|
|
83
|
+
name: string,
|
|
84
|
+
) => Effect.Effect<boolean, PlatformError>;
|
|
85
|
+
readonly loadOrConfigure: <Config extends { method: string }>(
|
|
86
|
+
auth: AuthProvider<Config>,
|
|
87
|
+
profileName: string,
|
|
88
|
+
ctx: ConfigureContext,
|
|
89
|
+
) => Effect.Effect<Config, AuthError | PlatformError>;
|
|
90
|
+
}
|
|
85
91
|
|
|
86
|
-
export
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
Effect.sync(() => (config.profiles[name] = profile)),
|
|
90
|
-
),
|
|
91
|
-
Effect.flatMap(writeConfig),
|
|
92
|
-
);
|
|
92
|
+
export class Profile extends Context.Service<Profile, ProfileService>()(
|
|
93
|
+
"Alchemy::Profile",
|
|
94
|
+
) {}
|
|
93
95
|
|
|
94
96
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
+
* Layer that builds the {@link Profile} service. Captures the
|
|
98
|
+
* {@link FileSystem.FileSystem} dependency at layer-build time, so any
|
|
99
|
+
* Effect that yields {@link Profile} ends up with `R = Profile` (no
|
|
100
|
+
* `FileSystem` leak). Provide this once at the top of your runtime
|
|
101
|
+
* (alongside `PlatformServices` / `NodeContext`).
|
|
97
102
|
*/
|
|
98
|
-
export const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
export const ProfileLive = Layer.effect(
|
|
104
|
+
Profile,
|
|
105
|
+
Effect.gen(function* () {
|
|
106
|
+
const fs = yield* FileSystem.FileSystem;
|
|
107
|
+
|
|
108
|
+
const readConfig: Effect.Effect<AlchemyConfig["Service"]> = fs
|
|
109
|
+
.readFileString(configFilePath)
|
|
110
|
+
.pipe(
|
|
111
|
+
Effect.flatMap((data) =>
|
|
112
|
+
Effect.try({
|
|
113
|
+
try: () => {
|
|
114
|
+
const parsed = JSON.parse(data);
|
|
115
|
+
if (parsed?.version !== CONFIG_VERSION) {
|
|
116
|
+
// TODO(sam): this is destructive, should we maintain a chain of migrations from 0 to current?
|
|
117
|
+
return emptyConfig();
|
|
118
|
+
}
|
|
119
|
+
return parsed as AlchemyConfig["Service"];
|
|
120
|
+
},
|
|
121
|
+
catch: emptyConfig,
|
|
122
|
+
}),
|
|
123
|
+
),
|
|
124
|
+
Effect.orElseSucceed(emptyConfig),
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
const writeConfig = (config: AlchemyConfig["Service"]) =>
|
|
128
|
+
fs
|
|
129
|
+
.makeDirectory(path.dirname(configFilePath), { recursive: true })
|
|
130
|
+
.pipe(
|
|
131
|
+
Effect.flatMap(() =>
|
|
132
|
+
fs.writeFileString(configFilePath, JSON.stringify(config, null, 2)),
|
|
133
|
+
),
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const getProfile = (name: string) =>
|
|
137
|
+
readConfig.pipe(Effect.map((config) => config.profiles[name]));
|
|
138
|
+
|
|
139
|
+
const setProfile = (name: string, profile: AlchemyProfile) =>
|
|
140
|
+
readConfig.pipe(
|
|
141
|
+
Effect.tap((config) =>
|
|
142
|
+
Effect.sync(() => (config.profiles[name] = profile)),
|
|
143
|
+
),
|
|
144
|
+
Effect.flatMap(writeConfig),
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const deleteProfile = (name: string) =>
|
|
148
|
+
readConfig.pipe(
|
|
149
|
+
Effect.flatMap((config) => {
|
|
150
|
+
if (!(name in config.profiles)) {
|
|
151
|
+
return Effect.succeed(false);
|
|
152
|
+
}
|
|
153
|
+
delete config.profiles[name];
|
|
154
|
+
return writeConfig(config).pipe(Effect.as(true));
|
|
155
|
+
}),
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const loadOrConfigure = <Config extends { method: string }>(
|
|
159
|
+
auth: AuthProvider<Config>,
|
|
160
|
+
profileName: string,
|
|
161
|
+
ctx: ConfigureContext,
|
|
162
|
+
) =>
|
|
163
|
+
Effect.flatMap(getProfile(profileName), (existing) =>
|
|
164
|
+
existing?.[auth.name]
|
|
165
|
+
? Effect.succeed(existing[auth.name] as Config)
|
|
166
|
+
: Effect.tap(auth.configure(profileName, ctx), (config) =>
|
|
167
|
+
setProfile(profileName, { ...existing, [auth.name]: config }),
|
|
168
|
+
),
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
readConfig,
|
|
173
|
+
writeConfig,
|
|
174
|
+
getProfile,
|
|
175
|
+
setProfile,
|
|
176
|
+
deleteProfile,
|
|
177
|
+
loadOrConfigure,
|
|
178
|
+
} satisfies ProfileService;
|
|
179
|
+
}),
|
|
180
|
+
);
|
|
108
181
|
|
|
109
182
|
/**
|
|
110
183
|
* Returns a `ConfigProvider` that overrides `ALCHEMY_PROFILE` with the
|
|
@@ -129,22 +202,3 @@ export const withProfileOverride = (
|
|
|
129
202
|
);
|
|
130
203
|
return ConfigProvider.orElse(base)(overrideProvider);
|
|
131
204
|
};
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Load the stored config for the given AuthProvider in `profileName`.
|
|
135
|
-
* If absent, run the provider's `configure` step (passing through `ctx` so
|
|
136
|
-
* providers can pick a CI-friendly default) and persist the resulting config
|
|
137
|
-
* under the provider's name.
|
|
138
|
-
*/
|
|
139
|
-
export const loadOrConfigure = <Config extends { method: string }>(
|
|
140
|
-
auth: AuthProvider<Config>,
|
|
141
|
-
profileName: string,
|
|
142
|
-
ctx: ConfigureContext,
|
|
143
|
-
) =>
|
|
144
|
-
Effect.flatMap(getProfile(profileName), (existing) =>
|
|
145
|
-
existing?.[auth.name]
|
|
146
|
-
? Effect.succeed(existing?.[auth.name])
|
|
147
|
-
: Effect.tap(auth.configure(profileName, ctx), (config) =>
|
|
148
|
-
setProfile(profileName, { ...existing, [auth.name]: config }),
|
|
149
|
-
),
|
|
150
|
-
);
|