manage-storage 0.0.3 → 0.0.4

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/README.md CHANGED
@@ -13,7 +13,6 @@ Universal cloud storage manager supporting AWS S3, Cloudflare R2, and Backblaze
13
13
  - **Lightweight**: Built on aws-lite (not the bloated AWS SDK) for faster cold starts
14
14
  - **Simple API**: Single function interface for all storage operations
15
15
  - **No File System**: Returns data directly - perfect for serverless/edge environments
16
- - **TypeScript Ready**: Full type support with comprehensive type definitions
17
16
 
18
17
  ## Installation
19
18
 
@@ -44,6 +43,18 @@ const data = await manageStorage("download", {
44
43
  // List all files
45
44
  const files = await manageStorage("list");
46
45
 
46
+ // Copy a file
47
+ await manageStorage("copy", {
48
+ key: "documents/report.pdf",
49
+ destinationKey: "documents/report-backup.pdf",
50
+ });
51
+
52
+ // Rename a file (copy + delete)
53
+ await manageStorage("rename", {
54
+ key: "documents/old-name.pdf",
55
+ destinationKey: "documents/new-name.pdf",
56
+ });
57
+
47
58
  // Delete a file
48
59
  await manageStorage("delete", {
49
60
  key: "documents/report.pdf",
@@ -90,16 +101,17 @@ Performs storage operations on your configured cloud provider.
90
101
 
91
102
  #### Parameters
92
103
 
93
- - **action** `string` - The operation to perform: `'upload'`, `'download'`, `'delete'`, `'list'`, or `'deleteAll'`
104
+ - **action** `string` - The operation to perform: `'upload'`, `'download'`, `'delete'`, `'list'`, `'deleteAll'`, `'copy'`, or `'rename'`
94
105
  - **options** `object` - Operation-specific options
95
106
 
96
107
  #### Options
97
108
 
98
- | Option | Type | Required | Description |
99
- | ---------- | ------------------------ | ----------------------------------- | ---------------------------------------------------- |
100
- | `key` | `string` | Yes (except for `list`/`deleteAll`) | The object key/path |
101
- | `body` | `string\|Buffer\|Stream` | Yes (for `upload`) | The file content to upload |
102
- | `provider` | `'s3'\|'r2'\|'b2'` | No | Force a specific provider (auto-detected if omitted) |
109
+ | Option | Type | Required | Description |
110
+ | ---------------- | ------------------------ | ----------------------------------- | ---------------------------------------------------- |
111
+ | `key` | `string` | Yes (except for `list`/`deleteAll`) | The object key/path |
112
+ | `destinationKey` | `string` | Yes (for `copy`/`rename`) | The destination key/path for copy/rename operations |
113
+ | `body` | `string\|Buffer\|Stream` | Yes (for `upload`) | The file content to upload |
114
+ | `provider` | `'s3'\|'r2'\|'b2'` | No | Force a specific provider (auto-detected if omitted) |
103
115
 
104
116
  ## Usage Examples
105
117
 
@@ -156,7 +168,39 @@ const notes = files.filter((key) => key.startsWith("notes/"));
156
168
  console.log(notes); // ['notes/memo.txt']
157
169
  ```
158
170
 
159
- ### 4. Delete Files
171
+ ### 4. Copy Files
172
+
173
+ ```javascript
174
+ // Copy a file to a new location
175
+ await manageStorage("copy", {
176
+ key: "documents/report.pdf",
177
+ destinationKey: "documents/backup/report-2024.pdf",
178
+ });
179
+
180
+ // Create a backup
181
+ await manageStorage("copy", {
182
+ key: "config/settings.json",
183
+ destinationKey: "config/settings.backup.json",
184
+ });
185
+ ```
186
+
187
+ ### 5. Rename Files
188
+
189
+ ```javascript
190
+ // Rename a file (performs copy + delete)
191
+ await manageStorage("rename", {
192
+ key: "old-filename.txt",
193
+ destinationKey: "new-filename.txt",
194
+ });
195
+
196
+ // Move to a different folder
197
+ await manageStorage("rename", {
198
+ key: "temp/draft.md",
199
+ destinationKey: "published/article.md",
200
+ });
201
+ ```
202
+
203
+ ### 6. Delete Files
160
204
 
161
205
  ```javascript
162
206
  // Delete a single file
@@ -169,7 +213,7 @@ const result = await manageStorage("deleteAll");
169
213
  console.log(`Deleted ${result.count} files`);
170
214
  ```
171
215
 
172
- ### 5. Force a Specific Provider
216
+ ### 7. Force a Specific Provider
173
217
 
174
218
  ```javascript
175
219
  // Use R2 even if other providers are configured
@@ -187,7 +231,7 @@ await manageStorage("upload", {
187
231
  });
188
232
  ```
189
233
 
190
- ### 6. Runtime Configuration (Override Environment Variables)
234
+ ### 8. Runtime Configuration (Override Environment Variables)
191
235
 
192
236
  ```javascript
193
237
  // Pass credentials at runtime instead of using env vars
@@ -242,7 +286,7 @@ export async function GET(req) {
242
286
 
243
287
  ```javascript
244
288
  import express from "express";
245
- import { manageStorage } from "@opensourceagi/cloud-storage";
289
+ import { manageStorage } from "manage-storage";
246
290
 
247
291
  const app = express();
248
292
  app.use(express.json());
@@ -290,7 +334,7 @@ app.listen(3000, () => console.log("Server running on port 3000"));
290
334
  ### Cloudflare Workers
291
335
 
292
336
  ```javascript
293
- import { manageStorage } from "@opensourceagi/cloud-storage";
337
+ import { manageStorage } from "manage-storage";
294
338
 
295
339
  export default {
296
340
  async fetch(request, env) {
@@ -383,6 +427,26 @@ const contents = await Promise.all(
383
427
  }
384
428
  ```
385
429
 
430
+ ### Copy
431
+
432
+ ```javascript
433
+ {
434
+ success: true,
435
+ sourceKey: 'documents/report.pdf',
436
+ destinationKey: 'documents/backup/report-2024.pdf'
437
+ }
438
+ ```
439
+
440
+ ### Rename
441
+
442
+ ```javascript
443
+ {
444
+ success: true,
445
+ oldKey: 'old-filename.txt',
446
+ newKey: 'new-filename.txt'
447
+ }
448
+ ```
449
+
386
450
  ## Why aws-lite?
387
451
 
388
452
  This library uses [@aws-lite](https://aws-lite.org/) instead of the official AWS SDK because:
@@ -393,11 +457,7 @@ This library uses [@aws-lite](https://aws-lite.org/) instead of the official AWS
393
457
  - **Modern API**: Clean, promise-based interface
394
458
  - **No dependencies overhead**: Minimal dependency tree
395
459
 
396
- # Cloud Object Storage Comparison: GCS, Backblaze B2, Cloudflare R2, and AWS S3
397
-
398
- Google Cloud Storage (GCS) joins Backblaze B2, Cloudflare R2, and AWS S3 as a hyperscaler option with [strong multi-region support](https://cloud.google.com/storage/pricing), multiple storage classes, and [deep integration with Google Cloud services](https://cloud.google.com/storage/pricing). These providers all [offer S3-compatible object storage](https://www.backblaze.com/cloud-storage/pricing) but differ significantly in [pricing models](https://www.backblaze.com/cloud-storage/pricing), especially storage costs, egress fees, and ecosystem fit.
399
-
400
- ## Updated pricing snapshot ("hot"/Standard storage)
460
+ # Cloud Object Storage Comparison
401
461
 
402
462
  | Service | Storage price (/TB-month) | Egress to internet | API ops (Class A/B per 1K, approx) | Minimum duration | Notes |
403
463
  | --------------------------------------------------------------- | ------------------------------ | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------ |
package/dist/index.d.ts CHANGED
@@ -1,7 +1,20 @@
1
1
  /**
2
2
  * Storage operation action type
3
3
  */
4
- export declare type Action = "upload" | "download" | "delete" | "list" | "deleteAll";
4
+ export declare type Action = "upload" | "download" | "delete" | "list" | "deleteAll" | "copy" | "rename";
5
+
6
+ /**
7
+ * Result from copy operation
8
+ */
9
+ export declare interface CopyResult {
10
+ /** Whether the copy was successful */
11
+ success: boolean;
12
+ /** The source object key */
13
+ sourceKey: string;
14
+ /** The destination object key */
15
+ destinationKey: string;
16
+ [key: string]: any;
17
+ }
5
18
 
6
19
  /**
7
20
  * Result from deleteAll operation
@@ -63,6 +76,20 @@ export declare interface DeleteResult {
63
76
  * });
64
77
  *
65
78
  * @example
79
+ * // Copy a file
80
+ * await manageStorage('copy', {
81
+ * key: 'documents/report.pdf',
82
+ * destinationKey: 'documents/report-copy.pdf'
83
+ * });
84
+ *
85
+ * @example
86
+ * // Rename a file (copy + delete)
87
+ * await manageStorage('rename', {
88
+ * key: 'documents/old-name.pdf',
89
+ * destinationKey: 'documents/new-name.pdf'
90
+ * });
91
+ *
92
+ * @example
66
93
  * // Force a specific provider with runtime credentials
67
94
  * await manageStorage('upload', {
68
95
  * key: 'test.txt',
@@ -74,34 +101,61 @@ export declare interface DeleteResult {
74
101
  * BUCKET_URL: 'https://account.r2.cloudflarestorage.com'
75
102
  * });
76
103
  */
77
- export declare function manageStorage(action: "upload", options: StorageOptions & {
104
+ declare function manageStorage(action: "upload", options: StorageOptions & {
78
105
  key: string;
79
106
  body: string | Buffer | ReadableStream;
80
107
  }): Promise<UploadResult>;
81
108
 
82
- export declare function manageStorage(action: "download", options: StorageOptions & {
109
+ declare function manageStorage(action: "download", options: StorageOptions & {
83
110
  key: string;
84
111
  }): Promise<string>;
85
112
 
86
- export declare function manageStorage(action: "delete", options: StorageOptions & {
113
+ declare function manageStorage(action: "delete", options: StorageOptions & {
87
114
  key: string;
88
115
  }): Promise<DeleteResult>;
89
116
 
90
- export declare function manageStorage(action: "list", options?: StorageOptions): Promise<string[]>;
117
+ declare function manageStorage(action: "list", options?: StorageOptions): Promise<string[]>;
118
+
119
+ declare function manageStorage(action: "deleteAll", options?: StorageOptions): Promise<DeleteAllResult>;
120
+
121
+ declare function manageStorage(action: "copy", options: StorageOptions & {
122
+ key: string;
123
+ destinationKey: string;
124
+ }): Promise<CopyResult>;
91
125
 
92
- export declare function manageStorage(action: "deleteAll", options?: StorageOptions): Promise<DeleteAllResult>;
126
+ declare function manageStorage(action: "rename", options: StorageOptions & {
127
+ key: string;
128
+ destinationKey: string;
129
+ }): Promise<RenameResult>;
130
+ export default manageStorage;
131
+ export { manageStorage }
93
132
 
94
133
  /**
95
134
  * Cloud storage provider type
96
135
  */
97
136
  export declare type Provider = "s3" | "r2" | "b2";
98
137
 
138
+ /**
139
+ * Result from rename operation
140
+ */
141
+ export declare interface RenameResult {
142
+ /** Whether the rename was successful */
143
+ success: boolean;
144
+ /** The old object key */
145
+ oldKey: string;
146
+ /** The new object key */
147
+ newKey: string;
148
+ [key: string]: any;
149
+ }
150
+
99
151
  /**
100
152
  * Options for storage operations
101
153
  */
102
154
  export declare interface StorageOptions {
103
155
  /** The object key/path (required for upload, download, delete) */
104
156
  key?: string;
157
+ /** The destination key/path (required for copy, rename) */
158
+ destinationKey?: string;
105
159
  /** The file content to upload (required for upload) */
106
160
  body?: string | Buffer | ReadableStream;
107
161
  /** Force a specific cloud provider (auto-detected if omitted) */
package/dist/index.js CHANGED
@@ -1,79 +1,105 @@
1
- import $ from "@aws-lite/client";
2
- import y from "@aws-lite/s3";
3
- import { config as f } from "dotenv";
4
- f();
5
- async function w(o, s = {}) {
6
- var _, i;
7
- const { key: e, body: E, provider: d, ...K } = s, c = d || b(), A = Object.fromEntries(
8
- Object.entries(K).map(([n, a]) => [`${c.toUpperCase()}_${n}`, a])
9
- ), t = g(c, A);
1
+ import b from "@aws-lite/client";
2
+ import k from "@aws-lite/s3";
3
+ import { config as w } from "dotenv";
4
+ w();
5
+ async function U(r, s = {}) {
6
+ var _, C;
7
+ const { key: e, body: a, destinationKey: o, provider: K, ...d } = s, u = K || B(), y = Object.fromEntries(
8
+ Object.entries(d).map(([n, l]) => [`${u.toUpperCase()}_${n}`, l])
9
+ ), t = f(u, y);
10
10
  if (!t.bucket || !t.accessKeyId || !t.secretAccessKey)
11
- throw new Error(`Missing credentials for ${c}`);
12
- const r = await $({
11
+ throw new Error(`Missing credentials for ${u}`);
12
+ const c = await b({
13
13
  region: t.region,
14
14
  endpoint: t.endpoint,
15
15
  accessKeyId: t.accessKeyId,
16
16
  secretAccessKey: t.secretAccessKey,
17
- plugins: [y]
17
+ plugins: [k]
18
18
  });
19
19
  try {
20
- switch (o) {
20
+ switch (r) {
21
21
  case "upload":
22
- const n = await r.s3.PutObject({
22
+ const n = await c.s3.PutObject({
23
23
  Bucket: t.bucket,
24
24
  Key: e,
25
- Body: E
25
+ Body: a
26
26
  });
27
- return console.log(`Uploaded ${e} to ${c}`), { success: !0, key: e, ...n };
27
+ return { success: !0, key: e, ...n };
28
28
  case "download":
29
- const a = await r.s3.GetObject({
29
+ return (await c.s3.GetObject({
30
30
  Bucket: t.bucket,
31
31
  Key: e
32
- });
33
- return console.log(`Downloaded ${e} from ${c}`), a.Body;
32
+ })).Body;
34
33
  case "delete":
35
- const S = await r.s3.DeleteObject({
34
+ const p = await c.s3.DeleteObject({
36
35
  Bucket: t.bucket,
37
36
  Key: e
38
37
  });
39
- return console.log(`Deleted ${e} from ${c}`), { success: !0, key: e, ...S };
38
+ return { success: !0, key: e, ...p };
40
39
  case "list":
41
- const C = ((_ = (await r.s3.ListObjectsV2({
40
+ return ((_ = (await c.s3.ListObjectsV2({
42
41
  Bucket: t.bucket
43
- })).Contents) == null ? void 0 : _.map((u) => u.Key)) || [];
44
- return console.log(C.join(`
45
- `)), C;
42
+ })).Contents) == null ? void 0 : _.map((E) => E.Key)) || [];
46
43
  case "deleteAll":
47
- const l = await r.s3.ListObjectsV2({
44
+ const i = await c.s3.ListObjectsV2({
48
45
  Bucket: t.bucket
49
46
  });
50
- if ((i = l.Contents) != null && i.length) {
51
- const u = await r.s3.DeleteObjects({
47
+ if ((C = i.Contents) != null && C.length) {
48
+ const E = await c.s3.DeleteObjects({
52
49
  Bucket: t.bucket,
53
50
  Delete: {
54
- Objects: l.Contents.map((p) => ({ Key: p.Key }))
51
+ Objects: i.Contents.map((A) => ({
52
+ Key: A.Key
53
+ }))
55
54
  }
56
55
  });
57
- return console.log(
58
- `Deleted all ${l.Contents.length} files from ${c}`
59
- ), {
56
+ return {
60
57
  success: !0,
61
- count: l.Contents.length,
62
- ...u
58
+ count: i.Contents.length,
59
+ ...E
63
60
  };
64
61
  } else
65
- return console.log(`${c} bucket empty`), { success: !0, count: 0 };
62
+ return { success: !0, count: 0 };
63
+ case "copy":
64
+ if (!o)
65
+ throw new Error("destinationKey is required for copy operation");
66
+ const S = await c.s3.CopyObject({
67
+ Bucket: t.bucket,
68
+ CopySource: `${t.bucket}/${e}`,
69
+ Key: o
70
+ });
71
+ return {
72
+ success: !0,
73
+ sourceKey: e,
74
+ destinationKey: o,
75
+ ...S
76
+ };
77
+ case "rename":
78
+ if (!o)
79
+ throw new Error("destinationKey is required for rename operation");
80
+ return await c.s3.CopyObject({
81
+ Bucket: t.bucket,
82
+ CopySource: `${t.bucket}/${e}`,
83
+ Key: o
84
+ }), await c.s3.DeleteObject({
85
+ Bucket: t.bucket,
86
+ Key: e
87
+ }), {
88
+ success: !0,
89
+ oldKey: e,
90
+ newKey: o
91
+ };
66
92
  default:
67
93
  throw new Error(
68
- "Invalid action: upload, download, delete, list, deleteAll"
94
+ "Invalid action: upload, download, delete, list, deleteAll, copy, rename"
69
95
  );
70
96
  }
71
97
  } catch (n) {
72
- throw console.error(`Error in ${c}:`, n.message), n;
98
+ throw console.error(`Error in ${u}:`, n.message), n;
73
99
  }
74
100
  }
75
- function b() {
76
- const o = {
101
+ function B() {
102
+ const r = {
77
103
  r2: [
78
104
  "R2_BUCKET_NAME",
79
105
  "R2_ACCESS_KEY_ID",
@@ -93,15 +119,15 @@ function b() {
93
119
  "S3_BUCKET_URL"
94
120
  ]
95
121
  };
96
- for (const [s, e] of Object.entries(o))
97
- if (e.every((E) => process.env[E]))
122
+ for (const [s, e] of Object.entries(r))
123
+ if (e.every((a) => process.env[a]))
98
124
  return s;
99
125
  return "r2";
100
126
  }
101
- function g(o, s = {}) {
102
- const e = o.toUpperCase() + "_";
127
+ function f(r, s = {}) {
128
+ const e = r.toUpperCase() + "_";
103
129
  return {
104
- region: o === "s3" ? s.awsRegion || process.env.S3_REGION || "us-east-1" : "auto",
130
+ region: r === "s3" ? s.awsRegion || process.env.S3_REGION || "us-east-1" : "auto",
105
131
  endpoint: s[`${e}BUCKET_URL`] || process.env[`${e}BUCKET_URL`] || "",
106
132
  bucket: s[`${e}BUCKET_NAME`] || process.env[`${e}BUCKET_NAME`] || "",
107
133
  accessKeyId: s[`${e}ACCESS_KEY_ID`] || s[`${e}APPLICATION_KEY_ID`] || process.env[`${e}ACCESS_KEY_ID`] || process.env[`${e}APPLICATION_KEY_ID`] || "",
@@ -109,5 +135,6 @@ function g(o, s = {}) {
109
135
  };
110
136
  }
111
137
  export {
112
- w as manageStorage
138
+ U as default,
139
+ U as manageStorage
113
140
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "manage-storage",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "Storage manager supporting AWS S3, Cloudflare R2, and Backblaze B2 with automatic provider detection",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",