@asteroidai/cli 1.8.193 → 1.8.197
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/asteroid.js +16 -10
- package/package.json +1 -1
- package/src/account.ts +6 -3
- package/src/auth/credentials.ts +5 -0
- package/src/http.ts +8 -6
- package/src/run.test.ts +34 -0
- package/src/run.ts +8 -2
package/dist/asteroid.js
CHANGED
|
@@ -5192,6 +5192,8 @@ var CredentialStore = class {
|
|
|
5192
5192
|
// src/auth/credentials.ts
|
|
5193
5193
|
var AuthError = class extends Error {
|
|
5194
5194
|
};
|
|
5195
|
+
var API_KEY_OVERRIDES = "ASTEROID_API_KEY is set, so the CLI uses that key and ignores `asteroid login`.";
|
|
5196
|
+
var UNSET_API_KEY = "Run `unset ASTEROID_API_KEY` to use your login instead.";
|
|
5195
5197
|
function orgFromToken(token) {
|
|
5196
5198
|
const claims = tokenClaims(token);
|
|
5197
5199
|
if (!claims.org_id) return void 0;
|
|
@@ -5301,7 +5303,7 @@ var ApiError = class extends Error {
|
|
|
5301
5303
|
status;
|
|
5302
5304
|
body;
|
|
5303
5305
|
};
|
|
5304
|
-
var VERSION = "1.8.
|
|
5306
|
+
var VERSION = "1.8.197";
|
|
5305
5307
|
function problem(status, body, fallback) {
|
|
5306
5308
|
if (body && typeof body === "object") {
|
|
5307
5309
|
const record2 = body;
|
|
@@ -5368,11 +5370,13 @@ async function send(apiUrl, auth, request, binary, fetchImpl = fetch) {
|
|
|
5368
5370
|
} catch {
|
|
5369
5371
|
parsed = text2;
|
|
5370
5372
|
}
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
)
|
|
5373
|
+
let message = problem(response.status, parsed, text2.slice(0, 200));
|
|
5374
|
+
const sentKey = "X-Api-Key" in hopHeaders;
|
|
5375
|
+
if (sentKey && response.status === 401)
|
|
5376
|
+
message = `ASTEROID_API_KEY was rejected: ${message}. Check the key. ${UNSET_API_KEY}`;
|
|
5377
|
+
else if (sentKey && response.status === 403)
|
|
5378
|
+
message = `${message} (sent with ASTEROID_API_KEY. ${UNSET_API_KEY})`;
|
|
5379
|
+
throw new ApiError(response.status, message, parsed);
|
|
5376
5380
|
}
|
|
5377
5381
|
if (binary)
|
|
5378
5382
|
return {
|
|
@@ -5401,7 +5405,8 @@ async function chooseOrg(deps, orgs2) {
|
|
|
5401
5405
|
async function login(deps) {
|
|
5402
5406
|
if (deps.env.apiKey)
|
|
5403
5407
|
deps.stderr(
|
|
5404
|
-
|
|
5408
|
+
`Warning: ${API_KEY_OVERRIDES} Every command will use the key, not this sign-in. ${UNSET_API_KEY}
|
|
5409
|
+
`
|
|
5405
5410
|
);
|
|
5406
5411
|
const client = {
|
|
5407
5412
|
clientId: deps.env.workosClientId,
|
|
@@ -5467,7 +5472,7 @@ async function logout(deps) {
|
|
|
5467
5472
|
async function orgs(deps, flagOrg, json) {
|
|
5468
5473
|
if (deps.env.apiKey)
|
|
5469
5474
|
throw new UsageError(
|
|
5470
|
-
|
|
5475
|
+
`${API_KEY_OVERRIDES} The key acts in one organization; \`asteroid whoami\` shows it. ${UNSET_API_KEY}`
|
|
5471
5476
|
);
|
|
5472
5477
|
const config = loadConfig(deps.env);
|
|
5473
5478
|
const auth = await resolveAuth(
|
|
@@ -5497,7 +5502,7 @@ async function orgs(deps, flagOrg, json) {
|
|
|
5497
5502
|
async function use(deps, ref) {
|
|
5498
5503
|
if (deps.env.apiKey)
|
|
5499
5504
|
throw new UsageError(
|
|
5500
|
-
|
|
5505
|
+
`${API_KEY_OVERRIDES} \`use\` only switches the login's organization. ${UNSET_API_KEY}`
|
|
5501
5506
|
);
|
|
5502
5507
|
const config = loadConfig(deps.env);
|
|
5503
5508
|
if (!ref && deps.ui && (config.orgs?.length ?? 0) > 0) {
|
|
@@ -5556,6 +5561,7 @@ async function whoami(deps, flagOrg, json) {
|
|
|
5556
5561
|
as: person?.email ?? body.id,
|
|
5557
5562
|
kind: body.kind,
|
|
5558
5563
|
credential: body.credential,
|
|
5564
|
+
source: auth.kind === "api-key" ? "ASTEROID_API_KEY" : "asteroid login",
|
|
5559
5565
|
organization,
|
|
5560
5566
|
...minutes === void 0 ? {} : { tokenExpiresIn: `${minutes}m` }
|
|
5561
5567
|
})}
|
|
@@ -5765,7 +5771,7 @@ function rejectUnknown(flags) {
|
|
|
5765
5771
|
function rejectOrgWithApiKey(deps, flagOrg) {
|
|
5766
5772
|
if (deps.env.apiKey && (flagOrg || deps.env.org)) {
|
|
5767
5773
|
throw new UsageError(
|
|
5768
|
-
|
|
5774
|
+
`${API_KEY_OVERRIDES} The key acts in its own organization, so drop --org and ASTEROID_ORG. ${UNSET_API_KEY}`
|
|
5769
5775
|
);
|
|
5770
5776
|
}
|
|
5771
5777
|
}
|
package/package.json
CHANGED
package/src/account.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { UsageError } from "./args";
|
|
2
2
|
import {
|
|
3
|
+
API_KEY_OVERRIDES,
|
|
3
4
|
AuthError,
|
|
4
5
|
orgFromToken,
|
|
5
6
|
rememberOrg,
|
|
6
7
|
resolveAuth,
|
|
8
|
+
UNSET_API_KEY,
|
|
7
9
|
} from "./auth/credentials";
|
|
8
10
|
import { CredentialStore } from "./auth/store";
|
|
9
11
|
import {
|
|
@@ -40,7 +42,7 @@ async function chooseOrg(deps: Deps, orgs: WorkosOrg[]): Promise<WorkosOrg> {
|
|
|
40
42
|
export async function login(deps: Deps): Promise<number> {
|
|
41
43
|
if (deps.env.apiKey)
|
|
42
44
|
deps.stderr(
|
|
43
|
-
|
|
45
|
+
`Warning: ${API_KEY_OVERRIDES} Every command will use the key, not this sign-in. ${UNSET_API_KEY}\n`,
|
|
44
46
|
);
|
|
45
47
|
const client = {
|
|
46
48
|
clientId: deps.env.workosClientId,
|
|
@@ -116,7 +118,7 @@ export async function orgs(
|
|
|
116
118
|
): Promise<number> {
|
|
117
119
|
if (deps.env.apiKey)
|
|
118
120
|
throw new UsageError(
|
|
119
|
-
|
|
121
|
+
`${API_KEY_OVERRIDES} The key acts in one organization; \`asteroid whoami\` shows it. ${UNSET_API_KEY}`,
|
|
120
122
|
);
|
|
121
123
|
const config = loadConfig(deps.env);
|
|
122
124
|
const auth = await resolveAuth(
|
|
@@ -148,7 +150,7 @@ export async function use(
|
|
|
148
150
|
): Promise<number> {
|
|
149
151
|
if (deps.env.apiKey)
|
|
150
152
|
throw new UsageError(
|
|
151
|
-
|
|
153
|
+
`${API_KEY_OVERRIDES} \`use\` only switches the login's organization. ${UNSET_API_KEY}`,
|
|
152
154
|
);
|
|
153
155
|
const config = loadConfig(deps.env);
|
|
154
156
|
if (!ref && deps.ui && (config.orgs?.length ?? 0) > 0) {
|
|
@@ -213,6 +215,7 @@ export async function whoami(
|
|
|
213
215
|
as: person?.email ?? body.id,
|
|
214
216
|
kind: body.kind,
|
|
215
217
|
credential: body.credential,
|
|
218
|
+
source: auth.kind === "api-key" ? "ASTEROID_API_KEY" : "asteroid login",
|
|
216
219
|
organization,
|
|
217
220
|
...(minutes === undefined ? {} : { tokenExpiresIn: `${minutes}m` }),
|
|
218
221
|
})}\n`,
|
package/src/auth/credentials.ts
CHANGED
|
@@ -12,6 +12,11 @@ import { refresh, tokenClaims, WorkosError } from "./workos";
|
|
|
12
12
|
|
|
13
13
|
export class AuthError extends Error {}
|
|
14
14
|
|
|
15
|
+
export const API_KEY_OVERRIDES =
|
|
16
|
+
"ASTEROID_API_KEY is set, so the CLI uses that key and ignores `asteroid login`.";
|
|
17
|
+
export const UNSET_API_KEY =
|
|
18
|
+
"Run `unset ASTEROID_API_KEY` to use your login instead.";
|
|
19
|
+
|
|
15
20
|
export interface Auth {
|
|
16
21
|
kind: "api-key" | "bearer";
|
|
17
22
|
headers: Record<string, string>;
|
package/src/http.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Auth, UNSET_API_KEY } from "./auth/credentials";
|
|
2
2
|
import type { BuiltRequest } from "./request";
|
|
3
3
|
|
|
4
4
|
export class ApiError extends Error {
|
|
@@ -95,11 +95,13 @@ export async function send(
|
|
|
95
95
|
} catch {
|
|
96
96
|
parsed = text;
|
|
97
97
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
)
|
|
98
|
+
let message = problem(response.status, parsed, text.slice(0, 200));
|
|
99
|
+
const sentKey = "X-Api-Key" in hopHeaders;
|
|
100
|
+
if (sentKey && response.status === 401)
|
|
101
|
+
message = `ASTEROID_API_KEY was rejected: ${message}. Check the key. ${UNSET_API_KEY}`;
|
|
102
|
+
else if (sentKey && response.status === 403)
|
|
103
|
+
message = `${message} (sent with ASTEROID_API_KEY. ${UNSET_API_KEY})`;
|
|
104
|
+
throw new ApiError(response.status, message, parsed);
|
|
103
105
|
}
|
|
104
106
|
if (binary)
|
|
105
107
|
return {
|
package/src/run.test.ts
CHANGED
|
@@ -184,6 +184,24 @@ describe("guards", () => {
|
|
|
184
184
|
expect(h.calls).toHaveLength(0);
|
|
185
185
|
});
|
|
186
186
|
|
|
187
|
+
it("tells a signed-in user that the API key overrides use", async () => {
|
|
188
|
+
const h = harness({ ASTEROID_API_KEY: "sk_test" }, () => json({}));
|
|
189
|
+
await new CredentialStore(h.deps.env).writeLogin({ refreshToken: "r1" });
|
|
190
|
+
expect(await run(["use", "org_A"], h.deps)).toBe(2);
|
|
191
|
+
expect(h.err.join("")).toContain("ignores `asteroid login`");
|
|
192
|
+
expect(h.err.join("")).toContain("unset ASTEROID_API_KEY");
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it("names the API key when the API rejects it", async () => {
|
|
196
|
+
const h = harness({ ASTEROID_API_KEY: "sk_bad" }, () =>
|
|
197
|
+
json({ detail: "invalid API key" }, 401),
|
|
198
|
+
);
|
|
199
|
+
expect(await run(["workflow", "list"], h.deps)).toBe(1);
|
|
200
|
+
expect(h.err.join("")).toContain(
|
|
201
|
+
"401: ASTEROID_API_KEY was rejected: invalid API key.",
|
|
202
|
+
);
|
|
203
|
+
});
|
|
204
|
+
|
|
187
205
|
it("rejects extra arguments and unknown flags on account commands", async () => {
|
|
188
206
|
const h = harness({}, () => json({}));
|
|
189
207
|
expect(await run(["use", "a", "b"], h.deps)).toBe(2);
|
|
@@ -209,6 +227,22 @@ describe("guards", () => {
|
|
|
209
227
|
).toBeUndefined();
|
|
210
228
|
});
|
|
211
229
|
|
|
230
|
+
it("does not blame the API key for an error after a cross-host redirect", async () => {
|
|
231
|
+
const h = harness({ ASTEROID_API_KEY: "sk_test" }, (call) =>
|
|
232
|
+
call.url.startsWith("https://odyssey")
|
|
233
|
+
? new Response(null, {
|
|
234
|
+
status: 303,
|
|
235
|
+
headers: { location: "https://storage.test/file" },
|
|
236
|
+
})
|
|
237
|
+
: new Response("expired", { status: 403 }),
|
|
238
|
+
);
|
|
239
|
+
expect(
|
|
240
|
+
await run(["execution", "file", "download", "e1", "f1"], h.deps),
|
|
241
|
+
).toBe(1);
|
|
242
|
+
expect(h.err.join("")).toContain("403: expired");
|
|
243
|
+
expect(h.err.join("")).not.toContain("ASTEROID_API_KEY");
|
|
244
|
+
});
|
|
245
|
+
|
|
212
246
|
it("keeps the method and body on a 307", async () => {
|
|
213
247
|
const h = harness({ ASTEROID_API_KEY: "sk_test" }, (call) =>
|
|
214
248
|
call.url.endsWith("/validate")
|
package/src/run.ts
CHANGED
|
@@ -2,7 +2,13 @@ import { writeFileSync } from "node:fs";
|
|
|
2
2
|
|
|
3
3
|
import { login, logout, orgs, use, whoami } from "./account";
|
|
4
4
|
import { type Parsed, UsageError } from "./args";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
API_KEY_OVERRIDES,
|
|
7
|
+
type Auth,
|
|
8
|
+
AuthError,
|
|
9
|
+
resolveAuth,
|
|
10
|
+
UNSET_API_KEY,
|
|
11
|
+
} from "./auth/credentials";
|
|
6
12
|
import { WorkosError } from "./auth/workos";
|
|
7
13
|
import { type Env, loadConfig, orgLabel, requestedOrg } from "./config";
|
|
8
14
|
import { COMMANDS } from "./generated/commands";
|
|
@@ -30,7 +36,7 @@ export interface Deps {
|
|
|
30
36
|
function rejectOrgWithApiKey(deps: Deps, flagOrg: string | undefined) {
|
|
31
37
|
if (deps.env.apiKey && (flagOrg || deps.env.org)) {
|
|
32
38
|
throw new UsageError(
|
|
33
|
-
|
|
39
|
+
`${API_KEY_OVERRIDES} The key acts in its own organization, so drop --org and ASTEROID_ORG. ${UNSET_API_KEY}`,
|
|
34
40
|
);
|
|
35
41
|
}
|
|
36
42
|
}
|