@keystrokehq/cli 0.0.95 → 0.0.97

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
@@ -19,20 +19,23 @@ Right now the CLI exposes `init`, `build`, `dev`, `start`, `health`, `auth`, `--
19
19
 
20
20
  ### `auth`
21
21
 
22
- Authenticate with a running keystroke deployment via Better Auth device flow. Config lives in `~/.keystroke`; bearer tokens live in the OS keychain.
22
+ Authenticate with Keystroke via Better Auth device flow. Config lives in `~/.keystroke`; bearer tokens live in the OS keychain.
23
23
 
24
24
  ```bash
25
25
  keystroke auth login
26
26
  keystroke auth login --web-url http://localhost:3000
27
+ keystroke auth login --web-url https://app.keystroke.ai --platform-url https://api.keystroke.ai
27
28
  keystroke auth status
28
29
  keystroke auth logout
29
30
  ```
30
31
 
31
- | Setting | Default | Purpose |
32
- | ------------- | ----------------------- | ------------------------------------------------------------- |
33
- | `webUrl` | `http://localhost:3000` | Web dashboard; dev proxies `/api/*` and `/health` to platform |
34
- | `platformUrl` | `http://localhost:3002` | Platform API (direct; used by CLI platform commands) |
35
- | `serverUrl` | `http://localhost:3001` | Local keystroke server API |
32
+ | Setting | Default | Purpose |
33
+ | ------------- | -------------------------- | ---------------------------------------------------------------- |
34
+ | `webUrl` | `https://app.keystroke.ai` | Web dashboard; device login and session checks |
35
+ | `platformUrl` | `https://api.keystroke.ai` | Platform API (direct; used by CLI platform commands) |
36
+ | `serverUrl` | `http://localhost:3001` | Local keystroke server API (`keystroke dev` / `keystroke start`) |
37
+
38
+ `auth login` persists both `webUrl` and `platformUrl`. Local dev: `--web-url http://localhost:3000` (platform URL resolves to `http://localhost:3002`). Cloud auth does not change `serverUrl` — local project commands still hit your dev server.
36
39
 
37
40
  Existing commands do not require auth yet. Use `resolveCliAuth()` when adding protected commands.
38
41
 
package/dist/index.mjs CHANGED
@@ -6129,6 +6129,12 @@ const OrganizationSlugSchema = string().trim().toLowerCase().min(2, "Slug must b
6129
6129
  const ClaimableOrganizationSlugSchema = OrganizationSlugSchema.refine((slug) => !RESERVED_ORGANIZATION_SLUGS.has(slug), "This slug is reserved");
6130
6130
  /** Browser→platform request budget (ping + small platform overhead). */
6131
6131
  const PROJECT_REACHABILITY_REQUEST_TIMEOUT_MS = 17e3;
6132
+ /** Normalize a public origin URL (no trailing slash). */
6133
+ function originFromPublicUrl(value, fallback) {
6134
+ const trimmed = value?.trim();
6135
+ if (!trimmed) return fallback.replace(/\/+$/, "");
6136
+ return trimmed.replace(/\/+$/, "");
6137
+ }
6132
6138
  /** TCP port to bind for a local server, derived from a public URL. */
6133
6139
  function listenPortFromUrl(url, fallback) {
6134
6140
  const parsed = new URL(url);
@@ -7201,6 +7207,27 @@ function clearAccessToken(webUrl) {
7201
7207
  new Entry(SERVICE, accountForWebUrl(webUrl)).deletePassword();
7202
7208
  }
7203
7209
  //#endregion
7210
+ //#region src/resolve-platform-url.ts
7211
+ const DEFAULT_WEB_URL = "https://app.keystroke.ai";
7212
+ const DEFAULT_PLATFORM_URL = "https://api.keystroke.ai";
7213
+ const LOCAL_PLATFORM_URL = "http://localhost:3002";
7214
+ function webOriginFromUrl(webUrl) {
7215
+ return originFromPublicUrl(webUrl, webUrl.replace(/\/+$/, ""));
7216
+ }
7217
+ /** Known web origins with a fixed platform API — undefined for custom/staging URLs. */
7218
+ function knownPlatformUrlForWebUrl(webUrl) {
7219
+ const webOrigin = webOriginFromUrl(webUrl);
7220
+ if (webOrigin === "http://localhost:3000" || webOrigin === "http://127.0.0.1:3000") return LOCAL_PLATFORM_URL;
7221
+ if (webOrigin === "https://app.keystroke.ai") return DEFAULT_PLATFORM_URL;
7222
+ }
7223
+ function resolvePlatformUrlForWebUrl(webUrl, options = {}) {
7224
+ const explicit = options.platformUrl?.trim();
7225
+ if (explicit) return explicit.replace(/\/+$/, "");
7226
+ const known = knownPlatformUrlForWebUrl(webUrl);
7227
+ if (known) return known;
7228
+ return (options.fallback?.trim() || "https://api.keystroke.ai").replace(/\/+$/, "");
7229
+ }
7230
+ //#endregion
7204
7231
  //#region src/config.ts
7205
7232
  function getCliConfigDir(cwd = join(homedir(), ".keystroke")) {
7206
7233
  return cwd;
@@ -7213,8 +7240,13 @@ function getEffectiveApiTarget(config) {
7213
7240
  if (explicit === "local" || explicit === "platform") return explicit;
7214
7241
  return "local";
7215
7242
  }
7243
+ function syncPlatformUrlWithWebUrl(config) {
7244
+ const known = knownPlatformUrlForWebUrl(config.get("webUrl"));
7245
+ if (!known) return;
7246
+ if (config.get("platformUrl") !== known) config.set("platformUrl", known);
7247
+ }
7216
7248
  function createCliConfig(cwd = getCliConfigDir()) {
7217
- return new Conf({
7249
+ const config = new Conf({
7218
7250
  projectName: "keystroke",
7219
7251
  cwd,
7220
7252
  schema: {
@@ -7224,11 +7256,11 @@ function createCliConfig(cwd = getCliConfigDir()) {
7224
7256
  },
7225
7257
  webUrl: {
7226
7258
  type: "string",
7227
- default: "http://localhost:3000"
7259
+ default: DEFAULT_WEB_URL
7228
7260
  },
7229
7261
  platformUrl: {
7230
7262
  type: "string",
7231
- default: "http://localhost:3002"
7263
+ default: DEFAULT_PLATFORM_URL
7232
7264
  },
7233
7265
  activeOrganizationId: { type: "string" },
7234
7266
  activeProjectId: { type: "string" },
@@ -7238,6 +7270,8 @@ function createCliConfig(cwd = getCliConfigDir()) {
7238
7270
  }
7239
7271
  }
7240
7272
  });
7273
+ syncPlatformUrlWithWebUrl(config);
7274
+ return config;
7241
7275
  }
7242
7276
  function getServerUrl(config) {
7243
7277
  return config.get("serverUrl");
@@ -7246,7 +7280,7 @@ function getWebUrl(config) {
7246
7280
  return config.get("webUrl");
7247
7281
  }
7248
7282
  function getPlatformUrl(config) {
7249
- return config.get("platformUrl");
7283
+ return resolvePlatformUrlForWebUrl(getWebUrl(config), { fallback: config.get("platformUrl") });
7250
7284
  }
7251
7285
  //#endregion
7252
7286
  //#region src/auth/resolve-cli-auth.ts
@@ -13362,10 +13396,15 @@ async function getSessionWithBearer(baseURL, accessToken) {
13362
13396
  //#endregion
13363
13397
  //#region src/commands/auth/login.ts
13364
13398
  function registerAuthLoginCommand(auth) {
13365
- auth.command("login").description("Authenticate via browser device flow").option("--web-url <url>", "Web dashboard origin (default from config)").option("--org <id>", "Active organization id (skips prompt when you belong to several)").action(async (options) => {
13399
+ auth.command("login").description("Authenticate via browser device flow").option("--web-url <url>", "Web dashboard origin (default from config)").option("--platform-url <url>", "Platform API origin (derived from web URL when omitted)").option("--org <id>", "Active organization id (skips prompt when you belong to several)").action(async (options) => {
13366
13400
  const config = createCliConfig();
13367
13401
  const webUrl = options.webUrl ?? getWebUrl(config);
13368
- if (options.webUrl) config.set("webUrl", webUrl);
13402
+ const platformUrl = resolvePlatformUrlForWebUrl(webUrl, {
13403
+ platformUrl: options.platformUrl,
13404
+ fallback: getPlatformUrl(config)
13405
+ });
13406
+ config.set("webUrl", webUrl);
13407
+ config.set("platformUrl", platformUrl);
13369
13408
  try {
13370
13409
  const result = await runDeviceLogin({
13371
13410
  baseURL: webUrl,
@@ -14312,7 +14351,7 @@ function registerConfigCommand(program) {
14312
14351
  process.stdout.write(`${JSON.stringify({
14313
14352
  serverUrl: cliConfig.get("serverUrl"),
14314
14353
  webUrl: cliConfig.get("webUrl"),
14315
- platformUrl: cliConfig.get("platformUrl"),
14354
+ platformUrl: getPlatformUrl(cliConfig),
14316
14355
  activeOrganizationId: cliConfig.get("activeOrganizationId"),
14317
14356
  activeProjectId: cliConfig.get("activeProjectId"),
14318
14357
  apiTarget: getEffectiveApiTarget(cliConfig),