@wervt/cli 0.2.10 → 0.2.12

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/README.md CHANGED
@@ -1,3 +1,20 @@
1
1
  # @wervt/cli
2
2
 
3
- Build and host small Nuxt apps written by agents. Work in progress, nothing usable yet.
3
+ The `wervt` command: deploy and manage apps on a [wervt](https://wervt.app) server.
4
+
5
+ ```bash
6
+ vpx @wervt/cli login --url https://api.wervt.app # approve the code in the dashboard
7
+ vpx @wervt/cli skill install # teach your agent wervt
8
+ ```
9
+
10
+ In an app (`vp create wervt my-app` adds the CLI as a dev dependency):
11
+
12
+ ```bash
13
+ vp exec wervt deploy # build, upload, migrate, activate
14
+ vp exec wervt access my-app --public # or --add friend@example.com
15
+ vp exec wervt logs my-app
16
+ ```
17
+
18
+ Without [Vite+](https://viteplus.dev), use `npx @wervt/cli` and `pnpm exec wervt`. `wervt --help`
19
+ lists every command: `apps`, `releases`, `rollback`, `activate`, `env`, `tokens`, `members`,
20
+ `tasks`, `stats`, `delete`, `whoami`, … Docs: [wervt.app](https://wervt.app/getting-started/quickstart).
package/dist/index.mjs CHANGED
@@ -206,12 +206,12 @@ const deploy = defineCommand({
206
206
  },
207
207
  check: {
208
208
  type: "string",
209
- description: "Pages to request once the release started, a 5xx fails (default: /)"
209
+ description: "Pages to request once the release started, a 5xx fails (default: /). Shape routes are checked too; --check= turns all checks off"
210
210
  },
211
211
  "rollback-on-fail": {
212
212
  type: "boolean",
213
213
  default: false,
214
- description: "Go back to the previous release when a page check fails"
214
+ description: "Go back to the previous release when a page or shape check fails"
215
215
  },
216
216
  ...connection
217
217
  },
@@ -286,7 +286,7 @@ const deploy = defineCommand({
286
286
  return;
287
287
  }
288
288
  if (event.step === "check-failed") {
289
- const failed = event.failed.map((check) => `${check.path} (${check.status || "no answer"})`).join(", ");
289
+ const failed = event.failed.map((check) => `${check.kind === "shape" ? "shape " : ""}${check.path} (${check.status || "no answer"})`).join(", ");
290
290
  p.log.error(`Release ${event.release} started, but failed: ${failed}`);
291
291
  if (event.message) p.log.message(event.message);
292
292
  if (event.restored) p.log.info(`${name} is back on ${event.restored}.`);
@@ -463,6 +463,45 @@ const access = defineCommand({
463
463
  if (result.visibility === "private") console.log(result.allow.length ? `allowed: ${result.allow.join(", ")}` : "allowed: admins only");
464
464
  }
465
465
  });
466
+ const members = defineCommand({
467
+ meta: {
468
+ name: "members",
469
+ description: "Show or change who manages an app (its owner and members)"
470
+ },
471
+ args: {
472
+ app: {
473
+ type: "positional",
474
+ required: true,
475
+ description: "App name"
476
+ },
477
+ add: {
478
+ type: "string",
479
+ description: "Add members by email (comma separated)"
480
+ },
481
+ remove: {
482
+ type: "string",
483
+ description: "Remove members by email (comma separated)"
484
+ },
485
+ owner: {
486
+ type: "string",
487
+ description: "Hand the app to another owner"
488
+ },
489
+ ...connection
490
+ },
491
+ async run({ args }) {
492
+ const change = {};
493
+ if (args.add) change.add = toList(args.add);
494
+ if (args.remove) change.remove = toList(args.remove);
495
+ if (args.owner) change.owner = args.owner;
496
+ const result = await (Object.keys(change).length ? await api(`/v1/apps/${args.app}/owners`, args, {
497
+ method: "PATCH",
498
+ headers: { "content-type": "application/json" },
499
+ body: JSON.stringify(change)
500
+ }) : await api(`/v1/apps/${args.app}/owners`, args)).json();
501
+ console.log(`owner: ${result.owner}`);
502
+ console.log(`members: ${result.members.length ? result.members.join(", ") : "none"}`);
503
+ }
504
+ });
466
505
  const env = defineCommand({
467
506
  meta: {
468
507
  name: "env",
@@ -791,12 +830,16 @@ const whoami = defineCommand({
791
830
  args: connection,
792
831
  async run({ args }) {
793
832
  const { url, token } = await resolveConfig(args);
794
- const deployApp = token.match(/^wervtd_([a-z0-9-]+)_/)?.[1];
795
- let role = deployApp ? `deploy token for ${deployApp}` : "unknown";
796
- if (!deployApp) {
797
- const res = await fetch(`${url}/v1/databases`, { headers: { authorization: `Bearer ${token}` } });
798
- if (res.status === 401) throw new Error(`The token is not valid for ${url}`);
799
- role = res.ok ? "admin" : res.status === 403 ? "read" : `unknown (${res.status})`;
833
+ const res = await fetch(`${url}/v1/whoami`, { headers: { authorization: `Bearer ${token}` } });
834
+ if (res.status === 401) throw new Error(`The token is not valid for ${url}`);
835
+ let role;
836
+ if (res.ok) {
837
+ const me = await res.json();
838
+ role = me.role === "deploy" ? `deploy token for ${me.app}` : me.email ? `${me.role} (${me.email})` : me.role;
839
+ } else {
840
+ const deployApp = token.match(/^wervtd_([a-z0-9-]+)_/)?.[1];
841
+ const probe = deployApp ? void 0 : await fetch(`${url}/v1/databases`, { headers: { authorization: `Bearer ${token}` } });
842
+ role = deployApp ? `deploy token for ${deployApp}` : probe.ok ? "admin" : probe.status === 403 ? "read" : `unknown (${probe.status})`;
800
843
  }
801
844
  console.log(`${url}\n${role}`);
802
845
  }
@@ -939,6 +982,7 @@ runMain(defineCommand({
939
982
  rollback,
940
983
  reprovision,
941
984
  access,
985
+ members,
942
986
  env,
943
987
  tokens,
944
988
  tasks,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wervt/cli",
3
- "version": "0.2.10",
3
+ "version": "0.2.12",
4
4
  "description": "Deploy and manage apps on wervt.",
5
5
  "keywords": [
6
6
  "agents",
package/skill/SKILL.md CHANGED
@@ -63,8 +63,9 @@ existing app, work in its repository instead.
63
63
 
64
64
  ```bash
65
65
  pnpm exec wervt deploy # build, upload, migrate, activate
66
- pnpm exec wervt access <name> --public # new apps are private (signed-in admins only)
66
+ pnpm exec wervt access <name> --public # new apps are private (owner, members, admins)
67
67
  pnpm exec wervt access <name> --add a@x.com,*@company.com # or let specific people in
68
+ pnpm exec wervt members <name> --add a@x.com # who may deploy and manage it (the first deploy owns it)
68
69
  pnpm exec wervt env <name> --set KEY=value # server env vars, applied from the next request
69
70
  ```
70
71