effect-cloudflare-r2-layer 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +268 -0
- package/cjs/dts/effects/tapLayer.effect.d.ts +3 -0
- package/cjs/dts/errors/file-storage.error.d.ts +9 -0
- package/cjs/dts/index.d.ts +5 -0
- package/cjs/dts/layer/file-storage.layer.d.ts +22 -0
- package/cjs/dts/r2/implementations/get-file-url.effect.d.ts +2 -0
- package/cjs/dts/r2/implementations/get-url.effect.d.ts +4 -0
- package/cjs/dts/r2/implementations/index.d.ts +2 -0
- package/cjs/dts/r2/implementations/read-as-json.effect.d.ts +3 -0
- package/cjs/dts/r2/implementations/read-as-raw-binary.effect.d.ts +3 -0
- package/cjs/dts/r2/implementations/read-as-text.effect.d.ts +3 -0
- package/cjs/dts/r2/implementations/upload-file.effect.d.ts +9 -0
- package/cjs/dts/r2/providers/r2-file-storage.provider.d.ts +3 -0
- package/cjs/dts/r2/r2-file-storage.layer.d.ts +2 -0
- package/cjs/effects/tapLayer.effect.js +7 -0
- package/cjs/effects/tapLayer.effect.js.map +1 -0
- package/cjs/errors/file-storage.error.js +8 -0
- package/cjs/errors/file-storage.error.js.map +1 -0
- package/cjs/index.js +26 -0
- package/cjs/index.js.map +1 -0
- package/cjs/layer/file-storage.layer.js +14 -0
- package/cjs/layer/file-storage.layer.js.map +1 -0
- package/cjs/package.json +1 -0
- package/cjs/r2/implementations/get-file-url.effect.js +9 -0
- package/cjs/r2/implementations/get-file-url.effect.js.map +1 -0
- package/cjs/r2/implementations/get-url.effect.js +19 -0
- package/cjs/r2/implementations/get-url.effect.js.map +1 -0
- package/cjs/r2/implementations/index.js +19 -0
- package/cjs/r2/implementations/index.js.map +1 -0
- package/cjs/r2/implementations/read-as-json.effect.js +19 -0
- package/cjs/r2/implementations/read-as-json.effect.js.map +1 -0
- package/cjs/r2/implementations/read-as-raw-binary.effect.js +18 -0
- package/cjs/r2/implementations/read-as-raw-binary.effect.js.map +1 -0
- package/cjs/r2/implementations/read-as-text.effect.js +18 -0
- package/cjs/r2/implementations/read-as-text.effect.js.map +1 -0
- package/cjs/r2/implementations/upload-file.effect.js +20 -0
- package/cjs/r2/implementations/upload-file.effect.js.map +1 -0
- package/cjs/r2/providers/r2-file-storage.provider.js +23 -0
- package/cjs/r2/providers/r2-file-storage.provider.js.map +1 -0
- package/cjs/r2/r2-file-storage.layer.js +17 -0
- package/cjs/r2/r2-file-storage.layer.js.map +1 -0
- package/esm/dts/effects/tapLayer.effect.d.ts +3 -0
- package/esm/dts/errors/file-storage.error.d.ts +9 -0
- package/esm/dts/index.d.ts +5 -0
- package/esm/dts/layer/file-storage.layer.d.ts +22 -0
- package/esm/dts/r2/implementations/get-file-url.effect.d.ts +2 -0
- package/esm/dts/r2/implementations/get-url.effect.d.ts +4 -0
- package/esm/dts/r2/implementations/index.d.ts +2 -0
- package/esm/dts/r2/implementations/read-as-json.effect.d.ts +3 -0
- package/esm/dts/r2/implementations/read-as-raw-binary.effect.d.ts +3 -0
- package/esm/dts/r2/implementations/read-as-text.effect.d.ts +3 -0
- package/esm/dts/r2/implementations/upload-file.effect.d.ts +9 -0
- package/esm/dts/r2/providers/r2-file-storage.provider.d.ts +3 -0
- package/esm/dts/r2/r2-file-storage.layer.d.ts +2 -0
- package/esm/effects/tapLayer.effect.js +3 -0
- package/esm/effects/tapLayer.effect.js.map +1 -0
- package/esm/errors/file-storage.error.js +4 -0
- package/esm/errors/file-storage.error.js.map +1 -0
- package/esm/index.js +6 -0
- package/esm/index.js.map +1 -0
- package/esm/layer/file-storage.layer.js +11 -0
- package/esm/layer/file-storage.layer.js.map +1 -0
- package/esm/package.json +1 -0
- package/esm/r2/implementations/get-file-url.effect.js +5 -0
- package/esm/r2/implementations/get-file-url.effect.js.map +1 -0
- package/esm/r2/implementations/get-url.effect.js +15 -0
- package/esm/r2/implementations/get-url.effect.js.map +1 -0
- package/esm/r2/implementations/index.js +3 -0
- package/esm/r2/implementations/index.js.map +1 -0
- package/esm/r2/implementations/read-as-json.effect.js +15 -0
- package/esm/r2/implementations/read-as-json.effect.js.map +1 -0
- package/esm/r2/implementations/read-as-raw-binary.effect.js +14 -0
- package/esm/r2/implementations/read-as-raw-binary.effect.js.map +1 -0
- package/esm/r2/implementations/read-as-text.effect.js +14 -0
- package/esm/r2/implementations/read-as-text.effect.js.map +1 -0
- package/esm/r2/implementations/upload-file.effect.js +16 -0
- package/esm/r2/implementations/upload-file.effect.js.map +1 -0
- package/esm/r2/providers/r2-file-storage.provider.js +20 -0
- package/esm/r2/providers/r2-file-storage.provider.js.map +1 -0
- package/esm/r2/r2-file-storage.layer.js +14 -0
- package/esm/r2/r2-file-storage.layer.js.map +1 -0
- package/package.json +64 -0
package/README.md
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
# effect-cloudflare-r2-layer
|
2
|
+
|
3
|
+
An effect layer to interact with Cloudware R2 storage service.
|
4
|
+
|
5
|
+
<!-- readme-package-icons start -->
|
6
|
+
|
7
|
+
<p align="left"><a href="https://www.typescriptlang.org/docs/" target="_blank"><img height="50" src="https://raw.githubusercontent.com/jpb06/jpb06/master/icons/TypeScript.svg" /></a> <a href="https://nodejs.org/en/docs/" target="_blank"><img height="50" src="https://raw.githubusercontent.com/jpb06/jpb06/master/icons/NodeJS-Dark.svg" /></a> <a href="https://bun.sh/docs" target="_blank"><img height="50" src="https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Bun-Dark.svg" /></a> <a href="https://aws.amazon.com/developer/language/javascript/" target="_blank"><img height="50" src="https://raw.githubusercontent.com/jpb06/jpb06/master/icons/AWS-Dark.svg" /></a> <a href="https://biomejs.dev/guides/getting-started/" target="_blank"><img height="50" src="https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Biome-Dark.svg" /></a> <a href="https://github.com/motdotla/dotenv#readme" target="_blank"><img height="50" src="https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Dotenv-Dark.svg" /></a> <a href="https://www.effect.website/docs/quickstart" target="_blank"><img height="50" src="https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Effect-Dark.svg" /></a></p>
|
8
|
+
|
9
|
+
<!-- readme-package-icons end -->
|
10
|
+
|
11
|
+
## ⚡ Env variables
|
12
|
+
|
13
|
+
The layer requires the following env variables:
|
14
|
+
|
15
|
+
```env
|
16
|
+
CLOUDFLARE_ACCOUNT_ID=""
|
17
|
+
R2_DOCUMENTS_ACCESS_KEY_ID=""
|
18
|
+
R2_DOCUMENTS_SECRET_ACCESS_KEY=""
|
19
|
+
```
|
20
|
+
|
21
|
+
## ⚡ API
|
22
|
+
|
23
|
+
### 🔶 `uploadFile`
|
24
|
+
|
25
|
+
Adds a file to the specified bucket.
|
26
|
+
|
27
|
+
```typescript
|
28
|
+
interface UploadFileInput<TBucket extends string> {
|
29
|
+
bucketName: TBucket;
|
30
|
+
key: string;
|
31
|
+
data: Buffer;
|
32
|
+
contentType: string | undefined;
|
33
|
+
}
|
34
|
+
|
35
|
+
type uploadFile = <TBucket extends string>(
|
36
|
+
input: UploadFileInput<TBucket>
|
37
|
+
) => Effect.Effect<
|
38
|
+
void,
|
39
|
+
FileStorageError | ConfigError.ConfigError,
|
40
|
+
FileStorage
|
41
|
+
>;
|
42
|
+
```
|
43
|
+
|
44
|
+
#### 🧿 Example
|
45
|
+
|
46
|
+
```typescript
|
47
|
+
import { Effect, pipe } from 'effect';
|
48
|
+
import {
|
49
|
+
CloudflareR2StorageLayerLive,
|
50
|
+
FileStorageLayer,
|
51
|
+
} from 'effect-cloudflare-r2-layer';
|
52
|
+
import { readFile } from 'fs-extra';
|
53
|
+
|
54
|
+
type Buckets = 'assets' | 'config';
|
55
|
+
const fileName = 'yolo.jpg';
|
56
|
+
const filePath = './assets/yolo.jpg';
|
57
|
+
|
58
|
+
const task = pipe(
|
59
|
+
Effect.gen(function* () {
|
60
|
+
const fileData = yield* Effect.tryPromise({
|
61
|
+
try: () => readFile(filePath),
|
62
|
+
catch: (e) => new FsError({ cause: e }),
|
63
|
+
});
|
64
|
+
|
65
|
+
yield* FileStorageLayer.uploadFile<Buckets>({
|
66
|
+
key: fileName,
|
67
|
+
bucketName: 'assets',
|
68
|
+
data: fileData,
|
69
|
+
contentType: 'image/jpeg',
|
70
|
+
});
|
71
|
+
|
72
|
+
// ...
|
73
|
+
}),
|
74
|
+
Effect.provide(CloudflareR2StorageLayerLive);
|
75
|
+
);
|
76
|
+
```
|
77
|
+
|
78
|
+
### 🔶 `getFileUrl`
|
79
|
+
|
80
|
+
Gets a pre-signed url to fetch a ressource by its `filename` from the specified `bucket`.
|
81
|
+
|
82
|
+
```typescript
|
83
|
+
type getFileUrl = <TBucket extends string>(
|
84
|
+
bucket: TBucket
|
85
|
+
fileName: string,
|
86
|
+
) => Effect.Effect<
|
87
|
+
string,
|
88
|
+
FileStorageError | ConfigError.ConfigError,
|
89
|
+
FileStorage
|
90
|
+
>;
|
91
|
+
```
|
92
|
+
|
93
|
+
#### 🧿 Example
|
94
|
+
|
95
|
+
```typescript
|
96
|
+
import { Effect, pipe } from 'effect';
|
97
|
+
import {
|
98
|
+
CloudflareR2StorageLayerLive,
|
99
|
+
FileStorageLayer,
|
100
|
+
} from 'effect-cloudflare-r2-layer';
|
101
|
+
|
102
|
+
type Buckets = 'assets' | 'config';
|
103
|
+
const filename = 'yolo.jpg';
|
104
|
+
|
105
|
+
const task = pipe(
|
106
|
+
Effect.gen(function* () {
|
107
|
+
const url = yield* FileStorageLayer.getFileUrl<Buckets>('assets', filename);
|
108
|
+
|
109
|
+
// ...
|
110
|
+
}),
|
111
|
+
Effect.provide(CloudflareR2StorageLayerLive);
|
112
|
+
);
|
113
|
+
```
|
114
|
+
|
115
|
+
### 🔶 `readAsJson`
|
116
|
+
|
117
|
+
Fetches a file, expecting a content extending `Record<string, unknown>`.
|
118
|
+
|
119
|
+
```typescript
|
120
|
+
readAsJson: <TBucket extends string, TShape extends Record<string, unknown>>(
|
121
|
+
bucketName: TBucket,
|
122
|
+
documentKey: string
|
123
|
+
) =>
|
124
|
+
Effect.Effect<
|
125
|
+
TShape,
|
126
|
+
ConfigError | HttpClientError | FileStorageError,
|
127
|
+
Scope | HttpClient.HttpClient.Service
|
128
|
+
>;
|
129
|
+
```
|
130
|
+
|
131
|
+
#### 🧿 Example
|
132
|
+
|
133
|
+
```typescript
|
134
|
+
import { FetchHttpClient } from '@effect/platform';
|
135
|
+
import { Effect, Layer, pipe } from 'effect';
|
136
|
+
import {
|
137
|
+
CloudflareR2StorageLayerLive,
|
138
|
+
FileStorageLayer,
|
139
|
+
} from 'effect-cloudflare-r2-layer';
|
140
|
+
|
141
|
+
type Buckets = 'assets' | 'config';
|
142
|
+
|
143
|
+
type JsonData = {
|
144
|
+
cool: boolean;
|
145
|
+
yolo: string;
|
146
|
+
};
|
147
|
+
|
148
|
+
const task = pipe(
|
149
|
+
pipe(
|
150
|
+
Effect.gen(function* () {
|
151
|
+
const json = yield* FileStorageLayer.readAsJson<Buckets, JsonData>(
|
152
|
+
'config',
|
153
|
+
'app-config.json'
|
154
|
+
);
|
155
|
+
|
156
|
+
// json is of type JsonData ...
|
157
|
+
}),
|
158
|
+
Effect.scoped,
|
159
|
+
Effect.provide(
|
160
|
+
Layer.mergeAll(CloudflareR2StorageLayerLive, FetchHttpClient.layer)
|
161
|
+
)
|
162
|
+
)
|
163
|
+
);
|
164
|
+
```
|
165
|
+
|
166
|
+
### 🔶 `readAsText`
|
167
|
+
|
168
|
+
Fetches a file as a string.
|
169
|
+
|
170
|
+
```typescript
|
171
|
+
readAsText: <TBucket extends string>(
|
172
|
+
bucketName: TBucket,
|
173
|
+
documentKey: string
|
174
|
+
) =>
|
175
|
+
Effect.Effect<
|
176
|
+
string,
|
177
|
+
ConfigError | HttpClientError | FileStorageError,
|
178
|
+
Scope | HttpClient.HttpClient.Service
|
179
|
+
>;
|
180
|
+
```
|
181
|
+
|
182
|
+
#### 🧿 Example
|
183
|
+
|
184
|
+
```typescript
|
185
|
+
import { FetchHttpClient } from '@effect/platform';
|
186
|
+
import { Effect, Layer, pipe } from 'effect';
|
187
|
+
import {
|
188
|
+
CloudflareR2StorageLayerLive,
|
189
|
+
FileStorageLayer,
|
190
|
+
} from 'effect-cloudflare-r2-layer';
|
191
|
+
|
192
|
+
type Buckets = 'assets' | 'config';
|
193
|
+
|
194
|
+
const task = pipe(
|
195
|
+
pipe(
|
196
|
+
Effect.gen(function* () {
|
197
|
+
const text = yield* FileStorageLayer.readAsText<Buckets>(
|
198
|
+
'assets',
|
199
|
+
'content.txt'
|
200
|
+
);
|
201
|
+
|
202
|
+
// ...
|
203
|
+
}),
|
204
|
+
Effect.scoped,
|
205
|
+
Effect.provide(
|
206
|
+
Layer.mergeAll(CloudflareR2StorageLayerLive, FetchHttpClient.layer)
|
207
|
+
)
|
208
|
+
)
|
209
|
+
);
|
210
|
+
```
|
211
|
+
|
212
|
+
### 🔶 `readAsRawBinary`
|
213
|
+
|
214
|
+
Fetches a file as raw binary.
|
215
|
+
|
216
|
+
```typescript
|
217
|
+
readAsRawBinary: <TBucket extends string>(
|
218
|
+
bucketName: TBucket,
|
219
|
+
documentKey: string
|
220
|
+
) =>
|
221
|
+
Effect.Effect<
|
222
|
+
ArrayBuffer,
|
223
|
+
ConfigError | HttpClientError | FileStorageError,
|
224
|
+
Scope | HttpClient.HttpClient.Service
|
225
|
+
>;
|
226
|
+
```
|
227
|
+
|
228
|
+
#### 🧿 Example
|
229
|
+
|
230
|
+
```typescript
|
231
|
+
import { FetchHttpClient } from '@effect/platform';
|
232
|
+
import { Effect, Layer, pipe } from 'effect';
|
233
|
+
import {
|
234
|
+
CloudflareR2StorageLayerLive,
|
235
|
+
FileStorageLayer,
|
236
|
+
} from 'effect-cloudflare-r2-layer';
|
237
|
+
import fs from 'fs-extra';
|
238
|
+
import { TaggedError } from 'effect/Data';
|
239
|
+
|
240
|
+
export class FsError extends TaggedError('FsError')<{
|
241
|
+
cause?: unknown;
|
242
|
+
}> {}
|
243
|
+
|
244
|
+
type Buckets = 'assets' | 'config';
|
245
|
+
|
246
|
+
const task = pipe(
|
247
|
+
pipe(
|
248
|
+
Effect.gen(function* () {
|
249
|
+
const buffer = yield* FileStorageLayer.readAsRawBinary<Buckets>(
|
250
|
+
'assets',
|
251
|
+
'yolo.jpg'
|
252
|
+
);
|
253
|
+
|
254
|
+
yield* Effect.tryPromise({
|
255
|
+
try: () =>
|
256
|
+
fs.writeFile('./file.jpg', Buffer.from(buffer), {
|
257
|
+
encoding: 'utf-8',
|
258
|
+
}),
|
259
|
+
catch: (e) => new FsError({ cause: e }),
|
260
|
+
});
|
261
|
+
}),
|
262
|
+
Effect.scoped,
|
263
|
+
Effect.provide(
|
264
|
+
Layer.mergeAll(CloudflareR2StorageLayerLive, FetchHttpClient.layer)
|
265
|
+
)
|
266
|
+
)
|
267
|
+
);
|
268
|
+
```
|
@@ -0,0 +1,9 @@
|
|
1
|
+
declare const FileStorageError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
|
2
|
+
readonly _tag: "file-storage-error";
|
3
|
+
} & Readonly<A>;
|
4
|
+
export declare class FileStorageError extends FileStorageError_base<{
|
5
|
+
cause?: unknown;
|
6
|
+
message?: string;
|
7
|
+
}> {
|
8
|
+
}
|
9
|
+
export {};
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { HttpClientError } from '@effect/platform/HttpClientError';
|
2
|
+
import type { ConfigError, Effect } from 'effect';
|
3
|
+
import { Context } from 'effect';
|
4
|
+
import { HttpClient } from '@effect/platform';
|
5
|
+
import { Scope } from 'effect/Scope';
|
6
|
+
import type { FileStorageError } from '../errors/file-storage.error.js';
|
7
|
+
import type { UploadFileInput } from '../r2/implementations/upload-file.effect.js';
|
8
|
+
export interface FileStorage {
|
9
|
+
readonly getFileUrl: <TBucket extends string>(fileName: string, bucket: TBucket) => Effect.Effect<string, FileStorageError | ConfigError.ConfigError>;
|
10
|
+
readonly readAsRawBinary: <TBucket extends string>(bucketName: TBucket, documentKey: string) => Effect.Effect<ArrayBuffer, ConfigError.ConfigError | HttpClientError | FileStorageError, Scope | HttpClient.HttpClient.Service>;
|
11
|
+
readonly readAsJson: <TBucket extends string, TShape extends Record<string, unknown>>(bucketName: TBucket, documentKey: string) => Effect.Effect<TShape, ConfigError.ConfigError | HttpClientError | FileStorageError, Scope | HttpClient.HttpClient.Service>;
|
12
|
+
readonly readAsText: <TBucket extends string>(bucketName: TBucket, documentKey: string) => Effect.Effect<string, ConfigError.ConfigError | HttpClientError | FileStorageError, Scope | HttpClient.HttpClient.Service>;
|
13
|
+
readonly uploadFile: <TBucket extends string>(input: UploadFileInput<TBucket>) => Effect.Effect<void, FileStorageError | ConfigError.ConfigError>;
|
14
|
+
}
|
15
|
+
export declare const FileStorageLayerContext: Context.Tag<FileStorage, FileStorage>;
|
16
|
+
export declare const FileStorageLayer: {
|
17
|
+
getFileUrl: <TBucket extends string>(bucket: TBucket, fileName: string) => Effect.Effect<string, FileStorageError | ConfigError.ConfigError, FileStorage>;
|
18
|
+
readAsRawBinary: <TBucket extends string>(bucket: TBucket, fileName: string) => Effect.Effect<ArrayBuffer, FileStorageError | ConfigError.ConfigError | HttpClientError, FileStorage | Scope | HttpClient.HttpClient.Service>;
|
19
|
+
readAsJson: <TBucket extends string, TShape extends Record<string, unknown>>(bucket: TBucket, fileName: string) => Effect.Effect<TShape, FileStorageError | ConfigError.ConfigError | HttpClientError, FileStorage | Scope | HttpClient.HttpClient.Service>;
|
20
|
+
readAsText: <TBucket extends string>(bucket: TBucket, fileName: string) => Effect.Effect<string, FileStorageError | ConfigError.ConfigError | HttpClientError, FileStorage | Scope | HttpClient.HttpClient.Service>;
|
21
|
+
uploadFile: <TBucket extends string>(input: UploadFileInput<TBucket>) => Effect.Effect<void, FileStorageError | ConfigError.ConfigError, FileStorage>;
|
22
|
+
};
|
@@ -0,0 +1,4 @@
|
|
1
|
+
import type { S3Client } from '@aws-sdk/client-s3';
|
2
|
+
import { Effect } from 'effect';
|
3
|
+
import { FileStorageError } from '../../errors/file-storage.error.js';
|
4
|
+
export declare const getUrl: <TBucket extends string>(provider: S3Client, bucketName: TBucket, documentKey: TBucket) => Effect.Effect<string, FileStorageError, never>;
|
@@ -0,0 +1,3 @@
|
|
1
|
+
import { HttpClient } from '@effect/platform';
|
2
|
+
import { Effect } from 'effect';
|
3
|
+
export declare const readAsJson: <TBucket extends string, TShape extends Record<string, unknown>>(bucketName: TBucket, documentKey: string) => Effect.Effect<TShape, import("../../errors/file-storage.error.js").FileStorageError | import("effect/ConfigError").ConfigError | import("@effect/platform/HttpClientError").HttpClientError, import("effect/Scope").Scope | HttpClient.HttpClient.Service>;
|
@@ -0,0 +1,3 @@
|
|
1
|
+
import { HttpClient } from '@effect/platform';
|
2
|
+
import { Effect } from 'effect';
|
3
|
+
export declare const readAsRawBinary: <TBucket extends string>(bucketName: TBucket, documentKey: string) => Effect.Effect<ArrayBuffer, import("../../errors/file-storage.error.js").FileStorageError | import("effect/ConfigError").ConfigError | import("@effect/platform/HttpClientError").HttpClientError, import("effect/Scope").Scope | HttpClient.HttpClient.Service>;
|
@@ -0,0 +1,3 @@
|
|
1
|
+
import { HttpClient } from '@effect/platform';
|
2
|
+
import { Effect } from 'effect';
|
3
|
+
export declare const readAsText: <TBucket extends string>(bucketName: TBucket, documentKey: string) => Effect.Effect<string, import("../../errors/file-storage.error.js").FileStorageError | import("effect/ConfigError").ConfigError | import("@effect/platform/HttpClientError").HttpClientError, import("effect/Scope").Scope | HttpClient.HttpClient.Service>;
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { Effect } from 'effect';
|
2
|
+
import { FileStorageError } from '../../errors/file-storage.error.js';
|
3
|
+
export interface UploadFileInput<TBucket extends string> {
|
4
|
+
bucketName: TBucket;
|
5
|
+
key: string;
|
6
|
+
data: Buffer;
|
7
|
+
contentType: string | undefined;
|
8
|
+
}
|
9
|
+
export declare const uploadFile: <TBucket extends string>({ bucketName, key, data, contentType, }: UploadFileInput<TBucket>) => Effect.Effect<import("@aws-sdk/client-s3").PutObjectCommandOutput, FileStorageError | import("effect/ConfigError").ConfigError, never>;
|
@@ -0,0 +1,7 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.tapLayer = void 0;
|
4
|
+
const effect_1 = require("effect");
|
5
|
+
const tapLayer = (context, effect) => (0, effect_1.pipe)(context, effect_1.Effect.flatMap(effect));
|
6
|
+
exports.tapLayer = tapLayer;
|
7
|
+
//# sourceMappingURL=tapLayer.effect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"tapLayer.effect.js","sourceRoot":"","sources":["../../../src/effects/tapLayer.effect.ts"],"names":[],"mappings":";;;AACA,mCAAsC;AAE/B,MAAM,QAAQ,GAAG,CACtB,OAA0B,EAC1B,MAA4C,EAC5C,EAAE,CAAC,IAAA,aAAI,EAAC,OAAO,EAAE,eAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAH9B,QAAA,QAAQ,YAGsB"}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.FileStorageError = void 0;
|
4
|
+
const Data_1 = require("effect/Data");
|
5
|
+
class FileStorageError extends (0, Data_1.TaggedError)('file-storage-error') {
|
6
|
+
}
|
7
|
+
exports.FileStorageError = FileStorageError;
|
8
|
+
//# sourceMappingURL=file-storage.error.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"file-storage.error.js","sourceRoot":"","sources":["../../../src/errors/file-storage.error.ts"],"names":[],"mappings":";;;AAAA,sCAA0C;AAE1C,MAAa,gBAAiB,SAAQ,IAAA,kBAAW,EAAC,oBAAoB,CAGpE;CAAG;AAHL,4CAGK"}
|
package/cjs/index.js
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15
|
+
};
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
18
|
+
};
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
20
|
+
exports.FileStorageLayer = void 0;
|
21
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
22
|
+
dotenv_1.default.config();
|
23
|
+
const file_storage_layer_js_1 = require("./layer/file-storage.layer.js");
|
24
|
+
Object.defineProperty(exports, "FileStorageLayer", { enumerable: true, get: function () { return file_storage_layer_js_1.FileStorageLayer; } });
|
25
|
+
__exportStar(require("./r2/r2-file-storage.layer.js"), exports);
|
26
|
+
//# sourceMappingURL=index.js.map
|
package/cjs/index.js.map
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,oDAA4B;AAC5B,gBAAM,CAAC,MAAM,EAAE,CAAC;AAGhB,yEAAiE;AAExD,iGAFA,wCAAgB,OAEA;AAEzB,gEAA8C"}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.FileStorageLayer = exports.FileStorageLayerContext = void 0;
|
4
|
+
const effect_1 = require("effect");
|
5
|
+
const tapLayer_effect_js_1 = require("./../effects/tapLayer.effect.js");
|
6
|
+
exports.FileStorageLayerContext = effect_1.Context.GenericTag('file-storage');
|
7
|
+
exports.FileStorageLayer = {
|
8
|
+
getFileUrl: (bucket, fileName) => (0, tapLayer_effect_js_1.tapLayer)(exports.FileStorageLayerContext, ({ getFileUrl }) => getFileUrl(bucket, fileName)),
|
9
|
+
readAsRawBinary: (bucket, fileName) => (0, tapLayer_effect_js_1.tapLayer)(exports.FileStorageLayerContext, ({ readAsRawBinary }) => readAsRawBinary(bucket, fileName)),
|
10
|
+
readAsJson: (bucket, fileName) => (0, tapLayer_effect_js_1.tapLayer)(exports.FileStorageLayerContext, ({ readAsJson }) => readAsJson(bucket, fileName)),
|
11
|
+
readAsText: (bucket, fileName) => (0, tapLayer_effect_js_1.tapLayer)(exports.FileStorageLayerContext, ({ readAsText }) => readAsText(bucket, fileName)),
|
12
|
+
uploadFile: (input) => (0, tapLayer_effect_js_1.tapLayer)(exports.FileStorageLayerContext, ({ uploadFile }) => uploadFile(input)),
|
13
|
+
};
|
14
|
+
//# sourceMappingURL=file-storage.layer.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"file-storage.layer.js","sourceRoot":"","sources":["../../../src/layer/file-storage.layer.ts"],"names":[],"mappings":";;;AAEA,mCAAiC;AAMjC,wEAA2D;AAuC9C,QAAA,uBAAuB,GAClC,gBAAO,CAAC,UAAU,CAAc,cAAc,CAAC,CAAC;AAErC,QAAA,gBAAgB,GAAG;IAC9B,UAAU,EAAE,CAAyB,MAAe,EAAE,QAAgB,EAAE,EAAE,CACxE,IAAA,6BAAQ,EAAC,+BAAuB,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CACnD,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAC7B;IACH,eAAe,EAAE,CACf,MAAe,EACf,QAAgB,EAChB,EAAE,CACF,IAAA,6BAAQ,EAAC,+BAAuB,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE,CACxD,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAClC;IACH,UAAU,EAAE,CACV,MAAe,EACf,QAAgB,EAChB,EAAE,CACF,IAAA,6BAAQ,EAAC,+BAAuB,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CACnD,UAAU,CAAkB,MAAM,EAAE,QAAQ,CAAC,CAC9C;IACH,UAAU,EAAE,CAAyB,MAAe,EAAE,QAAgB,EAAE,EAAE,CACxE,IAAA,6BAAQ,EAAC,+BAAuB,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CACnD,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAC7B;IACH,UAAU,EAAE,CAAyB,KAA+B,EAAE,EAAE,CACtE,IAAA,6BAAQ,EAAC,+BAAuB,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;CAC3E,CAAC"}
|
package/cjs/package.json
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"type": "commonjs"}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.getFileUrl = void 0;
|
4
|
+
const effect_1 = require("effect");
|
5
|
+
const r2_file_storage_provider_js_1 = require("../providers/r2-file-storage.provider.js");
|
6
|
+
const get_url_effect_js_1 = require("./get-url.effect.js");
|
7
|
+
const getFileUrl = (bucketName, documentKey) => effect_1.Effect.withSpan('get-file-url', { attributes: { bucketName, documentKey } })((0, effect_1.pipe)(r2_file_storage_provider_js_1.cloudflareR2StorageProvider, effect_1.Effect.flatMap((provider) => (0, get_url_effect_js_1.getUrl)(provider, bucketName, documentKey))));
|
8
|
+
exports.getFileUrl = getFileUrl;
|
9
|
+
//# sourceMappingURL=get-file-url.effect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"get-file-url.effect.js","sourceRoot":"","sources":["../../../../src/r2/implementations/get-file-url.effect.ts"],"names":[],"mappings":";;;AAAA,mCAAsC;AAEtC,0FAAuF;AACvF,2DAA6C;AAEtC,MAAM,UAAU,GAAG,CACxB,UAAmB,EACnB,WAAmB,EACnB,EAAE,CACF,eAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,CAAC,CAC1E,IAAA,aAAI,EACF,yDAA2B,EAC3B,eAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAA,0BAAM,EAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CACxE,CACF,CAAC;AATS,QAAA,UAAU,cASnB"}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.getUrl = void 0;
|
4
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
5
|
+
const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
|
6
|
+
const effect_1 = require("effect");
|
7
|
+
const file_storage_error_js_1 = require("../../errors/file-storage.error.js");
|
8
|
+
const oneHourDuration = 60 * 60;
|
9
|
+
const getUrl = (provider, bucketName, documentKey) => effect_1.Effect.withSpan('get-url', { attributes: { bucketName, documentKey } })(effect_1.Effect.tryPromise({
|
10
|
+
try: () => (0, s3_request_presigner_1.getSignedUrl)(provider, new client_s3_1.GetObjectCommand({
|
11
|
+
Bucket: bucketName,
|
12
|
+
Key: documentKey,
|
13
|
+
}), {
|
14
|
+
expiresIn: oneHourDuration,
|
15
|
+
}),
|
16
|
+
catch: (e) => new file_storage_error_js_1.FileStorageError({ cause: e }),
|
17
|
+
}));
|
18
|
+
exports.getUrl = getUrl;
|
19
|
+
//# sourceMappingURL=get-url.effect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"get-url.effect.js","sourceRoot":"","sources":["../../../../src/r2/implementations/get-url.effect.ts"],"names":[],"mappings":";;;AACA,kDAAsD;AACtD,wEAAgF;AAChF,mCAAgC;AAEhC,8EAAsE;AAEtE,MAAM,eAAe,GAAG,EAAE,GAAG,EAAE,CAAC;AAEzB,MAAM,MAAM,GAAG,CACpB,QAAkB,EAClB,UAAmB,EACnB,WAAoB,EACpB,EAAE,CACF,eAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,CAAC,CACrE,eAAM,CAAC,UAAU,CAAC;IAChB,GAAG,EAAE,GAAG,EAAE,CACR,IAAA,mCAAe,EACb,QAAQ,EACR,IAAI,4BAAgB,CAAC;QACnB,MAAM,EAAE,UAAU;QAClB,GAAG,EAAE,WAAW;KACjB,CAAC,EACF;QACE,SAAS,EAAE,eAAe;KAC3B,CACF;IACH,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,wCAAgB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;CACjD,CAAC,CACH,CAAC;AApBS,QAAA,MAAM,UAoBf"}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15
|
+
};
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
17
|
+
__exportStar(require("./get-file-url.effect.js"), exports);
|
18
|
+
__exportStar(require("./upload-file.effect.js"), exports);
|
19
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/r2/implementations/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2DAAyC;AACzC,0DAAwC"}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.readAsJson = void 0;
|
4
|
+
const platform_1 = require("@effect/platform");
|
5
|
+
const effect_1 = require("effect");
|
6
|
+
const r2_file_storage_provider_js_1 = require("../providers/r2-file-storage.provider.js");
|
7
|
+
const get_url_effect_js_1 = require("./get-url.effect.js");
|
8
|
+
const readAsJson = (bucketName, documentKey) => effect_1.Effect.withSpan('read-as-json', {
|
9
|
+
attributes: { bucketName, documentKey },
|
10
|
+
})(effect_1.Effect.gen(function* () {
|
11
|
+
const provider = yield* r2_file_storage_provider_js_1.cloudflareR2StorageProvider;
|
12
|
+
const url = yield* (0, get_url_effect_js_1.getUrl)(provider, bucketName, documentKey);
|
13
|
+
const client = yield* platform_1.HttpClient.HttpClient;
|
14
|
+
const response = yield* client.get(url);
|
15
|
+
const json = yield* response.json;
|
16
|
+
return json;
|
17
|
+
}));
|
18
|
+
exports.readAsJson = readAsJson;
|
19
|
+
//# sourceMappingURL=read-as-json.effect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"read-as-json.effect.js","sourceRoot":"","sources":["../../../../src/r2/implementations/read-as-json.effect.ts"],"names":[],"mappings":";;;AAAA,+CAA8C;AAC9C,mCAAgC;AAEhC,0FAAuF;AACvF,2DAA6C;AAEtC,MAAM,UAAU,GAAG,CAIxB,UAAmB,EACnB,WAAmB,EACnB,EAAE,CACF,eAAM,CAAC,QAAQ,CAAC,cAAc,EAAE;IAC9B,UAAU,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE;CACxC,CAAC,CACA,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,yDAA2B,CAAC;IACpD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,IAAA,0BAAM,EAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAE7D,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,qBAAU,CAAC,UAAU,CAAC;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAExC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;IAElC,OAAO,IAAc,CAAC;AACxB,CAAC,CAAC,CACH,CAAC;AArBS,QAAA,UAAU,cAqBnB"}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.readAsRawBinary = void 0;
|
4
|
+
const platform_1 = require("@effect/platform");
|
5
|
+
const effect_1 = require("effect");
|
6
|
+
const r2_file_storage_provider_js_1 = require("../providers/r2-file-storage.provider.js");
|
7
|
+
const get_url_effect_js_1 = require("./get-url.effect.js");
|
8
|
+
const readAsRawBinary = (bucketName, documentKey) => effect_1.Effect.withSpan('read-as-raw-binary', {
|
9
|
+
attributes: { bucketName, documentKey },
|
10
|
+
})(effect_1.Effect.gen(function* () {
|
11
|
+
const provider = yield* r2_file_storage_provider_js_1.cloudflareR2StorageProvider;
|
12
|
+
const url = yield* (0, get_url_effect_js_1.getUrl)(provider, bucketName, documentKey);
|
13
|
+
const client = yield* platform_1.HttpClient.HttpClient;
|
14
|
+
const response = yield* client.get(url);
|
15
|
+
return yield* response.arrayBuffer;
|
16
|
+
}));
|
17
|
+
exports.readAsRawBinary = readAsRawBinary;
|
18
|
+
//# sourceMappingURL=read-as-raw-binary.effect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"read-as-raw-binary.effect.js","sourceRoot":"","sources":["../../../../src/r2/implementations/read-as-raw-binary.effect.ts"],"names":[],"mappings":";;;AAAA,+CAA8C;AAC9C,mCAAgC;AAEhC,0FAAuF;AACvF,2DAA6C;AAEtC,MAAM,eAAe,GAAG,CAC7B,UAAmB,EACnB,WAAmB,EACnB,EAAE,CACF,eAAM,CAAC,QAAQ,CAAC,oBAAoB,EAAE;IACpC,UAAU,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE;CACxC,CAAC,CACA,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,yDAA2B,CAAC;IACpD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,IAAA,0BAAM,EAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAE7D,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,qBAAU,CAAC,UAAU,CAAC;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAExC,OAAO,KAAK,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;AACrC,CAAC,CAAC,CACH,CAAC;AAhBS,QAAA,eAAe,mBAgBxB"}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.readAsText = void 0;
|
4
|
+
const platform_1 = require("@effect/platform");
|
5
|
+
const effect_1 = require("effect");
|
6
|
+
const r2_file_storage_provider_js_1 = require("../providers/r2-file-storage.provider.js");
|
7
|
+
const get_url_effect_js_1 = require("./get-url.effect.js");
|
8
|
+
const readAsText = (bucketName, documentKey) => effect_1.Effect.withSpan('read-as-text', {
|
9
|
+
attributes: { bucketName, documentKey },
|
10
|
+
})(effect_1.Effect.gen(function* () {
|
11
|
+
const provider = yield* r2_file_storage_provider_js_1.cloudflareR2StorageProvider;
|
12
|
+
const url = yield* (0, get_url_effect_js_1.getUrl)(provider, bucketName, documentKey);
|
13
|
+
const client = yield* platform_1.HttpClient.HttpClient;
|
14
|
+
const response = yield* client.get(url);
|
15
|
+
return yield* response.text;
|
16
|
+
}));
|
17
|
+
exports.readAsText = readAsText;
|
18
|
+
//# sourceMappingURL=read-as-text.effect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"read-as-text.effect.js","sourceRoot":"","sources":["../../../../src/r2/implementations/read-as-text.effect.ts"],"names":[],"mappings":";;;AAAA,+CAA8C;AAC9C,mCAAgC;AAEhC,0FAAuF;AACvF,2DAA6C;AAEtC,MAAM,UAAU,GAAG,CACxB,UAAmB,EACnB,WAAmB,EACnB,EAAE,CACF,eAAM,CAAC,QAAQ,CAAC,cAAc,EAAE;IAC9B,UAAU,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE;CACxC,CAAC,CACA,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,yDAA2B,CAAC;IACpD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,IAAA,0BAAM,EAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAE7D,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,qBAAU,CAAC,UAAU,CAAC;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAExC,OAAO,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC9B,CAAC,CAAC,CACH,CAAC;AAhBS,QAAA,UAAU,cAgBnB"}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.uploadFile = void 0;
|
4
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
5
|
+
const effect_1 = require("effect");
|
6
|
+
const file_storage_error_js_1 = require("../../errors/file-storage.error.js");
|
7
|
+
const r2_file_storage_provider_js_1 = require("../providers/r2-file-storage.provider.js");
|
8
|
+
const uploadFile = ({ bucketName, key, data, contentType, }) => effect_1.Effect.withSpan('upload-file', {
|
9
|
+
attributes: { bucketName, key, contentType },
|
10
|
+
})((0, effect_1.pipe)(r2_file_storage_provider_js_1.cloudflareR2StorageProvider, effect_1.Effect.flatMap((provider) => effect_1.Effect.tryPromise({
|
11
|
+
try: () => provider.send(new client_s3_1.PutObjectCommand({
|
12
|
+
Body: data,
|
13
|
+
ContentType: contentType,
|
14
|
+
Key: key,
|
15
|
+
Bucket: bucketName,
|
16
|
+
})),
|
17
|
+
catch: (e) => new file_storage_error_js_1.FileStorageError({ cause: e }),
|
18
|
+
}))));
|
19
|
+
exports.uploadFile = uploadFile;
|
20
|
+
//# sourceMappingURL=upload-file.effect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"upload-file.effect.js","sourceRoot":"","sources":["../../../../src/r2/implementations/upload-file.effect.ts"],"names":[],"mappings":";;;AAAA,kDAAsD;AACtD,mCAAsC;AAEtC,8EAAsE;AACtE,0FAAuF;AAShF,MAAM,UAAU,GAAG,CAAyB,EACjD,UAAU,EACV,GAAG,EACH,IAAI,EACJ,WAAW,GACc,EAAE,EAAE,CAC7B,eAAM,CAAC,QAAQ,CAAC,aAAa,EAAE;IAC7B,UAAU,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE;CAC7C,CAAC,CACA,IAAA,aAAI,EACF,yDAA2B,EAC3B,eAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAC1B,eAAM,CAAC,UAAU,CAAC;IAChB,GAAG,EAAE,GAAG,EAAE,CACR,QAAQ,CAAC,IAAI,CACX,IAAI,4BAAgB,CAAC;QACnB,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,WAAqB;QAClC,GAAG,EAAE,GAAG;QACR,MAAM,EAAE,UAAU;KACnB,CAAC,CACH;IACH,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,wCAAgB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;CACjD,CAAC,CACH,CACF,CACF,CAAC;AA1BS,QAAA,UAAU,cA0BnB"}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.cloudflareR2StorageProvider = void 0;
|
4
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
5
|
+
const effect_1 = require("effect");
|
6
|
+
const getR2Config = (0, effect_1.pipe)(effect_1.Effect.all([
|
7
|
+
effect_1.Config.string('CLOUDFLARE_ACCOUNT_ID'),
|
8
|
+
effect_1.Config.string('R2_DOCUMENTS_ACCESS_KEY_ID'),
|
9
|
+
effect_1.Config.string('R2_DOCUMENTS_SECRET_ACCESS_KEY'),
|
10
|
+
]), effect_1.Effect.map(([cloudflareAccountId, accessKeyId, secretAccessKey]) => ({
|
11
|
+
cloudflareAccountId,
|
12
|
+
accessKeyId,
|
13
|
+
secretAccessKey,
|
14
|
+
})));
|
15
|
+
exports.cloudflareR2StorageProvider = (0, effect_1.pipe)(getR2Config, effect_1.Effect.flatMap((config) => effect_1.Effect.succeed(new client_s3_1.S3Client({
|
16
|
+
region: 'auto',
|
17
|
+
endpoint: `https://${config.cloudflareAccountId}.r2.cloudflarestorage.com`,
|
18
|
+
credentials: {
|
19
|
+
accessKeyId: config.accessKeyId,
|
20
|
+
secretAccessKey: config.secretAccessKey,
|
21
|
+
},
|
22
|
+
}))));
|
23
|
+
//# sourceMappingURL=r2-file-storage.provider.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"r2-file-storage.provider.js","sourceRoot":"","sources":["../../../../src/r2/providers/r2-file-storage.provider.ts"],"names":[],"mappings":";;;AAAA,kDAA8C;AAC9C,mCAA8C;AAE9C,MAAM,WAAW,GAAG,IAAA,aAAI,EACtB,eAAM,CAAC,GAAG,CAAC;IACT,eAAM,CAAC,MAAM,CAAC,uBAAuB,CAAC;IACtC,eAAM,CAAC,MAAM,CAAC,4BAA4B,CAAC;IAC3C,eAAM,CAAC,MAAM,CAAC,gCAAgC,CAAC;CAChD,CAAC,EACF,eAAM,CAAC,GAAG,CAAC,CAAC,CAAC,mBAAmB,EAAE,WAAW,EAAE,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC;IACnE,mBAAmB;IACnB,WAAW;IACX,eAAe;CAChB,CAAC,CAAC,CACJ,CAAC;AAEW,QAAA,2BAA2B,GAAG,IAAA,aAAI,EAC7C,WAAW,EACX,eAAM,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CACxB,eAAM,CAAC,OAAO,CACZ,IAAI,oBAAQ,CAAC;IACX,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,WAAW,MAAM,CAAC,mBAAmB,2BAA2B;IAC1E,WAAW,EAAE;QACX,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,eAAe,EAAE,MAAM,CAAC,eAAe;KACxC;CACF,CAAC,CACH,CACF,CACF,CAAC"}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.CloudflareR2StorageLayerLive = void 0;
|
4
|
+
const effect_1 = require("effect");
|
5
|
+
const file_storage_layer_js_1 = require("../layer/file-storage.layer.js");
|
6
|
+
const index_js_1 = require("./implementations/index.js");
|
7
|
+
const read_as_json_effect_js_1 = require("./implementations/read-as-json.effect.js");
|
8
|
+
const read_as_raw_binary_effect_js_1 = require("./implementations/read-as-raw-binary.effect.js");
|
9
|
+
const read_as_text_effect_js_1 = require("./implementations/read-as-text.effect.js");
|
10
|
+
exports.CloudflareR2StorageLayerLive = effect_1.Layer.succeed(file_storage_layer_js_1.FileStorageLayerContext, file_storage_layer_js_1.FileStorageLayerContext.of({
|
11
|
+
getFileUrl: index_js_1.getFileUrl,
|
12
|
+
uploadFile: index_js_1.uploadFile,
|
13
|
+
readAsText: read_as_text_effect_js_1.readAsText,
|
14
|
+
readAsJson: read_as_json_effect_js_1.readAsJson,
|
15
|
+
readAsRawBinary: read_as_raw_binary_effect_js_1.readAsRawBinary,
|
16
|
+
}));
|
17
|
+
//# sourceMappingURL=r2-file-storage.layer.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"r2-file-storage.layer.js","sourceRoot":"","sources":["../../../src/r2/r2-file-storage.layer.ts"],"names":[],"mappings":";;;AAAA,mCAA+B;AAE/B,0EAAyE;AACzE,yDAAoE;AACpE,qFAAsE;AACtE,iGAAiF;AACjF,qFAAsE;AAEzD,QAAA,4BAA4B,GAAG,cAAK,CAAC,OAAO,CACvD,+CAAuB,EACvB,+CAAuB,CAAC,EAAE,CAAC;IACzB,UAAU,EAAV,qBAAU;IACV,UAAU,EAAV,qBAAU;IACV,UAAU,EAAV,mCAAU;IACV,UAAU,EAAV,mCAAU;IACV,eAAe,EAAf,8CAAe;CAChB,CAAC,CACH,CAAC"}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
declare const FileStorageError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
|
2
|
+
readonly _tag: "file-storage-error";
|
3
|
+
} & Readonly<A>;
|
4
|
+
export declare class FileStorageError extends FileStorageError_base<{
|
5
|
+
cause?: unknown;
|
6
|
+
message?: string;
|
7
|
+
}> {
|
8
|
+
}
|
9
|
+
export {};
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { HttpClientError } from '@effect/platform/HttpClientError';
|
2
|
+
import type { ConfigError, Effect } from 'effect';
|
3
|
+
import { Context } from 'effect';
|
4
|
+
import { HttpClient } from '@effect/platform';
|
5
|
+
import { Scope } from 'effect/Scope';
|
6
|
+
import type { FileStorageError } from '../errors/file-storage.error.js';
|
7
|
+
import type { UploadFileInput } from '../r2/implementations/upload-file.effect.js';
|
8
|
+
export interface FileStorage {
|
9
|
+
readonly getFileUrl: <TBucket extends string>(fileName: string, bucket: TBucket) => Effect.Effect<string, FileStorageError | ConfigError.ConfigError>;
|
10
|
+
readonly readAsRawBinary: <TBucket extends string>(bucketName: TBucket, documentKey: string) => Effect.Effect<ArrayBuffer, ConfigError.ConfigError | HttpClientError | FileStorageError, Scope | HttpClient.HttpClient.Service>;
|
11
|
+
readonly readAsJson: <TBucket extends string, TShape extends Record<string, unknown>>(bucketName: TBucket, documentKey: string) => Effect.Effect<TShape, ConfigError.ConfigError | HttpClientError | FileStorageError, Scope | HttpClient.HttpClient.Service>;
|
12
|
+
readonly readAsText: <TBucket extends string>(bucketName: TBucket, documentKey: string) => Effect.Effect<string, ConfigError.ConfigError | HttpClientError | FileStorageError, Scope | HttpClient.HttpClient.Service>;
|
13
|
+
readonly uploadFile: <TBucket extends string>(input: UploadFileInput<TBucket>) => Effect.Effect<void, FileStorageError | ConfigError.ConfigError>;
|
14
|
+
}
|
15
|
+
export declare const FileStorageLayerContext: Context.Tag<FileStorage, FileStorage>;
|
16
|
+
export declare const FileStorageLayer: {
|
17
|
+
getFileUrl: <TBucket extends string>(bucket: TBucket, fileName: string) => Effect.Effect<string, FileStorageError | ConfigError.ConfigError, FileStorage>;
|
18
|
+
readAsRawBinary: <TBucket extends string>(bucket: TBucket, fileName: string) => Effect.Effect<ArrayBuffer, FileStorageError | ConfigError.ConfigError | HttpClientError, FileStorage | Scope | HttpClient.HttpClient.Service>;
|
19
|
+
readAsJson: <TBucket extends string, TShape extends Record<string, unknown>>(bucket: TBucket, fileName: string) => Effect.Effect<TShape, FileStorageError | ConfigError.ConfigError | HttpClientError, FileStorage | Scope | HttpClient.HttpClient.Service>;
|
20
|
+
readAsText: <TBucket extends string>(bucket: TBucket, fileName: string) => Effect.Effect<string, FileStorageError | ConfigError.ConfigError | HttpClientError, FileStorage | Scope | HttpClient.HttpClient.Service>;
|
21
|
+
uploadFile: <TBucket extends string>(input: UploadFileInput<TBucket>) => Effect.Effect<void, FileStorageError | ConfigError.ConfigError, FileStorage>;
|
22
|
+
};
|
@@ -0,0 +1,4 @@
|
|
1
|
+
import type { S3Client } from '@aws-sdk/client-s3';
|
2
|
+
import { Effect } from 'effect';
|
3
|
+
import { FileStorageError } from '../../errors/file-storage.error.js';
|
4
|
+
export declare const getUrl: <TBucket extends string>(provider: S3Client, bucketName: TBucket, documentKey: TBucket) => Effect.Effect<string, FileStorageError, never>;
|
@@ -0,0 +1,3 @@
|
|
1
|
+
import { HttpClient } from '@effect/platform';
|
2
|
+
import { Effect } from 'effect';
|
3
|
+
export declare const readAsJson: <TBucket extends string, TShape extends Record<string, unknown>>(bucketName: TBucket, documentKey: string) => Effect.Effect<TShape, import("../../errors/file-storage.error.js").FileStorageError | import("effect/ConfigError").ConfigError | import("@effect/platform/HttpClientError").HttpClientError, import("effect/Scope").Scope | HttpClient.HttpClient.Service>;
|
@@ -0,0 +1,3 @@
|
|
1
|
+
import { HttpClient } from '@effect/platform';
|
2
|
+
import { Effect } from 'effect';
|
3
|
+
export declare const readAsRawBinary: <TBucket extends string>(bucketName: TBucket, documentKey: string) => Effect.Effect<ArrayBuffer, import("../../errors/file-storage.error.js").FileStorageError | import("effect/ConfigError").ConfigError | import("@effect/platform/HttpClientError").HttpClientError, import("effect/Scope").Scope | HttpClient.HttpClient.Service>;
|
@@ -0,0 +1,3 @@
|
|
1
|
+
import { HttpClient } from '@effect/platform';
|
2
|
+
import { Effect } from 'effect';
|
3
|
+
export declare const readAsText: <TBucket extends string>(bucketName: TBucket, documentKey: string) => Effect.Effect<string, import("../../errors/file-storage.error.js").FileStorageError | import("effect/ConfigError").ConfigError | import("@effect/platform/HttpClientError").HttpClientError, import("effect/Scope").Scope | HttpClient.HttpClient.Service>;
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { Effect } from 'effect';
|
2
|
+
import { FileStorageError } from '../../errors/file-storage.error.js';
|
3
|
+
export interface UploadFileInput<TBucket extends string> {
|
4
|
+
bucketName: TBucket;
|
5
|
+
key: string;
|
6
|
+
data: Buffer;
|
7
|
+
contentType: string | undefined;
|
8
|
+
}
|
9
|
+
export declare const uploadFile: <TBucket extends string>({ bucketName, key, data, contentType, }: UploadFileInput<TBucket>) => Effect.Effect<import("@aws-sdk/client-s3").PutObjectCommandOutput, FileStorageError | import("effect/ConfigError").ConfigError, never>;
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"tapLayer.effect.js","sourceRoot":"","sources":["../../../src/effects/tapLayer.effect.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,OAA0B,EAC1B,MAA4C,EAC5C,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"file-storage.error.js","sourceRoot":"","sources":["../../../src/errors/file-storage.error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,OAAO,gBAAiB,SAAQ,WAAW,CAAC,oBAAoB,CAGpE;CAAG"}
|
package/esm/index.js
ADDED
package/esm/index.js.map
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,MAAM,CAAC,MAAM,EAAE,CAAC;AAGhB,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAE5B,cAAc,+BAA+B,CAAC"}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { Context } from 'effect';
|
2
|
+
import { tapLayer } from './../effects/tapLayer.effect.js';
|
3
|
+
export const FileStorageLayerContext = Context.GenericTag('file-storage');
|
4
|
+
export const FileStorageLayer = {
|
5
|
+
getFileUrl: (bucket, fileName) => tapLayer(FileStorageLayerContext, ({ getFileUrl }) => getFileUrl(bucket, fileName)),
|
6
|
+
readAsRawBinary: (bucket, fileName) => tapLayer(FileStorageLayerContext, ({ readAsRawBinary }) => readAsRawBinary(bucket, fileName)),
|
7
|
+
readAsJson: (bucket, fileName) => tapLayer(FileStorageLayerContext, ({ readAsJson }) => readAsJson(bucket, fileName)),
|
8
|
+
readAsText: (bucket, fileName) => tapLayer(FileStorageLayerContext, ({ readAsText }) => readAsText(bucket, fileName)),
|
9
|
+
uploadFile: (input) => tapLayer(FileStorageLayerContext, ({ uploadFile }) => uploadFile(input)),
|
10
|
+
};
|
11
|
+
//# sourceMappingURL=file-storage.layer.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"file-storage.layer.js","sourceRoot":"","sources":["../../../src/layer/file-storage.layer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAMjC,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAuC3D,MAAM,CAAC,MAAM,uBAAuB,GAClC,OAAO,CAAC,UAAU,CAAc,cAAc,CAAC,CAAC;AAElD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,UAAU,EAAE,CAAyB,MAAe,EAAE,QAAgB,EAAE,EAAE,CACxE,QAAQ,CAAC,uBAAuB,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CACnD,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAC7B;IACH,eAAe,EAAE,CACf,MAAe,EACf,QAAgB,EAChB,EAAE,CACF,QAAQ,CAAC,uBAAuB,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE,CACxD,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAClC;IACH,UAAU,EAAE,CACV,MAAe,EACf,QAAgB,EAChB,EAAE,CACF,QAAQ,CAAC,uBAAuB,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CACnD,UAAU,CAAkB,MAAM,EAAE,QAAQ,CAAC,CAC9C;IACH,UAAU,EAAE,CAAyB,MAAe,EAAE,QAAgB,EAAE,EAAE,CACxE,QAAQ,CAAC,uBAAuB,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CACnD,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAC7B;IACH,UAAU,EAAE,CAAyB,KAA+B,EAAE,EAAE,CACtE,QAAQ,CAAC,uBAAuB,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;CAC3E,CAAC"}
|
package/esm/package.json
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"type": "module"}
|
@@ -0,0 +1,5 @@
|
|
1
|
+
import { Effect, pipe } from 'effect';
|
2
|
+
import { cloudflareR2StorageProvider } from '../providers/r2-file-storage.provider.js';
|
3
|
+
import { getUrl } from './get-url.effect.js';
|
4
|
+
export const getFileUrl = (bucketName, documentKey) => Effect.withSpan('get-file-url', { attributes: { bucketName, documentKey } })(pipe(cloudflareR2StorageProvider, Effect.flatMap((provider) => getUrl(provider, bucketName, documentKey))));
|
5
|
+
//# sourceMappingURL=get-file-url.effect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"get-file-url.effect.js","sourceRoot":"","sources":["../../../../src/r2/implementations/get-file-url.effect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,UAAmB,EACnB,WAAmB,EACnB,EAAE,CACF,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,CAAC,CAC1E,IAAI,CACF,2BAA2B,EAC3B,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CACxE,CACF,CAAC"}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { GetObjectCommand } from '@aws-sdk/client-s3';
|
2
|
+
import { getSignedUrl as awsGetSignedUrl } from '@aws-sdk/s3-request-presigner';
|
3
|
+
import { Effect } from 'effect';
|
4
|
+
import { FileStorageError } from '../../errors/file-storage.error.js';
|
5
|
+
const oneHourDuration = 60 * 60;
|
6
|
+
export const getUrl = (provider, bucketName, documentKey) => Effect.withSpan('get-url', { attributes: { bucketName, documentKey } })(Effect.tryPromise({
|
7
|
+
try: () => awsGetSignedUrl(provider, new GetObjectCommand({
|
8
|
+
Bucket: bucketName,
|
9
|
+
Key: documentKey,
|
10
|
+
}), {
|
11
|
+
expiresIn: oneHourDuration,
|
12
|
+
}),
|
13
|
+
catch: (e) => new FileStorageError({ cause: e }),
|
14
|
+
}));
|
15
|
+
//# sourceMappingURL=get-url.effect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"get-url.effect.js","sourceRoot":"","sources":["../../../../src/r2/implementations/get-url.effect.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,YAAY,IAAI,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,MAAM,eAAe,GAAG,EAAE,GAAG,EAAE,CAAC;AAEhC,MAAM,CAAC,MAAM,MAAM,GAAG,CACpB,QAAkB,EAClB,UAAmB,EACnB,WAAoB,EACpB,EAAE,CACF,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,CAAC,CACrE,MAAM,CAAC,UAAU,CAAC;IAChB,GAAG,EAAE,GAAG,EAAE,CACR,eAAe,CACb,QAAQ,EACR,IAAI,gBAAgB,CAAC;QACnB,MAAM,EAAE,UAAU;QAClB,GAAG,EAAE,WAAW;KACjB,CAAC,EACF;QACE,SAAS,EAAE,eAAe;KAC3B,CACF;IACH,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,gBAAgB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;CACjD,CAAC,CACH,CAAC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/r2/implementations/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC"}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { HttpClient } from '@effect/platform';
|
2
|
+
import { Effect } from 'effect';
|
3
|
+
import { cloudflareR2StorageProvider } from '../providers/r2-file-storage.provider.js';
|
4
|
+
import { getUrl } from './get-url.effect.js';
|
5
|
+
export const readAsJson = (bucketName, documentKey) => Effect.withSpan('read-as-json', {
|
6
|
+
attributes: { bucketName, documentKey },
|
7
|
+
})(Effect.gen(function* () {
|
8
|
+
const provider = yield* cloudflareR2StorageProvider;
|
9
|
+
const url = yield* getUrl(provider, bucketName, documentKey);
|
10
|
+
const client = yield* HttpClient.HttpClient;
|
11
|
+
const response = yield* client.get(url);
|
12
|
+
const json = yield* response.json;
|
13
|
+
return json;
|
14
|
+
}));
|
15
|
+
//# sourceMappingURL=read-as-json.effect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"read-as-json.effect.js","sourceRoot":"","sources":["../../../../src/r2/implementations/read-as-json.effect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,MAAM,CAAC,MAAM,UAAU,GAAG,CAIxB,UAAmB,EACnB,WAAmB,EACnB,EAAE,CACF,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE;IAC9B,UAAU,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE;CACxC,CAAC,CACA,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,2BAA2B,CAAC;IACpD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAE7D,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAExC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;IAElC,OAAO,IAAc,CAAC;AACxB,CAAC,CAAC,CACH,CAAC"}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { HttpClient } from '@effect/platform';
|
2
|
+
import { Effect } from 'effect';
|
3
|
+
import { cloudflareR2StorageProvider } from '../providers/r2-file-storage.provider.js';
|
4
|
+
import { getUrl } from './get-url.effect.js';
|
5
|
+
export const readAsRawBinary = (bucketName, documentKey) => Effect.withSpan('read-as-raw-binary', {
|
6
|
+
attributes: { bucketName, documentKey },
|
7
|
+
})(Effect.gen(function* () {
|
8
|
+
const provider = yield* cloudflareR2StorageProvider;
|
9
|
+
const url = yield* getUrl(provider, bucketName, documentKey);
|
10
|
+
const client = yield* HttpClient.HttpClient;
|
11
|
+
const response = yield* client.get(url);
|
12
|
+
return yield* response.arrayBuffer;
|
13
|
+
}));
|
14
|
+
//# sourceMappingURL=read-as-raw-binary.effect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"read-as-raw-binary.effect.js","sourceRoot":"","sources":["../../../../src/r2/implementations/read-as-raw-binary.effect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,UAAmB,EACnB,WAAmB,EACnB,EAAE,CACF,MAAM,CAAC,QAAQ,CAAC,oBAAoB,EAAE;IACpC,UAAU,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE;CACxC,CAAC,CACA,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,2BAA2B,CAAC;IACpD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAE7D,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAExC,OAAO,KAAK,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;AACrC,CAAC,CAAC,CACH,CAAC"}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { HttpClient } from '@effect/platform';
|
2
|
+
import { Effect } from 'effect';
|
3
|
+
import { cloudflareR2StorageProvider } from '../providers/r2-file-storage.provider.js';
|
4
|
+
import { getUrl } from './get-url.effect.js';
|
5
|
+
export const readAsText = (bucketName, documentKey) => Effect.withSpan('read-as-text', {
|
6
|
+
attributes: { bucketName, documentKey },
|
7
|
+
})(Effect.gen(function* () {
|
8
|
+
const provider = yield* cloudflareR2StorageProvider;
|
9
|
+
const url = yield* getUrl(provider, bucketName, documentKey);
|
10
|
+
const client = yield* HttpClient.HttpClient;
|
11
|
+
const response = yield* client.get(url);
|
12
|
+
return yield* response.text;
|
13
|
+
}));
|
14
|
+
//# sourceMappingURL=read-as-text.effect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"read-as-text.effect.js","sourceRoot":"","sources":["../../../../src/r2/implementations/read-as-text.effect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,UAAmB,EACnB,WAAmB,EACnB,EAAE,CACF,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE;IAC9B,UAAU,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE;CACxC,CAAC,CACA,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,2BAA2B,CAAC;IACpD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAE7D,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAExC,OAAO,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC9B,CAAC,CAAC,CACH,CAAC"}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { PutObjectCommand } from '@aws-sdk/client-s3';
|
2
|
+
import { Effect, pipe } from 'effect';
|
3
|
+
import { FileStorageError } from '../../errors/file-storage.error.js';
|
4
|
+
import { cloudflareR2StorageProvider } from '../providers/r2-file-storage.provider.js';
|
5
|
+
export const uploadFile = ({ bucketName, key, data, contentType, }) => Effect.withSpan('upload-file', {
|
6
|
+
attributes: { bucketName, key, contentType },
|
7
|
+
})(pipe(cloudflareR2StorageProvider, Effect.flatMap((provider) => Effect.tryPromise({
|
8
|
+
try: () => provider.send(new PutObjectCommand({
|
9
|
+
Body: data,
|
10
|
+
ContentType: contentType,
|
11
|
+
Key: key,
|
12
|
+
Bucket: bucketName,
|
13
|
+
})),
|
14
|
+
catch: (e) => new FileStorageError({ cause: e }),
|
15
|
+
}))));
|
16
|
+
//# sourceMappingURL=upload-file.effect.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"upload-file.effect.js","sourceRoot":"","sources":["../../../../src/r2/implementations/upload-file.effect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AASvF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAyB,EACjD,UAAU,EACV,GAAG,EACH,IAAI,EACJ,WAAW,GACc,EAAE,EAAE,CAC7B,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE;IAC7B,UAAU,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE;CAC7C,CAAC,CACA,IAAI,CACF,2BAA2B,EAC3B,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAC1B,MAAM,CAAC,UAAU,CAAC;IAChB,GAAG,EAAE,GAAG,EAAE,CACR,QAAQ,CAAC,IAAI,CACX,IAAI,gBAAgB,CAAC;QACnB,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,WAAqB;QAClC,GAAG,EAAE,GAAG;QACR,MAAM,EAAE,UAAU;KACnB,CAAC,CACH;IACH,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,gBAAgB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;CACjD,CAAC,CACH,CACF,CACF,CAAC"}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
2
|
+
import { Config, Effect, pipe } from 'effect';
|
3
|
+
const getR2Config = pipe(Effect.all([
|
4
|
+
Config.string('CLOUDFLARE_ACCOUNT_ID'),
|
5
|
+
Config.string('R2_DOCUMENTS_ACCESS_KEY_ID'),
|
6
|
+
Config.string('R2_DOCUMENTS_SECRET_ACCESS_KEY'),
|
7
|
+
]), Effect.map(([cloudflareAccountId, accessKeyId, secretAccessKey]) => ({
|
8
|
+
cloudflareAccountId,
|
9
|
+
accessKeyId,
|
10
|
+
secretAccessKey,
|
11
|
+
})));
|
12
|
+
export const cloudflareR2StorageProvider = pipe(getR2Config, Effect.flatMap((config) => Effect.succeed(new S3Client({
|
13
|
+
region: 'auto',
|
14
|
+
endpoint: `https://${config.cloudflareAccountId}.r2.cloudflarestorage.com`,
|
15
|
+
credentials: {
|
16
|
+
accessKeyId: config.accessKeyId,
|
17
|
+
secretAccessKey: config.secretAccessKey,
|
18
|
+
},
|
19
|
+
}))));
|
20
|
+
//# sourceMappingURL=r2-file-storage.provider.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"r2-file-storage.provider.js","sourceRoot":"","sources":["../../../../src/r2/providers/r2-file-storage.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9C,MAAM,WAAW,GAAG,IAAI,CACtB,MAAM,CAAC,GAAG,CAAC;IACT,MAAM,CAAC,MAAM,CAAC,uBAAuB,CAAC;IACtC,MAAM,CAAC,MAAM,CAAC,4BAA4B,CAAC;IAC3C,MAAM,CAAC,MAAM,CAAC,gCAAgC,CAAC;CAChD,CAAC,EACF,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,mBAAmB,EAAE,WAAW,EAAE,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC;IACnE,mBAAmB;IACnB,WAAW;IACX,eAAe;CAChB,CAAC,CAAC,CACJ,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,IAAI,CAC7C,WAAW,EACX,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CACxB,MAAM,CAAC,OAAO,CACZ,IAAI,QAAQ,CAAC;IACX,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,WAAW,MAAM,CAAC,mBAAmB,2BAA2B;IAC1E,WAAW,EAAE;QACX,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,eAAe,EAAE,MAAM,CAAC,eAAe;KACxC;CACF,CAAC,CACH,CACF,CACF,CAAC"}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { Layer } from 'effect';
|
2
|
+
import { FileStorageLayerContext } from '../layer/file-storage.layer.js';
|
3
|
+
import { getFileUrl, uploadFile } from './implementations/index.js';
|
4
|
+
import { readAsJson } from './implementations/read-as-json.effect.js';
|
5
|
+
import { readAsRawBinary } from './implementations/read-as-raw-binary.effect.js';
|
6
|
+
import { readAsText } from './implementations/read-as-text.effect.js';
|
7
|
+
export const CloudflareR2StorageLayerLive = Layer.succeed(FileStorageLayerContext, FileStorageLayerContext.of({
|
8
|
+
getFileUrl,
|
9
|
+
uploadFile,
|
10
|
+
readAsText,
|
11
|
+
readAsJson,
|
12
|
+
readAsRawBinary,
|
13
|
+
}));
|
14
|
+
//# sourceMappingURL=r2-file-storage.layer.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"r2-file-storage.layer.js","sourceRoot":"","sources":["../../../src/r2/r2-file-storage.layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAEtE,MAAM,CAAC,MAAM,4BAA4B,GAAG,KAAK,CAAC,OAAO,CACvD,uBAAuB,EACvB,uBAAuB,CAAC,EAAE,CAAC;IACzB,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,eAAe;CAChB,CAAC,CACH,CAAC"}
|
package/package.json
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
{
|
2
|
+
"name": "effect-cloudflare-r2-layer",
|
3
|
+
"version": "1.0.1",
|
4
|
+
"author": "jpb06 <jp.bois.06@outlook.fr>",
|
5
|
+
"description": "An effect layer to interact with Cloudware R2 storage service",
|
6
|
+
"keywords": [
|
7
|
+
"effect"
|
8
|
+
],
|
9
|
+
"main": "./cjs/index.js",
|
10
|
+
"module": "./esm/index.js",
|
11
|
+
"type": "module",
|
12
|
+
"exports": {
|
13
|
+
".": {
|
14
|
+
"require": {
|
15
|
+
"default": "./cjs/index.js",
|
16
|
+
"types": "./dts/cjs/index.d.ts"
|
17
|
+
},
|
18
|
+
"import": {
|
19
|
+
"default": "./esm/index.js",
|
20
|
+
"types": "./dts/esm/index.d.ts"
|
21
|
+
}
|
22
|
+
}
|
23
|
+
},
|
24
|
+
"engines": {
|
25
|
+
"node": "20.x"
|
26
|
+
},
|
27
|
+
"scripts": {
|
28
|
+
"update-deps": "bunx npm-check-updates --root --format group -i",
|
29
|
+
"copy-package": "copyfiles package.json ./dist/",
|
30
|
+
"copy-readme": "copyfiles README.md ./dist/",
|
31
|
+
"build": "del-cli ./dist && bun build-esm && bun build-cjs",
|
32
|
+
"build-esm": "tsc --project tsconfig.esm.json",
|
33
|
+
"build-cjs": "tsc --project tsconfig.cjs.json",
|
34
|
+
"postbuild-cjs": "echo '{\"type\": \"commonjs\"}' > dist/cjs/package.json",
|
35
|
+
"postbuild-esm": "echo '{\"type\": \"module\"}' > dist/esm/package.json",
|
36
|
+
"postbuild": "bun run copy-package && bun run copy-readme",
|
37
|
+
"format": "biome format --write ./src",
|
38
|
+
"format-ci": "biome format ./src",
|
39
|
+
"lint": "biome lint ./src",
|
40
|
+
"type-check": "tsc --noEmit",
|
41
|
+
"sync-icons": "bun generateReadmeIcons -h 50"
|
42
|
+
},
|
43
|
+
"dependencies": {
|
44
|
+
"@aws-sdk/client-s3": "^3.658.1",
|
45
|
+
"@aws-sdk/s3-request-presigner": "^3.658.1",
|
46
|
+
"@effect/platform": "^0.66.2",
|
47
|
+
"dotenv": "^16.4.5",
|
48
|
+
"effect": "^3.8.4",
|
49
|
+
"effect-errors": "^1.7.11"
|
50
|
+
},
|
51
|
+
"peerDependencies": {
|
52
|
+
"typescript": "^5.0.0"
|
53
|
+
},
|
54
|
+
"devDependencies": {
|
55
|
+
"@biomejs/biome": "^1.9.2",
|
56
|
+
"@types/bun": "latest",
|
57
|
+
"@types/fs-extra": "^11.0.4",
|
58
|
+
"copyfiles": "^2.4.1",
|
59
|
+
"del-cli": "^5.1.0",
|
60
|
+
"fs-extra": "^11.2.0",
|
61
|
+
"readme-package-icons": "^1.1.15",
|
62
|
+
"tsx": "^4.19.1"
|
63
|
+
}
|
64
|
+
}
|