effect-cf 0.13.1 → 0.15.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/CHANGELOG.md +18 -0
- package/README.md +28 -1
- package/dist/{Hyperdrive-L6ldMlRF.d.mts → Hyperdrive-C0vfrPeG.d.mts} +1 -1
- package/dist/HyperdrivePg.d.mts +1 -1
- package/dist/index.d.mts +551 -311
- package/dist/index.mjs +460 -316
- package/package.json +8 -8
- package/src/AiGateway.ts +284 -0
- package/src/BrowserRendering.ts +286 -0
- package/src/CloudflareOtlp.ts +90 -386
- package/src/DurableObject.ts +3 -2
- package/src/Email.ts +134 -0
- package/src/Environment.ts +1 -1
- package/src/Images.ts +42 -24
- package/src/Kv.ts +6 -2
- package/src/QueueBinding.ts +19 -10
- package/src/R2.ts +47 -33
- package/src/Vectorize.ts +213 -0
- package/src/WorkersAi.ts +239 -0
- package/src/Workflow.ts +2 -0
- package/src/WorkflowBinding.ts +15 -9
- package/src/index.ts +5 -0
package/src/Email.ts
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
EmailAddress as CloudflareEmailAddress,
|
|
3
|
+
EmailAttachment as CloudflareEmailAttachment,
|
|
4
|
+
EmailMessage as CloudflareEmailMessage,
|
|
5
|
+
EmailSendResult as CloudflareEmailSendResult,
|
|
6
|
+
SendEmail as CloudflareSendEmail,
|
|
7
|
+
} from "@cloudflare/workers-types";
|
|
8
|
+
import { Context, Data, Effect, type Layer } from "effect";
|
|
9
|
+
|
|
10
|
+
import * as Binding from "./Binding";
|
|
11
|
+
import type { WorkerEnvironment } from "./Environment";
|
|
12
|
+
|
|
13
|
+
const expectedSendEmailBinding = "Send Email binding with send()";
|
|
14
|
+
|
|
15
|
+
/** Error raised when a Cloudflare Send Email operation fails. */
|
|
16
|
+
export class EmailOperationError extends Data.TaggedError("EmailOperationError")<{
|
|
17
|
+
readonly binding: string;
|
|
18
|
+
readonly operation: string;
|
|
19
|
+
readonly cause: unknown;
|
|
20
|
+
}> {}
|
|
21
|
+
|
|
22
|
+
/** Typed Cloudflare Send Email binding definition. */
|
|
23
|
+
export interface EmailDefinition {
|
|
24
|
+
/** Binding name as configured in `wrangler.jsonc`. */
|
|
25
|
+
readonly binding: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type EmailAddress = CloudflareEmailAddress;
|
|
29
|
+
export type EmailAttachment = CloudflareEmailAttachment;
|
|
30
|
+
export type EmailMessage = CloudflareEmailMessage;
|
|
31
|
+
export type EmailMessageBuilder = Parameters<CloudflareSendEmail["send"]>[0];
|
|
32
|
+
export type EmailSendInput = EmailMessage | EmailMessageBuilder;
|
|
33
|
+
export type EmailSendResult = CloudflareEmailSendResult;
|
|
34
|
+
export type EmailBinding = CloudflareSendEmail;
|
|
35
|
+
|
|
36
|
+
interface EmailRuntimeBinding {
|
|
37
|
+
readonly send: (message: EmailSendInput) => Promise<EmailSendResult>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface EmailClient {
|
|
41
|
+
readonly send: {
|
|
42
|
+
(message: EmailMessage): Effect.Effect<EmailSendResult, EmailOperationError>;
|
|
43
|
+
(builder: EmailMessageBuilder): Effect.Effect<EmailSendResult, EmailOperationError>;
|
|
44
|
+
};
|
|
45
|
+
readonly unsafeRaw: Effect.Effect<EmailBinding>;
|
|
46
|
+
readonly definition: EmailDefinition;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
declare const EmailServiceTypeId: unique symbol;
|
|
50
|
+
|
|
51
|
+
/** Nominal service marker for Send Email services created with {@link make}. */
|
|
52
|
+
export interface EmailService<Id extends string> {
|
|
53
|
+
readonly [EmailServiceTypeId]: {
|
|
54
|
+
readonly id: Id;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type LayerOptions = {
|
|
59
|
+
readonly binding: string;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export interface TagClass<Self, Id extends string> extends Context.ServiceClass<
|
|
63
|
+
Self,
|
|
64
|
+
Id,
|
|
65
|
+
EmailClient
|
|
66
|
+
> {
|
|
67
|
+
readonly id: Id;
|
|
68
|
+
readonly layer: (
|
|
69
|
+
options: LayerOptions,
|
|
70
|
+
) => Layer.Layer<
|
|
71
|
+
Self,
|
|
72
|
+
Binding.BindingNotFoundError | Binding.BindingValidationError,
|
|
73
|
+
WorkerEnvironment
|
|
74
|
+
>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const emailError = (binding: string, operation: string, cause: unknown) =>
|
|
78
|
+
new EmailOperationError({ binding, operation, cause });
|
|
79
|
+
|
|
80
|
+
const tryEmailPromise = <A>(
|
|
81
|
+
binding: string,
|
|
82
|
+
operation: string,
|
|
83
|
+
evaluate: () => Promise<A>,
|
|
84
|
+
): Effect.Effect<A, EmailOperationError> =>
|
|
85
|
+
Effect.tryPromise({
|
|
86
|
+
try: evaluate,
|
|
87
|
+
catch: (cause) => emailError(binding, operation, cause),
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export const isEmailBinding = (value: unknown): value is EmailBinding => {
|
|
91
|
+
if (typeof value !== "object" || value === null) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const resource = value as Record<string, unknown>;
|
|
96
|
+
|
|
97
|
+
return typeof resource.send === "function";
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const makeClient =
|
|
101
|
+
(definition: EmailDefinition) =>
|
|
102
|
+
(email: EmailBinding): EmailClient => {
|
|
103
|
+
const runtime = email as EmailRuntimeBinding;
|
|
104
|
+
const send = ((message: EmailSendInput) =>
|
|
105
|
+
tryEmailPromise(definition.binding, "send", () =>
|
|
106
|
+
runtime.send(message),
|
|
107
|
+
)) as EmailClient["send"];
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
definition,
|
|
111
|
+
send,
|
|
112
|
+
unsafeRaw: Effect.succeed(email),
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export const layer = <Self>(tag: Context.Service<Self, EmailClient>, definition: EmailDefinition) =>
|
|
117
|
+
Binding.layer(tag, definition.binding, isEmailBinding, makeClient(definition), {
|
|
118
|
+
expected: expectedSendEmailBinding,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
export const make = <Id extends string>(id: Id) => Tag<EmailService<Id>>()<Id>(id);
|
|
122
|
+
|
|
123
|
+
export const Tag =
|
|
124
|
+
<Self>() =>
|
|
125
|
+
<Id extends string>(id: Id) => {
|
|
126
|
+
const tag = Context.Service<Self, EmailClient>()(id);
|
|
127
|
+
|
|
128
|
+
const makeLayer = (definition: LayerOptions) => layer(tag, definition);
|
|
129
|
+
|
|
130
|
+
return Object.assign(tag, {
|
|
131
|
+
id,
|
|
132
|
+
layer: makeLayer,
|
|
133
|
+
}) as TagClass<Self, Id>;
|
|
134
|
+
};
|
package/src/Environment.ts
CHANGED
|
@@ -25,7 +25,7 @@ type ScalarConfigKey = Extract<
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Effect `Config` helpers for scalar Cloudflare vars and secrets declared on
|
|
28
|
-
* `Cloudflare.Env
|
|
28
|
+
* `Cloudflare.Env`.
|
|
29
29
|
*
|
|
30
30
|
* Users still author their app config explicitly with Effect `Config`:
|
|
31
31
|
*
|
package/src/Images.ts
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
HostedImagesBinding as CloudflareHostedImagesBinding,
|
|
3
|
+
ImageDrawOptions as CloudflareImageDrawOptions,
|
|
4
|
+
ImageHandle as CloudflareImageHandle,
|
|
5
|
+
ImageInfoResponse as CloudflareImageInfoResponse,
|
|
6
|
+
ImageInputOptions as CloudflareImageInputOptions,
|
|
7
|
+
ImageList as CloudflareImageList,
|
|
8
|
+
ImageListOptions as CloudflareImageListOptions,
|
|
9
|
+
ImageMetadata as CloudflareImageMetadata,
|
|
10
|
+
ImageOutputOptions as CloudflareImageOutputOptions,
|
|
11
|
+
ImageTransform as CloudflareImageTransform,
|
|
12
|
+
ImageTransformationOutputOptions as CloudflareImageTransformationOutputOptions,
|
|
13
|
+
ImageTransformationResult as CloudflareImageTransformationResult,
|
|
14
|
+
ImageTransformer as CloudflareImageTransformer,
|
|
15
|
+
ImageUpdateOptions as CloudflareImageUpdateOptions,
|
|
16
|
+
ImageUploadOptions as CloudflareImageUploadOptions,
|
|
17
|
+
Response as CloudflareResponse,
|
|
18
|
+
} from "@cloudflare/workers-types";
|
|
1
19
|
import { Context, Data, Effect, Option, type Layer } from "effect";
|
|
2
20
|
|
|
3
21
|
import * as Binding from "./Binding";
|
|
@@ -19,23 +37,23 @@ export interface ImagesDefinition {
|
|
|
19
37
|
readonly binding: string;
|
|
20
38
|
}
|
|
21
39
|
|
|
22
|
-
export type ImageInfoResponse =
|
|
23
|
-
export type ImageTransform =
|
|
24
|
-
export type ImageDrawOptions =
|
|
25
|
-
export type ImageInputOptions =
|
|
26
|
-
export type ImageOutputOptions =
|
|
27
|
-
export type ImageTransformationOutputOptions =
|
|
28
|
-
export type ImageTransformationResult =
|
|
29
|
-
export type ImageUploadOptions =
|
|
30
|
-
export type ImageUpdateOptions =
|
|
31
|
-
export type ImageListOptions =
|
|
32
|
-
export type ImageList =
|
|
33
|
-
export type ImageMetadata =
|
|
40
|
+
export type ImageInfoResponse = CloudflareImageInfoResponse;
|
|
41
|
+
export type ImageTransform = CloudflareImageTransform;
|
|
42
|
+
export type ImageDrawOptions = CloudflareImageDrawOptions;
|
|
43
|
+
export type ImageInputOptions = CloudflareImageInputOptions;
|
|
44
|
+
export type ImageOutputOptions = CloudflareImageOutputOptions;
|
|
45
|
+
export type ImageTransformationOutputOptions = CloudflareImageTransformationOutputOptions;
|
|
46
|
+
export type ImageTransformationResult = CloudflareImageTransformationResult;
|
|
47
|
+
export type ImageUploadOptions = CloudflareImageUploadOptions;
|
|
48
|
+
export type ImageUpdateOptions = CloudflareImageUpdateOptions;
|
|
49
|
+
export type ImageListOptions = CloudflareImageListOptions;
|
|
50
|
+
export type ImageList = CloudflareImageList;
|
|
51
|
+
export type ImageMetadata = CloudflareImageMetadata;
|
|
34
52
|
export type ImageInputValue = ReadableStream<Uint8Array> | ArrayBuffer;
|
|
35
53
|
export type ImageUploadValue = ReadableStream<Uint8Array> | ArrayBuffer;
|
|
36
54
|
|
|
37
55
|
export interface DrawStepOptions {
|
|
38
|
-
readonly image: ReadableStream<Uint8Array> |
|
|
56
|
+
readonly image: ReadableStream<Uint8Array> | CloudflareImageTransformer;
|
|
39
57
|
readonly options?: ImageDrawOptions;
|
|
40
58
|
}
|
|
41
59
|
|
|
@@ -58,8 +76,8 @@ export interface ProcessOptions {
|
|
|
58
76
|
}
|
|
59
77
|
|
|
60
78
|
export interface ImagesTransformationResultClient {
|
|
61
|
-
readonly raw:
|
|
62
|
-
readonly response: Effect.Effect<
|
|
79
|
+
readonly raw: CloudflareImageTransformationResult;
|
|
80
|
+
readonly response: Effect.Effect<CloudflareResponse, ImagesOperationError>;
|
|
63
81
|
readonly contentType: Effect.Effect<string, ImagesOperationError>;
|
|
64
82
|
readonly image: (
|
|
65
83
|
options?: ImageTransformationOutputOptions,
|
|
@@ -67,7 +85,7 @@ export interface ImagesTransformationResultClient {
|
|
|
67
85
|
}
|
|
68
86
|
|
|
69
87
|
export interface ImageHandleClient {
|
|
70
|
-
readonly raw:
|
|
88
|
+
readonly raw: CloudflareImageHandle;
|
|
71
89
|
readonly details: Effect.Effect<Option.Option<ImageMetadata>, ImagesOperationError>;
|
|
72
90
|
readonly bytes: Effect.Effect<Option.Option<ReadableStream<Uint8Array>>, ImagesOperationError>;
|
|
73
91
|
readonly update: (
|
|
@@ -83,7 +101,7 @@ export interface HostedImagesClient {
|
|
|
83
101
|
options?: ImageUploadOptions,
|
|
84
102
|
) => Effect.Effect<ImageMetadata, ImagesOperationError>;
|
|
85
103
|
readonly list: (options?: ImageListOptions) => Effect.Effect<ImageList, ImagesOperationError>;
|
|
86
|
-
readonly unsafeRaw: Effect.Effect<
|
|
104
|
+
readonly unsafeRaw: Effect.Effect<CloudflareHostedImagesBinding>;
|
|
87
105
|
}
|
|
88
106
|
|
|
89
107
|
export interface ImagesRuntimeBinding {
|
|
@@ -94,8 +112,8 @@ export interface ImagesRuntimeBinding {
|
|
|
94
112
|
readonly input: (
|
|
95
113
|
image: ImageInputValue,
|
|
96
114
|
options?: ImageInputOptions,
|
|
97
|
-
) =>
|
|
98
|
-
readonly hosted?:
|
|
115
|
+
) => CloudflareImageTransformer;
|
|
116
|
+
readonly hosted?: CloudflareHostedImagesBinding;
|
|
99
117
|
}
|
|
100
118
|
|
|
101
119
|
export interface ImagesClient {
|
|
@@ -106,7 +124,7 @@ export interface ImagesClient {
|
|
|
106
124
|
readonly input: (
|
|
107
125
|
image: ImageInputValue,
|
|
108
126
|
options?: ImageInputOptions,
|
|
109
|
-
) => Effect.Effect<
|
|
127
|
+
) => Effect.Effect<CloudflareImageTransformer, ImagesOperationError>;
|
|
110
128
|
readonly process: (
|
|
111
129
|
steps: Steps,
|
|
112
130
|
options: ProcessOptions,
|
|
@@ -223,7 +241,7 @@ const maybe = <A>(value: A | null): Option.Option<A> =>
|
|
|
223
241
|
const hasFunction = (value: object, key: string): boolean =>
|
|
224
242
|
typeof Reflect.get(value, key) === "function";
|
|
225
243
|
|
|
226
|
-
const isHostedImagesBinding = (value: unknown): value is
|
|
244
|
+
const isHostedImagesBinding = (value: unknown): value is CloudflareHostedImagesBinding =>
|
|
227
245
|
typeof value === "object" &&
|
|
228
246
|
value !== null &&
|
|
229
247
|
hasFunction(value, "image") &&
|
|
@@ -238,7 +256,7 @@ export const isImagesBinding = (value: unknown): value is ImagesRuntimeBinding =
|
|
|
238
256
|
|
|
239
257
|
const wrapResult = (
|
|
240
258
|
binding: string,
|
|
241
|
-
result:
|
|
259
|
+
result: CloudflareImageTransformationResult,
|
|
242
260
|
): ImagesTransformationResultClient => ({
|
|
243
261
|
raw: result,
|
|
244
262
|
response: tryImagesSync(binding, "response", () => result.response()),
|
|
@@ -246,7 +264,7 @@ const wrapResult = (
|
|
|
246
264
|
image: (options) => tryImagesSync(binding, "image", () => result.image(options)),
|
|
247
265
|
});
|
|
248
266
|
|
|
249
|
-
const wrapHandle = (binding: string, handle:
|
|
267
|
+
const wrapHandle = (binding: string, handle: CloudflareImageHandle): ImageHandleClient => ({
|
|
250
268
|
raw: handle,
|
|
251
269
|
details: tryImagesPromise(binding, "details", () => handle.details()).pipe(Effect.map(maybe)),
|
|
252
270
|
bytes: tryImagesPromise(binding, "bytes", () => handle.bytes()).pipe(Effect.map(maybe)),
|
|
@@ -256,7 +274,7 @@ const wrapHandle = (binding: string, handle: globalThis.ImageHandle): ImageHandl
|
|
|
256
274
|
|
|
257
275
|
const wrapHosted = (
|
|
258
276
|
binding: string,
|
|
259
|
-
hosted:
|
|
277
|
+
hosted: CloudflareHostedImagesBinding,
|
|
260
278
|
): HostedImagesClient => ({
|
|
261
279
|
image: (imageId) => wrapHandle(binding, hosted.image(imageId)),
|
|
262
280
|
upload: (image, options) =>
|
package/src/Kv.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
KVNamespaceListOptions as CloudflareKVNamespaceListOptions,
|
|
3
|
+
KVNamespacePutOptions as CloudflareKVNamespacePutOptions,
|
|
4
|
+
} from "@cloudflare/workers-types";
|
|
1
5
|
import { Context, Data, Effect, Option, Schema as S, type Layer } from "effect";
|
|
2
6
|
|
|
3
7
|
import * as Binding from "./Binding";
|
|
@@ -14,9 +18,9 @@ export class KvOperationError extends Data.TaggedError("KvOperationError")<{
|
|
|
14
18
|
}> {}
|
|
15
19
|
|
|
16
20
|
/** `KVNamespace.put` options. */
|
|
17
|
-
export type KvPutOptions =
|
|
21
|
+
export type KvPutOptions = CloudflareKVNamespacePutOptions;
|
|
18
22
|
/** `KVNamespace.list` options with optional metadata decoding schema. */
|
|
19
|
-
export type KvListOptions<Metadata = unknown> =
|
|
23
|
+
export type KvListOptions<Metadata = unknown> = CloudflareKVNamespaceListOptions & {
|
|
20
24
|
readonly metadataSchema?: S.Codec<Metadata, unknown>;
|
|
21
25
|
};
|
|
22
26
|
|
package/src/QueueBinding.ts
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
MessageSendRequest as CloudflareMessageSendRequest,
|
|
3
|
+
Queue as CloudflareQueue,
|
|
4
|
+
QueueMetrics as CloudflareQueueMetrics,
|
|
5
|
+
QueueSendBatchOptions as CloudflareQueueSendBatchOptions,
|
|
6
|
+
QueueSendBatchResponse as CloudflareQueueSendBatchResponse,
|
|
7
|
+
QueueSendOptions as CloudflareQueueSendOptions,
|
|
8
|
+
QueueSendResponse as CloudflareQueueSendResponse,
|
|
9
|
+
} from "@cloudflare/workers-types";
|
|
1
10
|
import { Context, Data, Effect, Schema as S } from "effect";
|
|
2
11
|
|
|
3
12
|
import * as Binding from "./Binding";
|
|
4
13
|
import type * as RpcDefinition from "./RpcDefinition";
|
|
5
14
|
|
|
6
|
-
export type QueueSendOptions =
|
|
7
|
-
export type QueueSendResponse =
|
|
8
|
-
export type QueueSendBatchOptions =
|
|
9
|
-
export type QueueSendBatchResponse =
|
|
10
|
-
export type QueueMetrics =
|
|
11
|
-
export type MessageSendRequest<Body> =
|
|
15
|
+
export type QueueSendOptions = CloudflareQueueSendOptions;
|
|
16
|
+
export type QueueSendResponse = CloudflareQueueSendResponse;
|
|
17
|
+
export type QueueSendBatchOptions = CloudflareQueueSendBatchOptions;
|
|
18
|
+
export type QueueSendBatchResponse = CloudflareQueueSendBatchResponse;
|
|
19
|
+
export type QueueMetrics = CloudflareQueueMetrics;
|
|
20
|
+
export type MessageSendRequest<Body> = CloudflareMessageSendRequest<Body>;
|
|
12
21
|
|
|
13
|
-
export type QueueProducer<Body> = Pick<
|
|
14
|
-
Partial<Pick<
|
|
22
|
+
export type QueueProducer<Body> = Pick<CloudflareQueue<Body>, "send"> &
|
|
23
|
+
Partial<Pick<CloudflareQueue<Body>, "sendBatch" | "metrics">>;
|
|
15
24
|
|
|
16
25
|
const expectedQueueProducer = "Queue producer binding with send(); optional sendBatch()/metrics()";
|
|
17
26
|
|
|
@@ -32,7 +41,7 @@ export interface QueueBindingClient<Message extends RpcDefinition.ServiceFreeSch
|
|
|
32
41
|
options?: QueueSendBatchOptions,
|
|
33
42
|
) => Effect.Effect<void, QueueOperationError | S.SchemaError>;
|
|
34
43
|
readonly metrics: () => Effect.Effect<QueueMetrics, QueueOperationError>;
|
|
35
|
-
readonly unsafeRaw: Effect.Effect<
|
|
44
|
+
readonly unsafeRaw: Effect.Effect<CloudflareQueue<S.Codec.Encoded<Message>>>;
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
export class QueueOperationError extends Data.TaggedError("QueueOperationError")<{
|
|
@@ -129,7 +138,7 @@ export const makeClient = <Message extends RpcDefinition.ServiceFreeSchema>(
|
|
|
129
138
|
|
|
130
139
|
return tryQueuePromise(definition.binding, "metrics", () => metrics.call(queue));
|
|
131
140
|
},
|
|
132
|
-
unsafeRaw: Effect.succeed(queue as
|
|
141
|
+
unsafeRaw: Effect.succeed(queue as CloudflareQueue<EncodedBody>),
|
|
133
142
|
});
|
|
134
143
|
};
|
|
135
144
|
|
package/src/R2.ts
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
R2Bucket as CloudflareR2Bucket,
|
|
3
|
+
R2Conditional as CloudflareR2Conditional,
|
|
4
|
+
R2GetOptions as CloudflareR2GetOptions,
|
|
5
|
+
R2ListOptions as CloudflareR2ListOptions,
|
|
6
|
+
R2MultipartOptions as CloudflareR2MultipartOptions,
|
|
7
|
+
R2MultipartUpload as CloudflareR2MultipartUpload,
|
|
8
|
+
R2Object as CloudflareR2Object,
|
|
9
|
+
R2ObjectBody as CloudflareR2ObjectBody,
|
|
10
|
+
R2Objects as CloudflareR2Objects,
|
|
11
|
+
R2PutOptions as CloudflareR2PutOptions,
|
|
12
|
+
R2UploadPartOptions as CloudflareR2UploadPartOptions,
|
|
13
|
+
R2UploadedPart as CloudflareR2UploadedPart,
|
|
14
|
+
} from "@cloudflare/workers-types";
|
|
1
15
|
import { Context, Data, Effect, Option, type Layer } from "effect";
|
|
2
16
|
|
|
3
17
|
import * as Binding from "./Binding";
|
|
@@ -19,19 +33,19 @@ export interface R2Definition {
|
|
|
19
33
|
readonly binding: string;
|
|
20
34
|
}
|
|
21
35
|
|
|
22
|
-
export type R2GetOptions =
|
|
23
|
-
export type R2PutOptions =
|
|
24
|
-
export type R2ListOptions =
|
|
25
|
-
export type R2MultipartOptions =
|
|
26
|
-
export type R2UploadPartOptions =
|
|
36
|
+
export type R2GetOptions = CloudflareR2GetOptions;
|
|
37
|
+
export type R2PutOptions = CloudflareR2PutOptions;
|
|
38
|
+
export type R2ListOptions = CloudflareR2ListOptions;
|
|
39
|
+
export type R2MultipartOptions = CloudflareR2MultipartOptions;
|
|
40
|
+
export type R2UploadPartOptions = CloudflareR2UploadPartOptions;
|
|
27
41
|
export type R2PutValue = ReadableStream | ArrayBuffer | ArrayBufferView | string | null | Blob;
|
|
28
42
|
export type R2UploadPartValue = ReadableStream | ArrayBuffer | ArrayBufferView | string | Blob;
|
|
29
43
|
|
|
30
44
|
export interface R2ObjectBodyClient extends Omit<
|
|
31
|
-
|
|
45
|
+
CloudflareR2ObjectBody,
|
|
32
46
|
"arrayBuffer" | "blob" | "bytes" | "json" | "text"
|
|
33
47
|
> {
|
|
34
|
-
readonly raw:
|
|
48
|
+
readonly raw: CloudflareR2ObjectBody;
|
|
35
49
|
readonly arrayBuffer: Effect.Effect<ArrayBuffer, R2OperationError>;
|
|
36
50
|
readonly bytes: Effect.Effect<Uint8Array, R2OperationError>;
|
|
37
51
|
readonly text: Effect.Effect<string, R2OperationError>;
|
|
@@ -40,29 +54,29 @@ export interface R2ObjectBodyClient extends Omit<
|
|
|
40
54
|
}
|
|
41
55
|
|
|
42
56
|
export interface R2MultipartUploadClient {
|
|
43
|
-
readonly raw:
|
|
57
|
+
readonly raw: CloudflareR2MultipartUpload;
|
|
44
58
|
readonly key: string;
|
|
45
59
|
readonly uploadId: string;
|
|
46
60
|
readonly uploadPart: (
|
|
47
61
|
partNumber: number,
|
|
48
62
|
value: R2UploadPartValue,
|
|
49
63
|
options?: R2UploadPartOptions,
|
|
50
|
-
) => Effect.Effect<
|
|
64
|
+
) => Effect.Effect<CloudflareR2UploadedPart, R2OperationError>;
|
|
51
65
|
readonly abort: Effect.Effect<void, R2OperationError>;
|
|
52
66
|
readonly complete: (
|
|
53
|
-
uploadedParts: ReadonlyArray<
|
|
54
|
-
) => Effect.Effect<
|
|
67
|
+
uploadedParts: ReadonlyArray<CloudflareR2UploadedPart>,
|
|
68
|
+
) => Effect.Effect<CloudflareR2Object, R2OperationError>;
|
|
55
69
|
}
|
|
56
70
|
|
|
57
71
|
export interface R2Client {
|
|
58
72
|
readonly head: (
|
|
59
73
|
key: string,
|
|
60
|
-
) => Effect.Effect<Option.Option<
|
|
74
|
+
) => Effect.Effect<Option.Option<CloudflareR2Object>, R2OperationError>;
|
|
61
75
|
readonly get: {
|
|
62
76
|
(
|
|
63
77
|
key: string,
|
|
64
|
-
options: R2GetOptions & { readonly onlyIf:
|
|
65
|
-
): Effect.Effect<Option.Option<R2ObjectBodyClient |
|
|
78
|
+
options: R2GetOptions & { readonly onlyIf: CloudflareR2Conditional | Headers },
|
|
79
|
+
): Effect.Effect<Option.Option<R2ObjectBodyClient | CloudflareR2Object>, R2OperationError>;
|
|
66
80
|
(
|
|
67
81
|
key: string,
|
|
68
82
|
options?: R2GetOptions,
|
|
@@ -72,13 +86,13 @@ export interface R2Client {
|
|
|
72
86
|
(
|
|
73
87
|
key: string,
|
|
74
88
|
value: R2PutValue,
|
|
75
|
-
options: R2PutOptions & { readonly onlyIf:
|
|
76
|
-
): Effect.Effect<Option.Option<
|
|
89
|
+
options: R2PutOptions & { readonly onlyIf: CloudflareR2Conditional | Headers },
|
|
90
|
+
): Effect.Effect<Option.Option<CloudflareR2Object>, R2OperationError>;
|
|
77
91
|
(
|
|
78
92
|
key: string,
|
|
79
93
|
value: R2PutValue,
|
|
80
94
|
options?: R2PutOptions,
|
|
81
|
-
): Effect.Effect<
|
|
95
|
+
): Effect.Effect<CloudflareR2Object, R2OperationError>;
|
|
82
96
|
};
|
|
83
97
|
readonly createMultipartUpload: (
|
|
84
98
|
key: string,
|
|
@@ -89,8 +103,8 @@ export interface R2Client {
|
|
|
89
103
|
uploadId: string,
|
|
90
104
|
) => Effect.Effect<R2MultipartUploadClient, R2OperationError>;
|
|
91
105
|
readonly delete: (keys: string | ReadonlyArray<string>) => Effect.Effect<void, R2OperationError>;
|
|
92
|
-
readonly list: (options?: R2ListOptions) => Effect.Effect<
|
|
93
|
-
readonly unsafeRaw: Effect.Effect<
|
|
106
|
+
readonly list: (options?: R2ListOptions) => Effect.Effect<CloudflareR2Objects, R2OperationError>;
|
|
107
|
+
readonly unsafeRaw: Effect.Effect<CloudflareR2Bucket>;
|
|
94
108
|
readonly definition: R2Definition;
|
|
95
109
|
}
|
|
96
110
|
|
|
@@ -149,16 +163,16 @@ const maybe = <A>(value: A | null): Option.Option<A> =>
|
|
|
149
163
|
value === null ? Option.none() : Option.some(value);
|
|
150
164
|
|
|
151
165
|
const isR2ObjectBody = (
|
|
152
|
-
value:
|
|
153
|
-
): value is
|
|
166
|
+
value: CloudflareR2ObjectBody | CloudflareR2Object,
|
|
167
|
+
): value is CloudflareR2ObjectBody =>
|
|
154
168
|
"body" in value &&
|
|
155
|
-
typeof (value as
|
|
156
|
-
typeof (value as
|
|
157
|
-
typeof (value as
|
|
158
|
-
typeof (value as
|
|
159
|
-
typeof (value as
|
|
169
|
+
typeof (value as CloudflareR2ObjectBody).arrayBuffer === "function" &&
|
|
170
|
+
typeof (value as CloudflareR2ObjectBody).bytes === "function" &&
|
|
171
|
+
typeof (value as CloudflareR2ObjectBody).text === "function" &&
|
|
172
|
+
typeof (value as CloudflareR2ObjectBody).json === "function" &&
|
|
173
|
+
typeof (value as CloudflareR2ObjectBody).blob === "function";
|
|
160
174
|
|
|
161
|
-
const wrapObjectBody = (binding: string, object:
|
|
175
|
+
const wrapObjectBody = (binding: string, object: CloudflareR2ObjectBody): R2ObjectBodyClient => ({
|
|
162
176
|
key: object.key,
|
|
163
177
|
version: object.version,
|
|
164
178
|
size: object.size,
|
|
@@ -186,8 +200,8 @@ const wrapObjectBody = (binding: string, object: globalThis.R2ObjectBody): R2Obj
|
|
|
186
200
|
|
|
187
201
|
const wrapGetResult = (
|
|
188
202
|
binding: string,
|
|
189
|
-
object:
|
|
190
|
-
): R2ObjectBodyClient |
|
|
203
|
+
object: CloudflareR2ObjectBody | CloudflareR2Object | null,
|
|
204
|
+
): R2ObjectBodyClient | CloudflareR2Object | null => {
|
|
191
205
|
if (object === null || !isR2ObjectBody(object)) {
|
|
192
206
|
return object;
|
|
193
207
|
}
|
|
@@ -195,7 +209,7 @@ const wrapGetResult = (
|
|
|
195
209
|
return wrapObjectBody(binding, object);
|
|
196
210
|
};
|
|
197
211
|
|
|
198
|
-
export const isR2Bucket = (value: unknown): value is
|
|
212
|
+
export const isR2Bucket = (value: unknown): value is CloudflareR2Bucket => {
|
|
199
213
|
if (typeof value !== "object" || value === null) {
|
|
200
214
|
return false;
|
|
201
215
|
}
|
|
@@ -215,8 +229,8 @@ export const isR2Bucket = (value: unknown): value is globalThis.R2Bucket => {
|
|
|
215
229
|
|
|
216
230
|
export const makeClient = (
|
|
217
231
|
definition: R2Definition,
|
|
218
|
-
): ((bucket:
|
|
219
|
-
const wrapUpload = (upload:
|
|
232
|
+
): ((bucket: CloudflareR2Bucket) => R2Client) => {
|
|
233
|
+
const wrapUpload = (upload: CloudflareR2MultipartUpload): R2MultipartUploadClient => ({
|
|
220
234
|
raw: upload,
|
|
221
235
|
key: upload.key,
|
|
222
236
|
uploadId: upload.uploadId,
|
|
@@ -246,7 +260,7 @@ export const makeClient = (
|
|
|
246
260
|
tryR2Promise(definition.binding, "put", () => bucket.put(key, value, options)).pipe(
|
|
247
261
|
Effect.map((object) => {
|
|
248
262
|
if (object === null) {
|
|
249
|
-
return Option.none<
|
|
263
|
+
return Option.none<CloudflareR2Object>();
|
|
250
264
|
}
|
|
251
265
|
|
|
252
266
|
if (options !== undefined && "onlyIf" in options) {
|