stow-cli 1.0.1 → 1.0.3

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 (56) hide show
  1. package/dist/{app-2A2CFVBC.js → app-JPUDM4LJ.js} +1 -1
  2. package/dist/backfill-QZTVNJZM.js +61 -0
  3. package/dist/buckets-JQKZ3PH3.js +63 -0
  4. package/dist/{chunk-ZDVARBCV.js → chunk-ELSDWMEB.js} +8 -2
  5. package/dist/chunk-WAQSCS57.js +38 -0
  6. package/dist/cli.js +508 -15
  7. package/dist/drops-QXGTYB5E.js +39 -0
  8. package/dist/files-OCYICIAM.js +165 -0
  9. package/dist/health-YMZTZUFX.js +52 -0
  10. package/dist/jobs-6JY4SVV5.js +92 -0
  11. package/dist/jobs-OKKGKSIH.js +83 -0
  12. package/dist/maintenance-EZUHQK5Q.js +86 -0
  13. package/dist/profiles-GWLBEEIT.js +50 -0
  14. package/dist/queues-EQX7EJZF.js +51 -0
  15. package/dist/search-2PXM6XQ6.js +108 -0
  16. package/dist/tags-LSVEIIUF.js +46 -0
  17. package/dist/{upload-MI6VFGTC.js → upload-ESYKBYHA.js} +3 -3
  18. package/dist/{whoami-754O5IML.js → whoami-4UYMSRVP.js} +1 -1
  19. package/package.json +1 -1
  20. package/dist/app-2H4TLSN7.js +0 -239
  21. package/dist/app-HYCPA7GA.js +0 -239
  22. package/dist/app-IZGSPZPX.js +0 -239
  23. package/dist/app-UGUM75MC.js +0 -239
  24. package/dist/app-XPOEAZJC.js +0 -239
  25. package/dist/app-YITP5APT.js +0 -233
  26. package/dist/chunk-2AORPTQB.js +0 -23
  27. package/dist/chunk-FEMMZ4YZ.js +0 -125
  28. package/dist/chunk-LYCXXF2T.js +0 -79
  29. package/dist/chunk-MHRMBH4Y.js +0 -36
  30. package/dist/chunk-R5CCBTXZ.js +0 -79
  31. package/dist/chunk-YRHPOFJT.js +0 -115
  32. package/dist/cli.d.ts +0 -1
  33. package/dist/delete-AECEJX5W.js +0 -18
  34. package/dist/delete-KYOZEODD.js +0 -18
  35. package/dist/delete-OLOAJRRO.js +0 -18
  36. package/dist/delete-V4EY4UBG.js +0 -18
  37. package/dist/list-7A3VZA2T.js +0 -97
  38. package/dist/list-DHXVIMRI.js +0 -94
  39. package/dist/list-DJEAKEZJ.js +0 -106
  40. package/dist/list-DQRU6QHO.js +0 -106
  41. package/dist/list-I5A6LTHX.js +0 -106
  42. package/dist/list-KEQPJY7I.js +0 -109
  43. package/dist/list-Z3MPT6MI.js +0 -109
  44. package/dist/open-2YNHG3MA.js +0 -15
  45. package/dist/upload-3NS5O3UL.js +0 -120
  46. package/dist/upload-B2PGW3AN.js +0 -125
  47. package/dist/upload-DQDBDIDI.js +0 -92
  48. package/dist/upload-FGNGNPC3.js +0 -93
  49. package/dist/upload-HKUPWTK2.js +0 -173
  50. package/dist/upload-JDVSJVWK.js +0 -173
  51. package/dist/upload-K4H7ZVRW.js +0 -98
  52. package/dist/whoami-2SLCNVKP.js +0 -27
  53. package/dist/whoami-DOMX3Z5K.js +0 -28
  54. package/dist/whoami-IPMCUEUH.js +0 -27
  55. package/dist/whoami-JSQA2IDN.js +0 -27
  56. package/dist/whoami-RKH5HHPR.js +0 -27
@@ -0,0 +1,165 @@
1
+ import {
2
+ formatBytes,
3
+ formatTable,
4
+ outputJson
5
+ } from "./chunk-ELSDWMEB.js";
6
+ import {
7
+ createStow
8
+ } from "./chunk-JYOMHKFS.js";
9
+ import {
10
+ getApiKey,
11
+ getBaseUrl
12
+ } from "./chunk-OZ7QQTIZ.js";
13
+
14
+ // src/commands/files.ts
15
+ async function listFiles(bucket, options) {
16
+ const stow = createStow();
17
+ const parsedLimit = options.limit ? Number.parseInt(options.limit, 10) : null;
18
+ const data = await stow.listFiles({
19
+ bucket,
20
+ ...options.search ? { prefix: options.search } : {},
21
+ ...parsedLimit && Number.isFinite(parsedLimit) && parsedLimit > 0 ? { limit: parsedLimit } : {}
22
+ });
23
+ if (options.json) {
24
+ outputJson(data);
25
+ return;
26
+ }
27
+ if (data.files.length === 0) {
28
+ console.log(`No files in bucket '${bucket}'.`);
29
+ return;
30
+ }
31
+ const rows = data.files.map((f) => [
32
+ f.key,
33
+ formatBytes(f.size),
34
+ f.lastModified.split("T")[0] ?? f.lastModified
35
+ ]);
36
+ console.log(formatTable(["Key", "Size", "Modified"], rows));
37
+ if (data.nextCursor) {
38
+ console.log("\n(more files available \u2014 use --limit to see more)");
39
+ }
40
+ }
41
+ async function getFile(bucket, key, options) {
42
+ const stow = createStow();
43
+ const file = await stow.getFile(key, { bucket });
44
+ if (options.json) {
45
+ outputJson(file);
46
+ return;
47
+ }
48
+ console.log(
49
+ formatTable(
50
+ ["Field", "Value"],
51
+ [
52
+ ["Key", file.key],
53
+ ["Size", formatBytes(file.size)],
54
+ ["Type", file.contentType],
55
+ ["Created", file.createdAt],
56
+ ["URL", file.url ?? "(private)"],
57
+ [
58
+ "Dimensions",
59
+ file.width && file.height ? `${file.width}\xD7${file.height}` : "\u2014"
60
+ ],
61
+ ["Duration", file.duration ? `${file.duration}s` : "\u2014"],
62
+ ["Embedding", file.embeddingStatus ?? "\u2014"]
63
+ ]
64
+ )
65
+ );
66
+ if (file.metadata && Object.keys(file.metadata).length > 0) {
67
+ console.log("\nMetadata:");
68
+ for (const [k, v] of Object.entries(file.metadata)) {
69
+ console.log(` ${k}: ${v}`);
70
+ }
71
+ }
72
+ }
73
+ async function updateFile(bucket, key, options) {
74
+ if (!options.metadata || options.metadata.length === 0) {
75
+ console.error("Error: At least one -m key=value pair is required.");
76
+ process.exit(1);
77
+ }
78
+ const metadata = {};
79
+ for (const pair of options.metadata) {
80
+ const idx = pair.indexOf("=");
81
+ if (idx === -1) {
82
+ console.error(`Error: Invalid metadata format '${pair}'. Use key=value.`);
83
+ process.exit(1);
84
+ }
85
+ metadata[pair.slice(0, idx)] = pair.slice(idx + 1);
86
+ }
87
+ const stow = createStow();
88
+ const file = await stow.updateFileMetadata(key, metadata, { bucket });
89
+ if (options.json) {
90
+ outputJson(file);
91
+ return;
92
+ }
93
+ console.log(`Updated ${key}`);
94
+ }
95
+ async function enrichFile(bucket, key) {
96
+ const stow = createStow();
97
+ const results = await Promise.allSettled([
98
+ stow.generateTitle(key, { bucket }),
99
+ stow.generateDescription(key, { bucket }),
100
+ stow.generateAltText(key, { bucket })
101
+ ]);
102
+ const labels = ["Title", "Description", "Alt text"];
103
+ for (let i = 0; i < results.length; i++) {
104
+ const result = results[i];
105
+ const label = labels[i];
106
+ if (result.status === "fulfilled") {
107
+ console.log(` ${label}: triggered`);
108
+ } else {
109
+ console.error(` ${label}: failed \u2014 ${result.reason}`);
110
+ }
111
+ }
112
+ const succeeded = results.filter((r) => r.status === "fulfilled").length;
113
+ console.log(
114
+ `
115
+ Enriched ${key}: ${succeeded}/${results.length} tasks dispatched`
116
+ );
117
+ }
118
+ async function listMissing(bucket, type, options) {
119
+ const validTypes = ["dimensions", "embeddings", "colors"];
120
+ if (!validTypes.includes(type)) {
121
+ console.error(
122
+ `Error: Invalid type '${type}'. Must be one of: ${validTypes.join(", ")}`
123
+ );
124
+ process.exit(1);
125
+ }
126
+ const parsedLimit = options.limit ? Number.parseInt(options.limit, 10) : null;
127
+ const baseUrl = getBaseUrl();
128
+ const apiKey = getApiKey();
129
+ const params = new URLSearchParams({
130
+ bucket,
131
+ missing: type,
132
+ ...parsedLimit && Number.isFinite(parsedLimit) && parsedLimit > 0 ? { limit: String(parsedLimit) } : {}
133
+ });
134
+ const res = await fetch(`${baseUrl}/api/files?${params}`, {
135
+ headers: { "x-api-key": apiKey }
136
+ });
137
+ if (!res.ok) {
138
+ const body = await res.json().catch(() => ({}));
139
+ throw new Error(body.error ?? `HTTP ${res.status}`);
140
+ }
141
+ const data = await res.json();
142
+ if (options.json) {
143
+ outputJson(data);
144
+ return;
145
+ }
146
+ if (data.files.length === 0) {
147
+ console.log(`No files missing ${type} in bucket '${bucket}'.`);
148
+ return;
149
+ }
150
+ const rows = data.files.map((f) => [
151
+ f.key,
152
+ formatBytes(f.size),
153
+ f.lastModified.split("T")[0] ?? f.lastModified
154
+ ]);
155
+ console.log(formatTable(["Key", "Size", "Modified"], rows));
156
+ console.log(`
157
+ ${data.files.length} files missing ${type}`);
158
+ }
159
+ export {
160
+ enrichFile,
161
+ getFile,
162
+ listFiles,
163
+ listMissing,
164
+ updateFile
165
+ };
@@ -0,0 +1,52 @@
1
+ import {
2
+ adminRequest
3
+ } from "./chunk-WAQSCS57.js";
4
+ import {
5
+ formatTable,
6
+ outputJson
7
+ } from "./chunk-ELSDWMEB.js";
8
+ import "./chunk-OZ7QQTIZ.js";
9
+
10
+ // src/commands/admin/health.ts
11
+ async function health(options) {
12
+ const result = await adminRequest({
13
+ method: "GET",
14
+ path: "/api/health"
15
+ });
16
+ if (options.json) {
17
+ outputJson(result);
18
+ return;
19
+ }
20
+ const statusIcon = result.status === "ok" ? "\u2713" : "\u2717";
21
+ console.log(`${statusIcon} ${result.status} (${result.version})`);
22
+ console.log(` ${result.timestamp}`);
23
+ console.log("\nChecks:");
24
+ for (const [name, status] of Object.entries(result.checks)) {
25
+ const icon = status === "ok" ? "\u2713" : "\u2717";
26
+ console.log(` ${icon} ${name}`);
27
+ }
28
+ if (result.queues) {
29
+ console.log("\nQueues:");
30
+ const rows = [];
31
+ for (const [name, counts] of Object.entries(result.queues)) {
32
+ if (counts === "unavailable") {
33
+ rows.push([name, "\u2014", "\u2014", "\u2014", "\u2014"]);
34
+ } else {
35
+ const c = counts;
36
+ rows.push([
37
+ name,
38
+ String(c.waiting ?? 0),
39
+ String(c.active ?? 0),
40
+ String(c.completed ?? 0),
41
+ String(c.failed ?? 0)
42
+ ]);
43
+ }
44
+ }
45
+ console.log(
46
+ formatTable(["Queue", "Waiting", "Active", "Completed", "Failed"], rows)
47
+ );
48
+ }
49
+ }
50
+ export {
51
+ health
52
+ };
@@ -0,0 +1,92 @@
1
+ import {
2
+ formatTable,
3
+ outputJson
4
+ } from "./chunk-ELSDWMEB.js";
5
+ import {
6
+ getApiKey,
7
+ getBaseUrl
8
+ } from "./chunk-OZ7QQTIZ.js";
9
+
10
+ // src/commands/jobs.ts
11
+ async function bucketRequest(opts) {
12
+ const baseUrl = getBaseUrl();
13
+ const apiKey = getApiKey();
14
+ const res = await fetch(`${baseUrl}${opts.path}`, {
15
+ method: opts.method,
16
+ headers: {
17
+ "x-api-key": apiKey,
18
+ ...opts.body ? { "Content-Type": "application/json" } : {}
19
+ },
20
+ ...opts.body ? { body: JSON.stringify(opts.body) } : {}
21
+ });
22
+ if (!res.ok) {
23
+ const body = await res.json().catch(() => ({ error: res.statusText }));
24
+ const message = body.error ?? `HTTP ${res.status}`;
25
+ throw new Error(message);
26
+ }
27
+ return await res.json();
28
+ }
29
+ function formatTimestamp(ts) {
30
+ return new Date(ts).toISOString().replace("T", " ").slice(0, 19);
31
+ }
32
+ async function listJobs(bucketId, options) {
33
+ const params = new URLSearchParams();
34
+ if (options.status) {
35
+ params.set("status", options.status);
36
+ }
37
+ if (options.queue) {
38
+ params.set("queue", options.queue);
39
+ }
40
+ if (options.limit) {
41
+ params.set("limit", options.limit);
42
+ }
43
+ const qs = params.toString();
44
+ const path = `/api/buckets/${bucketId}/jobs${qs ? `?${qs}` : ""}`;
45
+ const result = await bucketRequest({
46
+ method: "GET",
47
+ path
48
+ });
49
+ if (options.json) {
50
+ outputJson(result.jobs);
51
+ return;
52
+ }
53
+ if (result.jobs.length === 0) {
54
+ console.log("No jobs found.");
55
+ return;
56
+ }
57
+ const rows = result.jobs.map((job) => [
58
+ job.jobId,
59
+ job.queueName,
60
+ job.status,
61
+ job.data.fileId.slice(0, 8) + "\u2026",
62
+ formatTimestamp(job.timestamp),
63
+ job.failedReason ? job.failedReason.slice(0, 40) : ""
64
+ ]);
65
+ console.log(
66
+ formatTable(["ID", "Queue", "Status", "File", "Created", "Error"], rows)
67
+ );
68
+ }
69
+ async function retryJob(jobId, options) {
70
+ const result = await bucketRequest({
71
+ method: "POST",
72
+ path: `/api/buckets/${options.bucket}/jobs/${jobId}/retry`,
73
+ body: { queue: options.queue }
74
+ });
75
+ if (result.retried) {
76
+ console.log(`Job ${jobId} retried.`);
77
+ }
78
+ }
79
+ async function deleteJob(jobId, options) {
80
+ const result = await bucketRequest({
81
+ method: "DELETE",
82
+ path: `/api/buckets/${options.bucket}/jobs/${jobId}?queue=${encodeURIComponent(options.queue)}`
83
+ });
84
+ if (result.deleted) {
85
+ console.log(`Job ${jobId} removed.`);
86
+ }
87
+ }
88
+ export {
89
+ deleteJob,
90
+ listJobs,
91
+ retryJob
92
+ };
@@ -0,0 +1,83 @@
1
+ import {
2
+ adminRequest
3
+ } from "./chunk-WAQSCS57.js";
4
+ import {
5
+ formatTable,
6
+ outputJson
7
+ } from "./chunk-ELSDWMEB.js";
8
+ import "./chunk-OZ7QQTIZ.js";
9
+
10
+ // src/commands/admin/jobs.ts
11
+ function formatTimestamp(ts) {
12
+ return new Date(ts).toISOString().replace("T", " ").slice(0, 19);
13
+ }
14
+ async function listAdminJobs(options) {
15
+ const params = new URLSearchParams();
16
+ if (options.org) {
17
+ params.set("orgId", options.org);
18
+ }
19
+ if (options.bucket) {
20
+ params.set("bucketId", options.bucket);
21
+ }
22
+ if (options.status) {
23
+ params.set("status", options.status);
24
+ }
25
+ if (options.queue) {
26
+ params.set("queue", options.queue);
27
+ }
28
+ if (options.limit) {
29
+ params.set("limit", options.limit);
30
+ }
31
+ const qs = params.toString();
32
+ const result = await adminRequest({
33
+ method: "GET",
34
+ path: `/api/admin/jobs${qs ? `?${qs}` : ""}`
35
+ });
36
+ if (options.json) {
37
+ outputJson(result.jobs);
38
+ return;
39
+ }
40
+ if (result.jobs.length === 0) {
41
+ console.log("No jobs found.");
42
+ return;
43
+ }
44
+ const rows = result.jobs.map((job) => [
45
+ job.jobId,
46
+ job.queueName,
47
+ job.status,
48
+ job.data.fileId.slice(0, 8) + "\u2026",
49
+ job.data.orgId.slice(0, 8) + "\u2026",
50
+ formatTimestamp(job.timestamp),
51
+ job.failedReason ? job.failedReason.slice(0, 40) : ""
52
+ ]);
53
+ console.log(
54
+ formatTable(
55
+ ["ID", "Queue", "Status", "File", "Org", "Created", "Error"],
56
+ rows
57
+ )
58
+ );
59
+ }
60
+ async function retryAdminJob(jobId, options) {
61
+ const result = await adminRequest({
62
+ method: "POST",
63
+ path: `/api/admin/jobs/${jobId}/retry`,
64
+ body: { queue: options.queue }
65
+ });
66
+ if (result.retried) {
67
+ console.log(`Job ${jobId} retried.`);
68
+ }
69
+ }
70
+ async function deleteAdminJob(jobId, options) {
71
+ const result = await adminRequest({
72
+ method: "DELETE",
73
+ path: `/api/admin/jobs/${jobId}?queue=${encodeURIComponent(options.queue)}`
74
+ });
75
+ if (result.deleted) {
76
+ console.log(`Job ${jobId} removed.`);
77
+ }
78
+ }
79
+ export {
80
+ deleteAdminJob,
81
+ listAdminJobs,
82
+ retryAdminJob
83
+ };
@@ -0,0 +1,86 @@
1
+ import {
2
+ adminRequest
3
+ } from "./chunk-WAQSCS57.js";
4
+ import {
5
+ outputJson
6
+ } from "./chunk-ELSDWMEB.js";
7
+ import "./chunk-OZ7QQTIZ.js";
8
+
9
+ // src/commands/admin/maintenance.ts
10
+ async function cleanupDrops(options) {
11
+ const params = new URLSearchParams();
12
+ if (options.maxAgeHours) {
13
+ params.set("maxAgeHours", options.maxAgeHours);
14
+ }
15
+ if (options.dryRun) {
16
+ params.set("dryRun", "true");
17
+ }
18
+ const qs = params.toString();
19
+ const result = await adminRequest({
20
+ method: "POST",
21
+ path: `/api/admin/cleanup-drops${qs ? `?${qs}` : ""}`
22
+ });
23
+ if (options.json) {
24
+ outputJson(result);
25
+ return;
26
+ }
27
+ console.log(
28
+ options.dryRun ? `[dry run] Would clean up ${result.count ?? 0} drops` : `Cleaned up ${result.deleted ?? 0} drops`
29
+ );
30
+ }
31
+ async function purgeEvents(options) {
32
+ const params = new URLSearchParams();
33
+ if (options.dryRun) {
34
+ params.set("dryRun", "true");
35
+ }
36
+ const qs = params.toString();
37
+ const result = await adminRequest({
38
+ method: "POST",
39
+ path: `/api/admin/purge-events${qs ? `?${qs}` : ""}`
40
+ });
41
+ if (options.json) {
42
+ outputJson(result);
43
+ return;
44
+ }
45
+ console.log(
46
+ options.dryRun ? `[dry run] Would purge ${result.count ?? 0} events` : `Purged ${result.deleted ?? 0} events`
47
+ );
48
+ }
49
+ async function reconcileFiles(options) {
50
+ const params = new URLSearchParams({ bucketId: options.bucket });
51
+ if (options.dryRun) {
52
+ params.set("dryRun", "true");
53
+ }
54
+ const result = await adminRequest({
55
+ method: "POST",
56
+ path: `/api/admin/reconcile-files?${params}`
57
+ });
58
+ if (options.json) {
59
+ outputJson(result);
60
+ return;
61
+ }
62
+ if (options.dryRun) {
63
+ console.log(
64
+ `[dry run] ${result.mismatched ?? 0} files need reconciliation`
65
+ );
66
+ } else {
67
+ console.log(`Reconciled ${result.reconciled ?? 0} files`);
68
+ }
69
+ }
70
+ async function retrySyncFailures(options) {
71
+ const result = await adminRequest({
72
+ method: "POST",
73
+ path: "/api/admin/retry-sync-failures"
74
+ });
75
+ if (options.json) {
76
+ outputJson(result);
77
+ return;
78
+ }
79
+ console.log(`Retried ${result.retried ?? 0} sync failures`);
80
+ }
81
+ export {
82
+ cleanupDrops,
83
+ purgeEvents,
84
+ reconcileFiles,
85
+ retrySyncFailures
86
+ };
@@ -0,0 +1,50 @@
1
+ import {
2
+ formatTable,
3
+ outputJson
4
+ } from "./chunk-ELSDWMEB.js";
5
+ import {
6
+ createStow
7
+ } from "./chunk-JYOMHKFS.js";
8
+ import "./chunk-OZ7QQTIZ.js";
9
+
10
+ // src/commands/profiles.ts
11
+ async function createProfile(options) {
12
+ const stow = createStow();
13
+ const profile = await stow.profiles.create({
14
+ name: options.name,
15
+ ...options.bucket ? { bucketId: options.bucket } : {}
16
+ });
17
+ if (options.json) {
18
+ outputJson(profile);
19
+ return;
20
+ }
21
+ console.log(`Created profile: ${profile.name} (${profile.id})`);
22
+ }
23
+ async function getProfile(id, options) {
24
+ const stow = createStow();
25
+ const profile = await stow.profiles.get(id);
26
+ if (options.json) {
27
+ outputJson(profile);
28
+ return;
29
+ }
30
+ console.log(`Profile: ${profile.name} (${profile.id})`);
31
+ if (profile.clusters && profile.clusters.length > 0) {
32
+ console.log("\nClusters:");
33
+ const rows = profile.clusters.map((c) => [
34
+ String(c.index),
35
+ c.name ?? "(unnamed)",
36
+ String(c.signalCount)
37
+ ]);
38
+ console.log(formatTable(["Index", "Name", "Signals"], rows));
39
+ }
40
+ }
41
+ async function deleteProfile(id) {
42
+ const stow = createStow();
43
+ await stow.profiles.delete(id);
44
+ console.log(`Deleted profile: ${id}`);
45
+ }
46
+ export {
47
+ createProfile,
48
+ deleteProfile,
49
+ getProfile
50
+ };
@@ -0,0 +1,51 @@
1
+ import {
2
+ adminRequest
3
+ } from "./chunk-WAQSCS57.js";
4
+ import {
5
+ formatTable,
6
+ outputJson
7
+ } from "./chunk-ELSDWMEB.js";
8
+ import "./chunk-OZ7QQTIZ.js";
9
+
10
+ // src/commands/admin/queues.ts
11
+ async function listQueues(options) {
12
+ const result = await adminRequest({
13
+ method: "GET",
14
+ path: "/api/admin/queues"
15
+ });
16
+ if (options.json) {
17
+ outputJson(result.queues);
18
+ return;
19
+ }
20
+ const entries = Object.entries(result.queues);
21
+ if (entries.length === 0) {
22
+ console.log("No queues found.");
23
+ return;
24
+ }
25
+ const rows = entries.map(([name, counts]) => [
26
+ name,
27
+ String(counts.waiting),
28
+ String(counts.active),
29
+ String(counts.completed),
30
+ String(counts.failed)
31
+ ]);
32
+ console.log(
33
+ formatTable(["Queue", "Waiting", "Active", "Completed", "Failed"], rows)
34
+ );
35
+ }
36
+ async function cleanQueue(queueName, options) {
37
+ const status = options.failed ? "failed" : "completed";
38
+ const grace = options.grace ? Number(options.grace) : 0;
39
+ const result = await adminRequest({
40
+ method: "POST",
41
+ path: `/api/admin/queues/${encodeURIComponent(queueName)}/clean`,
42
+ body: { status, grace }
43
+ });
44
+ console.log(
45
+ `Cleaned ${result.cleaned} ${result.status} jobs from ${result.queue}.`
46
+ );
47
+ }
48
+ export {
49
+ cleanQueue,
50
+ listQueues
51
+ };
@@ -0,0 +1,108 @@
1
+ import {
2
+ formatBytes,
3
+ formatTable,
4
+ outputJson
5
+ } from "./chunk-ELSDWMEB.js";
6
+ import {
7
+ createStow
8
+ } from "./chunk-JYOMHKFS.js";
9
+ import "./chunk-OZ7QQTIZ.js";
10
+
11
+ // src/commands/search.ts
12
+ async function textSearch(query, options) {
13
+ const stow = createStow();
14
+ const parsedLimit = options.limit ? Number.parseInt(options.limit, 10) : null;
15
+ const data = await stow.search.text({
16
+ query,
17
+ ...options.bucket ? { bucket: options.bucket } : {},
18
+ ...parsedLimit && parsedLimit > 0 ? { limit: parsedLimit } : {}
19
+ });
20
+ if (options.json) {
21
+ outputJson(data);
22
+ return;
23
+ }
24
+ if (data.results.length === 0) {
25
+ console.log("No results found.");
26
+ return;
27
+ }
28
+ const rows = data.results.map((r) => [
29
+ r.key,
30
+ formatBytes(r.size),
31
+ r.similarity.toFixed(3)
32
+ ]);
33
+ console.log(formatTable(["Key", "Size", "Similarity"], rows));
34
+ }
35
+ async function similarSearch(options) {
36
+ const stow = createStow();
37
+ const parsedLimit = options.limit ? Number.parseInt(options.limit, 10) : null;
38
+ const data = await stow.search.similar({
39
+ fileKey: options.file,
40
+ ...options.bucket ? { bucket: options.bucket } : {},
41
+ ...parsedLimit && parsedLimit > 0 ? { limit: parsedLimit } : {}
42
+ });
43
+ if (options.json) {
44
+ outputJson(data);
45
+ return;
46
+ }
47
+ if (data.results.length === 0) {
48
+ console.log("No similar files found.");
49
+ return;
50
+ }
51
+ const rows = data.results.map((r) => [
52
+ r.key,
53
+ formatBytes(r.size),
54
+ r.similarity.toFixed(3)
55
+ ]);
56
+ console.log(formatTable(["Key", "Size", "Similarity"], rows));
57
+ }
58
+ async function colorSearch(options) {
59
+ const stow = createStow();
60
+ const parsedLimit = options.limit ? Number.parseInt(options.limit, 10) : null;
61
+ const data = await stow.search.color({
62
+ hex: options.hex,
63
+ ...options.bucket ? { bucket: options.bucket } : {},
64
+ ...parsedLimit && parsedLimit > 0 ? { limit: parsedLimit } : {}
65
+ });
66
+ if (options.json) {
67
+ outputJson(data);
68
+ return;
69
+ }
70
+ if (data.results.length === 0) {
71
+ console.log("No results found.");
72
+ return;
73
+ }
74
+ const rows = data.results.map((r) => [
75
+ r.key,
76
+ r.contentType,
77
+ r.colorDistance.toFixed(3)
78
+ ]);
79
+ console.log(formatTable(["Key", "Type", "Distance"], rows));
80
+ }
81
+ async function diverseSearch(options) {
82
+ const stow = createStow();
83
+ const parsedLimit = options.limit ? Number.parseInt(options.limit, 10) : null;
84
+ const data = await stow.search.diverse({
85
+ ...options.bucket ? { bucket: options.bucket } : {},
86
+ ...parsedLimit && parsedLimit > 0 ? { limit: parsedLimit } : {}
87
+ });
88
+ if (options.json) {
89
+ outputJson(data);
90
+ return;
91
+ }
92
+ if (data.results.length === 0) {
93
+ console.log("No results found.");
94
+ return;
95
+ }
96
+ const rows = data.results.map((r) => [
97
+ r.key,
98
+ formatBytes(r.size),
99
+ r.similarity.toFixed(3)
100
+ ]);
101
+ console.log(formatTable(["Key", "Size", "Similarity"], rows));
102
+ }
103
+ export {
104
+ colorSearch,
105
+ diverseSearch,
106
+ similarSearch,
107
+ textSearch
108
+ };