@framedash/cli 0.1.1 → 0.1.3
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 +62 -5
- package/dist/commands/alerts.d.ts.map +1 -1
- package/dist/commands/alerts.js +2 -1
- package/dist/commands/alerts.js.map +1 -1
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +25 -2
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/builds.d.ts +2 -0
- package/dist/commands/builds.d.ts.map +1 -0
- package/dist/commands/builds.js +31 -0
- package/dist/commands/builds.js.map +1 -0
- package/dist/commands/content.d.ts.map +1 -1
- package/dist/commands/content.js +2 -2
- package/dist/commands/content.js.map +1 -1
- package/dist/commands/dashboard.d.ts.map +1 -1
- package/dist/commands/dashboard.js +3 -3
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/funnel.d.ts.map +1 -1
- package/dist/commands/funnel.js +7 -8
- package/dist/commands/funnel.js.map +1 -1
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +142 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +2 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +79 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/map-capture.d.ts +2 -1
- package/dist/commands/map-capture.d.ts.map +1 -1
- package/dist/commands/map-capture.js +42 -12
- package/dist/commands/map-capture.js.map +1 -1
- package/dist/commands/perf-diff.d.ts +2 -0
- package/dist/commands/perf-diff.d.ts.map +1 -0
- package/dist/commands/perf-diff.js +125 -0
- package/dist/commands/perf-diff.js.map +1 -0
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +12 -0
- package/dist/commands/query.js.map +1 -1
- package/dist/commands/retention.d.ts.map +1 -1
- package/dist/commands/retention.js +3 -3
- package/dist/commands/retention.js.map +1 -1
- package/dist/commands/run-profile-test.d.ts +7 -0
- package/dist/commands/run-profile-test.d.ts.map +1 -0
- package/dist/commands/run-profile-test.js +503 -0
- package/dist/commands/run-profile-test.js.map +1 -0
- package/dist/commands/threshold-profiles.d.ts +2 -0
- package/dist/commands/threshold-profiles.d.ts.map +1 -0
- package/dist/commands/threshold-profiles.js +24 -0
- package/dist/commands/threshold-profiles.js.map +1 -0
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/config.d.ts +42 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +44 -14
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/create-client.d.ts +27 -1
- package/dist/lib/create-client.d.ts.map +1 -1
- package/dist/lib/create-client.js +167 -24
- package/dist/lib/create-client.js.map +1 -1
- package/dist/lib/formatters.js +93 -1
- package/dist/lib/formatters.js.map +1 -1
- package/dist/lib/logger.d.ts +2 -0
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +4 -0
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/oauth/loopback-server.d.ts +27 -0
- package/dist/lib/oauth/loopback-server.d.ts.map +1 -0
- package/dist/lib/oauth/loopback-server.js +164 -0
- package/dist/lib/oauth/loopback-server.js.map +1 -0
- package/dist/lib/oauth/manager.d.ts +36 -0
- package/dist/lib/oauth/manager.d.ts.map +1 -0
- package/dist/lib/oauth/manager.js +130 -0
- package/dist/lib/oauth/manager.js.map +1 -0
- package/dist/lib/oauth/pkce.d.ts +15 -0
- package/dist/lib/oauth/pkce.d.ts.map +1 -0
- package/dist/lib/oauth/pkce.js +24 -0
- package/dist/lib/oauth/pkce.js.map +1 -0
- package/dist/lib/oauth/token-endpoint.d.ts +39 -0
- package/dist/lib/oauth/token-endpoint.d.ts.map +1 -0
- package/dist/lib/oauth/token-endpoint.js +117 -0
- package/dist/lib/oauth/token-endpoint.js.map +1 -0
- package/dist/lib/oauth/token-store.d.ts +34 -0
- package/dist/lib/oauth/token-store.d.ts.map +1 -0
- package/dist/lib/oauth/token-store.js +164 -0
- package/dist/lib/oauth/token-store.js.map +1 -0
- package/dist/lib/perf-diff-eval.d.ts +58 -0
- package/dist/lib/perf-diff-eval.d.ts.map +1 -0
- package/dist/lib/perf-diff-eval.js +49 -0
- package/dist/lib/perf-diff-eval.js.map +1 -0
- package/dist/lib/run-command.js +2 -2
- package/dist/lib/run-command.js.map +1 -1
- package/dist/lib/run-profile-test-lib.d.ts +156 -0
- package/dist/lib/run-profile-test-lib.d.ts.map +1 -0
- package/dist/lib/run-profile-test-lib.js +171 -0
- package/dist/lib/run-profile-test-lib.js.map +1 -0
- package/dist/lib/uploader.d.ts +14 -1
- package/dist/lib/uploader.d.ts.map +1 -1
- package/dist/lib/uploader.js +26 -12
- package/dist/lib/uploader.js.map +1 -1
- package/package.json +3 -3
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,16 +1,57 @@
|
|
|
1
|
+
import { type StoredTokenEntry } from "./oauth/token-store.js";
|
|
1
2
|
export type OutputFormat = "json" | "table" | "csv";
|
|
2
|
-
|
|
3
|
+
/** Where an API key came from (drives `framedash auth` source display). */
|
|
4
|
+
export type ApiKeySource = "flag" | "file" | "env";
|
|
5
|
+
/**
|
|
6
|
+
* The resolved credential for a run. Precedence: --api-key > --api-key-file >
|
|
7
|
+
* FRAMEDASH_API_KEY env > OAuth tokens stored by `framedash login` for the
|
|
8
|
+
* resolved base URL's origin. The OAuth variant carries the stored entry so
|
|
9
|
+
* the client starts from it without re-reading the store; the token values
|
|
10
|
+
* inside must never be logged.
|
|
11
|
+
*/
|
|
12
|
+
export type CliCredential = {
|
|
13
|
+
kind: "api-key";
|
|
3
14
|
apiKey: string;
|
|
15
|
+
source: ApiKeySource;
|
|
16
|
+
} | {
|
|
17
|
+
kind: "oauth";
|
|
18
|
+
origin: string;
|
|
19
|
+
entry: StoredTokenEntry;
|
|
20
|
+
};
|
|
21
|
+
export type CliConfig = {
|
|
22
|
+
credential: CliCredential;
|
|
4
23
|
projectId: string;
|
|
5
24
|
baseUrl: string;
|
|
6
25
|
format: OutputFormat;
|
|
7
26
|
};
|
|
27
|
+
/** Resolve --base-url/--format (and env fallbacks) for commands that need no credential. */
|
|
28
|
+
export declare function resolveBaseAndFormat(values: Record<string, unknown>): {
|
|
29
|
+
baseUrl: string;
|
|
30
|
+
format: OutputFormat;
|
|
31
|
+
};
|
|
8
32
|
/**
|
|
9
33
|
* Resolve the API key, preferring sources that keep it out of the process
|
|
10
34
|
* argument list: --api-key flag, then --api-key-file (a path, or "-" for stdin),
|
|
11
35
|
* then the FRAMEDASH_API_KEY env var. Returns undefined if none is set.
|
|
12
36
|
*/
|
|
13
37
|
export declare function resolveApiKey(values: Record<string, unknown>): string | undefined;
|
|
38
|
+
/** As resolveApiKey, but also reports WHICH source supplied the key. */
|
|
39
|
+
export declare function resolveApiKeyWithSource(values: Record<string, unknown>): {
|
|
40
|
+
apiKey: string;
|
|
41
|
+
source: ApiKeySource;
|
|
42
|
+
} | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Resolve the credential for the given base URL. API keys (flag > file > env)
|
|
45
|
+
* win over a stored OAuth login; the OAuth token store is consulted only for
|
|
46
|
+
* the resolved base URL's exact origin. Returns undefined when nothing is set.
|
|
47
|
+
*
|
|
48
|
+
* NOTE: throws a TypeError (from `new URL`) when `baseUrl` is not a valid
|
|
49
|
+
* URL and no API key short-circuits the lookup. Callers that accept raw user
|
|
50
|
+
* input for the base URL (map-capture) must validate or catch accordingly;
|
|
51
|
+
* resolveConfig* callers are safe because resolveBaseAndFormat has already
|
|
52
|
+
* vetted the URL.
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveCredential(values: Record<string, unknown>, baseUrl: string): CliCredential | undefined;
|
|
14
55
|
/** Resolve global CLI config from parsed flags and environment variables. */
|
|
15
56
|
export declare function resolveConfig(values: Record<string, unknown>): CliConfig;
|
|
16
57
|
/** Resolve config for commands that don't require --project-id (e.g. auth). */
|
package/dist/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAEhF,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAEpD,2EAA2E;AAC3E,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GACtB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAE9D,MAAM,MAAM,SAAS,GAAG;IACvB,UAAU,EAAE,aAAa,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC;CACrB,CAAC;AAMF,4FAA4F;AAC5F,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC;CACrB,CAsBA;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,CAEjF;AAED,wEAAwE;AACxE,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAAG,SAAS,CAgCtD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,MAAM,GACb,aAAa,GAAG,SAAS,CAS3B;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAgBxE;AAED,+EAA+E;AAC/E,wBAAgB,2BAA2B,CAC1C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAS9B;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOxE;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOnE;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;CAO1B,CAAC"}
|
package/dist/lib/config.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { assertSafeBaseUrl } from "@framedash/api-client";
|
|
3
3
|
import { error } from "./logger.js";
|
|
4
|
-
|
|
4
|
+
import { readStoredEntry } from "./oauth/token-store.js";
|
|
5
|
+
const NO_CREDENTIAL_MESSAGE = "No credentials found: pass --api-key/--api-key-file, set FRAMEDASH_API_KEY, " +
|
|
6
|
+
"or run 'framedash login' (interactive). CI/non-interactive use should set FRAMEDASH_API_KEY.";
|
|
7
|
+
/** Resolve --base-url/--format (and env fallbacks) for commands that need no credential. */
|
|
8
|
+
export function resolveBaseAndFormat(values) {
|
|
5
9
|
const baseUrl = values["base-url"] ??
|
|
6
10
|
process.env.FRAMEDASH_BASE_URL ??
|
|
7
11
|
"https://app.framedash.dev";
|
|
@@ -27,9 +31,13 @@ function resolveBaseAndFormat(values) {
|
|
|
27
31
|
* then the FRAMEDASH_API_KEY env var. Returns undefined if none is set.
|
|
28
32
|
*/
|
|
29
33
|
export function resolveApiKey(values) {
|
|
34
|
+
return resolveApiKeyWithSource(values)?.apiKey;
|
|
35
|
+
}
|
|
36
|
+
/** As resolveApiKey, but also reports WHICH source supplied the key. */
|
|
37
|
+
export function resolveApiKeyWithSource(values) {
|
|
30
38
|
const flag = values["api-key"];
|
|
31
39
|
if (flag)
|
|
32
|
-
return flag;
|
|
40
|
+
return { apiKey: flag, source: "flag" };
|
|
33
41
|
const file = values["api-key-file"];
|
|
34
42
|
if (file) {
|
|
35
43
|
const label = file === "-" ? "stdin" : file;
|
|
@@ -52,15 +60,38 @@ export function resolveApiKey(values) {
|
|
|
52
60
|
error(`--api-key-file (${label}) is empty`);
|
|
53
61
|
process.exit(1);
|
|
54
62
|
}
|
|
55
|
-
return key;
|
|
63
|
+
return { apiKey: key, source: "file" };
|
|
56
64
|
}
|
|
57
|
-
|
|
65
|
+
const envKey = process.env.FRAMEDASH_API_KEY;
|
|
66
|
+
return envKey ? { apiKey: envKey, source: "env" } : undefined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolve the credential for the given base URL. API keys (flag > file > env)
|
|
70
|
+
* win over a stored OAuth login; the OAuth token store is consulted only for
|
|
71
|
+
* the resolved base URL's exact origin. Returns undefined when nothing is set.
|
|
72
|
+
*
|
|
73
|
+
* NOTE: throws a TypeError (from `new URL`) when `baseUrl` is not a valid
|
|
74
|
+
* URL and no API key short-circuits the lookup. Callers that accept raw user
|
|
75
|
+
* input for the base URL (map-capture) must validate or catch accordingly;
|
|
76
|
+
* resolveConfig* callers are safe because resolveBaseAndFormat has already
|
|
77
|
+
* vetted the URL.
|
|
78
|
+
*/
|
|
79
|
+
export function resolveCredential(values, baseUrl) {
|
|
80
|
+
const key = resolveApiKeyWithSource(values);
|
|
81
|
+
if (key)
|
|
82
|
+
return { kind: "api-key", ...key };
|
|
83
|
+
const origin = new URL(baseUrl).origin;
|
|
84
|
+
const entry = readStoredEntry(origin);
|
|
85
|
+
if (entry)
|
|
86
|
+
return { kind: "oauth", origin, entry };
|
|
87
|
+
return undefined;
|
|
58
88
|
}
|
|
59
89
|
/** Resolve global CLI config from parsed flags and environment variables. */
|
|
60
90
|
export function resolveConfig(values) {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
91
|
+
const { baseUrl, format } = resolveBaseAndFormat(values);
|
|
92
|
+
const credential = resolveCredential(values, baseUrl);
|
|
93
|
+
if (!credential) {
|
|
94
|
+
error(NO_CREDENTIAL_MESSAGE);
|
|
64
95
|
process.exit(1);
|
|
65
96
|
}
|
|
66
97
|
const projectId = values["project-id"] ?? process.env.FRAMEDASH_PROJECT_ID;
|
|
@@ -68,18 +99,17 @@ export function resolveConfig(values) {
|
|
|
68
99
|
error("--project-id or FRAMEDASH_PROJECT_ID env is required");
|
|
69
100
|
process.exit(1);
|
|
70
101
|
}
|
|
71
|
-
|
|
72
|
-
return { apiKey, projectId, baseUrl, format };
|
|
102
|
+
return { credential, projectId, baseUrl, format };
|
|
73
103
|
}
|
|
74
104
|
/** Resolve config for commands that don't require --project-id (e.g. auth). */
|
|
75
105
|
export function resolveConfigWithoutProject(values) {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
106
|
+
const { baseUrl, format } = resolveBaseAndFormat(values);
|
|
107
|
+
const credential = resolveCredential(values, baseUrl);
|
|
108
|
+
if (!credential) {
|
|
109
|
+
error(NO_CREDENTIAL_MESSAGE);
|
|
79
110
|
process.exit(1);
|
|
80
111
|
}
|
|
81
|
-
|
|
82
|
-
return { apiKey, baseUrl, format };
|
|
112
|
+
return { credential, baseUrl, format };
|
|
83
113
|
}
|
|
84
114
|
/** Parse a string flag as a positive integer with a descriptive error. */
|
|
85
115
|
export function parsePositiveInt(value, flagName) {
|
package/dist/lib/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,29 @@
|
|
|
1
1
|
import { ApiClient } from "@framedash/api-client";
|
|
2
|
-
|
|
2
|
+
import type { CliCredential } from "./config.js";
|
|
3
|
+
import { OAuthTokenManager } from "./oauth/manager.js";
|
|
4
|
+
export type CreateClientOptions = {
|
|
5
|
+
throwOnError?: boolean;
|
|
6
|
+
};
|
|
7
|
+
/** Test-only: drop cached managers so each test starts from its own entry. */
|
|
8
|
+
export declare function resetOAuthManagerCacheForTests(): void;
|
|
9
|
+
/**
|
|
10
|
+
* Process-shared token manager for an origin. Also used by non-ApiClient
|
|
11
|
+
* consumers (the map-capture uploader) so EVERY Bearer credential in the
|
|
12
|
+
* process rides on the same rotation state.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getSharedOAuthManager(baseUrl: string, credential: Extract<CliCredential, {
|
|
15
|
+
kind: "oauth";
|
|
16
|
+
}>): OAuthTokenManager;
|
|
17
|
+
/**
|
|
18
|
+
* Create the CLI's API client from the resolved credential. By default a
|
|
19
|
+
* request error prints a message and exits the process (the right behavior
|
|
20
|
+
* for one-shot commands). Pass `throwOnError` for a client used inside a
|
|
21
|
+
* retry loop (e.g. the run-profile-test ingest poll), where a transient
|
|
22
|
+
* 429/5xx must be thrown and retried, not exit.
|
|
23
|
+
*
|
|
24
|
+
* API keys go on X-API-Key as before. A stored OAuth login gets a wrapper
|
|
25
|
+
* that refreshes near expiry, retries exactly once after a 401, and persists
|
|
26
|
+
* rotated refresh tokens.
|
|
27
|
+
*/
|
|
28
|
+
export declare function createClient(baseUrl: string, credential: CliCredential, projectId: string, options?: CreateClientOptions): ApiClient;
|
|
3
29
|
//# sourceMappingURL=create-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-client.d.ts","sourceRoot":"","sources":["../../src/lib/create-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"create-client.d.ts","sourceRoot":"","sources":["../../src/lib/create-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAY,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAA2B,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEhF,MAAM,MAAM,mBAAmB,GAAG;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAY7D,8EAA8E;AAC9E,wBAAgB,8BAA8B,IAAI,IAAI,CAErD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,OAAO,CAAC,aAAa,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,GACnD,iBAAiB,CAOnB;AAuBD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC3B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,aAAa,EACzB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,SAAS,CAiBX"}
|
|
@@ -1,30 +1,173 @@
|
|
|
1
|
-
import { ApiClient } from "@framedash/api-client";
|
|
1
|
+
import { ApiClient, ApiError } from "@framedash/api-client";
|
|
2
2
|
import { error } from "./logger.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
import { OAuthLoginRequiredError, OAuthTokenManager } from "./oauth/manager.js";
|
|
4
|
+
/**
|
|
5
|
+
* ONE token manager per origin per process. Refresh tokens are single-use
|
|
6
|
+
* (rotation), so two independent managers over the same stored login would
|
|
7
|
+
* race: the second to refresh presents an already-consumed token, which the
|
|
8
|
+
* server treats as theft and answers by revoking the whole grant. Commands
|
|
9
|
+
* that build several clients (e.g. run-profile-test's exit-on-error client
|
|
10
|
+
* plus its throwing poll client) must therefore share rotation state.
|
|
11
|
+
*/
|
|
12
|
+
const managerCache = new Map();
|
|
13
|
+
/** Test-only: drop cached managers so each test starts from its own entry. */
|
|
14
|
+
export function resetOAuthManagerCacheForTests() {
|
|
15
|
+
managerCache.clear();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Process-shared token manager for an origin. Also used by non-ApiClient
|
|
19
|
+
* consumers (the map-capture uploader) so EVERY Bearer credential in the
|
|
20
|
+
* process rides on the same rotation state.
|
|
21
|
+
*/
|
|
22
|
+
export function getSharedOAuthManager(baseUrl, credential) {
|
|
23
|
+
let manager = managerCache.get(credential.origin);
|
|
24
|
+
if (!manager) {
|
|
25
|
+
manager = new OAuthTokenManager(baseUrl, credential.origin, credential.entry);
|
|
26
|
+
managerCache.set(credential.origin, manager);
|
|
27
|
+
}
|
|
28
|
+
return manager;
|
|
29
|
+
}
|
|
30
|
+
/** Print an ApiError (with 429 rate-limit detail) and exit -- the default for one-shot commands. */
|
|
31
|
+
function printAndExit(err) {
|
|
32
|
+
if (err.status === 429) {
|
|
33
|
+
const retryAfter = err.retryAfter;
|
|
34
|
+
if (retryAfter !== undefined) {
|
|
35
|
+
error(`Rate limit exceeded (429). Retry after ${retryAfter}s.`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
const reset = err.headers.get("X-RateLimit-Reset");
|
|
39
|
+
const resetNum = reset ? Number(reset) : Number.NaN;
|
|
40
|
+
const resetStr = !Number.isNaN(resetNum) && resetNum > 0
|
|
41
|
+
? new Date(resetNum * 1000).toLocaleTimeString()
|
|
42
|
+
: "unknown";
|
|
43
|
+
error(`Rate limit exceeded (429). Resets at ${resetStr}.`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
error(err.message);
|
|
48
|
+
}
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Create the CLI's API client from the resolved credential. By default a
|
|
53
|
+
* request error prints a message and exits the process (the right behavior
|
|
54
|
+
* for one-shot commands). Pass `throwOnError` for a client used inside a
|
|
55
|
+
* retry loop (e.g. the run-profile-test ingest poll), where a transient
|
|
56
|
+
* 429/5xx must be thrown and retried, not exit.
|
|
57
|
+
*
|
|
58
|
+
* API keys go on X-API-Key as before. A stored OAuth login gets a wrapper
|
|
59
|
+
* that refreshes near expiry, retries exactly once after a 401, and persists
|
|
60
|
+
* rotated refresh tokens.
|
|
61
|
+
*/
|
|
62
|
+
export function createClient(baseUrl, credential, projectId, options) {
|
|
63
|
+
const onError = options?.throwOnError
|
|
64
|
+
? (err) => {
|
|
65
|
+
throw err;
|
|
66
|
+
}
|
|
67
|
+
: printAndExit;
|
|
68
|
+
if (credential.kind === "api-key") {
|
|
69
|
+
return new ApiClient({ baseUrl, apiKey: credential.apiKey, projectId, onError });
|
|
70
|
+
}
|
|
71
|
+
return new OAuthApiClient(baseUrl, projectId, getSharedOAuthManager(baseUrl, credential), options);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* ApiClient facade for the OAuth path. Extends ApiClient so the rest of the
|
|
75
|
+
* CLI (typed against ApiClient) needs no changes, but every verb delegates
|
|
76
|
+
* to a short-lived inner client carrying the CURRENT access token from the
|
|
77
|
+
* token manager; the superclass instance itself never sends a request.
|
|
78
|
+
*
|
|
79
|
+
* 401 handling: refresh once, retry once. A second failure surfaces like any
|
|
80
|
+
* other API error. A dead grant (refresh -> invalid_grant) always prints the
|
|
81
|
+
* re-login instruction and exits, even in throwOnError mode -- retry loops
|
|
82
|
+
* (which swallow thrown errors) must not spin on an unrecoverable credential.
|
|
83
|
+
*/
|
|
84
|
+
class OAuthApiClient extends ApiClient {
|
|
85
|
+
oauthBaseUrl;
|
|
86
|
+
oauthProjectId;
|
|
87
|
+
manager;
|
|
88
|
+
options;
|
|
89
|
+
constructor(oauthBaseUrl, oauthProjectId, manager, options) {
|
|
90
|
+
super({
|
|
91
|
+
baseUrl: oauthBaseUrl,
|
|
92
|
+
projectId: oauthProjectId,
|
|
93
|
+
// Never sent: all verbs are overridden to use the inner client.
|
|
94
|
+
accessToken: "oauth-managed-placeholder",
|
|
95
|
+
onError: (err) => {
|
|
96
|
+
throw err;
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
this.oauthBaseUrl = oauthBaseUrl;
|
|
100
|
+
this.oauthProjectId = oauthProjectId;
|
|
101
|
+
this.manager = manager;
|
|
102
|
+
this.options = options;
|
|
103
|
+
}
|
|
104
|
+
async get(path) {
|
|
105
|
+
return this.execute((client) => client.get(path));
|
|
106
|
+
}
|
|
107
|
+
async post(path, body) {
|
|
108
|
+
return this.execute((client) => client.post(path, body));
|
|
109
|
+
}
|
|
110
|
+
async patch(path, body) {
|
|
111
|
+
return this.execute((client) => client.patch(path, body));
|
|
112
|
+
}
|
|
113
|
+
async delete(path) {
|
|
114
|
+
return this.execute((client) => client.delete(path));
|
|
115
|
+
}
|
|
116
|
+
withProject(projectId) {
|
|
117
|
+
return new OAuthApiClient(this.oauthBaseUrl, projectId, this.manager, this.options);
|
|
118
|
+
}
|
|
119
|
+
buildInner(accessToken) {
|
|
120
|
+
return new ApiClient({
|
|
121
|
+
baseUrl: this.oauthBaseUrl,
|
|
122
|
+
projectId: this.oauthProjectId,
|
|
123
|
+
accessToken,
|
|
124
|
+
onError: (err) => {
|
|
125
|
+
throw err;
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
async token(forceRefresh) {
|
|
130
|
+
try {
|
|
131
|
+
return forceRefresh ? await this.manager.forceRefresh() : await this.manager.getAccessToken();
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
if (err instanceof OAuthLoginRequiredError) {
|
|
135
|
+
error(err.message);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
throw err;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
async execute(fn) {
|
|
142
|
+
const accessToken = await this.token(false);
|
|
143
|
+
try {
|
|
144
|
+
return await fn(this.buildInner(accessToken));
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
if (isApiError(err) && err.status === 401) {
|
|
148
|
+
// The server rejected a token we believed valid (revoked access
|
|
149
|
+
// token, clock skew): refresh and retry exactly once.
|
|
150
|
+
const freshToken = await this.token(true);
|
|
151
|
+
try {
|
|
152
|
+
return await fn(this.buildInner(freshToken));
|
|
13
153
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const resetNum = reset ? Number(reset) : Number.NaN;
|
|
17
|
-
const resetStr = !Number.isNaN(resetNum) && resetNum > 0
|
|
18
|
-
? new Date(resetNum * 1000).toLocaleTimeString()
|
|
19
|
-
: "unknown";
|
|
20
|
-
error(`Rate limit exceeded (429). Resets at ${resetStr}.`);
|
|
154
|
+
catch (retryErr) {
|
|
155
|
+
return this.reportError(retryErr);
|
|
21
156
|
}
|
|
22
157
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
158
|
+
return this.reportError(err);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
reportError(err) {
|
|
162
|
+
if (isApiError(err) && !this.options?.throwOnError) {
|
|
163
|
+
printAndExit(err);
|
|
164
|
+
}
|
|
165
|
+
// throwOnError mode, or a non-API failure (network error): propagate,
|
|
166
|
+
// matching the api-key client (index.ts prints and exits).
|
|
167
|
+
throw err;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function isApiError(err) {
|
|
171
|
+
return err instanceof ApiError;
|
|
29
172
|
}
|
|
30
173
|
//# sourceMappingURL=create-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-client.js","sourceRoot":"","sources":["../../src/lib/create-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"create-client.js","sourceRoot":"","sources":["../../src/lib/create-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAIhF;;;;;;;GAOG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,EAA6B,CAAC;AAE1D,8EAA8E;AAC9E,MAAM,UAAU,8BAA8B;IAC7C,YAAY,CAAC,KAAK,EAAE,CAAC;AACtB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACpC,OAAe,EACf,UAAqD;IAErD,IAAI,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAClD,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,OAAO,GAAG,IAAI,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;QAC9E,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,oGAAoG;AACpG,SAAS,YAAY,CAAC,GAAa;IAClC,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACxB,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC;QAClC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC9B,KAAK,CAAC,0CAA0C,UAAU,IAAI,CAAC,CAAC;QACjE,CAAC;aAAM,CAAC;YACP,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YACpD,MAAM,QAAQ,GACb,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC;gBACtC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,kBAAkB,EAAE;gBAChD,CAAC,CAAC,SAAS,CAAC;YACd,KAAK,CAAC,wCAAwC,QAAQ,GAAG,CAAC,CAAC;QAC5D,CAAC;IACF,CAAC;SAAM,CAAC;QACP,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAC3B,OAAe,EACf,UAAyB,EACzB,SAAiB,EACjB,OAA6B;IAE7B,MAAM,OAAO,GAA6B,OAAO,EAAE,YAAY;QAC9D,CAAC,CAAC,CAAC,GAAG,EAAS,EAAE;YACf,MAAM,GAAG,CAAC;QACX,CAAC;QACF,CAAC,CAAC,YAAY,CAAC;IAEhB,IAAI,UAAU,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACnC,OAAO,IAAI,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,IAAI,cAAc,CACxB,OAAO,EACP,SAAS,EACT,qBAAqB,CAAC,OAAO,EAAE,UAAU,CAAC,EAC1C,OAAO,CACP,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,cAAe,SAAQ,SAAS;IAEnB;IACA;IACA;IACA;IAJlB,YACkB,YAAoB,EACpB,cAAsB,EACtB,OAA0B,EAC1B,OAA6B;QAE9C,KAAK,CAAC;YACL,OAAO,EAAE,YAAY;YACrB,SAAS,EAAE,cAAc;YACzB,gEAAgE;YAChE,WAAW,EAAE,2BAA2B;YACxC,OAAO,EAAE,CAAC,GAAG,EAAS,EAAE;gBACvB,MAAM,GAAG,CAAC;YACX,CAAC;SACD,CAAC,CAAC;QAbc,iBAAY,GAAZ,YAAY,CAAQ;QACpB,mBAAc,GAAd,cAAc,CAAQ;QACtB,YAAO,GAAP,OAAO,CAAmB;QAC1B,YAAO,GAAP,OAAO,CAAsB;IAW/C,CAAC;IAEQ,KAAK,CAAC,GAAG,CAAc,IAAY;QAC3C,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAI,IAAI,CAAC,CAAC,CAAC;IACtD,CAAC;IAEQ,KAAK,CAAC,IAAI,CAAc,IAAY,EAAE,IAAc;QAC5D,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAI,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7D,CAAC;IAEQ,KAAK,CAAC,KAAK,CAAc,IAAY,EAAE,IAAa;QAC5D,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAI,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC9D,CAAC;IAEQ,KAAK,CAAC,MAAM,CAAc,IAAY;QAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAI,IAAI,CAAC,CAAC,CAAC;IACzD,CAAC;IAEQ,WAAW,CAAC,SAAiB;QACrC,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACrF,CAAC;IAEO,UAAU,CAAC,WAAmB;QACrC,OAAO,IAAI,SAAS,CAAC;YACpB,OAAO,EAAE,IAAI,CAAC,YAAY;YAC1B,SAAS,EAAE,IAAI,CAAC,cAAc;YAC9B,WAAW;YACX,OAAO,EAAE,CAAC,GAAG,EAAS,EAAE;gBACvB,MAAM,GAAG,CAAC;YACX,CAAC;SACD,CAAC,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,YAAqB;QACxC,IAAI,CAAC;YACJ,OAAO,YAAY,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC/F,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,GAAG,YAAY,uBAAuB,EAAE,CAAC;gBAC5C,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjB,CAAC;YACD,MAAM,GAAG,CAAC;QACX,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,OAAO,CAAI,EAAqC;QAC7D,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC;YACJ,OAAO,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC3C,gEAAgE;gBAChE,sDAAsD;gBACtD,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC1C,IAAI,CAAC;oBACJ,OAAO,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;gBAC9C,CAAC;gBAAC,OAAO,QAAQ,EAAE,CAAC;oBACnB,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;gBACnC,CAAC;YACF,CAAC;YACD,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;IACF,CAAC;IAEO,WAAW,CAAC,GAAY;QAC/B,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC;YACpD,YAAY,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QACD,sEAAsE;QACtE,2DAA2D;QAC3D,MAAM,GAAG,CAAC;IACX,CAAC;CACD;AAED,SAAS,UAAU,CAAC,GAAY;IAC/B,OAAO,GAAG,YAAY,QAAQ,CAAC;AAChC,CAAC"}
|
package/dist/lib/formatters.js
CHANGED
|
@@ -10,13 +10,105 @@ export function formatOutput(data, format) {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
function formatTable(data) {
|
|
13
|
+
// A single object whose values contain nested arrays/objects (e.g. the
|
|
14
|
+
// dashboard's { kpis, dailyActiveUsers, topEvents }) renders one titled
|
|
15
|
+
// section per key rather than a single blob-cell row. Flat arrays-of-objects
|
|
16
|
+
// (maps list, alerts list, builds) fall through to the plain table renderer
|
|
17
|
+
// unchanged.
|
|
18
|
+
if (isSectionedPayload(data)) {
|
|
19
|
+
return formatSections(data);
|
|
20
|
+
}
|
|
13
21
|
const rows = toRows(data);
|
|
14
22
|
if (rows.length === 0)
|
|
15
23
|
return "(no data)";
|
|
16
24
|
const firstRow = rows[0];
|
|
17
25
|
if (!firstRow)
|
|
18
26
|
return "(no data)";
|
|
19
|
-
|
|
27
|
+
return renderRows(rows, Object.keys(firstRow));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* True for an envelope-style object whose every field is a nested array/object
|
|
31
|
+
* (e.g. the dashboard's { kpis, dailyActiveUsers, topEvents } or status's
|
|
32
|
+
* { project, kpis }). Records that mix scalar fields with a nested one -- such as
|
|
33
|
+
* an alert row's scalars plus channelIds: [] -- stay on the plain one-row table
|
|
34
|
+
* path, so `alerts create/update --format table` output does not regress.
|
|
35
|
+
*/
|
|
36
|
+
function isSectionedPayload(data) {
|
|
37
|
+
if (Array.isArray(data))
|
|
38
|
+
return false;
|
|
39
|
+
if (typeof data !== "object" || data === null)
|
|
40
|
+
return false;
|
|
41
|
+
const values = Object.values(data);
|
|
42
|
+
if (values.length === 0)
|
|
43
|
+
return false;
|
|
44
|
+
return values.every((v) => v !== null && typeof v === "object");
|
|
45
|
+
}
|
|
46
|
+
/** Render each top-level key of a sectioned payload as a titled sub-table. */
|
|
47
|
+
function formatSections(obj) {
|
|
48
|
+
const sections = Object.entries(obj).map(([key, value]) => {
|
|
49
|
+
let table;
|
|
50
|
+
if (Array.isArray(value)) {
|
|
51
|
+
table = formatArraySection(value);
|
|
52
|
+
}
|
|
53
|
+
else if (value !== null && typeof value === "object") {
|
|
54
|
+
table = formatObjectSection(value);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
table = cellString(value);
|
|
58
|
+
}
|
|
59
|
+
return `## ${key}\n${table}`;
|
|
60
|
+
});
|
|
61
|
+
return sections.join("\n\n");
|
|
62
|
+
}
|
|
63
|
+
/** An array-of-objects section: normal table, nested objects flattened to dot-paths. */
|
|
64
|
+
function formatArraySection(arr) {
|
|
65
|
+
if (arr.length === 0)
|
|
66
|
+
return "(no data)";
|
|
67
|
+
const rows = arr.map((item) => typeof item === "object" && item !== null && !Array.isArray(item)
|
|
68
|
+
? flattenOneLevel(item)
|
|
69
|
+
: { value: item });
|
|
70
|
+
return renderRows(rows, unionKeys(rows));
|
|
71
|
+
}
|
|
72
|
+
/** An object section: two-column key/value rows. */
|
|
73
|
+
function formatObjectSection(obj) {
|
|
74
|
+
const rows = Object.entries(obj).map(([key, value]) => ({ key, value }));
|
|
75
|
+
if (rows.length === 0)
|
|
76
|
+
return "(no data)";
|
|
77
|
+
return renderRows(rows, ["key", "value"]);
|
|
78
|
+
}
|
|
79
|
+
/** Flatten one level of nested objects into dot-path keys; deeper nesting stays JSON. */
|
|
80
|
+
function flattenOneLevel(row) {
|
|
81
|
+
const out = {};
|
|
82
|
+
for (const [key, value] of Object.entries(row)) {
|
|
83
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
84
|
+
for (const [subKey, subValue] of Object.entries(value)) {
|
|
85
|
+
out[`${key}.${subKey}`] = subValue;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
out[key] = value;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
/** Union of row keys in first-seen order. */
|
|
95
|
+
function unionKeys(rows) {
|
|
96
|
+
const seen = new Set();
|
|
97
|
+
const keys = [];
|
|
98
|
+
for (const row of rows) {
|
|
99
|
+
for (const key of Object.keys(row)) {
|
|
100
|
+
if (!seen.has(key)) {
|
|
101
|
+
seen.add(key);
|
|
102
|
+
keys.push(key);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return keys;
|
|
107
|
+
}
|
|
108
|
+
/** Render aligned columns for the given rows/keys using cellString for each cell. */
|
|
109
|
+
function renderRows(rows, keys) {
|
|
110
|
+
if (rows.length === 0 || keys.length === 0)
|
|
111
|
+
return "(no data)";
|
|
20
112
|
const widths = keys.map((k) => Math.max(k.length, ...rows.map((r) => cellString(r[k]).length)));
|
|
21
113
|
const header = keys.map((k, i) => k.padEnd(widths[i] ?? k.length)).join(" ");
|
|
22
114
|
const separator = widths.map((w) => "-".repeat(w)).join(" ");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../src/lib/formatters.ts"],"names":[],"mappings":"AAEA,0DAA0D;AAC1D,MAAM,UAAU,YAAY,CAAC,IAAa,EAAE,MAAoB;IAC/D,QAAQ,MAAM,EAAE,CAAC;QAChB,KAAK,MAAM;YACV,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACtC,KAAK,OAAO;YACX,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;QAC1B,KAAK,KAAK;YACT,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;AACF,CAAC;AAED,SAAS,WAAW,CAAC,IAAa;IACjC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,WAAW,CAAC;IAE1C,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,CAAC,QAAQ;QAAE,OAAO,WAAW,CAAC;IAElC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../src/lib/formatters.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/logger.d.ts
CHANGED
|
@@ -5,5 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export declare function log(message: string): void;
|
|
7
7
|
export declare function success(message: string): void;
|
|
8
|
+
/** Non-fatal warning (the run still exits 0). */
|
|
9
|
+
export declare function warn(message: string): void;
|
|
8
10
|
export declare function error(message: string): void;
|
|
9
11
|
//# sourceMappingURL=logger.d.ts.map
|
package/dist/lib/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEzC;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3C"}
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEzC;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,iDAAiD;AACjD,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3C"}
|
package/dist/lib/logger.js
CHANGED
|
@@ -9,6 +9,10 @@ export function log(message) {
|
|
|
9
9
|
export function success(message) {
|
|
10
10
|
process.stderr.write(` \u2713 ${message}\n`);
|
|
11
11
|
}
|
|
12
|
+
/** Non-fatal warning (the run still exits 0). */
|
|
13
|
+
export function warn(message) {
|
|
14
|
+
process.stderr.write(` ! ${message}\n`);
|
|
15
|
+
}
|
|
12
16
|
export function error(message) {
|
|
13
17
|
process.stderr.write(` \u2717 ${message}\n`);
|
|
14
18
|
}
|
package/dist/lib/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,UAAU,GAAG,CAAC,OAAe;IAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,OAAe;IACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,OAAO,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,OAAe;IACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,OAAO,IAAI,CAAC,CAAC;AAC/C,CAAC"}
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,UAAU,GAAG,CAAC,OAAe;IAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,OAAe;IACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,OAAO,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,IAAI,CAAC,OAAe;IACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,OAAO,IAAI,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,OAAe;IACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,OAAO,IAAI,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The authorization server bounced back an OAuth error (e.g. the user hit
|
|
3
|
+
* Deny -> access_denied). Distinguished from local failures so the CLI can
|
|
4
|
+
* present it as a normal outcome rather than a bug.
|
|
5
|
+
*/
|
|
6
|
+
export declare class OAuthCallbackError extends Error {
|
|
7
|
+
readonly code: string;
|
|
8
|
+
constructor(code: string, description: string | null);
|
|
9
|
+
}
|
|
10
|
+
export type LoopbackServer = {
|
|
11
|
+
/** The ephemeral port actually bound on 127.0.0.1. */
|
|
12
|
+
port: number;
|
|
13
|
+
/** The exact redirect URI to register in the authorize request. */
|
|
14
|
+
redirectUri: string;
|
|
15
|
+
/** Resolve with the authorization code, or reject on error/timeout. */
|
|
16
|
+
waitForCallback: (timeoutMs: number) => Promise<{
|
|
17
|
+
code: string;
|
|
18
|
+
}>;
|
|
19
|
+
close: () => Promise<void>;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Start the loopback callback receiver. `expectedState` is the CSRF state
|
|
23
|
+
* minted for this login attempt; only a /callback request carrying exactly
|
|
24
|
+
* that state can complete the flow.
|
|
25
|
+
*/
|
|
26
|
+
export declare function startLoopbackServer(expectedState: string): Promise<LoopbackServer>;
|
|
27
|
+
//# sourceMappingURL=loopback-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loopback-server.d.ts","sourceRoot":"","sources":["../../../src/lib/oauth/loopback-server.ts"],"names":[],"mappings":"AAiCA;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;aAE3B,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM,EAC5B,WAAW,EAAE,MAAM,GAAG,IAAI;CAK3B;AAWD,MAAM,MAAM,cAAc,GAAG;IAC5B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CA+HlF"}
|