effect-cf 0.8.0 → 0.9.1
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/CHANGELOG.md +12 -0
- package/README.md +19 -0
- package/dist/index.d.mts +21 -4
- package/dist/index.mjs +53 -18
- package/package.json +1 -1
- package/src/DurableObject.ts +14 -0
- package/src/R2.ts +101 -41
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# effect-cf
|
|
2
2
|
|
|
3
|
+
## 0.9.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#27](https://github.com/danieljvdm/effect-cf/pull/27) [`ac2fb0f`](https://github.com/danieljvdm/effect-cf/commit/ac2fb0f9b557c1f73d779ed024c03245c1850b02) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Wrap R2 object body reader methods in Effect so `json`, `text`, `bytes`, `arrayBuffer`, and `blob` report read failures as `R2OperationError`.
|
|
8
|
+
|
|
9
|
+
## 0.9.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [#25](https://github.com/danieljvdm/effect-cf/pull/25) [`c7daaff`](https://github.com/danieljvdm/effect-cf/commit/c7daaff779934c83519ad9689e1f98dc100b5251) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Add a Durable Object `initialize` hook for running Effect setup each time Cloudflare loads a Durable Object instance into memory.
|
|
14
|
+
|
|
3
15
|
## 0.8.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -240,6 +240,25 @@ In definition-backed workflows, the `payload` argument is the typed decoded payl
|
|
|
240
240
|
|
|
241
241
|
## Durable Object WebSockets
|
|
242
242
|
|
|
243
|
+
Use `initialize` for work that should run each time Cloudflare loads a Durable
|
|
244
|
+
Object instance into memory. Yield `state.blockConcurrencyWhile(...)` when
|
|
245
|
+
later events should wait for initialize to finish. If work should happen only once
|
|
246
|
+
for a Durable Object id, store a sentinel in Durable Object storage.
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
export const RoomLive = DurableObject.make(layer, {
|
|
250
|
+
initialize: Effect.gen(function* () {
|
|
251
|
+
const state = yield* DurableObjectState.DurableObjectState;
|
|
252
|
+
yield* state.blockConcurrencyWhile(
|
|
253
|
+
Effect.gen(function* () {
|
|
254
|
+
yield* state.storage.put("loadedAt", Date.now());
|
|
255
|
+
}),
|
|
256
|
+
);
|
|
257
|
+
}),
|
|
258
|
+
fetch,
|
|
259
|
+
});
|
|
260
|
+
```
|
|
261
|
+
|
|
243
262
|
Durable Object application sockets should use the hibernation-compatible state API. Accept sockets with `DurableObjectWebSocket.acceptUpgrade(...)`; do not call `server.accept()` or attach native `message` listeners in application code.
|
|
244
263
|
|
|
245
264
|
```ts
|
package/dist/index.d.mts
CHANGED
|
@@ -376,7 +376,7 @@ declare const method$3: {
|
|
|
376
376
|
<Success extends ServiceFreeSchema$3>(definition: {
|
|
377
377
|
readonly success: Success;
|
|
378
378
|
}): Method$4<readonly [], Success>;
|
|
379
|
-
<const Args extends
|
|
379
|
+
<const Args extends readonly ServiceFreeSchema$3[], Success extends ServiceFreeSchema$3>(definition: {
|
|
380
380
|
readonly args: Args;
|
|
381
381
|
readonly success: Success;
|
|
382
382
|
}): Method$4<Args, Success>;
|
|
@@ -1288,6 +1288,15 @@ type RpcHandlers<ROut, Api> = { readonly [Key in keyof Api as Key extends keyof
|
|
|
1288
1288
|
* Options for creating a Durable Object class backed by Effect handlers.
|
|
1289
1289
|
*/
|
|
1290
1290
|
interface DurableObjectOptions<ROut, Rpc extends DurableObjectRpc<ROut>> {
|
|
1291
|
+
/**
|
|
1292
|
+
* Effect run when Cloudflare loads this Durable Object instance into memory.
|
|
1293
|
+
*
|
|
1294
|
+
* Use `DurableObjectState.blockConcurrencyWhile` inside this hook when
|
|
1295
|
+
* incoming events should wait for setup to finish. Cloudflare may construct
|
|
1296
|
+
* the same Durable Object id again after eviction or restart; use Durable
|
|
1297
|
+
* Object storage if work must happen only once per id.
|
|
1298
|
+
*/
|
|
1299
|
+
readonly initialize?: Effect.Effect<void, unknown, HandlerContext<ROut>>;
|
|
1291
1300
|
/** Optional RPC methods exposed as Durable Object instance methods. */
|
|
1292
1301
|
readonly rpc?: Rpc;
|
|
1293
1302
|
/** Optional fetch handler for HTTP/WebSocket requests. */
|
|
@@ -1912,7 +1921,7 @@ declare const Tag$4: <Self>() => <Id extends string, Key, Value, EncodedValue>(i
|
|
|
1912
1921
|
readonly value: Schema.Codec<Value, EncodedValue>;
|
|
1913
1922
|
}) => TagClass$3<Self, Id, Key, Value, EncodedValue>;
|
|
1914
1923
|
declare namespace R2_d_exports {
|
|
1915
|
-
export { LayerOptions$2 as LayerOptions, R2Client, R2Definition, R2GetOptions, R2ListOptions, R2MultipartOptions, R2MultipartUploadClient, R2OperationError, R2PutOptions, R2PutValue, R2Service, R2UploadPartOptions, R2UploadPartValue, Tag$3 as Tag, TagClass$2 as TagClass, isR2Bucket, layer$1 as layer, make$2 as make, makeClient$1 as makeClient };
|
|
1924
|
+
export { LayerOptions$2 as LayerOptions, R2Client, R2Definition, R2GetOptions, R2ListOptions, R2MultipartOptions, R2MultipartUploadClient, R2ObjectBodyClient, R2OperationError, R2PutOptions, R2PutValue, R2Service, R2UploadPartOptions, R2UploadPartValue, Tag$3 as Tag, TagClass$2 as TagClass, isR2Bucket, layer$1 as layer, make$2 as make, makeClient$1 as makeClient };
|
|
1916
1925
|
}
|
|
1917
1926
|
declare const R2OperationError_base: new <A extends Record<string, any> = {}>(args: _$effect_Types0.VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => _$effect_Cause0.YieldableError & {
|
|
1918
1927
|
readonly _tag: "R2OperationError";
|
|
@@ -1935,6 +1944,14 @@ type R2MultipartOptions = globalThis.R2MultipartOptions;
|
|
|
1935
1944
|
type R2UploadPartOptions = globalThis.R2UploadPartOptions;
|
|
1936
1945
|
type R2PutValue = ReadableStream | ArrayBuffer | ArrayBufferView | string | null | Blob;
|
|
1937
1946
|
type R2UploadPartValue = ReadableStream | ArrayBuffer | ArrayBufferView | string | Blob;
|
|
1947
|
+
interface R2ObjectBodyClient extends Omit<globalThis.R2ObjectBody, "arrayBuffer" | "blob" | "bytes" | "json" | "text"> {
|
|
1948
|
+
readonly raw: globalThis.R2ObjectBody;
|
|
1949
|
+
readonly arrayBuffer: Effect.Effect<ArrayBuffer, R2OperationError>;
|
|
1950
|
+
readonly bytes: Effect.Effect<Uint8Array, R2OperationError>;
|
|
1951
|
+
readonly text: Effect.Effect<string, R2OperationError>;
|
|
1952
|
+
readonly json: <T = unknown>() => Effect.Effect<T, R2OperationError>;
|
|
1953
|
+
readonly blob: Effect.Effect<Blob, R2OperationError>;
|
|
1954
|
+
}
|
|
1938
1955
|
interface R2MultipartUploadClient {
|
|
1939
1956
|
readonly raw: globalThis.R2MultipartUpload;
|
|
1940
1957
|
readonly key: string;
|
|
@@ -1948,8 +1965,8 @@ interface R2Client {
|
|
|
1948
1965
|
readonly get: {
|
|
1949
1966
|
(key: string, options: R2GetOptions & {
|
|
1950
1967
|
readonly onlyIf: globalThis.R2Conditional | Headers;
|
|
1951
|
-
}): Effect.Effect<Option.Option<
|
|
1952
|
-
(key: string, options?: R2GetOptions): Effect.Effect<Option.Option<
|
|
1968
|
+
}): Effect.Effect<Option.Option<R2ObjectBodyClient | globalThis.R2Object>, R2OperationError>;
|
|
1969
|
+
(key: string, options?: R2GetOptions): Effect.Effect<Option.Option<R2ObjectBodyClient>, R2OperationError>;
|
|
1953
1970
|
};
|
|
1954
1971
|
readonly put: {
|
|
1955
1972
|
(key: string, value: R2PutValue, options: R2PutOptions & {
|
package/dist/index.mjs
CHANGED
|
@@ -1253,6 +1253,8 @@ const make$4 = (layer, options = {}) => {
|
|
|
1253
1253
|
super(state, env);
|
|
1254
1254
|
const runtimeLayer = provideEntrypointServices(layer, Layer.mergeAll(Layer.succeed(DurableObjectState, fromDurableObjectState(state)), Layer.succeed(WorkerEnvironment, env)));
|
|
1255
1255
|
this.runtime = ManagedRuntime.make(runtimeLayer);
|
|
1256
|
+
const initialize = options.initialize;
|
|
1257
|
+
if (initialize !== void 0) state.waitUntil(this[RunSymbol](initialize));
|
|
1256
1258
|
}
|
|
1257
1259
|
[RunSymbol](effect) {
|
|
1258
1260
|
return this.runtime.runPromise(Effect.scoped(effect));
|
|
@@ -1976,6 +1978,36 @@ const tryR2Sync = (binding, operation, evaluate) => Effect.try({
|
|
|
1976
1978
|
catch: (cause) => r2Error(binding, operation, cause)
|
|
1977
1979
|
});
|
|
1978
1980
|
const maybe = (value) => value === null ? Option.none() : Option.some(value);
|
|
1981
|
+
const isR2ObjectBody = (value) => "body" in value && typeof value.arrayBuffer === "function" && typeof value.bytes === "function" && typeof value.text === "function" && typeof value.json === "function" && typeof value.blob === "function";
|
|
1982
|
+
const wrapObjectBody = (binding, object) => ({
|
|
1983
|
+
key: object.key,
|
|
1984
|
+
version: object.version,
|
|
1985
|
+
size: object.size,
|
|
1986
|
+
etag: object.etag,
|
|
1987
|
+
httpEtag: object.httpEtag,
|
|
1988
|
+
checksums: object.checksums,
|
|
1989
|
+
uploaded: object.uploaded,
|
|
1990
|
+
httpMetadata: object.httpMetadata,
|
|
1991
|
+
customMetadata: object.customMetadata,
|
|
1992
|
+
range: object.range,
|
|
1993
|
+
storageClass: object.storageClass,
|
|
1994
|
+
ssecKeyMd5: object.ssecKeyMd5,
|
|
1995
|
+
writeHttpMetadata: (headers) => object.writeHttpMetadata(headers),
|
|
1996
|
+
raw: object,
|
|
1997
|
+
body: object.body,
|
|
1998
|
+
get bodyUsed() {
|
|
1999
|
+
return object.bodyUsed;
|
|
2000
|
+
},
|
|
2001
|
+
arrayBuffer: tryR2Promise(binding, "arrayBuffer", () => object.arrayBuffer()),
|
|
2002
|
+
bytes: tryR2Promise(binding, "bytes", () => object.bytes()),
|
|
2003
|
+
text: tryR2Promise(binding, "text", () => object.text()),
|
|
2004
|
+
json: () => tryR2Promise(binding, "json", () => object.json()),
|
|
2005
|
+
blob: tryR2Promise(binding, "blob", () => object.blob())
|
|
2006
|
+
});
|
|
2007
|
+
const wrapGetResult = (binding, object) => {
|
|
2008
|
+
if (object === null || !isR2ObjectBody(object)) return object;
|
|
2009
|
+
return wrapObjectBody(binding, object);
|
|
2010
|
+
};
|
|
1979
2011
|
const isR2Bucket = (value) => {
|
|
1980
2012
|
if (typeof value !== "object" || value === null) return false;
|
|
1981
2013
|
const resource = value;
|
|
@@ -1990,24 +2022,27 @@ const makeClient$1 = (definition) => {
|
|
|
1990
2022
|
abort: tryR2Promise(definition.binding, "abortMultipartUpload", () => upload.abort()),
|
|
1991
2023
|
complete: (uploadedParts) => tryR2Promise(definition.binding, "completeMultipartUpload", () => upload.complete([...uploadedParts]))
|
|
1992
2024
|
});
|
|
1993
|
-
return (bucket) =>
|
|
1994
|
-
definition,
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2025
|
+
return (bucket) => {
|
|
2026
|
+
const get = ((key, options) => tryR2Promise(definition.binding, "get", () => bucket.get(key, options)).pipe(Effect.map((object) => maybe(wrapGetResult(definition.binding, object)))));
|
|
2027
|
+
return {
|
|
2028
|
+
definition,
|
|
2029
|
+
head: (key) => tryR2Promise(definition.binding, "head", () => bucket.head(key)).pipe(Effect.map(maybe)),
|
|
2030
|
+
get,
|
|
2031
|
+
put: ((key, value, options) => tryR2Promise(definition.binding, "put", () => bucket.put(key, value, options)).pipe(Effect.map((object) => {
|
|
2032
|
+
if (object === null) return Option.none();
|
|
2033
|
+
if (options !== void 0 && "onlyIf" in options) return Option.some(object);
|
|
2034
|
+
return object;
|
|
2035
|
+
}))),
|
|
2036
|
+
createMultipartUpload: (key, options) => tryR2Promise(definition.binding, "createMultipartUpload", () => bucket.createMultipartUpload(key, options)).pipe(Effect.map(wrapUpload)),
|
|
2037
|
+
resumeMultipartUpload: (key, uploadId) => tryR2Sync(definition.binding, "resumeMultipartUpload", () => wrapUpload(bucket.resumeMultipartUpload(key, uploadId))),
|
|
2038
|
+
delete: (keys) => {
|
|
2039
|
+
const nativeKeys = typeof keys === "string" ? keys : [...keys];
|
|
2040
|
+
return tryR2Promise(definition.binding, "delete", () => bucket.delete(nativeKeys));
|
|
2041
|
+
},
|
|
2042
|
+
list: (options) => tryR2Promise(definition.binding, "list", () => bucket.list(options)),
|
|
2043
|
+
unsafeRaw: Effect.succeed(bucket)
|
|
2044
|
+
};
|
|
2045
|
+
};
|
|
2011
2046
|
};
|
|
2012
2047
|
const layer$1 = (tag, definition) => layer$8(tag, definition.binding, isR2Bucket, makeClient$1(definition));
|
|
2013
2048
|
const make$2 = (id) => Tag$2()(id);
|
package/package.json
CHANGED
package/src/DurableObject.ts
CHANGED
|
@@ -73,6 +73,15 @@ export type RpcHandlers<ROut, Api> = {
|
|
|
73
73
|
* Options for creating a Durable Object class backed by Effect handlers.
|
|
74
74
|
*/
|
|
75
75
|
export interface DurableObjectOptions<ROut, Rpc extends DurableObjectRpc<ROut>> {
|
|
76
|
+
/**
|
|
77
|
+
* Effect run when Cloudflare loads this Durable Object instance into memory.
|
|
78
|
+
*
|
|
79
|
+
* Use `DurableObjectState.blockConcurrencyWhile` inside this hook when
|
|
80
|
+
* incoming events should wait for setup to finish. Cloudflare may construct
|
|
81
|
+
* the same Durable Object id again after eviction or restart; use Durable
|
|
82
|
+
* Object storage if work must happen only once per id.
|
|
83
|
+
*/
|
|
84
|
+
readonly initialize?: Effect.Effect<void, unknown, HandlerContext<ROut>>;
|
|
76
85
|
/** Optional RPC methods exposed as Durable Object instance methods. */
|
|
77
86
|
readonly rpc?: Rpc;
|
|
78
87
|
/** Optional fetch handler for HTTP/WebSocket requests. */
|
|
@@ -137,6 +146,11 @@ export const make = <
|
|
|
137
146
|
const runtimeLayer = Entrypoint.provideEntrypointServices(layer, services);
|
|
138
147
|
|
|
139
148
|
this.runtime = ManagedRuntime.make(runtimeLayer);
|
|
149
|
+
|
|
150
|
+
const initialize = options.initialize;
|
|
151
|
+
if (initialize !== undefined) {
|
|
152
|
+
state.waitUntil(this[RunSymbol](initialize));
|
|
153
|
+
}
|
|
140
154
|
}
|
|
141
155
|
|
|
142
156
|
[RunSymbol]<A, E>(effect: Effect.Effect<A, E, HandlerContext<ROut>>): Promise<A> {
|
package/src/R2.ts
CHANGED
|
@@ -24,6 +24,18 @@ export type R2UploadPartOptions = globalThis.R2UploadPartOptions;
|
|
|
24
24
|
export type R2PutValue = ReadableStream | ArrayBuffer | ArrayBufferView | string | null | Blob;
|
|
25
25
|
export type R2UploadPartValue = ReadableStream | ArrayBuffer | ArrayBufferView | string | Blob;
|
|
26
26
|
|
|
27
|
+
export interface R2ObjectBodyClient extends Omit<
|
|
28
|
+
globalThis.R2ObjectBody,
|
|
29
|
+
"arrayBuffer" | "blob" | "bytes" | "json" | "text"
|
|
30
|
+
> {
|
|
31
|
+
readonly raw: globalThis.R2ObjectBody;
|
|
32
|
+
readonly arrayBuffer: Effect.Effect<ArrayBuffer, R2OperationError>;
|
|
33
|
+
readonly bytes: Effect.Effect<Uint8Array, R2OperationError>;
|
|
34
|
+
readonly text: Effect.Effect<string, R2OperationError>;
|
|
35
|
+
readonly json: <T = unknown>() => Effect.Effect<T, R2OperationError>;
|
|
36
|
+
readonly blob: Effect.Effect<Blob, R2OperationError>;
|
|
37
|
+
}
|
|
38
|
+
|
|
27
39
|
export interface R2MultipartUploadClient {
|
|
28
40
|
readonly raw: globalThis.R2MultipartUpload;
|
|
29
41
|
readonly key: string;
|
|
@@ -47,14 +59,11 @@ export interface R2Client {
|
|
|
47
59
|
(
|
|
48
60
|
key: string,
|
|
49
61
|
options: R2GetOptions & { readonly onlyIf: globalThis.R2Conditional | Headers },
|
|
50
|
-
): Effect.Effect<
|
|
51
|
-
Option.Option<globalThis.R2ObjectBody | globalThis.R2Object>,
|
|
52
|
-
R2OperationError
|
|
53
|
-
>;
|
|
62
|
+
): Effect.Effect<Option.Option<R2ObjectBodyClient | globalThis.R2Object>, R2OperationError>;
|
|
54
63
|
(
|
|
55
64
|
key: string,
|
|
56
65
|
options?: R2GetOptions,
|
|
57
|
-
): Effect.Effect<Option.Option<
|
|
66
|
+
): Effect.Effect<Option.Option<R2ObjectBodyClient>, R2OperationError>;
|
|
58
67
|
};
|
|
59
68
|
readonly put: {
|
|
60
69
|
(
|
|
@@ -136,6 +145,53 @@ const tryR2Sync = <A>(
|
|
|
136
145
|
const maybe = <A>(value: A | null): Option.Option<A> =>
|
|
137
146
|
value === null ? Option.none() : Option.some(value);
|
|
138
147
|
|
|
148
|
+
const isR2ObjectBody = (
|
|
149
|
+
value: globalThis.R2ObjectBody | globalThis.R2Object,
|
|
150
|
+
): value is globalThis.R2ObjectBody =>
|
|
151
|
+
"body" in value &&
|
|
152
|
+
typeof (value as globalThis.R2ObjectBody).arrayBuffer === "function" &&
|
|
153
|
+
typeof (value as globalThis.R2ObjectBody).bytes === "function" &&
|
|
154
|
+
typeof (value as globalThis.R2ObjectBody).text === "function" &&
|
|
155
|
+
typeof (value as globalThis.R2ObjectBody).json === "function" &&
|
|
156
|
+
typeof (value as globalThis.R2ObjectBody).blob === "function";
|
|
157
|
+
|
|
158
|
+
const wrapObjectBody = (binding: string, object: globalThis.R2ObjectBody): R2ObjectBodyClient => ({
|
|
159
|
+
key: object.key,
|
|
160
|
+
version: object.version,
|
|
161
|
+
size: object.size,
|
|
162
|
+
etag: object.etag,
|
|
163
|
+
httpEtag: object.httpEtag,
|
|
164
|
+
checksums: object.checksums,
|
|
165
|
+
uploaded: object.uploaded,
|
|
166
|
+
httpMetadata: object.httpMetadata,
|
|
167
|
+
customMetadata: object.customMetadata,
|
|
168
|
+
range: object.range,
|
|
169
|
+
storageClass: object.storageClass,
|
|
170
|
+
ssecKeyMd5: object.ssecKeyMd5,
|
|
171
|
+
writeHttpMetadata: (headers) => object.writeHttpMetadata(headers),
|
|
172
|
+
raw: object,
|
|
173
|
+
body: object.body,
|
|
174
|
+
get bodyUsed() {
|
|
175
|
+
return object.bodyUsed;
|
|
176
|
+
},
|
|
177
|
+
arrayBuffer: tryR2Promise(binding, "arrayBuffer", () => object.arrayBuffer()),
|
|
178
|
+
bytes: tryR2Promise(binding, "bytes", () => object.bytes()),
|
|
179
|
+
text: tryR2Promise(binding, "text", () => object.text()),
|
|
180
|
+
json: <T = unknown>() => tryR2Promise(binding, "json", () => object.json<T>()),
|
|
181
|
+
blob: tryR2Promise(binding, "blob", () => object.blob()),
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const wrapGetResult = (
|
|
185
|
+
binding: string,
|
|
186
|
+
object: globalThis.R2ObjectBody | globalThis.R2Object | null,
|
|
187
|
+
): R2ObjectBodyClient | globalThis.R2Object | null => {
|
|
188
|
+
if (object === null || !isR2ObjectBody(object)) {
|
|
189
|
+
return object;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return wrapObjectBody(binding, object);
|
|
193
|
+
};
|
|
194
|
+
|
|
139
195
|
export const isR2Bucket = (value: unknown): value is globalThis.R2Bucket => {
|
|
140
196
|
if (typeof value !== "object" || value === null) {
|
|
141
197
|
return false;
|
|
@@ -172,43 +228,47 @@ export const makeClient = (
|
|
|
172
228
|
),
|
|
173
229
|
});
|
|
174
230
|
|
|
175
|
-
return (bucket) =>
|
|
176
|
-
|
|
177
|
-
head: (key) =>
|
|
178
|
-
tryR2Promise(definition.binding, "head", () => bucket.head(key)).pipe(Effect.map(maybe)),
|
|
179
|
-
get: ((key: string, options?: R2GetOptions) =>
|
|
231
|
+
return (bucket) => {
|
|
232
|
+
const get = ((key: string, options?: R2GetOptions) =>
|
|
180
233
|
tryR2Promise(definition.binding, "get", () => bucket.get(key, options)).pipe(
|
|
181
|
-
Effect.map(maybe),
|
|
182
|
-
)) as R2Client["get"]
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
234
|
+
Effect.map((object) => maybe(wrapGetResult(definition.binding, object))),
|
|
235
|
+
)) as R2Client["get"];
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
definition,
|
|
239
|
+
head: (key) =>
|
|
240
|
+
tryR2Promise(definition.binding, "head", () => bucket.head(key)).pipe(Effect.map(maybe)),
|
|
241
|
+
get,
|
|
242
|
+
put: ((key: string, value: R2PutValue, options?: R2PutOptions) =>
|
|
243
|
+
tryR2Promise(definition.binding, "put", () => bucket.put(key, value, options)).pipe(
|
|
244
|
+
Effect.map((object) => {
|
|
245
|
+
if (object === null) {
|
|
246
|
+
return Option.none<globalThis.R2Object>();
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (options !== undefined && "onlyIf" in options) {
|
|
250
|
+
return Option.some(object);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return object;
|
|
254
|
+
}),
|
|
255
|
+
)) as R2Client["put"],
|
|
256
|
+
createMultipartUpload: (key, options) =>
|
|
257
|
+
tryR2Promise(definition.binding, "createMultipartUpload", () =>
|
|
258
|
+
bucket.createMultipartUpload(key, options),
|
|
259
|
+
).pipe(Effect.map(wrapUpload)),
|
|
260
|
+
resumeMultipartUpload: (key, uploadId) =>
|
|
261
|
+
tryR2Sync(definition.binding, "resumeMultipartUpload", () =>
|
|
262
|
+
wrapUpload(bucket.resumeMultipartUpload(key, uploadId)),
|
|
263
|
+
),
|
|
264
|
+
delete: (keys) => {
|
|
265
|
+
const nativeKeys = typeof keys === "string" ? keys : [...keys];
|
|
266
|
+
return tryR2Promise(definition.binding, "delete", () => bucket.delete(nativeKeys));
|
|
267
|
+
},
|
|
268
|
+
list: (options) => tryR2Promise(definition.binding, "list", () => bucket.list(options)),
|
|
269
|
+
unsafeRaw: Effect.succeed(bucket),
|
|
270
|
+
};
|
|
271
|
+
};
|
|
212
272
|
};
|
|
213
273
|
|
|
214
274
|
export const layer = <Self>(tag: Context.Service<Self, R2Client>, definition: R2Definition) =>
|