passwd-sso-cli 0.4.47 → 0.4.48
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/commands/api-key.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* revoke — Revoke an API key
|
|
8
8
|
*/
|
|
9
9
|
import { apiRequest } from "../lib/api-client.js";
|
|
10
|
+
import { readMainApiErrorBody } from "../lib/api-error-body.js";
|
|
10
11
|
import * as output from "../lib/output.js";
|
|
11
12
|
export async function apiKeyListCommand(options = {}) {
|
|
12
13
|
const res = await apiRequest("/api/api-keys");
|
|
@@ -73,8 +74,8 @@ export async function apiKeyCreateCommand(opts) {
|
|
|
73
74
|
},
|
|
74
75
|
});
|
|
75
76
|
if (!res.ok) {
|
|
76
|
-
const err = res.data;
|
|
77
|
-
output.error(`Failed to create API key: ${err
|
|
77
|
+
const err = readMainApiErrorBody(res.data);
|
|
78
|
+
output.error(`Failed to create API key: ${err?.error ?? `HTTP ${res.status}`}`);
|
|
78
79
|
return;
|
|
79
80
|
}
|
|
80
81
|
if (opts.json) {
|
|
@@ -99,12 +100,12 @@ export async function apiKeyCreateCommand(opts) {
|
|
|
99
100
|
export async function apiKeyRevokeCommand(id, options = {}) {
|
|
100
101
|
const res = await apiRequest(`/api/api-keys/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
101
102
|
if (!res.ok) {
|
|
102
|
-
const err = res.data;
|
|
103
|
+
const err = readMainApiErrorBody(res.data);
|
|
103
104
|
if (options.json) {
|
|
104
|
-
output.json({ success: false, error: err
|
|
105
|
+
output.json({ success: false, error: err?.error ?? `HTTP ${res.status}` });
|
|
105
106
|
}
|
|
106
107
|
else {
|
|
107
|
-
output.error(`Failed to revoke API key: ${err
|
|
108
|
+
output.error(`Failed to revoke API key: ${err?.error ?? `HTTP ${res.status}`}`);
|
|
108
109
|
}
|
|
109
110
|
return;
|
|
110
111
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed error-body access for main-API responses.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors `src/lib/http/api-response.ts` `MainApiErrorBody` — keep in sync.
|
|
5
|
+
* The CLI cannot import from the app's `src/` (separate tsconfig / `rootDir`),
|
|
6
|
+
* so this is a deliberate type duplicate with the same shape and invariants.
|
|
7
|
+
* See `docs/api/error-handling.md` for the canonical envelope.
|
|
8
|
+
*
|
|
9
|
+
* Keep in sync with the other 2 copies:
|
|
10
|
+
* - src/lib/http/read-api-error-body.ts (main, canonical)
|
|
11
|
+
* - extension/src/lib/api-error-body.ts (browser extension)
|
|
12
|
+
* CI drift check: scripts/checks/check-api-error-body-drift.sh
|
|
13
|
+
*
|
|
14
|
+
* Note: OAuth endpoints (`/api/mcp/token`, `/api/mcp/register`) use the RFC 6749
|
|
15
|
+
* error envelope (`error`, `error_description`), NOT this shape. Reads from
|
|
16
|
+
* those endpoints belong in `cli/src/lib/oauth.ts` and are intentionally not
|
|
17
|
+
* migrated here.
|
|
18
|
+
*/
|
|
19
|
+
export type MainApiErrorBody = {
|
|
20
|
+
readonly error: string;
|
|
21
|
+
readonly details?: unknown;
|
|
22
|
+
readonly lockedUntil?: string | null;
|
|
23
|
+
readonly currentKeyVersion?: number;
|
|
24
|
+
};
|
|
25
|
+
export declare function readApiErrorBody(res: Response): Promise<MainApiErrorBody | null>;
|
|
26
|
+
/**
|
|
27
|
+
* Read `details.message` from an already-parsed error body.
|
|
28
|
+
*
|
|
29
|
+
* The `apiRequest` wrapper in `api-client.ts` returns `res.data` as the raw
|
|
30
|
+
* JSON body (success OR error shape). On error paths, callers can pass that
|
|
31
|
+
* body here after narrowing it via `readMainApiErrorBody`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getApiErrorMessage(body: MainApiErrorBody | null): string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Read a single named field from `body.details` with a runtime type guard.
|
|
36
|
+
*
|
|
37
|
+
* Mirrors `getApiErrorDetail` in the main copy. See that file for full
|
|
38
|
+
* rationale.
|
|
39
|
+
*/
|
|
40
|
+
export declare function getApiErrorDetail<T>(body: MainApiErrorBody | null, field: string, guard: (value: unknown) => value is T): T | null;
|
|
41
|
+
/**
|
|
42
|
+
* Read `details.properties[<field>].errors` from a Zod `treeifyError()` shape.
|
|
43
|
+
*
|
|
44
|
+
* Centralizes the per-field Zod-tree access pattern used by validation-error
|
|
45
|
+
* consumers (slug, url, etc.). Returns the errors array if present, `null`
|
|
46
|
+
* otherwise.
|
|
47
|
+
*/
|
|
48
|
+
export declare function getApiErrorFieldErrors(body: MainApiErrorBody | null, field: string): readonly unknown[] | null;
|
|
49
|
+
/**
|
|
50
|
+
* Narrow an unknown value (e.g. `apiRequest`'s `res.data`) to `MainApiErrorBody`.
|
|
51
|
+
*
|
|
52
|
+
* Useful at error-path call sites that consume the wrapper's `res.data` rather
|
|
53
|
+
* than reading the `Response` directly.
|
|
54
|
+
*/
|
|
55
|
+
export declare function readMainApiErrorBody(value: unknown): MainApiErrorBody | null;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed error-body access for main-API responses.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors `src/lib/http/api-response.ts` `MainApiErrorBody` — keep in sync.
|
|
5
|
+
* The CLI cannot import from the app's `src/` (separate tsconfig / `rootDir`),
|
|
6
|
+
* so this is a deliberate type duplicate with the same shape and invariants.
|
|
7
|
+
* See `docs/api/error-handling.md` for the canonical envelope.
|
|
8
|
+
*
|
|
9
|
+
* Keep in sync with the other 2 copies:
|
|
10
|
+
* - src/lib/http/read-api-error-body.ts (main, canonical)
|
|
11
|
+
* - extension/src/lib/api-error-body.ts (browser extension)
|
|
12
|
+
* CI drift check: scripts/checks/check-api-error-body-drift.sh
|
|
13
|
+
*
|
|
14
|
+
* Note: OAuth endpoints (`/api/mcp/token`, `/api/mcp/register`) use the RFC 6749
|
|
15
|
+
* error envelope (`error`, `error_description`), NOT this shape. Reads from
|
|
16
|
+
* those endpoints belong in `cli/src/lib/oauth.ts` and are intentionally not
|
|
17
|
+
* migrated here.
|
|
18
|
+
*/
|
|
19
|
+
export async function readApiErrorBody(res) {
|
|
20
|
+
if (res.ok)
|
|
21
|
+
return null;
|
|
22
|
+
const json = await res.json().catch(() => null);
|
|
23
|
+
if (!json ||
|
|
24
|
+
typeof json !== "object" ||
|
|
25
|
+
typeof json.error !== "string") {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return json;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Read `details.message` from an already-parsed error body.
|
|
32
|
+
*
|
|
33
|
+
* The `apiRequest` wrapper in `api-client.ts` returns `res.data` as the raw
|
|
34
|
+
* JSON body (success OR error shape). On error paths, callers can pass that
|
|
35
|
+
* body here after narrowing it via `readMainApiErrorBody`.
|
|
36
|
+
*/
|
|
37
|
+
export function getApiErrorMessage(body) {
|
|
38
|
+
if (!body || typeof body.details !== "object" || body.details === null) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const message = body.details.message;
|
|
42
|
+
return typeof message === "string" ? message : null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Read a single named field from `body.details` with a runtime type guard.
|
|
46
|
+
*
|
|
47
|
+
* Mirrors `getApiErrorDetail` in the main copy. See that file for full
|
|
48
|
+
* rationale.
|
|
49
|
+
*/
|
|
50
|
+
export function getApiErrorDetail(body, field, guard) {
|
|
51
|
+
if (!body || typeof body.details !== "object" || body.details === null) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const value = body.details[field];
|
|
55
|
+
return guard(value) ? value : null;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Read `details.properties[<field>].errors` from a Zod `treeifyError()` shape.
|
|
59
|
+
*
|
|
60
|
+
* Centralizes the per-field Zod-tree access pattern used by validation-error
|
|
61
|
+
* consumers (slug, url, etc.). Returns the errors array if present, `null`
|
|
62
|
+
* otherwise.
|
|
63
|
+
*/
|
|
64
|
+
export function getApiErrorFieldErrors(body, field) {
|
|
65
|
+
if (!body || typeof body.details !== "object" || body.details === null) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const properties = body.details.properties;
|
|
69
|
+
if (!properties || typeof properties !== "object")
|
|
70
|
+
return null;
|
|
71
|
+
const fieldObj = properties[field];
|
|
72
|
+
if (!fieldObj || typeof fieldObj !== "object")
|
|
73
|
+
return null;
|
|
74
|
+
const errors = fieldObj.errors;
|
|
75
|
+
return Array.isArray(errors) ? errors : null;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Narrow an unknown value (e.g. `apiRequest`'s `res.data`) to `MainApiErrorBody`.
|
|
79
|
+
*
|
|
80
|
+
* Useful at error-path call sites that consume the wrapper's `res.data` rather
|
|
81
|
+
* than reading the `Response` directly.
|
|
82
|
+
*/
|
|
83
|
+
export function readMainApiErrorBody(value) {
|
|
84
|
+
if (!value || typeof value !== "object")
|
|
85
|
+
return null;
|
|
86
|
+
if (typeof value.error !== "string")
|
|
87
|
+
return null;
|
|
88
|
+
return value;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=api-error-body.js.map
|