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.
Files changed (41) hide show
  1. package/bin/alchemy-effect.js +9 -7
  2. package/bin/alchemy-effect.js.map +1 -1
  3. package/bin/alchemy-effect.ts +11 -0
  4. package/package.json +1 -1
  5. package/src/AWS/AutoScaling/LaunchTemplate.ts +5 -4
  6. package/src/AWS/EC2/Instance.ts +3 -4
  7. package/src/AWS/ECS/Task.ts +36 -34
  8. package/src/AWS/Lambda/Function.ts +68 -68
  9. package/src/Binding.ts +10 -3
  10. package/src/Cloudflare/Container.ts +68 -67
  11. package/src/Cloudflare/D1/D1Database.ts +32 -32
  12. package/src/Cloudflare/KV/Delete.ts +7 -5
  13. package/src/Cloudflare/KV/Get.ts +5 -5
  14. package/src/Cloudflare/KV/GetWithMetadata.ts +5 -5
  15. package/src/Cloudflare/KV/{Namespace.ts → KVNamespace.ts} +6 -6
  16. package/src/Cloudflare/KV/{NamespaceBinding.ts → KVNamespaceBinding.ts} +2 -2
  17. package/src/Cloudflare/KV/List.ts +5 -5
  18. package/src/Cloudflare/KV/Put.ts +5 -5
  19. package/src/Cloudflare/KV/index.ts +1 -1
  20. package/src/Cloudflare/Providers.ts +2 -8
  21. package/src/Cloudflare/R2/{Bucket.ts → R2Bucket.ts} +19 -19
  22. package/src/Cloudflare/R2/R2BucketBinding.ts +299 -0
  23. package/src/Cloudflare/R2/index.ts +2 -9
  24. package/src/Cloudflare/Workers/InferEnv.ts +23 -0
  25. package/src/Cloudflare/Workers/Worker.ts +185 -108
  26. package/src/Cloudflare/Workers/index.ts +1 -0
  27. package/src/Cloudflare/index.ts +2 -2
  28. package/src/Plan.ts +12 -0
  29. package/src/Platform.ts +39 -55
  30. package/src/Test/Vitest.ts +15 -2
  31. package/src/Util/effect.ts +24 -0
  32. package/src/Cloudflare/R2/BucketBinding.ts +0 -31
  33. package/src/Cloudflare/R2/CreateMultipartUpload.ts +0 -59
  34. package/src/Cloudflare/R2/DeleteObject.ts +0 -41
  35. package/src/Cloudflare/R2/GetObject.ts +0 -47
  36. package/src/Cloudflare/R2/HeadObject.ts +0 -41
  37. package/src/Cloudflare/R2/ListObjects.ts +0 -45
  38. package/src/Cloudflare/R2/MultipartUploadClient.ts +0 -40
  39. package/src/Cloudflare/R2/PutObject.ts +0 -55
  40. package/src/Cloudflare/R2/ResumeMultipartUpload.ts +0 -48
  41. package/src/Cloudflare/R2/UploadValue.ts +0 -10
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alchemy-effect",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "homepage": "https://alchemy.run",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Sam Goodwin <sam@alchemy.run>",
@@ -162,10 +162,11 @@ export const LaunchTemplate: Platform<
162
162
  LaunchTemplateServices,
163
163
  LaunchTemplateShape,
164
164
  LaunchTemplateExecutionContext
165
- > = Platform(
166
- "AWS.AutoScaling.LaunchTemplate",
167
- createEc2HostExecutionContext("AWS.AutoScaling.LaunchTemplate"),
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(
@@ -304,10 +304,9 @@ export const Instance: Platform<
304
304
  InstanceServices,
305
305
  InstanceShape,
306
306
  InstanceExecutionContext
307
- > = Platform(
308
- "AWS.EC2.Instance",
309
- createEc2HostExecutionContext("AWS.EC2.Instance"),
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(
@@ -174,43 +174,45 @@ export const Task: Platform<
174
174
  TaskServices,
175
175
  TaskShape,
176
176
  TaskExecutionContext
177
- > = Platform("AWS.ECS.Task", (id): TaskExecutionContext => {
178
- const runners: Effect.Effect<void, never, any>[] = [];
179
- const env: Record<string, any> = {};
180
-
181
- return {
182
- Type: "AWS.ECS.Task",
183
- id,
184
- env,
185
- set: (bindingId: string, output: Output.Output) =>
186
- Effect.sync(() => {
187
- const key = bindingId.replaceAll(/[^a-zA-Z0-9]/g, "_");
188
- env[key] = output.pipe(Output.map((value) => JSON.stringify(value)));
189
- return key;
190
- }),
191
- get: <T>(key: string) =>
192
- Config.string(key)
193
- .asEffect()
194
- .pipe(
195
- Effect.flatMap((value) =>
196
- Effect.try({
197
- try: () => JSON.parse(value) as T,
198
- catch: (error) => error as Error,
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
- run: (effect: Effect.Effect<void, never, any>) =>
210
- Effect.sync(() => {
211
- runners.push(effect);
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, (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
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
- 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
- );
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
- throw new Error("No event handler found");
207
- },
208
- ),
209
- })),
210
- };
211
- return ctx;
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", (id: string): Server.ProcessContext => {
272
- const runners: Effect.Effect<void, never, any>[] = [];
273
- const env: Record<string, any> = {};
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
- const serve = <Req = never>(handler: HttpEffect<Req>) =>
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
- const key = bindingId.replaceAll(/[^a-zA-Z0-9]/g, "_");
300
- env[key] = output.pipe(Output.map((value) => JSON.stringify(value)));
301
- return key;
302
- }),
303
- get: <T>(key: string) =>
304
- Config.string(key)
305
- .asEffect()
306
- .pipe(
307
- Effect.flatMap((value) =>
308
- Effect.try({
309
- try: () => JSON.parse(value) as T,
310
- catch: (error) => error as Error,
311
- }),
312
- ),
313
- Effect.catch((cause) =>
314
- Effect.die(
315
- new Error(`Failed to get environment variable: ${key}`, {
316
- cause,
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
- run: ((effect: Effect.Effect<void, never, any>) =>
322
- Effect.sync(() => {
323
- runners.push(effect);
324
- })) as unknown as Server.ProcessContext["run"],
325
- serve,
326
- exports: Effect.sync(() => ({
327
- default: Effect.all(
328
- runners.map((eff) =>
329
- Effect.forever(
330
- eff.pipe(
331
- // Log and ignore errors (daemon mode, it should just re-run)
332
- Effect.tapError((err) => Effect.logError(err)),
333
- Effect.ignore,
334
- // TODO(sam): ignore cause? for now, let that actually kill the server
335
- // Effect.ignoreCause
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
- concurrency: "unbounded",
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 { Namespace } from "./Namespace.ts";
7
- import { NamespaceBinding } from "./NamespaceBinding.ts";
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
- (namespace: Namespace) => Effect.Effect<(key: string) => Effect.Effect<void>>
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: 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: Namespace) => Effect.Effect<void>
37
+ (namespace: KVNamespace) => Effect.Effect<void>
36
38
  >()("Cloudflare.KV.Delete") {}
37
39
 
38
40
  export const DeletePolicyLive = DeletePolicy.layer.succeed(NamespaceBinding);
@@ -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 { Namespace } from "./Namespace.ts";
7
- import { NamespaceBinding } from "./NamespaceBinding.ts";
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: 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: 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: Namespace) => Effect.Effect<void>
37
+ (namespace: KVNamespace) => Effect.Effect<void>
38
38
  >()("Cloudflare.KV.Get") {}
39
39
 
40
40
  export const GetPolicyLive = GetPolicy.layer.succeed(NamespaceBinding);