stow-cli 1.0.3 → 2.0.2

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.
Files changed (63) hide show
  1. package/dist/{app-JPUDM4LJ.js → app-2A2CFVBC.js} +1 -1
  2. package/dist/app-2H4TLSN7.js +239 -0
  3. package/dist/app-DTW2LNXW.js +249 -0
  4. package/dist/app-HYCPA7GA.js +239 -0
  5. package/dist/app-IZGSPZPX.js +239 -0
  6. package/dist/app-UGUM75MC.js +239 -0
  7. package/dist/app-XPOEAZJC.js +239 -0
  8. package/dist/app-YITP5APT.js +233 -0
  9. package/dist/{backfill-QZTVNJZM.js → backfill-G57M2BRA.js} +3 -3
  10. package/dist/{buckets-JQKZ3PH3.js → buckets-NXIVHPW5.js} +2 -2
  11. package/dist/chunk-2AORPTQB.js +23 -0
  12. package/dist/chunk-5LU25QZK.js +17 -0
  13. package/dist/chunk-FEMMZ4YZ.js +125 -0
  14. package/dist/chunk-LYCXXF2T.js +79 -0
  15. package/dist/chunk-MHRMBH4Y.js +36 -0
  16. package/dist/{chunk-WAQSCS57.js → chunk-QF7PVPWQ.js} +1 -1
  17. package/dist/chunk-R5CCBTXZ.js +79 -0
  18. package/dist/chunk-TOADDO2F.js +23 -0
  19. package/dist/chunk-YRHPOFJT.js +115 -0
  20. package/dist/chunk-ZDVARBCV.js +43 -0
  21. package/dist/cli.d.ts +1 -0
  22. package/dist/cli.js +43 -43
  23. package/dist/delete-AECEJX5W.js +18 -0
  24. package/dist/delete-GEX3O7YS.js +14 -0
  25. package/dist/delete-KYOZEODD.js +18 -0
  26. package/dist/delete-OLOAJRRO.js +18 -0
  27. package/dist/delete-V4EY4UBG.js +18 -0
  28. package/dist/{drops-QXGTYB5E.js → drops-RD55IDZ4.js} +2 -2
  29. package/dist/{files-OCYICIAM.js → files-E662TXUP.js} +3 -3
  30. package/dist/{health-YMZTZUFX.js → health-6LWM7KAT.js} +3 -3
  31. package/dist/{jobs-6JY4SVV5.js → jobs-CLXYKZ3B.js} +4 -4
  32. package/dist/{jobs-OKKGKSIH.js → jobs-K3LTNETU.js} +5 -5
  33. package/dist/list-7A3VZA2T.js +97 -0
  34. package/dist/list-DHXVIMRI.js +94 -0
  35. package/dist/list-DJEAKEZJ.js +106 -0
  36. package/dist/list-DQRU6QHO.js +106 -0
  37. package/dist/list-I5A6LTHX.js +106 -0
  38. package/dist/list-KEQPJY7I.js +109 -0
  39. package/dist/list-Z3MPT6MI.js +109 -0
  40. package/dist/{maintenance-EZUHQK5Q.js → maintenance-7LOAGG6J.js} +6 -6
  41. package/dist/open-2YNHG3MA.js +15 -0
  42. package/dist/open-F73Q2OHD.js +15 -0
  43. package/dist/{profiles-GWLBEEIT.js → profiles-C6SCFXS6.js} +2 -2
  44. package/dist/{queues-EQX7EJZF.js → queues-2GJAMMNF.js} +4 -4
  45. package/dist/{search-2PXM6XQ6.js → search-DV4VV62L.js} +2 -2
  46. package/dist/{tags-LSVEIIUF.js → tags-URHK2YH5.js} +2 -2
  47. package/dist/upload-3NS5O3UL.js +120 -0
  48. package/dist/upload-5RIDB2C5.js +92 -0
  49. package/dist/upload-B2PGW3AN.js +125 -0
  50. package/dist/{upload-ESYKBYHA.js → upload-DQDBDIDI.js} +1 -1
  51. package/dist/upload-FGNGNPC3.js +93 -0
  52. package/dist/upload-HKUPWTK2.js +173 -0
  53. package/dist/upload-JDVSJVWK.js +173 -0
  54. package/dist/upload-K4H7ZVRW.js +98 -0
  55. package/dist/upload-MI6VFGTC.js +92 -0
  56. package/dist/whoami-2SLCNVKP.js +27 -0
  57. package/dist/whoami-5IYRZKWS.js +28 -0
  58. package/dist/{whoami-4UYMSRVP.js → whoami-754O5IML.js} +1 -1
  59. package/dist/whoami-DOMX3Z5K.js +28 -0
  60. package/dist/whoami-IPMCUEUH.js +27 -0
  61. package/dist/whoami-JSQA2IDN.js +27 -0
  62. package/dist/whoami-RKH5HHPR.js +27 -0
  63. package/package.json +4 -4
@@ -5,11 +5,11 @@ import {
5
5
  } from "./chunk-ELSDWMEB.js";
6
6
  import {
7
7
  createStow
8
- } from "./chunk-JYOMHKFS.js";
8
+ } from "./chunk-5LU25QZK.js";
9
9
  import {
10
10
  getApiKey,
11
11
  getBaseUrl
12
- } from "./chunk-OZ7QQTIZ.js";
12
+ } from "./chunk-TOADDO2F.js";
13
13
 
14
14
  // src/commands/files.ts
15
15
  async function listFiles(bucket, options) {
@@ -131,7 +131,7 @@ async function listMissing(bucket, type, options) {
131
131
  missing: type,
132
132
  ...parsedLimit && Number.isFinite(parsedLimit) && parsedLimit > 0 ? { limit: String(parsedLimit) } : {}
133
133
  });
134
- const res = await fetch(`${baseUrl}/api/files?${params}`, {
134
+ const res = await fetch(`${baseUrl}/files?${params}`, {
135
135
  headers: { "x-api-key": apiKey }
136
136
  });
137
137
  if (!res.ok) {
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  adminRequest
3
- } from "./chunk-WAQSCS57.js";
3
+ } from "./chunk-QF7PVPWQ.js";
4
4
  import {
5
5
  formatTable,
6
6
  outputJson
7
7
  } from "./chunk-ELSDWMEB.js";
8
- import "./chunk-OZ7QQTIZ.js";
8
+ import "./chunk-TOADDO2F.js";
9
9
 
10
10
  // src/commands/admin/health.ts
11
11
  async function health(options) {
12
12
  const result = await adminRequest({
13
13
  method: "GET",
14
- path: "/api/health"
14
+ path: "/health"
15
15
  });
16
16
  if (options.json) {
17
17
  outputJson(result);
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  getApiKey,
7
7
  getBaseUrl
8
- } from "./chunk-OZ7QQTIZ.js";
8
+ } from "./chunk-TOADDO2F.js";
9
9
 
10
10
  // src/commands/jobs.ts
11
11
  async function bucketRequest(opts) {
@@ -41,7 +41,7 @@ async function listJobs(bucketId, options) {
41
41
  params.set("limit", options.limit);
42
42
  }
43
43
  const qs = params.toString();
44
- const path = `/api/buckets/${bucketId}/jobs${qs ? `?${qs}` : ""}`;
44
+ const path = `/buckets/${bucketId}/jobs${qs ? `?${qs}` : ""}`;
45
45
  const result = await bucketRequest({
46
46
  method: "GET",
47
47
  path
@@ -69,7 +69,7 @@ async function listJobs(bucketId, options) {
69
69
  async function retryJob(jobId, options) {
70
70
  const result = await bucketRequest({
71
71
  method: "POST",
72
- path: `/api/buckets/${options.bucket}/jobs/${jobId}/retry`,
72
+ path: `/buckets/${options.bucket}/jobs/${jobId}/retry`,
73
73
  body: { queue: options.queue }
74
74
  });
75
75
  if (result.retried) {
@@ -79,7 +79,7 @@ async function retryJob(jobId, options) {
79
79
  async function deleteJob(jobId, options) {
80
80
  const result = await bucketRequest({
81
81
  method: "DELETE",
82
- path: `/api/buckets/${options.bucket}/jobs/${jobId}?queue=${encodeURIComponent(options.queue)}`
82
+ path: `/buckets/${options.bucket}/jobs/${jobId}?queue=${encodeURIComponent(options.queue)}`
83
83
  });
84
84
  if (result.deleted) {
85
85
  console.log(`Job ${jobId} removed.`);
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  adminRequest
3
- } from "./chunk-WAQSCS57.js";
3
+ } from "./chunk-QF7PVPWQ.js";
4
4
  import {
5
5
  formatTable,
6
6
  outputJson
7
7
  } from "./chunk-ELSDWMEB.js";
8
- import "./chunk-OZ7QQTIZ.js";
8
+ import "./chunk-TOADDO2F.js";
9
9
 
10
10
  // src/commands/admin/jobs.ts
11
11
  function formatTimestamp(ts) {
@@ -31,7 +31,7 @@ async function listAdminJobs(options) {
31
31
  const qs = params.toString();
32
32
  const result = await adminRequest({
33
33
  method: "GET",
34
- path: `/api/admin/jobs${qs ? `?${qs}` : ""}`
34
+ path: `/admin/jobs${qs ? `?${qs}` : ""}`
35
35
  });
36
36
  if (options.json) {
37
37
  outputJson(result.jobs);
@@ -60,7 +60,7 @@ async function listAdminJobs(options) {
60
60
  async function retryAdminJob(jobId, options) {
61
61
  const result = await adminRequest({
62
62
  method: "POST",
63
- path: `/api/admin/jobs/${jobId}/retry`,
63
+ path: `/admin/jobs/${jobId}/retry`,
64
64
  body: { queue: options.queue }
65
65
  });
66
66
  if (result.retried) {
@@ -70,7 +70,7 @@ async function retryAdminJob(jobId, options) {
70
70
  async function deleteAdminJob(jobId, options) {
71
71
  const result = await adminRequest({
72
72
  method: "DELETE",
73
- path: `/api/admin/jobs/${jobId}?queue=${encodeURIComponent(options.queue)}`
73
+ path: `/admin/jobs/${jobId}?queue=${encodeURIComponent(options.queue)}`
74
74
  });
75
75
  if (result.deleted) {
76
76
  console.log(`Job ${jobId} removed.`);
@@ -0,0 +1,97 @@
1
+ import {
2
+ createStow
3
+ } from "./chunk-JYOMHKFS.js";
4
+ import {
5
+ formatBytes,
6
+ formatTable,
7
+ usageBar
8
+ } from "./chunk-ZDVARBCV.js";
9
+ import "./chunk-OZ7QQTIZ.js";
10
+
11
+ // src/commands/list.ts
12
+ async function listBuckets() {
13
+ const stow = createStow();
14
+ const data = await stow.listBuckets();
15
+ if (data.buckets.length === 0) {
16
+ console.log("No buckets yet. Create one with: stow buckets create <name>");
17
+ return;
18
+ }
19
+ const rows = data.buckets.map((b) => [
20
+ b.name,
21
+ b.isPublic ? "public" : "private",
22
+ `${b.fileCount ?? 0} files`,
23
+ formatBytes(b.usageBytes ?? 0),
24
+ b.description || ""
25
+ ]);
26
+ console.log(
27
+ formatTable(["Name", "Access", "Files", "Size", "Description"], rows)
28
+ );
29
+ }
30
+ async function createBucket(name, options) {
31
+ const stow = createStow();
32
+ const bucket = await stow.createBucket({
33
+ name,
34
+ ...options.description ? { description: options.description } : {},
35
+ ...options.public ? { isPublic: true } : {}
36
+ });
37
+ console.log(`Created bucket: ${bucket.name}`);
38
+ }
39
+ async function renameBucket(name, newName, options) {
40
+ if (!options.yes) {
41
+ console.error(
42
+ "Warning: Renaming a bucket will break any existing URLs using the old name."
43
+ );
44
+ console.error("Use --yes to skip this warning.");
45
+ }
46
+ const stow = createStow();
47
+ const bucket = await stow.renameBucket(name, newName);
48
+ console.log(`Renamed bucket: ${name} \u2192 ${bucket.name}`);
49
+ }
50
+ async function listFiles(bucket, options) {
51
+ const stow = createStow();
52
+ const parsedLimit = options.limit ? Number.parseInt(options.limit, 10) : null;
53
+ const data = await stow.listFiles({
54
+ bucket,
55
+ ...options.search ? { prefix: options.search } : {},
56
+ ...parsedLimit && Number.isFinite(parsedLimit) && parsedLimit > 0 ? { limit: parsedLimit } : {}
57
+ });
58
+ if (data.files.length === 0) {
59
+ console.log(`No files in bucket '${bucket}'.`);
60
+ return;
61
+ }
62
+ const rows = data.files.map((f) => [
63
+ f.key,
64
+ formatBytes(f.size),
65
+ f.lastModified.split("T")[0]
66
+ ]);
67
+ console.log(formatTable(["Key", "Size", "Modified"], rows));
68
+ if (data.nextCursor) {
69
+ console.log("\n(more files available \u2014 use --limit to see more)");
70
+ }
71
+ }
72
+ async function listDrops() {
73
+ const stow = createStow();
74
+ const data = await stow.listDrops();
75
+ if (data.drops.length === 0) {
76
+ console.log("No drops yet. Create one with: stow drop <file>");
77
+ return;
78
+ }
79
+ const rows = data.drops.map((d) => [
80
+ d.filename,
81
+ formatBytes(Number(d.size)),
82
+ d.contentType,
83
+ d.url
84
+ ]);
85
+ console.log(formatTable(["Filename", "Size", "Type", "URL"], rows));
86
+ console.log(
87
+ `
88
+ Storage: ${usageBar(data.usage.bytes, data.usage.limit)} ${formatBytes(data.usage.bytes)} / ${formatBytes(data.usage.limit)}`
89
+ );
90
+ }
91
+ export {
92
+ createBucket,
93
+ listBuckets,
94
+ listDrops,
95
+ listFiles,
96
+ renameBucket
97
+ };
@@ -0,0 +1,94 @@
1
+ import {
2
+ formatBytes,
3
+ formatTable,
4
+ usageBar
5
+ } from "./chunk-MHRMBH4Y.js";
6
+ import {
7
+ apiRequest
8
+ } from "./chunk-YRHPOFJT.js";
9
+ import "./chunk-2AORPTQB.js";
10
+
11
+ // src/commands/list.ts
12
+ async function listBuckets() {
13
+ const data = await apiRequest("/api/buckets");
14
+ if (data.buckets.length === 0) {
15
+ console.log("No buckets yet. Create one with: stow buckets create <name>");
16
+ return;
17
+ }
18
+ const rows = data.buckets.map((b) => [
19
+ b.name,
20
+ b.isPublic ? "public" : "private",
21
+ `${b.fileCount} files`,
22
+ formatBytes(b.usageBytes),
23
+ b.description || ""
24
+ ]);
25
+ console.log(formatTable(["Name", "Access", "Files", "Size", "Description"], rows));
26
+ }
27
+ async function createBucket(name, options) {
28
+ const body = { name };
29
+ if (options.description) body.description = options.description;
30
+ if (options.public) body.isPublic = true;
31
+ const data = await apiRequest("/api/buckets", {
32
+ method: "POST",
33
+ body: JSON.stringify(body)
34
+ });
35
+ console.log(`Created bucket: ${data.bucket.name}`);
36
+ }
37
+ async function renameBucket(name, newName, options) {
38
+ if (!options.yes) {
39
+ console.error("Warning: Renaming a bucket will break any existing URLs using the old name.");
40
+ console.error("Use --yes to skip this warning.");
41
+ }
42
+ const data = await apiRequest(`/api/buckets/_?bucket=${encodeURIComponent(name)}`, {
43
+ method: "PATCH",
44
+ body: JSON.stringify({ name: newName })
45
+ });
46
+ console.log(`Renamed bucket: ${name} \u2192 ${data.bucket.name}`);
47
+ }
48
+ async function listFiles(bucket, options) {
49
+ const params = new URLSearchParams({ bucket });
50
+ if (options.search) params.set("prefix", options.search);
51
+ if (options.limit) params.set("limit", options.limit);
52
+ const data = await apiRequest(
53
+ `/api/files?${params}`
54
+ );
55
+ if (data.files.length === 0) {
56
+ console.log(`No files in bucket '${bucket}'.`);
57
+ return;
58
+ }
59
+ const rows = data.files.map((f) => [
60
+ f.key,
61
+ formatBytes(f.size),
62
+ f.lastModified.split("T")[0]
63
+ ]);
64
+ console.log(formatTable(["Key", "Size", "Modified"], rows));
65
+ if (data.nextCursor) {
66
+ console.log(`
67
+ (more files available \u2014 use --limit to see more)`);
68
+ }
69
+ }
70
+ async function listDrops() {
71
+ const data = await apiRequest("/api/drops");
72
+ if (data.drops.length === 0) {
73
+ console.log("No drops yet. Create one with: stow drop <file>");
74
+ return;
75
+ }
76
+ const rows = data.drops.map((d) => [
77
+ d.filename,
78
+ formatBytes(Number(d.size)),
79
+ d.contentType,
80
+ d.url
81
+ ]);
82
+ console.log(formatTable(["Filename", "Size", "Type", "URL"], rows));
83
+ console.log(
84
+ `
85
+ Storage: ${usageBar(data.usage.bytes, data.usage.limit)} ${formatBytes(data.usage.bytes)} / ${formatBytes(data.usage.limit)}`
86
+ );
87
+ }
88
+ export {
89
+ createBucket,
90
+ listBuckets,
91
+ listDrops,
92
+ listFiles,
93
+ renameBucket
94
+ };
@@ -0,0 +1,106 @@
1
+ import {
2
+ formatBytes,
3
+ formatTable,
4
+ usageBar
5
+ } from "./chunk-ZDVARBCV.js";
6
+ import {
7
+ apiRequest
8
+ } from "./chunk-FEMMZ4YZ.js";
9
+ import "./chunk-2AORPTQB.js";
10
+
11
+ // src/commands/list.ts
12
+ async function listBuckets() {
13
+ const data = await apiRequest("/api/buckets");
14
+ if (data.buckets.length === 0) {
15
+ console.log("No buckets yet. Create one with: stow buckets create <name>");
16
+ return;
17
+ }
18
+ const rows = data.buckets.map((b) => [
19
+ b.name,
20
+ b.isPublic ? "public" : "private",
21
+ `${b.fileCount} files`,
22
+ formatBytes(b.usageBytes),
23
+ b.description || ""
24
+ ]);
25
+ console.log(
26
+ formatTable(["Name", "Access", "Files", "Size", "Description"], rows)
27
+ );
28
+ }
29
+ async function createBucket(name, options) {
30
+ const body = { name };
31
+ if (options.description) {
32
+ body.description = options.description;
33
+ }
34
+ if (options.public) {
35
+ body.isPublic = true;
36
+ }
37
+ const data = await apiRequest("/api/buckets", {
38
+ method: "POST",
39
+ body: JSON.stringify(body)
40
+ });
41
+ console.log(`Created bucket: ${data.bucket.name}`);
42
+ }
43
+ async function renameBucket(name, newName, options) {
44
+ if (!options.yes) {
45
+ console.error(
46
+ "Warning: Renaming a bucket will break any existing URLs using the old name."
47
+ );
48
+ console.error("Use --yes to skip this warning.");
49
+ }
50
+ const data = await apiRequest(
51
+ `/api/buckets/_?bucket=${encodeURIComponent(name)}`,
52
+ {
53
+ method: "PATCH",
54
+ body: JSON.stringify({ name: newName })
55
+ }
56
+ );
57
+ console.log(`Renamed bucket: ${name} \u2192 ${data.bucket.name}`);
58
+ }
59
+ async function listFiles(bucket, options) {
60
+ const params = new URLSearchParams({ bucket });
61
+ if (options.search) {
62
+ params.set("prefix", options.search);
63
+ }
64
+ if (options.limit) {
65
+ params.set("limit", options.limit);
66
+ }
67
+ const data = await apiRequest(`/api/files?${params}`);
68
+ if (data.files.length === 0) {
69
+ console.log(`No files in bucket '${bucket}'.`);
70
+ return;
71
+ }
72
+ const rows = data.files.map((f) => [
73
+ f.key,
74
+ formatBytes(f.size),
75
+ f.lastModified.split("T")[0]
76
+ ]);
77
+ console.log(formatTable(["Key", "Size", "Modified"], rows));
78
+ if (data.nextCursor) {
79
+ console.log("\n(more files available \u2014 use --limit to see more)");
80
+ }
81
+ }
82
+ async function listDrops() {
83
+ const data = await apiRequest("/api/drops");
84
+ if (data.drops.length === 0) {
85
+ console.log("No drops yet. Create one with: stow drop <file>");
86
+ return;
87
+ }
88
+ const rows = data.drops.map((d) => [
89
+ d.filename,
90
+ formatBytes(Number(d.size)),
91
+ d.contentType,
92
+ d.url
93
+ ]);
94
+ console.log(formatTable(["Filename", "Size", "Type", "URL"], rows));
95
+ console.log(
96
+ `
97
+ Storage: ${usageBar(data.usage.bytes, data.usage.limit)} ${formatBytes(data.usage.bytes)} / ${formatBytes(data.usage.limit)}`
98
+ );
99
+ }
100
+ export {
101
+ createBucket,
102
+ listBuckets,
103
+ listDrops,
104
+ listFiles,
105
+ renameBucket
106
+ };
@@ -0,0 +1,106 @@
1
+ import {
2
+ formatBytes,
3
+ formatTable,
4
+ usageBar
5
+ } from "./chunk-ZDVARBCV.js";
6
+ import {
7
+ apiRequest
8
+ } from "./chunk-R5CCBTXZ.js";
9
+ import "./chunk-2AORPTQB.js";
10
+
11
+ // src/commands/list.ts
12
+ async function listBuckets() {
13
+ const data = await apiRequest("/api/buckets");
14
+ if (data.buckets.length === 0) {
15
+ console.log("No buckets yet. Create one with: stow buckets create <name>");
16
+ return;
17
+ }
18
+ const rows = data.buckets.map((b) => [
19
+ b.name,
20
+ b.isPublic ? "public" : "private",
21
+ `${b.fileCount} files`,
22
+ formatBytes(b.usageBytes),
23
+ b.description || ""
24
+ ]);
25
+ console.log(
26
+ formatTable(["Name", "Access", "Files", "Size", "Description"], rows)
27
+ );
28
+ }
29
+ async function createBucket(name, options) {
30
+ const body = { name };
31
+ if (options.description) {
32
+ body.description = options.description;
33
+ }
34
+ if (options.public) {
35
+ body.isPublic = true;
36
+ }
37
+ const data = await apiRequest("/api/buckets", {
38
+ method: "POST",
39
+ body: JSON.stringify(body)
40
+ });
41
+ console.log(`Created bucket: ${data.bucket.name}`);
42
+ }
43
+ async function renameBucket(name, newName, options) {
44
+ if (!options.yes) {
45
+ console.error(
46
+ "Warning: Renaming a bucket will break any existing URLs using the old name."
47
+ );
48
+ console.error("Use --yes to skip this warning.");
49
+ }
50
+ const data = await apiRequest(
51
+ `/api/buckets/_?bucket=${encodeURIComponent(name)}`,
52
+ {
53
+ method: "PATCH",
54
+ body: JSON.stringify({ name: newName })
55
+ }
56
+ );
57
+ console.log(`Renamed bucket: ${name} \u2192 ${data.bucket.name}`);
58
+ }
59
+ async function listFiles(bucket, options) {
60
+ const params = new URLSearchParams({ bucket });
61
+ if (options.search) {
62
+ params.set("prefix", options.search);
63
+ }
64
+ if (options.limit) {
65
+ params.set("limit", options.limit);
66
+ }
67
+ const data = await apiRequest(`/api/files?${params}`);
68
+ if (data.files.length === 0) {
69
+ console.log(`No files in bucket '${bucket}'.`);
70
+ return;
71
+ }
72
+ const rows = data.files.map((f) => [
73
+ f.key,
74
+ formatBytes(f.size),
75
+ f.lastModified.split("T")[0]
76
+ ]);
77
+ console.log(formatTable(["Key", "Size", "Modified"], rows));
78
+ if (data.nextCursor) {
79
+ console.log("\n(more files available \u2014 use --limit to see more)");
80
+ }
81
+ }
82
+ async function listDrops() {
83
+ const data = await apiRequest("/api/drops");
84
+ if (data.drops.length === 0) {
85
+ console.log("No drops yet. Create one with: stow drop <file>");
86
+ return;
87
+ }
88
+ const rows = data.drops.map((d) => [
89
+ d.filename,
90
+ formatBytes(Number(d.size)),
91
+ d.contentType,
92
+ d.url
93
+ ]);
94
+ console.log(formatTable(["Filename", "Size", "Type", "URL"], rows));
95
+ console.log(
96
+ `
97
+ Storage: ${usageBar(data.usage.bytes, data.usage.limit)} ${formatBytes(data.usage.bytes)} / ${formatBytes(data.usage.limit)}`
98
+ );
99
+ }
100
+ export {
101
+ createBucket,
102
+ listBuckets,
103
+ listDrops,
104
+ listFiles,
105
+ renameBucket
106
+ };
@@ -0,0 +1,106 @@
1
+ import {
2
+ formatBytes,
3
+ formatTable,
4
+ usageBar
5
+ } from "./chunk-ZDVARBCV.js";
6
+ import {
7
+ apiRequest
8
+ } from "./chunk-LYCXXF2T.js";
9
+ import "./chunk-OZ7QQTIZ.js";
10
+
11
+ // src/commands/list.ts
12
+ async function listBuckets() {
13
+ const data = await apiRequest("/api/buckets");
14
+ if (data.buckets.length === 0) {
15
+ console.log("No buckets yet. Create one with: stow buckets create <name>");
16
+ return;
17
+ }
18
+ const rows = data.buckets.map((b) => [
19
+ b.name,
20
+ b.isPublic ? "public" : "private",
21
+ `${b.fileCount} files`,
22
+ formatBytes(b.usageBytes),
23
+ b.description || ""
24
+ ]);
25
+ console.log(
26
+ formatTable(["Name", "Access", "Files", "Size", "Description"], rows)
27
+ );
28
+ }
29
+ async function createBucket(name, options) {
30
+ const body = { name };
31
+ if (options.description) {
32
+ body.description = options.description;
33
+ }
34
+ if (options.public) {
35
+ body.isPublic = true;
36
+ }
37
+ const data = await apiRequest("/api/buckets", {
38
+ method: "POST",
39
+ body: JSON.stringify(body)
40
+ });
41
+ console.log(`Created bucket: ${data.bucket.name}`);
42
+ }
43
+ async function renameBucket(name, newName, options) {
44
+ if (!options.yes) {
45
+ console.error(
46
+ "Warning: Renaming a bucket will break any existing URLs using the old name."
47
+ );
48
+ console.error("Use --yes to skip this warning.");
49
+ }
50
+ const data = await apiRequest(
51
+ `/api/buckets/_?bucket=${encodeURIComponent(name)}`,
52
+ {
53
+ method: "PATCH",
54
+ body: JSON.stringify({ name: newName })
55
+ }
56
+ );
57
+ console.log(`Renamed bucket: ${name} \u2192 ${data.bucket.name}`);
58
+ }
59
+ async function listFiles(bucket, options) {
60
+ const params = new URLSearchParams({ bucket });
61
+ if (options.search) {
62
+ params.set("prefix", options.search);
63
+ }
64
+ if (options.limit) {
65
+ params.set("limit", options.limit);
66
+ }
67
+ const data = await apiRequest(`/api/files?${params}`);
68
+ if (data.files.length === 0) {
69
+ console.log(`No files in bucket '${bucket}'.`);
70
+ return;
71
+ }
72
+ const rows = data.files.map((f) => [
73
+ f.key,
74
+ formatBytes(f.size),
75
+ f.lastModified.split("T")[0]
76
+ ]);
77
+ console.log(formatTable(["Key", "Size", "Modified"], rows));
78
+ if (data.nextCursor) {
79
+ console.log("\n(more files available \u2014 use --limit to see more)");
80
+ }
81
+ }
82
+ async function listDrops() {
83
+ const data = await apiRequest("/api/drops");
84
+ if (data.drops.length === 0) {
85
+ console.log("No drops yet. Create one with: stow drop <file>");
86
+ return;
87
+ }
88
+ const rows = data.drops.map((d) => [
89
+ d.filename,
90
+ formatBytes(Number(d.size)),
91
+ d.contentType,
92
+ d.url
93
+ ]);
94
+ console.log(formatTable(["Filename", "Size", "Type", "URL"], rows));
95
+ console.log(
96
+ `
97
+ Storage: ${usageBar(data.usage.bytes, data.usage.limit)} ${formatBytes(data.usage.bytes)} / ${formatBytes(data.usage.limit)}`
98
+ );
99
+ }
100
+ export {
101
+ createBucket,
102
+ listBuckets,
103
+ listDrops,
104
+ listFiles,
105
+ renameBucket
106
+ };