@mediamonks/canopy-cli 0.7.26 → 0.7.27
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/docs/cli-feedback.md +9 -6
- package/dist/{docs-x3hMtUzT.mjs → docs-CuS9nIXm.mjs} +1 -1
- package/dist/{feedback-C9m3dNkJ.mjs → feedback-DormOsQa.mjs} +38 -18
- package/dist/index.mjs +5 -5
- package/dist/{package-CBso2611.mjs → package-CsmBH_fN.mjs} +1 -1
- package/dist/{skill-DmVlZXgv.mjs → skill-DX18WOap.mjs} +1 -1
- package/dist/{upgrade-C7u8pxeV.mjs → upgrade-PfdH0NPe.mjs} +1 -1
- package/package.json +1 -1
|
@@ -24,12 +24,15 @@ canopy feedback attach <id> ./after-fix.png --comment "fixed — see the shot"
|
|
|
24
24
|
|
|
25
25
|
## Subcommands
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
Every report has a key made of its project and a number, like
|
|
28
|
+
`my-project-17`. Inbox commands resolve the project the usual way —
|
|
29
|
+
`canopy.json` in the target directory, or `--project <slug>` — and require
|
|
30
|
+
project membership; inside the project you can refer to a report by its
|
|
31
|
+
number alone (`canopy feedback show 17`). The item-scoped commands (`show`,
|
|
32
|
+
`comment`, `status`, `attach`) also take the full key from anywhere, with no
|
|
33
|
+
project context: the key names its project. Older ids from before keys
|
|
34
|
+
existed still work wherever a key does. `list` and `show` take `--json` for
|
|
35
|
+
machine-readable output.
|
|
33
36
|
|
|
34
37
|
- `list [--status <s>] [--kind <k>]` — the project's inbox. Statuses:
|
|
35
38
|
`investigate`, `investigated`, `accepted`, `in_progress`, `resolved`,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as version } from "./package-
|
|
1
|
+
import { t as version } from "./package-CsmBH_fN.mjs";
|
|
2
2
|
import { n as siteConfig } from "./site-DM2J10CB.mjs";
|
|
3
3
|
import { i as latestKnownVersion, r as compareSemver } from "./version-check-CcsA1QjI.mjs";
|
|
4
4
|
import { r as reportErrors } from "./ui-DR-siu2S.mjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as version } from "./package-
|
|
1
|
+
import { t as version } from "./package-CsmBH_fN.mjs";
|
|
2
2
|
import { a as projectDirArgs, c as resolveProject, d as tryResolveProject, n as siteConfig, u as tryReadCanopyJson } from "./site-DM2J10CB.mjs";
|
|
3
3
|
import { c as apiDownload, l as apiRequest, r as reportErrors, t as formatDateTime, u as apiUpload } from "./ui-DR-siu2S.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
@@ -72,19 +72,38 @@ const jsonArg = { json: {
|
|
|
72
72
|
type: "boolean",
|
|
73
73
|
description: "Machine-readable JSON output"
|
|
74
74
|
} };
|
|
75
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
76
|
+
const KEY_RE = /^([a-z][a-z0-9-]*)-(\d+)$/;
|
|
75
77
|
/**
|
|
76
|
-
* The project
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* an id from a notification or a Slack thread, in a directory that isn't the
|
|
80
|
-
* project.
|
|
78
|
+
* The project slug a full key names (`kitchen-sink-17` → `kitchen-sink`), or
|
|
79
|
+
* null for a UUID or a bare number. UUIDs are checked first: one whose last
|
|
80
|
+
* group is all digits would otherwise look like a key.
|
|
81
81
|
*/
|
|
82
|
-
|
|
82
|
+
function slugOfKey(ref) {
|
|
83
|
+
if (UUID_RE.test(ref)) return null;
|
|
84
|
+
return KEY_RE.exec(ref.toLowerCase())?.[1] ?? null;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The project an item-scoped command targets. A full key names its own
|
|
88
|
+
* project and wins over the directory — `canopy feedback show other-3` from
|
|
89
|
+
* inside `sink` means other's report, not a miss on sink's. Otherwise
|
|
90
|
+
* `--project` or canopy.json; and failing those, the API's project-less
|
|
91
|
+
* lookup for a UUID from an old link. A bare number is only meaningful with a
|
|
92
|
+
* project in hand.
|
|
93
|
+
*/
|
|
94
|
+
async function resolveItemSlug(args, ref) {
|
|
95
|
+
const fromKey = slugOfKey(ref);
|
|
96
|
+
if (fromKey) return fromKey;
|
|
83
97
|
const { slug } = tryResolveProject(args);
|
|
84
98
|
if (slug) return slug;
|
|
85
|
-
|
|
99
|
+
if (/^\d+$/.test(ref)) throw new Error(`"${ref}" is a bare report number — run this inside the project, pass --project, or use the full key (e.g. my-project-${ref}).`);
|
|
100
|
+
const { project } = await apiRequest("GET", `/feedback/${encodeURIComponent(ref)}`);
|
|
86
101
|
return project.slug;
|
|
87
102
|
}
|
|
103
|
+
/** What a report is called in output: its key, or the UUID on pre-key rows. */
|
|
104
|
+
function refOf(item) {
|
|
105
|
+
return item.key ?? item.id;
|
|
106
|
+
}
|
|
88
107
|
function firstLine(body) {
|
|
89
108
|
const line = body.split("\n")[0] ?? "";
|
|
90
109
|
return line.length > 72 ? `${line.slice(0, 71)}…` : line;
|
|
@@ -101,7 +120,7 @@ function printItems(items) {
|
|
|
101
120
|
for (const item of items) {
|
|
102
121
|
const comments = item.comment_count ? ` 💬${item.comment_count}` : "";
|
|
103
122
|
const shots = item.attachment_count ? ` 📎${item.attachment_count}` : "";
|
|
104
|
-
console.log(`${item
|
|
123
|
+
console.log(`${refOf(item)} ${item.status} ${item.kind} ${itemLabel(item)}${comments}${shots}`);
|
|
105
124
|
}
|
|
106
125
|
}
|
|
107
126
|
const listCommand = defineCommand({
|
|
@@ -139,7 +158,7 @@ const showCommand = defineCommand({
|
|
|
139
158
|
args: {
|
|
140
159
|
id: {
|
|
141
160
|
type: "positional",
|
|
142
|
-
description: "
|
|
161
|
+
description: "Report key like my-project-17 (from `canopy feedback list`), or its number inside the project",
|
|
143
162
|
required: true
|
|
144
163
|
},
|
|
145
164
|
...projectDirArgs,
|
|
@@ -150,7 +169,8 @@ const showCommand = defineCommand({
|
|
|
150
169
|
}
|
|
151
170
|
},
|
|
152
171
|
run: reportErrors("feedback show", async ({ args }) => {
|
|
153
|
-
const
|
|
172
|
+
const slug = slugOfKey(args.id) ?? tryResolveProject(args).slug;
|
|
173
|
+
if (!slug && /^\d+$/.test(args.id)) throw new Error(`"${args.id}" is a bare report number — run this inside the project, pass --project, or use the full key (e.g. my-project-${args.id}).`);
|
|
154
174
|
const detail = await apiRequest("GET", slug ? `/projects/${slug}/feedback/${encodeURIComponent(args.id)}` : `/feedback/${encodeURIComponent(args.id)}`);
|
|
155
175
|
if (args.json) {
|
|
156
176
|
console.log(JSON.stringify(detail, null, 2));
|
|
@@ -158,7 +178,7 @@ const showCommand = defineCommand({
|
|
|
158
178
|
}
|
|
159
179
|
const { item, comments } = detail;
|
|
160
180
|
if (item.title) console.log(item.title);
|
|
161
|
-
console.log(`${item.kind} · ${item.status} · via ${item.source} · ${formatDateTime(item.created_at)}`);
|
|
181
|
+
console.log(`${refOf(item)} · ${item.kind} · ${item.status} · via ${item.source} · ${formatDateTime(item.created_at)}`);
|
|
162
182
|
console.log(`reported by ${item.reporter_name || item.reporter_email || "unknown"}` + (item.deployment_id ? ` on ${item.deployment_id}` : "") + (item.channel === "staging" ? " (staging)" : ""));
|
|
163
183
|
console.log(`\n${item.body}\n`);
|
|
164
184
|
if (item.context) {
|
|
@@ -207,7 +227,7 @@ const commentCommand = defineCommand({
|
|
|
207
227
|
args: {
|
|
208
228
|
id: {
|
|
209
229
|
type: "positional",
|
|
210
|
-
description: "
|
|
230
|
+
description: "Report key (my-project-17), or its number inside the project",
|
|
211
231
|
required: true
|
|
212
232
|
},
|
|
213
233
|
text: {
|
|
@@ -237,7 +257,7 @@ const statusCommand = defineCommand({
|
|
|
237
257
|
args: {
|
|
238
258
|
id: {
|
|
239
259
|
type: "positional",
|
|
240
|
-
description: "
|
|
260
|
+
description: "Report key (my-project-17), or its number inside the project",
|
|
241
261
|
required: true
|
|
242
262
|
},
|
|
243
263
|
to: {
|
|
@@ -281,7 +301,7 @@ const mineCommand = defineCommand({
|
|
|
281
301
|
console.log("You haven't filed any reports.");
|
|
282
302
|
return;
|
|
283
303
|
}
|
|
284
|
-
for (const item of items) console.log(`${item
|
|
304
|
+
for (const item of items) console.log(`${refOf(item)} ${item.status} ${item.kind} [${item.project_slug}] ${itemLabel(item)}`);
|
|
285
305
|
})
|
|
286
306
|
});
|
|
287
307
|
const reportCommand = defineCommand({
|
|
@@ -348,8 +368,8 @@ const reportCommand = defineCommand({
|
|
|
348
368
|
...args.status ? { status: args.status } : {},
|
|
349
369
|
context
|
|
350
370
|
});
|
|
351
|
-
console.log(`Filed ${kind} ${item.
|
|
352
|
-
if (paths.length > 0) await attachFiles(item.project, item.
|
|
371
|
+
console.log(`Filed ${kind} ${item.key} on ${item.project} as ${item.status}.`);
|
|
372
|
+
if (paths.length > 0) await attachFiles(item.project, item.key, paths, args.caption);
|
|
353
373
|
console.log(`Follow it with \`canopy feedback mine\` or on the dashboard's Reports page.`);
|
|
354
374
|
})
|
|
355
375
|
});
|
|
@@ -370,7 +390,7 @@ const feedbackCommand = defineCommand({
|
|
|
370
390
|
args: {
|
|
371
391
|
id: {
|
|
372
392
|
type: "positional",
|
|
373
|
-
description: "
|
|
393
|
+
description: "Report key (my-project-17), or its number inside the project",
|
|
374
394
|
required: true
|
|
375
395
|
},
|
|
376
396
|
file: {
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as version } from "./package-
|
|
2
|
+
import { t as version } from "./package-CsmBH_fN.mjs";
|
|
3
3
|
import { r as siteHeaderLine, t as setInvocationProfile } from "./site-DM2J10CB.mjs";
|
|
4
4
|
import { a as notifyOfUpdate, o as runRefresh } from "./version-check-CcsA1QjI.mjs";
|
|
5
5
|
import { defineCommand, runMain } from "citty";
|
|
@@ -77,13 +77,13 @@ const main = defineCommand({
|
|
|
77
77
|
egress: () => import("./egress-Cn-P46O3.mjs").then((m) => m.egressCommand),
|
|
78
78
|
secrets: () => import("./secrets-BD3DaTih.mjs").then((m) => m.secretsCommand),
|
|
79
79
|
schedule: () => import("./schedule-Buu71RWQ.mjs").then((m) => m.scheduleCommand),
|
|
80
|
-
feedback: () => import("./feedback-
|
|
80
|
+
feedback: () => import("./feedback-DormOsQa.mjs").then((m) => m.feedbackCommand),
|
|
81
81
|
db: () => import("./db-DVMwCLlU.mjs").then((m) => m.dbCommand),
|
|
82
82
|
usage: () => import("./usage-81JSiWIx.mjs").then((m) => m.usageCommand),
|
|
83
83
|
open: () => import("./open-rS1ARzOy.mjs").then((m) => m.openCommand),
|
|
84
|
-
docs: () => import("./docs-
|
|
85
|
-
skill: () => import("./skill-
|
|
86
|
-
upgrade: () => import("./upgrade-
|
|
84
|
+
docs: () => import("./docs-CuS9nIXm.mjs").then((m) => m.docsCommand),
|
|
85
|
+
skill: () => import("./skill-DX18WOap.mjs").then((m) => m.skillCommand),
|
|
86
|
+
upgrade: () => import("./upgrade-PfdH0NPe.mjs").then((m) => m.upgradeCommand),
|
|
87
87
|
logs: () => import("./logs-CfDINw7U.mjs").then((m) => m.logsCommand)
|
|
88
88
|
}
|
|
89
89
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as version } from "./package-
|
|
1
|
+
import { t as version } from "./package-CsmBH_fN.mjs";
|
|
2
2
|
import { r as reportErrors } from "./ui-DR-siu2S.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import { cpSync, existsSync, mkdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
@@ -112,7 +112,7 @@ const upgradeCommand = defineCommand({
|
|
|
112
112
|
const spec = `${PACKAGE_NAME}@${args.version ?? "latest"}`;
|
|
113
113
|
const command = pmCommand(pm);
|
|
114
114
|
const cmd = installArgs(pm, spec);
|
|
115
|
-
const { skillInstalled } = await import("./skill-
|
|
115
|
+
const { skillInstalled } = await import("./skill-DX18WOap.mjs");
|
|
116
116
|
const { homedir } = await import("node:os");
|
|
117
117
|
const refreshGlobal = skillInstalled(homedir());
|
|
118
118
|
const refreshRepo = process.cwd() !== homedir() && skillInstalled(process.cwd());
|