@kryd/cli 0.3.0 → 0.4.0

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 (2) hide show
  1. package/dist/index.js +98 -7
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -15327,6 +15327,15 @@ async function getProject(apiUrl, token, projectId) {
15327
15327
  }
15328
15328
  return await res.json();
15329
15329
  }
15330
+ async function listProjects(apiUrl, token) {
15331
+ const res = await fetch(`${apiUrl}/projects`, {
15332
+ headers: { authorization: `Bearer ${token}` }
15333
+ });
15334
+ if (!res.ok) {
15335
+ throw new ApiError(`Listing projects failed (${res.status})`, await parseEnvelope(res));
15336
+ }
15337
+ return (await res.json()).items;
15338
+ }
15330
15339
  async function deleteProject(apiUrl, token, projectId) {
15331
15340
  const res = await fetch(`${apiUrl}/projects/${encodeURIComponent(projectId)}`, {
15332
15341
  method: "DELETE",
@@ -16022,7 +16031,10 @@ async function runInit(opts) {
16022
16031
  // First `kryd init` for the account claims the tenant slug (the vanity routing key in
16023
16032
  // every deploy URL); later inits omit it (the account already has one). Story 3.8.
16024
16033
  // Built conditionally (exactOptionalPropertyTypes — don't pass an explicit undefined).
16025
- ...opts.tenant ? { tenantSlug: opts.tenant } : {}
16034
+ ...opts.tenant ? { tenantSlug: opts.tenant } : {},
16035
+ // KRYD-184a: only sent when the flag is present. The API defaults to private and sends
16036
+ // `private` explicitly to the forge on every path, so omitting this is never "public".
16037
+ ...opts.public ? { public: true } : {}
16026
16038
  });
16027
16039
  let linkNote = "";
16028
16040
  try {
@@ -16522,6 +16534,37 @@ function reportDetachResult(result, opts) {
16522
16534
  process.exitCode = 1;
16523
16535
  }
16524
16536
  }
16537
+ function isProjectId(arg) {
16538
+ return arg.startsWith("proj_");
16539
+ }
16540
+ async function resolveProjectIdByName(apiUrl, token, name) {
16541
+ let projects;
16542
+ try {
16543
+ projects = await listProjects(apiUrl, token);
16544
+ } catch (err) {
16545
+ reportError(err);
16546
+ return null;
16547
+ }
16548
+ const matches = projects.filter((p) => p.name === name);
16549
+ if (matches.length === 0) {
16550
+ process.stderr.write(
16551
+ `No project named ${name} on this account. Run \`kryd project list\` to see the names.
16552
+ `
16553
+ );
16554
+ process.exitCode = 1;
16555
+ return null;
16556
+ }
16557
+ if (matches.length === 1) return matches[0].id;
16558
+ const listed = matches.map((p) => ` ${p.id} ${p.status}
16559
+ `).join("");
16560
+ process.stderr.write(
16561
+ `${matches.length} projects are named ${name}:
16562
+ ${listed}Re-run \`kryd project rm <id>\` with the one you mean.
16563
+ `
16564
+ );
16565
+ process.exitCode = 1;
16566
+ return null;
16567
+ }
16525
16568
  async function runProjectRemove(opts) {
16526
16569
  const apiUrl = resolveApiUrl(opts.apiUrl);
16527
16570
  const token = loadConfig().token;
@@ -16530,9 +16573,15 @@ async function runProjectRemove(opts) {
16530
16573
  process.exitCode = 1;
16531
16574
  return;
16532
16575
  }
16533
- const projectId = resolveProjectId(opts.project, opts.cwd);
16576
+ let projectId;
16577
+ if (opts.project !== void 0 && !isProjectId(opts.project)) {
16578
+ projectId = await resolveProjectIdByName(apiUrl, token, opts.project);
16579
+ if (!projectId) return;
16580
+ } else {
16581
+ projectId = resolveProjectId(opts.project, opts.cwd);
16582
+ }
16534
16583
  if (!projectId) {
16535
- reportNotLinked("kryd project rm <projectId>");
16584
+ reportNotLinked("kryd project rm <name|id>");
16536
16585
  return;
16537
16586
  }
16538
16587
  let project2;
@@ -16540,8 +16589,10 @@ async function runProjectRemove(opts) {
16540
16589
  try {
16541
16590
  project2 = await getProject(apiUrl, token, projectId);
16542
16591
  if (!project2) {
16543
- process.stderr.write(`No project ${projectId} on this account.
16544
- `);
16592
+ process.stderr.write(
16593
+ `No project with id ${projectId} on this account. Run \`kryd project list\` to see your projects.
16594
+ `
16595
+ );
16545
16596
  process.exitCode = 1;
16546
16597
  return;
16547
16598
  }
@@ -16738,6 +16789,40 @@ function envAnnotation(environments) {
16738
16789
  if (preview && !prod) return " \u2192 preview only";
16739
16790
  return "";
16740
16791
  }
16792
+ async function runProjectList(opts) {
16793
+ const apiUrl = resolveApiUrl(opts.apiUrl);
16794
+ const token = loadConfig().token;
16795
+ if (!token) {
16796
+ process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
16797
+ process.exitCode = 1;
16798
+ return;
16799
+ }
16800
+ let projects;
16801
+ try {
16802
+ projects = await listProjects(apiUrl, token);
16803
+ } catch (err) {
16804
+ reportError(err);
16805
+ return;
16806
+ }
16807
+ if (projects.length === 0) {
16808
+ process.stdout.write("No projects yet \u2014 run `kryd init` in a project directory.\n");
16809
+ return;
16810
+ }
16811
+ const linkedId = resolveProjectId(void 0, opts.cwd);
16812
+ const nameWidth = projects.reduce((max, p) => Math.max(max, p.name.length), 0);
16813
+ const subWidth = projects.reduce((max, p) => Math.max(max, p.subdomain.length), 0);
16814
+ const statusWidth = projects.reduce((max, p) => Math.max(max, p.status.length), 0);
16815
+ for (const p of projects) {
16816
+ const mark = p.id === linkedId ? "*" : " ";
16817
+ process.stdout.write(
16818
+ `${mark} ${p.name.padEnd(nameWidth)} ${p.subdomain.padEnd(subWidth)} ${p.status.padEnd(statusWidth)} ${p.id}
16819
+ `
16820
+ );
16821
+ }
16822
+ if (projects.some((p) => p.id === linkedId)) {
16823
+ process.stdout.write("\n* linked to this directory\n");
16824
+ }
16825
+ }
16741
16826
  function renderEnvGroup(heading, vars, opts) {
16742
16827
  const width = vars.reduce((max, v) => Math.max(max, v.key.length), 0);
16743
16828
  const dates = opts.showUpdated ? vars.map((v) => isoDate(v.updatedAt)) : [];
@@ -17127,7 +17212,7 @@ Run \`kryd env list\` to see what is set. (If you meant the runtime variable of
17127
17212
  reportError(err);
17128
17213
  }
17129
17214
  }
17130
- var CLI_VERSION = true ? "0.3.0" : "0.0.0-dev";
17215
+ var CLI_VERSION = true ? "0.4.0" : "0.0.0-dev";
17131
17216
  var program = new Command();
17132
17217
  program.name("kryd").description("Kryd CLI").version(CLI_VERSION);
17133
17218
  program.command("login").description("Sign in via the browser (default) and store a token").option("--email <email>", "account email (with --password; non-interactive escape hatch)").option("--password <password>", "account password (with --email; visible in `ps` \u2014 prefer the browser flow)").option(
@@ -17145,6 +17230,10 @@ program.command("init").description("Link this project's repo + register its pus
17145
17230
  // has always assigned a slug, so the flag could only agree with it or 409. It now changes the
17146
17231
  // slug, and only while nothing derives from it.
17147
17232
  "your tenant slug \u2014 appears in every deploy URL; changeable until your first project"
17233
+ ).option(
17234
+ "--public",
17235
+ // KRYD-184a. Chosen at creation; there is no command to flip it afterwards yet (KRYD-341).
17236
+ "create the repository PUBLIC \u2014 readable by anyone signed in to the forge (default: private). Set at creation only"
17148
17237
  ).option("--api-url <url>", "control-plane API base URL").action((opts) => runInit(opts));
17149
17238
  program.command("logs [target]").description(
17150
17239
  "Follow logs. Default: a deploy's build/deploy logs ([target]=deployment id, latest if omitted). With --runtime: a container's stdout/stderr \u2014 [target]=a project id tails its live app, a deployment id (dpl_\u2026) tails THAT deploy's container (incl. a failed one, to see why it crashed)."
@@ -17170,8 +17259,9 @@ program.command("redeploy [project]").description(
17170
17259
  "Redeploy the current live commit (no rebuild) to apply config/env changes, and follow it live"
17171
17260
  ).option("--api-url <url>", "control-plane API base URL").action((project2, opts) => runRedeploy({ ...opts, project: project2 }));
17172
17261
  var project = program.command("project").description("Manage your projects");
17262
+ project.command("list").description("List your projects \u2014 name, subdomain, status and id").option("--api-url <url>", "control-plane API base URL").action((opts) => runProjectList(opts));
17173
17263
  project.command("rm [project]").description(
17174
- "Permanently delete a project and everything Kryd created for it (asks you to type its name)"
17264
+ "Permanently delete a project and everything Kryd created for it (by name or id; asks you to type its name)"
17175
17265
  ).option("--yes", "skip the confirmation (for non-interactive use)").option("--api-url <url>", "control-plane API base URL").action((projectArg, opts) => runProjectRemove({ ...opts, project: projectArg }));
17176
17266
  var db = program.command("db").description("Manage project databases");
17177
17267
  db.command("create [project]").description("Attach a shared or bring-your-own Postgres database to a project").option("--shared", "attach a shared managed database (the default)").option(
@@ -17237,6 +17327,7 @@ export {
17237
17327
  runLogin,
17238
17328
  runLogout,
17239
17329
  runLogs,
17330
+ runProjectList,
17240
17331
  runProjectRemove,
17241
17332
  runPush,
17242
17333
  runRedeploy,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kryd/cli",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Kryd CLI — push a React / Vite / Next.js app to the European cloud for your AI: git push → live with SSL, one-click managed Postgres & object storage, and an EU-hosted AI gateway already wired in. Your code and your model calls stay in the EU.",
5
5
  "keywords": [
6
6
  "kryd",
@@ -50,8 +50,8 @@
50
50
  "typescript": "^5.6.3",
51
51
  "vitest": "^2.1.8",
52
52
  "@kryd/shared-types": "0.0.0",
53
- "@kryd/config-eslint": "0.0.0",
54
- "@kryd/config-ts": "0.0.0"
53
+ "@kryd/config-ts": "0.0.0",
54
+ "@kryd/config-eslint": "0.0.0"
55
55
  },
56
56
  "scripts": {
57
57
  "build": "esbuild src/index.ts --bundle --platform=node --format=esm --external:commander --define:__KRYD_VERSION__=\\\"$npm_package_version\\\" --outfile=dist/index.js",