@keystrokehq/cli 0.0.95 → 0.0.96
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
|
|
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
|
|
32
|
-
| ------------- |
|
|
33
|
-
| `webUrl` | `
|
|
34
|
-
| `platformUrl` | `
|
|
35
|
-
| `serverUrl` | `http://localhost:3001`
|
|
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
|
-
|
|
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:
|
|
7259
|
+
default: DEFAULT_WEB_URL
|
|
7228
7260
|
},
|
|
7229
7261
|
platformUrl: {
|
|
7230
7262
|
type: "string",
|
|
7231
|
-
default:
|
|
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
|
-
|
|
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
|
|
14354
|
+
platformUrl: getPlatformUrl(cliConfig),
|
|
14316
14355
|
activeOrganizationId: cliConfig.get("activeOrganizationId"),
|
|
14317
14356
|
activeProjectId: cliConfig.get("activeProjectId"),
|
|
14318
14357
|
apiTarget: getEffectiveApiTarget(cliConfig),
|