@mediamonks/canopy-cli 0.7.36 → 0.7.38
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/{ai-DHLnyqfq.mjs → ai-CjvrcBIz.mjs} +2 -2
- package/dist/{api-C4rMhE7i.mjs → api-BPEYm9ts.mjs} +21 -0
- package/dist/{browse-Dycwj0V_.mjs → browse-CBelCgnW.mjs} +1 -1
- package/dist/{db-BB6O6085.mjs → db-CbqgjfYz.mjs} +159 -13
- package/dist/{deploy-Ka2lHkyy.mjs → deploy-CqCyry4o.mjs} +3 -3
- package/dist/{dev-BdXslHoA.mjs → dev-BtnEuAnS.mjs} +5 -5
- package/dist/dev-D_qzeLng.mjs +2 -0
- package/dist/docs/cli-create.md +2 -0
- package/dist/docs/cli-db.md +30 -1
- package/dist/docs/cli-projects.md +2 -0
- package/dist/docs/cli-secrets.md +2 -1
- package/dist/docs/cli-template.md +47 -0
- package/dist/docs/data.md +11 -0
- package/dist/docs/index.json +10 -0
- package/dist/docs/platform-project-data.md +23 -3
- package/dist/docs/templates.md +84 -0
- package/dist/{docs-Bb9hSk4h.mjs → docs-T1nuu00A.mjs} +2 -2
- package/dist/{egress-If_Gsx_M.mjs → egress-ButFsQ2N.mjs} +2 -2
- package/dist/{feedback-DzEKQlP6.mjs → feedback-C5NKCOXQ.mjs} +3 -3
- package/dist/index.mjs +31 -30
- package/dist/{local-Cyl39_Zu.mjs → local-BfqTheMP.mjs} +2 -2
- package/dist/{login-D0J5s_Ex.mjs → login-CtDWXICZ.mjs} +3 -3
- package/dist/{logs-DQQOawOG.mjs → logs-BltUi4Gp.mjs} +2 -2
- package/dist/{mcp-pNp-sbfJ.mjs → mcp-BwLRcfqz.mjs} +2 -2
- package/dist/{migrations-Czlcddyz.mjs → migrations-CF1iNZ7F.mjs} +1 -1
- package/dist/{open-DcaQKi1v.mjs → open-DXo60Ikf.mjs} +1 -1
- package/dist/{package-lYhex2Gp.mjs → package-CdDH35SE.mjs} +1 -1
- package/dist/project-template-BEr_tgIY.mjs +125 -0
- package/dist/project-template-DdT0dqpn.mjs +2 -0
- package/dist/{projects-DQAhCZm8.mjs → projects-Bm4oTodB.mjs} +74 -8
- package/dist/{repo-Bb9ntNa4.mjs → repo-CE22HpqZ.mjs} +18 -15
- package/dist/repo-DlYX_1tN.mjs +2 -0
- package/dist/{schedule-C5lMf3ny.mjs → schedule-DdMq5eXC.mjs} +2 -2
- package/dist/{secrets-BSEjZnxg.mjs → secrets-BOKuWBYV.mjs} +6 -5
- package/dist/{skill-BUA2uRR2.mjs → skill-3wOwhzDx.mjs} +2 -2
- package/dist/{staging-BZVty57b.mjs → staging-CU4QrzFX.mjs} +2 -2
- package/dist/{token-HHlUR0CF.mjs → token-BWnLsWLg.mjs} +2 -2
- package/dist/{ui-C_jSc1Kz.mjs → ui-CHfKV6lG.mjs} +1 -1
- package/dist/{upgrade-ZSb56qBJ.mjs → upgrade-BJ2dWjCG.mjs} +2 -2
- package/dist/{usage-CUYrWxv0.mjs → usage-Cqqvnzrf.mjs} +2 -2
- package/package.json +1 -1
- package/dist/dev-BeFX_wc5.mjs +0 -2
- package/dist/repo-1RQ1vBMv.mjs +0 -2
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { a as projectDirArgs, c as resolveProject } from "./site-DM2J10CB.mjs";
|
|
2
|
+
import { i as apiRequest, o as withContext } from "./api-BPEYm9ts.mjs";
|
|
3
|
+
import { a as unwrap, i as requireTty, r as reportErrors } from "./ui-CHfKV6lG.mjs";
|
|
4
|
+
import { defineCommand } from "citty";
|
|
5
|
+
import * as p from "@clack/prompts";
|
|
6
|
+
/** Plain words for the API's template errors. */
|
|
7
|
+
const TEMPLATE_FIXES = {
|
|
8
|
+
template_not_found: "No template by that name on this site. `canopy projects --templates` lists the templates you can start from.",
|
|
9
|
+
template_empty: "The template's repository has no code yet. Ask its owner to push it first.",
|
|
10
|
+
template_too_large: `The template's files are larger than the 32 MiB a copy can hold. Ask its owner to remove large files from the repository.`,
|
|
11
|
+
repo_required: "A template needs a Canopy git repository. Create one with `canopy repo create`, push the code, then try again.",
|
|
12
|
+
repo_empty: "Push the project's code to its repository first, then try again.",
|
|
13
|
+
owner_only: "Only the project owner can make it a template, or stop it being one.",
|
|
14
|
+
repos_not_configured: "Templates need Canopy git repositories, which are not available on this site yet."
|
|
15
|
+
};
|
|
16
|
+
/** What the new project gets, one line each — shown before creating. */
|
|
17
|
+
function describeCopy(copy) {
|
|
18
|
+
const lines = ["The code in its repository, as one fresh commit (no history)."];
|
|
19
|
+
if (copy.egress_mode === "open") lines.push("Outbound access: open (the backend may call any host).");
|
|
20
|
+
else if (copy.egress_allowlist.length) lines.push(`Outbound hosts allowed: ${copy.egress_allowlist.join(", ")}.`);
|
|
21
|
+
const loosened = [
|
|
22
|
+
!copy.csp_enabled && "Content-Security-Policy off",
|
|
23
|
+
copy.allow_framing && "other sites may frame the app",
|
|
24
|
+
copy.browser_db_access !== "full" && `browser database access: ${copy.browser_db_access}`,
|
|
25
|
+
!copy.feedback_widget && "feedback widget hidden"
|
|
26
|
+
].filter(Boolean);
|
|
27
|
+
if (loosened.length) lines.push(`Page settings: ${loosened.join("; ")}.`);
|
|
28
|
+
if (copy.google_bundles.length) lines.push(`Google access it asks visitors for: ${copy.google_bundles.join(", ")}.`);
|
|
29
|
+
if (copy.schedules.length) lines.push(`Schedules, turned off: ${copy.schedules.map((s) => `${s.name} (${s.cron})`).join(", ")}.`);
|
|
30
|
+
if (copy.secrets.length) lines.push(`Secret names to fill in (no values): ${copy.secrets.join(", ")}.`);
|
|
31
|
+
lines.push("Not copied: its data, files, members, password, budgets or history.");
|
|
32
|
+
return lines;
|
|
33
|
+
}
|
|
34
|
+
/** What is left to do once the project exists. */
|
|
35
|
+
function nextSteps(slug, copy) {
|
|
36
|
+
const steps = [`cd ${slug}`];
|
|
37
|
+
for (const name of copy.secrets) steps.push(`canopy secrets set ${name}`);
|
|
38
|
+
steps.push("canopy deploy");
|
|
39
|
+
for (const s of copy.schedules) steps.push(`canopy schedule add ${s.name} "${s.cron}" (to turn it on)`);
|
|
40
|
+
if (copy.google_restricted.length) steps.push(`Ask a Canopy admin to unlock restricted Google access (${copy.google_restricted.join(", ")}), then turn it on in the dashboard.`);
|
|
41
|
+
return steps;
|
|
42
|
+
}
|
|
43
|
+
function fetchTemplate(slug) {
|
|
44
|
+
return withContext(apiRequest("GET", `/projects/${slug}/template`), {
|
|
45
|
+
action: `read template ${slug}`,
|
|
46
|
+
fixes: TEMPLATE_FIXES
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const templateCommand = defineCommand({
|
|
50
|
+
meta: {
|
|
51
|
+
name: "template",
|
|
52
|
+
description: "Offer a project as a template (mark, unmark, show)"
|
|
53
|
+
},
|
|
54
|
+
subCommands: {
|
|
55
|
+
mark: defineCommand({
|
|
56
|
+
meta: {
|
|
57
|
+
name: "mark",
|
|
58
|
+
description: "Let anyone on this site start a project from this one"
|
|
59
|
+
},
|
|
60
|
+
args: {
|
|
61
|
+
...projectDirArgs,
|
|
62
|
+
yes: {
|
|
63
|
+
type: "boolean",
|
|
64
|
+
description: "Skip the confirmation",
|
|
65
|
+
default: false
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
run: reportErrors("template mark", async ({ args }) => {
|
|
69
|
+
const { slug } = resolveProject(args);
|
|
70
|
+
if (!args.yes) {
|
|
71
|
+
requireTty("pass --yes to confirm.");
|
|
72
|
+
p.log.info(`Everyone on this site will be able to start a project of their own with a copy of ${slug}'s current code in its repository, plus its setup (outbound hosts, page settings, schedule and secret names). Its data, secret values and members are never copied.`);
|
|
73
|
+
if (!unwrap(await p.confirm({
|
|
74
|
+
message: `Make ${slug} a template?`,
|
|
75
|
+
initialValue: false
|
|
76
|
+
}))) {
|
|
77
|
+
p.cancel("Not marked.");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if ((await withContext(apiRequest("PUT", `/projects/${slug}/template`, { enabled: true }), {
|
|
82
|
+
action: `make ${slug} a template`,
|
|
83
|
+
fixes: TEMPLATE_FIXES
|
|
84
|
+
})).warnings.includes("no_migrations")) p.log.warn("canopy.json sets no \"migrations\", so new projects start with an empty database: none of its tables come along. Add migrations to the repository to fix that.");
|
|
85
|
+
p.log.success(`${slug} is a template. Others start from it with \`canopy create <name> --from ${slug}\`.`);
|
|
86
|
+
})
|
|
87
|
+
}),
|
|
88
|
+
unmark: defineCommand({
|
|
89
|
+
meta: {
|
|
90
|
+
name: "unmark",
|
|
91
|
+
description: "Stop new projects starting from this one"
|
|
92
|
+
},
|
|
93
|
+
args: { ...projectDirArgs },
|
|
94
|
+
run: reportErrors("template unmark", async ({ args }) => {
|
|
95
|
+
const { slug } = resolveProject(args);
|
|
96
|
+
await withContext(apiRequest("PUT", `/projects/${slug}/template`, { enabled: false }), {
|
|
97
|
+
action: `stop ${slug} being a template`,
|
|
98
|
+
fixes: TEMPLATE_FIXES
|
|
99
|
+
});
|
|
100
|
+
p.log.success(`${slug} is no longer a template. Projects already started from it are not affected.`);
|
|
101
|
+
})
|
|
102
|
+
}),
|
|
103
|
+
show: defineCommand({
|
|
104
|
+
meta: {
|
|
105
|
+
name: "show",
|
|
106
|
+
description: "Show what a new project gets from a template"
|
|
107
|
+
},
|
|
108
|
+
args: { slug: {
|
|
109
|
+
type: "positional",
|
|
110
|
+
description: "Template slug",
|
|
111
|
+
required: true
|
|
112
|
+
} },
|
|
113
|
+
run: reportErrors("template show", async ({ args }) => {
|
|
114
|
+
const preview = await fetchTemplate(args.slug);
|
|
115
|
+
const t = preview.template;
|
|
116
|
+
console.log(`${t.name} (${t.slug}) — by ${t.owner.name} <${t.owner.email}>`);
|
|
117
|
+
if (t.description) console.log(t.description);
|
|
118
|
+
console.log("");
|
|
119
|
+
for (const line of describeCopy(preview.copies)) console.log(`- ${line}`);
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
//#endregion
|
|
125
|
+
export { templateCommand as a, nextSteps as i, describeCopy as n, fetchTemplate as r, TEMPLATE_FIXES as t };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { n as siteConfig, s as projectUrl, u as tryReadCanopyJson } from "./site-DM2J10CB.mjs";
|
|
2
|
-
import { i as apiRequest } from "./api-
|
|
3
|
-
import { a as unwrap, i as requireTty, r as reportErrors } from "./ui-
|
|
4
|
-
import { r as
|
|
2
|
+
import { i as apiRequest, o as withContext } from "./api-BPEYm9ts.mjs";
|
|
3
|
+
import { a as unwrap, i as requireTty, r as reportErrors } from "./ui-CHfKV6lG.mjs";
|
|
4
|
+
import { i as nextSteps, n as describeCopy, r as fetchTemplate, t as TEMPLATE_FIXES } from "./project-template-BEr_tgIY.mjs";
|
|
5
|
+
import { i as offerRepoOnCreate, n as cloneProjectRepo } from "./repo-CE22HpqZ.mjs";
|
|
5
6
|
import { defineCommand } from "citty";
|
|
6
7
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
7
8
|
import { join, relative, resolve, sep } from "node:path";
|
|
@@ -111,6 +112,10 @@ const createCommand = defineCommand({
|
|
|
111
112
|
type: "boolean",
|
|
112
113
|
description: "Also create a git repository for the project on Canopy",
|
|
113
114
|
negativeDescription: "Don't create a git repository (no question asked)"
|
|
115
|
+
},
|
|
116
|
+
from: {
|
|
117
|
+
type: "string",
|
|
118
|
+
description: "Start from a template project: a copy of its code and setup (`canopy projects --templates`)"
|
|
114
119
|
}
|
|
115
120
|
},
|
|
116
121
|
run: reportErrors("create", async ({ args }) => {
|
|
@@ -134,6 +139,10 @@ const createCommand = defineCommand({
|
|
|
134
139
|
}
|
|
135
140
|
})).trim();
|
|
136
141
|
slug ||= slugify(name);
|
|
142
|
+
if (args.from) {
|
|
143
|
+
await createFromTemplate(name, slug, args.from);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
137
146
|
const scaffold = shouldScaffoldCreate(args.scaffold);
|
|
138
147
|
let template = TEMPLATES.find((t) => t.id === (args.template ?? "static"));
|
|
139
148
|
if (!template) throw new Error(`Unknown template "${args.template}" — available: ${TEMPLATES.map((t) => t.id).join(", ")}.`);
|
|
@@ -188,6 +197,45 @@ const createCommand = defineCommand({
|
|
|
188
197
|
}
|
|
189
198
|
})
|
|
190
199
|
});
|
|
200
|
+
/**
|
|
201
|
+
* `canopy create --from` (project-templates): show what the new project
|
|
202
|
+
* gets, create it with a copy of the template, clone it, list what's left.
|
|
203
|
+
*/
|
|
204
|
+
async function createFromTemplate(name, slug, from) {
|
|
205
|
+
const targetDir = resolve(slug);
|
|
206
|
+
if (existsSync(targetDir)) throw new Error(`Directory ./${slug} already exists — remove it, or pick another slug.`);
|
|
207
|
+
const preview = await fetchTemplate(from);
|
|
208
|
+
p.note(describeCopy(preview.copies).join("\n"), `From ${preview.template.name} (by ${preview.template.owner.name}), ${slug} gets`);
|
|
209
|
+
if (process.stdin.isTTY) {
|
|
210
|
+
if (!unwrap(await p.confirm({
|
|
211
|
+
message: `Create ${slug} from ${from}?`,
|
|
212
|
+
initialValue: true
|
|
213
|
+
}))) {
|
|
214
|
+
p.cancel("Nothing created.");
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const spin = p.spinner();
|
|
219
|
+
spin.start(`Creating ${slug} from ${from}…`);
|
|
220
|
+
let project;
|
|
221
|
+
try {
|
|
222
|
+
({project} = await withContext(apiRequest("POST", "/projects", {
|
|
223
|
+
slug,
|
|
224
|
+
name,
|
|
225
|
+
from
|
|
226
|
+
}), {
|
|
227
|
+
action: `create ${slug} from ${from}`,
|
|
228
|
+
fixes: TEMPLATE_FIXES
|
|
229
|
+
}));
|
|
230
|
+
} catch (err) {
|
|
231
|
+
spin.error("Create failed.");
|
|
232
|
+
throw err;
|
|
233
|
+
}
|
|
234
|
+
spin.stop(`Created ${project.name} — ${projectUrl(project.slug)}`);
|
|
235
|
+
await cloneProjectRepo(slug, targetDir);
|
|
236
|
+
p.note(nextSteps(slug, preview.copies).join("\n"), `Cloned into ./${slug}/ — next`);
|
|
237
|
+
p.outro(`Live URL (after first deploy): ${projectUrl(project.slug)}`);
|
|
238
|
+
}
|
|
191
239
|
/** Empty enough to scaffold into: missing, or holding only dotfiles (.git, .agents…). */
|
|
192
240
|
function isEmptyish(dir) {
|
|
193
241
|
if (!existsSync(dir)) return true;
|
|
@@ -294,13 +342,31 @@ const projectsCommand = defineCommand({
|
|
|
294
342
|
name: "projects",
|
|
295
343
|
description: "List your projects"
|
|
296
344
|
},
|
|
297
|
-
args: {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
345
|
+
args: {
|
|
346
|
+
all: {
|
|
347
|
+
type: "boolean",
|
|
348
|
+
default: false,
|
|
349
|
+
description: "Include projects you can't edit"
|
|
350
|
+
},
|
|
351
|
+
templates: {
|
|
352
|
+
type: "boolean",
|
|
353
|
+
default: false,
|
|
354
|
+
description: "List the templates anyone can start a project from"
|
|
355
|
+
}
|
|
356
|
+
},
|
|
302
357
|
run: reportErrors("projects", async ({ args }) => {
|
|
303
358
|
const { projects, is_admin: isAdmin } = await apiRequest("GET", "/projects");
|
|
359
|
+
if (args.templates) {
|
|
360
|
+
const templates = projects.filter((project) => project.is_template);
|
|
361
|
+
if (templates.length === 0) {
|
|
362
|
+
console.log("No templates on this site yet.");
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
const width = Math.max(...templates.map((project) => project.slug.length));
|
|
366
|
+
for (const project of templates) console.log(`${project.slug.padEnd(width)} ${project.name} (${project.owner_email})`);
|
|
367
|
+
console.log(`\nStart from one with \`canopy create <name> --from <template>\`.`);
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
304
370
|
const mine = args.all || isAdmin ? projects : projects.filter((project) => project.role);
|
|
305
371
|
if (mine.length === 0) {
|
|
306
372
|
console.log(projects.length === 0 ? "No projects yet — run `canopy create`." : `No projects of your own yet — run \`canopy create\`, or --all to list all ${projects.length}.`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as projectDirArgs, c as resolveProject, n as siteConfig, u as tryReadCanopyJson } from "./site-DM2J10CB.mjs";
|
|
2
|
-
import { i as apiRequest, o as withContext } from "./api-
|
|
3
|
-
import { a as unwrap, i as requireTty, r as reportErrors, t as formatDateTime } from "./ui-
|
|
2
|
+
import { i as apiRequest, o as withContext } from "./api-BPEYm9ts.mjs";
|
|
3
|
+
import { a as unwrap, i as requireTty, r as reportErrors, t as formatDateTime } from "./ui-CHfKV6lG.mjs";
|
|
4
4
|
import { a as parseCredentialInput, i as helperCommand, o as runCredentialHelper, r as fileTokenCache, t as RepoCredentialError } from "./repo-credential-CNDRM-tG.mjs";
|
|
5
5
|
import { defineCommand } from "citty";
|
|
6
6
|
import { existsSync, realpathSync } from "node:fs";
|
|
@@ -268,20 +268,23 @@ const cloneCommand = defineCommand({
|
|
|
268
268
|
}
|
|
269
269
|
},
|
|
270
270
|
run: reportErrors("repo clone", async ({ args }) => {
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
await requireGit();
|
|
274
|
-
const target = resolve(args.target ?? slug);
|
|
275
|
-
const code = await gitInteractive([
|
|
276
|
-
"clone",
|
|
277
|
-
...credentialConfig(repo.remote, currentProfile(), slug).flatMap(([key, values]) => values.flatMap((value) => ["-c", `${key}=${value}`])),
|
|
278
|
-
repo.remote,
|
|
279
|
-
target
|
|
280
|
-
]);
|
|
281
|
-
if (code !== 0) throw new Error(`git clone failed (exit ${code}).`);
|
|
282
|
-
p.log.success(`Cloned ${slug} into ${target}.`);
|
|
271
|
+
const target = await cloneProjectRepo(args.slug, resolve(args.target ?? args.slug));
|
|
272
|
+
p.log.success(`Cloned ${args.slug} into ${target}.`);
|
|
283
273
|
})
|
|
284
274
|
});
|
|
275
|
+
/** Clone a project's Canopy repository into `target`, credential helper included. */
|
|
276
|
+
async function cloneProjectRepo(slug, target) {
|
|
277
|
+
const repo = requireCanopyRepo(slug, await fetchRepo(slug));
|
|
278
|
+
await requireGit();
|
|
279
|
+
const code = await gitInteractive([
|
|
280
|
+
"clone",
|
|
281
|
+
...credentialConfig(repo.remote, currentProfile(), slug).flatMap(([key, values]) => values.flatMap((value) => ["-c", `${key}=${value}`])),
|
|
282
|
+
repo.remote,
|
|
283
|
+
target
|
|
284
|
+
]);
|
|
285
|
+
if (code !== 0) throw new Error(`git clone failed (exit ${code}).`);
|
|
286
|
+
return target;
|
|
287
|
+
}
|
|
285
288
|
const deleteCommand = defineCommand({
|
|
286
289
|
meta: {
|
|
287
290
|
name: "delete",
|
|
@@ -420,4 +423,4 @@ async function offerRepoOnCreate(slug, dir, flag) {
|
|
|
420
423
|
}
|
|
421
424
|
}
|
|
422
425
|
//#endregion
|
|
423
|
-
export { repoCommand as i,
|
|
426
|
+
export { repoCommand as a, offerRepoOnCreate as i, cloneProjectRepo as n, connectFolder as r, cliInvocation as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c as resolveProject, o as projectFlagArgs } from "./site-DM2J10CB.mjs";
|
|
2
|
-
import { i as apiRequest, o as withContext } from "./api-
|
|
3
|
-
import { r as reportErrors, t as formatDateTime } from "./ui-
|
|
2
|
+
import { i as apiRequest, o as withContext } from "./api-BPEYm9ts.mjs";
|
|
3
|
+
import { r as reportErrors, t as formatDateTime } from "./ui-CHfKV6lG.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
//#region src/schedule.ts
|
|
6
6
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as projectDirArgs, c as resolveProject } from "./site-DM2J10CB.mjs";
|
|
2
|
-
import { i as apiRequest, o as withContext } from "./api-
|
|
3
|
-
import { a as unwrap, r as reportErrors, t as formatDateTime } from "./ui-
|
|
2
|
+
import { i as apiRequest, o as withContext } from "./api-BPEYm9ts.mjs";
|
|
3
|
+
import { a as unwrap, r as reportErrors, t as formatDateTime } from "./ui-CHfKV6lG.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import * as p from "@clack/prompts";
|
|
6
6
|
//#region src/secrets.ts
|
|
@@ -52,13 +52,14 @@ const secretsCommand = defineCommand({
|
|
|
52
52
|
args: { ...projectDirArgs },
|
|
53
53
|
run: reportErrors("secrets list", async ({ args }) => {
|
|
54
54
|
const { slug } = resolveProject(args);
|
|
55
|
-
const { secrets } = await apiRequest("GET", `/projects/${slug}/secrets`);
|
|
56
|
-
if (secrets.length === 0) {
|
|
55
|
+
const { secrets, missing = [] } = await apiRequest("GET", `/projects/${slug}/secrets`);
|
|
56
|
+
if (secrets.length === 0 && missing.length === 0) {
|
|
57
57
|
console.log(`No secrets set for ${slug} — add one with \`canopy secrets set NAME\`.`);
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
|
-
const width = Math.max(...secrets.map((s) => s.key.length));
|
|
60
|
+
const width = Math.max(...secrets.map((s) => s.key.length), ...missing.map((m) => m.length));
|
|
61
61
|
for (const s of secrets) console.log(`${s.key.padEnd(width)} updated ${formatDateTime(s.updated_at)}`);
|
|
62
|
+
for (const name of missing) console.log(`${name.padEnd(width)} missing — set it with \`canopy secrets set ${name}\``);
|
|
62
63
|
})
|
|
63
64
|
}),
|
|
64
65
|
set: defineCommand({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as version } from "./package-
|
|
2
|
-
import { r as reportErrors } from "./ui-
|
|
1
|
+
import { t as version } from "./package-CdDH35SE.mjs";
|
|
2
|
+
import { r as reportErrors } from "./ui-CHfKV6lG.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import { cpSync, existsSync, mkdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { homedir } from "node:os";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c as resolveProject, l as stagingUrl, o as projectFlagArgs, s as projectUrl } from "./site-DM2J10CB.mjs";
|
|
2
|
-
import { i as apiRequest, o as withContext } from "./api-
|
|
3
|
-
import { a as unwrap, i as requireTty, r as reportErrors, t as formatDateTime } from "./ui-
|
|
2
|
+
import { i as apiRequest, o as withContext } from "./api-BPEYm9ts.mjs";
|
|
3
|
+
import { a as unwrap, i as requireTty, r as reportErrors, t as formatDateTime } from "./ui-CHfKV6lG.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import * as p from "@clack/prompts";
|
|
6
6
|
//#region src/staging.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as projectDirArgs, c as resolveProject, o as projectFlagArgs } from "./site-DM2J10CB.mjs";
|
|
2
|
-
import { i as apiRequest } from "./api-
|
|
3
|
-
import { r as reportErrors, t as formatDateTime } from "./ui-
|
|
2
|
+
import { i as apiRequest } from "./api-BPEYm9ts.mjs";
|
|
3
|
+
import { r as reportErrors, t as formatDateTime } from "./ui-CHfKV6lG.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
const tokenCommand = defineCommand({
|
|
6
6
|
meta: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as PACKAGE_NAME } from "./version-check-CcsA1QjI.mjs";
|
|
2
|
-
import { r as reportErrors } from "./ui-
|
|
2
|
+
import { r as reportErrors } from "./ui-CHfKV6lG.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
@@ -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-3wOwhzDx.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());
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c as resolveProject, o as projectFlagArgs } from "./site-DM2J10CB.mjs";
|
|
2
|
-
import { i as apiRequest, o as withContext } from "./api-
|
|
3
|
-
import { r as reportErrors } from "./ui-
|
|
2
|
+
import { i as apiRequest, o as withContext } from "./api-BPEYm9ts.mjs";
|
|
3
|
+
import { r as reportErrors } from "./ui-CHfKV6lG.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
//#region src/usage.ts
|
|
6
6
|
/**
|
package/package.json
CHANGED
package/dist/dev-BeFX_wc5.mjs
DELETED
package/dist/repo-1RQ1vBMv.mjs
DELETED