@easybits.cloud/cli 0.15.1 → 0.15.2

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.
Files changed (3) hide show
  1. package/README.md +2 -0
  2. package/dist/index.js +85 -34
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -107,6 +107,8 @@ easybits files ls
107
107
  easybits files upload ./report.pdf
108
108
  easybits files rm FILE_ID --yes
109
109
  easybits websites ls
110
+ easybits websites create "My shop" --slug my-shop # slug optional
111
+ easybits websites slug my-shop my-store # change it; the old URL 301s
110
112
  easybits providers # storage provider (Tigris by default)
111
113
  easybits usage
112
114
 
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  import { parseArgs } from "util";
5
5
 
6
6
  // src/commands/account.ts
7
- import { resolveBaseUrl as resolveBaseUrl3 } from "@easybits.cloud/sdk";
7
+ import { resolveBaseUrl as resolveBaseUrl4 } from "@easybits.cloud/sdk";
8
8
 
9
9
  // src/args.ts
10
10
  import { existsSync, readFileSync } from "fs";
@@ -303,6 +303,9 @@ function maskSecret(v) {
303
303
  return v.length <= 8 ? "***" : `${v.slice(0, 4)}\u2026***`;
304
304
  }
305
305
 
306
+ // src/api.ts
307
+ import { EasybitsError as EasybitsError2, resolveBaseUrl as resolveBaseUrl3 } from "@easybits.cloud/sdk";
308
+
306
309
  // src/client.ts
307
310
  import { EasybitsClient, resolveBaseUrl as resolveBaseUrl2 } from "@easybits.cloud/sdk";
308
311
 
@@ -500,6 +503,32 @@ async function getClient(ctx) {
500
503
  return new EasybitsClient({ apiKey, baseUrl: await resolveBaseUrl2() });
501
504
  }
502
505
 
506
+ // src/api.ts
507
+ async function api(ctx, method, path, body, opts = {}) {
508
+ const token = await resolveCredential(ctx);
509
+ const base = (await resolveBaseUrl3()).replace(/\/$/, "");
510
+ const headers = { Authorization: `Bearer ${token}` };
511
+ let payload;
512
+ if (body !== void 0) {
513
+ if (opts.raw) {
514
+ payload = body;
515
+ headers["Content-Type"] = "application/octet-stream";
516
+ } else {
517
+ payload = JSON.stringify(body);
518
+ headers["Content-Type"] = "application/json";
519
+ }
520
+ }
521
+ const res = await fetch(`${base}/api/v2${path}`, { method, headers, body: payload });
522
+ const text = await res.text();
523
+ if (!res.ok) throw new EasybitsError2(res.status, text);
524
+ try {
525
+ return JSON.parse(text);
526
+ } catch {
527
+ return text;
528
+ }
529
+ }
530
+ var encodePath = (p) => p.replace(/^\/+/, "").split("/").map(encodeURIComponent).join("/");
531
+
503
532
  // src/commands/account.ts
504
533
  var login = {
505
534
  name: "login",
@@ -592,8 +621,8 @@ Webhooks: ${u.counts.webhooks}`
592
621
  var websites = {
593
622
  name: "websites",
594
623
  group: "Storage",
595
- summary: "List your static websites",
596
- synopsis: "websites",
624
+ summary: "Static websites: list, create, change slug",
625
+ synopsis: "websites <ls|create|slug>",
597
626
  subs: {
598
627
  ls: {
599
628
  aliases: ["list"],
@@ -613,10 +642,55 @@ var websites = {
613
642
  )
614
643
  );
615
644
  }
645
+ },
646
+ create: {
647
+ summary: "Create an empty static website (optionally with your own slug)",
648
+ usage: "easybits websites create <name> [--slug <slug>]",
649
+ options: { slug: { type: "string", value: "slug", description: "Public slug: /s/<slug>/ (a-z, 0-9, hyphens, 3-60 chars)" } },
650
+ examples: ['easybits websites create "Mi tienda" --slug mi-tienda'],
651
+ async run(ctx) {
652
+ const name = need(ctx, 0, "name", this.usage);
653
+ const slug = str(ctx, "slug");
654
+ const { website } = await api(ctx, "POST", "/websites", { name, ...slug ? { slug } : {} });
655
+ emit(ctx, website, () => console.log(t(`Created ${website.slug} \u2192 ${website.url}`, `Creado ${website.slug} \u2192 ${website.url}`)));
656
+ }
657
+ },
658
+ slug: {
659
+ summary: "Change a website's slug (the old URL redirects 301 to the new one)",
660
+ usage: "easybits websites slug <websiteId|slug> <new-slug>",
661
+ examples: ["easybits websites slug rio-durmiente mi-tienda"],
662
+ async run(ctx) {
663
+ const ref = need(ctx, 0, "website", this.usage);
664
+ const slug = need(ctx, 1, "new-slug", this.usage);
665
+ const websiteId = await resolveWebsiteId(ctx, ref);
666
+ const { website } = await api(ctx, "PATCH", `/websites/${websiteId}`, { slug });
667
+ emit(ctx, website, () => console.log(t(`Slug changed \u2192 ${website.url}`, `Slug cambiado \u2192 ${website.url}`)));
668
+ }
616
669
  }
617
670
  },
618
671
  defaultSub: "ls"
619
672
  };
673
+ function matchWebsite(ref, items) {
674
+ if (/^[0-9a-f]{24}$/i.test(ref)) return ref;
675
+ const r = ref.trim().toLowerCase();
676
+ return items.find((w) => w.slug === r)?.id ?? null;
677
+ }
678
+ async function resolveWebsiteId(ctx, ref) {
679
+ if (/^[0-9a-f]{24}$/i.test(ref)) return ref;
680
+ for (let offset = 0; ; offset += 100) {
681
+ const page = await api(ctx, "GET", `/websites?limit=100&offset=${offset}`);
682
+ const id = matchWebsite(ref, page.items);
683
+ if (id) return id;
684
+ if (page.items.length < 100 || offset + 100 >= page.total) break;
685
+ }
686
+ throw new CliError(
687
+ t(`No website with id or slug "${ref}".`, `No hay sitio con id o slug "${ref}".`),
688
+ EXIT.API,
689
+ `${t("List them with", "Enl\xEDstalos con")}: easybits websites ls`,
690
+ "not_found",
691
+ 404
692
+ );
693
+ }
620
694
  var providers = {
621
695
  name: "providers",
622
696
  group: "Storage",
@@ -660,7 +734,7 @@ var mcp = {
660
734
  return;
661
735
  }
662
736
  const apiKey = resolveApiKey(ctx);
663
- const baseUrl = await resolveBaseUrl3();
737
+ const baseUrl = await resolveBaseUrl4();
664
738
  const config = {
665
739
  mcpServers: {
666
740
  easybits: {
@@ -688,7 +762,7 @@ var whoami = {
688
762
  const source = process.env.EASYBITS_API_KEY ? "env EASYBITS_API_KEY" : ctx.token ? "--token" : readRc().oauth?.accessToken ? "browser session (~/.easybitsrc)" : readRc().apiKey ? "API key (~/.easybitsrc)" : void 0;
689
763
  if (!source) throw notLoggedIn();
690
764
  const email = await fetchEmail(await resolveCredential(ctx));
691
- emit(ctx, { email, source, baseUrl: await resolveBaseUrl3() }, () => console.log(`${email ?? t("(unknown email)", "(correo desconocido)")} ${t("via", "por")} ${source}`));
765
+ emit(ctx, { email, source, baseUrl: await resolveBaseUrl4() }, () => console.log(`${email ?? t("(unknown email)", "(correo desconocido)")} ${t("via", "por")} ${source}`));
692
766
  }
693
767
  }
694
768
  };
@@ -1901,33 +1975,6 @@ function parseLinkStats(columns, row) {
1901
1975
  return columns.map((column, i) => ({ column, permanent: n(i * 4), expiring: n(i * 4 + 1), external: n(i * 4 + 2), empty: n(i * 4 + 3) })).filter((s) => s.permanent + s.expiring + s.external > 0);
1902
1976
  }
1903
1977
 
1904
- // src/api.ts
1905
- import { EasybitsError as EasybitsError2, resolveBaseUrl as resolveBaseUrl4 } from "@easybits.cloud/sdk";
1906
- async function api(ctx, method, path, body, opts = {}) {
1907
- const token = await resolveCredential(ctx);
1908
- const base = (await resolveBaseUrl4()).replace(/\/$/, "");
1909
- const headers = { Authorization: `Bearer ${token}` };
1910
- let payload;
1911
- if (body !== void 0) {
1912
- if (opts.raw) {
1913
- payload = body;
1914
- headers["Content-Type"] = "application/octet-stream";
1915
- } else {
1916
- payload = JSON.stringify(body);
1917
- headers["Content-Type"] = "application/json";
1918
- }
1919
- }
1920
- const res = await fetch(`${base}/api/v2${path}`, { method, headers, body: payload });
1921
- const text = await res.text();
1922
- if (!res.ok) throw new EasybitsError2(res.status, text);
1923
- try {
1924
- return JSON.parse(text);
1925
- } catch {
1926
- return text;
1927
- }
1928
- }
1929
- var encodePath = (p) => p.replace(/^\/+/, "").split("/").map(encodeURIComponent).join("/");
1930
-
1931
1978
  // src/commands/agents-config.ts
1932
1979
  import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync8, readdirSync as readdirSync2, statSync as statSync4, writeFileSync as writeFileSync4 } from "fs";
1933
1980
  import { basename as basename3, dirname, join as join4, relative, resolve } from "path";
@@ -3668,7 +3715,7 @@ async function updateNotice(current2) {
3668
3715
  }
3669
3716
 
3670
3717
  // src/commands/doctor.ts
3671
- var VERSION = true ? "0.15.1" : "dev";
3718
+ var VERSION = true ? "0.15.2" : "dev";
3672
3719
  var doctor2 = {
3673
3720
  name: "doctor",
3674
3721
  group: "Account",
@@ -3955,6 +4002,10 @@ var HELP_ES = {
3955
4002
  "Upload a local file": "Sube un archivo local",
3956
4003
  "Delete a file (soft delete, 7-day trash)": "Borra un archivo (a la papelera 7 d\xEDas)",
3957
4004
  "List your static websites": "Enlista tus sitios est\xE1ticos",
4005
+ "Static websites: list, create, change slug": "Sitios est\xE1ticos: enlistar, crear, cambiar slug",
4006
+ "Create an empty static website (optionally with your own slug)": "Crea un sitio est\xE1tico vac\xEDo (con tu propio slug si quieres)",
4007
+ "Public slug: /s/<slug>/ (a-z, 0-9, hyphens, 3-60 chars)": "Slug p\xFAblico: /s/<slug>/ (a-z, 0-9, guiones, 3-60 caracteres)",
4008
+ "Change a website's slug (the old URL redirects 301 to the new one)": "Cambia el slug de un sitio (la URL vieja redirige 301 a la nueva)",
3958
4009
  "Show storage providers": "Muestra los proveedores de almacenamiento",
3959
4010
  "MCP": "MCP",
3960
4011
  "Print the MCP config JSON for your agent or editor": "Imprime el JSON de configuraci\xF3n MCP para tu agente o editor",
@@ -4172,7 +4223,7 @@ function normalizeArgs(input) {
4172
4223
  }
4173
4224
 
4174
4225
  // src/index.ts
4175
- var VERSION2 = true ? "0.15.1" : "dev";
4226
+ var VERSION2 = true ? "0.15.2" : "dev";
4176
4227
  var GLOBAL_OPTIONS = {
4177
4228
  json: { type: "boolean" },
4178
4229
  token: { type: "string" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easybits.cloud/cli",
3
- "version": "0.15.1",
3
+ "version": "0.15.2",
4
4
  "description": "Official CLI for EasyBits, the cloud for AI agents — sandboxes, hosting, domains, databases, agents and files from your terminal",
5
5
  "type": "module",
6
6
  "bin": {