@mediamonks/canopy-cli 0.7.0 → 0.7.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.
- package/dist/{db-BkUmbGgx.mjs → db-B8c6nhQ8.mjs} +2 -2
- package/dist/{deploy-BcczXlSQ.mjs → deploy-DuW0-201.mjs} +2 -2
- package/dist/{dev-DvyKHe2d.mjs → dev-DJwGvkDZ.mjs} +4 -4
- package/dist/dev-U9u6katn.mjs +2 -0
- package/dist/docs/porting-nextjs.md +7 -3
- package/dist/docs/staging.md +8 -0
- package/dist/docs/troubleshooting.md +12 -0
- package/dist/{docs-2cUEug69.mjs → docs-tof6Ou2-.mjs} +5 -1
- package/dist/index.mjs +22 -22
- package/dist/{local-C47tmhl7.mjs → local-DUp7p_2m.mjs} +2 -2
- package/dist/{login-ByD0hcxu.mjs → login-DZWQF4fS.mjs} +1 -1
- package/dist/{migrations-I1adj0z2.mjs → migrations-D1Va4TyD.mjs} +1 -1
- package/dist/{open-DD9oa-Ho.mjs → open-1ARSL5XC.mjs} +1 -1
- package/dist/{package-CDB-uxy3.mjs → package-BGFOC-Tg.mjs} +1 -1
- package/dist/{projects-CSH7KsPi.mjs → projects-CaGxv-4p.mjs} +1 -1
- package/dist/{skill-DrWzmUMv.mjs → skill-DHmCX1U-.mjs} +2 -2
- package/dist/{staging-CfF2-pHs.mjs → staging-DQQZXoKz.mjs} +44 -2
- package/dist/{token-nieJV1w7.mjs → token-CBuhzauo.mjs} +1 -1
- package/dist/{ui-D8HxX0Ng.mjs → ui-OMOjXJ2y.mjs} +36 -0
- package/dist/{upgrade-CH_jHkc7.mjs → upgrade-B8LKMI4s.mjs} +3 -3
- package/dist/{usage-qqPtkDtT.mjs → usage-DATkqUN0.mjs} +1 -1
- package/dist/{version-check-Cuh6HaLX.mjs → version-check-CcsA1QjI.mjs} +5 -1
- package/package.json +1 -1
- package/dist/dev-CvtoGFW0.mjs +0 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c as resolveProject, o as projectFlagArgs } from "./site-BUlQR117.mjs";
|
|
2
|
-
import { i as unwrap, l as withContext, n as reportErrors, o as apiDataRequest, r as requireTty } from "./ui-
|
|
3
|
-
import { n as migrateProject, r as readMigrationFiles, t as describeMigrateResult } from "./migrations-
|
|
2
|
+
import { i as unwrap, l as withContext, n as reportErrors, o as apiDataRequest, r as requireTty } from "./ui-OMOjXJ2y.mjs";
|
|
3
|
+
import { n as migrateProject, r as readMigrationFiles, t as describeMigrateResult } from "./migrations-D1Va4TyD.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
6
6
|
import * as p from "@clack/prompts";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as projectDirArgs, c as resolveProject, l as stagingUrl, n as siteConfig, o as projectFlagArgs, s as projectUrl, u as tryReadCanopyJson } from "./site-BUlQR117.mjs";
|
|
2
|
-
import { c as apiRequest, i as unwrap, l as withContext, n as reportErrors, o as apiDataRequest, s as apiDownload } from "./ui-
|
|
3
|
-
import { n as migrateProject, r as readMigrationFiles, t as describeMigrateResult } from "./migrations-
|
|
2
|
+
import { c as apiRequest, i as unwrap, l as withContext, n as reportErrors, o as apiDataRequest, s as apiDownload } from "./ui-OMOjXJ2y.mjs";
|
|
3
|
+
import { n as migrateProject, r as readMigrationFiles, t as describeMigrateResult } from "./migrations-D1Va4TyD.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as projectDirArgs, c as resolveProject, i as projectDialect, n as siteConfig, u as tryReadCanopyJson } from "./site-BUlQR117.mjs";
|
|
2
|
-
import { a as ApiError, c as apiRequest, l as withContext, n as reportErrors } from "./ui-
|
|
3
|
-
import { r as readMigrationFiles } from "./migrations-
|
|
2
|
+
import { a as ApiError, c as apiRequest, l as withContext, n as reportErrors } from "./ui-OMOjXJ2y.mjs";
|
|
3
|
+
import { r as readMigrationFiles } from "./migrations-D1Va4TyD.mjs";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { defineCommand } from "citty";
|
|
6
6
|
import { join } from "node:path";
|
|
@@ -112,7 +112,7 @@ async function devRemote(flags, slug) {
|
|
|
112
112
|
async function devLocal(flags, slug) {
|
|
113
113
|
let dump;
|
|
114
114
|
if (flags.pull) {
|
|
115
|
-
const { fetchProjectDump } = await import("./local-
|
|
115
|
+
const { fetchProjectDump } = await import("./local-DUp7p_2m.mjs");
|
|
116
116
|
console.log(`Pulling a fresh export of ${slug}${flags.staging ? " [staging]" : ""}…`);
|
|
117
117
|
dump = await fetchProjectDump(slug, flags.staging ? "staging" : "live");
|
|
118
118
|
}
|
|
@@ -127,7 +127,7 @@ async function devLocal(flags, slug) {
|
|
|
127
127
|
const reason = err instanceof ApiError ? err.explain().why : String(err);
|
|
128
128
|
console.log(`Note: ai/services will be unavailable — could not reach the platform (${reason}).`);
|
|
129
129
|
}
|
|
130
|
-
const { createSandbox } = await import("./local-
|
|
130
|
+
const { createSandbox } = await import("./local-DUp7p_2m.mjs");
|
|
131
131
|
const sandbox = await createSandbox({
|
|
132
132
|
slug,
|
|
133
133
|
persistDir: join(flags.dir, ".canopy", "local"),
|
|
@@ -166,9 +166,13 @@ Rules of the road for the worker:
|
|
|
166
166
|
stick to packages that don't need Node built-ins or native modules.
|
|
167
167
|
- **No filesystem, no long-lived state.** Persist through `canopy.db` and
|
|
168
168
|
`canopy.blob`.
|
|
169
|
-
- **Outbound requests are controlled.**
|
|
170
|
-
platform-managed egress allowlist
|
|
171
|
-
|
|
169
|
+
- **Outbound requests are controlled.** On the GCP target, calls to external
|
|
170
|
+
APIs pass through a platform-managed egress allowlist that is currently
|
|
171
|
+
fixed to platform infrastructure — there is no self-service way to add
|
|
172
|
+
hosts yet. Contact the platform team with the exact hostnames your project
|
|
173
|
+
needs (per-project allowlist management is planned; see `egress_denied` in
|
|
174
|
+
the [troubleshooting guide](https://docs.canopy.website/guides/troubleshooting)). On the Cloudflare
|
|
175
|
+
target outbound requests are currently unrestricted.
|
|
172
176
|
- Frontend calls are plain `fetch("/api/…")` — same origin, the platform
|
|
173
177
|
session cookie rides along automatically.
|
|
174
178
|
|
package/dist/docs/staging.md
CHANGED
|
@@ -51,6 +51,14 @@ canopy promote # the same migrations replay against live, then v g
|
|
|
51
51
|
A migration that fails on staging costs you nothing — live never saw it. See
|
|
52
52
|
[Schema migrations](https://docs.canopy.website/guides/migrations) for the migration system itself.
|
|
53
53
|
|
|
54
|
+
## Staging an older version
|
|
55
|
+
|
|
56
|
+
Any version in the deploy history can be pointed at the staging channel —
|
|
57
|
+
from the dashboard's deploy list (the **Stage** action, next to Rollback) or
|
|
58
|
+
with `canopy staging use v3`. Like rollback, it's a pointer move: nothing is
|
|
59
|
+
rebuilt, and live is untouched. Handy for comparing an old build against the
|
|
60
|
+
staging data, or re-testing a version before promoting it.
|
|
61
|
+
|
|
54
62
|
## Keeping staging fresh
|
|
55
63
|
|
|
56
64
|
Staging data drifts as you test. Re-clone it from live anytime:
|
|
@@ -59,6 +59,18 @@ The project hit its daily AI budget cap. The cap is enforced before every AI
|
|
|
59
59
|
call; it resets the next day, or a maintainer can raise the project's budget in
|
|
60
60
|
the dashboard.
|
|
61
61
|
|
|
62
|
+
## `egress_denied` (403)
|
|
63
|
+
|
|
64
|
+
An outbound `fetch` from your worker was blocked by the platform's egress
|
|
65
|
+
guard: `host <hostname> is not on the project allowlist`. On the GCP target
|
|
66
|
+
workers can only reach hosts on an allowlist, and today that list is fixed to
|
|
67
|
+
platform infrastructure (blob storage, Google auth, the Canopy API) — there is
|
|
68
|
+
no self-service way to add hosts yet. If your project needs to call an external
|
|
69
|
+
API, contact the platform team with the exact hostnames; per-project allowlist
|
|
70
|
+
management is planned. Calls made through the SDK / `env.CANOPY.fetch` don't
|
|
71
|
+
count as egress and are unaffected. On the Cloudflare target outbound requests
|
|
72
|
+
are currently unrestricted, so this error only appears on GCP.
|
|
73
|
+
|
|
62
74
|
## Docs are stale
|
|
63
75
|
|
|
64
76
|
`canopy docs` caches the platform's docs. Force a refresh:
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { t as version } from "./package-BGFOC-Tg.mjs";
|
|
1
2
|
import { n as siteConfig } from "./site-BUlQR117.mjs";
|
|
2
|
-
import {
|
|
3
|
+
import { i as latestKnownVersion, r as compareSemver } from "./version-check-CcsA1QjI.mjs";
|
|
4
|
+
import { n as reportErrors } from "./ui-OMOjXJ2y.mjs";
|
|
3
5
|
import { defineCommand } from "citty";
|
|
4
6
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
5
7
|
import { homedir } from "node:os";
|
|
@@ -172,6 +174,8 @@ const docsCommand = defineCommand({
|
|
|
172
174
|
run: reportErrors("docs", async ({ args }) => {
|
|
173
175
|
const refresh = args.refresh;
|
|
174
176
|
const topic = args.topic;
|
|
177
|
+
const latest = latestKnownVersion();
|
|
178
|
+
if (latest && compareSemver(version, latest) < 0) console.error(`Note: these docs describe CLI ${latest}; you have ${version} — commands or flags they mention may not exist here. Run \`canopy upgrade\`.\n`);
|
|
175
179
|
if (!topic) {
|
|
176
180
|
const topics = await listTopics(refresh);
|
|
177
181
|
if (topics.length === 0) throw new Error("No docs available — check your connection, or reinstall the CLI.");
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as version } from "./package-
|
|
2
|
+
import { t as version } from "./package-BGFOC-Tg.mjs";
|
|
3
3
|
import { r as siteHeaderLine, t as setInvocationProfile } from "./site-BUlQR117.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { a as notifyOfUpdate, o as runRefresh } from "./version-check-CcsA1QjI.mjs";
|
|
5
5
|
import { defineCommand, runMain } from "citty";
|
|
6
6
|
//#region src/index.ts
|
|
7
7
|
/**
|
|
@@ -73,26 +73,26 @@ const main = defineCommand({
|
|
|
73
73
|
description: "canopy — create and deploy vibecoded projects"
|
|
74
74
|
},
|
|
75
75
|
subCommands: {
|
|
76
|
-
login: () => import("./login-
|
|
77
|
-
whoami: () => import("./login-
|
|
78
|
-
logout: () => import("./login-
|
|
79
|
-
create: () => import("./projects-
|
|
80
|
-
init: () => import("./projects-
|
|
81
|
-
projects: () => import("./projects-
|
|
82
|
-
delete: () => import("./projects-
|
|
83
|
-
dev: () => import("./dev-
|
|
84
|
-
deploy: () => import("./deploy-
|
|
85
|
-
promote: () => import("./deploy-
|
|
86
|
-
staging: () => import("./staging-
|
|
87
|
-
rollback: () => import("./deploy-
|
|
88
|
-
download: () => import("./deploy-
|
|
89
|
-
token: () => import("./token-
|
|
90
|
-
db: () => import("./db-
|
|
91
|
-
usage: () => import("./usage-
|
|
92
|
-
open: () => import("./open-
|
|
93
|
-
docs: () => import("./docs-
|
|
94
|
-
skill: () => import("./skill-
|
|
95
|
-
upgrade: () => import("./upgrade-
|
|
76
|
+
login: () => import("./login-DZWQF4fS.mjs").then((m) => m.loginCommand),
|
|
77
|
+
whoami: () => import("./login-DZWQF4fS.mjs").then((m) => m.whoamiCommand),
|
|
78
|
+
logout: () => import("./login-DZWQF4fS.mjs").then((m) => m.logoutCommand),
|
|
79
|
+
create: () => import("./projects-CaGxv-4p.mjs").then((m) => m.createCommand),
|
|
80
|
+
init: () => import("./projects-CaGxv-4p.mjs").then((m) => m.initCommand),
|
|
81
|
+
projects: () => import("./projects-CaGxv-4p.mjs").then((m) => m.projectsCommand),
|
|
82
|
+
delete: () => import("./projects-CaGxv-4p.mjs").then((m) => m.deleteCommand),
|
|
83
|
+
dev: () => import("./dev-U9u6katn.mjs").then((m) => m.devCommand),
|
|
84
|
+
deploy: () => import("./deploy-DuW0-201.mjs").then((m) => m.deployCommand),
|
|
85
|
+
promote: () => import("./deploy-DuW0-201.mjs").then((m) => m.promoteCommand),
|
|
86
|
+
staging: () => import("./staging-DQQZXoKz.mjs").then((m) => m.stagingCommand),
|
|
87
|
+
rollback: () => import("./deploy-DuW0-201.mjs").then((m) => m.rollbackCommand),
|
|
88
|
+
download: () => import("./deploy-DuW0-201.mjs").then((m) => m.downloadCommand),
|
|
89
|
+
token: () => import("./token-CBuhzauo.mjs").then((m) => m.tokenCommand),
|
|
90
|
+
db: () => import("./db-B8c6nhQ8.mjs").then((m) => m.dbCommand),
|
|
91
|
+
usage: () => import("./usage-DATkqUN0.mjs").then((m) => m.usageCommand),
|
|
92
|
+
open: () => import("./open-1ARSL5XC.mjs").then((m) => m.openCommand),
|
|
93
|
+
docs: () => import("./docs-tof6Ou2-.mjs").then((m) => m.docsCommand),
|
|
94
|
+
skill: () => import("./skill-DHmCX1U-.mjs").then((m) => m.skillCommand),
|
|
95
|
+
upgrade: () => import("./upgrade-B8LKMI4s.mjs").then((m) => m.upgradeCommand),
|
|
96
96
|
logs: planned("logs", "Tail worker logs", "2")
|
|
97
97
|
}
|
|
98
98
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { o as apiDataRequest } from "./ui-
|
|
2
|
-
import { n as rewriteApiPath } from "./dev-
|
|
1
|
+
import { o as apiDataRequest } from "./ui-OMOjXJ2y.mjs";
|
|
2
|
+
import { n as rewriteApiPath } from "./dev-DJwGvkDZ.mjs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { dirname, join, relative, sep } from "node:path";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { _ as getBakedProfile, d as clearAllProfileTokens, f as listBakedProfiles, g as writeConfigFile, h as upsertProfileAuth, m as setActiveProfile, n as siteConfig, p as readConfigFile, v as isProfileId } from "./site-BUlQR117.mjs";
|
|
2
|
-
import { n as reportErrors, t as openBrowser } from "./ui-
|
|
2
|
+
import { n as reportErrors, t as openBrowser } from "./ui-OMOjXJ2y.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import * as p from "@clack/prompts";
|
|
5
5
|
import { createHash, randomBytes } from "node:crypto";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { u as tryReadCanopyJson } from "./site-BUlQR117.mjs";
|
|
2
|
-
import { o as apiDataRequest } from "./ui-
|
|
2
|
+
import { o as apiDataRequest } from "./ui-OMOjXJ2y.mjs";
|
|
3
3
|
import { readFileSync, readdirSync } from "node:fs";
|
|
4
4
|
import { join, resolve } from "node:path";
|
|
5
5
|
//#region src/migrations.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as projectDirArgs, c as resolveProject, l as stagingUrl, s as projectUrl } from "./site-BUlQR117.mjs";
|
|
2
|
-
import { n as reportErrors, t as openBrowser } from "./ui-
|
|
2
|
+
import { n as reportErrors, t as openBrowser } from "./ui-OMOjXJ2y.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
//#region src/open.ts
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as siteConfig, s as projectUrl, u as tryReadCanopyJson } from "./site-BUlQR117.mjs";
|
|
2
|
-
import { c as apiRequest, i as unwrap, n as reportErrors, r as requireTty } from "./ui-
|
|
2
|
+
import { c as apiRequest, i as unwrap, n as reportErrors, r as requireTty } from "./ui-OMOjXJ2y.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { join, relative, resolve, sep } from "node:path";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as version } from "./package-
|
|
2
|
-
import { n as reportErrors } from "./ui-
|
|
1
|
+
import { t as version } from "./package-BGFOC-Tg.mjs";
|
|
2
|
+
import { n as reportErrors } from "./ui-OMOjXJ2y.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import { cpSync, existsSync, mkdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { join, relative } from "node:path";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c as resolveProject, l as stagingUrl, o as projectFlagArgs, s as projectUrl } from "./site-BUlQR117.mjs";
|
|
2
|
-
import { c as apiRequest, i as unwrap, l as withContext, n as reportErrors, r as requireTty } from "./ui-
|
|
2
|
+
import { c as apiRequest, i as unwrap, l as withContext, n as reportErrors, r as requireTty } from "./ui-OMOjXJ2y.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import * as p from "@clack/prompts";
|
|
5
5
|
//#region src/staging.ts
|
|
@@ -13,7 +13,7 @@ const fetchStatus = (slug) => apiRequest("GET", `/projects/${slug}/staging`);
|
|
|
13
13
|
const stagingCommand = defineCommand({
|
|
14
14
|
meta: {
|
|
15
15
|
name: "staging",
|
|
16
|
-
description: "Staging channel: status, sync, destroy"
|
|
16
|
+
description: "Staging channel: status, use, sync, destroy"
|
|
17
17
|
},
|
|
18
18
|
subCommands: {
|
|
19
19
|
status: defineCommand({
|
|
@@ -35,6 +35,48 @@ const stagingCommand = defineCommand({
|
|
|
35
35
|
if (staging.version !== null && staging.version !== staging.live) console.log(` \`canopy promote\` makes v${staging.version} live`);
|
|
36
36
|
})
|
|
37
37
|
}),
|
|
38
|
+
use: defineCommand({
|
|
39
|
+
meta: {
|
|
40
|
+
name: "use",
|
|
41
|
+
description: "Serve an existing version on the staging channel (pick from history)"
|
|
42
|
+
},
|
|
43
|
+
args: {
|
|
44
|
+
version: {
|
|
45
|
+
type: "positional",
|
|
46
|
+
description: "Version to stage, e.g. v3 (picked from a list when omitted)",
|
|
47
|
+
required: false
|
|
48
|
+
},
|
|
49
|
+
...projectFlagArgs
|
|
50
|
+
},
|
|
51
|
+
run: reportErrors("staging use", async ({ args }) => {
|
|
52
|
+
const { slug } = resolveProject(args);
|
|
53
|
+
let target;
|
|
54
|
+
if (args.version !== void 0) {
|
|
55
|
+
if (!/^v?\d+$/.test(args.version)) throw new Error(`Invalid version "${args.version}" — expected a number like 3 or v3.`);
|
|
56
|
+
target = Number(args.version.replace(/^v/, ""));
|
|
57
|
+
} else {
|
|
58
|
+
requireTty("pass a version, e.g. `canopy staging use v3`.");
|
|
59
|
+
const { deploys, live, staging: staged } = await apiRequest("GET", `/projects/${slug}/deploys`);
|
|
60
|
+
if (deploys.length === 0) throw new Error("This project has no deploys yet.");
|
|
61
|
+
target = unwrap(await p.select({
|
|
62
|
+
message: "Version to serve on staging",
|
|
63
|
+
options: deploys.map((deploy) => ({
|
|
64
|
+
value: deploy.version,
|
|
65
|
+
label: `v${deploy.version} ${deploy.created_at} (${deploy.source})`,
|
|
66
|
+
hint: deploy.version === staged ? "staged" : deploy.version === live ? "live" : void 0
|
|
67
|
+
}))
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
const { staging: result } = await withContext(apiRequest("POST", `/projects/${slug}/deploys/${target}/stage`), {
|
|
71
|
+
action: `stage "${slug}" v${target}`,
|
|
72
|
+
fixes: {
|
|
73
|
+
staging_not_provisioned: "This project has no staging channel yet — create one in the dashboard's Settings, or with `canopy deploy --staging`.",
|
|
74
|
+
already_staged: `v${target} is already the staged version.`
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
console.log(`Staging: ${stagingUrl(slug)} (v${result.version}, was v${result.previous ?? "—"})`);
|
|
78
|
+
})
|
|
79
|
+
}),
|
|
38
80
|
sync: defineCommand({
|
|
39
81
|
meta: {
|
|
40
82
|
name: "sync",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as projectDirArgs, c as resolveProject, o as projectFlagArgs } from "./site-BUlQR117.mjs";
|
|
2
|
-
import { c as apiRequest, n as reportErrors } from "./ui-
|
|
2
|
+
import { c as apiRequest, n as reportErrors } from "./ui-OMOjXJ2y.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
const tokenCommand = defineCommand({
|
|
5
5
|
meta: {
|
|
@@ -274,10 +274,46 @@ function formatCliError(name, err) {
|
|
|
274
274
|
}
|
|
275
275
|
return `canopy ${name}: ${err instanceof Error ? err.message : String(err)}`;
|
|
276
276
|
}
|
|
277
|
+
const kebab = (s) => s.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
|
|
278
|
+
const camel = (s) => s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
279
|
+
/**
|
|
280
|
+
* Reject flags a command does not declare. citty parses with strict: false, so
|
|
281
|
+
* a misspelled or not-yet-released flag would otherwise be silently dropped —
|
|
282
|
+
* on `deploy --staging` (pre-0.7) that meant deploying to the wrong channel.
|
|
283
|
+
*/
|
|
284
|
+
function assertKnownFlags(name, rawArgs, argDefs) {
|
|
285
|
+
const known = /* @__PURE__ */ new Set([
|
|
286
|
+
"help",
|
|
287
|
+
"h",
|
|
288
|
+
"version",
|
|
289
|
+
"profile"
|
|
290
|
+
]);
|
|
291
|
+
for (const [key, def] of Object.entries(argDefs)) {
|
|
292
|
+
if (def.type === "positional") continue;
|
|
293
|
+
known.add(key);
|
|
294
|
+
known.add(kebab(key));
|
|
295
|
+
known.add(camel(key));
|
|
296
|
+
const aliases = typeof def.alias === "string" ? [def.alias] : def.alias ?? [];
|
|
297
|
+
for (const a of aliases) known.add(a);
|
|
298
|
+
if (def.type === "boolean") {
|
|
299
|
+
known.add(`no-${key}`);
|
|
300
|
+
known.add(`no-${kebab(key)}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
for (const token of rawArgs) {
|
|
304
|
+
if (token === "--") break;
|
|
305
|
+
if (!token.startsWith("-") || token === "-") continue;
|
|
306
|
+
const body = token.replace(/^--?/, "").split("=")[0] ?? "";
|
|
307
|
+
if (!body || /^\d/.test(body)) continue;
|
|
308
|
+
if (!known.has(body)) throw new Error(`Unknown flag --${body}. Run \`canopy ${name} --help\` to see supported flags — if the docs mention it, your CLI may be outdated (\`canopy upgrade\`).`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
277
311
|
/** Wrap a command action so failures print an actionable report and exit 1. */
|
|
278
312
|
function reportErrors(name, action) {
|
|
279
313
|
return async (...args) => {
|
|
280
314
|
try {
|
|
315
|
+
const ctx = args[0];
|
|
316
|
+
if (ctx?.rawArgs && ctx.cmd?.args) assertKnownFlags(name, ctx.rawArgs, ctx.cmd.args);
|
|
281
317
|
await action(...args);
|
|
282
318
|
} catch (err) {
|
|
283
319
|
console.error(formatCliError(name, err));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as PACKAGE_NAME } from "./version-check-
|
|
2
|
-
import { n as reportErrors } from "./ui-
|
|
1
|
+
import { t as PACKAGE_NAME } from "./version-check-CcsA1QjI.mjs";
|
|
2
|
+
import { n as reportErrors } from "./ui-OMOjXJ2y.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-DHmCX1U-.mjs");
|
|
116
116
|
const refreshSkill = skillInstalled(process.cwd());
|
|
117
117
|
console.log(`Upgrading via ${command}: ${command} ${cmd.join(" ")}`);
|
|
118
118
|
await run(command, cmd);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c as resolveProject, o as projectFlagArgs } from "./site-BUlQR117.mjs";
|
|
2
|
-
import { c as apiRequest, l as withContext, n as reportErrors } from "./ui-
|
|
2
|
+
import { c as apiRequest, l as withContext, n as reportErrors } from "./ui-OMOjXJ2y.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
//#region src/usage.ts
|
|
5
5
|
/**
|
|
@@ -72,6 +72,10 @@ function writeCache(cache) {
|
|
|
72
72
|
function disabled() {
|
|
73
73
|
return process.env["CANOPY_NO_UPDATE_CHECK"] === "1" || process.env["CI"] !== void 0 || !process.stderr.isTTY;
|
|
74
74
|
}
|
|
75
|
+
/** Latest version seen on the registry (from cache), if any. */
|
|
76
|
+
function latestKnownVersion() {
|
|
77
|
+
return readCache()?.latest;
|
|
78
|
+
}
|
|
75
79
|
/**
|
|
76
80
|
* Print an update hint from cache (if we're behind), then kick off a detached
|
|
77
81
|
* background refresh when the cache is stale. Never throws, never blocks.
|
|
@@ -125,4 +129,4 @@ async function runRefresh() {
|
|
|
125
129
|
writeCache(cache);
|
|
126
130
|
}
|
|
127
131
|
//#endregion
|
|
128
|
-
export {
|
|
132
|
+
export { notifyOfUpdate as a, latestKnownVersion as i, REFRESH_ENV as n, runRefresh as o, compareSemver as r, PACKAGE_NAME as t };
|
package/package.json
CHANGED
package/dist/dev-CvtoGFW0.mjs
DELETED