@mediamonks/canopy-cli 0.2.0 → 0.3.1
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/getting-started.md +6 -1
- package/dist/index.mjs +6 -6
- package/dist/{package-OcWG7JAW.mjs → package-B34Xg7L3.mjs} +1 -1
- package/dist/{projects-DJT_mJDR.mjs → projects-DOYKtMZC.mjs} +2 -2
- package/dist/skill/canopy/SKILL.md +23 -0
- package/dist/{skill-jbmERP1X.mjs → skill-BlRch5eA.mjs} +1 -1
- package/dist/{upgrade-Y8ejvoeg.mjs → upgrade-DblPIwpX.mjs} +51 -22
- package/package.json +1 -1
|
@@ -60,9 +60,14 @@ This prompts for a name and a starter template, scaffolds a runnable project
|
|
|
60
60
|
directory, and registers the project on the platform. To skip the prompts:
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
canopy create "My App" --scaffold --template
|
|
63
|
+
canopy create "My App" --scaffold --template spa
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
Templates: **`static`** (no-build html/css/js; SDK served untyped from the
|
|
67
|
+
platform) is the default and fine for a trivial page or two. Reach for
|
|
68
|
+
**`spa`** (Vite + React + TypeScript; typed SDK from npm) once you lean on the
|
|
69
|
+
SDK or expect the app to grow — most projects want this.
|
|
70
|
+
|
|
66
71
|
## 4. Run it locally
|
|
67
72
|
|
|
68
73
|
```bash
|
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-B34Xg7L3.mjs";
|
|
3
3
|
import { i as runRefresh, r as notifyOfUpdate } from "./version-check-CoWgQs2h.mjs";
|
|
4
4
|
import { defineCommand, runMain } from "citty";
|
|
5
5
|
//#region src/index.ts
|
|
@@ -44,9 +44,9 @@ const main = defineCommand({
|
|
|
44
44
|
login: () => import("./login-Dif9Y32q.mjs").then((m) => m.loginCommand),
|
|
45
45
|
whoami: () => import("./login-Dif9Y32q.mjs").then((m) => m.whoamiCommand),
|
|
46
46
|
logout: () => import("./login-Dif9Y32q.mjs").then((m) => m.logoutCommand),
|
|
47
|
-
create: () => import("./projects-
|
|
48
|
-
projects: () => import("./projects-
|
|
49
|
-
delete: () => import("./projects-
|
|
47
|
+
create: () => import("./projects-DOYKtMZC.mjs").then((m) => m.createCommand),
|
|
48
|
+
projects: () => import("./projects-DOYKtMZC.mjs").then((m) => m.projectsCommand),
|
|
49
|
+
delete: () => import("./projects-DOYKtMZC.mjs").then((m) => m.deleteCommand),
|
|
50
50
|
dev: () => import("./dev-D_GlUULk.mjs").then((m) => m.devCommand),
|
|
51
51
|
deploy: () => import("./deploy-N88l4Kt3.mjs").then((m) => m.deployCommand),
|
|
52
52
|
rollback: () => import("./deploy-N88l4Kt3.mjs").then((m) => m.rollbackCommand),
|
|
@@ -54,8 +54,8 @@ const main = defineCommand({
|
|
|
54
54
|
db: () => import("./db-CtUG4vfG.mjs").then((m) => m.dbCommand),
|
|
55
55
|
open: () => import("./open-xLiGUz_W.mjs").then((m) => m.openCommand),
|
|
56
56
|
docs: () => import("./docs-C3aOAx_A.mjs").then((m) => m.docsCommand),
|
|
57
|
-
skill: () => import("./skill-
|
|
58
|
-
upgrade: () => import("./upgrade-
|
|
57
|
+
skill: () => import("./skill-BlRch5eA.mjs").then((m) => m.skillCommand),
|
|
58
|
+
upgrade: () => import("./upgrade-DblPIwpX.mjs").then((m) => m.upgradeCommand),
|
|
59
59
|
logs: planned("logs", "Tail worker logs", "2")
|
|
60
60
|
}
|
|
61
61
|
});
|
|
@@ -21,12 +21,12 @@ const TEMPLATES = [
|
|
|
21
21
|
{
|
|
22
22
|
id: "static",
|
|
23
23
|
label: "Static site",
|
|
24
|
-
hint: "plain html/css/js, no build
|
|
24
|
+
hint: "plain html/css/js, no build; untyped SDK from the platform — simplest apps only"
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
id: "spa",
|
|
28
28
|
label: "React SPA",
|
|
29
|
-
hint: "Vite + React + TypeScript, SDK from npm",
|
|
29
|
+
hint: "Vite + React + TypeScript, typed SDK from npm — best for real SDK use or growth",
|
|
30
30
|
needsInstall: true
|
|
31
31
|
},
|
|
32
32
|
{
|
|
@@ -70,6 +70,29 @@ truth and never go stale.
|
|
|
70
70
|
- Manage data: `canopy db pull | snapshot | snapshots | restore`
|
|
71
71
|
- CI credentials: `canopy token create | list | revoke`
|
|
72
72
|
|
|
73
|
+
## Choosing a starter template (`canopy create`)
|
|
74
|
+
|
|
75
|
+
`canopy create` offers three scaffolds. **`static` is the default, but reach
|
|
76
|
+
for it only when the app is genuinely trivial** — a page or two with light SDK
|
|
77
|
+
use. Its SDK is served untyped from the platform (`/_api/v1/sdk.js`): no
|
|
78
|
+
autocomplete, no type-checking, mistakes only show up in the browser.
|
|
79
|
+
|
|
80
|
+
Prefer **`spa`** the moment either is true — which covers most real projects:
|
|
81
|
+
|
|
82
|
+
- **You lean on the SDK** (`db` queries, `blob`, `ai` — anything past a stray
|
|
83
|
+
`auth.user()`). `spa` installs the SDK from npm (`@mediamonks/canopy`), fully
|
|
84
|
+
typed, so the compiler catches mistakes as you write them.
|
|
85
|
+
- **The app will grow.** `spa` is Vite + React + TypeScript, giving components,
|
|
86
|
+
routing, and state a real home; `static` has no build step to organise into.
|
|
87
|
+
|
|
88
|
+
Use **`worker`** (`--template worker`; hidden from the picker) only when you
|
|
89
|
+
need server-side backend code — e.g. calling an external API with a secret the
|
|
90
|
+
browser can't hold. Per-project Workers are a Phase 2 preview (frontend deploys
|
|
91
|
+
now; `worker/` is picked up once the platform supports it).
|
|
92
|
+
|
|
93
|
+
Non-interactive: `canopy create "My App" --template spa`. **When unsure between
|
|
94
|
+
`static` and `spa`, pick `spa`.**
|
|
95
|
+
|
|
73
96
|
## Safety rules
|
|
74
97
|
|
|
75
98
|
- **Destructive commands** — `canopy db restore` and `canopy delete` wipe data.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as version } from "./package-
|
|
1
|
+
import { t as version } from "./package-B34Xg7L3.mjs";
|
|
2
2
|
import { n as reportErrors } from "./ui-C8VuPzGp.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import { cpSync, existsSync, mkdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
@@ -2,26 +2,58 @@ import { t as PACKAGE_NAME } from "./version-check-CoWgQs2h.mjs";
|
|
|
2
2
|
import { n as reportErrors } from "./ui-C8VuPzGp.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
5
6
|
//#region src/upgrade.ts
|
|
6
7
|
/**
|
|
7
8
|
* canopy upgrade — install the latest published CLI globally.
|
|
8
9
|
*
|
|
9
|
-
* We shell out to whichever
|
|
10
|
-
* defaulting to npm, and let it do the actual install so global prefixes,
|
|
11
|
-
* permissions and lockfiles stay
|
|
12
|
-
*
|
|
10
|
+
* We shell out to whichever installer we can detect (Vite+, npm, pnpm, yarn or
|
|
11
|
+
* bun), defaulting to npm, and let it do the actual install so global prefixes,
|
|
12
|
+
* permissions and lockfiles stay its concern. `--pm` overrides the guess;
|
|
13
|
+
* `--version` pins a specific release.
|
|
14
|
+
*
|
|
15
|
+
* Detecting Vite+ matters: `vp install -g` keeps its own global store under
|
|
16
|
+
* $VP_HOME and puts its bins first on PATH, so a plain `npm install -g` would
|
|
17
|
+
* install into npm's separate prefix and leave the active `canopy` untouched.
|
|
18
|
+
*/
|
|
19
|
+
const VALID_PMS = [
|
|
20
|
+
"viteplus",
|
|
21
|
+
"npm",
|
|
22
|
+
"pnpm",
|
|
23
|
+
"yarn",
|
|
24
|
+
"bun"
|
|
25
|
+
];
|
|
26
|
+
/** Where this CLI's own code lives — the surest hint at how it was installed. */
|
|
27
|
+
function installLocation() {
|
|
28
|
+
try {
|
|
29
|
+
return fileURLToPath(import.meta.url);
|
|
30
|
+
} catch {
|
|
31
|
+
return process.argv[1] ?? process.execPath;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Map the location of an installed binary to the installer that owns it — each
|
|
36
|
+
* keeps its global store in a recognisable place (Vite+ under $VP_HOME/packages,
|
|
37
|
+
* then …/pnpm/…, …/.bun/…, …/Yarn/…). Defaults to npm. Exported for testing.
|
|
13
38
|
*/
|
|
14
|
-
|
|
39
|
+
function installerForPath(path) {
|
|
40
|
+
if (/[\\/]\.vite-plus[\\/]packages[\\/]/.test(path)) return "viteplus";
|
|
41
|
+
if (/[\\/](?:pnpm|\.pnpm)[\\/]/.test(path)) return "pnpm";
|
|
42
|
+
if (/[\\/]\.bun[\\/]/.test(path)) return "bun";
|
|
43
|
+
if (/[\\/](?:Yarn|\.yarn)[\\/]/i.test(path)) return "yarn";
|
|
44
|
+
return "npm";
|
|
45
|
+
}
|
|
46
|
+
/** Best-effort guess of the installer that put this CLI on the machine. */
|
|
15
47
|
function detectPackageManager() {
|
|
16
48
|
const ua = process.env["npm_config_user_agent"] ?? "";
|
|
17
49
|
if (ua.startsWith("pnpm")) return "pnpm";
|
|
18
50
|
if (ua.startsWith("yarn")) return "yarn";
|
|
19
51
|
if (ua.startsWith("bun")) return "bun";
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return "
|
|
52
|
+
return installerForPath(installLocation());
|
|
53
|
+
}
|
|
54
|
+
/** The executable to invoke for `pm` (Vite+ drives installs through `vp`). */
|
|
55
|
+
function pmCommand(pm) {
|
|
56
|
+
return pm === "viteplus" ? "vp" : pm;
|
|
25
57
|
}
|
|
26
58
|
/** The global-install argv for `pm`, targeting `spec` (e.g. name@latest). */
|
|
27
59
|
function installArgs(pm, spec) {
|
|
@@ -70,23 +102,20 @@ const upgradeCommand = defineCommand({
|
|
|
70
102
|
},
|
|
71
103
|
pm: {
|
|
72
104
|
type: "string",
|
|
73
|
-
description: "
|
|
105
|
+
description: "Installer to use: vp, npm, pnpm, yarn or bun (auto-detected by default)"
|
|
74
106
|
}
|
|
75
107
|
},
|
|
76
108
|
run: reportErrors("upgrade", async ({ args }) => {
|
|
77
|
-
const chosen = args.pm;
|
|
78
|
-
if (chosen && !
|
|
79
|
-
"npm",
|
|
80
|
-
"pnpm",
|
|
81
|
-
"yarn",
|
|
82
|
-
"bun"
|
|
83
|
-
].includes(chosen)) throw new Error(`Unknown --pm "${chosen}" — use npm, pnpm, yarn or bun.`);
|
|
109
|
+
const chosen = args.pm === "vp" ? "viteplus" : args.pm;
|
|
110
|
+
if (chosen && !VALID_PMS.includes(chosen)) throw new Error(`Unknown --pm "${args.pm}" — use vp, npm, pnpm, yarn or bun.`);
|
|
84
111
|
const pm = chosen ?? detectPackageManager();
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
112
|
+
const spec = `${PACKAGE_NAME}@${args.version ?? "latest"}`;
|
|
113
|
+
const command = pmCommand(pm);
|
|
114
|
+
const cmd = installArgs(pm, spec);
|
|
115
|
+
console.log(`Upgrading via ${command}: ${command} ${cmd.join(" ")}`);
|
|
116
|
+
await run(command, cmd);
|
|
88
117
|
console.log(`\nDone. Run \`canopy --version\` to confirm.`);
|
|
89
|
-
const { skillInstalled } = await import("./skill-
|
|
118
|
+
const { skillInstalled } = await import("./skill-BlRch5eA.mjs");
|
|
90
119
|
if (skillInstalled(process.cwd())) {
|
|
91
120
|
console.log("Refreshing the Canopy agent skill in this repo…");
|
|
92
121
|
await run("canopy", ["skill", "install"]).catch((err) => {
|