@mediamonks/canopy-cli 0.5.1 → 0.7.0
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-BW1ZolWn.mjs → db-BkUmbGgx.mjs} +71 -15
- package/dist/{deploy-alC2--pZ.mjs → deploy-BcczXlSQ.mjs} +106 -8
- package/dist/dev-CvtoGFW0.mjs +2 -0
- package/dist/{dev-CQQhMOoD.mjs → dev-DvyKHe2d.mjs} +44 -14
- package/dist/docs/ci.md +1 -3
- package/dist/docs/cli.md +3 -4
- package/dist/docs/data.md +5 -4
- package/dist/docs/deploy.md +16 -4
- package/dist/docs/dev.md +13 -11
- package/dist/docs/getting-started.md +1 -3
- package/dist/docs/infrastructure.md +27 -15
- package/dist/docs/migrations.md +183 -0
- package/dist/docs/porting-nextjs.md +232 -0
- package/dist/docs/sdk-ai.md +103 -0
- package/dist/docs/sdk-auth.md +57 -0
- package/dist/docs/sdk-database.md +126 -0
- package/dist/docs/sdk-files.md +82 -0
- package/dist/docs/sdk-services.md +58 -0
- package/dist/docs/sdk.md +113 -0
- package/dist/docs/staging.md +98 -0
- package/dist/docs/static-serving.md +4 -1
- package/dist/docs/troubleshooting.md +1 -3
- package/dist/{docs-DvSPpSIR.mjs → docs-2cUEug69.mjs} +23 -10
- package/dist/index.mjs +22 -20
- package/dist/{local-C5-GWJcx.mjs → local-C47tmhl7.mjs} +365 -41
- package/dist/{login-BO6abf40.mjs → login-ByD0hcxu.mjs} +5 -3
- package/dist/migrations-I1adj0z2.mjs +50 -0
- package/dist/{open-DnlYDqrU.mjs → open-DD9oa-Ho.mjs} +11 -4
- package/dist/{package-CHoZKzaw.mjs → package-CDB-uxy3.mjs} +1 -1
- package/dist/{projects-ijfe7Ffx.mjs → projects-CSH7KsPi.mjs} +17 -9
- package/dist/{site-BJjoePQS.mjs → site-BUlQR117.mjs} +14 -1
- package/dist/skill/canopy/SKILL.md +24 -1
- package/dist/{skill-CW0QSbAJ.mjs → skill-DrWzmUMv.mjs} +2 -2
- package/dist/staging-CfF2-pHs.mjs +113 -0
- package/dist/templates/spa/AGENTS.md +4 -0
- package/dist/templates/static/AGENTS.md +4 -0
- package/dist/templates/worker/AGENTS.md +7 -0
- package/dist/{token-BeF9zczg.mjs → token-nieJV1w7.mjs} +2 -2
- package/dist/{ui-DThlyHgo.mjs → ui-D8HxX0Ng.mjs} +3 -2
- package/dist/{upgrade-CGz1yzsW.mjs → upgrade-CH_jHkc7.mjs} +2 -2
- package/dist/{usage-DQpH7A3X.mjs → usage-qqPtkDtT.mjs} +2 -2
- package/package.json +2 -2
- package/dist/dev-BJ5xEwqW.mjs +0 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { c as apiRequest, i as unwrap, n as reportErrors, r as requireTty } from "./ui-
|
|
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-D8HxX0Ng.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";
|
|
@@ -75,7 +75,12 @@ function writeCanopyJson(dir, fields) {
|
|
|
75
75
|
writeFileSync(join(dir, "canopy.json"), `${JSON.stringify(next, null, 2)}\n`);
|
|
76
76
|
}
|
|
77
77
|
function slugify(input) {
|
|
78
|
-
|
|
78
|
+
let slug = input.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-").replaceAll(/(^-+|-+$)/g, "").slice(0, 40);
|
|
79
|
+
while (slug.includes("-dot-")) slug = slug.replaceAll("-dot-", "-");
|
|
80
|
+
return slug;
|
|
81
|
+
}
|
|
82
|
+
function shouldScaffoldCreate(requested, cwd = process.cwd()) {
|
|
83
|
+
return requested ?? !existsSync(join(cwd, "canopy.json"));
|
|
79
84
|
}
|
|
80
85
|
const createCommand = defineCommand({
|
|
81
86
|
meta: {
|
|
@@ -98,7 +103,6 @@ const createCommand = defineCommand({
|
|
|
98
103
|
},
|
|
99
104
|
scaffold: {
|
|
100
105
|
type: "boolean",
|
|
101
|
-
default: true,
|
|
102
106
|
description: "Scaffold ./<slug>/ from the starter template",
|
|
103
107
|
negativeDescription: "Only register — no files written"
|
|
104
108
|
}
|
|
@@ -118,12 +122,16 @@ const createCommand = defineCommand({
|
|
|
118
122
|
message: "Slug",
|
|
119
123
|
defaultValue: slugify(name),
|
|
120
124
|
placeholder: slugify(name),
|
|
121
|
-
validate: (value) =>
|
|
125
|
+
validate: (value) => {
|
|
126
|
+
if (value && !/^[a-z0-9][a-z0-9-]*$/.test(value)) return "Lowercase letters, digits and dashes only.";
|
|
127
|
+
if (value?.includes("-dot-")) return `"-dot-" is reserved for preview hostnames.`;
|
|
128
|
+
}
|
|
122
129
|
})).trim();
|
|
123
130
|
slug ||= slugify(name);
|
|
131
|
+
const scaffold = shouldScaffoldCreate(args.scaffold);
|
|
124
132
|
let template = TEMPLATES.find((t) => t.id === (args.template ?? "static"));
|
|
125
133
|
if (!template) throw new Error(`Unknown template "${args.template}" — available: ${TEMPLATES.map((t) => t.id).join(", ")}.`);
|
|
126
|
-
if (
|
|
134
|
+
if (scaffold && !args.template && process.stdin.isTTY) {
|
|
127
135
|
const id = unwrap(await p.select({
|
|
128
136
|
message: "Template",
|
|
129
137
|
options: TEMPLATES.filter((t) => !t.hidden).map((t) => ({
|
|
@@ -136,7 +144,7 @@ const createCommand = defineCommand({
|
|
|
136
144
|
}
|
|
137
145
|
if (template.hidden) p.log.warn("Per-project Workers are not deployable yet (Phase 2) — `canopy deploy` publishes the frontend only for now.");
|
|
138
146
|
const targetDir = resolve(slug);
|
|
139
|
-
if (
|
|
147
|
+
if (scaffold && existsSync(targetDir)) throw new Error(`Directory ./${slug} already exists — remove it, or use --no-scaffold to only register.`);
|
|
140
148
|
const spin = p.spinner();
|
|
141
149
|
spin.start(`Registering ${slug}…`);
|
|
142
150
|
let project;
|
|
@@ -150,7 +158,7 @@ const createCommand = defineCommand({
|
|
|
150
158
|
throw err;
|
|
151
159
|
}
|
|
152
160
|
spin.stop(`Created ${project.name} — ${projectUrl(project.slug)}`);
|
|
153
|
-
if (
|
|
161
|
+
if (scaffold) {
|
|
154
162
|
scaffoldTemplate(template.id, targetDir, {
|
|
155
163
|
name,
|
|
156
164
|
slug
|
|
@@ -166,7 +174,7 @@ const createCommand = defineCommand({
|
|
|
166
174
|
];
|
|
167
175
|
p.note(steps.join("\n"), `Scaffolded ./${slug}/ (${template.id}) — next`);
|
|
168
176
|
p.outro(`Live URL (after first deploy): ${projectUrl(project.slug)}`);
|
|
169
|
-
} else p.outro("Registered without scaffolding — add a canopy.json to deploy an existing app.");
|
|
177
|
+
} else p.outro(existsSync(join(process.cwd(), "canopy.json")) ? "Registered without scaffolding — the existing canopy.json was left unchanged." : "Registered without scaffolding — add a canopy.json to deploy an existing app.");
|
|
170
178
|
})
|
|
171
179
|
});
|
|
172
180
|
/** Empty enough to scaffold into: missing, or holding only dotfiles (.git, .agents…). */
|
|
@@ -175,6 +175,12 @@ function projectUrl(slug) {
|
|
|
175
175
|
if (apiHost === "run.app" || apiHost.endsWith(".run.app") || apiHost.startsWith("api.")) throw new Error("Cannot derive the project URL. Set projectDomain (baked profile or CANOPY_PROJECT_DOMAIN).");
|
|
176
176
|
return `https://${slug}.${apiHost.split(".").slice(-2).join(".")}`;
|
|
177
177
|
}
|
|
178
|
+
/** The staging channel's URL (docs/14): the first label becomes `staging-dot-<slug>`. */
|
|
179
|
+
function stagingUrl(slug) {
|
|
180
|
+
const url = new URL(projectUrl(slug));
|
|
181
|
+
url.hostname = `staging-dot-${url.hostname}`;
|
|
182
|
+
return url.origin;
|
|
183
|
+
}
|
|
178
184
|
/** canopy.json parsed if present; undefined when the file is missing. */
|
|
179
185
|
function tryReadCanopyJson(dir) {
|
|
180
186
|
let raw;
|
|
@@ -185,6 +191,13 @@ function tryReadCanopyJson(dir) {
|
|
|
185
191
|
}
|
|
186
192
|
return JSON.parse(raw);
|
|
187
193
|
}
|
|
194
|
+
/** The validated dialect lock from canopy.json, if the project set one. */
|
|
195
|
+
function projectDialect(dir) {
|
|
196
|
+
const dialect = tryReadCanopyJson(dir)?.dialect;
|
|
197
|
+
if (dialect === void 0) return void 0;
|
|
198
|
+
if (dialect !== "sqlite" && dialect !== "postgres") throw new Error(`canopy.json "dialect" must be "sqlite" or "postgres", not ${JSON.stringify(dialect)}.`);
|
|
199
|
+
return dialect;
|
|
200
|
+
}
|
|
188
201
|
function readCanopyJson(dir) {
|
|
189
202
|
const config = tryReadCanopyJson(dir);
|
|
190
203
|
if (config === void 0) throw new Error(`No canopy.json in ${dir} — run from a project created by \`canopy create\`, add one ({"slug": "<slug>", "dist": "dist"}), or pass --project <slug>.`);
|
|
@@ -251,4 +264,4 @@ function siteHeaderLine(cliVersion) {
|
|
|
251
264
|
return `canopy ${cliVersion} · ${c.envOverride || !c.profileId ? c.apiUrl : `${c.profileId} (${c.projectDomain ?? new URL(c.apiUrl).hostname})`}`;
|
|
252
265
|
}
|
|
253
266
|
//#endregion
|
|
254
|
-
export {
|
|
267
|
+
export { getBakedProfile as _, projectDirArgs as a, resolveProject as c, clearAllProfileTokens as d, listBakedProfiles as f, writeConfigFile as g, upsertProfileAuth as h, projectDialect as i, stagingUrl as l, setActiveProfile as m, siteConfig as n, projectFlagArgs as o, readConfigFile as p, siteHeaderLine as r, projectUrl as s, setInvocationProfile as t, tryReadCanopyJson as u, isProfileId as v };
|
|
@@ -89,11 +89,34 @@ truth and never go stale.
|
|
|
89
89
|
current directory; add `--no-scaffold` to link an app you already have.
|
|
90
90
|
- Run locally: `canopy dev` (live data) or `canopy dev --local` (offline sandbox)
|
|
91
91
|
- Deploy: `canopy deploy` (add `--build` if the project has a build step)
|
|
92
|
+
- Test first on staging: `canopy deploy --staging` → verify → `canopy promote`
|
|
93
|
+
(own database cloned from live; `canopy staging status | sync | destroy`)
|
|
92
94
|
- Roll back: `canopy rollback`
|
|
93
95
|
- Open the live site: `canopy open`
|
|
94
|
-
- Manage data: `canopy db pull | snapshot | snapshots | restore`
|
|
96
|
+
- Manage data: `canopy db pull | snapshot | snapshots | restore | migrate`
|
|
95
97
|
- CI credentials: `canopy token create | list | revoke`
|
|
96
98
|
|
|
99
|
+
## Custom tables & migrations (devs; Drizzle recommended)
|
|
100
|
+
|
|
101
|
+
The document API (`canopy.db.collection(…)`) needs no schema — prefer it. When
|
|
102
|
+
a project defines its **own tables** (raw `canopy.db.sql()` / Drizzle), use the
|
|
103
|
+
migrations flow — read `canopy docs migrations` first. The rules that prevent
|
|
104
|
+
confusing failures:
|
|
105
|
+
|
|
106
|
+
- Pin `"dialect"` and `"migrations"` in `canopy.json`; put ordered `.sql`
|
|
107
|
+
files in that directory (Drizzle: `npx drizzle-kit generate` writes them).
|
|
108
|
+
- **There is no `DATABASE_URL` and never will be.** Never run
|
|
109
|
+
`drizzle-kit push`/`migrate`/`studio` or Drizzle's runtime `migrate()` —
|
|
110
|
+
generating is local, applying is Canopy's job: `canopy deploy` applies
|
|
111
|
+
pending migrations automatically (`canopy db migrate` applies without a
|
|
112
|
+
deploy; `canopy dev --local` applies to the sandbox on boot).
|
|
113
|
+
- Never edit an applied migration (the platform refuses edited history) and
|
|
114
|
+
never reference `_canopy_*` tables.
|
|
115
|
+
- **Schema change? Rehearse it on staging.** `canopy deploy --staging` applies
|
|
116
|
+
pending migrations to the staging database (a clone of live) — verify the
|
|
117
|
+
app there, then `canopy promote` replays them against live and flips the
|
|
118
|
+
version. Never promote with failing checks.
|
|
119
|
+
|
|
97
120
|
## Choosing a starter template (`canopy create` / `canopy init`)
|
|
98
121
|
|
|
99
122
|
Both `canopy create` and `canopy init` scaffold from the same three templates.
|
|
@@ -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-CDB-uxy3.mjs";
|
|
2
|
+
import { n as reportErrors } from "./ui-D8HxX0Ng.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";
|
|
@@ -0,0 +1,113 @@
|
|
|
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-D8HxX0Ng.mjs";
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
//#region src/staging.ts
|
|
6
|
+
/**
|
|
7
|
+
* canopy staging status | sync | destroy — the project's staging channel
|
|
8
|
+
* (docs/14): its own database (a clone of live), blob prefix and backend
|
|
9
|
+
* worker, served at staging-dot-<slug>.<domain>. Created lazily by
|
|
10
|
+
* `canopy deploy --staging`; promoted with `canopy promote`.
|
|
11
|
+
*/
|
|
12
|
+
const fetchStatus = (slug) => apiRequest("GET", `/projects/${slug}/staging`);
|
|
13
|
+
const stagingCommand = defineCommand({
|
|
14
|
+
meta: {
|
|
15
|
+
name: "staging",
|
|
16
|
+
description: "Staging channel: status, sync, destroy"
|
|
17
|
+
},
|
|
18
|
+
subCommands: {
|
|
19
|
+
status: defineCommand({
|
|
20
|
+
meta: {
|
|
21
|
+
name: "status",
|
|
22
|
+
description: "Show the staging channel's state"
|
|
23
|
+
},
|
|
24
|
+
args: projectFlagArgs,
|
|
25
|
+
run: reportErrors("staging status", async ({ args }) => {
|
|
26
|
+
const { slug } = resolveProject(args);
|
|
27
|
+
const { staging } = await fetchStatus(slug);
|
|
28
|
+
if (!staging.provisioned) {
|
|
29
|
+
console.log(`No staging channel for ${slug} — create one with \`canopy deploy --staging\`.`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
console.log(`Staging: ${stagingUrl(slug)}`);
|
|
33
|
+
console.log(` staged v${staging.version ?? "— (nothing deployed yet)"}` + (staging.hasWorker ? " (with backend)" : ""));
|
|
34
|
+
console.log(` live v${staging.live ?? "—"} ${projectUrl(slug)}`);
|
|
35
|
+
if (staging.version !== null && staging.version !== staging.live) console.log(` \`canopy promote\` makes v${staging.version} live`);
|
|
36
|
+
})
|
|
37
|
+
}),
|
|
38
|
+
sync: defineCommand({
|
|
39
|
+
meta: {
|
|
40
|
+
name: "sync",
|
|
41
|
+
description: "Re-clone the live database into staging (staging data is replaced)"
|
|
42
|
+
},
|
|
43
|
+
args: {
|
|
44
|
+
...projectFlagArgs,
|
|
45
|
+
yes: {
|
|
46
|
+
type: "boolean",
|
|
47
|
+
default: false,
|
|
48
|
+
description: "Skip the confirmation prompt"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
run: reportErrors("staging sync", async ({ args }) => {
|
|
52
|
+
const { slug } = resolveProject(args);
|
|
53
|
+
if (!args.yes) {
|
|
54
|
+
requireTty("pass --yes to sync without confirmation.");
|
|
55
|
+
if (!unwrap(await p.confirm({ message: `Replace "${slug}"'s STAGING data with a fresh copy of live?` }))) {
|
|
56
|
+
p.cancel("Aborted.");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const spin = p.spinner();
|
|
61
|
+
spin.start(`Cloning live → staging for ${slug}…`);
|
|
62
|
+
try {
|
|
63
|
+
await withContext(apiRequest("POST", `/projects/${slug}/staging/sync`), {
|
|
64
|
+
action: `sync staging for "${slug}"`,
|
|
65
|
+
fixes: { staging_not_provisioned: "This project has no staging channel yet — `canopy deploy --staging` creates one (already cloned from live)." }
|
|
66
|
+
});
|
|
67
|
+
} catch (err) {
|
|
68
|
+
spin.error("Sync failed.");
|
|
69
|
+
throw err;
|
|
70
|
+
}
|
|
71
|
+
spin.stop(`Staging database now matches live for ${slug}.`);
|
|
72
|
+
})
|
|
73
|
+
}),
|
|
74
|
+
destroy: defineCommand({
|
|
75
|
+
meta: {
|
|
76
|
+
name: "destroy",
|
|
77
|
+
description: "Tear the staging channel down (database, files, backend — live is untouched)"
|
|
78
|
+
},
|
|
79
|
+
args: {
|
|
80
|
+
...projectFlagArgs,
|
|
81
|
+
yes: {
|
|
82
|
+
type: "boolean",
|
|
83
|
+
default: false,
|
|
84
|
+
description: "Skip the type-the-slug confirmation"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
run: reportErrors("staging destroy", async ({ args }) => {
|
|
88
|
+
const { slug } = resolveProject(args);
|
|
89
|
+
if (!args.yes) {
|
|
90
|
+
requireTty("pass --yes to destroy without confirmation.");
|
|
91
|
+
if (unwrap(await p.text({ message: `This deletes "${slug}"'s staging database, files and backend (live is untouched). Type the slug to confirm.` })).trim() !== slug) {
|
|
92
|
+
p.cancel("Aborted.");
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const spin = p.spinner();
|
|
97
|
+
spin.start(`Destroying staging for ${slug}…`);
|
|
98
|
+
try {
|
|
99
|
+
await withContext(apiRequest("DELETE", `/projects/${slug}/staging`), {
|
|
100
|
+
action: `destroy staging for "${slug}"`,
|
|
101
|
+
fixes: { staging_not_provisioned: "This project has no staging channel." }
|
|
102
|
+
});
|
|
103
|
+
} catch (err) {
|
|
104
|
+
spin.error("Destroy failed.");
|
|
105
|
+
throw err;
|
|
106
|
+
}
|
|
107
|
+
spin.stop(`Staging channel removed for ${slug}. \`canopy deploy --staging\` recreates it.`);
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
//#endregion
|
|
113
|
+
export { stagingCommand };
|
|
@@ -30,6 +30,10 @@ the [Canopy dashboard](https://dashboard.thanarie.dev).
|
|
|
30
30
|
writes never reach the platform. Prefer it for destructive experiments.
|
|
31
31
|
- `canopy deploy` — builds (`npm run build`) and publishes `dist/`; live
|
|
32
32
|
(behind company login) at https://{{slug}}.thanarie.dev.
|
|
33
|
+
- Risky change (schema migration, backend rework)? `canopy deploy --staging`
|
|
34
|
+
first — a private copy with its own database cloned from live — verify, then
|
|
35
|
+
`canopy promote` ships the exact tested version. Never promote with failing
|
|
36
|
+
checks.
|
|
33
37
|
|
|
34
38
|
## Boundaries
|
|
35
39
|
|
|
@@ -29,6 +29,10 @@ the [Canopy dashboard](https://dashboard.thanarie.dev).
|
|
|
29
29
|
writes never reach the platform. Prefer it for destructive experiments.
|
|
30
30
|
- `canopy deploy` — publish; live (behind company login) at
|
|
31
31
|
https://{{slug}}.thanarie.dev.
|
|
32
|
+
- Risky change (schema migration, backend rework)? `canopy deploy --staging`
|
|
33
|
+
first — a private copy with its own database cloned from live — verify, then
|
|
34
|
+
`canopy promote` ships the exact tested version. Never promote with failing
|
|
35
|
+
checks.
|
|
32
36
|
|
|
33
37
|
## Boundaries
|
|
34
38
|
|
|
@@ -39,6 +39,13 @@ the [Canopy dashboard](https://dashboard.thanarie.dev).
|
|
|
39
39
|
writes never reach the platform. Prefer it for destructive experiments.
|
|
40
40
|
- `canopy deploy` — builds (`npm run build`) and publishes; live (behind
|
|
41
41
|
company login) at https://{{slug}}.thanarie.dev.
|
|
42
|
+
- Defining your own tables (raw `sql()` / Drizzle)? Use the migrations flow —
|
|
43
|
+
`canopy docs migrations`. Never invent a `DATABASE_URL` (none exists):
|
|
44
|
+
generate migrations locally, and `canopy deploy` applies them.
|
|
45
|
+
- Risky change (schema migration, backend rework)? `canopy deploy --staging`
|
|
46
|
+
first — a private copy with its own database cloned from live — verify, then
|
|
47
|
+
`canopy promote` ships the exact tested version. Never promote with failing
|
|
48
|
+
checks.
|
|
42
49
|
|
|
43
50
|
## Boundaries
|
|
44
51
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { c as apiRequest, n as reportErrors } from "./ui-
|
|
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-D8HxX0Ng.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
const tokenCommand = defineCommand({
|
|
5
5
|
meta: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as siteConfig } from "./site-
|
|
1
|
+
import { n as siteConfig } from "./site-BUlQR117.mjs";
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
3
|
import { cancel, isCancel } from "@clack/prompts";
|
|
4
4
|
//#region src/api.ts
|
|
@@ -211,13 +211,14 @@ async function apiDownload(path) {
|
|
|
211
211
|
* unscoped; the target project rides as X-Canopy-Project and the api. gateway
|
|
212
212
|
* re-vouches it (docs/10-cli-sites.md D17).
|
|
213
213
|
*/
|
|
214
|
-
async function apiDataRequest(method, path, projectSlug, body, rawContentType) {
|
|
214
|
+
async function apiDataRequest(method, path, projectSlug, body, rawContentType, channel) {
|
|
215
215
|
const { apiUrl, token, isDeployToken } = credentials();
|
|
216
216
|
const response = await fetch(`${apiUrl}/data/v1${path}`, {
|
|
217
217
|
method,
|
|
218
218
|
headers: {
|
|
219
219
|
authorization: `Bearer ${token}`,
|
|
220
220
|
"x-canopy-project": projectSlug,
|
|
221
|
+
...channel === "staging" ? { "x-canopy-channel": "staging" } : {},
|
|
221
222
|
...body === void 0 ? {} : { "content-type": rawContentType ?? "application/json" }
|
|
222
223
|
},
|
|
223
224
|
body: body === void 0 ? void 0 : rawContentType !== void 0 ? body : JSON.stringify(body)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as PACKAGE_NAME } from "./version-check-Cuh6HaLX.mjs";
|
|
2
|
-
import { n as reportErrors } from "./ui-
|
|
2
|
+
import { n as reportErrors } from "./ui-D8HxX0Ng.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-DrWzmUMv.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
|
-
import {
|
|
2
|
-
import { c as apiRequest, l as withContext, n as reportErrors } from "./ui-
|
|
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-D8HxX0Ng.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
//#region src/usage.ts
|
|
5
5
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mediamonks/canopy-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Canopy CLI — create, develop and deploy Canopy projects.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"canopy": "./dist/index.mjs"
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"hono": "^4.8.0",
|
|
22
22
|
"vite-server": "npm:vite@^7",
|
|
23
23
|
"@mediamonks/canopy": "0.0.3",
|
|
24
|
-
"@mediamonks/canopy-data-plane": "0.0.
|
|
24
|
+
"@mediamonks/canopy-data-plane": "0.0.2"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^26.1.1",
|
package/dist/dev-BJ5xEwqW.mjs
DELETED