@cervio/cli 0.1.4 → 1.0.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/LICENSE +21 -0
- package/README.md +38 -22
- package/dist/cli.js +73 -45
- package/package.json +29 -21
- package/dist/cli.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026-present Cervio S.r.l.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# @cervio/cli
|
|
2
2
|
|
|
3
|
-
Developer CLI for Cervio
|
|
4
|
-
|
|
3
|
+
Developer CLI for Cervio plugins: login, validate, pack, push and manage releases, built
|
|
4
|
+
on [`@cervio/plugin-core`](https://www.npmjs.com/package/@cervio/plugin-core), the same
|
|
5
|
+
validation the Cervio host applies to uploads.
|
|
5
6
|
|
|
6
7
|
The binary is `cervio`. This document is the **command reference** (source of truth for flags
|
|
7
8
|
and behaviour). Partner-facing install and multi-instance auth also live on
|
|
@@ -9,12 +10,11 @@ and behaviour). Partner-facing install and multi-instance auth also live on
|
|
|
9
10
|
|
|
10
11
|
## Install
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
Requires Node.js 26 or later.
|
|
13
14
|
|
|
14
15
|
```bash
|
|
15
|
-
npm install -
|
|
16
|
-
|
|
17
|
-
pnpm add -D @cervio/cli
|
|
16
|
+
npm install --save-dev @cervio/cli # per project (the templates already include it)
|
|
17
|
+
npm install -g @cervio/cli # or globally
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
## Typical workflow
|
|
@@ -31,8 +31,8 @@ cervio push --changelog "…" --expect-host https://your-instance.cervio.app
|
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
**First stable push before `--dev`.** The first upload must be a release-channel push
|
|
34
|
-
(`cervio push` without `--dev`) so the host creates the
|
|
35
|
-
|
|
34
|
+
(`cervio push` without `--dev`) so the host creates the plugin. Only then can
|
|
35
|
+
`cervio push --dev` upload a scratch build of it.
|
|
36
36
|
|
|
37
37
|
## Configuration
|
|
38
38
|
|
|
@@ -46,6 +46,7 @@ Env overrides:
|
|
|
46
46
|
|
|
47
47
|
- `CERVIO_URL` - host URL (wins over `cervio.json`, loses to an explicit `--host` flag)
|
|
48
48
|
- `CERVIO_TOKEN` - bearer token (wins over `~/.cervio/credentials.json` entirely)
|
|
49
|
+
- `CERVIO_CONFIG_DIR` - folder for `credentials.json` and `state.json` instead of `~/.cervio` (useful on CI runners)
|
|
49
50
|
|
|
50
51
|
Host resolution order for most commands: `--host` flag → `CERVIO_URL` → `cervio.json` `"host"`.
|
|
51
52
|
Token resolution order: `CERVIO_TOKEN` → `~/.cervio/credentials.json` entry for the resolved host.
|
|
@@ -55,8 +56,7 @@ Do not duplicate multi-instance guidance here - use the auth-instances docs (or
|
|
|
55
56
|
|
|
56
57
|
## PAT scopes
|
|
57
58
|
|
|
58
|
-
The plugin admin API is scope-gated
|
|
59
|
-
used with this CLI needs:
|
|
59
|
+
The plugin admin API is scope-gated. A personal access token used with this CLI needs:
|
|
60
60
|
|
|
61
61
|
| Scope | Commands |
|
|
62
62
|
|---|---|
|
|
@@ -86,7 +86,7 @@ declares scopes. Use **`plugin:read` + `plugin:push`** for this CLI.
|
|
|
86
86
|
| `versions` | `--host <url>`, `--json` |
|
|
87
87
|
| `download` | `--host <url>`, `--release <semver>`, `--dev`, `-o/--output <path>`, `--json` |
|
|
88
88
|
| `rollback <version>` | `--host <url>`, `--json` |
|
|
89
|
-
| `route set` | `--host <url>`, `--slug <slug>`, `--
|
|
89
|
+
| `route set` | `--host <url>`, `--slug <slug>`, `--dev-channel on\|off`, `--json` |
|
|
90
90
|
| `open` | `--host <url>` |
|
|
91
91
|
|
|
92
92
|
`--json` is for agents/CI: machine-readable stdout, no interactive prompts (failures become
|
|
@@ -147,7 +147,7 @@ Flow:
|
|
|
147
147
|
5. Packs the plugin (or validates `--file`) and `POST`s it to `/api/v1/admin/plugins/upload` as
|
|
148
148
|
`multipart/form-data` - see "Upload request format" below. **`--dev` requires the plugin
|
|
149
149
|
to already exist on the host** (i.e. at least one prior non-dev push) - the dev channel
|
|
150
|
-
|
|
150
|
+
updates a scratch build of an existing plugin and cannot create one.
|
|
151
151
|
6. On success, updates `lastHost` in `~/.cervio/state.json`.
|
|
152
152
|
|
|
153
153
|
Together with `cervio download`, `--file` lets you round-trip a host artifact
|
|
@@ -158,7 +158,7 @@ Together with `cervio download`, `--file` lets you round-trip a host artifact
|
|
|
158
158
|
|---|---|
|
|
159
159
|
| `--host <url>` | Override resolved host |
|
|
160
160
|
| `--release <semver>` | Download that release label (default: current active release) |
|
|
161
|
-
| `--dev` | Download the
|
|
161
|
+
| `--dev` | Download the dev-channel ZIP instead |
|
|
162
162
|
| `-o, --output <path>` | Destination file (default: `.cervio/out/<plugin_key>-vX.zip` or `…-dev.zip`) |
|
|
163
163
|
| `--json` | Machine-readable output |
|
|
164
164
|
|
|
@@ -181,10 +181,8 @@ With `--dev`, also prints `updated_by_email` and `updated_at` from the remote de
|
|
|
181
181
|
|
|
182
182
|
### `cervio init [name]`
|
|
183
183
|
|
|
184
|
-
Scaffolds a new plugin project
|
|
185
|
-
|
|
186
|
-
resolves the local workspace bin automatically. Optional positional `name` is passed through
|
|
187
|
-
to the scaffolder.
|
|
184
|
+
Scaffolds a new plugin project with [`@cervio/create-plugin`](../create-plugin), the same
|
|
185
|
+
scaffolder as `npm create @cervio/plugin`. The optional positional `name` is passed through.
|
|
188
186
|
|
|
189
187
|
### `cervio watch [--push] [--dev] [--host <url>]`
|
|
190
188
|
|
|
@@ -194,8 +192,8 @@ to the scaffolder.
|
|
|
194
192
|
| `--dev` | With `--push`, push to the dev channel |
|
|
195
193
|
| `--host <url>` | Override host for the push |
|
|
196
194
|
|
|
197
|
-
Watches `src/`
|
|
198
|
-
only build + validate run.
|
|
195
|
+
Watches `src/` (Node's recursive `fs.watch`, changes coalesced); on any change, rebuilds
|
|
196
|
+
and validates. Without `--push`, only build + validate run.
|
|
199
197
|
|
|
200
198
|
### `cervio doctor [--host <url>] [--json]`
|
|
201
199
|
|
|
@@ -219,7 +217,6 @@ row's UUID, not the semver string - the CLI resolves this for you).
|
|
|
219
217
|
|---|---|
|
|
220
218
|
| `--host <url>` | Override resolved host |
|
|
221
219
|
| `--slug <slug>` | New route slug |
|
|
222
|
-
| `--cache on\|off` | Enable/disable route artifact caching |
|
|
223
220
|
| `--dev-channel on\|off` | Enable/disable the plugin **dev channel** (required before `push --dev` is useful in the UI) |
|
|
224
221
|
| `--json` | Machine-readable output |
|
|
225
222
|
|
|
@@ -231,7 +228,7 @@ Example:
|
|
|
231
228
|
|
|
232
229
|
```bash
|
|
233
230
|
cervio route set --dev-channel on
|
|
234
|
-
cervio route set --slug timesheets --
|
|
231
|
+
cervio route set --slug timesheets --dev-channel on
|
|
235
232
|
```
|
|
236
233
|
|
|
237
234
|
### `cervio open [--host <url>]`
|
|
@@ -254,7 +251,7 @@ cervio status --dev --json
|
|
|
254
251
|
|
|
255
252
|
## Upload request format
|
|
256
253
|
|
|
257
|
-
|
|
254
|
+
`POST /api/v1/admin/plugins/upload` takes `multipart/form-data` with:
|
|
258
255
|
|
|
259
256
|
| Field | Type | Notes |
|
|
260
257
|
|---|---|---|
|
|
@@ -271,6 +268,11 @@ Response shape depends on `channel`:
|
|
|
271
268
|
- `dev`: `{ channel: "dev", plugin, dev_channel: { content_sha256, artifact_sha256, artifact_size_bytes, updated_at } }`.
|
|
272
269
|
Fails with `plugin_not_found` if the plugin doesn't exist yet (see `push` flow above).
|
|
273
270
|
|
|
271
|
+
## Requests
|
|
272
|
+
|
|
273
|
+
Every request sends `User-Agent: cervio-cli/<version> node/<version>`, so a Cervio host can
|
|
274
|
+
see which CLI versions are still in use.
|
|
275
|
+
|
|
274
276
|
## Known gaps
|
|
275
277
|
|
|
276
278
|
- `GET /api/v1/me` does not return an organization display name (only `organization_id`), so
|
|
@@ -286,3 +288,17 @@ pnpm --filter @cervio/cli build # tsup → dist/cli.js
|
|
|
286
288
|
pnpm --filter @cervio/cli typecheck
|
|
287
289
|
node packages/cli/dist/cli.js --help
|
|
288
290
|
```
|
|
291
|
+
|
|
292
|
+
## License
|
|
293
|
+
|
|
294
|
+
MIT, see [LICENSE](LICENSE).
|
|
295
|
+
|
|
296
|
+
**Trademark.** "Cervio" and the Cervio logo are trademarks of Cervio S.r.l. This license
|
|
297
|
+
does not grant permission to use them. You may say that a plugin "works with Cervio"; you
|
|
298
|
+
may not imply endorsement or ship a product named Cervio.
|
|
299
|
+
|
|
300
|
+
**Platform.** Using a Cervio organization is governed by your partner or customer
|
|
301
|
+
agreement, not by this license.
|
|
302
|
+
|
|
303
|
+
**Your plugins.** Plugins you write are yours: using this package gives Cervio no rights
|
|
304
|
+
over your plugin, and does not require you to open-source it.
|
package/dist/cli.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createRequire } from 'module';
|
|
3
2
|
import { Command } from 'commander';
|
|
3
|
+
import { createRequire } from 'module';
|
|
4
4
|
import { spawn } from 'child_process';
|
|
5
|
-
import
|
|
6
|
-
import { promises } from 'fs';
|
|
5
|
+
import { styleText } from 'util';
|
|
6
|
+
import { promises, openAsBlob, watch } from 'fs';
|
|
7
7
|
import path from 'path';
|
|
8
|
-
import { validatePluginDir, validatePluginZipBuffer, parseManifestObject, packPlugin } from '@cervio/plugin-core';
|
|
8
|
+
import { validatePluginDir, validatePluginZipBuffer, parseManifestObject, packPlugin, PLUGIN_ARTIFACT_SOFT_STRONG_WARN_BYTES, PLUGIN_ARTIFACT_SOFT_WARN_BYTES } from '@cervio/plugin-core';
|
|
9
9
|
import os from 'os';
|
|
10
|
+
import { createPlugin } from '@cervio/create-plugin';
|
|
10
11
|
import prompts2 from 'prompts';
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
var CLI_VERSION = createRequire(import.meta.url)("../package.json").version;
|
|
14
|
+
var USER_AGENT = `cervio-cli/${CLI_VERSION} node/${process.versions.node}`;
|
|
13
15
|
|
|
14
16
|
// src/api.ts
|
|
15
17
|
var ApiError = class extends Error {
|
|
@@ -31,6 +33,7 @@ function createApiClient(opts) {
|
|
|
31
33
|
const url = pathname.startsWith("http") ? pathname : `${baseUrl}${pathname}`;
|
|
32
34
|
const headers = new Headers(init.headers);
|
|
33
35
|
if (token) headers.set("Authorization", `Bearer ${token}`);
|
|
36
|
+
headers.set("User-Agent", USER_AGENT);
|
|
34
37
|
if (!headers.has("Accept")) headers.set("Accept", "application/json");
|
|
35
38
|
let res;
|
|
36
39
|
try {
|
|
@@ -39,7 +42,7 @@ function createApiClient(opts) {
|
|
|
39
42
|
throw new ApiError(0, `Could not reach ${url}: ${err.message}`);
|
|
40
43
|
}
|
|
41
44
|
const contentType = res.headers.get("content-type") ?? "";
|
|
42
|
-
let body
|
|
45
|
+
let body;
|
|
43
46
|
if (contentType.includes("application/json")) {
|
|
44
47
|
body = await res.json().catch(() => null);
|
|
45
48
|
} else {
|
|
@@ -87,7 +90,7 @@ function createApiClient(opts) {
|
|
|
87
90
|
body: JSON.stringify(data)
|
|
88
91
|
}),
|
|
89
92
|
/**
|
|
90
|
-
*
|
|
93
|
+
* `POST /api/v1/admin/plugins/upload`. Requires PAT
|
|
91
94
|
* scope `plugin:push`. multipart/form-data fields:
|
|
92
95
|
* - `file` (required): the packed .zip, content-type application/zip.
|
|
93
96
|
* - `plugin_id` (optional UUID): omitted by this CLI - the backend
|
|
@@ -117,6 +120,7 @@ async function downloadBinary(pathname, opts) {
|
|
|
117
120
|
const url = pathname.startsWith("http") ? pathname : `${opts.host}${pathname}`;
|
|
118
121
|
const headers = new Headers({ Accept: "application/zip, application/octet-stream, */*" });
|
|
119
122
|
if (opts.token) headers.set("Authorization", `Bearer ${opts.token}`);
|
|
123
|
+
headers.set("User-Agent", USER_AGENT);
|
|
120
124
|
let res;
|
|
121
125
|
try {
|
|
122
126
|
res = await fetch(url, { headers });
|
|
@@ -125,7 +129,7 @@ async function downloadBinary(pathname, opts) {
|
|
|
125
129
|
}
|
|
126
130
|
if (!res.ok) {
|
|
127
131
|
const contentType = res.headers.get("content-type") ?? "";
|
|
128
|
-
let body
|
|
132
|
+
let body;
|
|
129
133
|
if (contentType.includes("application/json")) {
|
|
130
134
|
body = await res.json().catch(() => null);
|
|
131
135
|
} else {
|
|
@@ -157,11 +161,11 @@ var CliError = class extends Error {
|
|
|
157
161
|
};
|
|
158
162
|
var log = {
|
|
159
163
|
info: (msg) => console.log(msg),
|
|
160
|
-
success: (msg) => console.log(
|
|
161
|
-
warn: (msg) => console.warn(
|
|
162
|
-
error: (msg) => console.error(
|
|
163
|
-
step: (msg) => console.log(
|
|
164
|
-
dim: (msg) => console.log(
|
|
164
|
+
success: (msg) => console.log(styleText("green", "\u2714"), msg),
|
|
165
|
+
warn: (msg) => console.warn(styleText("yellow", "\u26A0"), msg),
|
|
166
|
+
error: (msg) => console.error(styleText("red", "\u2716"), msg),
|
|
167
|
+
step: (msg) => console.log(styleText("cyan", "\u2192"), msg),
|
|
168
|
+
dim: (msg) => console.log(styleText("dim", msg))
|
|
165
169
|
};
|
|
166
170
|
function printResult(json, data, human) {
|
|
167
171
|
if (json) {
|
|
@@ -205,6 +209,20 @@ function minutesSince(isoDate) {
|
|
|
205
209
|
const ms = Date.now() - new Date(isoDate).getTime();
|
|
206
210
|
return ms / 6e4;
|
|
207
211
|
}
|
|
212
|
+
async function openUrl(url) {
|
|
213
|
+
const [command, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", '""', url.replace(/&/g, "^&")]] : ["xdg-open", [url]];
|
|
214
|
+
await new Promise((resolve) => {
|
|
215
|
+
const child = spawn(command, args, { stdio: "ignore", detached: true });
|
|
216
|
+
child.once("error", () => {
|
|
217
|
+
log.info(`Open this URL in your browser: ${url}`);
|
|
218
|
+
resolve();
|
|
219
|
+
});
|
|
220
|
+
child.once("spawn", () => {
|
|
221
|
+
child.unref();
|
|
222
|
+
resolve();
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
}
|
|
208
226
|
|
|
209
227
|
// src/commands/build.ts
|
|
210
228
|
async function buildCommand() {
|
|
@@ -214,12 +232,14 @@ async function buildCommand() {
|
|
|
214
232
|
await runCommand(pm, ["run", "build"], { cwd });
|
|
215
233
|
log.success("Build complete.");
|
|
216
234
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
235
|
+
function cervioConfigDir() {
|
|
236
|
+
return process.env.CERVIO_CONFIG_DIR || path.join(os.homedir(), ".cervio");
|
|
237
|
+
}
|
|
238
|
+
var credentialsPath = () => path.join(cervioConfigDir(), "credentials.json");
|
|
239
|
+
var statePath = () => path.join(cervioConfigDir(), "state.json");
|
|
220
240
|
var PROJECT_CONFIG_FILENAME = "cervio.json";
|
|
221
241
|
async function ensureCervioDir() {
|
|
222
|
-
await promises.mkdir(
|
|
242
|
+
await promises.mkdir(cervioConfigDir(), { recursive: true, mode: 448 });
|
|
223
243
|
}
|
|
224
244
|
async function readJsonFile(filePath, fallback) {
|
|
225
245
|
try {
|
|
@@ -239,7 +259,7 @@ function normalizeHost(host) {
|
|
|
239
259
|
return host.trim().replace(/\/+$/, "");
|
|
240
260
|
}
|
|
241
261
|
async function readCredentials() {
|
|
242
|
-
return readJsonFile(
|
|
262
|
+
return readJsonFile(credentialsPath(), {});
|
|
243
263
|
}
|
|
244
264
|
async function getToken(host) {
|
|
245
265
|
const creds = await readCredentials();
|
|
@@ -248,13 +268,13 @@ async function getToken(host) {
|
|
|
248
268
|
async function saveToken(host, token) {
|
|
249
269
|
const creds = await readCredentials();
|
|
250
270
|
creds[normalizeHost(host)] = { token };
|
|
251
|
-
await writeJsonFile(
|
|
271
|
+
await writeJsonFile(credentialsPath(), creds);
|
|
252
272
|
}
|
|
253
273
|
async function readState() {
|
|
254
|
-
return readJsonFile(
|
|
274
|
+
return readJsonFile(statePath(), {});
|
|
255
275
|
}
|
|
256
276
|
async function writeState(state) {
|
|
257
|
-
await writeJsonFile(
|
|
277
|
+
await writeJsonFile(statePath(), state);
|
|
258
278
|
}
|
|
259
279
|
async function getLastHost() {
|
|
260
280
|
const state = await readState();
|
|
@@ -411,8 +431,8 @@ async function downloadCommand(opts) {
|
|
|
411
431
|
const pluginId = await resolvePluginId(ctx, projectConfig.plugin_key);
|
|
412
432
|
let channel = "release";
|
|
413
433
|
let versionLabel = null;
|
|
414
|
-
let contentSha256
|
|
415
|
-
let artifactSha256
|
|
434
|
+
let contentSha256;
|
|
435
|
+
let artifactSha256;
|
|
416
436
|
let bytes;
|
|
417
437
|
let defaultFileName;
|
|
418
438
|
try {
|
|
@@ -481,12 +501,9 @@ async function downloadCommand(opts) {
|
|
|
481
501
|
if (data.artifact_sha256) log.info(` artifact_sha256: ${data.artifact_sha256}`);
|
|
482
502
|
});
|
|
483
503
|
}
|
|
484
|
-
|
|
485
|
-
// src/commands/init.ts
|
|
486
504
|
async function initCommand(name) {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
await runCommand("npx", ["create-cervio-plugin", ...args]);
|
|
505
|
+
log.step("Scaffolding a new Cervio plugin...");
|
|
506
|
+
await createPlugin(name ? [name] : []);
|
|
490
507
|
}
|
|
491
508
|
async function loginCommand(opts) {
|
|
492
509
|
if (!opts.host) {
|
|
@@ -513,6 +530,8 @@ async function loginCommand(opts) {
|
|
|
513
530
|
log.info(` org: ${me.organization_name ?? me.organization_id}`);
|
|
514
531
|
log.info(` auth: ${me.auth_method}`);
|
|
515
532
|
}
|
|
533
|
+
|
|
534
|
+
// src/commands/open.ts
|
|
516
535
|
async function openCommand(opts) {
|
|
517
536
|
const ctx = await resolveContext({ host: opts.host });
|
|
518
537
|
const projectConfig = requireProjectConfig(ctx);
|
|
@@ -521,7 +540,7 @@ async function openCommand(opts) {
|
|
|
521
540
|
}
|
|
522
541
|
const url = `${ctx.host}/r/${projectConfig.route_slug}`;
|
|
523
542
|
log.step(`Opening ${url}`);
|
|
524
|
-
await
|
|
543
|
+
await openUrl(url);
|
|
525
544
|
}
|
|
526
545
|
async function packForPublish(dir = process.cwd()) {
|
|
527
546
|
const result = await packPlugin({ dir });
|
|
@@ -545,6 +564,15 @@ async function packCommand(opts) {
|
|
|
545
564
|
log.success(`Packed ${data.pluginKey} (${formatBytes(data.sizeBytes)})`);
|
|
546
565
|
log.info(` content_sha256: ${data.contentSha256}`);
|
|
547
566
|
log.info(` output: ${data.outputPath}`);
|
|
567
|
+
if (data.sizeBytes >= PLUGIN_ARTIFACT_SOFT_STRONG_WARN_BYTES) {
|
|
568
|
+
log.warn(
|
|
569
|
+
`Artifact is large (${formatBytes(data.sizeBytes)} \u2265 3 MB). Cold open will be slow; trim the ZIP (target < 1 MB).`
|
|
570
|
+
);
|
|
571
|
+
} else if (data.sizeBytes >= PLUGIN_ARTIFACT_SOFT_WARN_BYTES) {
|
|
572
|
+
log.warn(
|
|
573
|
+
`Artifact is above the soft budget (${formatBytes(data.sizeBytes)} \u2265 1 MB). Prefer a smaller bundle for faster opens.`
|
|
574
|
+
);
|
|
575
|
+
}
|
|
548
576
|
});
|
|
549
577
|
}
|
|
550
578
|
var DEFAULT_DEV_CONFLICT_MINUTES = 30;
|
|
@@ -636,10 +664,12 @@ async function pushCommand(opts) {
|
|
|
636
664
|
}
|
|
637
665
|
}
|
|
638
666
|
}
|
|
639
|
-
let
|
|
667
|
+
let zipPath;
|
|
640
668
|
let zipFileName;
|
|
641
669
|
if (opts.file) {
|
|
642
670
|
const filePath = path.resolve(process.cwd(), opts.file);
|
|
671
|
+
zipPath = filePath;
|
|
672
|
+
let zipBuffer;
|
|
643
673
|
try {
|
|
644
674
|
zipBuffer = await promises.readFile(filePath);
|
|
645
675
|
} catch (err) {
|
|
@@ -660,11 +690,11 @@ async function pushCommand(opts) {
|
|
|
660
690
|
log.info(`Using existing ZIP ${filePath} (content_sha256=${validated.value.contentSha256})`);
|
|
661
691
|
} else {
|
|
662
692
|
const packed = await packForPublish(process.cwd());
|
|
663
|
-
|
|
693
|
+
zipPath = packed.outputPath;
|
|
664
694
|
zipFileName = `${packed.pluginKey}.zip`;
|
|
665
695
|
}
|
|
666
696
|
const form = new FormData();
|
|
667
|
-
form.set("file",
|
|
697
|
+
form.set("file", await openAsBlob(zipPath, { type: "application/zip" }), zipFileName);
|
|
668
698
|
if (opts.changelog) form.set("changelog", opts.changelog);
|
|
669
699
|
form.set("set_current", String(opts.activate !== false));
|
|
670
700
|
if (opts.dev) form.set("channel", "dev");
|
|
@@ -773,7 +803,6 @@ async function routeSetCommand(opts) {
|
|
|
773
803
|
requireToken(ctx);
|
|
774
804
|
const projectConfig = requireProjectConfig(ctx);
|
|
775
805
|
const pluginId = await resolvePluginId(ctx, projectConfig.plugin_key);
|
|
776
|
-
const cache = parseOnOff(opts.cache, "--cache");
|
|
777
806
|
const devChannel = parseOnOff(opts.devChannel, "--dev-channel");
|
|
778
807
|
let slug = opts.slug;
|
|
779
808
|
if (!slug) {
|
|
@@ -785,12 +814,11 @@ async function routeSetCommand(opts) {
|
|
|
785
814
|
}
|
|
786
815
|
const { route_config } = await ctx.client.setRouteConfig(pluginId, {
|
|
787
816
|
route_slug: slug,
|
|
788
|
-
artifact_cache_enabled: cache,
|
|
789
817
|
dev_channel_enabled: devChannel
|
|
790
818
|
});
|
|
791
819
|
printResult(!!opts.json, { host: ctx.host, plugin_key: projectConfig.plugin_key, route_config }, (data) => {
|
|
792
820
|
const rc = data.route_config;
|
|
793
|
-
const extras = rc ? ` (
|
|
821
|
+
const extras = rc ? ` (dev_channel=${rc.dev_channel_enabled ? "on" : "off"})` : "";
|
|
794
822
|
log.success(
|
|
795
823
|
`Updated route config for ${data.plugin_key} on ${data.host}: /r/${rc?.route_slug}` + extras
|
|
796
824
|
);
|
|
@@ -953,14 +981,17 @@ async function watchCommand(opts) {
|
|
|
953
981
|
}
|
|
954
982
|
};
|
|
955
983
|
log.info(`Watching ${srcDir} for changes (Ctrl+C to stop)...`);
|
|
956
|
-
|
|
957
|
-
watcher
|
|
958
|
-
|
|
984
|
+
let debounce;
|
|
985
|
+
const watcher = watch(srcDir, { recursive: true }, () => {
|
|
986
|
+
clearTimeout(debounce);
|
|
987
|
+
debounce = setTimeout(() => void runCycle(), 100);
|
|
959
988
|
});
|
|
960
989
|
await runCycle();
|
|
961
990
|
await new Promise((resolve) => {
|
|
962
991
|
process.on("SIGINT", () => {
|
|
963
|
-
|
|
992
|
+
clearTimeout(debounce);
|
|
993
|
+
watcher.close();
|
|
994
|
+
resolve();
|
|
964
995
|
});
|
|
965
996
|
});
|
|
966
997
|
}
|
|
@@ -979,7 +1010,6 @@ async function whoamiCommand(opts) {
|
|
|
979
1010
|
}
|
|
980
1011
|
|
|
981
1012
|
// src/index.ts
|
|
982
|
-
var CLI_VERSION = createRequire(import.meta.url)("../package.json").version;
|
|
983
1013
|
function action(fn) {
|
|
984
1014
|
return async (...args) => {
|
|
985
1015
|
try {
|
|
@@ -999,7 +1029,7 @@ function action(fn) {
|
|
|
999
1029
|
};
|
|
1000
1030
|
}
|
|
1001
1031
|
var program = new Command();
|
|
1002
|
-
program.name("cervio").description("Cervio
|
|
1032
|
+
program.name("cervio").description("Cervio plugin developer CLI").version(CLI_VERSION);
|
|
1003
1033
|
program.command("login").description("Authenticate with a Cervio host and save the token").option("--host <url>", "Cervio host, e.g. https://app.example.com").option("--token <token>", "Personal access token (prompted if omitted)").action(action(loginCommand));
|
|
1004
1034
|
program.command("whoami").description("Print the current host and identity").option("--host <url>", "Override the resolved host").option("--json", "Output JSON").action(action(whoamiCommand));
|
|
1005
1035
|
program.command("build").description("Run the project build script (pnpm/npm run build)").action(action(buildCommand));
|
|
@@ -1014,11 +1044,9 @@ program.command("versions").description("List released versions for the current
|
|
|
1014
1044
|
program.command("download").description("Download a release or dev-channel ZIP from the host").option("--host <url>", "Override the resolved host").option("--release <semver>", "Download a specific release version (default: current)").option("--dev", "Download the dev-channel artifact instead of a release").option("-o, --output <path>", "Output path (default: .cervio/out/<plugin_key>-\u2026.zip)").option("--json", "Output JSON").action(action(downloadCommand));
|
|
1015
1045
|
program.command("rollback <version>").description("Activate a previously released version").option("--host <url>", "Override the resolved host").option("--json", "Output JSON").action(action(rollbackCommand));
|
|
1016
1046
|
var route = program.command("route").description("Manage the plugin route configuration");
|
|
1017
|
-
route.command("set").description("Update the route slug
|
|
1047
|
+
route.command("set").description("Update the route slug and/or the dev-channel setting").option("--host <url>", "Override the resolved host").option("--slug <slug>", "New route slug").option("--dev-channel <onoff>", 'Enable/disable the plugin dev channel ("on" or "off")').option("--json", "Output JSON").action(action(routeSetCommand));
|
|
1018
1048
|
program.command("open").description("Open the plugin route in a browser").option("--host <url>", "Override the resolved host").action(action(openCommand));
|
|
1019
1049
|
program.parseAsync(process.argv).catch((err) => {
|
|
1020
1050
|
log.error(err instanceof Error ? err.message : String(err));
|
|
1021
1051
|
process.exitCode = 1;
|
|
1022
1052
|
});
|
|
1023
|
-
//# sourceMappingURL=cli.js.map
|
|
1024
|
-
//# sourceMappingURL=cli.js.map
|
package/package.json
CHANGED
|
@@ -1,44 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cervio/cli",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "Developer CLI for Cervio
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Developer CLI for Cervio plugins: login, validate, pack, push and manage releases.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"cervio",
|
|
7
|
+
"cli",
|
|
8
|
+
"plugin"
|
|
9
|
+
],
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"homepage": "https://github.com/cervio-app/cervio-devkit/tree/main/packages/cli#readme",
|
|
12
|
+
"bugs": "https://github.com/cervio-app/cervio-devkit/issues",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/cervio-app/cervio-devkit.git",
|
|
16
|
+
"directory": "packages/cli"
|
|
17
|
+
},
|
|
5
18
|
"type": "module",
|
|
6
19
|
"bin": {
|
|
7
20
|
"cervio": "./dist/cli.js"
|
|
8
21
|
},
|
|
9
22
|
"files": [
|
|
10
23
|
"dist",
|
|
11
|
-
"README.md"
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE"
|
|
12
26
|
],
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=26"
|
|
29
|
+
},
|
|
13
30
|
"dependencies": {
|
|
14
|
-
"
|
|
15
|
-
"chokidar": "^4.0.3",
|
|
16
|
-
"commander": "^14.0.3",
|
|
17
|
-
"open": "^10.2.0",
|
|
31
|
+
"commander": "^15.0.0",
|
|
18
32
|
"prompts": "^2.4.2",
|
|
19
|
-
"@cervio/plugin
|
|
33
|
+
"@cervio/create-plugin": "^1.1.0",
|
|
34
|
+
"@cervio/plugin-core": "^1.0.1"
|
|
20
35
|
},
|
|
21
36
|
"devDependencies": {
|
|
22
|
-
"@types/node": "^
|
|
37
|
+
"@types/node": "^26.0.0",
|
|
23
38
|
"@types/prompts": "^2.4.9",
|
|
24
|
-
"tsup": "^
|
|
25
|
-
"typescript": "^5.8.3"
|
|
39
|
+
"tsup": "^9.0.0",
|
|
40
|
+
"typescript": "^5.8.3",
|
|
41
|
+
"vitest": "^5.0.5"
|
|
26
42
|
},
|
|
27
43
|
"publishConfig": {
|
|
28
44
|
"access": "public"
|
|
29
45
|
},
|
|
30
|
-
"engines": {
|
|
31
|
-
"node": ">=18.17"
|
|
32
|
-
},
|
|
33
|
-
"license": "UNLICENSED",
|
|
34
|
-
"keywords": [
|
|
35
|
-
"cervio",
|
|
36
|
-
"cli",
|
|
37
|
-
"plugin"
|
|
38
|
-
],
|
|
39
46
|
"scripts": {
|
|
40
47
|
"build": "tsup --config tsup.config.ts",
|
|
41
48
|
"dev": "tsup --config tsup.config.ts --watch",
|
|
42
|
-
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
49
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
50
|
+
"test": "vitest run"
|
|
43
51
|
}
|
|
44
52
|
}
|
package/dist/cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api.ts","../src/util.ts","../src/commands/build.ts","../src/config.ts","../src/context.ts","../src/commands/doctor.ts","../src/commands/download.ts","../src/commands/init.ts","../src/commands/login.ts","../src/commands/open.ts","../src/commands/pack.ts","../src/commands/push.ts","../src/commands/rollback.ts","../src/commands/route.ts","../src/commands/status.ts","../src/commands/validate.ts","../src/commands/versions.ts","../src/commands/watch.ts","../src/commands/whoami.ts","../src/index.ts"],"names":["path","fs","prompts","route_config","validatePluginDir"],"mappings":"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","file":"cli.js","sourcesContent":["/**\n * Thin fetch-based client for the Cervio REST API (`/api/v1/**`).\n *\n * Shapes here are matched against the actual `app/api/v1/**` route handlers\n * (not guessed) as of this writing. See packages/cli/README.md \"PAT scopes\"\n * for the token scopes each call needs.\n */\n\nexport class ApiError extends Error {\n status: number\n code?: string\n body?: unknown\n\n constructor(status: number, message: string, code?: string, body?: unknown) {\n super(message)\n this.name = 'ApiError'\n this.status = status\n this.code = code\n this.body = body\n }\n}\n\nexport type MeResponse = {\n user_id: string\n organization_id: string\n email: string | null\n auth_method: string\n /** Not currently returned by GET /api/v1/me; kept optional for forward-compat. */\n organization_name?: string\n}\n\nexport type PluginType = 'task' | 'form' | 'task_form' | 'route' | 'policy' | 'server'\n\nexport type PluginSummary = {\n id: string\n plugin_key: string\n plugin_name: string | null\n plugin_description: string | null\n plugin_type: PluginType\n is_active: boolean\n is_builtin: boolean\n admin_path: string | null\n}\n\n/** installed_plugins row as returned by GET /api/v1/admin/plugins/{pluginId}. */\nexport type PluginDetail = {\n id: string\n plugin_key: string\n plugin_name: string | null\n plugin_description: string | null\n plugin_type: PluginType\n is_active: boolean\n is_builtin: boolean\n admin_path: string | null\n source_type: string | null\n current_version_id: string | null\n last_uploaded_at: string | null\n required_connection_capabilities: string[]\n declared_entities: unknown[]\n declared_cervio_apis: unknown[]\n declared_settings_schema: unknown[]\n}\n\nexport type PluginVersionSummary = {\n id: string\n plugin_id: string\n version: string\n changelog: string | null\n artifact_path: string\n artifact_entry_path?: string | null\n artifact_sha256: string\n content_sha256?: string | null\n artifact_size_bytes: number\n created_at: string\n}\n\nexport type DevChannelInfo = {\n content_sha256: string\n artifact_sha256: string\n artifact_size_bytes: number\n updated_at: string\n /** User id; only present from GET .../dev-channel (not from the upload response). */\n updated_by?: string | null\n updated_by_email?: string | null\n}\n\nexport type RouteConfig = {\n id: string\n plugin_id: string\n route_slug: string\n menu_section_id: string | null\n menu_item_id: string | null\n menu_label: string | null\n menu_icon: string | null\n artifact_cache_enabled: boolean\n runtime_settings: Record<string, unknown>\n dev_channel_enabled: boolean\n}\n\nexport type UploadReleaseResult = {\n channel: 'release'\n created: boolean\n reason: string | null\n plugin: { id: string; plugin_key: string; plugin_name: string; plugin_type: PluginType }\n version: PluginVersionSummary\n}\n\nexport type UploadDevResult = {\n channel: 'dev'\n plugin: { id: string; plugin_key: string; plugin_name: string; plugin_type: PluginType }\n dev_channel: {\n content_sha256: string\n artifact_sha256: string\n artifact_size_bytes: number\n updated_at: string\n }\n}\n\nexport type UploadResult = UploadReleaseResult | UploadDevResult\n\nexport type ApiClient = ReturnType<typeof createApiClient>\n\nexport function createApiClient(opts: { host: string; token?: string }) {\n const baseUrl = opts.host.replace(/\\/+$/, '')\n const token = opts.token\n\n async function request<T = unknown>(pathname: string, init: RequestInit = {}): Promise<T> {\n const url = pathname.startsWith('http') ? pathname : `${baseUrl}${pathname}`\n const headers = new Headers(init.headers)\n if (token) headers.set('Authorization', `Bearer ${token}`)\n if (!headers.has('Accept')) headers.set('Accept', 'application/json')\n\n let res: Response\n try {\n res = await fetch(url, { ...init, headers })\n } catch (err) {\n throw new ApiError(0, `Could not reach ${url}: ${(err as Error).message}`)\n }\n\n const contentType = res.headers.get('content-type') ?? ''\n let body: unknown = null\n if (contentType.includes('application/json')) {\n body = await res.json().catch(() => null)\n } else {\n const text = await res.text().catch(() => '')\n body = text || null\n }\n\n if (!res.ok) {\n const message =\n body && typeof body === 'object' && typeof (body as Record<string, unknown>).message === 'string'\n ? (body as Record<string, string>).message\n : `Request failed with status ${res.status} (${pathname})`\n const code =\n body && typeof body === 'object' && typeof (body as Record<string, unknown>).error === 'string'\n ? (body as Record<string, string>).error\n : undefined\n throw new ApiError(res.status, message, code, body)\n }\n\n return body as T\n }\n\n return {\n baseUrl,\n token,\n request,\n\n /** No scope requirement. */\n getMe: () => request<MeResponse>('/api/v1/me'),\n\n /** Requires PAT scope `plugin:read` (legacy unscoped PATs are rejected). */\n listEntities: (search?: string) =>\n request<{ entities: Array<{ id: string; name: string; label: string }> }>(\n `/api/v1/entities${search ? `?search=${encodeURIComponent(search)}` : ''}`,\n ),\n\n /** Requires PAT scope `plugin:read`. */\n listPlugins: () => request<{ plugins: PluginSummary[] }>('/api/v1/admin/plugins'),\n\n /** Requires PAT scope `plugin:read`. */\n getPlugin: (pluginId: string) =>\n request<{ plugin: PluginDetail; current_version: PluginVersionSummary | null }>(\n `/api/v1/admin/plugins/${pluginId}`,\n ),\n\n /** Requires PAT scope `plugin:read`. */\n getDevChannel: (pluginId: string) =>\n request<{ dev_channel: DevChannelInfo | null }>(`/api/v1/admin/plugins/${pluginId}/dev-channel`),\n\n /** Requires PAT scope `plugin:read`. */\n listVersions: (pluginId: string) =>\n request<{ versions: PluginVersionSummary[] }>(`/api/v1/admin/plugins/${pluginId}/versions`),\n\n /** Requires PAT scope `plugin:push`. `versionId` is the version row's UUID (`id`), not the semver label. */\n activateVersion: (pluginId: string, versionId: string) =>\n request<{ ok: true; plugin_id: string; current_version_id: string }>(\n `/api/v1/admin/plugins/${pluginId}/versions/${versionId}/activate`,\n { method: 'POST' },\n ),\n\n /** Requires PAT scope `plugin:read`. */\n getRouteConfig: (pluginId: string) =>\n request<{ route_config: RouteConfig | null }>(`/api/v1/admin/plugins/${pluginId}/route-config`),\n\n /** Requires PAT scope `plugin:push`. `route_slug` is required by the route on every PUT (full upsert, not a patch). */\n setRouteConfig: (\n pluginId: string,\n data: { route_slug: string; artifact_cache_enabled?: boolean; dev_channel_enabled?: boolean },\n ) =>\n request<{ route_config: RouteConfig | null }>(`/api/v1/admin/plugins/${pluginId}/route-config`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n }),\n\n /**\n * Matches app/api/v1/admin/plugins/upload/route.ts exactly. Requires PAT\n * scope `plugin:push`. multipart/form-data fields:\n * - `file` (required): the packed .zip, content-type application/zip.\n * - `plugin_id` (optional UUID): omitted by this CLI - the backend\n * resolves/creates the plugin by the `plugin_key` embedded in the manifest.\n * - `changelog`, `plugin_name`, `plugin_description`, `plugin_type` (optional).\n * - `set_current` (\"true\"/\"false\"): whether to activate the uploaded\n * release version. Ignored for `channel=dev`.\n * - `channel` (\"release\" default, or \"dev\"): dev-channel pushes require\n * the plugin to already exist (a prior release push) - the route\n * returns `plugin_not_found` otherwise. Response shape depends on\n * the channel (see `UploadReleaseResult` / `UploadDevResult`).\n */\n uploadPlugin: (form: FormData) =>\n request<UploadResult>('/api/v1/admin/plugins/upload', { method: 'POST', body: form }),\n\n /**\n * Streams a release ZIP. Requires PAT scope `plugin:read`.\n * `versionId` is the version row UUID (`id`), not the semver label.\n */\n downloadVersionArtifact: (pluginId: string, versionId: string) =>\n downloadBinary(\n `/api/v1/admin/plugins/${pluginId}/versions/${versionId}/artifact`,\n { host: baseUrl, token },\n ),\n\n /** Streams the current dev-channel ZIP. Requires PAT scope `plugin:read`. */\n downloadDevArtifact: (pluginId: string) =>\n downloadBinary(`/api/v1/admin/plugins/${pluginId}/dev-channel/artifact`, { host: baseUrl, token }),\n }\n}\n\nexport type ArtifactDownloadResult = {\n bytes: Buffer\n fileName: string | null\n versionLabel: string | null\n contentSha256: string | null\n artifactSha256: string | null\n}\n\nasync function downloadBinary(\n pathname: string,\n opts: { host: string; token?: string },\n): Promise<ArtifactDownloadResult> {\n const url = pathname.startsWith('http') ? pathname : `${opts.host}${pathname}`\n const headers = new Headers({ Accept: 'application/zip, application/octet-stream, */*' })\n if (opts.token) headers.set('Authorization', `Bearer ${opts.token}`)\n\n let res: Response\n try {\n res = await fetch(url, { headers })\n } catch (err) {\n throw new ApiError(0, `Could not reach ${url}: ${(err as Error).message}`)\n }\n\n if (!res.ok) {\n const contentType = res.headers.get('content-type') ?? ''\n let body: unknown = null\n if (contentType.includes('application/json')) {\n body = await res.json().catch(() => null)\n } else {\n body = await res.text().catch(() => '')\n }\n const message =\n body && typeof body === 'object' && typeof (body as Record<string, unknown>).message === 'string'\n ? (body as Record<string, string>).message\n : `Request failed with status ${res.status} (${pathname})`\n const code =\n body && typeof body === 'object' && typeof (body as Record<string, unknown>).error === 'string'\n ? (body as Record<string, string>).error\n : undefined\n throw new ApiError(res.status, message, code, body)\n }\n\n const arrayBuffer = await res.arrayBuffer()\n const disposition = res.headers.get('content-disposition') ?? ''\n const fileNameMatch = /filename=\"([^\"]+)\"/i.exec(disposition)\n return {\n bytes: Buffer.from(arrayBuffer),\n fileName: fileNameMatch?.[1] ?? null,\n versionLabel: res.headers.get('x-plugin-version'),\n contentSha256: res.headers.get('x-content-sha256'),\n artifactSha256: res.headers.get('x-artifact-sha256'),\n }\n}\n","import { spawn } from 'node:child_process'\nimport chalk from 'chalk'\n\nexport class CliError extends Error {\n /** Process exit code to use when this error escapes to the top-level handler. */\n exitCode: number\n constructor(message: string, exitCode = 1) {\n super(message)\n this.name = 'CliError'\n this.exitCode = exitCode\n }\n}\n\nexport const log = {\n info: (msg: string) => console.log(msg),\n success: (msg: string) => console.log(chalk.green('✔'), msg),\n warn: (msg: string) => console.warn(chalk.yellow('⚠'), msg),\n error: (msg: string) => console.error(chalk.red('✖'), msg),\n step: (msg: string) => console.log(chalk.cyan('→'), msg),\n dim: (msg: string) => console.log(chalk.dim(msg)),\n}\n\n/** Print either a JSON payload (machine-readable, one object, stdout only) or run a human renderer. */\nexport function printResult<T>(json: boolean, data: T, human: (data: T) => void): void {\n if (json) {\n console.log(JSON.stringify(data, null, 2))\n } else {\n human(data)\n }\n}\n\nexport function runCommand(\n command: string,\n args: string[],\n opts: { cwd?: string } = {},\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n cwd: opts.cwd ?? process.cwd(),\n stdio: 'inherit',\n shell: process.platform === 'win32',\n })\n child.on('error', (err) => reject(new CliError(`Failed to run \"${command}\": ${err.message}`)))\n child.on('exit', (code) => {\n if (code === 0) resolve()\n else reject(new CliError(`\"${command} ${args.join(' ')}\" exited with code ${code}`, code ?? 1))\n })\n })\n}\n\n/** Detect whether a `pnpm-lock.yaml` is present in cwd, to prefer pnpm over npm for `build`/`init`. */\nexport async function detectPackageManager(cwd: string): Promise<'pnpm' | 'npm'> {\n const { existsSync } = await import('node:fs')\n const path = await import('node:path')\n if (existsSync(path.join(cwd, 'pnpm-lock.yaml'))) return 'pnpm'\n return 'npm'\n}\n\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n const units = ['KB', 'MB', 'GB']\n let value = bytes / 1024\n let unitIndex = 0\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024\n unitIndex += 1\n }\n return `${value.toFixed(1)} ${units[unitIndex]}`\n}\n\nexport function minutesSince(isoDate: string): number {\n const ms = Date.now() - new Date(isoDate).getTime()\n return ms / 60_000\n}\n","import { detectPackageManager, log, runCommand } from '../util.js'\n\nexport async function buildCommand(): Promise<void> {\n const cwd = process.cwd()\n const pm = await detectPackageManager(cwd)\n log.step(`Running \"${pm} run build\" in ${cwd}`)\n await runCommand(pm, ['run', 'build'], { cwd })\n log.success('Build complete.')\n}\n","import { promises as fs } from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\n\nexport type Credentials = Record<string, { token: string }>\n\nexport type CliState = {\n lastHost?: string\n}\n\nexport type ProjectConfig = {\n host?: string\n plugin_key: string\n route_slug?: string\n dev_conflict_minutes?: number\n}\n\nconst CERVIO_DIR = path.join(os.homedir(), '.cervio')\nconst CREDENTIALS_PATH = path.join(CERVIO_DIR, 'credentials.json')\nconst STATE_PATH = path.join(CERVIO_DIR, 'state.json')\nexport const PROJECT_CONFIG_FILENAME = 'cervio.json'\n\nasync function ensureCervioDir(): Promise<void> {\n await fs.mkdir(CERVIO_DIR, { recursive: true })\n}\n\nasync function readJsonFile<T>(filePath: string, fallback: T): Promise<T> {\n try {\n const raw = await fs.readFile(filePath, 'utf8')\n return JSON.parse(raw) as T\n } catch (err) {\n if ((err as NodeJS.ErrnoException)?.code === 'ENOENT') return fallback\n throw err\n }\n}\n\nasync function writeJsonFile(filePath: string, data: unknown): Promise<void> {\n await ensureCervioDir()\n await fs.writeFile(filePath, `${JSON.stringify(data, null, 2)}\\n`, { mode: 0o600 })\n}\n\n/** Normalize a host URL for use as a credentials/state key (strip trailing slashes). */\nexport function normalizeHost(host: string): string {\n return host.trim().replace(/\\/+$/, '')\n}\n\nexport async function readCredentials(): Promise<Credentials> {\n return readJsonFile<Credentials>(CREDENTIALS_PATH, {})\n}\n\nexport async function getToken(host: string): Promise<string | undefined> {\n const creds = await readCredentials()\n return creds[normalizeHost(host)]?.token\n}\n\nexport async function saveToken(host: string, token: string): Promise<void> {\n const creds = await readCredentials()\n creds[normalizeHost(host)] = { token }\n await writeJsonFile(CREDENTIALS_PATH, creds)\n}\n\nexport async function removeToken(host: string): Promise<void> {\n const creds = await readCredentials()\n delete creds[normalizeHost(host)]\n await writeJsonFile(CREDENTIALS_PATH, creds)\n}\n\nexport async function readState(): Promise<CliState> {\n return readJsonFile<CliState>(STATE_PATH, {})\n}\n\nexport async function writeState(state: CliState): Promise<void> {\n await writeJsonFile(STATE_PATH, state)\n}\n\nexport async function getLastHost(): Promise<string | undefined> {\n const state = await readState()\n return state.lastHost\n}\n\nexport async function setLastHost(host: string): Promise<void> {\n const state = await readState()\n state.lastHost = normalizeHost(host)\n await writeState(state)\n}\n\nexport function projectConfigPath(cwd = process.cwd()): string {\n return path.join(cwd, PROJECT_CONFIG_FILENAME)\n}\n\nexport async function readProjectConfig(cwd = process.cwd()): Promise<ProjectConfig | null> {\n try {\n const raw = await fs.readFile(projectConfigPath(cwd), 'utf8')\n return JSON.parse(raw) as ProjectConfig\n } catch (err) {\n if ((err as NodeJS.ErrnoException)?.code === 'ENOENT') return null\n throw err\n }\n}\n\nexport async function writeProjectConfig(\n config: ProjectConfig,\n cwd = process.cwd(),\n): Promise<void> {\n await fs.writeFile(projectConfigPath(cwd), `${JSON.stringify(config, null, 2)}\\n`)\n}\n\n/**\n * Resolve the target host from (in priority order): explicit CLI flag,\n * `CERVIO_URL` env var, then `cervio.json` in the cwd.\n */\nexport function resolveHost(opts: {\n cliHost?: string\n projectConfig?: ProjectConfig | null\n}): string | undefined {\n const host = opts.cliHost || process.env.CERVIO_URL || opts.projectConfig?.host\n return host ? normalizeHost(host) : undefined\n}\n\n/**\n * Resolve the bearer token for a host: `CERVIO_TOKEN` env var wins, otherwise\n * fall back to the stored credential for that host.\n */\nexport async function resolveToken(host: string): Promise<string | undefined> {\n if (process.env.CERVIO_TOKEN) return process.env.CERVIO_TOKEN\n return getToken(host)\n}\n\nexport { CERVIO_DIR, CREDENTIALS_PATH, STATE_PATH }\n","import { createApiClient, type ApiClient } from './api.js'\nimport { type ProjectConfig, readProjectConfig, resolveHost, resolveToken } from './config.js'\nimport { CliError } from './util.js'\n\nexport type ResolvedContext = {\n host: string\n token?: string\n client: ApiClient\n projectConfig: ProjectConfig | null\n}\n\n/** Resolve host + token + project config, in priority order: CLI flag > CERVIO_URL/CERVIO_TOKEN > cervio.json. */\nexport async function resolveContext(opts: { host?: string } = {}): Promise<ResolvedContext> {\n const projectConfig = await readProjectConfig()\n const host = resolveHost({ cliHost: opts.host, projectConfig })\n if (!host) {\n throw new CliError(\n 'No host configured. Pass --host <url>, set CERVIO_URL, or add \"host\" to cervio.json (run \"cervio login\" first).',\n )\n }\n const token = await resolveToken(host)\n const client = createApiClient({ host, token })\n return { host, token, client, projectConfig }\n}\n\nexport function requireToken(ctx: ResolvedContext): string {\n if (!ctx.token) {\n throw new CliError(\n `Not logged in to ${ctx.host}. Run \"cervio login --host ${ctx.host}\" or set CERVIO_TOKEN.`,\n )\n }\n return ctx.token\n}\n\nexport function requireProjectConfig(ctx: ResolvedContext): ProjectConfig {\n if (!ctx.projectConfig) {\n throw new CliError('No cervio.json found in the current directory. Run \"cervio init\" first.')\n }\n return ctx.projectConfig\n}\n\n/** Resolve a plugin's UUID from its plugin_key via GET /api/v1/admin/plugins. */\nexport async function resolvePluginId(ctx: ResolvedContext, pluginKey: string): Promise<string> {\n const id = await tryResolvePluginId(ctx, pluginKey)\n if (!id) {\n throw new CliError(\n `No plugin with plugin_key \"${pluginKey}\" found on ${ctx.host}. Push it once with \"cervio push\" first.`,\n )\n }\n return id\n}\n\n/** Same as {@link resolvePluginId} but returns null instead of throwing when not found. */\nexport async function tryResolvePluginId(\n ctx: ResolvedContext,\n pluginKey: string,\n): Promise<string | null> {\n const { plugins } = await ctx.client.listPlugins()\n return plugins.find((p) => p.plugin_key === pluginKey)?.id ?? null\n}\n","import { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport { parseManifestObject, validatePluginDir } from '@cervio/plugin-core'\nimport { ApiError } from '../api.js'\nimport { resolveContext } from '../context.js'\nimport { log, printResult } from '../util.js'\n\ntype CheckResult = { name: string; ok: boolean; detail: string }\n\nexport async function doctorCommand(opts: { host?: string; json?: boolean }): Promise<void> {\n const checks: CheckResult[] = []\n const cwd = process.cwd()\n\n let ctx\n try {\n ctx = await resolveContext({ host: opts.host })\n checks.push({ name: 'host_configured', ok: true, detail: ctx.host })\n } catch (err) {\n checks.push({ name: 'host_configured', ok: false, detail: err instanceof Error ? err.message : String(err) })\n return report(checks, opts.json)\n }\n\n if (!ctx.token) {\n checks.push({ name: 'token_present', ok: false, detail: 'No token found (env CERVIO_TOKEN or ~/.cervio/credentials.json).' })\n } else {\n checks.push({ name: 'token_present', ok: true, detail: 'found' })\n }\n\n let entities: Array<{ name: string; label: string }> = []\n try {\n const me = await ctx.client.getMe()\n checks.push({ name: 'host_reachable', ok: true, detail: `reachable, auth via ${me.auth_method}` })\n checks.push({ name: 'token_valid', ok: true, detail: me.email ?? me.user_id })\n\n const entitiesRes = await ctx.client.listEntities()\n entities = entitiesRes.entities\n checks.push({ name: 'entities_endpoint', ok: true, detail: `${entities.length} entities visible` })\n } catch (err) {\n if (err instanceof ApiError && (err.status === 401 || err.status === 403)) {\n checks.push({ name: 'token_valid', ok: false, detail: err.message })\n } else {\n checks.push({ name: 'host_reachable', ok: false, detail: err instanceof Error ? err.message : String(err) })\n }\n }\n\n const manifestPath = path.join(cwd, 'manifest.json')\n let declaredEntities: string[] = []\n try {\n const raw = JSON.parse(await fs.readFile(manifestPath, 'utf8')) as Record<string, unknown>\n const parsed = parseManifestObject(raw)\n if (parsed.ok) {\n declaredEntities = parsed.value.entities.map((e) => e.name)\n checks.push({ name: 'manifest_valid', ok: true, detail: `plugin_key=${parsed.value.pluginKey}` })\n } else {\n checks.push({ name: 'manifest_valid', ok: false, detail: parsed.error })\n }\n } catch (err) {\n checks.push({ name: 'manifest_valid', ok: false, detail: `manifest.json not readable: ${err instanceof Error ? err.message : String(err)}` })\n }\n\n const packResult = await validatePluginDir(cwd)\n checks.push(\n packResult.ok\n ? { name: 'build_valid', ok: true, detail: `content_sha256=${packResult.value.contentSha256}` }\n : { name: 'build_valid', ok: false, detail: packResult.error },\n )\n\n if (declaredEntities.length) {\n const known = new Set(entities.map((e) => e.name))\n const missing = declaredEntities.filter((name) => !known.has(name))\n checks.push(\n missing.length === 0\n ? { name: 'entities_exist', ok: true, detail: declaredEntities.join(', ') }\n : { name: 'entities_exist', ok: false, detail: `missing: ${missing.join(', ')}` },\n )\n }\n\n report(checks, opts.json)\n}\n\nfunction report(checks: CheckResult[], json?: boolean): void {\n const ok = checks.every((c) => c.ok)\n printResult(!!json, { ok, checks }, () => {\n for (const check of checks) {\n const marker = check.ok ? '✔' : '✖'\n log.info(`${marker} ${check.name}: ${check.detail}`)\n }\n if (ok) log.success('All checks passed.')\n else log.error('Some checks failed.')\n })\n if (!ok) {\n process.exitCode = 1\n }\n}\n","import { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport { ApiError } from '../api.js'\nimport { requireProjectConfig, requireToken, resolveContext, resolvePluginId } from '../context.js'\nimport { CliError, log, printResult } from '../util.js'\n\nexport type DownloadOptions = {\n host?: string\n /** Semver label of a release to download (CLI flag: `--release`). */\n release?: string\n /** @deprecated Prefer `release` - kept so older callers still work if they pass `version`. */\n version?: string\n dev?: boolean\n output?: string\n json?: boolean\n}\n\n/**\n * Download a release or dev-channel ZIP from the host into the local filesystem.\n *\n * - Default: current release version (`installed_plugins.current_version_id`)\n * - `--release <semver>`: a specific released version label\n * - `--dev`: the scratch `plugin_dev_channel` artifact (mutually exclusive with `--release`)\n */\nexport async function downloadCommand(opts: DownloadOptions): Promise<void> {\n const release = opts.release ?? opts.version\n if (opts.dev && release) {\n throw new CliError('Use either --dev or --release, not both.')\n }\n\n const ctx = await resolveContext({ host: opts.host })\n requireToken(ctx)\n const projectConfig = requireProjectConfig(ctx)\n const pluginId = await resolvePluginId(ctx, projectConfig.plugin_key)\n\n let channel: 'release' | 'dev' = 'release'\n let versionLabel: string | null = null\n let contentSha256: string | null = null\n let artifactSha256: string | null = null\n let bytes: Buffer\n let defaultFileName: string\n\n try {\n if (opts.dev) {\n channel = 'dev'\n const result = await ctx.client.downloadDevArtifact(pluginId)\n bytes = result.bytes\n contentSha256 = result.contentSha256\n artifactSha256 = result.artifactSha256\n defaultFileName = `${projectConfig.plugin_key}-dev.zip`\n } else {\n const { plugin, current_version } = await ctx.client.getPlugin(pluginId)\n let versionId = current_version?.id ?? plugin.current_version_id\n versionLabel = current_version?.version ?? null\n contentSha256 = current_version?.content_sha256 ?? null\n artifactSha256 = current_version?.artifact_sha256 ?? null\n\n if (release) {\n const { versions } = await ctx.client.listVersions(pluginId)\n const hit = versions.find((v) => v.version === release)\n if (!hit) {\n throw new CliError(\n `Version \"${release}\" not found for ${projectConfig.plugin_key} on ${ctx.host}. Run \"cervio versions\".`,\n )\n }\n versionId = hit.id\n versionLabel = hit.version\n contentSha256 = hit.content_sha256 ?? null\n artifactSha256 = hit.artifact_sha256\n }\n\n if (!versionId) {\n throw new CliError(`Plugin \"${projectConfig.plugin_key}\" has no release version on ${ctx.host} yet.`)\n }\n\n const result = await ctx.client.downloadVersionArtifact(pluginId, versionId)\n bytes = result.bytes\n if (result.versionLabel) versionLabel = result.versionLabel\n if (result.contentSha256) contentSha256 = result.contentSha256\n if (result.artifactSha256) artifactSha256 = result.artifactSha256\n defaultFileName = `${projectConfig.plugin_key}-v${versionLabel ?? 'unknown'}.zip`\n }\n } catch (err) {\n if (err instanceof ApiError && (err.status === 404 || err.status === 405)) {\n throw new CliError(\n `Artifact download is not available on ${ctx.host} yet (deploy the admin artifact routes).`,\n )\n }\n throw err\n }\n\n const outputPath = path.resolve(process.cwd(), opts.output ?? path.join('.cervio', 'out', defaultFileName))\n await fs.mkdir(path.dirname(outputPath), { recursive: true })\n await fs.writeFile(outputPath, bytes)\n\n const payload = {\n ok: true as const,\n host: ctx.host,\n plugin_key: projectConfig.plugin_key,\n channel,\n version: versionLabel,\n content_sha256: contentSha256,\n artifact_sha256: artifactSha256,\n bytes: bytes.byteLength,\n path: outputPath,\n }\n\n printResult(!!opts.json, payload, (data) => {\n log.success(`Downloaded ${data.plugin_key}${data.version ? `@${data.version}` : ' (dev)'} → ${data.path}`)\n log.info(` bytes: ${data.bytes}`)\n if (data.content_sha256) log.info(` content_sha256: ${data.content_sha256}`)\n if (data.artifact_sha256) log.info(` artifact_sha256: ${data.artifact_sha256}`)\n })\n}\n","import { log, runCommand } from '../util.js'\n\n/**\n * Scaffolds via `npx create-cervio-plugin` (see packages/create-cervio-plugin).\n * Inside this monorepo, npx resolves the local workspace bin\n * (`node_modules/.bin/create-cervio-plugin`) automatically; outside of it,\n * npx fetches the published package.\n */\nexport async function initCommand(name: string | undefined): Promise<void> {\n const args = name ? [name] : []\n log.step('Scaffolding via \"npx create-cervio-plugin\"...')\n await runCommand('npx', ['create-cervio-plugin', ...args])\n}\n","import prompts from 'prompts'\nimport { createApiClient } from '../api.js'\nimport { normalizeHost, saveToken } from '../config.js'\nimport { CliError, log } from '../util.js'\n\nexport async function loginCommand(opts: { host?: string; token?: string }): Promise<void> {\n if (!opts.host) {\n throw new CliError('--host <url> is required, e.g. cervio login --host https://app.example.com')\n }\n const host = normalizeHost(opts.host)\n\n let token = opts.token\n if (!token) {\n const response = await prompts({\n type: 'password',\n name: 'token',\n message: `Personal access token for ${host}`,\n })\n token = typeof response.token === 'string' ? response.token.trim() : ''\n }\n if (!token) {\n throw new CliError('No token provided.')\n }\n\n const client = createApiClient({ host, token })\n const me = await client.getMe()\n\n await saveToken(host, token)\n\n log.success(`Logged in to ${host}`)\n log.info(` user: ${me.email ?? me.user_id}`)\n log.info(` org: ${me.organization_name ?? me.organization_id}`)\n log.info(` auth: ${me.auth_method}`)\n}\n","import open from 'open'\nimport { requireProjectConfig, resolveContext } from '../context.js'\nimport { CliError, log } from '../util.js'\n\nexport async function openCommand(opts: { host?: string }): Promise<void> {\n const ctx = await resolveContext({ host: opts.host })\n const projectConfig = requireProjectConfig(ctx)\n if (!projectConfig.route_slug) {\n throw new CliError('cervio.json has no \"route_slug\" configured.')\n }\n\n const url = `${ctx.host}/r/${projectConfig.route_slug}`\n log.step(`Opening ${url}`)\n await open(url)\n}\n","import { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport { packPlugin } from '@cervio/plugin-core'\nimport { CliError, formatBytes, log, printResult } from '../util.js'\n\nexport type PackedOutput = {\n pluginKey: string\n contentSha256: string\n sizeBytes: number\n outputPath: string\n}\n\nexport async function packForPublish(dir = process.cwd()): Promise<PackedOutput> {\n const result = await packPlugin({ dir })\n if (!result.ok) {\n throw new CliError(`Pack failed: ${result.error}`)\n }\n\n const outDir = path.join(dir, '.cervio', 'out')\n await fs.mkdir(outDir, { recursive: true })\n const outputPath = path.join(outDir, `${result.value.pluginKey}.zip`)\n await fs.writeFile(outputPath, result.value.buffer)\n\n return {\n pluginKey: result.value.pluginKey,\n contentSha256: result.value.contentSha256,\n sizeBytes: result.value.sizeBytes,\n outputPath,\n }\n}\n\nexport async function packCommand(opts: { json?: boolean; dir?: string }): Promise<void> {\n const packed = await packForPublish(opts.dir ?? process.cwd())\n printResult(!!opts.json, packed, (data) => {\n log.success(`Packed ${data.pluginKey} (${formatBytes(data.sizeBytes)})`)\n log.info(` content_sha256: ${data.contentSha256}`)\n log.info(` output: ${data.outputPath}`)\n })\n}\n","import { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport prompts from 'prompts'\nimport { validatePluginZipBuffer } from '@cervio/plugin-core'\nimport { ApiError, createApiClient } from '../api.js'\nimport {\n getLastHost,\n normalizeHost,\n readProjectConfig,\n resolveHost,\n resolveToken,\n setLastHost,\n} from '../config.js'\nimport { packForPublish } from './pack.js'\nimport { CliError, log, minutesSince } from '../util.js'\n\nexport type PushOptions = {\n host?: string\n changelog?: string\n activate?: boolean\n json?: boolean\n yes?: boolean\n expectHost?: string\n dev?: boolean\n force?: boolean\n /** Upload an existing ZIP instead of packing the current directory. */\n file?: string\n}\n\nconst DEFAULT_DEV_CONFLICT_MINUTES = 30\n\nexport async function pushCommand(opts: PushOptions): Promise<void> {\n const projectConfig = await readProjectConfig()\n if (!projectConfig) {\n throw new CliError('No cervio.json found in the current directory. Run \"cervio init\" first.')\n }\n\n const host = resolveHost({ cliHost: opts.host, projectConfig })\n if (!host) {\n throw new CliError('No host configured. Pass --host, set CERVIO_URL, or add \"host\" to cervio.json.')\n }\n\n if (opts.expectHost && normalizeHost(opts.expectHost) !== host) {\n const message = `Resolved host ${host} does not match --expect-host ${normalizeHost(opts.expectHost)}.`\n if (opts.json) {\n console.log(JSON.stringify({ ok: false, error: 'host_mismatch', host, expected: normalizeHost(opts.expectHost) }, null, 2))\n process.exitCode = 1\n return\n }\n throw new CliError(message)\n }\n\n const token = await resolveToken(host)\n if (!token) {\n throw new CliError(`Not logged in to ${host}. Run \"cervio login --host ${host}\" first.`)\n }\n const client = createApiClient({ host, token })\n\n let orgName: string | undefined\n try {\n const me = await client.getMe()\n orgName = me.organization_name ?? me.organization_id\n } catch {\n // /api/v1/me failing shouldn't block push reporting; host is still printed below.\n }\n\n log.info(`Publishing to ${host}${orgName ? ` (org: ${orgName})` : ''}`)\n\n const lastHost = await getLastHost()\n if (lastHost && lastHost !== host) {\n if (opts.json) {\n // No prompt in --json mode; the caller is expected to have already\n // confirmed via --yes or --expect-host out of band.\n if (!opts.yes) {\n console.log(\n JSON.stringify(\n { ok: false, error: 'host_changed', host, last_host: lastHost },\n null,\n 2,\n ),\n )\n process.exitCode = 1\n return\n }\n } else if (!opts.yes) {\n const response = await prompts({\n type: 'confirm',\n name: 'proceed',\n message: `Last push was to ${lastHost}. Continue publishing to ${host}?`,\n initial: false,\n })\n if (!response.proceed) {\n log.warn('Push cancelled.')\n return\n }\n } else {\n log.warn(`Host changed from ${lastHost} to ${host} (--yes supplied, continuing).`)\n }\n }\n\n if (opts.dev) {\n const conflict = await checkDevChannelConflict({\n client,\n projectConfig,\n currentUserEmail: (await safeMe(client))?.email ?? null,\n force: !!opts.force,\n })\n if (conflict) {\n if (opts.json) {\n console.log(JSON.stringify({ ok: false, error: 'dev_channel_conflict', host, conflict }, null, 2))\n process.exitCode = 1\n return\n }\n if (!opts.force) {\n const response = await prompts({\n type: 'confirm',\n name: 'proceed',\n message: `Dev channel was last updated by ${conflict.updated_by_email ?? 'someone else'} ${conflict.minutes_ago.toFixed(0)}m ago. Overwrite anyway?`,\n initial: false,\n })\n if (!response.proceed) {\n log.warn('Push cancelled (dev channel conflict).')\n return\n }\n } else {\n log.warn('Dev channel conflict detected, continuing due to --force.')\n }\n }\n }\n\n let zipBuffer: Buffer\n let zipFileName: string\n if (opts.file) {\n const filePath = path.resolve(process.cwd(), opts.file)\n try {\n zipBuffer = await fs.readFile(filePath)\n } catch (err) {\n throw new CliError(\n `Could not read --file ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n const validated = await validatePluginZipBuffer(zipBuffer)\n if (!validated.ok) {\n throw new CliError(`Invalid plugin ZIP (${opts.file}): ${validated.error}`)\n }\n if (validated.value.pluginKey !== projectConfig.plugin_key) {\n throw new CliError(\n `ZIP plugin_key \"${validated.value.pluginKey}\" does not match cervio.json \"${projectConfig.plugin_key}\".`,\n )\n }\n zipFileName = path.basename(filePath).endsWith('.zip')\n ? path.basename(filePath)\n : `${validated.value.pluginKey}.zip`\n log.info(`Using existing ZIP ${filePath} (content_sha256=${validated.value.contentSha256})`)\n } else {\n const packed = await packForPublish(process.cwd())\n zipBuffer = await fs.readFile(packed.outputPath)\n zipFileName = `${packed.pluginKey}.zip`\n }\n\n const form = new FormData()\n form.set('file', new Blob([zipBuffer], { type: 'application/zip' }), zipFileName)\n if (opts.changelog) form.set('changelog', opts.changelog)\n form.set('set_current', String(opts.activate !== false))\n if (opts.dev) form.set('channel', 'dev')\n\n let upload\n try {\n upload = await client.uploadPlugin(form)\n } catch (err) {\n if (err instanceof ApiError) {\n if (opts.json) {\n console.log(JSON.stringify({ ok: false, error: err.code ?? 'upload_failed', message: err.message, host }, null, 2))\n process.exitCode = 1\n return\n }\n if (err.code === 'plugin_not_found' && opts.dev) {\n throw new CliError(\n `Plugin \"${projectConfig.plugin_key}\" does not exist on ${host} yet. Dev-channel pushes require a prior release push - run \"cervio push\" (without --dev) once first.`,\n )\n }\n throw new CliError(`Upload failed: ${err.message}`)\n }\n throw err\n }\n\n await setLastHost(host)\n\n if (opts.json) {\n console.log(JSON.stringify({ ok: true, host, ...upload }, null, 2))\n return\n }\n\n if (upload.channel === 'dev') {\n log.success(`Pushed ${upload.plugin.plugin_key} to the dev channel on ${host}`)\n log.info(` content_sha256: ${upload.dev_channel.content_sha256}`)\n log.info(` updated_at: ${upload.dev_channel.updated_at}`)\n } else {\n log.success(`Pushed ${upload.plugin.plugin_key}@${upload.version.version} to ${host}`)\n log.info(` content_sha256: ${upload.version.content_sha256 ?? '(n/a)'}`)\n if (upload.reason) log.dim(` ${upload.reason}`)\n }\n}\n\nasync function safeMe(client: ReturnType<typeof createApiClient>) {\n try {\n return await client.getMe()\n } catch {\n return null\n }\n}\n\nasync function checkDevChannelConflict(args: {\n client: ReturnType<typeof createApiClient>\n projectConfig: NonNullable<Awaited<ReturnType<typeof readProjectConfig>>>\n currentUserEmail: string | null\n force: boolean\n}): Promise<{ updated_by_email: string | null; updated_at: string; minutes_ago: number } | null> {\n if (args.force) return null\n const pluginId = await resolvePluginIdSafely(args.client, args.projectConfig.plugin_key)\n if (!pluginId) return null // plugin not created yet on host: nothing to conflict with\n\n let devChannel\n try {\n const res = await args.client.getDevChannel(pluginId)\n devChannel = res.dev_channel\n } catch (err) {\n if (err instanceof ApiError && (err.status === 404 || err.status === 405)) {\n // Older host without the dev-channel endpoint: cannot check for\n // conflicts, so proceed without blocking the push.\n return null\n }\n throw err\n }\n if (!devChannel?.updated_at) return null\n\n const conflictWindow = args.projectConfig.dev_conflict_minutes ?? DEFAULT_DEV_CONFLICT_MINUTES\n const minutesAgo = minutesSince(devChannel.updated_at)\n const sameUser =\n !!args.currentUserEmail &&\n !!devChannel.updated_by_email &&\n devChannel.updated_by_email.toLowerCase() === args.currentUserEmail.toLowerCase()\n\n if (!sameUser && minutesAgo <= conflictWindow) {\n return { updated_by_email: devChannel.updated_by_email ?? null, updated_at: devChannel.updated_at, minutes_ago: minutesAgo }\n }\n return null\n}\n\nasync function resolvePluginIdSafely(\n client: ReturnType<typeof createApiClient>,\n pluginKey: string,\n): Promise<string | null> {\n try {\n const { plugins } = await client.listPlugins()\n return plugins.find((p) => p.plugin_key === pluginKey)?.id ?? null\n } catch {\n return null\n }\n}\n","import { requireProjectConfig, requireToken, resolveContext, resolvePluginId } from '../context.js'\nimport { CliError, log, printResult } from '../util.js'\n\nexport async function rollbackCommand(\n version: string,\n opts: { host?: string; json?: boolean },\n): Promise<void> {\n const ctx = await resolveContext({ host: opts.host })\n requireToken(ctx)\n const projectConfig = requireProjectConfig(ctx)\n const pluginId = await resolvePluginId(ctx, projectConfig.plugin_key)\n\n const { versions } = await ctx.client.listVersions(pluginId)\n const match = versions.find((v) => v.version === version)\n if (!match) {\n throw new CliError(\n `No version \"${version}\" found for ${projectConfig.plugin_key} on ${ctx.host}. Run \"cervio versions\" to list available versions.`,\n )\n }\n\n const result = await ctx.client.activateVersion(pluginId, match.id)\n\n printResult(!!opts.json, { host: ctx.host, plugin_key: projectConfig.plugin_key, version, ...result }, (data) => {\n log.success(`Activated ${data.plugin_key}@${version} on ${data.host}`)\n })\n}\n","import { requireProjectConfig, requireToken, resolveContext, resolvePluginId } from '../context.js'\nimport { CliError, log, printResult } from '../util.js'\n\nfunction parseOnOff(value: string | undefined, flag: string): boolean | undefined {\n if (value === undefined) return undefined\n const normalized = value.toLowerCase()\n if (normalized === 'on') return true\n if (normalized === 'off') return false\n throw new CliError(`${flag} must be \"on\" or \"off\".`)\n}\n\nexport async function routeSetCommand(opts: {\n host?: string\n slug?: string\n cache?: string\n devChannel?: string\n json?: boolean\n}): Promise<void> {\n const ctx = await resolveContext({ host: opts.host })\n requireToken(ctx)\n const projectConfig = requireProjectConfig(ctx)\n const pluginId = await resolvePluginId(ctx, projectConfig.plugin_key)\n\n const cache = parseOnOff(opts.cache, '--cache')\n const devChannel = parseOnOff(opts.devChannel, '--dev-channel')\n\n // PUT is a full upsert: route_slug is always required. Fall back to the\n // existing config's slug (or cervio.json's route_slug) when --slug is omitted.\n let slug = opts.slug\n if (!slug) {\n const { route_config } = await ctx.client.getRouteConfig(pluginId)\n slug = route_config?.route_slug ?? projectConfig.route_slug\n }\n if (!slug) {\n throw new CliError('No route slug known. Pass --slug <slug> (or set \"route_slug\" in cervio.json).')\n }\n\n const { route_config } = await ctx.client.setRouteConfig(pluginId, {\n route_slug: slug,\n artifact_cache_enabled: cache,\n dev_channel_enabled: devChannel,\n })\n\n printResult(!!opts.json, { host: ctx.host, plugin_key: projectConfig.plugin_key, route_config }, (data) => {\n const rc = data.route_config\n const extras = rc\n ? ` (cache=${rc.artifact_cache_enabled ? 'on' : 'off'}, dev_channel=${rc.dev_channel_enabled ? 'on' : 'off'})`\n : ''\n log.success(\n `Updated route config for ${data.plugin_key} on ${data.host}: /r/${rc?.route_slug}` + extras,\n )\n })\n}\n","import { validatePluginDir } from '@cervio/plugin-core'\nimport { ApiError } from '../api.js'\nimport { requireProjectConfig, requireToken, resolveContext, tryResolvePluginId } from '../context.js'\nimport { CliError, log, printResult } from '../util.js'\n\nexport async function statusCommand(opts: { host?: string; dev?: boolean; json?: boolean }): Promise<void> {\n const ctx = await resolveContext({ host: opts.host })\n requireToken(ctx)\n const projectConfig = requireProjectConfig(ctx)\n\n const local = await validatePluginDir(process.cwd())\n if (!local.ok) {\n throw new CliError(`Local plugin failed validation: ${local.error}`)\n }\n\n const pluginId = await tryResolvePluginId(ctx, projectConfig.plugin_key)\n if (!pluginId) {\n return printResult(!!opts.json, {\n host: ctx.host,\n plugin_key: projectConfig.plugin_key,\n local_content_sha256: local.value.contentSha256,\n state: 'not_pushed' as const,\n }, (data) => {\n log.warn(`\"${data.plugin_key}\" has not been pushed to ${data.host} yet.`)\n log.info(` local content_sha256: ${data.local_content_sha256}`)\n })\n }\n\n let remoteSha256: string | null = null\n let remoteVersion: string | null = null\n let updatedByEmail: string | null = null\n let updatedAt: string | null = null\n let unimplemented = false\n try {\n if (opts.dev) {\n const { dev_channel } = await ctx.client.getDevChannel(pluginId)\n remoteSha256 = dev_channel?.content_sha256 ?? null\n remoteVersion = null // dev channel has no semver label\n updatedByEmail = dev_channel?.updated_by_email ?? null\n updatedAt = dev_channel?.updated_at ?? null\n } else {\n const { current_version } = await ctx.client.getPlugin(pluginId)\n remoteSha256 = current_version?.content_sha256 ?? null\n remoteVersion = current_version?.version ?? null\n }\n } catch (err) {\n if (err instanceof ApiError && (err.status === 404 || err.status === 405)) {\n unimplemented = true\n } else {\n throw err\n }\n }\n\n const inSync = !unimplemented && remoteSha256 !== null && remoteSha256 === local.value.contentSha256\n\n printResult(\n !!opts.json,\n {\n host: ctx.host,\n channel: opts.dev ? 'dev' : 'current',\n plugin_key: projectConfig.plugin_key,\n local_content_sha256: local.value.contentSha256,\n remote_content_sha256: remoteSha256,\n remote_version: remoteVersion,\n in_sync: inSync,\n remote_check_unavailable: unimplemented,\n ...(opts.dev\n ? {\n updated_by_email: updatedByEmail,\n updated_at: updatedAt,\n }\n : {}),\n },\n (data) => {\n log.info(`host: ${data.host}`)\n log.info(`plugin: ${data.plugin_key} (${data.channel} channel)`)\n log.info(`local: ${data.local_content_sha256}`)\n if (data.remote_check_unavailable) {\n log.warn(\n `remote: unavailable - the ${\n opts.dev ? 'dev-channel' : 'plugin detail'\n } endpoint is not implemented on this host yet.`,\n )\n return\n }\n log.info(`remote: ${data.remote_content_sha256 ?? '(none)'}${data.remote_version ? ` (v${data.remote_version})` : ''}`)\n if (opts.dev) {\n log.info(`updated_by: ${data.updated_by_email ?? '(unknown)'}`)\n log.info(`updated_at: ${data.updated_at ?? '(none)'}`)\n }\n if (data.in_sync) log.success('Up to date.')\n else log.warn('Local build differs from the deployed version. Run \"cervio push\" to publish.')\n },\n )\n}\n","import { validatePluginDir } from '@cervio/plugin-core'\nimport { CliError, log, printResult } from '../util.js'\n\nexport async function validateCommand(opts: { json?: boolean; dir?: string }): Promise<void> {\n const dir = opts.dir ?? process.cwd()\n const result = await validatePluginDir(dir)\n\n if (!result.ok) {\n if (opts.json) {\n console.log(JSON.stringify({ ok: false, error: result.error }, null, 2))\n process.exitCode = 1\n return\n }\n throw new CliError(`Validation failed: ${result.error}`)\n }\n\n printResult(!!opts.json, { ok: true, ...result.value }, (data) => {\n log.success('Plugin is valid.')\n log.info(` plugin_key: ${data.pluginKey}`)\n log.info(` content_sha256: ${data.contentSha256}`)\n })\n}\n","import { ApiError } from '../api.js'\nimport { requireProjectConfig, requireToken, resolveContext, resolvePluginId } from '../context.js'\nimport { CliError, log, printResult } from '../util.js'\n\nexport async function versionsCommand(opts: { host?: string; json?: boolean }): Promise<void> {\n const ctx = await resolveContext({ host: opts.host })\n requireToken(ctx)\n const projectConfig = requireProjectConfig(ctx)\n const pluginId = await resolvePluginId(ctx, projectConfig.plugin_key)\n\n try {\n const { versions } = await ctx.client.listVersions(pluginId)\n printResult(!!opts.json, { host: ctx.host, plugin_key: projectConfig.plugin_key, versions }, (data) => {\n for (const v of data.versions) {\n log.info(`${v.version} ${v.content_sha256 ?? ''} ${v.created_at}${v.changelog ? ` ${v.changelog}` : ''}`)\n }\n })\n } catch (err) {\n if (err instanceof ApiError && (err.status === 404 || err.status === 405)) {\n throw new CliError(\n `GET /api/v1/admin/plugins/${pluginId}/versions is not implemented on ${ctx.host} yet.`,\n )\n }\n throw err\n }\n}\n","import path from 'node:path'\nimport chokidar from 'chokidar'\nimport { validatePluginDir } from '@cervio/plugin-core'\nimport { buildCommand } from './build.js'\nimport { pushCommand } from './push.js'\nimport { log } from '../util.js'\n\nexport type WatchOptions = {\n push?: boolean\n dev?: boolean\n host?: string\n}\n\nexport async function watchCommand(opts: WatchOptions): Promise<void> {\n const cwd = process.cwd()\n const srcDir = path.join(cwd, 'src')\n\n let running = false\n let pending = false\n\n const runCycle = async () => {\n if (running) {\n pending = true\n return\n }\n running = true\n try {\n log.step('Rebuilding...')\n await buildCommand()\n\n log.step('Validating...')\n const result = await validatePluginDir(cwd)\n if (!result.ok) {\n log.error(`Validation failed: ${result.error}`)\n return\n }\n log.success(`Valid (content_sha256: ${result.value.contentSha256})`)\n\n if (opts.push) {\n log.step(`Pushing${opts.dev ? ' to dev channel' : ''}...`)\n await pushCommand({ host: opts.host, dev: opts.dev, activate: true })\n }\n } catch (err) {\n log.error(err instanceof Error ? err.message : String(err))\n } finally {\n running = false\n if (pending) {\n pending = false\n void runCycle()\n }\n }\n }\n\n log.info(`Watching ${srcDir} for changes (Ctrl+C to stop)...`)\n const watcher = chokidar.watch(srcDir, { ignoreInitial: true })\n watcher.on('all', () => {\n void runCycle()\n })\n\n await runCycle()\n\n await new Promise<void>((resolve) => {\n process.on('SIGINT', () => {\n void watcher.close().then(() => resolve())\n })\n })\n}\n","import { resolveContext, requireToken } from '../context.js'\nimport { printResult } from '../util.js'\n\nexport async function whoamiCommand(opts: { host?: string; json?: boolean }): Promise<void> {\n const ctx = await resolveContext({ host: opts.host })\n requireToken(ctx)\n const me = await ctx.client.getMe()\n\n printResult(!!opts.json, { host: ctx.host, ...me }, (data) => {\n console.log(`host: ${data.host}`)\n console.log(`user: ${data.email ?? data.user_id}`)\n console.log(`org: ${data.organization_name ?? data.organization_id}`)\n console.log(`auth: ${data.auth_method}`)\n })\n}\n","import { createRequire } from 'node:module'\nimport { Command } from 'commander'\nimport { ApiError } from './api.js'\nimport { buildCommand } from './commands/build.js'\nimport { doctorCommand } from './commands/doctor.js'\nimport { downloadCommand } from './commands/download.js'\nimport { initCommand } from './commands/init.js'\nimport { loginCommand } from './commands/login.js'\nimport { openCommand } from './commands/open.js'\nimport { packCommand } from './commands/pack.js'\nimport { pushCommand } from './commands/push.js'\nimport { rollbackCommand } from './commands/rollback.js'\nimport { routeSetCommand } from './commands/route.js'\nimport { statusCommand } from './commands/status.js'\nimport { validateCommand } from './commands/validate.js'\nimport { versionsCommand } from './commands/versions.js'\nimport { watchCommand } from './commands/watch.js'\nimport { whoamiCommand } from './commands/whoami.js'\nimport { CliError, log } from './util.js'\n\nconst CLI_VERSION = createRequire(import.meta.url)('../package.json').version as string\n\nfunction action<Args extends unknown[]>(fn: (...args: Args) => Promise<void>) {\n return async (...args: Args) => {\n try {\n await fn(...args)\n } catch (err) {\n if (err instanceof CliError) {\n log.error(err.message)\n process.exitCode = err.exitCode\n } else if (err instanceof ApiError) {\n log.error(`${err.message}${err.code ? ` [${err.code}]` : ''}`)\n process.exitCode = 1\n } else {\n log.error(err instanceof Error ? err.message : String(err))\n process.exitCode = 1\n }\n }\n }\n}\n\nconst program = new Command()\n\nprogram\n .name('cervio')\n .description('Cervio route plugin developer CLI')\n .version(CLI_VERSION)\n\nprogram\n .command('login')\n .description('Authenticate with a Cervio host and save the token')\n .option('--host <url>', 'Cervio host, e.g. https://app.example.com')\n .option('--token <token>', 'Personal access token (prompted if omitted)')\n .action(action(loginCommand))\n\nprogram\n .command('whoami')\n .description('Print the current host and identity')\n .option('--host <url>', 'Override the resolved host')\n .option('--json', 'Output JSON')\n .action(action(whoamiCommand))\n\nprogram\n .command('build')\n .description('Run the project build script (pnpm/npm run build)')\n .action(action(buildCommand))\n\nprogram\n .command('validate')\n .description('Validate the plugin in the current directory')\n .option('--json', 'Output JSON')\n .action(action(validateCommand))\n\nprogram\n .command('pack')\n .description('Pack the built plugin into .cervio/out/<plugin_key>.zip')\n .option('--json', 'Output JSON')\n .action(action(packCommand))\n\nprogram\n .command('push')\n .description('Validate, pack, and upload the plugin to a Cervio host')\n .option('--host <url>', 'Override the resolved host')\n .option('--changelog <text>', 'Changelog note for this version')\n .option('--no-activate', 'Upload without making this the active version')\n .option('--json', 'Output JSON (no interactive prompts)')\n .option('--yes', 'Skip the host-change confirmation prompt')\n .option('--expect-host <url>', 'Fail if the resolved host does not match')\n .option('--dev', 'Push to the dev channel instead of the release channel')\n .option('--force', 'Bypass the dev-channel conflict check')\n .option('--file <path>', 'Upload an existing ZIP instead of packing the current directory')\n .action(action(pushCommand))\n\nprogram\n .command('status')\n .description('Compare the local build against the deployed version')\n .option('--host <url>', 'Override the resolved host')\n .option('--dev', 'Compare against the dev channel instead')\n .option('--json', 'Output JSON')\n .action(action(statusCommand))\n\nprogram\n .command('init [name]')\n .description('Scaffold a new plugin project')\n .action(action(initCommand))\n\nprogram\n .command('watch')\n .description('Rebuild and validate on src/ changes')\n .option('--push', 'Push after each successful validation')\n .option('--dev', 'Push to the dev channel (with --push)')\n .option('--host <url>', 'Override the resolved host (with --push)')\n .action(action(watchCommand))\n\nprogram\n .command('doctor')\n .description('Diagnose host connectivity, auth, manifest, and entity deps')\n .option('--host <url>', 'Override the resolved host')\n .option('--json', 'Output JSON')\n .action(action(doctorCommand))\n\nprogram\n .command('versions')\n .description('List released versions for the current plugin')\n .option('--host <url>', 'Override the resolved host')\n .option('--json', 'Output JSON')\n .action(action(versionsCommand))\n\nprogram\n .command('download')\n .description('Download a release or dev-channel ZIP from the host')\n .option('--host <url>', 'Override the resolved host')\n .option('--release <semver>', 'Download a specific release version (default: current)')\n .option('--dev', 'Download the dev-channel artifact instead of a release')\n .option('-o, --output <path>', 'Output path (default: .cervio/out/<plugin_key>-….zip)')\n .option('--json', 'Output JSON')\n .action(action(downloadCommand))\n\nprogram\n .command('rollback <version>')\n .description('Activate a previously released version')\n .option('--host <url>', 'Override the resolved host')\n .option('--json', 'Output JSON')\n .action(action(rollbackCommand))\n\nconst route = program.command('route').description('Manage the plugin route configuration')\nroute\n .command('set')\n .description('Update the route slug, cache, and/or dev-channel setting')\n .option('--host <url>', 'Override the resolved host')\n .option('--slug <slug>', 'New route slug')\n .option('--cache <onoff>', 'Enable/disable route caching (\"on\" or \"off\")')\n .option('--dev-channel <onoff>', 'Enable/disable the plugin dev channel (\"on\" or \"off\")')\n .option('--json', 'Output JSON')\n .action(action(routeSetCommand))\n\nprogram\n .command('open')\n .description('Open the plugin route in a browser')\n .option('--host <url>', 'Override the resolved host')\n .action(action(openCommand))\n\nprogram.parseAsync(process.argv).catch((err) => {\n log.error(err instanceof Error ? err.message : String(err))\n process.exitCode = 1\n})\n"]}
|