alchemy-effect 0.7.0 → 0.8.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/bin/alchemy-effect.js +9 -7
- package/bin/alchemy-effect.js.map +1 -1
- package/bin/alchemy-effect.ts +11 -0
- package/package.json +1 -1
- package/src/AWS/AutoScaling/LaunchTemplate.ts +5 -4
- package/src/AWS/EC2/Instance.ts +3 -4
- package/src/AWS/ECS/Task.ts +36 -34
- package/src/AWS/Lambda/Function.ts +68 -68
- package/src/Binding.ts +10 -3
- package/src/Cloudflare/Container.ts +68 -67
- package/src/Cloudflare/D1/D1Database.ts +32 -32
- package/src/Cloudflare/KV/Delete.ts +7 -5
- package/src/Cloudflare/KV/Get.ts +5 -5
- package/src/Cloudflare/KV/GetWithMetadata.ts +5 -5
- package/src/Cloudflare/KV/{Namespace.ts → KVNamespace.ts} +6 -6
- package/src/Cloudflare/KV/{NamespaceBinding.ts → KVNamespaceBinding.ts} +2 -2
- package/src/Cloudflare/KV/List.ts +5 -5
- package/src/Cloudflare/KV/Put.ts +5 -5
- package/src/Cloudflare/KV/index.ts +1 -1
- package/src/Cloudflare/Providers.ts +2 -8
- package/src/Cloudflare/R2/{Bucket.ts → R2Bucket.ts} +19 -19
- package/src/Cloudflare/R2/R2BucketBinding.ts +299 -0
- package/src/Cloudflare/R2/index.ts +2 -9
- package/src/Cloudflare/Workers/InferEnv.ts +23 -0
- package/src/Cloudflare/Workers/Worker.ts +185 -108
- package/src/Cloudflare/Workers/index.ts +1 -0
- package/src/Cloudflare/index.ts +2 -2
- package/src/Plan.ts +12 -0
- package/src/Platform.ts +39 -55
- package/src/Test/Vitest.ts +15 -2
- package/src/Util/effect.ts +24 -0
- package/src/Cloudflare/R2/BucketBinding.ts +0 -31
- package/src/Cloudflare/R2/CreateMultipartUpload.ts +0 -59
- package/src/Cloudflare/R2/DeleteObject.ts +0 -41
- package/src/Cloudflare/R2/GetObject.ts +0 -47
- package/src/Cloudflare/R2/HeadObject.ts +0 -41
- package/src/Cloudflare/R2/ListObjects.ts +0 -45
- package/src/Cloudflare/R2/MultipartUploadClient.ts +0 -40
- package/src/Cloudflare/R2/PutObject.ts +0 -55
- package/src/Cloudflare/R2/ResumeMultipartUpload.ts +0 -48
- package/src/Cloudflare/R2/UploadValue.ts +0 -10
package/bin/alchemy-effect.ts
CHANGED
|
@@ -93,6 +93,13 @@ const yes = Flag.boolean("yes").pipe(
|
|
|
93
93
|
Flag.withDefault(false),
|
|
94
94
|
);
|
|
95
95
|
|
|
96
|
+
const force = Flag.boolean("force").pipe(
|
|
97
|
+
Flag.withDescription(
|
|
98
|
+
"Force updates for resources that would otherwise no-op",
|
|
99
|
+
),
|
|
100
|
+
Flag.withDefault(false),
|
|
101
|
+
);
|
|
102
|
+
|
|
96
103
|
const fileLogger = Effect.fnUntraced(function* (
|
|
97
104
|
...segments: ReadonlyArray<string>
|
|
98
105
|
) {
|
|
@@ -142,6 +149,7 @@ const deployCommand = Command.make(
|
|
|
142
149
|
"deploy",
|
|
143
150
|
{
|
|
144
151
|
dryRun,
|
|
152
|
+
force,
|
|
145
153
|
main,
|
|
146
154
|
envFile,
|
|
147
155
|
stage,
|
|
@@ -186,6 +194,7 @@ const execStack = Effect.fn(function* ({
|
|
|
186
194
|
stage,
|
|
187
195
|
envFile,
|
|
188
196
|
dryRun = false,
|
|
197
|
+
force = false,
|
|
189
198
|
yes = false,
|
|
190
199
|
destroy = false,
|
|
191
200
|
}: {
|
|
@@ -193,6 +202,7 @@ const execStack = Effect.fn(function* ({
|
|
|
193
202
|
stage: string;
|
|
194
203
|
envFile: Option.Option<string>;
|
|
195
204
|
dryRun?: boolean;
|
|
205
|
+
force?: boolean;
|
|
196
206
|
yes?: boolean;
|
|
197
207
|
destroy?: boolean;
|
|
198
208
|
}) {
|
|
@@ -244,6 +254,7 @@ const execStack = Effect.fn(function* ({
|
|
|
244
254
|
output: {},
|
|
245
255
|
}
|
|
246
256
|
: stack,
|
|
257
|
+
{ force },
|
|
247
258
|
);
|
|
248
259
|
if (dryRun) {
|
|
249
260
|
yield* cli.displayPlan(updatePlan);
|
package/package.json
CHANGED
|
@@ -162,10 +162,11 @@ export const LaunchTemplate: Platform<
|
|
|
162
162
|
LaunchTemplateServices,
|
|
163
163
|
LaunchTemplateShape,
|
|
164
164
|
LaunchTemplateExecutionContext
|
|
165
|
-
> = Platform(
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
)
|
|
165
|
+
> = Platform("AWS.AutoScaling.LaunchTemplate", {
|
|
166
|
+
createExecutionContext: createEc2HostExecutionContext(
|
|
167
|
+
"AWS.AutoScaling.LaunchTemplate",
|
|
168
|
+
),
|
|
169
|
+
});
|
|
169
170
|
|
|
170
171
|
export const LaunchTemplateProvider = () =>
|
|
171
172
|
LaunchTemplate.provider.effect(
|
package/src/AWS/EC2/Instance.ts
CHANGED
|
@@ -304,10 +304,9 @@ export const Instance: Platform<
|
|
|
304
304
|
InstanceServices,
|
|
305
305
|
InstanceShape,
|
|
306
306
|
InstanceExecutionContext
|
|
307
|
-
> = Platform(
|
|
308
|
-
"AWS.EC2.Instance",
|
|
309
|
-
|
|
310
|
-
);
|
|
307
|
+
> = Platform("AWS.EC2.Instance", {
|
|
308
|
+
createExecutionContext: createEc2HostExecutionContext("AWS.EC2.Instance"),
|
|
309
|
+
});
|
|
311
310
|
|
|
312
311
|
export const InstanceProvider = () =>
|
|
313
312
|
Instance.provider.effect(
|
package/src/AWS/ECS/Task.ts
CHANGED
|
@@ -174,43 +174,45 @@ export const Task: Platform<
|
|
|
174
174
|
TaskServices,
|
|
175
175
|
TaskShape,
|
|
176
176
|
TaskExecutionContext
|
|
177
|
-
> = Platform("AWS.ECS.Task",
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
.
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
Effect.
|
|
197
|
-
try
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
),
|
|
201
|
-
Effect.catch((cause) =>
|
|
202
|
-
Effect.die(
|
|
203
|
-
new Error(`Failed to get environment variable: ${key}`, {
|
|
204
|
-
cause,
|
|
177
|
+
> = Platform("AWS.ECS.Task", {
|
|
178
|
+
createExecutionContext: (id): TaskExecutionContext => {
|
|
179
|
+
const runners: Effect.Effect<void, never, any>[] = [];
|
|
180
|
+
const env: Record<string, any> = {};
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
Type: "AWS.ECS.Task",
|
|
184
|
+
id,
|
|
185
|
+
env,
|
|
186
|
+
set: (bindingId: string, output: Output.Output) =>
|
|
187
|
+
Effect.sync(() => {
|
|
188
|
+
const key = bindingId.replaceAll(/[^a-zA-Z0-9]/g, "_");
|
|
189
|
+
env[key] = output.pipe(Output.map((value) => JSON.stringify(value)));
|
|
190
|
+
return key;
|
|
191
|
+
}),
|
|
192
|
+
get: <T>(key: string) =>
|
|
193
|
+
Config.string(key)
|
|
194
|
+
.asEffect()
|
|
195
|
+
.pipe(
|
|
196
|
+
Effect.flatMap((value) =>
|
|
197
|
+
Effect.try({
|
|
198
|
+
try: () => JSON.parse(value) as T,
|
|
199
|
+
catch: (error) => error as Error,
|
|
205
200
|
}),
|
|
206
201
|
),
|
|
202
|
+
Effect.catch((cause) =>
|
|
203
|
+
Effect.die(
|
|
204
|
+
new Error(`Failed to get environment variable: ${key}`, {
|
|
205
|
+
cause,
|
|
206
|
+
}),
|
|
207
|
+
),
|
|
208
|
+
),
|
|
207
209
|
),
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
210
|
+
run: (effect: Effect.Effect<void, never, any>) =>
|
|
211
|
+
Effect.sync(() => {
|
|
212
|
+
runners.push(effect);
|
|
213
|
+
}),
|
|
214
|
+
};
|
|
215
|
+
},
|
|
214
216
|
});
|
|
215
217
|
|
|
216
218
|
export const TaskProvider = () =>
|
|
@@ -9,7 +9,6 @@ import * as Config from "effect/Config";
|
|
|
9
9
|
import * as Effect from "effect/Effect";
|
|
10
10
|
import * as FileSystem from "effect/FileSystem";
|
|
11
11
|
import * as Option from "effect/Option";
|
|
12
|
-
import * as Path from "effect/Path";
|
|
13
12
|
import * as Schedule from "effect/Schedule";
|
|
14
13
|
import * as ServiceMap from "effect/ServiceMap";
|
|
15
14
|
import * as Stream from "effect/Stream";
|
|
@@ -139,76 +138,78 @@ export const Function: Platform<
|
|
|
139
138
|
FunctionServices,
|
|
140
139
|
FunctionShape,
|
|
141
140
|
Serverless.FunctionContext
|
|
142
|
-
> = Platform(FunctionTypeId,
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
Effect.
|
|
162
|
-
try
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
),
|
|
166
|
-
Effect.catch((cause) =>
|
|
167
|
-
Effect.die(
|
|
168
|
-
new Error(`Failed to get environment variable: ${key}`, {
|
|
169
|
-
cause,
|
|
141
|
+
> = Platform(FunctionTypeId, {
|
|
142
|
+
createExecutionContext: (id: string): Serverless.FunctionContext => {
|
|
143
|
+
const listeners: Effect.Effect<Serverless.FunctionListener>[] = [];
|
|
144
|
+
const env: Record<string, any> = {};
|
|
145
|
+
|
|
146
|
+
const ctx = {
|
|
147
|
+
Type: FunctionTypeId,
|
|
148
|
+
id,
|
|
149
|
+
env,
|
|
150
|
+
set: (id: string, output: Output.Output) =>
|
|
151
|
+
Effect.sync(() => {
|
|
152
|
+
const key = id.replaceAll(/[^a-zA-Z0-9]/g, "_");
|
|
153
|
+
env[key] = output.pipe(Output.map((value) => JSON.stringify(value)));
|
|
154
|
+
return key;
|
|
155
|
+
}),
|
|
156
|
+
get: <T>(key: string) =>
|
|
157
|
+
Config.string(key)
|
|
158
|
+
.asEffect()
|
|
159
|
+
.pipe(
|
|
160
|
+
Effect.flatMap((val) =>
|
|
161
|
+
Effect.try({
|
|
162
|
+
try: () => JSON.parse(val) as T,
|
|
163
|
+
catch: () => val, // assume it's just a string
|
|
170
164
|
}),
|
|
171
165
|
),
|
|
166
|
+
Effect.catch((cause) =>
|
|
167
|
+
Effect.die(
|
|
168
|
+
new Error(`Failed to get environment variable: ${key}`, {
|
|
169
|
+
cause,
|
|
170
|
+
}),
|
|
171
|
+
),
|
|
172
|
+
),
|
|
172
173
|
),
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
174
|
+
serve: (handler: HttpEffect) =>
|
|
175
|
+
ctx.listen(makeFunctionHttpHandler(handler)),
|
|
176
|
+
listen: ((
|
|
177
|
+
handler:
|
|
178
|
+
| Serverless.FunctionListener
|
|
179
|
+
| Effect.Effect<Serverless.FunctionListener>,
|
|
180
|
+
) =>
|
|
181
|
+
Effect.sync(() =>
|
|
182
|
+
Effect.isEffect(handler)
|
|
183
|
+
? listeners.push(handler)
|
|
184
|
+
: listeners.push(Effect.succeed(handler)),
|
|
185
|
+
)) as any as Serverless.FunctionContext["listen"],
|
|
186
|
+
exports: Effect.sync(() => ({
|
|
187
|
+
// construct an Effect that produces the Function's entrypoint
|
|
188
|
+
// Effect<(event, context) => Promise<any>>
|
|
189
|
+
handler: Effect.map(
|
|
190
|
+
Effect.all(listeners, {
|
|
191
|
+
concurrency: "unbounded",
|
|
192
|
+
}),
|
|
193
|
+
(handlers) =>
|
|
194
|
+
async (event: any, context: lambda.Context): Promise<any> => {
|
|
195
|
+
console.log({ event, handlers });
|
|
196
|
+
for (const handler of handlers) {
|
|
197
|
+
const eff = handler(event);
|
|
198
|
+
if (Effect.isEffect(eff)) {
|
|
199
|
+
return await eff.pipe(
|
|
200
|
+
Effect.provideService(HandlerContext, context),
|
|
201
|
+
Effect.tap(Effect.logDebug),
|
|
202
|
+
Effect.runPromise,
|
|
203
|
+
);
|
|
204
|
+
}
|
|
204
205
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
),
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
|
|
206
|
+
throw new Error("No event handler found");
|
|
207
|
+
},
|
|
208
|
+
),
|
|
209
|
+
})),
|
|
210
|
+
};
|
|
211
|
+
return ctx;
|
|
212
|
+
},
|
|
212
213
|
});
|
|
213
214
|
|
|
214
215
|
export const FunctionProvider = () =>
|
|
@@ -218,7 +219,6 @@ export const FunctionProvider = () =>
|
|
|
218
219
|
const accountId = yield* Account;
|
|
219
220
|
const region = yield* Region;
|
|
220
221
|
const fs = yield* FileSystem.FileSystem;
|
|
221
|
-
const path = yield* Path.Path;
|
|
222
222
|
const virtualEntryPlugin = yield* Bundle.virtualEntryPlugin;
|
|
223
223
|
const alchemyEnv = {
|
|
224
224
|
ALCHEMY_STACK_NAME: stack.name,
|
package/src/Binding.ts
CHANGED
|
@@ -28,15 +28,22 @@ export interface Service<
|
|
|
28
28
|
extends ServiceMap.Service<Self, Shape>, ServiceLike {
|
|
29
29
|
readonly key: Identifier;
|
|
30
30
|
new (_: never): ServiceShape<Identifier, Shape>;
|
|
31
|
-
bind: (
|
|
32
|
-
...args: Parameters<Shape>
|
|
31
|
+
bind: <Req = never>(
|
|
32
|
+
...args: BindParameters<Parameters<Shape>, Req>
|
|
33
33
|
) => Effect.Effect<
|
|
34
34
|
Effect.Success<ReturnType<Shape>>,
|
|
35
35
|
Effect.Error<ReturnType<Shape>>,
|
|
36
|
-
Self | Effect.Services<ReturnType<Shape>>
|
|
36
|
+
Self | Effect.Services<ReturnType<Shape>> | Req
|
|
37
37
|
>;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
type BindParameters<
|
|
41
|
+
Parameters extends any[],
|
|
42
|
+
Req = never,
|
|
43
|
+
> = Parameters extends [infer First, ...infer Rest]
|
|
44
|
+
? [First | Effect.Effect<First, never, Req>, ...BindParameters<Rest, Req>]
|
|
45
|
+
: [];
|
|
46
|
+
|
|
40
47
|
/**
|
|
41
48
|
* Creates a runtime binding service.
|
|
42
49
|
*
|
|
@@ -268,80 +268,82 @@ export const Container: Platform<
|
|
|
268
268
|
ContainerShape,
|
|
269
269
|
Server.ProcessContext,
|
|
270
270
|
Container
|
|
271
|
-
> = Platform("Cloudflare.Container",
|
|
272
|
-
|
|
273
|
-
|
|
271
|
+
> = Platform("Cloudflare.Container", {
|
|
272
|
+
createExecutionContext: (id: string): Server.ProcessContext => {
|
|
273
|
+
const runners: Effect.Effect<void, never, any>[] = [];
|
|
274
|
+
const env: Record<string, any> = {};
|
|
274
275
|
|
|
275
|
-
|
|
276
|
-
Effect.sync(() => {
|
|
277
|
-
runners.push(
|
|
278
|
-
Effect.gen(function* () {
|
|
279
|
-
const httpServer = yield* Effect.serviceOption(HttpServer).pipe(
|
|
280
|
-
Effect.map(Option.getOrUndefined),
|
|
281
|
-
);
|
|
282
|
-
if (httpServer) {
|
|
283
|
-
yield* httpServer.serve(handler);
|
|
284
|
-
yield* Effect.never;
|
|
285
|
-
} else {
|
|
286
|
-
// this should only happen at plantime, validate?
|
|
287
|
-
}
|
|
288
|
-
}).pipe(Effect.orDie),
|
|
289
|
-
);
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
return {
|
|
293
|
-
Type: ContainerTypeId,
|
|
294
|
-
LogicalId: id,
|
|
295
|
-
id,
|
|
296
|
-
env,
|
|
297
|
-
set: (bindingId: string, output: Output.Output) =>
|
|
276
|
+
const serve = <Req = never>(handler: HttpEffect<Req>) =>
|
|
298
277
|
Effect.sync(() => {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
278
|
+
runners.push(
|
|
279
|
+
Effect.gen(function* () {
|
|
280
|
+
const httpServer = yield* Effect.serviceOption(HttpServer).pipe(
|
|
281
|
+
Effect.map(Option.getOrUndefined),
|
|
282
|
+
);
|
|
283
|
+
if (httpServer) {
|
|
284
|
+
yield* httpServer.serve(handler);
|
|
285
|
+
yield* Effect.never;
|
|
286
|
+
} else {
|
|
287
|
+
// this should only happen at plantime, validate?
|
|
288
|
+
}
|
|
289
|
+
}).pipe(Effect.orDie),
|
|
290
|
+
);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
Type: ContainerTypeId,
|
|
295
|
+
LogicalId: id,
|
|
296
|
+
id,
|
|
297
|
+
env,
|
|
298
|
+
set: (bindingId: string, output: Output.Output) =>
|
|
299
|
+
Effect.sync(() => {
|
|
300
|
+
const key = bindingId.replaceAll(/[^a-zA-Z0-9]/g, "_");
|
|
301
|
+
env[key] = output.pipe(Output.map((value) => JSON.stringify(value)));
|
|
302
|
+
return key;
|
|
303
|
+
}),
|
|
304
|
+
get: <T>(key: string) =>
|
|
305
|
+
Config.string(key)
|
|
306
|
+
.asEffect()
|
|
307
|
+
.pipe(
|
|
308
|
+
Effect.flatMap((value) =>
|
|
309
|
+
Effect.try({
|
|
310
|
+
try: () => JSON.parse(value) as T,
|
|
311
|
+
catch: (error) => error as Error,
|
|
317
312
|
}),
|
|
318
313
|
),
|
|
314
|
+
Effect.catch((cause) =>
|
|
315
|
+
Effect.die(
|
|
316
|
+
new Error(`Failed to get environment variable: ${key}`, {
|
|
317
|
+
cause,
|
|
318
|
+
}),
|
|
319
|
+
),
|
|
320
|
+
),
|
|
319
321
|
),
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
322
|
+
run: ((effect: Effect.Effect<void, never, any>) =>
|
|
323
|
+
Effect.sync(() => {
|
|
324
|
+
runners.push(effect);
|
|
325
|
+
})) as unknown as Server.ProcessContext["run"],
|
|
326
|
+
serve,
|
|
327
|
+
exports: Effect.sync(() => ({
|
|
328
|
+
default: Effect.all(
|
|
329
|
+
runners.map((eff) =>
|
|
330
|
+
Effect.forever(
|
|
331
|
+
eff.pipe(
|
|
332
|
+
// Log and ignore errors (daemon mode, it should just re-run)
|
|
333
|
+
Effect.tapError((err) => Effect.logError(err)),
|
|
334
|
+
Effect.ignore,
|
|
335
|
+
// TODO(sam): ignore cause? for now, let that actually kill the server
|
|
336
|
+
// Effect.ignoreCause
|
|
337
|
+
),
|
|
336
338
|
),
|
|
337
339
|
),
|
|
340
|
+
{
|
|
341
|
+
concurrency: "unbounded",
|
|
342
|
+
},
|
|
338
343
|
),
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
),
|
|
343
|
-
})),
|
|
344
|
-
} as Server.ProcessContext;
|
|
344
|
+
})),
|
|
345
|
+
} as Server.ProcessContext;
|
|
346
|
+
},
|
|
345
347
|
});
|
|
346
348
|
|
|
347
349
|
export const bindContainer = Effect.fnUntraced(function* <Shape, Req = never>(
|
|
@@ -637,7 +639,6 @@ export const ContainerProvider = () =>
|
|
|
637
639
|
});
|
|
638
640
|
|
|
639
641
|
const bundleProgram = Effect.fnUntraced(function* ({
|
|
640
|
-
id,
|
|
641
642
|
main,
|
|
642
643
|
runtime,
|
|
643
644
|
handler = "default",
|
|
@@ -123,6 +123,38 @@ export const DatabaseProvider = (): Layer<
|
|
|
123
123
|
return { action: "update" } as const;
|
|
124
124
|
}
|
|
125
125
|
}),
|
|
126
|
+
read: Effect.fn(function* ({ id, output, olds }) {
|
|
127
|
+
if (output?.databaseId) {
|
|
128
|
+
return yield* getDb({
|
|
129
|
+
accountId: output.accountId,
|
|
130
|
+
databaseId: output.databaseId,
|
|
131
|
+
}).pipe(
|
|
132
|
+
Effect.map((db) => ({
|
|
133
|
+
databaseId: db.uuid ?? output.databaseId,
|
|
134
|
+
databaseName: db.name ?? output.databaseName,
|
|
135
|
+
jurisdiction: output.jurisdiction,
|
|
136
|
+
readReplication: db.readReplication ?? undefined,
|
|
137
|
+
accountId: output.accountId,
|
|
138
|
+
})),
|
|
139
|
+
Effect.catchTag("DatabaseNotFound", () =>
|
|
140
|
+
Effect.succeed(undefined),
|
|
141
|
+
),
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
const name = yield* createDatabaseName(id, olds?.name);
|
|
145
|
+
const dbs = yield* listDbs({ accountId, name });
|
|
146
|
+
const match = dbs.result.find((db) => db.name === name);
|
|
147
|
+
if (match) {
|
|
148
|
+
return {
|
|
149
|
+
databaseId: match.uuid!,
|
|
150
|
+
databaseName: match.name ?? name,
|
|
151
|
+
jurisdiction: (olds?.jurisdiction ?? "default") as Jurisdiction,
|
|
152
|
+
readReplication: olds?.readReplication,
|
|
153
|
+
accountId,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return undefined;
|
|
157
|
+
}),
|
|
126
158
|
create: Effect.fn(function* ({ id, news = {} }) {
|
|
127
159
|
const name = yield* createDatabaseName(id, news.name);
|
|
128
160
|
const jurisdiction = news.jurisdiction ?? "default";
|
|
@@ -185,38 +217,6 @@ export const DatabaseProvider = (): Layer<
|
|
|
185
217
|
databaseId: output.databaseId,
|
|
186
218
|
}).pipe(Effect.catchTag("DatabaseNotFound", () => Effect.void));
|
|
187
219
|
}),
|
|
188
|
-
read: Effect.fn(function* ({ id, output, olds }) {
|
|
189
|
-
if (output?.databaseId) {
|
|
190
|
-
return yield* getDb({
|
|
191
|
-
accountId: output.accountId,
|
|
192
|
-
databaseId: output.databaseId,
|
|
193
|
-
}).pipe(
|
|
194
|
-
Effect.map((db) => ({
|
|
195
|
-
databaseId: db.uuid ?? output.databaseId,
|
|
196
|
-
databaseName: db.name ?? output.databaseName,
|
|
197
|
-
jurisdiction: output.jurisdiction,
|
|
198
|
-
readReplication: db.readReplication ?? undefined,
|
|
199
|
-
accountId: output.accountId,
|
|
200
|
-
})),
|
|
201
|
-
Effect.catchTag("DatabaseNotFound", () =>
|
|
202
|
-
Effect.succeed(undefined),
|
|
203
|
-
),
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
const name = yield* createDatabaseName(id, olds?.name);
|
|
207
|
-
const dbs = yield* listDbs({ accountId, name });
|
|
208
|
-
const match = dbs.result.find((db) => db.name === name);
|
|
209
|
-
if (match) {
|
|
210
|
-
return {
|
|
211
|
-
databaseId: match.uuid!,
|
|
212
|
-
databaseName: match.name ?? name,
|
|
213
|
-
jurisdiction: (olds?.jurisdiction ?? "default") as Jurisdiction,
|
|
214
|
-
readReplication: olds?.readReplication,
|
|
215
|
-
accountId,
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
return undefined;
|
|
219
|
-
}),
|
|
220
220
|
};
|
|
221
221
|
}),
|
|
222
222
|
);
|
|
@@ -3,12 +3,14 @@ import * as Effect from "effect/Effect";
|
|
|
3
3
|
import * as Layer from "effect/Layer";
|
|
4
4
|
import * as Binding from "../../Binding.ts";
|
|
5
5
|
import { WorkerEnvironment } from "../Workers/Worker.ts";
|
|
6
|
-
import type {
|
|
7
|
-
import { NamespaceBinding } from "./
|
|
6
|
+
import type { KVNamespace } from "./KVNamespace.ts";
|
|
7
|
+
import { NamespaceBinding } from "./KVNamespaceBinding.ts";
|
|
8
8
|
|
|
9
9
|
export class Delete extends Binding.Service<
|
|
10
10
|
Delete,
|
|
11
|
-
(
|
|
11
|
+
(
|
|
12
|
+
namespace: KVNamespace,
|
|
13
|
+
) => Effect.Effect<(key: string) => Effect.Effect<void>>
|
|
12
14
|
>()("Cloudflare.KV.Delete") {}
|
|
13
15
|
|
|
14
16
|
export const DeleteLive = Layer.effect(
|
|
@@ -17,7 +19,7 @@ export const DeleteLive = Layer.effect(
|
|
|
17
19
|
const Policy = yield* DeletePolicy;
|
|
18
20
|
const env = yield* WorkerEnvironment;
|
|
19
21
|
|
|
20
|
-
return Effect.fn(function* (namespace:
|
|
22
|
+
return Effect.fn(function* (namespace: KVNamespace) {
|
|
21
23
|
yield* Policy(namespace);
|
|
22
24
|
const kvNamespace = (env as Record<string, runtime.KVNamespace>)[
|
|
23
25
|
namespace.LogicalId
|
|
@@ -32,7 +34,7 @@ export const DeleteLive = Layer.effect(
|
|
|
32
34
|
|
|
33
35
|
export class DeletePolicy extends Binding.Policy<
|
|
34
36
|
DeletePolicy,
|
|
35
|
-
(namespace:
|
|
37
|
+
(namespace: KVNamespace) => Effect.Effect<void>
|
|
36
38
|
>()("Cloudflare.KV.Delete") {}
|
|
37
39
|
|
|
38
40
|
export const DeletePolicyLive = DeletePolicy.layer.succeed(NamespaceBinding);
|
package/src/Cloudflare/KV/Get.ts
CHANGED
|
@@ -3,13 +3,13 @@ import * as Effect from "effect/Effect";
|
|
|
3
3
|
import * as Layer from "effect/Layer";
|
|
4
4
|
import * as Binding from "../../Binding.ts";
|
|
5
5
|
import { WorkerEnvironment } from "../Workers/Worker.ts";
|
|
6
|
-
import type {
|
|
7
|
-
import { NamespaceBinding } from "./
|
|
6
|
+
import type { KVNamespace } from "./KVNamespace.ts";
|
|
7
|
+
import { NamespaceBinding } from "./KVNamespaceBinding.ts";
|
|
8
8
|
|
|
9
9
|
export class Get extends Binding.Service<
|
|
10
10
|
Get,
|
|
11
11
|
(
|
|
12
|
-
namespace:
|
|
12
|
+
namespace: KVNamespace,
|
|
13
13
|
) => Effect.Effect<(key: string) => Effect.Effect<string | null>>
|
|
14
14
|
>()("Cloudflare.KV.Get") {}
|
|
15
15
|
|
|
@@ -19,7 +19,7 @@ export const GetLive = Layer.effect(
|
|
|
19
19
|
const Policy = yield* GetPolicy;
|
|
20
20
|
const env = yield* WorkerEnvironment;
|
|
21
21
|
|
|
22
|
-
return Effect.fn(function* (namespace:
|
|
22
|
+
return Effect.fn(function* (namespace: KVNamespace) {
|
|
23
23
|
yield* Policy(namespace);
|
|
24
24
|
const kvNamespace = (env as Record<string, runtime.KVNamespace>)[
|
|
25
25
|
namespace.LogicalId
|
|
@@ -34,7 +34,7 @@ export const GetLive = Layer.effect(
|
|
|
34
34
|
|
|
35
35
|
export class GetPolicy extends Binding.Policy<
|
|
36
36
|
GetPolicy,
|
|
37
|
-
(namespace:
|
|
37
|
+
(namespace: KVNamespace) => Effect.Effect<void>
|
|
38
38
|
>()("Cloudflare.KV.Get") {}
|
|
39
39
|
|
|
40
40
|
export const GetPolicyLive = GetPolicy.layer.succeed(NamespaceBinding);
|