effect-cf 0.4.0 → 0.6.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/src/Kv.ts CHANGED
@@ -84,6 +84,28 @@ export interface KvService<Id extends string, Key, Value, EncodedValue> {
84
84
  };
85
85
  }
86
86
 
87
+ export interface KvClient<Key, Value, EncodedValue> {
88
+ readonly put: (
89
+ key: Key,
90
+ value: Value,
91
+ options?: KvPutOptions,
92
+ ) => Effect.Effect<void, KvOperationError | S.SchemaError>;
93
+ readonly get: (key: Key) => Effect.Effect<Option.Option<Value>, KvOperationError | S.SchemaError>;
94
+ readonly getWithMetadata: <Metadata>(
95
+ key: Key,
96
+ metadataSchema: S.Codec<Metadata, unknown>,
97
+ ) => Effect.Effect<
98
+ Option.Option<KvWithMetadata<Value, Metadata>>,
99
+ KvOperationError | S.SchemaError
100
+ >;
101
+ readonly list: <Metadata = unknown>(
102
+ options?: KvListOptions<Metadata>,
103
+ ) => Effect.Effect<KvListResult<Key, Metadata>, KvOperationError | S.SchemaError>;
104
+ readonly remove: (key: Key) => Effect.Effect<void, KvOperationError | S.SchemaError>;
105
+ readonly unsafeRaw: Effect.Effect<KVNamespace>;
106
+ readonly definition: KvDefinition<Key, Value, EncodedValue>;
107
+ }
108
+
87
109
  declare const BindingServiceTypeId: unique symbol;
88
110
 
89
111
  /** Nominal service marker for KV bindings created from a reusable {@link Definition}. */
@@ -208,46 +230,123 @@ export const Service =
208
230
  id: Id,
209
231
  definition: KvDefinition<Key, Value, EncodedValue>,
210
232
  ) => {
211
- const tag = Binding.Service<Self>()(id, definition.binding, (value): value is KVNamespace => {
212
- if (typeof value !== "object" || value === null) {
213
- return false;
214
- }
215
-
216
- const resource = value as Record<string, unknown>;
217
-
218
- return (
219
- typeof resource.get === "function" &&
220
- typeof resource.put === "function" &&
221
- typeof resource.delete === "function" &&
222
- typeof resource.getWithMetadata === "function" &&
223
- typeof resource.list === "function"
224
- );
225
- });
226
-
227
233
  const encodeKey = S.encodeEffect(definition.key);
228
234
  const decodeKey = S.decodeUnknownEffect(definition.key);
229
235
  const encodeValue = S.encodeEffect(S.fromJsonString(S.toCodecJson(definition.value)));
230
236
  const decodeValue = S.decodeUnknownEffect(S.fromJsonString(S.toCodecJson(definition.value)));
231
237
 
238
+ const makeClient = (kv: KVNamespace): KvClient<Key, Value, EncodedValue> => ({
239
+ definition,
240
+ put: Effect.fnUntraced(function* (key: Key, value: Value, options?: KvPutOptions) {
241
+ const keyEncoded = yield* encodeKey(key);
242
+ const valueEncoded = yield* encodeValue(value);
243
+ yield* tryKvPromise(definition.binding, "put", () =>
244
+ kv.put(keyEncoded, valueEncoded, options),
245
+ );
246
+ }),
247
+ get: Effect.fnUntraced(function* (key: Key) {
248
+ const keyEncoded = yield* encodeKey(key);
249
+ const valueEncoded = yield* tryKvPromise(definition.binding, "get", () =>
250
+ kv.get(keyEncoded),
251
+ );
252
+
253
+ if (valueEncoded === null) {
254
+ return Option.none();
255
+ }
256
+
257
+ return yield* decodeValue(valueEncoded).pipe(Effect.map(Option.some));
258
+ }),
259
+ getWithMetadata: Effect.fnUntraced(function* <Metadata>(
260
+ key: Key,
261
+ metadataSchema: S.Codec<Metadata, unknown>,
262
+ ) {
263
+ const keyEncoded = yield* encodeKey(key);
264
+ const result = yield* tryKvPromise(definition.binding, "getWithMetadata", () =>
265
+ kv.getWithMetadata<Metadata>(keyEncoded),
266
+ );
267
+
268
+ if (result.value === null) {
269
+ return Option.none();
270
+ }
271
+
272
+ const value = yield* decodeValue(result.value);
273
+ const metadata =
274
+ result.metadata === null
275
+ ? Option.none<Metadata>()
276
+ : Option.some(yield* S.decodeUnknownEffect(metadataSchema)(result.metadata));
277
+
278
+ return Option.some({
279
+ value,
280
+ metadata,
281
+ cacheStatus: maybeString(result.cacheStatus),
282
+ });
283
+ }),
284
+ list: Effect.fnUntraced(function* <Metadata = unknown>(options?: KvListOptions<Metadata>) {
285
+ const { metadataSchema, ...kvOptions } = options ?? {};
286
+ const result = yield* tryKvPromise(definition.binding, "list", () =>
287
+ kv.list<Metadata>(kvOptions),
288
+ );
289
+ const keys: Array<KvListKey<Key, Metadata>> = [];
290
+
291
+ for (const key of result.keys) {
292
+ const decodedName = yield* decodeKey(key.name);
293
+ const decodedMetadata =
294
+ key.metadata === undefined
295
+ ? Option.none<Metadata>()
296
+ : metadataSchema === undefined
297
+ ? Option.some(key.metadata as Metadata)
298
+ : Option.some(yield* S.decodeUnknownEffect(metadataSchema)(key.metadata));
299
+
300
+ keys.push({
301
+ name: decodedName,
302
+ expiration: maybeNumber(key.expiration),
303
+ metadata: decodedMetadata,
304
+ });
305
+ }
306
+
307
+ return {
308
+ keys,
309
+ listComplete: result.list_complete,
310
+ cursor: maybeString("cursor" in result ? result.cursor : undefined),
311
+ cacheStatus: maybeString(result.cacheStatus),
312
+ };
313
+ }),
314
+ remove: Effect.fnUntraced(function* (key: Key) {
315
+ const keyEncoded = yield* encodeKey(key);
316
+ yield* tryKvPromise(definition.binding, "delete", () => kv.delete(keyEncoded));
317
+ }),
318
+ unsafeRaw: Effect.succeed(kv),
319
+ });
320
+
321
+ const tag = Binding.Service<Self>()(
322
+ id,
323
+ definition.binding,
324
+ (value): value is KVNamespace => {
325
+ if (typeof value !== "object" || value === null) {
326
+ return false;
327
+ }
328
+
329
+ const resource = value as Record<string, unknown>;
330
+
331
+ return (
332
+ typeof resource.get === "function" &&
333
+ typeof resource.put === "function" &&
334
+ typeof resource.delete === "function" &&
335
+ typeof resource.getWithMetadata === "function" &&
336
+ typeof resource.list === "function"
337
+ );
338
+ },
339
+ makeClient,
340
+ );
341
+
232
342
  const put = Effect.fnUntraced(function* (key: Key, value: Value, options?: KvPutOptions) {
233
343
  const kv = yield* tag;
234
- const keyEncoded = yield* encodeKey(key);
235
- const valueEncoded = yield* encodeValue(value);
236
- yield* tryKvPromise(definition.binding, "put", () =>
237
- kv.put(keyEncoded, valueEncoded, options),
238
- );
344
+ yield* kv.put(key, value, options);
239
345
  });
240
346
 
241
347
  const get = Effect.fnUntraced(function* (key: Key) {
242
348
  const kv = yield* tag;
243
- const keyEncoded = yield* encodeKey(key);
244
- const valueEncoded = yield* tryKvPromise(definition.binding, "get", () => kv.get(keyEncoded));
245
-
246
- if (valueEncoded === null) {
247
- return Option.none();
248
- }
249
-
250
- return yield* decodeValue(valueEncoded).pipe(Effect.map(Option.some));
349
+ return yield* kv.get(key);
251
350
  });
252
351
 
253
352
  const getWithMetadata = Effect.fnUntraced(function* <Metadata>(
@@ -255,70 +354,24 @@ export const Service =
255
354
  metadataSchema: S.Codec<Metadata, unknown>,
256
355
  ) {
257
356
  const kv = yield* tag;
258
- const keyEncoded = yield* encodeKey(key);
259
- const result = yield* tryKvPromise(definition.binding, "getWithMetadata", () =>
260
- kv.getWithMetadata<Metadata>(keyEncoded),
261
- );
262
-
263
- if (result.value === null) {
264
- return Option.none();
265
- }
266
-
267
- const value = yield* decodeValue(result.value);
268
- const metadata =
269
- result.metadata === null
270
- ? Option.none<Metadata>()
271
- : Option.some(yield* S.decodeUnknownEffect(metadataSchema)(result.metadata));
272
-
273
- return Option.some({
274
- value,
275
- metadata,
276
- cacheStatus: maybeString(result.cacheStatus),
277
- });
357
+ return yield* kv.getWithMetadata(key, metadataSchema);
278
358
  });
279
359
 
280
360
  const list = Effect.fnUntraced(function* <Metadata = unknown>(
281
361
  options?: KvListOptions<Metadata>,
282
362
  ) {
283
363
  const kv = yield* tag;
284
- const { metadataSchema, ...kvOptions } = options ?? {};
285
- const result = yield* tryKvPromise(definition.binding, "list", () =>
286
- kv.list<Metadata>(kvOptions),
287
- );
288
- const keys: Array<KvListKey<Key, Metadata>> = [];
289
-
290
- for (const key of result.keys) {
291
- const decodedName = yield* decodeKey(key.name);
292
- const decodedMetadata =
293
- key.metadata === undefined
294
- ? Option.none<Metadata>()
295
- : metadataSchema === undefined
296
- ? Option.some(key.metadata as Metadata)
297
- : Option.some(yield* S.decodeUnknownEffect(metadataSchema)(key.metadata));
298
-
299
- keys.push({
300
- name: decodedName,
301
- expiration: maybeNumber(key.expiration),
302
- metadata: decodedMetadata,
303
- });
304
- }
305
-
306
- return {
307
- keys,
308
- listComplete: result.list_complete,
309
- cursor: maybeString("cursor" in result ? result.cursor : undefined),
310
- cacheStatus: maybeString(result.cacheStatus),
311
- };
364
+ return yield* kv.list(options);
312
365
  });
313
366
 
314
367
  const remove = Effect.fnUntraced(function* (key: Key) {
315
368
  const kv = yield* tag;
316
- const keyEncoded = yield* encodeKey(key);
317
- yield* tryKvPromise(definition.binding, "delete", () => kv.delete(keyEncoded));
369
+ yield* kv.remove(key);
318
370
  });
319
371
 
320
372
  const unsafeRaw = Effect.fnUntraced(function* () {
321
- return yield* tag;
373
+ const kv = yield* tag;
374
+ return yield* kv.unsafeRaw;
322
375
  });
323
376
 
324
377
  return Object.assign(tag, {
@@ -19,6 +19,19 @@ export interface QueueBindingDefinition<Message extends RpcDefinition.ServiceFre
19
19
  readonly message: Message;
20
20
  }
21
21
 
22
+ export interface QueueBindingClient<Message extends RpcDefinition.ServiceFreeSchema> {
23
+ readonly send: (
24
+ message: S.Schema.Type<Message>,
25
+ options?: QueueSendOptions,
26
+ ) => Effect.Effect<void, QueueOperationError | S.SchemaError>;
27
+ readonly sendBatch: (
28
+ messages: Iterable<MessageSendRequest<S.Schema.Type<Message>>>,
29
+ options?: QueueSendBatchOptions,
30
+ ) => Effect.Effect<void, QueueOperationError | S.SchemaError>;
31
+ readonly metrics: () => Effect.Effect<QueueMetrics, QueueOperationError>;
32
+ readonly unsafeRaw: Effect.Effect<globalThis.Queue<S.Codec.Encoded<Message>>>;
33
+ }
34
+
22
35
  declare const QueueServiceTypeId: unique symbol;
23
36
 
24
37
  /** Nominal service marker for Queue services created with {@link make}. */
@@ -81,19 +94,45 @@ export const Service =
81
94
  type Body = S.Schema.Type<Message>;
82
95
  type EncodedBody = S.Codec.Encoded<Message>;
83
96
 
97
+ const encodeMessage = S.encodeEffect(definition.message);
98
+
99
+ const makeClient = (queue: globalThis.Queue<EncodedBody>): QueueBindingClient<Message> => ({
100
+ send: Effect.fnUntraced(function* (message: Body, options?: QueueSendOptions) {
101
+ const encoded = yield* encodeMessage(message);
102
+
103
+ yield* tryQueuePromise(definition.binding, "send", () => queue.send(encoded, options));
104
+ }),
105
+ sendBatch: Effect.fnUntraced(function* (
106
+ messages: Iterable<MessageSendRequest<Body>>,
107
+ options?: QueueSendBatchOptions,
108
+ ) {
109
+ const encodedMessages: Array<MessageSendRequest<EncodedBody>> = [];
110
+
111
+ for (const message of messages) {
112
+ encodedMessages.push({
113
+ ...message,
114
+ body: yield* encodeMessage(message.body),
115
+ });
116
+ }
117
+
118
+ yield* tryQueuePromise(definition.binding, "sendBatch", () =>
119
+ queue.sendBatch(encodedMessages, options),
120
+ );
121
+ }),
122
+ metrics: () => tryQueuePromise(definition.binding, "metrics", () => queue.metrics()),
123
+ unsafeRaw: Effect.succeed(queue),
124
+ });
125
+
84
126
  const tag = Binding.Service<Self>()(
85
127
  id,
86
128
  definition.binding,
87
129
  (value): value is globalThis.Queue<EncodedBody> => isQueue<EncodedBody>(value),
130
+ makeClient,
88
131
  );
89
132
 
90
- const encodeMessage = S.encodeEffect(definition.message);
91
-
92
133
  const send = Effect.fnUntraced(function* (message: Body, options?: QueueSendOptions) {
93
134
  const queue = yield* tag;
94
- const encoded = yield* encodeMessage(message);
95
-
96
- return yield* tryQueuePromise(definition.binding, "send", () => queue.send(encoded, options));
135
+ yield* queue.send(message, options);
97
136
  });
98
137
 
99
138
  const sendBatch = Effect.fnUntraced(function* (
@@ -101,24 +140,17 @@ export const Service =
101
140
  options?: QueueSendBatchOptions,
102
141
  ) {
103
142
  const queue = yield* tag;
104
- const encodedMessages: Array<MessageSendRequest<EncodedBody>> = [];
105
-
106
- for (const message of messages) {
107
- encodedMessages.push({
108
- ...message,
109
- body: yield* encodeMessage(message.body),
110
- });
111
- }
112
-
113
- return yield* tryQueuePromise(definition.binding, "sendBatch", () =>
114
- queue.sendBatch(encodedMessages, options),
115
- );
143
+ yield* queue.sendBatch(messages, options);
116
144
  });
117
145
 
118
146
  const metrics = Effect.fnUntraced(function* () {
119
147
  const queue = yield* tag;
148
+ return yield* queue.metrics();
149
+ });
120
150
 
121
- return yield* tryQueuePromise(definition.binding, "metrics", () => queue.metrics());
151
+ const unsafeRaw = Effect.fnUntraced(function* () {
152
+ const queue = yield* tag;
153
+ return yield* queue.unsafeRaw;
122
154
  });
123
155
 
124
156
  return Object.assign(tag, {
@@ -127,5 +159,6 @@ export const Service =
127
159
  send,
128
160
  sendBatch,
129
161
  metrics,
162
+ unsafeRaw,
130
163
  });
131
164
  };
@@ -1,4 +1,4 @@
1
- import { Data, Effect } from "effect";
1
+ import { Data, Effect, type Scope } from "effect";
2
2
 
3
3
  import * as Binding from "./Binding";
4
4
  import * as CloudflareRpc from "./Rpc";
@@ -75,25 +75,47 @@ type ServiceMethodSuccess<Api, Method extends keyof Api> = RpcInvocation.AsyncMe
75
75
  Method
76
76
  >;
77
77
 
78
- type ServiceCall<Self, Api> = <Method extends ServiceMethodKey<Api>>(
78
+ type ServiceCall<R, Api> = <Method extends ServiceMethodKey<Api>>(
79
79
  method: Method,
80
80
  ...args: ServiceMethodArgs<Api, Method>
81
- ) => Effect.Effect<ServiceMethodSuccess<Api, Method>, ServiceBindingRpcError, Self>;
81
+ ) => Effect.Effect<ServiceMethodSuccess<Api, Method>, ServiceBindingRpcError, R>;
82
82
 
83
- type DefinitionDirectMethods<Self, Definition extends WorkerDefinition.Definition.Any> = {
83
+ type DefinitionDirectMethods<R, Definition extends WorkerDefinition.Definition.Any> = {
84
84
  readonly [Method in RpcDefinition.Definition.MethodNames<Definition>]: (
85
85
  ...args: RpcDefinition.Method.Args<Definition["methods"][Method]>
86
86
  ) => Effect.Effect<
87
87
  RpcDefinition.Method.Success<Definition["methods"][Method]>,
88
88
  ServiceBindingRpcError,
89
- Self
89
+ R
90
90
  >;
91
91
  };
92
92
 
93
- type DirectMethods<Self, Definition> = Definition extends WorkerDefinition.Definition.Any
94
- ? DefinitionDirectMethods<Self, Definition>
93
+ type DirectMethods<R, Definition> = Definition extends WorkerDefinition.Definition.Any
94
+ ? DefinitionDirectMethods<R, Definition>
95
95
  : {};
96
96
 
97
+ export type ServiceBindingEffectClient<
98
+ Api extends object,
99
+ Definition extends WorkerDefinition.Definition.Any | undefined = undefined,
100
+ > = DirectMethods<never, Definition> & {
101
+ readonly fetch: (
102
+ input: RequestInfo | URL,
103
+ init?: RequestInit,
104
+ ) => Effect.Effect<globalThis.Response, ServiceBindingFetchError>;
105
+ readonly rpc: <Method extends ServiceMethodKey<Api>>(
106
+ method: Method,
107
+ ...args: ServiceMethodArgs<Api, Method>
108
+ ) => Effect.Effect<ServiceMethodSuccess<Api, Method>, ServiceBindingRpcError>;
109
+ readonly call: <Method extends ServiceMethodKey<Api>>(
110
+ method: Method,
111
+ ...args: ServiceMethodArgs<Api, Method>
112
+ ) => Effect.Effect<ServiceMethodSuccess<Api, Method>, ServiceBindingRpcError>;
113
+ readonly scopedCall: <Method extends ServiceMethodKey<Api>>(
114
+ method: Method,
115
+ ...args: ServiceMethodArgs<Api, Method>
116
+ ) => Effect.Effect<Awaited<ServiceMethodSuccess<Api, Method>>, unknown, Scope.Scope>;
117
+ };
118
+
97
119
  /**
98
120
  * Creates a typed Effect service for a Worker service binding.
99
121
  *
@@ -131,21 +153,125 @@ export const Service =
131
153
  ) => {
132
154
  type ServiceApi = ApiOrDefinition<Api, Definition>;
133
155
 
156
+ const makeClient = (
157
+ service: ServiceBindingClient<ServiceApi>,
158
+ ): ServiceBindingEffectClient<ServiceApi, Definition> => {
159
+ const fetch = (input: RequestInfo | URL, init?: RequestInit) =>
160
+ Effect.tryPromise({
161
+ try: () => service.fetch(input, init),
162
+ catch: (cause) => new ServiceBindingFetchError({ binding: definition.binding, cause }),
163
+ });
164
+
165
+ const rpc = <Method extends ServiceMethodKey<ServiceApi>>(
166
+ method: Method,
167
+ ...args: ServiceMethodArgs<ServiceApi, Method>
168
+ ) =>
169
+ Effect.gen(function* () {
170
+ const methodName = String(method);
171
+ const encodedArgs =
172
+ definition.definition === undefined
173
+ ? args
174
+ : yield* RpcDefinition.encodeArgs(
175
+ definition.definition,
176
+ methodName as RpcDefinition.Definition.MethodNames<NonNullable<Definition>>,
177
+ args as never,
178
+ ).pipe(
179
+ Effect.mapError(
180
+ (cause) =>
181
+ new ServiceBindingRpcError({
182
+ binding: definition.binding,
183
+ method: methodName,
184
+ cause,
185
+ }),
186
+ ),
187
+ );
188
+
189
+ return yield* RpcInvocation.invokeRpcMethod(
190
+ service,
191
+ method,
192
+ encodedArgs as ServiceMethodArgs<ServiceApi, Method>,
193
+ (cause) =>
194
+ new ServiceBindingRpcError({
195
+ binding: definition.binding,
196
+ method: methodName,
197
+ cause,
198
+ }),
199
+ );
200
+ });
201
+
202
+ const call = <Method extends ServiceMethodKey<ServiceApi>>(
203
+ method: Method,
204
+ ...args: ServiceMethodArgs<ServiceApi, Method>
205
+ ) =>
206
+ Effect.gen(function* () {
207
+ const methodName = String(method);
208
+ const value = yield* CloudflareRpc.resolve(yield* rpc(method, ...args)).pipe(
209
+ Effect.mapError(
210
+ (cause) =>
211
+ new ServiceBindingRpcError({
212
+ binding: definition.binding,
213
+ method: methodName,
214
+ cause,
215
+ }),
216
+ ),
217
+ );
218
+
219
+ if (definition.definition === undefined) {
220
+ return value as ServiceMethodSuccess<ServiceApi, Method>;
221
+ }
222
+
223
+ const decoded = yield* RpcDefinition.decodeSuccess(
224
+ definition.definition,
225
+ methodName as RpcDefinition.Definition.MethodNames<NonNullable<Definition>>,
226
+ value,
227
+ ).pipe(
228
+ Effect.mapError(
229
+ (cause) =>
230
+ new ServiceBindingRpcError({
231
+ binding: definition.binding,
232
+ method: methodName,
233
+ cause,
234
+ }),
235
+ ),
236
+ );
237
+
238
+ return decoded as ServiceMethodSuccess<ServiceApi, Method>;
239
+ });
240
+
241
+ const scopedCall = <Method extends ServiceMethodKey<ServiceApi>>(
242
+ method: Method,
243
+ ...args: ServiceMethodArgs<ServiceApi, Method>
244
+ ) =>
245
+ Effect.gen(function* () {
246
+ const result = yield* rpc(method, ...args);
247
+ return yield* CloudflareRpc.scoped(result);
248
+ });
249
+
250
+ const directMethods = makeDirectMethods<never, ServiceApi, Definition>(
251
+ definition.definition,
252
+ call,
253
+ );
254
+
255
+ return Object.assign(directMethods, {
256
+ fetch,
257
+ rpc,
258
+ call,
259
+ scopedCall,
260
+ }) as ServiceBindingEffectClient<ServiceApi, Definition>;
261
+ };
262
+
134
263
  const tag = Binding.Service<Self>()(
135
264
  id,
136
265
  definition.binding,
137
266
  (value): value is ServiceBindingClient<ServiceApi> =>
138
267
  typeof value === "object" && value !== null && "fetch" in value,
268
+ makeClient,
139
269
  );
140
270
 
141
271
  const fetch = (input: RequestInfo | URL, init?: RequestInit) =>
142
272
  Effect.gen(function* () {
143
273
  const service = yield* tag;
144
-
145
- return yield* Effect.tryPromise({
146
- try: () => service.fetch(input, init),
147
- catch: (cause) => new ServiceBindingFetchError({ binding: definition.binding, cause }),
148
- });
274
+ return yield* service.fetch(input, init);
149
275
  });
150
276
 
151
277
  const rpc = <Method extends ServiceMethodKey<ServiceApi>>(
@@ -154,36 +280,7 @@ export const Service =
154
280
  ) =>
155
281
  Effect.gen(function* () {
156
282
  const service = yield* tag;
157
- const methodName = String(method);
158
- const encodedArgs =
159
- definition.definition === undefined
160
- ? args
161
- : yield* RpcDefinition.encodeArgs(
162
- definition.definition,
163
- methodName as RpcDefinition.Definition.MethodNames<NonNullable<Definition>>,
164
- args as never,
165
- ).pipe(
166
- Effect.mapError(
167
- (cause) =>
168
- new ServiceBindingRpcError({
169
- binding: definition.binding,
170
- method: methodName,
171
- cause,
172
- }),
173
- ),
174
- );
175
-
176
- return yield* RpcInvocation.invokeRpcMethod(
177
- service,
178
- method,
179
- encodedArgs as ServiceMethodArgs<ServiceApi, Method>,
180
- (cause) =>
181
- new ServiceBindingRpcError({
182
- binding: definition.binding,
183
- method: methodName,
184
- cause,
185
- }),
186
- );
283
+ return yield* service.rpc(method, ...args);
187
284
  });
188
285
 
189
286
  const call = <Method extends ServiceMethodKey<ServiceApi>>(
@@ -191,38 +288,8 @@ export const Service =
191
288
  ...args: ServiceMethodArgs<ServiceApi, Method>
192
289
  ) =>
193
290
  Effect.gen(function* () {
194
- const methodName = String(method);
195
- const value = yield* CloudflareRpc.resolve(yield* rpc(method, ...args)).pipe(
196
- Effect.mapError(
197
- (cause) =>
198
- new ServiceBindingRpcError({
199
- binding: definition.binding,
200
- method: methodName,
201
- cause,
202
- }),
203
- ),
204
- );
205
-
206
- if (definition.definition === undefined) {
207
- return value as ServiceMethodSuccess<ServiceApi, Method>;
208
- }
209
-
210
- const decoded = yield* RpcDefinition.decodeSuccess(
211
- definition.definition,
212
- methodName as RpcDefinition.Definition.MethodNames<NonNullable<Definition>>,
213
- value,
214
- ).pipe(
215
- Effect.mapError(
216
- (cause) =>
217
- new ServiceBindingRpcError({
218
- binding: definition.binding,
219
- method: methodName,
220
- cause,
221
- }),
222
- ),
223
- );
224
-
225
- return decoded as ServiceMethodSuccess<ServiceApi, Method>;
291
+ const service = yield* tag;
292
+ return yield* service.call(method, ...args);
226
293
  });
227
294
 
228
295
  const scopedCall = <Method extends ServiceMethodKey<ServiceApi>>(
@@ -230,8 +297,8 @@ export const Service =
230
297
  ...args: ServiceMethodArgs<ServiceApi, Method>
231
298
  ) =>
232
299
  Effect.gen(function* () {
233
- const result = yield* rpc(method, ...args);
234
- return yield* CloudflareRpc.scoped(result);
300
+ const service = yield* tag;
301
+ return yield* service.scopedCall(method, ...args);
235
302
  });
236
303
 
237
304
  const directMethods = makeDirectMethods<Self, ServiceApi, Definition>(
@@ -257,14 +324,10 @@ export const Service =
257
324
  };
258
325
  };
259
326
 
260
- const makeDirectMethods = <
261
- Self,
262
- Api,
263
- Definition extends WorkerDefinition.Definition.Any | undefined,
264
- >(
327
+ const makeDirectMethods = <R, Api, Definition extends WorkerDefinition.Definition.Any | undefined>(
265
328
  rpcDefinition: Definition | undefined,
266
- call: ServiceCall<Self, Api>,
267
- ): DirectMethods<Self, Definition> => {
329
+ call: ServiceCall<R, Api>,
330
+ ): DirectMethods<R, Definition> => {
268
331
  const methods = {} as Record<string, unknown>;
269
332
 
270
333
  if (rpcDefinition !== undefined) {
@@ -274,5 +337,5 @@ const makeDirectMethods = <
274
337
  }
275
338
  }
276
339
 
277
- return methods as DirectMethods<Self, Definition>;
340
+ return methods as DirectMethods<R, Definition>;
278
341
  };
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * as Binding from "./Binding";
2
+ export * as D1 from "./D1";
2
3
  export * as DurableObject from "./DurableObject";
3
4
  export * as DurableObjectAlarm from "./DurableObjectAlarm";
4
5
  export * as DurableObjectDefinition from "./DurableObjectDefinition";