@thomasfosterau/effect-connect-alchemy-cloudflare 0.0.0 → 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Thomas Foster
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,62 @@
1
- # @thomasfosterau/effect-connect-alchemy-cloudflare
1
+ # `@thomasfosterau/effect-connect-alchemy-cloudflare`
2
2
 
3
- Placeholder reserved for npm trusted publishing; the first real release is 0.1.0, from https://github.com/thomasfosterau/effect-connect.
3
+ Deploy-time bindings for [`@thomasfosterau/effect-connect`](https://github.com/thomasfosterau/effect-connect/tree/trunk/packages/core#readme) on Cloudflare Workers deployed with [Alchemy](https://alchemy.run)'s Cloudflare provider, [`@alchemy.run/cloudflare`](https://www.npmjs.com/package/@alchemy.run/cloudflare). Each builder returns the record of Worker `env` bindings one provider reads, under that provider's own keys (`RESEND_API_KEY` for Resend, the one provider today). Secrets are `Redacted` values, which Alchemy deploys as secret bindings. Spread the record into your Worker's `env`, and the provider's `resolveTransport(env)` (or `layerConfig`) finds its credentials at runtime.
4
+
5
+ It binds credentials only. It provisions nothing on the vendor's side (domains, API keys). Its types are the Cloudflare provider's: every bindings record is a `WorkerBindings` (each value a `Cloudflare.WorkerBindingResource`), and `Deployed<B>` is `Cloudflare.InferEnv<B>`. At runtime the builders need only `effect`.
6
+
7
+ This package was created using Claude Code, and its API is in flux: expect churn and breaking changes.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pnpm add -D @thomasfosterau/effect-connect-alchemy-cloudflare @alchemy.run/cloudflare@2.0.0-beta.85 alchemy@2.0.0-beta.85 effect
13
+ ```
14
+
15
+ Its peer dependencies are all required: `@alchemy.run/cloudflare` and `alchemy`, exactly `2.0.0-beta.85` (the provider peers on that exact `alchemy`), and `effect` `^4.1.0`, the range both of them require. Node.js 22 or newer is required. The package runs on the deploy machine, inside your `alchemy.run.ts`, never in the Worker.
16
+
17
+ ## Usage
18
+
19
+ On the deploy machine, build the bindings and pass them into the Worker's `env`:
20
+
21
+ ```ts skip-type-checking
22
+ import * as Redacted from "effect/Redacted";
23
+ import { resendBindings } from "@thomasfosterau/effect-connect-alchemy-cloudflare";
24
+
25
+ const env = {
26
+ ...resendBindings({ apiKey: Redacted.make(process.env.RESEND_API_KEY!) }),
27
+ };
28
+ // …then `env` in your Worker resource's props.
29
+ ```
30
+
31
+ Or read the same names through `effect/Config` on the deploy machine, with the `…BindingsConfig` forms. Each one is a `Config` of the whole record, and fails when a required value is missing:
32
+
33
+ ```ts skip-type-checking
34
+ import * as Effect from "effect/Effect";
35
+ import { resendBindingsConfig } from "@thomasfosterau/effect-connect-alchemy-cloudflare";
36
+
37
+ const env = Effect.gen(function* () {
38
+ return { ...(yield* resendBindingsConfig) };
39
+ });
40
+ ```
41
+
42
+ In the Worker, the provider reads them back:
43
+
44
+ ```ts skip-type-checking
45
+ import * as Resend from "@thomasfosterau/effect-connect-resend";
46
+
47
+ const EmailLive = Resend.resolveTransport(env); // the live sender: RESEND_API_KEY is bound
48
+ ```
49
+
50
+ ## API
51
+
52
+ | Export | Binds | Read at runtime by |
53
+ | --- | --- | --- |
54
+ | `resendBindings`, `resendBindingsConfig`, `ResendBindings`, `ResendBindingsInput` | `RESEND_API_KEY` (secret) | `effect-connect-resend`'s `resolveTransport(env)` (`ResendEnv`) |
55
+ | `WorkerBindings<B>` | — | The constraint every bindings record meets: each value a `Cloudflare.WorkerBindingResource`, so the record spreads into a `Cloudflare.Worker`'s `env`. |
56
+ | `Deployed<B>` | — | `Cloudflare.InferEnv<B>`: the `env` a Worker receives for a bindings record `B`, every value a plain string. Each provider's env type accepts it. |
57
+
58
+ `Deployed<B>` is defined as the provider's own `Cloudflare.InferEnv<B>`, so a Worker typed with it is checked against the env Alchemy actually deploys; the package's tests assert, for every builder against `@alchemy.run/cloudflare` 2.0.0-beta.85, that it is also what `InferEnv` gives a `Cloudflare.Worker` whose `env` is `B`, and that the provider's env type accepts it.
59
+
60
+ ## License
61
+
62
+ MIT
@@ -0,0 +1,98 @@
1
+ import * as Config from "effect/Config";
2
+ import * as Cloudflare from "@alchemy.run/cloudflare";
3
+ import * as Redacted from "effect/Redacted";
4
+ /**
5
+ * A record Alchemy's Cloudflare provider accepts as a Worker's `env`: every
6
+ * value is a `Cloudflare.WorkerBindingResource` (a `Redacted` deploys as a
7
+ * secret binding, a string as a plain one). Every builder's record satisfies
8
+ * it, so it spreads into a `Cloudflare.Worker`'s `env` prop as is.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import type { ResendBindings, WorkerBindings } from "@thomasfosterau/effect-connect-alchemy-cloudflare";
13
+ *
14
+ * const check = <B extends WorkerBindings<B>>(bindings: B): B => bindings;
15
+ * const accept = (bindings: ResendBindings): ResendBindings => check(bindings);
16
+ * console.log(typeof accept); // "function"
17
+ * ```
18
+ *
19
+ * @since 0.1.0
20
+ */
21
+ export type WorkerBindings<B> = { readonly [K in keyof B]: Cloudflare.WorkerBindingResource; };
22
+ /**
23
+ * The `env` a Worker receives for a bindings record: the provider's own
24
+ * `Cloudflare.InferEnv` of it. Alchemy deploys a `Redacted` value as a secret
25
+ * binding and a string as a plain one, and the Worker reads both back as
26
+ * plain strings; optional keys stay optional.
27
+ *
28
+ * A provider's env contract (`ResendEnv`, …) accepts this type, which is
29
+ * what the package's tests assert for every builder.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * import type { Deployed, ResendBindings } from "@thomasfosterau/effect-connect-alchemy-cloudflare";
34
+ *
35
+ * const env: Deployed<ResendBindings> = { RESEND_API_KEY: "re_123" };
36
+ * console.log(env.RESEND_API_KEY); // "re_123"
37
+ * ```
38
+ *
39
+ * @since 0.1.0
40
+ */
41
+ export type Deployed<B extends WorkerBindings<B>> = Cloudflare.InferEnv<B>;
42
+ /**
43
+ * What {@link resendBindings} takes.
44
+ *
45
+ * @since 0.1.0
46
+ */
47
+ export interface ResendBindingsInput {
48
+ /** The Resend API key. */
49
+ readonly apiKey: Redacted.Redacted;
50
+ }
51
+ /**
52
+ * The Resend bindings for a Worker's `env`: `RESEND_API_KEY`, deployed as a
53
+ * secret because it is `Redacted`.
54
+ *
55
+ * @since 0.1.0
56
+ */
57
+ export interface ResendBindings {
58
+ readonly RESEND_API_KEY: Redacted.Redacted;
59
+ }
60
+ /**
61
+ * The Resend bindings from literal values, to spread into a Worker's `env`.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * import * as assert from "node:assert";
66
+ * import * as Redacted from "effect/Redacted";
67
+ * import { resendBindings } from "@thomasfosterau/effect-connect-alchemy-cloudflare";
68
+ *
69
+ * const env = resendBindings({ apiKey: Redacted.make("re_123") });
70
+ * assert.strictEqual(Redacted.value(env.RESEND_API_KEY), "re_123");
71
+ * ```
72
+ *
73
+ * @since 0.1.0
74
+ */
75
+ export declare const resendBindings: (input: ResendBindingsInput) => ResendBindings;
76
+ /**
77
+ * The Resend bindings read through `effect/Config` on the deploy machine:
78
+ * `RESEND_API_KEY` (required, redacted). Fails with a `ConfigError` when it
79
+ * is unset or empty, so a deploy never ships a Worker without its key.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * import * as assert from "node:assert";
84
+ * import * as ConfigProvider from "effect/ConfigProvider";
85
+ * import * as Effect from "effect/Effect";
86
+ * import * as Redacted from "effect/Redacted";
87
+ * import { resendBindingsConfig } from "@thomasfosterau/effect-connect-alchemy-cloudflare";
88
+ *
89
+ * const env = Effect.runSync(
90
+ * resendBindingsConfig.parse(ConfigProvider.fromEnv({ env: { RESEND_API_KEY: "re_123" } })),
91
+ * );
92
+ * assert.strictEqual(Redacted.value(env.RESEND_API_KEY), "re_123");
93
+ * ```
94
+ *
95
+ * @since 0.1.0
96
+ */
97
+ export declare const resendBindingsConfig: Config.Config<ResendBindings>;
98
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,50 @@
1
+ import * as Config from "effect/Config";
2
+ // src/Resend.ts
3
+ /**
4
+ * The Worker bindings `@thomasfosterau/effect-connect-resend` reads
5
+ * (`ResendEnv`): the API key, as a secret.
6
+ *
7
+ * @module Resend
8
+ * @since 0.1.0
9
+ */
10
+ /**
11
+ * The Resend bindings from literal values, to spread into a Worker's `env`.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import * as assert from "node:assert";
16
+ * import * as Redacted from "effect/Redacted";
17
+ * import { resendBindings } from "@thomasfosterau/effect-connect-alchemy-cloudflare";
18
+ *
19
+ * const env = resendBindings({ apiKey: Redacted.make("re_123") });
20
+ * assert.strictEqual(Redacted.value(env.RESEND_API_KEY), "re_123");
21
+ * ```
22
+ *
23
+ * @since 0.1.0
24
+ */
25
+ const resendBindings = (input) => ({ RESEND_API_KEY: input.apiKey });
26
+ /**
27
+ * The Resend bindings read through `effect/Config` on the deploy machine:
28
+ * `RESEND_API_KEY` (required, redacted). Fails with a `ConfigError` when it
29
+ * is unset or empty, so a deploy never ships a Worker without its key.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * import * as assert from "node:assert";
34
+ * import * as ConfigProvider from "effect/ConfigProvider";
35
+ * import * as Effect from "effect/Effect";
36
+ * import * as Redacted from "effect/Redacted";
37
+ * import { resendBindingsConfig } from "@thomasfosterau/effect-connect-alchemy-cloudflare";
38
+ *
39
+ * const env = Effect.runSync(
40
+ * resendBindingsConfig.parse(ConfigProvider.fromEnv({ env: { RESEND_API_KEY: "re_123" } })),
41
+ * );
42
+ * assert.strictEqual(Redacted.value(env.RESEND_API_KEY), "re_123");
43
+ * ```
44
+ *
45
+ * @since 0.1.0
46
+ */
47
+ const resendBindingsConfig = Config.all({ RESEND_API_KEY: Config.Redacted("RESEND_API_KEY") });
48
+ export { resendBindings, resendBindingsConfig };
49
+
50
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/Resend.ts"],"sourcesContent":["/**\n * The Worker bindings `@thomasfosterau/effect-connect-resend` reads\n * (`ResendEnv`): the API key, as a secret.\n *\n * @module Resend\n * @since 0.1.0\n */\n\nimport * as Config from \"effect/Config\";\nimport type * as Redacted from \"effect/Redacted\";\n\n/**\n * What {@link resendBindings} takes.\n *\n * @since 0.1.0\n */\nexport interface ResendBindingsInput {\n /** The Resend API key. */\n readonly apiKey: Redacted.Redacted;\n}\n\n/**\n * The Resend bindings for a Worker's `env`: `RESEND_API_KEY`, deployed as a\n * secret because it is `Redacted`.\n *\n * @since 0.1.0\n */\nexport interface ResendBindings {\n readonly RESEND_API_KEY: Redacted.Redacted;\n}\n\n/**\n * The Resend bindings from literal values, to spread into a Worker's `env`.\n *\n * @example\n * ```ts\n * import * as assert from \"node:assert\";\n * import * as Redacted from \"effect/Redacted\";\n * import { resendBindings } from \"@thomasfosterau/effect-connect-alchemy-cloudflare\";\n *\n * const env = resendBindings({ apiKey: Redacted.make(\"re_123\") });\n * assert.strictEqual(Redacted.value(env.RESEND_API_KEY), \"re_123\");\n * ```\n *\n * @since 0.1.0\n */\nexport const resendBindings = (input: ResendBindingsInput): ResendBindings => ({\n RESEND_API_KEY: input.apiKey,\n});\n\n/**\n * The Resend bindings read through `effect/Config` on the deploy machine:\n * `RESEND_API_KEY` (required, redacted). Fails with a `ConfigError` when it\n * is unset or empty, so a deploy never ships a Worker without its key.\n *\n * @example\n * ```ts\n * import * as assert from \"node:assert\";\n * import * as ConfigProvider from \"effect/ConfigProvider\";\n * import * as Effect from \"effect/Effect\";\n * import * as Redacted from \"effect/Redacted\";\n * import { resendBindingsConfig } from \"@thomasfosterau/effect-connect-alchemy-cloudflare\";\n *\n * const env = Effect.runSync(\n * resendBindingsConfig.parse(ConfigProvider.fromEnv({ env: { RESEND_API_KEY: \"re_123\" } })),\n * );\n * assert.strictEqual(Redacted.value(env.RESEND_API_KEY), \"re_123\");\n * ```\n *\n * @since 0.1.0\n */\nexport const resendBindingsConfig: Config.Config<ResendBindings> = Config.all({\n RESEND_API_KEY: Config.Redacted(\"RESEND_API_KEY\"),\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA8CA,MAAa,kBAAkB,WAAgD,EAC7E,gBAAgB,MAAM,OACxB;;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,uBAAsD,OAAO,IAAI,EAC5E,gBAAgB,OAAO,SAAS,gBAAgB,EAClD,CAAC"}
package/package.json CHANGED
@@ -1,14 +1,60 @@
1
1
  {
2
2
  "name": "@thomasfosterau/effect-connect-alchemy-cloudflare",
3
- "version": "0.0.0",
4
- "description": "Placeholder reserved for npm trusted publishing; the first real release of @thomasfosterau/effect-connect-alchemy-cloudflare is 0.1.0.",
3
+ "version": "0.1.0",
4
+ "description": "Alchemy Cloudflare deploy-time bindings for @thomasfosterau/effect-connect: per-provider builders whose keys match each provider's Worker env contract, with secrets as Redacted values, so a Cloudflare Worker deployed with Alchemy's Cloudflare provider gets exactly the bindings resolveTransport(env) reads, typed by the provider's own InferEnv.",
5
+ "keywords": [
6
+ "alchemy",
7
+ "cloudflare",
8
+ "effect",
9
+ "email",
10
+ "sms",
11
+ "typescript",
12
+ "workers"
13
+ ],
14
+ "homepage": "https://github.com/thomasfosterau/effect-connect#readme",
15
+ "bugs": {
16
+ "url": "https://github.com/thomasfosterau/effect-connect/issues"
17
+ },
5
18
  "license": "MIT",
19
+ "author": "Thomas Foster <me@thomasfoster.au>",
6
20
  "repository": {
7
21
  "type": "git",
8
- "url": "git+https://github.com/thomasfosterau/effect-connect.git",
22
+ "url": "https://github.com/thomasfosterau/effect-connect.git",
9
23
  "directory": "packages/alchemy-cloudflare"
10
24
  },
25
+ "files": [
26
+ "dist",
27
+ "src",
28
+ "!src/**/*.test.ts",
29
+ "README.md",
30
+ "LICENSE"
31
+ ],
32
+ "type": "module",
33
+ "sideEffects": false,
34
+ "exports": {
35
+ ".": {
36
+ "types": "./dist/index.d.ts",
37
+ "default": "./dist/index.js"
38
+ }
39
+ },
11
40
  "publishConfig": {
12
41
  "access": "public"
42
+ },
43
+ "devDependencies": {
44
+ "@alchemy.run/cloudflare": "2.0.0-beta.85",
45
+ "@effect/language-service": "^0.87.5",
46
+ "@effect/vitest": "4.1.2",
47
+ "@types/node": "^26.6.6",
48
+ "alchemy": "2.0.0-beta.85",
49
+ "effect": "4.1.2",
50
+ "@thomasfosterau/effect-connect-resend": "^0.1.0"
51
+ },
52
+ "peerDependencies": {
53
+ "@alchemy.run/cloudflare": "2.0.0-beta.85",
54
+ "alchemy": "2.0.0-beta.85",
55
+ "effect": "^4.1.0"
56
+ },
57
+ "engines": {
58
+ "node": ">=22"
13
59
  }
14
- }
60
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * The types that tie a bindings record to Alchemy's Cloudflare provider
3
+ * (`@alchemy.run/cloudflare`): what a record may hold, and what a Worker
4
+ * receives once Alchemy has deployed it.
5
+ *
6
+ * @module Bindings
7
+ * @since 0.1.0
8
+ */
9
+
10
+ import type * as Cloudflare from "@alchemy.run/cloudflare";
11
+
12
+ /**
13
+ * A record Alchemy's Cloudflare provider accepts as a Worker's `env`: every
14
+ * value is a `Cloudflare.WorkerBindingResource` (a `Redacted` deploys as a
15
+ * secret binding, a string as a plain one). Every builder's record satisfies
16
+ * it, so it spreads into a `Cloudflare.Worker`'s `env` prop as is.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * import type { ResendBindings, WorkerBindings } from "@thomasfosterau/effect-connect-alchemy-cloudflare";
21
+ *
22
+ * const check = <B extends WorkerBindings<B>>(bindings: B): B => bindings;
23
+ * const accept = (bindings: ResendBindings): ResendBindings => check(bindings);
24
+ * console.log(typeof accept); // "function"
25
+ * ```
26
+ *
27
+ * @since 0.1.0
28
+ */
29
+ export type WorkerBindings<B> = {
30
+ readonly [K in keyof B]: Cloudflare.WorkerBindingResource;
31
+ };
32
+
33
+ /**
34
+ * The `env` a Worker receives for a bindings record: the provider's own
35
+ * `Cloudflare.InferEnv` of it. Alchemy deploys a `Redacted` value as a secret
36
+ * binding and a string as a plain one, and the Worker reads both back as
37
+ * plain strings; optional keys stay optional.
38
+ *
39
+ * A provider's env contract (`ResendEnv`, …) accepts this type, which is
40
+ * what the package's tests assert for every builder.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import type { Deployed, ResendBindings } from "@thomasfosterau/effect-connect-alchemy-cloudflare";
45
+ *
46
+ * const env: Deployed<ResendBindings> = { RESEND_API_KEY: "re_123" };
47
+ * console.log(env.RESEND_API_KEY); // "re_123"
48
+ * ```
49
+ *
50
+ * @since 0.1.0
51
+ */
52
+ export type Deployed<B extends WorkerBindings<B>> = Cloudflare.InferEnv<B>;
package/src/Resend.ts ADDED
@@ -0,0 +1,74 @@
1
+ /**
2
+ * The Worker bindings `@thomasfosterau/effect-connect-resend` reads
3
+ * (`ResendEnv`): the API key, as a secret.
4
+ *
5
+ * @module Resend
6
+ * @since 0.1.0
7
+ */
8
+
9
+ import * as Config from "effect/Config";
10
+ import type * as Redacted from "effect/Redacted";
11
+
12
+ /**
13
+ * What {@link resendBindings} takes.
14
+ *
15
+ * @since 0.1.0
16
+ */
17
+ export interface ResendBindingsInput {
18
+ /** The Resend API key. */
19
+ readonly apiKey: Redacted.Redacted;
20
+ }
21
+
22
+ /**
23
+ * The Resend bindings for a Worker's `env`: `RESEND_API_KEY`, deployed as a
24
+ * secret because it is `Redacted`.
25
+ *
26
+ * @since 0.1.0
27
+ */
28
+ export interface ResendBindings {
29
+ readonly RESEND_API_KEY: Redacted.Redacted;
30
+ }
31
+
32
+ /**
33
+ * The Resend bindings from literal values, to spread into a Worker's `env`.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * import * as assert from "node:assert";
38
+ * import * as Redacted from "effect/Redacted";
39
+ * import { resendBindings } from "@thomasfosterau/effect-connect-alchemy-cloudflare";
40
+ *
41
+ * const env = resendBindings({ apiKey: Redacted.make("re_123") });
42
+ * assert.strictEqual(Redacted.value(env.RESEND_API_KEY), "re_123");
43
+ * ```
44
+ *
45
+ * @since 0.1.0
46
+ */
47
+ export const resendBindings = (input: ResendBindingsInput): ResendBindings => ({
48
+ RESEND_API_KEY: input.apiKey,
49
+ });
50
+
51
+ /**
52
+ * The Resend bindings read through `effect/Config` on the deploy machine:
53
+ * `RESEND_API_KEY` (required, redacted). Fails with a `ConfigError` when it
54
+ * is unset or empty, so a deploy never ships a Worker without its key.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * import * as assert from "node:assert";
59
+ * import * as ConfigProvider from "effect/ConfigProvider";
60
+ * import * as Effect from "effect/Effect";
61
+ * import * as Redacted from "effect/Redacted";
62
+ * import { resendBindingsConfig } from "@thomasfosterau/effect-connect-alchemy-cloudflare";
63
+ *
64
+ * const env = Effect.runSync(
65
+ * resendBindingsConfig.parse(ConfigProvider.fromEnv({ env: { RESEND_API_KEY: "re_123" } })),
66
+ * );
67
+ * assert.strictEqual(Redacted.value(env.RESEND_API_KEY), "re_123");
68
+ * ```
69
+ *
70
+ * @since 0.1.0
71
+ */
72
+ export const resendBindingsConfig: Config.Config<ResendBindings> = Config.all({
73
+ RESEND_API_KEY: Config.Redacted("RESEND_API_KEY"),
74
+ });
package/src/index.ts ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * `@thomasfosterau/effect-connect-alchemy-cloudflare` — deploy-time bindings
3
+ * for `@thomasfosterau/effect-connect` on Cloudflare Workers deployed with
4
+ * [Alchemy](https://alchemy.run)'s Cloudflare provider
5
+ * (`@alchemy.run/cloudflare`). One builder per provider (Resend today)
6
+ * produces the record of `env` bindings that provider's
7
+ * `resolveTransport(env)` (or `layerConfig`) reads, under the same keys, with
8
+ * secrets as `Redacted` values (Alchemy deploys those as secret bindings) and
9
+ * unset optional values left out. Each also has a `…BindingsConfig` form
10
+ * that reads the values on the deploy machine through `effect/Config`.
11
+ *
12
+ * Its types are the Cloudflare provider's: every record is a
13
+ * `WorkerBindings` (each value a `Cloudflare.WorkerBindingResource`), and
14
+ * `Deployed<B>` is `Cloudflare.InferEnv<B>`, the `env` a Worker bound with
15
+ * it receives. `@alchemy.run/cloudflare` is a required peer for those types
16
+ * alone: nothing imports it at runtime.
17
+ *
18
+ * It binds credentials only: it provisions nothing on the vendor's side
19
+ * (domains, API keys).
20
+ *
21
+ * @module index
22
+ * @since 0.1.0
23
+ */
24
+
25
+ /**
26
+ * The Cloudflare provider's view of a bindings record (`WorkerBindings`,
27
+ * `Deployed`).
28
+ *
29
+ * @since 0.1.0
30
+ */
31
+ export * from "./Bindings.ts";
32
+ /**
33
+ * The Resend bindings (`RESEND_API_KEY`).
34
+ *
35
+ * @since 0.1.0
36
+ */
37
+ export * from "./Resend.ts";