@aphexcms/storage-s3 0.1.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.
@@ -0,0 +1,125 @@
1
+ import type { StorageAdapter, StorageProvider, StorageConfig, UploadFileData, StorageFile } from '@aphexcms/cms-core/server';
2
+ export interface S3StorageConfig extends StorageConfig {
3
+ options: {
4
+ bucket: string;
5
+ endpoint: string;
6
+ accessKeyId: string;
7
+ secretAccessKey: string;
8
+ region?: string;
9
+ publicUrl?: string;
10
+ };
11
+ }
12
+ /**
13
+ * S3-Compatible Storage Adapter
14
+ *
15
+ * This adapter uses the S3-compatible API to store files in any S3-compatible storage service:
16
+ * - AWS S3
17
+ * - Cloudflare R2
18
+ * - MinIO
19
+ * - DigitalOcean Spaces
20
+ * - Backblaze B2
21
+ * - Any other S3-compatible service
22
+ *
23
+ * Key design decisions:
24
+ * - Storage keys include the bucket name (e.g., "my-bucket/filename.jpg")
25
+ * - Public URLs can use custom CDN/public URLs without the bucket prefix
26
+ * - This separation allows S3 API to work correctly while serving public URLs cleanly
27
+ */
28
+ export declare class S3StorageAdapter implements StorageAdapter {
29
+ readonly name = "s3";
30
+ private client;
31
+ private bucket;
32
+ private publicUrl;
33
+ private config;
34
+ constructor(config: S3StorageConfig);
35
+ private generateUniqueFilename;
36
+ store(data: UploadFileData): Promise<StorageFile>;
37
+ delete(path: string): Promise<boolean>;
38
+ exists(path: string): Promise<boolean>;
39
+ getUrl(path: string): string;
40
+ getStorageInfo(): Promise<{
41
+ totalSize: number;
42
+ }>;
43
+ isHealthy(): Promise<boolean>;
44
+ getSignedUrl(path: string): Promise<string>;
45
+ }
46
+ export declare class S3StorageProvider implements StorageProvider {
47
+ name: string;
48
+ createAdapter(config: StorageConfig): StorageAdapter;
49
+ }
50
+ /**
51
+ * Helper function to configure S3-compatible storage
52
+ *
53
+ * Works with any S3-compatible service including AWS S3, Cloudflare R2, MinIO, DigitalOcean Spaces, etc.
54
+ *
55
+ * @param config - S3 configuration options
56
+ * @param config.bucket - Bucket name
57
+ * @param config.endpoint - S3 endpoint URL
58
+ * @param config.accessKeyId - API access key ID
59
+ * @param config.secretAccessKey - API secret access key
60
+ * @param config.publicUrl - Public URL for file access (optional, uses endpoint if not provided)
61
+ * @param config.region - AWS region (defaults to 'auto')
62
+ * @param config.basePath - Optional path prefix for organizing files
63
+ * @param config.maxFileSize - Maximum file size in bytes (default: 10MB)
64
+ * @param config.allowedTypes - Allowed MIME types (default: common image types)
65
+ *
66
+ * @example Cloudflare R2
67
+ * ```typescript
68
+ * import { s3Storage } from '@aphexcms/storage-s3';
69
+ *
70
+ * export default createCMSConfig({
71
+ * storage: s3Storage({
72
+ * bucket: env.R2_BUCKET,
73
+ * endpoint: env.R2_ENDPOINT,
74
+ * accessKeyId: env.R2_ACCESS_KEY_ID,
75
+ * secretAccessKey: env.R2_SECRET_ACCESS_KEY,
76
+ * publicUrl: env.R2_PUBLIC_URL
77
+ * })
78
+ * });
79
+ * ```
80
+ *
81
+ * @example AWS S3
82
+ * ```typescript
83
+ * import { s3Storage } from '@aphexcms/storage-s3';
84
+ *
85
+ * export default createCMSConfig({
86
+ * storage: s3Storage({
87
+ * bucket: 'my-bucket',
88
+ * endpoint: 'https://s3.us-east-1.amazonaws.com',
89
+ * accessKeyId: env.AWS_ACCESS_KEY_ID,
90
+ * secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
91
+ * region: 'us-east-1'
92
+ * })
93
+ * });
94
+ * ```
95
+ *
96
+ * @example MinIO
97
+ * ```typescript
98
+ * import { s3Storage } from '@aphexcms/storage-s3';
99
+ *
100
+ * export default createCMSConfig({
101
+ * storage: s3Storage({
102
+ * bucket: 'my-bucket',
103
+ * endpoint: 'http://localhost:9000',
104
+ * accessKeyId: 'minioadmin',
105
+ * secretAccessKey: 'minioadmin'
106
+ * })
107
+ * });
108
+ * ```
109
+ */
110
+ export declare function s3Storage(config: {
111
+ bucket: string;
112
+ endpoint: string;
113
+ accessKeyId: string;
114
+ secretAccessKey: string;
115
+ region?: string;
116
+ publicUrl?: string;
117
+ basePath?: string;
118
+ baseUrl?: string;
119
+ maxFileSize?: number;
120
+ allowedTypes?: string[];
121
+ }): {
122
+ adapter: S3StorageAdapter;
123
+ disableLocalStorage: boolean;
124
+ };
125
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,EACd,WAAW,EACX,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACrD,OAAO,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACF;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,gBAAiB,YAAW,cAAc;IACtD,QAAQ,CAAC,IAAI,QAAQ;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAA2C;gBAE7C,MAAM,EAAE,eAAe;IA0BnC,OAAO,CAAC,sBAAsB;IAOxB,KAAK,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IA+BjD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAItC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAU5C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAStB,cAAc,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAKhD,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAQ7B,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAKjD;AAED,qBAAa,iBAAkB,YAAW,eAAe;IACxD,IAAI,SAAQ;IACZ,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,cAAc;CAGpD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;;;EAkBA"}
package/dist/index.js ADDED
@@ -0,0 +1,200 @@
1
+ import { S3mini } from 's3mini';
2
+ /**
3
+ * S3-Compatible Storage Adapter
4
+ *
5
+ * This adapter uses the S3-compatible API to store files in any S3-compatible storage service:
6
+ * - AWS S3
7
+ * - Cloudflare R2
8
+ * - MinIO
9
+ * - DigitalOcean Spaces
10
+ * - Backblaze B2
11
+ * - Any other S3-compatible service
12
+ *
13
+ * Key design decisions:
14
+ * - Storage keys include the bucket name (e.g., "my-bucket/filename.jpg")
15
+ * - Public URLs can use custom CDN/public URLs without the bucket prefix
16
+ * - This separation allows S3 API to work correctly while serving public URLs cleanly
17
+ */
18
+ export class S3StorageAdapter {
19
+ name = 's3';
20
+ client;
21
+ bucket;
22
+ publicUrl;
23
+ config;
24
+ constructor(config) {
25
+ const { bucket, endpoint, accessKeyId, secretAccessKey, region, publicUrl } = config.options;
26
+ this.client = new S3mini({
27
+ endpoint,
28
+ accessKeyId,
29
+ secretAccessKey,
30
+ region: region || 'auto'
31
+ });
32
+ this.bucket = bucket;
33
+ this.publicUrl = publicUrl || endpoint;
34
+ this.config = {
35
+ basePath: config.basePath ?? '',
36
+ baseUrl: config.baseUrl || this.publicUrl,
37
+ maxFileSize: config.maxFileSize || 10 * 1024 * 1024, // 10MB default
38
+ allowedTypes: config.allowedTypes || [
39
+ 'image/jpeg',
40
+ 'image/png',
41
+ 'image/webp',
42
+ 'image/gif',
43
+ 'image/avif'
44
+ ]
45
+ };
46
+ }
47
+ generateUniqueFilename(originalFilename) {
48
+ const lastDot = originalFilename.lastIndexOf('.');
49
+ const name = lastDot > -1 ? originalFilename.substring(0, lastDot) : originalFilename;
50
+ const ext = lastDot > -1 ? originalFilename.substring(lastDot) : '';
51
+ return `${name}-${Date.now()}-${Math.random().toString(36).substring(2, 8)}${ext}`;
52
+ }
53
+ async store(data) {
54
+ if (!this.config.allowedTypes.includes(data.mimeType)) {
55
+ throw new Error(`Invalid file type: ${data.mimeType}`);
56
+ }
57
+ if (data.size > this.config.maxFileSize) {
58
+ throw new Error(`File too large: ${data.size} bytes`);
59
+ }
60
+ const filename = this.generateUniqueFilename(data.filename);
61
+ // S3 operations require bucket in the key path
62
+ const s3Key = this.config.basePath
63
+ ? `${this.bucket}/${this.config.basePath}/${filename}`
64
+ : `${this.bucket}/${filename}`;
65
+ // Public URL path excludes bucket (public URL already points to bucket)
66
+ const publicPath = this.config.basePath ? `${this.config.basePath}/${filename}` : filename;
67
+ // Ensure proper Buffer format for fetch API compatibility
68
+ const buffer = Buffer.isBuffer(data.buffer) ? data.buffer : Buffer.from(data.buffer);
69
+ await this.client.putObject(s3Key, buffer, data.mimeType);
70
+ return {
71
+ path: s3Key,
72
+ url: `${this.config.baseUrl}/${publicPath}`,
73
+ size: data.size
74
+ };
75
+ }
76
+ async delete(path) {
77
+ return await this.client.deleteObject(path);
78
+ }
79
+ async exists(path) {
80
+ try {
81
+ const response = await this.client.objectExists(path);
82
+ return Boolean(response?.valueOf?.() ?? response);
83
+ }
84
+ catch (error) {
85
+ console.error(`Error checking existence of ${path}:`, error);
86
+ return false;
87
+ }
88
+ }
89
+ getUrl(path) {
90
+ // Strip bucket prefix from stored path for public URLs
91
+ // Example: "my-bucket/image.jpg" -> "image.jpg"
92
+ const pathWithoutBucket = path.startsWith(`${this.bucket}/`)
93
+ ? path.slice(this.bucket.length + 1)
94
+ : path;
95
+ return `${this.config.baseUrl}/${pathWithoutBucket}`;
96
+ }
97
+ async getStorageInfo() {
98
+ // TODO: Implement bucket size calculation
99
+ return { totalSize: 0 };
100
+ }
101
+ async isHealthy() {
102
+ try {
103
+ return await this.client.bucketExists();
104
+ }
105
+ catch {
106
+ return false;
107
+ }
108
+ }
109
+ async getSignedUrl(path) {
110
+ // TODO: Implement AWS Signature V4 for private file access
111
+ // For now, return public URL
112
+ return this.getUrl(path);
113
+ }
114
+ }
115
+ export class S3StorageProvider {
116
+ name = 's3';
117
+ createAdapter(config) {
118
+ return new S3StorageAdapter(config);
119
+ }
120
+ }
121
+ /**
122
+ * Helper function to configure S3-compatible storage
123
+ *
124
+ * Works with any S3-compatible service including AWS S3, Cloudflare R2, MinIO, DigitalOcean Spaces, etc.
125
+ *
126
+ * @param config - S3 configuration options
127
+ * @param config.bucket - Bucket name
128
+ * @param config.endpoint - S3 endpoint URL
129
+ * @param config.accessKeyId - API access key ID
130
+ * @param config.secretAccessKey - API secret access key
131
+ * @param config.publicUrl - Public URL for file access (optional, uses endpoint if not provided)
132
+ * @param config.region - AWS region (defaults to 'auto')
133
+ * @param config.basePath - Optional path prefix for organizing files
134
+ * @param config.maxFileSize - Maximum file size in bytes (default: 10MB)
135
+ * @param config.allowedTypes - Allowed MIME types (default: common image types)
136
+ *
137
+ * @example Cloudflare R2
138
+ * ```typescript
139
+ * import { s3Storage } from '@aphexcms/storage-s3';
140
+ *
141
+ * export default createCMSConfig({
142
+ * storage: s3Storage({
143
+ * bucket: env.R2_BUCKET,
144
+ * endpoint: env.R2_ENDPOINT,
145
+ * accessKeyId: env.R2_ACCESS_KEY_ID,
146
+ * secretAccessKey: env.R2_SECRET_ACCESS_KEY,
147
+ * publicUrl: env.R2_PUBLIC_URL
148
+ * })
149
+ * });
150
+ * ```
151
+ *
152
+ * @example AWS S3
153
+ * ```typescript
154
+ * import { s3Storage } from '@aphexcms/storage-s3';
155
+ *
156
+ * export default createCMSConfig({
157
+ * storage: s3Storage({
158
+ * bucket: 'my-bucket',
159
+ * endpoint: 'https://s3.us-east-1.amazonaws.com',
160
+ * accessKeyId: env.AWS_ACCESS_KEY_ID,
161
+ * secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
162
+ * region: 'us-east-1'
163
+ * })
164
+ * });
165
+ * ```
166
+ *
167
+ * @example MinIO
168
+ * ```typescript
169
+ * import { s3Storage } from '@aphexcms/storage-s3';
170
+ *
171
+ * export default createCMSConfig({
172
+ * storage: s3Storage({
173
+ * bucket: 'my-bucket',
174
+ * endpoint: 'http://localhost:9000',
175
+ * accessKeyId: 'minioadmin',
176
+ * secretAccessKey: 'minioadmin'
177
+ * })
178
+ * });
179
+ * ```
180
+ */
181
+ export function s3Storage(config) {
182
+ return {
183
+ adapter: new S3StorageAdapter({
184
+ basePath: config.basePath ?? '',
185
+ baseUrl: config.baseUrl || config.publicUrl || config.endpoint,
186
+ maxFileSize: config.maxFileSize,
187
+ allowedTypes: config.allowedTypes,
188
+ options: {
189
+ bucket: config.bucket,
190
+ endpoint: config.endpoint,
191
+ accessKeyId: config.accessKeyId,
192
+ secretAccessKey: config.secretAccessKey,
193
+ region: config.region,
194
+ publicUrl: config.publicUrl
195
+ }
196
+ }),
197
+ disableLocalStorage: true
198
+ };
199
+ }
200
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@aphexcms/storage-s3",
3
+ "version": "0.1.0",
4
+ "description": "S3-compatible storage adapter for Aphex CMS (AWS S3, Cloudflare R2, MinIO, etc.)",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "prepublishOnly": "pnpm build"
21
+ },
22
+ "dependencies": {
23
+ "s3mini": "^0.5.0"
24
+ },
25
+ "peerDependencies": {
26
+ "@aphexcms/cms-core": "workspace:*"
27
+ },
28
+ "devDependencies": {
29
+ "@aphexcms/cms-core": "workspace:*",
30
+ "tsup": "^8.0.0",
31
+ "typescript": "^5.3.3"
32
+ }
33
+ }