alchemy 2.0.0-beta.39 → 2.0.0-beta.40
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/exec.js +5 -26
- package/bin/exec.js.map +1 -1
- package/lib/Auth/Lock.d.ts +4 -3
- package/lib/Auth/Lock.d.ts.map +1 -1
- package/lib/Auth/Lock.js +6 -5
- package/lib/Auth/Lock.js.map +1 -1
- package/lib/Axiom/Chart.d.ts +52 -2
- package/lib/Axiom/Chart.d.ts.map +1 -1
- package/lib/Bundle/Bundle.d.ts +7 -4
- package/lib/Bundle/Bundle.d.ts.map +1 -1
- package/lib/Bundle/Bundle.js +37 -14
- package/lib/Bundle/Bundle.js.map +1 -1
- package/lib/Cloudflare/AiGateway/AiGateway.d.ts +11 -11
- package/lib/Cloudflare/AiGateway/AiGateway.d.ts.map +1 -1
- package/lib/Cloudflare/AiGateway/AiGateway.js +28 -63
- package/lib/Cloudflare/AiGateway/AiGateway.js.map +1 -1
- package/lib/Cloudflare/Bridge.d.ts +3 -0
- package/lib/Cloudflare/Bridge.d.ts.map +1 -0
- package/lib/Cloudflare/Bridge.js +3 -0
- package/lib/Cloudflare/Bridge.js.map +1 -0
- package/lib/Cloudflare/Container/StartContainer.d.ts +2 -2
- package/lib/Cloudflare/Container/StartContainer.d.ts.map +1 -1
- package/lib/Cloudflare/Container/StartContainer.js +3 -3
- package/lib/Cloudflare/Container/StartContainer.js.map +1 -1
- package/lib/Cloudflare/Local/Sidecar.d.ts +45 -21
- package/lib/Cloudflare/Local/Sidecar.d.ts.map +1 -1
- package/lib/Cloudflare/Local/Sidecar.js +30 -6
- package/lib/Cloudflare/Local/Sidecar.js.map +1 -1
- package/lib/Cloudflare/Local/SidecarHandlers.d.ts +5 -2
- package/lib/Cloudflare/Local/SidecarHandlers.d.ts.map +1 -1
- package/lib/Cloudflare/Local/SidecarHandlers.js +323 -70
- package/lib/Cloudflare/Local/SidecarHandlers.js.map +1 -1
- package/lib/Cloudflare/Local/SidecarServer.js +9 -5
- package/lib/Cloudflare/Local/SidecarServer.js.map +1 -1
- package/lib/Cloudflare/StateStore/Api.d.ts +1 -1
- package/lib/Cloudflare/StateStore/Api.js +1 -1
- package/lib/Cloudflare/StateStore/Store.d.ts +1 -1
- package/lib/Cloudflare/Workers/HttpServer.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/HttpServer.js +3 -25
- package/lib/Cloudflare/Workers/HttpServer.js.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts +1 -2
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js +16 -97
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
- package/lib/Cloudflare/Workers/Vite.d.ts +9 -0
- package/lib/Cloudflare/Workers/Vite.d.ts.map +1 -0
- package/lib/Cloudflare/Workers/Vite.js +95 -0
- package/lib/Cloudflare/Workers/Vite.js.map +1 -0
- package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.js +9 -95
- package/lib/Cloudflare/Workers/Worker.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBundle.d.ts +1 -2
- package/lib/Cloudflare/Workers/WorkerBundle.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBundle.js +5 -4
- package/lib/Cloudflare/Workers/WorkerBundle.js.map +1 -1
- package/lib/Diff.d.ts +15 -1
- package/lib/Diff.d.ts.map +1 -1
- package/lib/Diff.js +13 -7
- package/lib/Diff.js.map +1 -1
- package/lib/Http.d.ts.map +1 -1
- package/lib/Http.js +12 -7
- package/lib/Http.js.map +1 -1
- package/lib/Sidecar/Lock.d.ts +4 -5
- package/lib/Sidecar/Lock.d.ts.map +1 -1
- package/lib/Sidecar/Lock.js +22 -85
- package/lib/Sidecar/Lock.js.map +1 -1
- package/lib/Sidecar/RpcHandler.d.ts +4 -1
- package/lib/Sidecar/RpcHandler.d.ts.map +1 -1
- package/lib/Sidecar/RpcHandler.js +21 -2
- package/lib/Sidecar/RpcHandler.js.map +1 -1
- package/lib/Util/PlatformServices.d.ts.map +1 -1
- package/lib/Util/PlatformServices.js +0 -2
- package/lib/Util/PlatformServices.js.map +1 -1
- package/lib/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +17 -12
- package/src/AWS/EC2/hosted.ts +1 -1
- package/src/AWS/ECS/Task.ts +1 -1
- package/src/AWS/Lambda/Function.ts +1 -1
- package/src/Auth/Lock.ts +6 -5
- package/src/Axiom/Chart.ts +56 -2
- package/src/Bundle/Bundle.ts +41 -17
- package/src/Cloudflare/AiGateway/AiGateway.ts +43 -76
- package/src/Cloudflare/Bridge.ts +2 -0
- package/src/Cloudflare/Container/ContainerApplication.ts +1 -1
- package/src/Cloudflare/Container/StartContainer.ts +10 -3
- package/src/Cloudflare/Local/Sidecar.ts +50 -21
- package/src/Cloudflare/Local/SidecarHandlers.ts +395 -91
- package/src/Cloudflare/Local/SidecarServer.ts +12 -4
- package/src/Cloudflare/StateStore/Api.ts +1 -1
- package/src/Cloudflare/Workers/HttpServer.ts +5 -37
- package/src/Cloudflare/Workers/LocalWorkerProvider.ts +18 -111
- package/src/Cloudflare/Workers/Vite.ts +114 -0
- package/src/Cloudflare/Workers/Worker.ts +27 -109
- package/src/Cloudflare/Workers/WorkerBundle.ts +7 -7
- package/src/Diff.ts +29 -8
- package/src/Http.ts +14 -10
- package/src/Sidecar/Lock.ts +30 -154
- package/src/Sidecar/RpcHandler.ts +67 -40
- package/src/Util/PlatformServices.ts +0 -2
|
@@ -1,79 +1,221 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
Runtime,
|
|
3
|
+
type BindingHook,
|
|
4
|
+
type BindingServices,
|
|
5
|
+
type HyperdriveOrigin,
|
|
6
|
+
type Module,
|
|
7
|
+
type Assets as RuntimeAssets,
|
|
8
|
+
type DurableObjectNamespace as RuntimeDurableObjectNamespace,
|
|
9
|
+
type RuntimeServices,
|
|
10
|
+
} from "@distilled.cloud/cloudflare-runtime";
|
|
11
|
+
import {
|
|
12
|
+
Ai,
|
|
13
|
+
Assets,
|
|
14
|
+
Browser,
|
|
15
|
+
D1,
|
|
16
|
+
Data,
|
|
17
|
+
DurableObjectNamespace,
|
|
18
|
+
Hyperdrive,
|
|
19
|
+
Images,
|
|
20
|
+
Json,
|
|
21
|
+
KvNamespace,
|
|
22
|
+
R2Bucket,
|
|
23
|
+
Service,
|
|
24
|
+
Text,
|
|
25
|
+
VersionMetadata,
|
|
26
|
+
WasmModule,
|
|
27
|
+
WorkerLoader,
|
|
28
|
+
} from "@distilled.cloud/cloudflare-runtime/bindings";
|
|
29
|
+
import * as LocalProxy from "@distilled.cloud/cloudflare-runtime/proxy/LocalProxy";
|
|
3
30
|
import * as Cause from "effect/Cause";
|
|
4
|
-
import * as Deferred from "effect/Deferred";
|
|
5
31
|
import * as Effect from "effect/Effect";
|
|
6
32
|
import * as Exit from "effect/Exit";
|
|
7
33
|
import * as Fiber from "effect/Fiber";
|
|
8
34
|
import * as Hash from "effect/Hash";
|
|
9
35
|
import * as Layer from "effect/Layer";
|
|
36
|
+
import * as Path from "effect/Path";
|
|
37
|
+
import * as Redacted from "effect/Redacted";
|
|
10
38
|
import * as Result from "effect/Result";
|
|
11
39
|
import * as Scope from "effect/Scope";
|
|
12
40
|
import * as Stream from "effect/Stream";
|
|
13
|
-
import * as Bundle from "../../Bundle/Bundle.ts";
|
|
14
|
-
import {
|
|
41
|
+
import type * as Bundle from "../../Bundle/Bundle.ts";
|
|
42
|
+
import { InstanceId } from "../../InstanceId.ts";
|
|
43
|
+
import { Stack } from "../../Stack.ts";
|
|
44
|
+
import { Stage } from "../../Stage.ts";
|
|
45
|
+
import { CloudflareEnvironment } from "../CloudflareEnvironment.ts";
|
|
46
|
+
import { getCompatibility } from "../Workers/Compatibility.ts";
|
|
47
|
+
import { getCronBindings } from "../Workers/index.ts";
|
|
48
|
+
import * as Vite from "../Workers/Vite.ts";
|
|
49
|
+
import type {
|
|
50
|
+
Worker,
|
|
51
|
+
WorkerAssetsConfig,
|
|
52
|
+
WorkerBinding,
|
|
53
|
+
} from "../Workers/Worker.ts";
|
|
15
54
|
import {
|
|
55
|
+
WorkerBundle,
|
|
56
|
+
type WorkerBundleOptions,
|
|
57
|
+
} from "../Workers/WorkerBundle.ts";
|
|
58
|
+
import { createWorkerName } from "../Workers/WorkerName.ts";
|
|
59
|
+
import {
|
|
60
|
+
ServeError,
|
|
61
|
+
ServeResult,
|
|
16
62
|
Sidecar,
|
|
17
|
-
|
|
18
|
-
type
|
|
19
|
-
type ServeResult,
|
|
63
|
+
ValidationError,
|
|
64
|
+
type ReconcileOptions,
|
|
20
65
|
} from "./Sidecar.ts";
|
|
21
66
|
|
|
22
67
|
export const SidecarHandlers = Layer.effect(
|
|
23
68
|
Sidecar,
|
|
24
69
|
Effect.gen(function* () {
|
|
25
|
-
const
|
|
26
|
-
const
|
|
70
|
+
const { accountId } = yield* CloudflareEnvironment;
|
|
71
|
+
const bundler = yield* WorkerBundle;
|
|
72
|
+
const runtime = yield* Runtime;
|
|
73
|
+
const path = yield* Path.Path;
|
|
74
|
+
const localProxy = yield* LocalProxy.LocalProxy;
|
|
27
75
|
|
|
28
|
-
const
|
|
29
|
-
|
|
76
|
+
const toRuntimeModules = Effect.fn(function* (bundle: Bundle.BundleOutput) {
|
|
77
|
+
const modules: Module[] = [];
|
|
78
|
+
for (const file of bundle.files) {
|
|
79
|
+
const ext = path.extname(file.path);
|
|
80
|
+
const type = moduleTypeFromExtension(ext);
|
|
81
|
+
if (type === "SourceMap") continue;
|
|
82
|
+
if (type === "Data" || type === "Wasm") {
|
|
83
|
+
if (!(file.content instanceof Uint8Array)) {
|
|
84
|
+
return yield* new ValidationError({
|
|
85
|
+
message: `Expected Uint8Array for ${file.path} (${type})`,
|
|
86
|
+
value: file.content,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
modules.push({
|
|
90
|
+
name: file.path,
|
|
91
|
+
type,
|
|
92
|
+
content: file.content,
|
|
93
|
+
});
|
|
94
|
+
} else {
|
|
95
|
+
if (typeof file.content !== "string") {
|
|
96
|
+
return yield* new ValidationError({
|
|
97
|
+
message: `Expected string for ${file.path} (${type})`,
|
|
98
|
+
value: file.content,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
modules.push({
|
|
102
|
+
name: file.path,
|
|
103
|
+
type,
|
|
104
|
+
content: file.content,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return modules;
|
|
109
|
+
});
|
|
30
110
|
|
|
31
111
|
const serveScoped = Effect.fnUntraced(function* (
|
|
32
|
-
worker:
|
|
33
|
-
|
|
112
|
+
worker: WorkerConfig,
|
|
113
|
+
bundle: Bundle.BundleOutput,
|
|
34
114
|
) {
|
|
35
115
|
const scope = yield* Effect.flatMap(Effect.scope, Scope.fork);
|
|
36
|
-
const
|
|
37
|
-
.
|
|
38
|
-
name: worker.
|
|
116
|
+
const address = yield* runtime
|
|
117
|
+
.start({
|
|
118
|
+
name: worker.name,
|
|
39
119
|
compatibilityDate: worker.compatibility.date,
|
|
40
120
|
compatibilityFlags: worker.compatibility.flags,
|
|
41
|
-
bindings: worker.
|
|
121
|
+
bindings: worker.workerBindings as never,
|
|
42
122
|
hyperdrives: worker.hyperdrives,
|
|
43
|
-
durableObjectNamespaces:
|
|
44
|
-
|
|
123
|
+
durableObjectNamespaces: toRuntimeDurableObjectNamespaces(
|
|
124
|
+
worker.durableObjectNamespaces,
|
|
125
|
+
),
|
|
126
|
+
modules: yield* toRuntimeModules(bundle),
|
|
127
|
+
assets: toRuntimeAssets(worker.assets),
|
|
45
128
|
})
|
|
46
129
|
.pipe(Scope.provide(scope));
|
|
47
|
-
const previous =
|
|
130
|
+
const previous = workerdScopes.get(worker.id);
|
|
48
131
|
if (previous) {
|
|
49
132
|
yield* Effect.forkDetach(Scope.close(previous, Exit.void));
|
|
50
133
|
}
|
|
51
|
-
|
|
52
|
-
|
|
134
|
+
workerdScopes.set(worker.id, scope);
|
|
135
|
+
yield* localProxy.setLocalAddress(worker.id, address);
|
|
136
|
+
return address;
|
|
53
137
|
});
|
|
54
138
|
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
139
|
+
const buildConfig = Effect.fn(function* ({
|
|
140
|
+
id,
|
|
141
|
+
props,
|
|
142
|
+
bindings,
|
|
143
|
+
stack,
|
|
144
|
+
instanceId,
|
|
145
|
+
}: ReconcileOptions) {
|
|
146
|
+
const name = yield* createWorkerName(id, props.name).pipe(
|
|
147
|
+
Effect.provideService(Stack, stack),
|
|
148
|
+
Effect.provideService(Stage, stack.stage),
|
|
149
|
+
Effect.provideService(InstanceId, instanceId),
|
|
150
|
+
);
|
|
151
|
+
const compatibility = getCompatibility(props);
|
|
152
|
+
const workerBindings: BindingHook<BindingServices>[] = [];
|
|
153
|
+
const durableObjectNamespaces: Record<string, string> = {};
|
|
154
|
+
const hyperdrives: Record<string, Required<HyperdriveOrigin>> = {};
|
|
155
|
+
for (const { data } of bindings) {
|
|
156
|
+
for (const binding of data.bindings ?? []) {
|
|
157
|
+
if (binding.type === "durable_object_namespace") {
|
|
158
|
+
durableObjectNamespaces[binding.name] = binding.className!;
|
|
159
|
+
}
|
|
160
|
+
workerBindings.push(yield* toRuntimeBinding(binding));
|
|
161
|
+
}
|
|
162
|
+
if (data.hyperdrives) {
|
|
163
|
+
for (const [id, origin] of Object.entries(data.hyperdrives)) {
|
|
164
|
+
hyperdrives[id] = {
|
|
165
|
+
scheme: origin.scheme,
|
|
166
|
+
host: origin.host,
|
|
167
|
+
port: origin.port,
|
|
168
|
+
user: origin.user,
|
|
169
|
+
database: origin.database,
|
|
170
|
+
password: Redacted.isRedacted(origin.password)
|
|
171
|
+
? Redacted.value(origin.password)
|
|
172
|
+
: origin.password,
|
|
173
|
+
sslmode: origin.sslmode,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
61
177
|
}
|
|
62
|
-
|
|
178
|
+
for (const [key, value] of Object.entries(props.env ?? {})) {
|
|
179
|
+
if (value === undefined) continue;
|
|
180
|
+
if (Redacted.isRedacted(value)) {
|
|
181
|
+
workerBindings.push(Text.binding(key, Redacted.value(value)));
|
|
182
|
+
} else if (typeof value === "string") {
|
|
183
|
+
workerBindings.push(Text.binding(key, value));
|
|
184
|
+
} else {
|
|
185
|
+
workerBindings.push(Json.binding(key, value));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
id,
|
|
190
|
+
name,
|
|
191
|
+
compatibility,
|
|
192
|
+
workerBindings,
|
|
193
|
+
durableObjectNamespaces,
|
|
194
|
+
hyperdrives,
|
|
195
|
+
bundleOptions: {
|
|
196
|
+
id,
|
|
197
|
+
main: props.main,
|
|
198
|
+
compatibility,
|
|
199
|
+
entry: props.isExternal
|
|
200
|
+
? { kind: "external" }
|
|
201
|
+
: { kind: "effect", exports: (props.exports ?? {}) as any },
|
|
202
|
+
stack: { name: stack.name, stage: stack.stage },
|
|
203
|
+
userOptions: props.build,
|
|
204
|
+
} satisfies WorkerBundleOptions,
|
|
205
|
+
assets: props.assets,
|
|
206
|
+
};
|
|
207
|
+
});
|
|
63
208
|
|
|
64
|
-
|
|
65
|
-
|
|
209
|
+
type WorkerConfig = Effect.Success<ReturnType<typeof buildConfig>>;
|
|
210
|
+
|
|
211
|
+
const runServer = Effect.fnUntraced(function* (worker: WorkerConfig) {
|
|
66
212
|
let start = Date.now();
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
event._tag === "Error" && !Deferred.isDoneUnsafe(result)
|
|
70
|
-
? Effect.fail(event.error)
|
|
71
|
-
: Effect.succeed(event),
|
|
72
|
-
),
|
|
213
|
+
let status: "start" | "update" = "start";
|
|
214
|
+
yield* bundler.watch(worker.bundleOptions).pipe(
|
|
73
215
|
Stream.tap((event) => {
|
|
74
216
|
if (event._tag === "Start") {
|
|
75
217
|
start = Date.now();
|
|
76
|
-
if (
|
|
218
|
+
if (status === "update") {
|
|
77
219
|
return Effect.log(`[${worker.id}] Rebuilding`);
|
|
78
220
|
}
|
|
79
221
|
} else if (event._tag === "Error") {
|
|
@@ -86,105 +228,267 @@ export const SidecarHandlers = Layer.effect(
|
|
|
86
228
|
? Result.succeed(event.output)
|
|
87
229
|
: Result.failVoid,
|
|
88
230
|
),
|
|
89
|
-
Stream.
|
|
90
|
-
|
|
91
|
-
serveScoped(worker, modules).pipe(
|
|
231
|
+
Stream.mapEffect((bundle) =>
|
|
232
|
+
serveScoped(worker, bundle).pipe(
|
|
92
233
|
Effect.exit,
|
|
93
234
|
Effect.tap((exit) => {
|
|
94
|
-
const isDone = Deferred.isDoneUnsafe(result);
|
|
95
235
|
if (exit._tag === "Success") {
|
|
96
|
-
|
|
97
|
-
`[${worker.id}] ${
|
|
236
|
+
const message = Effect.log(
|
|
237
|
+
`[${worker.id}] ${status === "update" ? "Updated" : "Started"} in ${Math.round(Date.now() - start)}ms`,
|
|
98
238
|
);
|
|
99
|
-
|
|
239
|
+
status = "update";
|
|
240
|
+
return message;
|
|
241
|
+
} else {
|
|
100
242
|
return Effect.logError(
|
|
101
243
|
`[${worker.id}] Error`,
|
|
102
244
|
Cause.squash(exit.cause),
|
|
103
245
|
);
|
|
104
246
|
}
|
|
105
|
-
return Effect.void;
|
|
106
247
|
}),
|
|
107
|
-
Effect.tap((exit) => Deferred.complete(result, exit)),
|
|
108
248
|
),
|
|
109
249
|
),
|
|
110
|
-
Stream.onExit((exit) =>
|
|
111
|
-
exit._tag === "Failure" && !Deferred.isDoneUnsafe(result)
|
|
112
|
-
? Deferred.failCause(result, exit.cause)
|
|
113
|
-
: Effect.void,
|
|
114
|
-
),
|
|
115
250
|
Stream.runDrain,
|
|
116
251
|
Effect.forkScoped,
|
|
117
252
|
);
|
|
118
|
-
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
const rootScope = yield* Effect.scope;
|
|
256
|
+
const workerdScopes = new Map<string, Scope.Closeable>();
|
|
257
|
+
|
|
258
|
+
const context = yield* Effect.context<RuntimeServices>();
|
|
259
|
+
const instances = new Map<
|
|
260
|
+
string,
|
|
261
|
+
{
|
|
262
|
+
hash: number;
|
|
263
|
+
fiber: Fiber.Fiber<ServeResult, ServeError>;
|
|
264
|
+
scope: Scope.Closeable;
|
|
265
|
+
}
|
|
266
|
+
>();
|
|
267
|
+
|
|
268
|
+
const runInstance = Effect.fn(function* (options: ReconcileOptions) {
|
|
269
|
+
const { id, props, bindings } = options;
|
|
270
|
+
const config = yield* buildConfig(options);
|
|
271
|
+
const url = yield* localProxy.registerWorker(id);
|
|
272
|
+
if (props.vite) {
|
|
273
|
+
console.log("starting vite dev server", id);
|
|
274
|
+
const devServer = yield* Vite.viteDev(
|
|
275
|
+
props.vite.rootDir,
|
|
276
|
+
props.env ?? {},
|
|
277
|
+
{
|
|
278
|
+
compatibilityDate: config.compatibility.date,
|
|
279
|
+
compatibilityFlags: config.compatibility.flags,
|
|
280
|
+
worker: {
|
|
281
|
+
name: config.name,
|
|
282
|
+
bindings: config.workerBindings,
|
|
283
|
+
durableObjectNamespaces: toRuntimeDurableObjectNamespaces(
|
|
284
|
+
config.durableObjectNamespaces,
|
|
285
|
+
),
|
|
286
|
+
hyperdrives: config.hyperdrives,
|
|
287
|
+
assets: toRuntimeAssets(config.assets),
|
|
288
|
+
},
|
|
289
|
+
context,
|
|
290
|
+
},
|
|
291
|
+
);
|
|
292
|
+
console.log("vite dev server started", id);
|
|
293
|
+
const localAddress = devServer.resolvedUrls!.local[0].slice(0, -1);
|
|
294
|
+
yield* localProxy.setLocalAddress(id, localAddress);
|
|
295
|
+
} else {
|
|
296
|
+
yield* runServer(config);
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
workerId: config.name,
|
|
300
|
+
workerName: config.name,
|
|
301
|
+
logpush: undefined,
|
|
302
|
+
url,
|
|
303
|
+
tags: [],
|
|
304
|
+
durableObjectNamespaces: config.durableObjectNamespaces,
|
|
305
|
+
domains: [],
|
|
306
|
+
crons: Array.from(
|
|
307
|
+
new Set([...getCronBindings(bindings), ...(props.crons ?? [])]),
|
|
308
|
+
),
|
|
309
|
+
accountId,
|
|
310
|
+
} satisfies Worker["Attributes"];
|
|
119
311
|
});
|
|
120
312
|
|
|
121
313
|
return Sidecar.of({
|
|
122
|
-
|
|
123
|
-
const hash = Hash.structure(
|
|
124
|
-
|
|
314
|
+
diff: Effect.fn(function* (options) {
|
|
315
|
+
const hash = Hash.structure(options);
|
|
316
|
+
return {
|
|
317
|
+
action: instances.get(options.id)?.hash === hash ? "noop" : "update",
|
|
318
|
+
};
|
|
319
|
+
}),
|
|
320
|
+
reconcile: Effect.fn(function* (options) {
|
|
321
|
+
const hash = Hash.structure(options);
|
|
322
|
+
const existing = instances.get(options.id);
|
|
125
323
|
if (existing) {
|
|
126
324
|
if (existing.hash === hash) {
|
|
127
325
|
yield* Effect.log(
|
|
128
|
-
`[${
|
|
326
|
+
`[${options.id}] No changes, using existing instance`,
|
|
129
327
|
);
|
|
130
328
|
return yield* Fiber.join(existing.fiber);
|
|
131
329
|
}
|
|
132
330
|
yield* Effect.log(
|
|
133
|
-
`[${
|
|
331
|
+
`[${options.id}] Changes detected, interrupting existing instance`,
|
|
134
332
|
);
|
|
135
333
|
yield* Fiber.interrupt(existing.fiber);
|
|
136
334
|
yield* Scope.close(existing.scope, Exit.void);
|
|
137
|
-
|
|
335
|
+
instances.delete(options.id);
|
|
138
336
|
}
|
|
139
337
|
const scope = yield* Scope.fork(rootScope);
|
|
140
|
-
const fiber = yield*
|
|
338
|
+
const fiber = yield* runInstance(options).pipe(
|
|
141
339
|
Effect.forkDetach,
|
|
142
340
|
Scope.provide(scope),
|
|
143
341
|
);
|
|
144
|
-
|
|
342
|
+
instances.set(options.id, { hash, fiber, scope });
|
|
145
343
|
return yield* Fiber.join(fiber).pipe(
|
|
146
344
|
Effect.onExit((exit) =>
|
|
147
345
|
Effect.sync(() => {
|
|
148
346
|
if (exit._tag === "Failure") {
|
|
149
|
-
|
|
347
|
+
instances.delete(options.id);
|
|
150
348
|
}
|
|
151
349
|
}),
|
|
152
350
|
),
|
|
153
351
|
);
|
|
154
352
|
}),
|
|
155
|
-
|
|
156
|
-
const
|
|
157
|
-
if (
|
|
158
|
-
yield* Fiber.interrupt(
|
|
159
|
-
yield* Scope.close(
|
|
160
|
-
|
|
353
|
+
delete: Effect.fn(function* (id) {
|
|
354
|
+
const existing = instances.get(id);
|
|
355
|
+
if (existing) {
|
|
356
|
+
yield* Fiber.interrupt(existing.fiber);
|
|
357
|
+
yield* Scope.close(existing.scope, Exit.void);
|
|
358
|
+
instances.delete(id);
|
|
161
359
|
}
|
|
162
360
|
}),
|
|
163
361
|
});
|
|
164
362
|
}),
|
|
165
363
|
);
|
|
166
364
|
|
|
167
|
-
function
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (file.path.endsWith(".map")) {
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
if (file.content instanceof Uint8Array) {
|
|
176
|
-
modules.push({
|
|
177
|
-
name: file.path,
|
|
178
|
-
type: file.path.endsWith(".wasm") ? "Wasm" : "Data",
|
|
179
|
-
content: file.content,
|
|
180
|
-
});
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
modules.push({
|
|
184
|
-
name: file.path,
|
|
185
|
-
type: "ESModule",
|
|
186
|
-
content: file.content,
|
|
365
|
+
const toRuntimeBinding = Effect.fnUntraced(function* (b: WorkerBinding) {
|
|
366
|
+
const unsupported = () =>
|
|
367
|
+
new ValidationError({
|
|
368
|
+
message: `${b.type} bindings are not supported in local mode`,
|
|
369
|
+
value: b,
|
|
187
370
|
});
|
|
371
|
+
switch (b.type) {
|
|
372
|
+
case "ai":
|
|
373
|
+
return Ai.remote(b.name);
|
|
374
|
+
case "analytics_engine":
|
|
375
|
+
return yield* unsupported();
|
|
376
|
+
case "artifacts":
|
|
377
|
+
return yield* unsupported();
|
|
378
|
+
case "assets":
|
|
379
|
+
return Assets.binding(b.name);
|
|
380
|
+
case "browser":
|
|
381
|
+
return Browser.binding(b.name);
|
|
382
|
+
case "d1":
|
|
383
|
+
return D1.remote(b.name, b.id);
|
|
384
|
+
case "data_blob":
|
|
385
|
+
return Data.binding(b.name, Buffer.from(b.part));
|
|
386
|
+
case "dispatch_namespace":
|
|
387
|
+
return yield* unsupported();
|
|
388
|
+
case "durable_object_namespace":
|
|
389
|
+
return DurableObjectNamespace.local({
|
|
390
|
+
name: b.name,
|
|
391
|
+
className: b.className!,
|
|
392
|
+
scriptName: b.scriptName,
|
|
393
|
+
});
|
|
394
|
+
case "hyperdrive":
|
|
395
|
+
return Hyperdrive.binding(b.name, b.id);
|
|
396
|
+
case "images":
|
|
397
|
+
return Images.remote(b.name);
|
|
398
|
+
case "inherit":
|
|
399
|
+
return yield* unsupported();
|
|
400
|
+
case "json":
|
|
401
|
+
return Json.binding(b.name, b.json);
|
|
402
|
+
case "kv_namespace":
|
|
403
|
+
return KvNamespace.remote(b.name, b.namespaceId);
|
|
404
|
+
case "mtls_certificate":
|
|
405
|
+
return yield* unsupported();
|
|
406
|
+
case "pipelines":
|
|
407
|
+
return yield* unsupported();
|
|
408
|
+
case "plain_text":
|
|
409
|
+
return Text.binding(b.name, b.text);
|
|
410
|
+
case "queue":
|
|
411
|
+
return yield* unsupported();
|
|
412
|
+
case "r2_bucket":
|
|
413
|
+
return R2Bucket.remote(b.name, b.bucketName, b.jurisdiction);
|
|
414
|
+
case "ratelimit":
|
|
415
|
+
return yield* unsupported();
|
|
416
|
+
case "secret_key":
|
|
417
|
+
return yield* unsupported();
|
|
418
|
+
case "secret_text":
|
|
419
|
+
return Text.binding(b.name, b.text);
|
|
420
|
+
case "secrets_store_secret":
|
|
421
|
+
return yield* unsupported();
|
|
422
|
+
case "send_email":
|
|
423
|
+
return yield* unsupported();
|
|
424
|
+
case "service":
|
|
425
|
+
return Service.local({ name: b.name, scriptName: b.service });
|
|
426
|
+
case "text_blob":
|
|
427
|
+
return Data.binding(b.name, Buffer.from(b.part));
|
|
428
|
+
case "vectorize":
|
|
429
|
+
return yield* unsupported();
|
|
430
|
+
case "version_metadata":
|
|
431
|
+
return VersionMetadata.binding(b.name);
|
|
432
|
+
case "wasm_module":
|
|
433
|
+
return WasmModule.binding(b.name, Buffer.from(b.part));
|
|
434
|
+
case "worker_loader":
|
|
435
|
+
return WorkerLoader.binding(b.name);
|
|
436
|
+
case "workflow":
|
|
437
|
+
return yield* unsupported();
|
|
438
|
+
default:
|
|
439
|
+
return yield* unsupported();
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
const toRuntimeAssets = (
|
|
444
|
+
assets: WorkerAssetsConfig | undefined,
|
|
445
|
+
): RuntimeAssets | undefined => {
|
|
446
|
+
if (!assets) return undefined;
|
|
447
|
+
if (typeof assets === "string") {
|
|
448
|
+
return {
|
|
449
|
+
directory: assets,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
return {
|
|
453
|
+
directory: "directory" in assets ? assets.directory : assets.path,
|
|
454
|
+
headers: assets.config?.headers,
|
|
455
|
+
redirects: assets.config?.redirects,
|
|
456
|
+
htmlHandling: assets.config?.htmlHandling,
|
|
457
|
+
notFoundHandling: assets.config?.notFoundHandling,
|
|
458
|
+
runWorkerFirst: assets.config?.runWorkerFirst,
|
|
459
|
+
serveDirectly: assets.config?.serveDirectly,
|
|
460
|
+
};
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const toRuntimeDurableObjectNamespaces = (
|
|
464
|
+
namespaces: Record<string, string>,
|
|
465
|
+
): RuntimeDurableObjectNamespace[] => {
|
|
466
|
+
return Object.entries(namespaces).map(([className, namespaceId]) => ({
|
|
467
|
+
className,
|
|
468
|
+
uniqueKey: namespaceId,
|
|
469
|
+
sql: true,
|
|
470
|
+
}));
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
const moduleTypeFromExtension = (ext: string): Module["type"] | "SourceMap" => {
|
|
474
|
+
switch (ext) {
|
|
475
|
+
case ".wasm":
|
|
476
|
+
return "Wasm";
|
|
477
|
+
case ".txt":
|
|
478
|
+
case ".html":
|
|
479
|
+
case ".sql":
|
|
480
|
+
case ".custom":
|
|
481
|
+
return "Text";
|
|
482
|
+
case ".bin":
|
|
483
|
+
return "Data";
|
|
484
|
+
case ".mjs":
|
|
485
|
+
case ".js":
|
|
486
|
+
return "ESModule";
|
|
487
|
+
case ".cjs":
|
|
488
|
+
return "CommonJsModule";
|
|
489
|
+
case ".map":
|
|
490
|
+
return "SourceMap";
|
|
491
|
+
default:
|
|
492
|
+
return "Text";
|
|
188
493
|
}
|
|
189
|
-
|
|
190
|
-
}
|
|
494
|
+
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
layerLocalProxy,
|
|
3
|
+
layerRuntime,
|
|
4
|
+
} from "@distilled.cloud/cloudflare-runtime/RuntimeServices";
|
|
2
5
|
import * as Effect from "effect/Effect";
|
|
3
6
|
import * as Layer from "effect/Layer";
|
|
4
7
|
import * as Path from "effect/Path";
|
|
@@ -31,6 +34,7 @@ const apiServices = Layer.merge(
|
|
|
31
34
|
);
|
|
32
35
|
|
|
33
36
|
const runtimeServices = SidecarHandlers.pipe(
|
|
37
|
+
Layer.provide(layerLocalProxy(1337)),
|
|
34
38
|
Layer.provide(
|
|
35
39
|
Layer.unwrap(
|
|
36
40
|
Effect.gen(function* () {
|
|
@@ -38,9 +42,13 @@ const runtimeServices = SidecarHandlers.pipe(
|
|
|
38
42
|
yield* CloudflareEnvironment.CloudflareEnvironment;
|
|
39
43
|
const { dotAlchemy } = yield* AlchemyContext.AlchemyContext;
|
|
40
44
|
const path = yield* Path.Path;
|
|
41
|
-
return
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
return layerRuntime({
|
|
46
|
+
api: {
|
|
47
|
+
accountId,
|
|
48
|
+
},
|
|
49
|
+
storage: {
|
|
50
|
+
directory: path.join(dotAlchemy, "local"),
|
|
51
|
+
},
|
|
44
52
|
});
|
|
45
53
|
}),
|
|
46
54
|
),
|
|
@@ -29,7 +29,7 @@ export const STATE_STORE_SCRIPT_NAME = "alchemy-state-store" as const;
|
|
|
29
29
|
* compare against this constant; a mismatch (or 404) triggers a
|
|
30
30
|
* forced redeploy via the bootstrap flow.
|
|
31
31
|
*/
|
|
32
|
-
export const STATE_STORE_VERSION =
|
|
32
|
+
export const STATE_STORE_VERSION = 5 as const;
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* Hard-coded OTLP/HTTP endpoints. Point at the public ingest relay
|