@wave-ai-os/wave-cli 0.1.57 → 0.1.59
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 +16 -0
- package/dist/index.cjs +37 -5
- package/dist/index.js +38 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -103,6 +103,22 @@ Config files are JSON objects using the same keys accepted by `--auth-json-stdin
|
|
|
103
103
|
}
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
+
For a persistent production login, configure `https://api.ourwave.io` as the
|
|
107
|
+
GraphQL/API base and save only that API endpoint to the local CLI config. The
|
|
108
|
+
token remains in the configured credential store, not in `config.json`:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
wave --base-url https://api.ourwave.io login --save-base-url
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The API host is not the browser-login destination. When production returns a
|
|
115
|
+
relative authorization path such as `/cli/login?code=<code>`, the CLI opens the
|
|
116
|
+
Wave app login page at
|
|
117
|
+
`https://app.ourwave.io/login?next=%2Fcli%2Flogin%3Fcode%3D<encoded-code>`.
|
|
118
|
+
|
|
119
|
+
For a headless environment, add `--no-browser`. This is explicit by design:
|
|
120
|
+
it does not replace a developer's local API endpoint unless they request it.
|
|
121
|
+
|
|
106
122
|
Entity targeting follows the same explicit-first rule: command flags and positional args, then stdin JSON where supported, then environment/config context for organization and runtime. If a target remains unresolved, the CLI returns a structured JSON error with `suggestedAction`, `suggestedCommands`, or both where the command can provide actionable guidance.
|
|
107
123
|
|
|
108
124
|
## Discoverability and Diagnostics
|
package/dist/index.cjs
CHANGED
|
@@ -1793,7 +1793,6 @@ async function runGraphqlMutationCommand(input) {
|
|
|
1793
1793
|
// src/commands/runtimeOptions.ts
|
|
1794
1794
|
var import_node_fs3 = require("fs");
|
|
1795
1795
|
var import_promises2 = require("fs/promises");
|
|
1796
|
-
var import_node_os2 = require("os");
|
|
1797
1796
|
var import_node_path2 = require("path");
|
|
1798
1797
|
|
|
1799
1798
|
// src/authStorage.ts
|
|
@@ -1817,6 +1816,9 @@ function authHome(env = process.env) {
|
|
|
1817
1816
|
function tokenPath(env = process.env) {
|
|
1818
1817
|
return (0, import_node_path.join)(authHome(env), FILE_NAME);
|
|
1819
1818
|
}
|
|
1819
|
+
function configPath(env = process.env) {
|
|
1820
|
+
return normalize2(env.WAVE_CONFIG_PATH) ?? (0, import_node_path.join)(authHome(env), "config.json");
|
|
1821
|
+
}
|
|
1820
1822
|
function storageMode(env = process.env) {
|
|
1821
1823
|
const raw = normalize2(env.WAVE_CLI_AUTH_STORAGE)?.toLowerCase();
|
|
1822
1824
|
if (raw === "keychain" || raw === "file" || raw === "disabled") return raw;
|
|
@@ -1952,6 +1954,25 @@ async function writeStoredToken(token, baseUrl) {
|
|
|
1952
1954
|
await writeFileToken(token, baseUrl);
|
|
1953
1955
|
return { kind: "file", available: true, path: tokenPath() };
|
|
1954
1956
|
}
|
|
1957
|
+
async function persistBaseUrl(baseUrl, env = process.env) {
|
|
1958
|
+
const path = configPath(env);
|
|
1959
|
+
let existing = {};
|
|
1960
|
+
if ((0, import_node_fs2.existsSync)(path)) {
|
|
1961
|
+
const raw = await (0, import_promises.readFile)(path, "utf8");
|
|
1962
|
+
const parsed = JSON.parse(raw);
|
|
1963
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1964
|
+
throw new Error(`Wave config file must contain a JSON object: ${path}`);
|
|
1965
|
+
}
|
|
1966
|
+
existing = parsed;
|
|
1967
|
+
}
|
|
1968
|
+
await (0, import_promises.mkdir)((0, import_node_path.dirname)(path), { recursive: true, mode: 448 });
|
|
1969
|
+
await (0, import_promises.writeFile)(path, `${JSON.stringify({ ...existing, baseUrl }, null, 2)}
|
|
1970
|
+
`, {
|
|
1971
|
+
mode: 384
|
|
1972
|
+
});
|
|
1973
|
+
await (0, import_promises.chmod)(path, 384);
|
|
1974
|
+
return path;
|
|
1975
|
+
}
|
|
1955
1976
|
async function removeStoredToken(baseUrl) {
|
|
1956
1977
|
const removedKeychain = await deleteKeychainToken(baseUrl);
|
|
1957
1978
|
const removedFile = await deleteFileToken();
|
|
@@ -2252,7 +2273,7 @@ async function resolveWithStoredToken(context) {
|
|
|
2252
2273
|
function defaultConfigPath(env) {
|
|
2253
2274
|
const explicitEnv = normalize3(env.WAVE_CONFIG_PATH);
|
|
2254
2275
|
if (explicitEnv) return explicitEnv;
|
|
2255
|
-
const candidate = (0, import_node_path2.join)((
|
|
2276
|
+
const candidate = (0, import_node_path2.join)(authHome(env), "config.json");
|
|
2256
2277
|
return (0, import_node_fs3.existsSync)(candidate) ? candidate : void 0;
|
|
2257
2278
|
}
|
|
2258
2279
|
async function resolveConfigFileContext(options, env) {
|
|
@@ -10130,6 +10151,11 @@ function absoluteAuthorizeUrl(baseUrl, authorizeUrl, uiBaseUrl = explicitUiBaseU
|
|
|
10130
10151
|
if (/^https?:\/\//i.test(authorizeUrl)) {
|
|
10131
10152
|
return authorizeUrl;
|
|
10132
10153
|
}
|
|
10154
|
+
if (new URL(baseUrl).hostname.toLowerCase() === "api.ourwave.io") {
|
|
10155
|
+
const loginUrl = new URL("https://app.ourwave.io/login");
|
|
10156
|
+
loginUrl.searchParams.set("next", authorizeUrl);
|
|
10157
|
+
return loginUrl.toString();
|
|
10158
|
+
}
|
|
10133
10159
|
return new URL(authorizeUrl, uiBaseUrl ?? localUiBaseUrlFor(baseUrl) ?? baseUrl).toString();
|
|
10134
10160
|
}
|
|
10135
10161
|
function canOpenBrowser(noBrowser) {
|
|
@@ -10216,6 +10242,7 @@ async function runTokenLogin(cmd, opts) {
|
|
|
10216
10242
|
}
|
|
10217
10243
|
const statusData = asRecord6(status.result.data.cliAuthStatus) ?? {};
|
|
10218
10244
|
const storage = await writeStoredToken(token, baseUrl);
|
|
10245
|
+
const configPath2 = opts.saveBaseUrl ? await persistBaseUrl(baseUrl) : void 0;
|
|
10219
10246
|
return printEnvelopeAndExit({
|
|
10220
10247
|
envelope: envelope({
|
|
10221
10248
|
ok: true,
|
|
@@ -10226,6 +10253,8 @@ async function runTokenLogin(cmd, opts) {
|
|
|
10226
10253
|
mode: "token",
|
|
10227
10254
|
tokenStored: true,
|
|
10228
10255
|
storage,
|
|
10256
|
+
baseUrlSaved: Boolean(configPath2),
|
|
10257
|
+
configPath: configPath2 ?? null,
|
|
10229
10258
|
status: redactUnknown(statusData, [token])
|
|
10230
10259
|
}
|
|
10231
10260
|
})
|
|
@@ -10368,6 +10397,7 @@ async function runBrowserLogin(cmd, opts) {
|
|
|
10368
10397
|
});
|
|
10369
10398
|
}
|
|
10370
10399
|
const storage = await writeStoredToken(cliToken, baseUrl);
|
|
10400
|
+
const configPath2 = opts.saveBaseUrl ? await persistBaseUrl(baseUrl) : void 0;
|
|
10371
10401
|
return printEnvelopeAndExit({
|
|
10372
10402
|
envelope: envelope({
|
|
10373
10403
|
ok: true,
|
|
@@ -10379,7 +10409,9 @@ async function runBrowserLogin(cmd, opts) {
|
|
|
10379
10409
|
authorizeUrl,
|
|
10380
10410
|
expiresAt: expiresAt ?? null,
|
|
10381
10411
|
tokenStored: true,
|
|
10382
|
-
storage
|
|
10412
|
+
storage,
|
|
10413
|
+
baseUrlSaved: Boolean(configPath2),
|
|
10414
|
+
configPath: configPath2 ?? null
|
|
10383
10415
|
}
|
|
10384
10416
|
})
|
|
10385
10417
|
});
|
|
@@ -10507,7 +10539,7 @@ async function runAuthStatus(cmd) {
|
|
|
10507
10539
|
});
|
|
10508
10540
|
}
|
|
10509
10541
|
function registerAuthCommands(program) {
|
|
10510
|
-
program.command("login").description("Authenticate Wave CLI with a browser login session or provided CLI token").option("--no-browser", "Do not open a browser; include authorizeUrl in the JSON envelope").option("--token [token]", "Store and probe a provided CLI token instead of using browser login").option("--timeout-ms <timeoutMs>", "Login timeout in milliseconds").option("--poll-interval-ms <pollIntervalMs>", "Browser login polling interval in milliseconds").action((opts, cmd) => {
|
|
10542
|
+
program.command("login").description("Authenticate Wave CLI with a browser login session or provided CLI token").option("--no-browser", "Do not open a browser; include authorizeUrl in the JSON envelope").option("--save-base-url", "Persist the resolved API base URL for future Wave CLI commands").option("--token [token]", "Store and probe a provided CLI token instead of using browser login").option("--timeout-ms <timeoutMs>", "Login timeout in milliseconds").option("--poll-interval-ms <pollIntervalMs>", "Browser login polling interval in milliseconds").action((opts, cmd) => {
|
|
10511
10543
|
const globals = cmd.optsWithGlobals();
|
|
10512
10544
|
if (opts.token !== void 0 || globals.token !== void 0) {
|
|
10513
10545
|
return runTokenLogin(cmd, opts);
|
|
@@ -15766,7 +15798,7 @@ function attachDiscoveryHelp(program) {
|
|
|
15766
15798
|
}
|
|
15767
15799
|
|
|
15768
15800
|
// src/version.ts
|
|
15769
|
-
var CLI_VERSION = "0.1.
|
|
15801
|
+
var CLI_VERSION = "0.1.59";
|
|
15770
15802
|
|
|
15771
15803
|
// src/cli.ts
|
|
15772
15804
|
function buildCli(options) {
|
package/dist/index.js
CHANGED
|
@@ -1792,7 +1792,6 @@ async function runGraphqlMutationCommand(input) {
|
|
|
1792
1792
|
// src/commands/runtimeOptions.ts
|
|
1793
1793
|
import { existsSync as existsSync2 } from "fs";
|
|
1794
1794
|
import { readFile as readFile2 } from "fs/promises";
|
|
1795
|
-
import { homedir as homedir2 } from "os";
|
|
1796
1795
|
import { join as join2 } from "path";
|
|
1797
1796
|
|
|
1798
1797
|
// src/authStorage.ts
|
|
@@ -1800,7 +1799,7 @@ import { execFile } from "child_process";
|
|
|
1800
1799
|
import { constants, existsSync } from "fs";
|
|
1801
1800
|
import { access, mkdir, readFile, rm, stat, writeFile, chmod } from "fs/promises";
|
|
1802
1801
|
import { homedir } from "os";
|
|
1803
|
-
import { join } from "path";
|
|
1802
|
+
import { dirname, join } from "path";
|
|
1804
1803
|
import { promisify } from "util";
|
|
1805
1804
|
var execFileAsync = promisify(execFile);
|
|
1806
1805
|
var KEYCHAIN_SERVICE = "wave-cli";
|
|
@@ -1816,6 +1815,9 @@ function authHome(env = process.env) {
|
|
|
1816
1815
|
function tokenPath(env = process.env) {
|
|
1817
1816
|
return join(authHome(env), FILE_NAME);
|
|
1818
1817
|
}
|
|
1818
|
+
function configPath(env = process.env) {
|
|
1819
|
+
return normalize2(env.WAVE_CONFIG_PATH) ?? join(authHome(env), "config.json");
|
|
1820
|
+
}
|
|
1819
1821
|
function storageMode(env = process.env) {
|
|
1820
1822
|
const raw = normalize2(env.WAVE_CLI_AUTH_STORAGE)?.toLowerCase();
|
|
1821
1823
|
if (raw === "keychain" || raw === "file" || raw === "disabled") return raw;
|
|
@@ -1951,6 +1953,25 @@ async function writeStoredToken(token, baseUrl) {
|
|
|
1951
1953
|
await writeFileToken(token, baseUrl);
|
|
1952
1954
|
return { kind: "file", available: true, path: tokenPath() };
|
|
1953
1955
|
}
|
|
1956
|
+
async function persistBaseUrl(baseUrl, env = process.env) {
|
|
1957
|
+
const path = configPath(env);
|
|
1958
|
+
let existing = {};
|
|
1959
|
+
if (existsSync(path)) {
|
|
1960
|
+
const raw = await readFile(path, "utf8");
|
|
1961
|
+
const parsed = JSON.parse(raw);
|
|
1962
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1963
|
+
throw new Error(`Wave config file must contain a JSON object: ${path}`);
|
|
1964
|
+
}
|
|
1965
|
+
existing = parsed;
|
|
1966
|
+
}
|
|
1967
|
+
await mkdir(dirname(path), { recursive: true, mode: 448 });
|
|
1968
|
+
await writeFile(path, `${JSON.stringify({ ...existing, baseUrl }, null, 2)}
|
|
1969
|
+
`, {
|
|
1970
|
+
mode: 384
|
|
1971
|
+
});
|
|
1972
|
+
await chmod(path, 384);
|
|
1973
|
+
return path;
|
|
1974
|
+
}
|
|
1954
1975
|
async function removeStoredToken(baseUrl) {
|
|
1955
1976
|
const removedKeychain = await deleteKeychainToken(baseUrl);
|
|
1956
1977
|
const removedFile = await deleteFileToken();
|
|
@@ -2251,7 +2272,7 @@ async function resolveWithStoredToken(context) {
|
|
|
2251
2272
|
function defaultConfigPath(env) {
|
|
2252
2273
|
const explicitEnv = normalize3(env.WAVE_CONFIG_PATH);
|
|
2253
2274
|
if (explicitEnv) return explicitEnv;
|
|
2254
|
-
const candidate = join2(
|
|
2275
|
+
const candidate = join2(authHome(env), "config.json");
|
|
2255
2276
|
return existsSync2(candidate) ? candidate : void 0;
|
|
2256
2277
|
}
|
|
2257
2278
|
async function resolveConfigFileContext(options, env) {
|
|
@@ -10129,6 +10150,11 @@ function absoluteAuthorizeUrl(baseUrl, authorizeUrl, uiBaseUrl = explicitUiBaseU
|
|
|
10129
10150
|
if (/^https?:\/\//i.test(authorizeUrl)) {
|
|
10130
10151
|
return authorizeUrl;
|
|
10131
10152
|
}
|
|
10153
|
+
if (new URL(baseUrl).hostname.toLowerCase() === "api.ourwave.io") {
|
|
10154
|
+
const loginUrl = new URL("https://app.ourwave.io/login");
|
|
10155
|
+
loginUrl.searchParams.set("next", authorizeUrl);
|
|
10156
|
+
return loginUrl.toString();
|
|
10157
|
+
}
|
|
10132
10158
|
return new URL(authorizeUrl, uiBaseUrl ?? localUiBaseUrlFor(baseUrl) ?? baseUrl).toString();
|
|
10133
10159
|
}
|
|
10134
10160
|
function canOpenBrowser(noBrowser) {
|
|
@@ -10215,6 +10241,7 @@ async function runTokenLogin(cmd, opts) {
|
|
|
10215
10241
|
}
|
|
10216
10242
|
const statusData = asRecord6(status.result.data.cliAuthStatus) ?? {};
|
|
10217
10243
|
const storage = await writeStoredToken(token, baseUrl);
|
|
10244
|
+
const configPath2 = opts.saveBaseUrl ? await persistBaseUrl(baseUrl) : void 0;
|
|
10218
10245
|
return printEnvelopeAndExit({
|
|
10219
10246
|
envelope: envelope({
|
|
10220
10247
|
ok: true,
|
|
@@ -10225,6 +10252,8 @@ async function runTokenLogin(cmd, opts) {
|
|
|
10225
10252
|
mode: "token",
|
|
10226
10253
|
tokenStored: true,
|
|
10227
10254
|
storage,
|
|
10255
|
+
baseUrlSaved: Boolean(configPath2),
|
|
10256
|
+
configPath: configPath2 ?? null,
|
|
10228
10257
|
status: redactUnknown(statusData, [token])
|
|
10229
10258
|
}
|
|
10230
10259
|
})
|
|
@@ -10367,6 +10396,7 @@ async function runBrowserLogin(cmd, opts) {
|
|
|
10367
10396
|
});
|
|
10368
10397
|
}
|
|
10369
10398
|
const storage = await writeStoredToken(cliToken, baseUrl);
|
|
10399
|
+
const configPath2 = opts.saveBaseUrl ? await persistBaseUrl(baseUrl) : void 0;
|
|
10370
10400
|
return printEnvelopeAndExit({
|
|
10371
10401
|
envelope: envelope({
|
|
10372
10402
|
ok: true,
|
|
@@ -10378,7 +10408,9 @@ async function runBrowserLogin(cmd, opts) {
|
|
|
10378
10408
|
authorizeUrl,
|
|
10379
10409
|
expiresAt: expiresAt ?? null,
|
|
10380
10410
|
tokenStored: true,
|
|
10381
|
-
storage
|
|
10411
|
+
storage,
|
|
10412
|
+
baseUrlSaved: Boolean(configPath2),
|
|
10413
|
+
configPath: configPath2 ?? null
|
|
10382
10414
|
}
|
|
10383
10415
|
})
|
|
10384
10416
|
});
|
|
@@ -10506,7 +10538,7 @@ async function runAuthStatus(cmd) {
|
|
|
10506
10538
|
});
|
|
10507
10539
|
}
|
|
10508
10540
|
function registerAuthCommands(program) {
|
|
10509
|
-
program.command("login").description("Authenticate Wave CLI with a browser login session or provided CLI token").option("--no-browser", "Do not open a browser; include authorizeUrl in the JSON envelope").option("--token [token]", "Store and probe a provided CLI token instead of using browser login").option("--timeout-ms <timeoutMs>", "Login timeout in milliseconds").option("--poll-interval-ms <pollIntervalMs>", "Browser login polling interval in milliseconds").action((opts, cmd) => {
|
|
10541
|
+
program.command("login").description("Authenticate Wave CLI with a browser login session or provided CLI token").option("--no-browser", "Do not open a browser; include authorizeUrl in the JSON envelope").option("--save-base-url", "Persist the resolved API base URL for future Wave CLI commands").option("--token [token]", "Store and probe a provided CLI token instead of using browser login").option("--timeout-ms <timeoutMs>", "Login timeout in milliseconds").option("--poll-interval-ms <pollIntervalMs>", "Browser login polling interval in milliseconds").action((opts, cmd) => {
|
|
10510
10542
|
const globals = cmd.optsWithGlobals();
|
|
10511
10543
|
if (opts.token !== void 0 || globals.token !== void 0) {
|
|
10512
10544
|
return runTokenLogin(cmd, opts);
|
|
@@ -15765,7 +15797,7 @@ function attachDiscoveryHelp(program) {
|
|
|
15765
15797
|
}
|
|
15766
15798
|
|
|
15767
15799
|
// src/version.ts
|
|
15768
|
-
var CLI_VERSION = "0.1.
|
|
15800
|
+
var CLI_VERSION = "0.1.59";
|
|
15769
15801
|
|
|
15770
15802
|
// src/cli.ts
|
|
15771
15803
|
function buildCli(options) {
|