@keystrokehq/cli 0.0.97 → 0.0.99

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
@@ -11418,7 +11418,7 @@ function unreachableTarget(context) {
11418
11418
  function unreachableServerMessage(targetUrl) {
11419
11419
  return `Could not reach ${targetUrl ?? "the keystroke server"}. Is the server running? (keystroke dev or keystroke start)`;
11420
11420
  }
11421
- function formatKeystrokeError(error, context) {
11421
+ function formatHttpClientError(error, context) {
11422
11422
  if (error.status === 401) {
11423
11423
  if (context?.webUrl && !getAccessToken(context.webUrl)) return "Not logged in. Run `keystroke auth login` first.";
11424
11424
  return "Authentication failed. Run `keystroke auth login` again.";
@@ -11429,7 +11429,7 @@ function formatKeystrokeError(error, context) {
11429
11429
  return error.message;
11430
11430
  }
11431
11431
  function formatCliError(error, fallback, context) {
11432
- if (error instanceof KeystrokeError) return formatKeystrokeError(error, context);
11432
+ if (error instanceof KeystrokeError || error instanceof PlatformError) return formatHttpClientError(error, context);
11433
11433
  if (error instanceof Error) {
11434
11434
  if (isUnreachableServerError(error)) return unreachableServerMessage(unreachableTarget(context));
11435
11435
  return error.message;
@@ -14184,6 +14184,73 @@ function registerInitCommand(program) {
14184
14184
  });
14185
14185
  }
14186
14186
  //#endregion
14187
+ //#region src/commands/project/run-project.ts
14188
+ async function withActivePlatformClient(config, fn) {
14189
+ const platform = createCliPlatformClient(config);
14190
+ let active = await platform.organizations.getActive();
14191
+ if (!active) active = await selectActiveOrganization(config);
14192
+ platform.setActiveOrganizationId(active.organization.id);
14193
+ await fn(platform);
14194
+ }
14195
+ function writeInactiveDeployHints(projects) {
14196
+ const bin = cliBinaryName();
14197
+ for (const project of projects) {
14198
+ if (project.status !== "inactive") continue;
14199
+ process.stderr.write(`Project ${project.id} is inactive. Deploy with: ${bin} deploy --project ${project.id}\n`);
14200
+ }
14201
+ }
14202
+ async function runProjectList(config) {
14203
+ await withActivePlatformClient(config, async (platform) => {
14204
+ const projects = await platform.projects.list();
14205
+ process.stdout.write(`${JSON.stringify({ projects }, null, 2)}\n`);
14206
+ if (projects.length === 0) {
14207
+ const bin = cliBinaryName();
14208
+ process.stderr.write(`No projects yet. Create one with: ${bin} project create --name "My project"\n`);
14209
+ return;
14210
+ }
14211
+ writeInactiveDeployHints(projects);
14212
+ });
14213
+ }
14214
+ async function runProjectCreate(config, input) {
14215
+ await withActivePlatformClient(config, async (platform) => {
14216
+ const project = await platform.projects.create(input);
14217
+ process.stdout.write(`${JSON.stringify({ project }, null, 2)}\n`);
14218
+ writeInactiveDeployHints([project]);
14219
+ });
14220
+ }
14221
+ //#endregion
14222
+ //#region src/commands/project/index.ts
14223
+ function registerProjectCommand(program) {
14224
+ const project = program.command("project").description("List and create platform projects");
14225
+ project.command("list").description("List projects in the active organization").action(async () => {
14226
+ const config = createCliConfig();
14227
+ try {
14228
+ await runProjectList(config);
14229
+ } catch (error) {
14230
+ process.stderr.write(`${formatCliError(error, "List projects failed", {
14231
+ serverUrl: getPlatformUrl(config),
14232
+ webUrl: getWebUrl(config)
14233
+ })}\n`);
14234
+ process.exitCode = 1;
14235
+ }
14236
+ });
14237
+ project.command("create").description("Create a platform project in the active organization").requiredOption("--name <name>", "Project name").option("--description <description>", "Project description").action(async (options) => {
14238
+ const config = createCliConfig();
14239
+ try {
14240
+ await runProjectCreate(config, {
14241
+ name: options.name,
14242
+ ...options.description ? { description: options.description } : {}
14243
+ });
14244
+ } catch (error) {
14245
+ process.stderr.write(`${formatCliError(error, "Create project failed", {
14246
+ serverUrl: getPlatformUrl(config),
14247
+ webUrl: getWebUrl(config)
14248
+ })}\n`);
14249
+ process.exitCode = 1;
14250
+ }
14251
+ });
14252
+ }
14253
+ //#endregion
14187
14254
  //#region src/commands/start.ts
14188
14255
  function resolveStartServerUrl(portOverride) {
14189
14256
  const url = new URL(getServerUrl(createCliConfig()));
@@ -14331,18 +14398,32 @@ function registerWorkflowCommand(program) {
14331
14398
  registerWorkflowRunsCommand(workflow);
14332
14399
  }
14333
14400
  //#endregion
14334
- //#region src/commands/config/index.ts
14335
- async function assertActiveProject(projectId, config = createCliConfig()) {
14401
+ //#region src/commands/config/use-project.ts
14402
+ async function fetchProjectInOrg(config, projectId) {
14336
14403
  const platform = createCliPlatformClient(config);
14337
- let project;
14338
14404
  try {
14339
- project = await platform.projects.get(projectId);
14405
+ return await platform.projects.get(projectId);
14340
14406
  } catch (error) {
14341
- if (error instanceof PlatformError && error.status === 404) throw new Error(`Project ${projectId} not found in the active organization. Run \`keystroke config org\` to list projects, then \`keystroke config use project <id>\`.`);
14407
+ if (error instanceof PlatformError && error.status === 404) throw new Error(`Project ${projectId} not found in the active organization. Run \`keystroke project list\`, then \`keystroke config use project <id>\`.`);
14342
14408
  throw error;
14343
14409
  }
14344
- if (project.status !== "active") throw new Error(`Project ${projectId} is not active (${project.status})`);
14345
14410
  }
14411
+ function assertProjectReadyForConfig(project) {
14412
+ if (project.status === "failed") throw new Error(project.lastError ? `Project ${project.id} deploy failed: ${project.lastError}` : `Project ${project.id} deploy failed`);
14413
+ if (project.status === "starting") throw new Error(`Project ${project.id} is still starting. Wait for deploy to finish, then run \`keystroke config use project ${project.id}\`.`);
14414
+ }
14415
+ async function runConfigUseProject(config, projectId) {
14416
+ const project = await fetchProjectInOrg(config, projectId);
14417
+ assertProjectReadyForConfig(project);
14418
+ config.set("activeProjectId", projectId);
14419
+ config.set("apiTarget", "platform");
14420
+ return {
14421
+ stdout: project.status === "active" ? `Using platform project ${projectId}\n` : `Using platform project ${projectId} (${project.status})\n`,
14422
+ stderr: project.status === "inactive" ? `Project is not active yet. Deploy with: ${cliBinaryName()} deploy --project ${projectId}\n` : void 0
14423
+ };
14424
+ }
14425
+ //#endregion
14426
+ //#region src/commands/config/index.ts
14346
14427
  function registerConfigCommand(program) {
14347
14428
  const config = program.command("config").description("Manage CLI configuration");
14348
14429
  config.command("show").description("Show CLI configuration").action(() => {
@@ -14380,10 +14461,9 @@ function registerConfigCommand(program) {
14380
14461
  if (mode !== "project") throw new Error("Usage: keystroke config use [local|cloud|project [projectId]|org [organizationId]]");
14381
14462
  const targetProjectId = id ?? cliConfig.get("activeProjectId");
14382
14463
  if (!targetProjectId) throw new Error("Usage: keystroke config use project <projectId>");
14383
- await assertActiveProject(targetProjectId, cliConfig);
14384
- cliConfig.set("activeProjectId", targetProjectId);
14385
- cliConfig.set("apiTarget", "platform");
14386
- process.stdout.write(`Using platform project ${targetProjectId}\n`);
14464
+ const result = await runConfigUseProject(cliConfig, targetProjectId);
14465
+ process.stdout.write(result.stdout);
14466
+ if (result.stderr) process.stderr.write(result.stderr);
14387
14467
  });
14388
14468
  config.command("org").description("List organizations you belong to").action(async () => {
14389
14469
  const organizations = await listOrganizations(createCliConfig());
@@ -14403,6 +14483,7 @@ function createProgram() {
14403
14483
  registerAuthCommand(program);
14404
14484
  registerConnectCommand(program);
14405
14485
  registerConfigCommand(program);
14486
+ registerProjectCommand(program);
14406
14487
  registerCredentialsCommand(program);
14407
14488
  registerHealthCommand(program);
14408
14489
  registerInitCommand(program);