alchemy 2.0.0-beta.38 → 2.0.0-beta.39
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/lib/Cloudflare/Workers/HttpServer.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/HttpServer.js +25 -3
- package/lib/Cloudflare/Workers/HttpServer.js.map +1 -1
- package/lib/Cloudflare/Workers/InferEnv.d.ts +1 -1
- package/lib/Cloudflare/Workers/InferEnv.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.d.ts +2 -1
- package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.js +52 -28
- package/lib/Cloudflare/Workers/Worker.js.map +1 -1
- package/lib/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/Cloudflare/Workers/HttpServer.ts +37 -5
- package/src/Cloudflare/Workers/InferEnv.ts +15 -11
- package/src/Cloudflare/Workers/Worker.ts +59 -32
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type * as cf from "@cloudflare/workers-types";
|
|
2
2
|
import * as Cause from "effect/Cause";
|
|
3
|
+
import * as Context from "effect/Context";
|
|
3
4
|
import * as Effect from "effect/Effect";
|
|
4
5
|
import * as Option from "effect/Option";
|
|
5
6
|
import type { Scope } from "effect/Scope";
|
|
6
7
|
import type { HttpBodyError } from "effect/unstable/http/HttpBody";
|
|
8
|
+
import * as EffectHttp from "effect/unstable/http/HttpEffect";
|
|
9
|
+
import { ClientAbort } from "effect/unstable/http/HttpServerError";
|
|
7
10
|
import * as HttpServerError from "effect/unstable/http/HttpServerError";
|
|
8
11
|
import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest";
|
|
9
12
|
import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";
|
|
@@ -48,6 +51,10 @@ export const serveWebRequest = <Req = never>(
|
|
|
48
51
|
Exclude<Req, HttpServerRequest.HttpServerRequest | Scope>
|
|
49
52
|
> =>
|
|
50
53
|
Effect.gen(function* () {
|
|
54
|
+
const context =
|
|
55
|
+
yield* Effect.context<
|
|
56
|
+
Exclude<Req, HttpServerRequest.HttpServerRequest | Scope>
|
|
57
|
+
>();
|
|
51
58
|
const request = HttpServerRequest.fromWeb(
|
|
52
59
|
webRequest as any as globalThis.Request,
|
|
53
60
|
).modify({
|
|
@@ -61,9 +68,7 @@ export const serveWebRequest = <Req = never>(
|
|
|
61
68
|
}),
|
|
62
69
|
});
|
|
63
70
|
|
|
64
|
-
const
|
|
65
|
-
Effect.provideService(HttpServerRequest.HttpServerRequest, request),
|
|
66
|
-
Effect.provideService(Request, webRequest as any),
|
|
71
|
+
const safeHandler = handler.pipe(
|
|
67
72
|
Effect.catchCause((cause) => {
|
|
68
73
|
const message = Option.match(Cause.findErrorOption(cause), {
|
|
69
74
|
onNone: () => "Internal Server Error",
|
|
@@ -81,7 +86,34 @@ export const serveWebRequest = <Req = never>(
|
|
|
81
86
|
}),
|
|
82
87
|
);
|
|
83
88
|
|
|
84
|
-
|
|
85
|
-
|
|
89
|
+
const resolveSymbol = Symbol.for("@effect/platform/HttpApp/resolve");
|
|
90
|
+
const httpApp = EffectHttp.toHandled(safeHandler, (request, response) => {
|
|
91
|
+
response = EffectHttp.scopeTransferToStream(response);
|
|
92
|
+
(request as any)[resolveSymbol](
|
|
93
|
+
HttpServerResponse.toWeb(response, {
|
|
94
|
+
withoutBody: request.method === "HEAD",
|
|
95
|
+
context,
|
|
96
|
+
}),
|
|
97
|
+
);
|
|
98
|
+
return Effect.void;
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return yield* Effect.promise(() => {
|
|
102
|
+
return new Promise<Response>((resolve) => {
|
|
103
|
+
const contextMap = new Map<string, any>(context.mapUnsafe);
|
|
104
|
+
contextMap.set(HttpServerRequest.HttpServerRequest.key, request);
|
|
105
|
+
contextMap.set(Request.key, webRequest);
|
|
106
|
+
(request as any)[resolveSymbol] = resolve;
|
|
107
|
+
const fiber = Effect.runForkWith(Context.makeUnsafe(contextMap))(
|
|
108
|
+
httpApp as any,
|
|
109
|
+
);
|
|
110
|
+
webRequest.signal?.addEventListener(
|
|
111
|
+
"abort",
|
|
112
|
+
() => {
|
|
113
|
+
fiber.interruptUnsafe(undefined, ClientAbort.annotation);
|
|
114
|
+
},
|
|
115
|
+
{ once: true },
|
|
116
|
+
);
|
|
117
|
+
});
|
|
86
118
|
});
|
|
87
119
|
}) as any;
|
|
@@ -97,14 +97,18 @@ export type GetBindingType<T> = T extends Cloudflare.Assets
|
|
|
97
97
|
? Queue<unknown>
|
|
98
98
|
: T extends Cloudflare.AiGateway
|
|
99
99
|
? Ai
|
|
100
|
-
: T extends Cloudflare.
|
|
101
|
-
?
|
|
102
|
-
: T extends Cloudflare.
|
|
103
|
-
?
|
|
104
|
-
: T extends Cloudflare.
|
|
105
|
-
?
|
|
106
|
-
: T extends Cloudflare.
|
|
107
|
-
?
|
|
108
|
-
: T extends Cloudflare.
|
|
109
|
-
?
|
|
110
|
-
:
|
|
100
|
+
: T extends Cloudflare.SendEmail
|
|
101
|
+
? SendEmail
|
|
102
|
+
: T extends Cloudflare.AnalyticsEngineDataset
|
|
103
|
+
? AnalyticsEngineDataset
|
|
104
|
+
: T extends Cloudflare.Artifacts
|
|
105
|
+
? Artifacts
|
|
106
|
+
: T extends Cloudflare.Images
|
|
107
|
+
? ImagesBinding
|
|
108
|
+
: T extends Cloudflare.Hyperdrive
|
|
109
|
+
? Hyperdrive
|
|
110
|
+
: T extends Cloudflare.DurableObjectNamespaceLike
|
|
111
|
+
? DurableObjectNamespace<
|
|
112
|
+
Exclude<T["Shape"], undefined>
|
|
113
|
+
>
|
|
114
|
+
: never;
|
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
} from "../Artifacts/Artifacts.ts";
|
|
52
52
|
import { CloudflareEnvironment } from "../CloudflareEnvironment.ts";
|
|
53
53
|
import { D1Database } from "../D1/D1Database.ts";
|
|
54
|
+
import { isSendEmail, type SendEmail } from "../Email/SendEmail.ts";
|
|
54
55
|
import type {
|
|
55
56
|
Hyperdrive,
|
|
56
57
|
HyperdriveDevOrigin,
|
|
@@ -201,6 +202,7 @@ export type WorkerBindingResource =
|
|
|
201
202
|
| CloudflareQueue
|
|
202
203
|
| AiGateway
|
|
203
204
|
| AnalyticsEngineDataset
|
|
205
|
+
| SendEmail
|
|
204
206
|
| ArtifactsBinding
|
|
205
207
|
| ImagesBinding
|
|
206
208
|
| Hyperdrive
|
|
@@ -779,62 +781,71 @@ export const Worker: Platform<
|
|
|
779
781
|
name: bindingName,
|
|
780
782
|
dataset: binding.dataset,
|
|
781
783
|
}
|
|
782
|
-
:
|
|
784
|
+
: isSendEmail(binding)
|
|
783
785
|
? {
|
|
784
|
-
type: "
|
|
786
|
+
type: "send_email",
|
|
785
787
|
name: bindingName,
|
|
786
|
-
|
|
788
|
+
destinationAddress: binding.destinationAddress,
|
|
789
|
+
allowedDestinationAddresses:
|
|
790
|
+
binding.allowedDestinationAddresses,
|
|
791
|
+
allowedSenderAddresses: binding.allowedSenderAddresses,
|
|
787
792
|
}
|
|
788
|
-
: binding
|
|
793
|
+
: isDurableObjectNamespaceLike(binding)
|
|
789
794
|
? {
|
|
790
|
-
type: "
|
|
791
|
-
id: binding.databaseId,
|
|
795
|
+
type: "durable_object_namespace",
|
|
792
796
|
name: bindingName,
|
|
797
|
+
className: binding.className ?? binding.name,
|
|
793
798
|
}
|
|
794
|
-
: binding.Type === "Cloudflare.
|
|
799
|
+
: binding.Type === "Cloudflare.D1Database"
|
|
795
800
|
? {
|
|
796
|
-
type: "
|
|
801
|
+
type: "d1",
|
|
802
|
+
id: binding.databaseId,
|
|
797
803
|
name: bindingName,
|
|
798
|
-
bucketName: binding.bucketName,
|
|
799
|
-
jurisdiction: binding.jurisdiction.pipe(
|
|
800
|
-
Output.map((jurisdiction) =>
|
|
801
|
-
jurisdiction === "default"
|
|
802
|
-
? undefined
|
|
803
|
-
: jurisdiction,
|
|
804
|
-
),
|
|
805
|
-
),
|
|
806
804
|
}
|
|
807
|
-
: binding.Type === "Cloudflare.
|
|
805
|
+
: binding.Type === "Cloudflare.R2Bucket"
|
|
808
806
|
? {
|
|
809
|
-
type: "
|
|
807
|
+
type: "r2_bucket",
|
|
810
808
|
name: bindingName,
|
|
811
|
-
|
|
809
|
+
bucketName: binding.bucketName,
|
|
810
|
+
jurisdiction: binding.jurisdiction.pipe(
|
|
811
|
+
Output.map((jurisdiction) =>
|
|
812
|
+
jurisdiction === "default"
|
|
813
|
+
? undefined
|
|
814
|
+
: jurisdiction,
|
|
815
|
+
),
|
|
816
|
+
),
|
|
812
817
|
}
|
|
813
|
-
: binding.Type === "Cloudflare.
|
|
818
|
+
: binding.Type === "Cloudflare.KVNamespace"
|
|
814
819
|
? {
|
|
815
|
-
type: "
|
|
820
|
+
type: "kv_namespace",
|
|
816
821
|
name: bindingName,
|
|
817
|
-
|
|
822
|
+
namespaceId: binding.namespaceId,
|
|
818
823
|
}
|
|
819
|
-
: binding.Type === "Cloudflare.
|
|
824
|
+
: binding.Type === "Cloudflare.Queue"
|
|
820
825
|
? {
|
|
821
|
-
type: "
|
|
826
|
+
type: "queue",
|
|
822
827
|
name: bindingName,
|
|
828
|
+
queueName: binding.queueName,
|
|
823
829
|
}
|
|
824
|
-
: binding.Type === "Cloudflare.
|
|
830
|
+
: binding.Type === "Cloudflare.AiGateway"
|
|
825
831
|
? {
|
|
826
|
-
type: "
|
|
832
|
+
type: "ai",
|
|
827
833
|
name: bindingName,
|
|
828
|
-
id: binding.hyperdriveId,
|
|
829
834
|
}
|
|
830
|
-
:
|
|
835
|
+
: binding.Type === "Cloudflare.Hyperdrive"
|
|
831
836
|
? {
|
|
832
|
-
type: "
|
|
837
|
+
type: "hyperdrive",
|
|
833
838
|
name: bindingName,
|
|
834
|
-
|
|
839
|
+
id: binding.hyperdriveId,
|
|
835
840
|
}
|
|
836
|
-
:
|
|
837
|
-
|
|
841
|
+
: isWorker(binding)
|
|
842
|
+
? {
|
|
843
|
+
type: "service",
|
|
844
|
+
name: bindingName,
|
|
845
|
+
service: binding.workerName,
|
|
846
|
+
}
|
|
847
|
+
: // TODO(sam): handle others
|
|
848
|
+
undefined;
|
|
838
849
|
|
|
839
850
|
if (bindingMeta) {
|
|
840
851
|
yield* resource.bind`${bindingName}`({
|
|
@@ -1607,6 +1618,22 @@ export const LiveWorkerProvider = () =>
|
|
|
1607
1618
|
const builder = await vite.createBuilder(
|
|
1608
1619
|
{
|
|
1609
1620
|
root: props.vite?.rootDir,
|
|
1621
|
+
// Emulate `vite build` env semantics for `props.env`: only
|
|
1622
|
+
// keys with Vite's default `VITE_` prefix are inlined into
|
|
1623
|
+
// the bundle as `import.meta.env.*`. `Redacted` values are
|
|
1624
|
+
// unwrapped — by prefixing with `VITE_` the user is opting
|
|
1625
|
+
// them into the public bundle.
|
|
1626
|
+
define: Object.fromEntries(
|
|
1627
|
+
Object.entries(props.env ?? {}).flatMap(([key, raw]) => {
|
|
1628
|
+
if (!key.startsWith("VITE_")) return [];
|
|
1629
|
+
const value = Redacted.isRedacted(raw)
|
|
1630
|
+
? Redacted.value(raw)
|
|
1631
|
+
: raw;
|
|
1632
|
+
return [
|
|
1633
|
+
[`import.meta.env.${key}`, JSON.stringify(value)] as const,
|
|
1634
|
+
];
|
|
1635
|
+
}),
|
|
1636
|
+
),
|
|
1610
1637
|
// Declare the ssr environment so Vite 8+ creates it.
|
|
1611
1638
|
// The cloudflare-vite-plugin config hook merges its
|
|
1612
1639
|
// SSR-specific settings on top of this stub.
|