@magnet-cms/adapter-storage-r2 1.0.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/dist/index.cjs ADDED
@@ -0,0 +1,253 @@
1
+ 'use strict';
2
+
3
+ var crypto = require('crypto');
4
+ var clientS3 = require('@aws-sdk/client-s3');
5
+ var s3RequestPresigner = require('@aws-sdk/s3-request-presigner');
6
+ var common = require('@magnet-cms/common');
7
+
8
+ // src/r2-storage.adapter.ts
9
+ async function streamToBuffer(stream) {
10
+ const chunks = [];
11
+ for await (const chunk of stream) {
12
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
13
+ }
14
+ return Buffer.concat(chunks);
15
+ }
16
+ function generateFilename(originalFilename) {
17
+ const ext = originalFilename.split(".").pop() || "";
18
+ const uuid = crypto.randomUUID();
19
+ return ext ? `${uuid}.${ext}` : uuid;
20
+ }
21
+ var R2StorageAdapter = class _R2StorageAdapter extends common.StorageAdapter {
22
+ client;
23
+ config;
24
+ bucket;
25
+ constructor(config) {
26
+ super();
27
+ this.config = config;
28
+ this.bucket = config.bucket;
29
+ const endpoint = config.endpoint || `https://${config.accountId}.r2.cloudflarestorage.com`;
30
+ this.client = new clientS3.S3Client({
31
+ region: config.region || "auto",
32
+ credentials: {
33
+ accessKeyId: config.accessKeyId,
34
+ secretAccessKey: config.secretAccessKey
35
+ },
36
+ endpoint,
37
+ forcePathStyle: config.forcePathStyle ?? true
38
+ });
39
+ }
40
+ getKey(path) {
41
+ return path;
42
+ }
43
+ getPublicUrl(key) {
44
+ if (this.config.publicUrl) {
45
+ return `${this.config.publicUrl.replace(/\/$/, "")}/${key}`;
46
+ }
47
+ throw new Error(
48
+ "R2 storage requires publicUrl in config for public file URLs"
49
+ );
50
+ }
51
+ async initialize() {
52
+ await this.client.send(
53
+ new clientS3.ListObjectsV2Command({
54
+ Bucket: this.bucket,
55
+ MaxKeys: 1
56
+ })
57
+ );
58
+ }
59
+ async upload(file, originalFilename, options) {
60
+ const buffer = Buffer.isBuffer(file) ? file : await streamToBuffer(file);
61
+ const filename = options?.filename || generateFilename(originalFilename);
62
+ const folder = options?.folder || "";
63
+ const key = folder ? `${folder}/${filename}` : filename;
64
+ await this.client.send(
65
+ new clientS3.PutObjectCommand({
66
+ Bucket: this.bucket,
67
+ Key: key,
68
+ Body: buffer,
69
+ ContentType: options?.mimeType || "application/octet-stream"
70
+ })
71
+ );
72
+ const url = this.getPublicUrl(key);
73
+ return {
74
+ id: crypto.randomUUID(),
75
+ filename,
76
+ originalFilename,
77
+ mimeType: options?.mimeType || "application/octet-stream",
78
+ size: buffer.length,
79
+ path: key,
80
+ url,
81
+ folder: folder || void 0,
82
+ tags: options?.tags,
83
+ alt: options?.alt,
84
+ customFields: options?.customFields,
85
+ createdAt: /* @__PURE__ */ new Date(),
86
+ updatedAt: /* @__PURE__ */ new Date()
87
+ };
88
+ }
89
+ async uploadChunked(stream, originalFilename, _totalSize, options) {
90
+ const buffer = await streamToBuffer(stream);
91
+ return this.upload(buffer, originalFilename, options);
92
+ }
93
+ async delete(path) {
94
+ const key = this.getKey(path);
95
+ try {
96
+ await this.client.send(
97
+ new clientS3.DeleteObjectsCommand({
98
+ Bucket: this.bucket,
99
+ Delete: { Objects: [{ Key: key }] }
100
+ })
101
+ );
102
+ return true;
103
+ } catch {
104
+ return false;
105
+ }
106
+ }
107
+ async deleteMany(paths) {
108
+ const keys = paths.map((p) => ({ Key: this.getKey(p) }));
109
+ try {
110
+ await this.client.send(
111
+ new clientS3.DeleteObjectsCommand({
112
+ Bucket: this.bucket,
113
+ Delete: { Objects: keys }
114
+ })
115
+ );
116
+ return { deleted: paths.length, failed: [] };
117
+ } catch {
118
+ return { deleted: 0, failed: paths };
119
+ }
120
+ }
121
+ getUrl(path, _transform) {
122
+ return this.getPublicUrl(this.getKey(path));
123
+ }
124
+ async getStream(path) {
125
+ const key = this.getKey(path);
126
+ const response = await this.client.send(
127
+ new clientS3.GetObjectCommand({ Bucket: this.bucket, Key: key })
128
+ );
129
+ if (!response.Body) {
130
+ throw new Error(`Failed to get object: ${path}`);
131
+ }
132
+ return response.Body;
133
+ }
134
+ async getBuffer(path) {
135
+ const stream = await this.getStream(path);
136
+ return streamToBuffer(stream);
137
+ }
138
+ async exists(path) {
139
+ const key = this.getKey(path);
140
+ try {
141
+ await this.client.send(
142
+ new clientS3.HeadObjectCommand({ Bucket: this.bucket, Key: key })
143
+ );
144
+ return true;
145
+ } catch {
146
+ return false;
147
+ }
148
+ }
149
+ async transform(path, _options) {
150
+ return this.getBuffer(path);
151
+ }
152
+ async move(path, newPath) {
153
+ const srcKey = this.getKey(path);
154
+ const destKey = this.getKey(newPath);
155
+ await this.client.send(
156
+ new clientS3.CopyObjectCommand({
157
+ Bucket: this.bucket,
158
+ CopySource: `${this.bucket}/${srcKey}`,
159
+ Key: destKey
160
+ })
161
+ );
162
+ await this.delete(path);
163
+ const filename = newPath.split("/").pop() || newPath;
164
+ return {
165
+ id: crypto.randomUUID(),
166
+ filename,
167
+ originalFilename: filename,
168
+ mimeType: "application/octet-stream",
169
+ size: 0,
170
+ path: destKey,
171
+ url: this.getPublicUrl(destKey),
172
+ createdAt: /* @__PURE__ */ new Date(),
173
+ updatedAt: /* @__PURE__ */ new Date()
174
+ };
175
+ }
176
+ async copy(path, newPath) {
177
+ const srcKey = this.getKey(path);
178
+ const destKey = this.getKey(newPath);
179
+ await this.client.send(
180
+ new clientS3.CopyObjectCommand({
181
+ Bucket: this.bucket,
182
+ CopySource: `${this.bucket}/${srcKey}`,
183
+ Key: destKey
184
+ })
185
+ );
186
+ const filename = newPath.split("/").pop() || newPath;
187
+ return {
188
+ id: crypto.randomUUID(),
189
+ filename,
190
+ originalFilename: filename,
191
+ mimeType: "application/octet-stream",
192
+ size: 0,
193
+ path: destKey,
194
+ url: this.getPublicUrl(destKey),
195
+ createdAt: /* @__PURE__ */ new Date(),
196
+ updatedAt: /* @__PURE__ */ new Date()
197
+ };
198
+ }
199
+ async signedUrl(path, expiresIn = 3600) {
200
+ const key = this.getKey(path);
201
+ return s3RequestPresigner.getSignedUrl(
202
+ this.client,
203
+ new clientS3.GetObjectCommand({ Bucket: this.bucket, Key: key }),
204
+ { expiresIn }
205
+ );
206
+ }
207
+ /** Environment variables used by this adapter */
208
+ static envVars = [
209
+ { name: "R2_BUCKET", required: true, description: "R2 bucket name" },
210
+ {
211
+ name: "R2_ACCOUNT_ID",
212
+ required: true,
213
+ description: "Cloudflare account ID"
214
+ },
215
+ {
216
+ name: "R2_ACCESS_KEY_ID",
217
+ required: true,
218
+ description: "R2 access key ID"
219
+ },
220
+ {
221
+ name: "R2_SECRET_ACCESS_KEY",
222
+ required: true,
223
+ description: "R2 secret access key"
224
+ },
225
+ {
226
+ name: "R2_PUBLIC_URL",
227
+ required: false,
228
+ description: "Public URL for R2 bucket"
229
+ }
230
+ ];
231
+ /**
232
+ * Create a configured storage provider for MagnetModule.forRoot().
233
+ * Auto-resolves config values from environment variables if not provided.
234
+ */
235
+ static forRoot(config) {
236
+ const resolvedConfig = {
237
+ bucket: config?.bucket ?? process.env.R2_BUCKET ?? "",
238
+ region: config?.region ?? "auto",
239
+ accountId: config?.accountId ?? process.env.R2_ACCOUNT_ID ?? "",
240
+ accessKeyId: config?.accessKeyId ?? process.env.R2_ACCESS_KEY_ID ?? "",
241
+ secretAccessKey: config?.secretAccessKey ?? process.env.R2_SECRET_ACCESS_KEY ?? "",
242
+ publicUrl: config?.publicUrl ?? process.env.R2_PUBLIC_URL
243
+ };
244
+ return {
245
+ type: "storage",
246
+ adapter: new _R2StorageAdapter(resolvedConfig),
247
+ config: resolvedConfig,
248
+ envVars: _R2StorageAdapter.envVars
249
+ };
250
+ }
251
+ };
252
+
253
+ exports.R2StorageAdapter = R2StorageAdapter;
@@ -0,0 +1,54 @@
1
+ import { Readable } from 'node:stream';
2
+ import { StorageAdapter, R2StorageConfig, UploadOptions, UploadResult, TransformOptions, EnvVarRequirement, StorageMagnetProvider } from '@magnet-cms/common';
3
+
4
+ /**
5
+ * R2 Storage adapter for Magnet CMS.
6
+ * Uses Cloudflare R2 (S3-compatible) for file storage.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { R2StorageAdapter } from '@magnet-cms/adapter-storage-r2'
11
+ *
12
+ * const storage = new R2StorageAdapter({
13
+ * bucket: 'my-bucket',
14
+ * region: 'auto',
15
+ * accountId: process.env.CLOUDFLARE_ACCOUNT_ID,
16
+ * accessKeyId: process.env.R2_ACCESS_KEY_ID,
17
+ * secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
18
+ * publicUrl: 'https://pub-xxx.r2.dev',
19
+ * })
20
+ * ```
21
+ */
22
+ declare class R2StorageAdapter extends StorageAdapter {
23
+ private readonly client;
24
+ private readonly config;
25
+ private readonly bucket;
26
+ constructor(config: R2StorageConfig);
27
+ private getKey;
28
+ private getPublicUrl;
29
+ initialize(): Promise<void>;
30
+ upload(file: Buffer | Readable, originalFilename: string, options?: UploadOptions): Promise<UploadResult>;
31
+ uploadChunked(stream: Readable, originalFilename: string, _totalSize: number, options?: UploadOptions): Promise<UploadResult>;
32
+ delete(path: string): Promise<boolean>;
33
+ deleteMany(paths: string[]): Promise<{
34
+ deleted: number;
35
+ failed: string[];
36
+ }>;
37
+ getUrl(path: string, _transform?: TransformOptions): string;
38
+ getStream(path: string): Promise<Readable>;
39
+ getBuffer(path: string): Promise<Buffer>;
40
+ exists(path: string): Promise<boolean>;
41
+ transform(path: string, _options: TransformOptions): Promise<Buffer>;
42
+ move(path: string, newPath: string): Promise<UploadResult>;
43
+ copy(path: string, newPath: string): Promise<UploadResult>;
44
+ signedUrl(path: string, expiresIn?: number): Promise<string>;
45
+ /** Environment variables used by this adapter */
46
+ static readonly envVars: EnvVarRequirement[];
47
+ /**
48
+ * Create a configured storage provider for MagnetModule.forRoot().
49
+ * Auto-resolves config values from environment variables if not provided.
50
+ */
51
+ static forRoot(config?: Partial<R2StorageConfig>): StorageMagnetProvider;
52
+ }
53
+
54
+ export { R2StorageAdapter };
@@ -0,0 +1,54 @@
1
+ import { Readable } from 'node:stream';
2
+ import { StorageAdapter, R2StorageConfig, UploadOptions, UploadResult, TransformOptions, EnvVarRequirement, StorageMagnetProvider } from '@magnet-cms/common';
3
+
4
+ /**
5
+ * R2 Storage adapter for Magnet CMS.
6
+ * Uses Cloudflare R2 (S3-compatible) for file storage.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { R2StorageAdapter } from '@magnet-cms/adapter-storage-r2'
11
+ *
12
+ * const storage = new R2StorageAdapter({
13
+ * bucket: 'my-bucket',
14
+ * region: 'auto',
15
+ * accountId: process.env.CLOUDFLARE_ACCOUNT_ID,
16
+ * accessKeyId: process.env.R2_ACCESS_KEY_ID,
17
+ * secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
18
+ * publicUrl: 'https://pub-xxx.r2.dev',
19
+ * })
20
+ * ```
21
+ */
22
+ declare class R2StorageAdapter extends StorageAdapter {
23
+ private readonly client;
24
+ private readonly config;
25
+ private readonly bucket;
26
+ constructor(config: R2StorageConfig);
27
+ private getKey;
28
+ private getPublicUrl;
29
+ initialize(): Promise<void>;
30
+ upload(file: Buffer | Readable, originalFilename: string, options?: UploadOptions): Promise<UploadResult>;
31
+ uploadChunked(stream: Readable, originalFilename: string, _totalSize: number, options?: UploadOptions): Promise<UploadResult>;
32
+ delete(path: string): Promise<boolean>;
33
+ deleteMany(paths: string[]): Promise<{
34
+ deleted: number;
35
+ failed: string[];
36
+ }>;
37
+ getUrl(path: string, _transform?: TransformOptions): string;
38
+ getStream(path: string): Promise<Readable>;
39
+ getBuffer(path: string): Promise<Buffer>;
40
+ exists(path: string): Promise<boolean>;
41
+ transform(path: string, _options: TransformOptions): Promise<Buffer>;
42
+ move(path: string, newPath: string): Promise<UploadResult>;
43
+ copy(path: string, newPath: string): Promise<UploadResult>;
44
+ signedUrl(path: string, expiresIn?: number): Promise<string>;
45
+ /** Environment variables used by this adapter */
46
+ static readonly envVars: EnvVarRequirement[];
47
+ /**
48
+ * Create a configured storage provider for MagnetModule.forRoot().
49
+ * Auto-resolves config values from environment variables if not provided.
50
+ */
51
+ static forRoot(config?: Partial<R2StorageConfig>): StorageMagnetProvider;
52
+ }
53
+
54
+ export { R2StorageAdapter };
package/dist/index.js ADDED
@@ -0,0 +1,251 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { S3Client, ListObjectsV2Command, PutObjectCommand, DeleteObjectsCommand, GetObjectCommand, HeadObjectCommand, CopyObjectCommand } from '@aws-sdk/client-s3';
3
+ import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
4
+ import { StorageAdapter } from '@magnet-cms/common';
5
+
6
+ // src/r2-storage.adapter.ts
7
+ async function streamToBuffer(stream) {
8
+ const chunks = [];
9
+ for await (const chunk of stream) {
10
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
11
+ }
12
+ return Buffer.concat(chunks);
13
+ }
14
+ function generateFilename(originalFilename) {
15
+ const ext = originalFilename.split(".").pop() || "";
16
+ const uuid = randomUUID();
17
+ return ext ? `${uuid}.${ext}` : uuid;
18
+ }
19
+ var R2StorageAdapter = class _R2StorageAdapter extends StorageAdapter {
20
+ client;
21
+ config;
22
+ bucket;
23
+ constructor(config) {
24
+ super();
25
+ this.config = config;
26
+ this.bucket = config.bucket;
27
+ const endpoint = config.endpoint || `https://${config.accountId}.r2.cloudflarestorage.com`;
28
+ this.client = new S3Client({
29
+ region: config.region || "auto",
30
+ credentials: {
31
+ accessKeyId: config.accessKeyId,
32
+ secretAccessKey: config.secretAccessKey
33
+ },
34
+ endpoint,
35
+ forcePathStyle: config.forcePathStyle ?? true
36
+ });
37
+ }
38
+ getKey(path) {
39
+ return path;
40
+ }
41
+ getPublicUrl(key) {
42
+ if (this.config.publicUrl) {
43
+ return `${this.config.publicUrl.replace(/\/$/, "")}/${key}`;
44
+ }
45
+ throw new Error(
46
+ "R2 storage requires publicUrl in config for public file URLs"
47
+ );
48
+ }
49
+ async initialize() {
50
+ await this.client.send(
51
+ new ListObjectsV2Command({
52
+ Bucket: this.bucket,
53
+ MaxKeys: 1
54
+ })
55
+ );
56
+ }
57
+ async upload(file, originalFilename, options) {
58
+ const buffer = Buffer.isBuffer(file) ? file : await streamToBuffer(file);
59
+ const filename = options?.filename || generateFilename(originalFilename);
60
+ const folder = options?.folder || "";
61
+ const key = folder ? `${folder}/${filename}` : filename;
62
+ await this.client.send(
63
+ new PutObjectCommand({
64
+ Bucket: this.bucket,
65
+ Key: key,
66
+ Body: buffer,
67
+ ContentType: options?.mimeType || "application/octet-stream"
68
+ })
69
+ );
70
+ const url = this.getPublicUrl(key);
71
+ return {
72
+ id: randomUUID(),
73
+ filename,
74
+ originalFilename,
75
+ mimeType: options?.mimeType || "application/octet-stream",
76
+ size: buffer.length,
77
+ path: key,
78
+ url,
79
+ folder: folder || void 0,
80
+ tags: options?.tags,
81
+ alt: options?.alt,
82
+ customFields: options?.customFields,
83
+ createdAt: /* @__PURE__ */ new Date(),
84
+ updatedAt: /* @__PURE__ */ new Date()
85
+ };
86
+ }
87
+ async uploadChunked(stream, originalFilename, _totalSize, options) {
88
+ const buffer = await streamToBuffer(stream);
89
+ return this.upload(buffer, originalFilename, options);
90
+ }
91
+ async delete(path) {
92
+ const key = this.getKey(path);
93
+ try {
94
+ await this.client.send(
95
+ new DeleteObjectsCommand({
96
+ Bucket: this.bucket,
97
+ Delete: { Objects: [{ Key: key }] }
98
+ })
99
+ );
100
+ return true;
101
+ } catch {
102
+ return false;
103
+ }
104
+ }
105
+ async deleteMany(paths) {
106
+ const keys = paths.map((p) => ({ Key: this.getKey(p) }));
107
+ try {
108
+ await this.client.send(
109
+ new DeleteObjectsCommand({
110
+ Bucket: this.bucket,
111
+ Delete: { Objects: keys }
112
+ })
113
+ );
114
+ return { deleted: paths.length, failed: [] };
115
+ } catch {
116
+ return { deleted: 0, failed: paths };
117
+ }
118
+ }
119
+ getUrl(path, _transform) {
120
+ return this.getPublicUrl(this.getKey(path));
121
+ }
122
+ async getStream(path) {
123
+ const key = this.getKey(path);
124
+ const response = await this.client.send(
125
+ new GetObjectCommand({ Bucket: this.bucket, Key: key })
126
+ );
127
+ if (!response.Body) {
128
+ throw new Error(`Failed to get object: ${path}`);
129
+ }
130
+ return response.Body;
131
+ }
132
+ async getBuffer(path) {
133
+ const stream = await this.getStream(path);
134
+ return streamToBuffer(stream);
135
+ }
136
+ async exists(path) {
137
+ const key = this.getKey(path);
138
+ try {
139
+ await this.client.send(
140
+ new HeadObjectCommand({ Bucket: this.bucket, Key: key })
141
+ );
142
+ return true;
143
+ } catch {
144
+ return false;
145
+ }
146
+ }
147
+ async transform(path, _options) {
148
+ return this.getBuffer(path);
149
+ }
150
+ async move(path, newPath) {
151
+ const srcKey = this.getKey(path);
152
+ const destKey = this.getKey(newPath);
153
+ await this.client.send(
154
+ new CopyObjectCommand({
155
+ Bucket: this.bucket,
156
+ CopySource: `${this.bucket}/${srcKey}`,
157
+ Key: destKey
158
+ })
159
+ );
160
+ await this.delete(path);
161
+ const filename = newPath.split("/").pop() || newPath;
162
+ return {
163
+ id: randomUUID(),
164
+ filename,
165
+ originalFilename: filename,
166
+ mimeType: "application/octet-stream",
167
+ size: 0,
168
+ path: destKey,
169
+ url: this.getPublicUrl(destKey),
170
+ createdAt: /* @__PURE__ */ new Date(),
171
+ updatedAt: /* @__PURE__ */ new Date()
172
+ };
173
+ }
174
+ async copy(path, newPath) {
175
+ const srcKey = this.getKey(path);
176
+ const destKey = this.getKey(newPath);
177
+ await this.client.send(
178
+ new CopyObjectCommand({
179
+ Bucket: this.bucket,
180
+ CopySource: `${this.bucket}/${srcKey}`,
181
+ Key: destKey
182
+ })
183
+ );
184
+ const filename = newPath.split("/").pop() || newPath;
185
+ return {
186
+ id: randomUUID(),
187
+ filename,
188
+ originalFilename: filename,
189
+ mimeType: "application/octet-stream",
190
+ size: 0,
191
+ path: destKey,
192
+ url: this.getPublicUrl(destKey),
193
+ createdAt: /* @__PURE__ */ new Date(),
194
+ updatedAt: /* @__PURE__ */ new Date()
195
+ };
196
+ }
197
+ async signedUrl(path, expiresIn = 3600) {
198
+ const key = this.getKey(path);
199
+ return getSignedUrl(
200
+ this.client,
201
+ new GetObjectCommand({ Bucket: this.bucket, Key: key }),
202
+ { expiresIn }
203
+ );
204
+ }
205
+ /** Environment variables used by this adapter */
206
+ static envVars = [
207
+ { name: "R2_BUCKET", required: true, description: "R2 bucket name" },
208
+ {
209
+ name: "R2_ACCOUNT_ID",
210
+ required: true,
211
+ description: "Cloudflare account ID"
212
+ },
213
+ {
214
+ name: "R2_ACCESS_KEY_ID",
215
+ required: true,
216
+ description: "R2 access key ID"
217
+ },
218
+ {
219
+ name: "R2_SECRET_ACCESS_KEY",
220
+ required: true,
221
+ description: "R2 secret access key"
222
+ },
223
+ {
224
+ name: "R2_PUBLIC_URL",
225
+ required: false,
226
+ description: "Public URL for R2 bucket"
227
+ }
228
+ ];
229
+ /**
230
+ * Create a configured storage provider for MagnetModule.forRoot().
231
+ * Auto-resolves config values from environment variables if not provided.
232
+ */
233
+ static forRoot(config) {
234
+ const resolvedConfig = {
235
+ bucket: config?.bucket ?? process.env.R2_BUCKET ?? "",
236
+ region: config?.region ?? "auto",
237
+ accountId: config?.accountId ?? process.env.R2_ACCOUNT_ID ?? "",
238
+ accessKeyId: config?.accessKeyId ?? process.env.R2_ACCESS_KEY_ID ?? "",
239
+ secretAccessKey: config?.secretAccessKey ?? process.env.R2_SECRET_ACCESS_KEY ?? "",
240
+ publicUrl: config?.publicUrl ?? process.env.R2_PUBLIC_URL
241
+ };
242
+ return {
243
+ type: "storage",
244
+ adapter: new _R2StorageAdapter(resolvedConfig),
245
+ config: resolvedConfig,
246
+ envVars: _R2StorageAdapter.envVars
247
+ };
248
+ }
249
+ };
250
+
251
+ export { R2StorageAdapter };
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@magnet-cms/adapter-storage-r2",
3
+ "version": "1.0.0",
4
+ "description": "Cloudflare R2 storage adapter for Magnet CMS",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "exports": {
9
+ "import": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "require": {
14
+ "types": "./dist/index.d.cts",
15
+ "default": "./dist/index.cjs"
16
+ }
17
+ },
18
+ "types": "./dist/index.d.ts",
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "scripts": {
23
+ "build:dev": "tsup --watch",
24
+ "build": "tsup"
25
+ },
26
+ "devDependencies": {
27
+ "@magnet-cms/common": "workspace:*",
28
+ "@repo/biome": "workspace:*",
29
+ "@repo/tsup": "workspace:*",
30
+ "@repo/typescript-config": "workspace:*",
31
+ "@aws-sdk/client-s3": "^3.700.0",
32
+ "@aws-sdk/s3-request-presigner": "^3.700.0"
33
+ },
34
+ "peerDependencies": {
35
+ "@magnet-cms/common": "^0.1.0",
36
+ "@aws-sdk/client-s3": "^3.0.0",
37
+ "@aws-sdk/s3-request-presigner": "^3.0.0"
38
+ }
39
+ }