@wervt/cli 0.2.7 → 0.2.9

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/index.mjs CHANGED
@@ -695,6 +695,73 @@ const logs = defineCommand({
695
695
  for (const entry of entries.reverse()) printLog(entry, Boolean(args.json));
696
696
  }
697
697
  });
698
+ const SPARKS = "▁▂▃▄▅▆▇█";
699
+ const stats = defineCommand({
700
+ meta: {
701
+ name: "stats",
702
+ description: "Show an app's visitors, page views and top pages (cookieless analytics)"
703
+ },
704
+ args: {
705
+ app: {
706
+ type: "positional",
707
+ required: true,
708
+ description: "App name"
709
+ },
710
+ range: {
711
+ type: "string",
712
+ default: "7d",
713
+ description: "24h, 7d, 30d or 90d"
714
+ },
715
+ path: {
716
+ type: "string",
717
+ description: "Only views of this path"
718
+ },
719
+ referrer: {
720
+ type: "string",
721
+ description: "Only visits from this referrer host ('' for direct)"
722
+ },
723
+ country: {
724
+ type: "string",
725
+ description: "Only visits from this country (ISO code, e.g. DE)"
726
+ },
727
+ json: {
728
+ type: "boolean",
729
+ description: "Print JSON"
730
+ },
731
+ ...connection
732
+ },
733
+ async run({ args }) {
734
+ const params = new URLSearchParams({ range: args.range });
735
+ for (const key of [
736
+ "path",
737
+ "referrer",
738
+ "country"
739
+ ]) if (args[key] !== void 0) params.set(key, args[key]);
740
+ const report = await (await api(`/v1/apps/${args.app}/analytics?${params.toString()}`, args)).json();
741
+ if (args.json) return console.log(JSON.stringify(report));
742
+ const { totals, series } = report;
743
+ const peak = Math.max(1, ...series.map((point) => point.views));
744
+ const spark = series.map((point) => point.views ? SPARKS[Math.min(7, Math.floor(point.views / peak * 7.99))] : " ").join("");
745
+ console.log(`${styleText("bold", String(totals.visitors))} visitors ${styleText("bold", String(totals.views))} page views` + (totals.users ? ` ${styleText("bold", String(totals.users))} signed-in users` : "") + styleText("dim", ` (last ${report.range}, visitors unique per day)`));
746
+ console.log(styleText("cyan", spark), styleText("dim", `per ${report.bucket}, peak ${peak}`));
747
+ const section = (title, rows, none) => {
748
+ if (!rows.length) return;
749
+ console.log(`\n${styleText("bold", title)}`);
750
+ const width = Math.max(...rows.map((row) => String(row.visitors).length));
751
+ for (const row of rows.slice(0, 5)) console.log(` ${String(row.visitors).padStart(width)} ${row.value || styleText("dim", none)}`);
752
+ };
753
+ section("Pages", report.top.path, "(none)");
754
+ section("Referrers", report.top.referrer, "direct");
755
+ section("Countries", report.top.country, "unknown");
756
+ section("Devices", report.top.device, "unknown");
757
+ section("Browsers", report.top.browser, "unknown");
758
+ if (report.events.length) {
759
+ console.log(`\n${styleText("bold", "Events")}`);
760
+ const width = Math.max(...report.events.map((event) => String(event.count).length));
761
+ for (const event of report.events.slice(0, 10)) console.log(` ${String(event.count).padStart(width)} ${event.name}${event.label ? styleText("dim", ` ${event.label}`) : ""}`);
762
+ }
763
+ }
764
+ });
698
765
  const whoami = defineCommand({
699
766
  meta: {
700
767
  name: "whoami",
@@ -854,6 +921,7 @@ runMain(defineCommand({
854
921
  env,
855
922
  tokens,
856
923
  tasks,
924
+ stats,
857
925
  delete: remove,
858
926
  login,
859
927
  whoami,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wervt/cli",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "description": "Deploy and manage apps on wervt.",
5
5
  "keywords": [
6
6
  "agents",
package/skill/SKILL.md CHANGED
@@ -49,6 +49,8 @@ existing app, work in its repository instead.
49
49
  individual designs, Nuxt UI + the `nuxt-ui-mobile` skill for pure phone apps. Details in the
50
50
  app's `AGENTS.md`.
51
51
  - Users: wervt signs people in. Use `useWervtUser()`; never build login, passwords or OAuth.
52
+ - Browser agents: add a tool in `server/tools/` (`defineTool`) for each main thing a user does in
53
+ the app, so agents in the browser can do it too (WebMCP). Details in the app's `AGENTS.md`.
52
54
  - After changing `server/db/schema.ts`: `pnpm db:generate`, and commit the migration.
53
55
  - `pnpm dev` runs against a local wervt stack, which the user may not have. When it isn't running,
54
56
  don't set one up: `pnpm build` plus `pnpm exec vp check --fix` are the checks, and the