@mediamonks/canopy-cli 0.7.46 → 0.7.47
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/audience-B68YZBGy.mjs +121 -0
- package/dist/docs/cli-audience.md +47 -0
- package/dist/docs/index.json +5 -0
- package/dist/docs/platform-members-and-access.md +20 -0
- package/dist/{docs-CtMrMpt1.mjs → docs-D5gmZRJk.mjs} +1 -1
- package/dist/{feedback-BXhbxyXI.mjs → feedback-C6kiYRro.mjs} +1 -1
- package/dist/index.mjs +8 -7
- package/dist/{mcp-CGmWkGN8.mjs → mcp-DuCxfb85.mjs} +1 -1
- package/dist/{package-BdNHq8QV.mjs → package-BksVeJZB.mjs} +1 -1
- package/dist/{skill-vzcCD1b4.mjs → skill-Bz39NhTN.mjs} +1 -1
- package/dist/{upgrade-8_pFNTo5.mjs → upgrade-BjDaghNf.mjs} +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { c as projectDirArgs, d as resolveProject, l as projectFlagArgs } from "./site-BL5Ik-yj.mjs";
|
|
2
|
+
import { a as apiRequest, m as withContext } from "./api-DmJrIsE7.mjs";
|
|
3
|
+
import { r as reportErrors } from "./ui-26ETk1n8.mjs";
|
|
4
|
+
import { defineCommand } from "citty";
|
|
5
|
+
import * as p from "@clack/prompts";
|
|
6
|
+
//#region src/audience.ts
|
|
7
|
+
/**
|
|
8
|
+
* Project audience (OpenSpec change project-audience): `canopy audience
|
|
9
|
+
* show|set|draft|ready`. Who a project is for and whether it's still a draft
|
|
10
|
+
* are labels on the dashboard's project list, stored on the platform (never
|
|
11
|
+
* in canopy.json) and set through the project update route.
|
|
12
|
+
*/
|
|
13
|
+
const KINDS = [
|
|
14
|
+
"everyone",
|
|
15
|
+
"personal",
|
|
16
|
+
"client",
|
|
17
|
+
"department"
|
|
18
|
+
];
|
|
19
|
+
const NAME_MAX = 40;
|
|
20
|
+
/** `set <kind> [name]` → the update body, or a sentence saying what's wrong. */
|
|
21
|
+
function parseAudience(kind, name) {
|
|
22
|
+
const k = kind.trim().toLowerCase();
|
|
23
|
+
if (!KINDS.includes(k)) return `"${kind}" is not an audience. Use everyone, personal, client <name> or department <name>.`;
|
|
24
|
+
if (k === "client" || k === "department") {
|
|
25
|
+
const n = name?.trim() ?? "";
|
|
26
|
+
if (!n) return `Name the ${k}: canopy audience set ${k} "<name>"`;
|
|
27
|
+
if (n.length > NAME_MAX) return `Keep the ${k} name to ${NAME_MAX} characters.`;
|
|
28
|
+
return {
|
|
29
|
+
kind: k,
|
|
30
|
+
name: n
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (name?.trim()) return `${k === "everyone" ? "Everyone" : "Personal"} takes no name.`;
|
|
34
|
+
return { kind: k };
|
|
35
|
+
}
|
|
36
|
+
/** One line for people: who it's for, and whether it's a draft. */
|
|
37
|
+
function describeAudience(project) {
|
|
38
|
+
const a = project.audience ?? null;
|
|
39
|
+
const who = a === null ? "is for everyone" : a.kind === "personal" ? "is a personal project" : `is for the ${a.name} ${a.kind === "client" ? "client team" : "department"}`;
|
|
40
|
+
return `${project.slug} ${who}${project.draft ? ", and is still a draft" : ""}.`;
|
|
41
|
+
}
|
|
42
|
+
const FIXES = { invalid_audience: "Use everyone, personal, client <name> or department <name> (names up to 40 characters)." };
|
|
43
|
+
function update(slug, body) {
|
|
44
|
+
return withContext(apiRequest("PATCH", `/projects/${slug}`, body).then((r) => r.project), {
|
|
45
|
+
action: `update ${slug}`,
|
|
46
|
+
fixes: FIXES
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const audienceCommand = defineCommand({
|
|
50
|
+
meta: {
|
|
51
|
+
name: "audience",
|
|
52
|
+
description: "Who the project is for, and whether it's a draft (show, set, draft, ready)"
|
|
53
|
+
},
|
|
54
|
+
subCommands: {
|
|
55
|
+
show: defineCommand({
|
|
56
|
+
meta: {
|
|
57
|
+
name: "show",
|
|
58
|
+
description: "Show who the project is for and whether it's a draft"
|
|
59
|
+
},
|
|
60
|
+
args: { ...projectDirArgs },
|
|
61
|
+
run: reportErrors("audience show", async ({ args }) => {
|
|
62
|
+
const { slug } = resolveProject(args);
|
|
63
|
+
const { project } = await withContext(apiRequest("GET", `/projects/${slug}`), { action: `read ${slug}` });
|
|
64
|
+
console.log(describeAudience(project));
|
|
65
|
+
})
|
|
66
|
+
}),
|
|
67
|
+
set: defineCommand({
|
|
68
|
+
meta: {
|
|
69
|
+
name: "set",
|
|
70
|
+
description: "Say who it's for: everyone, personal, client <name> or department <name>"
|
|
71
|
+
},
|
|
72
|
+
args: {
|
|
73
|
+
kind: {
|
|
74
|
+
type: "positional",
|
|
75
|
+
description: "everyone | personal | client | department",
|
|
76
|
+
required: true
|
|
77
|
+
},
|
|
78
|
+
name: {
|
|
79
|
+
type: "positional",
|
|
80
|
+
description: "The client team or department (client and department only)",
|
|
81
|
+
required: false
|
|
82
|
+
},
|
|
83
|
+
...projectFlagArgs
|
|
84
|
+
},
|
|
85
|
+
run: reportErrors("audience set", async ({ args }) => {
|
|
86
|
+
const audience = parseAudience(args.kind, args.name);
|
|
87
|
+
if (typeof audience === "string") {
|
|
88
|
+
console.error(audience);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
const { slug } = resolveProject({ project: args.project });
|
|
92
|
+
p.log.success(describeAudience(await update(slug, { audience })));
|
|
93
|
+
p.log.info("It's a label on the project list; who can open the project is unchanged.");
|
|
94
|
+
})
|
|
95
|
+
}),
|
|
96
|
+
draft: defineCommand({
|
|
97
|
+
meta: {
|
|
98
|
+
name: "draft",
|
|
99
|
+
description: "Mark it as not ready yet (greyed out on the list)"
|
|
100
|
+
},
|
|
101
|
+
args: { ...projectDirArgs },
|
|
102
|
+
run: reportErrors("audience draft", async ({ args }) => {
|
|
103
|
+
const { slug } = resolveProject(args);
|
|
104
|
+
p.log.success(describeAudience(await update(slug, { draft: true })));
|
|
105
|
+
})
|
|
106
|
+
}),
|
|
107
|
+
ready: defineCommand({
|
|
108
|
+
meta: {
|
|
109
|
+
name: "ready",
|
|
110
|
+
description: "Mark it as ready (no longer a draft)"
|
|
111
|
+
},
|
|
112
|
+
args: { ...projectDirArgs },
|
|
113
|
+
run: reportErrors("audience ready", async ({ args }) => {
|
|
114
|
+
const { slug } = resolveProject(args);
|
|
115
|
+
p.log.success(describeAudience(await update(slug, { draft: false })));
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
//#endregion
|
|
121
|
+
export { audienceCommand };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: canopy audience
|
|
3
|
+
description: Say who a project is for and whether it's still a draft.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`canopy audience` sets the labels people see on the dashboard's project list:
|
|
7
|
+
who the project was made for, and whether it's still a draft. They never
|
|
8
|
+
change who can open the project. Read
|
|
9
|
+
[Saying who it's for](https://docs.canopy.website/platform/members-and-access#saying-who-its-for).
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
canopy audience show
|
|
15
|
+
canopy audience set <everyone|personal>
|
|
16
|
+
canopy audience set <client|department> <name>
|
|
17
|
+
canopy audience draft
|
|
18
|
+
canopy audience ready
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Arguments & flags
|
|
22
|
+
|
|
23
|
+
Each subcommand works on the project in the current folder (`canopy.json`),
|
|
24
|
+
or the one you name with `--project <slug>`. All of them honour the global
|
|
25
|
+
`--profile <site>` / `CANOPY_PROFILE`. Owners, managers and editors can change
|
|
26
|
+
them.
|
|
27
|
+
|
|
28
|
+
- `show` — who the project is for, and whether it's a draft.
|
|
29
|
+
- `set <kind> [name]` — `everyone` (the default), `personal`, or `client` /
|
|
30
|
+
`department` with a name of up to 40 characters. Quote names with spaces.
|
|
31
|
+
- `draft` — mark it as not ready yet. It shows greyed out on the project list
|
|
32
|
+
but stays listed and usable.
|
|
33
|
+
- `ready` — it's no longer a draft.
|
|
34
|
+
|
|
35
|
+
## Examples
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
canopy audience set client "Uniqlo"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Marks the project as made for the Uniqlo client team.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
canopy audience draft --project retro-board
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Marks `retro-board` as a draft without being in its folder.
|
package/dist/docs/index.json
CHANGED
|
@@ -246,6 +246,11 @@
|
|
|
246
246
|
"title": "canopy rename",
|
|
247
247
|
"summary": "Change a project's slug — its address — and update canopy.json."
|
|
248
248
|
},
|
|
249
|
+
{
|
|
250
|
+
"slug": "cli-audience",
|
|
251
|
+
"title": "canopy audience",
|
|
252
|
+
"summary": "Say who a project is for and whether it's still a draft."
|
|
253
|
+
},
|
|
249
254
|
{
|
|
250
255
|
"slug": "cli-dev",
|
|
251
256
|
"title": "canopy dev",
|
|
@@ -113,6 +113,26 @@ Turning it off again is the same toggle.
|
|
|
113
113
|
> **Note:** Members-only gates the **live app**. Management pages (settings, data, deploys) are always for the
|
|
114
114
|
> owner, managers and editors only, whatever this toggle says.
|
|
115
115
|
|
|
116
|
+
## Saying who it's for
|
|
117
|
+
|
|
118
|
+
Not every project is meant for everyone who scrolls past it. In **Settings →
|
|
119
|
+
Audience** you can say who it was made for:
|
|
120
|
+
|
|
121
|
+
- **Everyone**, the default. Nothing extra shows on the project list.
|
|
122
|
+
- **Just me**, for a personal tool or experiment.
|
|
123
|
+
- **A client team** or **a department**, with its name (up to 40 characters).
|
|
124
|
+
|
|
125
|
+
Other people see the audience as a small badge next to **Visit** on the
|
|
126
|
+
project list, and personal projects sort below the ones meant for everyone.
|
|
127
|
+
Every Monk can read the name, the same as the project's name and description.
|
|
128
|
+
|
|
129
|
+
Turn on **Still a draft** while it isn't ready. The project shows greyed out
|
|
130
|
+
and sorts lower, but it stays listed and anyone who could open it still can.
|
|
131
|
+
|
|
132
|
+
Both are labels only. They never change who can open the project; that's
|
|
133
|
+
what members-only and the client password are for. From the CLI, use
|
|
134
|
+
[`canopy audience`](https://docs.canopy.website/cli/audience).
|
|
135
|
+
|
|
116
136
|
## Platform admins and the Admin page
|
|
117
137
|
|
|
118
138
|
Platform admins get an extra **Admin** page in the dashboard. Its **Users**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as version } from "./package-
|
|
1
|
+
import { t as version } from "./package-BksVeJZB.mjs";
|
|
2
2
|
import { r as siteConfig } from "./site-BL5Ik-yj.mjs";
|
|
3
3
|
import { i as latestKnownVersion, r as compareSemver } from "./version-check-CcsA1QjI.mjs";
|
|
4
4
|
import { n as agentHeaders } from "./api-DmJrIsE7.mjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as version } from "./package-
|
|
1
|
+
import { t as version } from "./package-BksVeJZB.mjs";
|
|
2
2
|
import { c as projectDirArgs, d as resolveProject, h as tryResolveProject, m as tryReadCanopyJson, r as siteConfig } from "./site-BL5Ik-yj.mjs";
|
|
3
3
|
import { a as apiRequest, c as credentials, i as apiDownload, o as apiUpload, s as commonHeaders } from "./api-DmJrIsE7.mjs";
|
|
4
4
|
import { r as reportErrors, t as formatDateTime } from "./ui-26ETk1n8.mjs";
|
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-BksVeJZB.mjs";
|
|
3
3
|
import { i as siteHeaderLine, n as setInvocationProfile } from "./site-BL5Ik-yj.mjs";
|
|
4
4
|
import { a as notifyOfUpdate, o as runRefresh } from "./version-check-CcsA1QjI.mjs";
|
|
5
5
|
import { defineCommand, runMain } from "citty";
|
|
@@ -83,19 +83,20 @@ const main = defineCommand({
|
|
|
83
83
|
roles: () => import("./roles-CrYf_8wk.mjs").then((m) => m.rolesCommand),
|
|
84
84
|
members: () => import("./roles-CrYf_8wk.mjs").then((m) => m.membersCommand),
|
|
85
85
|
schedule: () => import("./schedule-DvHSSzfR.mjs").then((m) => m.scheduleCommand),
|
|
86
|
-
feedback: () => import("./feedback-
|
|
86
|
+
feedback: () => import("./feedback-C6kiYRro.mjs").then((m) => m.feedbackCommand),
|
|
87
87
|
db: () => import("./db-DpCMc0uz.mjs").then((m) => m.dbCommand),
|
|
88
88
|
usage: () => import("./usage-Bpz5B1N1.mjs").then((m) => m.usageCommand),
|
|
89
89
|
ai: () => import("./ai-CWPQiUft.mjs").then((m) => m.aiCommand),
|
|
90
90
|
open: () => import("./open-DcQSdfx5.mjs").then((m) => m.openCommand),
|
|
91
91
|
browse: () => import("./browse-BPLWhoFI.mjs").then((m) => m.browseCommand),
|
|
92
|
-
docs: () => import("./docs-
|
|
93
|
-
skill: () => import("./skill-
|
|
94
|
-
upgrade: () => import("./upgrade-
|
|
92
|
+
docs: () => import("./docs-D5gmZRJk.mjs").then((m) => m.docsCommand),
|
|
93
|
+
skill: () => import("./skill-Bz39NhTN.mjs").then((m) => m.skillCommand),
|
|
94
|
+
upgrade: () => import("./upgrade-BjDaghNf.mjs").then((m) => m.upgradeCommand),
|
|
95
95
|
logs: () => import("./logs-dZMPTJLu.mjs").then((m) => m.logsCommand),
|
|
96
|
-
mcp: () => import("./mcp-
|
|
96
|
+
mcp: () => import("./mcp-DuCxfb85.mjs").then((m) => m.mcpCommand),
|
|
97
97
|
repo: () => import("./repo-C7AXDtFZ.mjs").then((m) => m.repoCommand),
|
|
98
|
-
template: () => import("./project-template-Dw11151p.mjs").then((m) => m.templateCommand)
|
|
98
|
+
template: () => import("./project-template-Dw11151p.mjs").then((m) => m.templateCommand),
|
|
99
|
+
audience: () => import("./audience-B68YZBGy.mjs").then((m) => m.audienceCommand)
|
|
99
100
|
}
|
|
100
101
|
});
|
|
101
102
|
const quiet = process.argv[2] === "mcp" && process.argv[3] === "serve" || process.argv[2] === "repo" && process.argv[3] === "credential";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as version } from "./package-
|
|
1
|
+
import { t as version } from "./package-BksVeJZB.mjs";
|
|
2
2
|
import { h as tryResolveProject, p as stagingUrl, r as siteConfig, u as projectUrl } from "./site-BL5Ik-yj.mjs";
|
|
3
3
|
import { a as apiRequest, f as noticeRenamesOnly, l as currentSlug, t as ApiError } from "./api-DmJrIsE7.mjs";
|
|
4
4
|
import { t as liveDevServer } from "./dev-server-file-Dk9pk4AR.mjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as version } from "./package-
|
|
1
|
+
import { t as version } from "./package-BksVeJZB.mjs";
|
|
2
2
|
import { r as reportErrors } from "./ui-26ETk1n8.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-Bz39NhTN.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());
|