@arizeai/phoenix-cli 0.10.1 → 0.11.1
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/build/banner.d.ts +23 -2
- package/build/banner.d.ts.map +1 -1
- package/build/banner.js +35 -13
- package/build/banner.js.map +1 -1
- package/build/cli.d.ts +5 -1
- package/build/cli.d.ts.map +1 -1
- package/build/cli.js +12 -5
- package/build/cli.js.map +1 -1
- package/build/commands/api.d.ts +15 -0
- package/build/commands/api.d.ts.map +1 -1
- package/build/commands/api.js +58 -14
- package/build/commands/api.js.map +1 -1
- package/build/commands/prompt.js +1 -1
- package/build/curl.d.ts +13 -0
- package/build/curl.d.ts.map +1 -0
- package/build/curl.js +49 -0
- package/build/curl.js.map +1 -0
- package/build/index.js +7 -1
- package/build/index.js.map +1 -1
- package/build/version.d.ts +44 -0
- package/build/version.d.ts.map +1 -0
- package/build/version.js +171 -0
- package/build/version.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -299,6 +299,22 @@ Make authenticated GraphQL queries against the Phoenix API. Output is `{"data":
|
|
|
299
299
|
px api graphql '<query>' [--endpoint <url>] [--api-key <key>]
|
|
300
300
|
```
|
|
301
301
|
|
|
302
|
+
Preview the exact HTTP request as `curl` without executing it:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
px api graphql '{ projects { edges { node { name } } } }' --curl
|
|
306
|
+
px api graphql '{ projects { edges { node { name } } } }' --curl --show-token
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
`--curl` prints the equivalent request to stdout and exits without making a network call. Authorization headers are masked by default, including values supplied through `PHOENIX_API_KEY` or `PHOENIX_CLIENT_HEADERS`. Use `--show-token` only when you explicitly need the raw credential in the generated command.
|
|
310
|
+
|
|
311
|
+
Current scope and behavior:
|
|
312
|
+
|
|
313
|
+
- `--curl` is currently implemented for `px api graphql` only.
|
|
314
|
+
- `--curl` prints the request without executing it.
|
|
315
|
+
- `--show-token` is only valid with `--curl`.
|
|
316
|
+
- Authorization masking and header normalization are designed to match the live request behavior used by `fetch`.
|
|
317
|
+
|
|
302
318
|
Use introspection to discover what fields are available:
|
|
303
319
|
|
|
304
320
|
```bash
|
package/build/banner.d.ts
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Text shown below the Phoenix logo.
|
|
3
3
|
*/
|
|
4
|
-
export
|
|
4
|
+
export interface BannerInfoLinesOptions {
|
|
5
|
+
serverUrl: string;
|
|
6
|
+
project: string;
|
|
7
|
+
hasApiKey: boolean;
|
|
8
|
+
currentVersion: string;
|
|
9
|
+
latestVersion?: string;
|
|
10
|
+
hasUpdate?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Build the informational text displayed below the Phoenix logo.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getBannerInfoLines({ serverUrl, project, hasApiKey, currentVersion, latestVersion, hasUpdate, }: BannerInfoLinesOptions): string[];
|
|
16
|
+
/**
|
|
17
|
+
* Render the full banner with the logo first and metadata below it.
|
|
18
|
+
*/
|
|
19
|
+
export declare function renderBanner({ infoLines }: {
|
|
20
|
+
infoLines: string[];
|
|
21
|
+
}): string;
|
|
22
|
+
/**
|
|
23
|
+
* Print the Phoenix CLI banner with connection and update info aligned to the right of the logo.
|
|
24
|
+
*/
|
|
25
|
+
export declare function printBanner(): Promise<void>;
|
|
5
26
|
//# sourceMappingURL=banner.d.ts.map
|
package/build/banner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"banner.d.ts","sourceRoot":"","sources":["../src/banner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"banner.d.ts","sourceRoot":"","sources":["../src/banner.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,SAAS,EACT,OAAO,EACP,SAAS,EACT,cAAc,EACd,aAAa,EACb,SAAS,GACV,EAAE,sBAAsB,GAAG,MAAM,EAAE,CAYnC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,MAAM,CAE3E;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAcjD"}
|
package/build/banner.js
CHANGED
|
@@ -1,27 +1,49 @@
|
|
|
1
1
|
import { loadConfigFromEnvironment } from "./config.js";
|
|
2
2
|
import { writeOutput } from "./io.js";
|
|
3
|
+
import { getCliVersionStatus } from "./version.js";
|
|
3
4
|
const LOGO_LINES = [
|
|
4
5
|
"░█▀█░█░█░█▀█░█▀▀░█▀█░▀█▀░█░█",
|
|
5
6
|
"░█▀▀░█▀█░█░█░█▀▀░█░█░░█░░▄▀▄",
|
|
6
7
|
"░▀░░░▀░▀░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀░▀",
|
|
7
8
|
];
|
|
9
|
+
const TAGLINE = "CLI for interacting with your phoenix server";
|
|
8
10
|
/**
|
|
9
|
-
*
|
|
11
|
+
* Build the informational text displayed below the Phoenix logo.
|
|
10
12
|
*/
|
|
11
|
-
export function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
`
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
export function getBannerInfoLines({ serverUrl, project, hasApiKey, currentVersion, latestVersion, hasUpdate, }) {
|
|
14
|
+
return [
|
|
15
|
+
`Server: ${serverUrl}`,
|
|
16
|
+
`Project: ${project}`,
|
|
17
|
+
...(hasApiKey ? [`API Key: set`] : []),
|
|
18
|
+
`Version: v${currentVersion}`,
|
|
19
|
+
...(hasUpdate && latestVersion
|
|
20
|
+
? [
|
|
21
|
+
`Update: v${latestVersion} available. Run npm install -g @arizeai/phoenix-cli`,
|
|
22
|
+
]
|
|
23
|
+
: []),
|
|
19
24
|
];
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Render the full banner with the logo first and metadata below it.
|
|
28
|
+
*/
|
|
29
|
+
export function renderBanner({ infoLines }) {
|
|
30
|
+
return [...LOGO_LINES, "", TAGLINE, "", ...infoLines].join("\n");
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Print the Phoenix CLI banner with connection and update info aligned to the right of the logo.
|
|
34
|
+
*/
|
|
35
|
+
export async function printBanner() {
|
|
36
|
+
const config = loadConfigFromEnvironment();
|
|
37
|
+
const versionStatus = await getCliVersionStatus();
|
|
38
|
+
const infoLines = getBannerInfoLines({
|
|
39
|
+
serverUrl: config.endpoint ?? "not set",
|
|
40
|
+
project: config.project ?? "not set",
|
|
41
|
+
hasApiKey: Boolean(config.apiKey),
|
|
42
|
+
currentVersion: versionStatus.currentVersion,
|
|
43
|
+
latestVersion: versionStatus.latestVersion,
|
|
44
|
+
hasUpdate: versionStatus.hasUpdate,
|
|
23
45
|
});
|
|
24
|
-
writeOutput({ message:
|
|
46
|
+
writeOutput({ message: renderBanner({ infoLines }) });
|
|
25
47
|
writeOutput({ message: "" });
|
|
26
48
|
}
|
|
27
49
|
//# sourceMappingURL=banner.js.map
|
package/build/banner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"banner.js","sourceRoot":"","sources":["../src/banner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"banner.js","sourceRoot":"","sources":["../src/banner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,UAAU,GAAG;IACjB,8BAA8B;IAC9B,8BAA8B;IAC9B,8BAA8B;CAC/B,CAAC;AACF,MAAM,OAAO,GAAG,8CAA8C,CAAC;AAc/D;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,EACjC,SAAS,EACT,OAAO,EACP,SAAS,EACT,cAAc,EACd,aAAa,EACb,SAAS,GACc;IACvB,OAAO;QACL,YAAY,SAAS,EAAE;QACvB,YAAY,OAAO,EAAE;QACrB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtC,aAAa,cAAc,EAAE;QAC7B,GAAG,CAAC,SAAS,IAAI,aAAa;YAC5B,CAAC,CAAC;gBACE,aAAa,aAAa,qDAAqD;aAChF;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,SAAS,EAA2B;IACjE,OAAO,CAAC,GAAG,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,yBAAyB,EAAE,CAAC;IAC3C,MAAM,aAAa,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAClD,MAAM,SAAS,GAAG,kBAAkB,CAAC;QACnC,SAAS,EAAE,MAAM,CAAC,QAAQ,IAAI,SAAS;QACvC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,SAAS;QACpC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;QACjC,cAAc,EAAE,aAAa,CAAC,cAAc;QAC5C,aAAa,EAAE,aAAa,CAAC,aAAa;QAC1C,SAAS,EAAE,aAAa,CAAC,SAAS;KACnC,CAAC,CAAC;IAEH,WAAW,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;IACtD,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;AAC/B,CAAC"}
|
package/build/cli.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
export declare function createProgram(): Command;
|
|
4
|
+
export declare function main({ argv, }?: {
|
|
5
|
+
argv?: string[];
|
|
6
|
+
}): Promise<void>;
|
|
3
7
|
//# sourceMappingURL=cli.d.ts.map
|
package/build/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBpC,wBAAgB,aAAa,IAAI,OAAO,CA0BvC;AAGD,wBAAsB,IAAI,CAAC,EACzB,IAAmB,GACpB,GAAE;IACD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACZ,GAAG,OAAO,CAAC,IAAI,CAAC,CAWrB"}
|
package/build/cli.js
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import { printBanner } from "./banner.js";
|
|
4
4
|
import { createAnnotationConfigCommand, createApiCommand, createAuthCommand, createDatasetCommand, createDatasetsCommand, createDocsCommand, createExperimentCommand, createExperimentsCommand, createProjectsCommand, createPromptCommand, createPromptsCommand, createSessionCommand, createSessionsCommand, createSpansCommand, createTraceCommand, createTracesCommand, } from "./commands/index.js";
|
|
5
|
-
|
|
6
|
-
export function
|
|
5
|
+
import { CLI_VERSION } from "./version.js";
|
|
6
|
+
export function createProgram() {
|
|
7
7
|
const program = new Command();
|
|
8
8
|
program.name("px");
|
|
9
9
|
program.enablePositionalOptions();
|
|
10
|
+
program.version(CLI_VERSION);
|
|
10
11
|
// Register commands
|
|
11
12
|
program.addCommand(createAnnotationConfigCommand());
|
|
12
13
|
program.addCommand(createAuthCommand());
|
|
@@ -24,11 +25,17 @@ export function main() {
|
|
|
24
25
|
program.addCommand(createPromptCommand());
|
|
25
26
|
program.addCommand(createApiCommand());
|
|
26
27
|
program.addCommand(createDocsCommand());
|
|
28
|
+
return program;
|
|
29
|
+
}
|
|
30
|
+
// Phoenix CLI Main Logic
|
|
31
|
+
export async function main({ argv = process.argv, } = {}) {
|
|
32
|
+
const program = createProgram();
|
|
27
33
|
// Show banner and help if no command provided
|
|
28
|
-
if (
|
|
29
|
-
printBanner();
|
|
34
|
+
if (argv.length === 2) {
|
|
35
|
+
await printBanner();
|
|
30
36
|
program.help();
|
|
37
|
+
return;
|
|
31
38
|
}
|
|
32
|
-
program.
|
|
39
|
+
await program.parseAsync(argv);
|
|
33
40
|
}
|
|
34
41
|
//# sourceMappingURL=cli.js.map
|
package/build/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAClC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAE7B,oBAAoB;IACpB,OAAO,CAAC,UAAU,CAAC,6BAA6B,EAAE,CAAC,CAAC;IACpD,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACxC,OAAO,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC1C,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,UAAU,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAC3C,OAAO,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,UAAU,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAC3C,OAAO,CAAC,UAAU,CAAC,wBAAwB,EAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,UAAU,CAAC,uBAAuB,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,UAAU,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAC3C,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC1C,OAAO,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACvC,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAExC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,yBAAyB;AACzB,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,EACzB,IAAI,GAAG,OAAO,CAAC,IAAI,MAGjB,EAAE;IACJ,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAEhC,8CAA8C;IAC9C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,WAAW,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IAED,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC"}
|
package/build/commands/api.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
+
import type { PhoenixConfig } from "../config.js";
|
|
2
3
|
/**
|
|
3
4
|
* Returns true if the query string is a GraphQL mutation or subscription.
|
|
4
5
|
* Strips # comments first to avoid false positives.
|
|
@@ -6,5 +7,19 @@ import { Command } from "commander";
|
|
|
6
7
|
export declare function isNonQuery({ query }: {
|
|
7
8
|
query: string;
|
|
8
9
|
}): boolean;
|
|
10
|
+
export interface ApiGraphqlRequest {
|
|
11
|
+
url: string;
|
|
12
|
+
method: "POST";
|
|
13
|
+
headers: Record<string, string>;
|
|
14
|
+
body: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Builds the exact outbound GraphQL request used by both live execution and
|
|
18
|
+
* `--curl` preview mode so the two paths cannot drift apart.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildGraphqlRequest({ query, config, }: {
|
|
21
|
+
query: string;
|
|
22
|
+
config: PhoenixConfig;
|
|
23
|
+
}): ApiGraphqlRequest;
|
|
9
24
|
export declare function createApiCommand(): Command;
|
|
10
25
|
//# sourceMappingURL=api.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/commands/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/commands/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAM/C;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAGhE;AASD,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,MAAM,GACP,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,aAAa,CAAC;CACvB,GAAG,iBAAiB,CAepB;AA6ID,wBAAgB,gBAAgB,IAAI,OAAO,CAK1C"}
|
package/build/commands/api.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import { getConfigErrorMessage, resolveConfig } from "../config.js";
|
|
3
|
+
import { renderCurlCommand } from "../curl.js";
|
|
3
4
|
import { ExitCode, getExitCodeForError } from "../exitCodes.js";
|
|
4
5
|
import { writeError, writeOutput } from "../io.js";
|
|
5
6
|
/**
|
|
@@ -10,8 +11,33 @@ export function isNonQuery({ query }) {
|
|
|
10
11
|
const stripped = query.replace(/#[^\n]*/g, "");
|
|
11
12
|
return /^\s*(mutation|subscription)[\s({]/m.test(stripped);
|
|
12
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Builds the exact outbound GraphQL request used by both live execution and
|
|
16
|
+
* `--curl` preview mode so the two paths cannot drift apart.
|
|
17
|
+
*/
|
|
18
|
+
export function buildGraphqlRequest({ query, config, }) {
|
|
19
|
+
const headers = {
|
|
20
|
+
"Content-Type": "application/json",
|
|
21
|
+
...(config.headers ?? {}),
|
|
22
|
+
};
|
|
23
|
+
if (config.apiKey) {
|
|
24
|
+
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
url: `${config.endpoint?.replace(/\/$/, "")}/graphql`,
|
|
28
|
+
method: "POST",
|
|
29
|
+
headers,
|
|
30
|
+
body: JSON.stringify({ query }),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
13
33
|
async function apiGraphqlHandler(query, options) {
|
|
14
34
|
try {
|
|
35
|
+
if (options.showToken && !options.curl) {
|
|
36
|
+
writeError({
|
|
37
|
+
message: "Error: --show-token can only be used with --curl.",
|
|
38
|
+
});
|
|
39
|
+
process.exit(ExitCode.INVALID_ARGUMENT);
|
|
40
|
+
}
|
|
15
41
|
// 1. Reject mutations and subscriptions
|
|
16
42
|
if (isNonQuery({ query })) {
|
|
17
43
|
writeError({
|
|
@@ -33,24 +59,31 @@ async function apiGraphqlHandler(query, options) {
|
|
|
33
59
|
});
|
|
34
60
|
process.exit(ExitCode.INVALID_ARGUMENT);
|
|
35
61
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
62
|
+
const request = buildGraphqlRequest({
|
|
63
|
+
query,
|
|
64
|
+
config,
|
|
65
|
+
});
|
|
66
|
+
if (options.curl) {
|
|
67
|
+
writeOutput({
|
|
68
|
+
message: renderCurlCommand({
|
|
69
|
+
method: request.method,
|
|
70
|
+
url: request.url,
|
|
71
|
+
headers: request.headers,
|
|
72
|
+
body: request.body,
|
|
73
|
+
maskTokens: !options.showToken,
|
|
74
|
+
}),
|
|
75
|
+
});
|
|
76
|
+
return;
|
|
44
77
|
}
|
|
45
78
|
// 4. POST using Node 22 built-in fetch
|
|
46
|
-
const response = await fetch(
|
|
47
|
-
method:
|
|
48
|
-
headers,
|
|
49
|
-
body:
|
|
79
|
+
const response = await fetch(request.url, {
|
|
80
|
+
method: request.method,
|
|
81
|
+
headers: request.headers,
|
|
82
|
+
body: request.body,
|
|
50
83
|
});
|
|
51
84
|
if (!response.ok) {
|
|
52
85
|
writeError({
|
|
53
|
-
message: `Error: HTTP ${response.status} ${response.statusText} from ${
|
|
86
|
+
message: `Error: HTTP ${response.status} ${response.statusText} from ${request.url}`,
|
|
54
87
|
});
|
|
55
88
|
if (response.status === 401 || response.status === 403) {
|
|
56
89
|
process.exit(ExitCode.AUTH_REQUIRED);
|
|
@@ -92,10 +125,21 @@ function createApiGraphqlCommand() {
|
|
|
92
125
|
"\n" +
|
|
93
126
|
" # Pipe to jq to extract fields\n" +
|
|
94
127
|
" px api graphql '{ projects { edges { node { name } } } }' | \\\n" +
|
|
95
|
-
" jq '.data.projects.edges[].node.name'"
|
|
128
|
+
" jq '.data.projects.edges[].node.name'\n" +
|
|
129
|
+
"\n" +
|
|
130
|
+
" # Print the equivalent curl command without executing it\n" +
|
|
131
|
+
" px api graphql '{ projects { edges { node { name } } } }' --curl\n" +
|
|
132
|
+
"\n" +
|
|
133
|
+
" # Reveal the raw token in curl output\n" +
|
|
134
|
+
" px api graphql '{ projects { edges { node { name } } } }' --curl --show-token\n" +
|
|
135
|
+
"\n" +
|
|
136
|
+
" Curl mode prints the request without executing it.\n" +
|
|
137
|
+
" Auth tokens are masked by default. Use --show-token with --curl to reveal them.")
|
|
96
138
|
.argument("<query>", "GraphQL query string")
|
|
97
139
|
.option("--endpoint <url>", "Phoenix API endpoint (or set PHOENIX_HOST)")
|
|
98
140
|
.option("--api-key <key>", "Phoenix API key (or set PHOENIX_API_KEY)")
|
|
141
|
+
.option("--curl", "Print the equivalent curl command instead of executing the request")
|
|
142
|
+
.option("--show-token", "Show the raw Authorization token in curl output (requires --curl)")
|
|
99
143
|
.action(apiGraphqlHandler);
|
|
100
144
|
}
|
|
101
145
|
export function createApiCommand() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/commands/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/commands/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEhD;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,EAAE,KAAK,EAAqB;IACrD,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC/C,OAAO,oCAAoC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC7D,CAAC;AAgBD;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,KAAK,EACL,MAAM,GAIP;IACC,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;KAC1B,CAAC;IACF,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,CAAC,MAAM,EAAE,CAAC;IACvD,CAAC;IAED,OAAO;QACL,GAAG,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU;QACrD,MAAM,EAAE,MAAM;QACd,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;KAChC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,iBAAiB,CAC9B,KAAa,EACb,OAA0B;IAE1B,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACvC,UAAU,CAAC;gBACT,OAAO,EAAE,mDAAmD;aAC7D,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QAC1C,CAAC;QAED,wCAAwC;QACxC,IAAI,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YAC1B,UAAU,CAAC;gBACT,OAAO,EACL,iFAAiF;aACpF,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QAC1C,CAAC;QAED,0DAA0D;QAC1D,MAAM,MAAM,GAAG,aAAa,CAAC;YAC3B,UAAU,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;SACnE,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrB,UAAU,CAAC;gBACT,OAAO,EAAE,qBAAqB,CAAC;oBAC7B,MAAM,EAAE;wBACN,gGAAgG;qBACjG;iBACF,CAAC;aACH,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QAC1C,CAAC;QAED,MAAM,OAAO,GAAG,mBAAmB,CAAC;YAClC,KAAK;YACL,MAAM;SACP,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,WAAW,CAAC;gBACV,OAAO,EAAE,iBAAiB,CAAC;oBACzB,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,GAAG,EAAE,OAAO,CAAC,GAAG;oBAChB,OAAO,EAAE,OAAO,CAAC,OAAO;oBACxB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,UAAU,EAAE,CAAC,OAAO,CAAC,SAAS;iBAC/B,CAAC;aACH,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,uCAAuC;QACvC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;YACxC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,UAAU,CAAC;gBACT,OAAO,EAAE,eAAe,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,SAAS,OAAO,CAAC,GAAG,EAAE;aACrF,CAAC,CAAC;YACH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACvD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;YACvC,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;QAED,+BAA+B;QAC/B,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAGlC,CAAC;QAEF,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnE,UAAU,CAAC,EAAE,OAAO,EAAE,oBAAoB,IAAI,EAAE,EAAE,CAAC,CAAC;QACtD,CAAC;QAED,kEAAkE;QAClE,WAAW,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAExD,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;YAC/D,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,UAAU,CAAC;YACT,OAAO,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SAC5E,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB;IAC9B,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC;SAC1B,WAAW,CACV,oDAAoD;QAClD,IAAI;QACJ,0DAA0D;QAC1D,IAAI;QACJ,eAAe;QACf,IAAI;QACJ,4BAA4B;QAC5B,iEAAiE;QACjE,IAAI;QACJ,uBAAuB;QACvB,2EAA2E;QAC3E,IAAI;QACJ,sCAAsC;QACtC,sEAAsE;QACtE,+CAA+C;QAC/C,IAAI;QACJ,gEAAgE;QAChE,wEAAwE;QACxE,IAAI;QACJ,6CAA6C;QAC7C,qFAAqF;QACrF,IAAI;QACJ,wDAAwD;QACxD,mFAAmF,CACtF;SACA,QAAQ,CAAC,SAAS,EAAE,sBAAsB,CAAC;SAC3C,MAAM,CAAC,kBAAkB,EAAE,4CAA4C,CAAC;SACxE,MAAM,CAAC,iBAAiB,EAAE,0CAA0C,CAAC;SACrE,MAAM,CACL,QAAQ,EACR,oEAAoE,CACrE;SACA,MAAM,CACL,cAAc,EACd,mEAAmE,CACpE;SACA,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,CAAC,WAAW,CAAC,gDAAgD,CAAC,CAAC;IACtE,OAAO,CAAC,UAAU,CAAC,uBAAuB,EAAE,CAAC,CAAC;IAC9C,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/build/commands/prompt.js
CHANGED
|
@@ -97,7 +97,7 @@ export function createPromptCommand() {
|
|
|
97
97
|
const command = new Command("prompt");
|
|
98
98
|
command
|
|
99
99
|
.description("Show a Phoenix prompt")
|
|
100
|
-
.argument("<
|
|
100
|
+
.argument("<prompt-identifier>", "Prompt name or ID")
|
|
101
101
|
.option("--endpoint <url>", "Phoenix API endpoint")
|
|
102
102
|
.option("--api-key <key>", "Phoenix API key for authentication")
|
|
103
103
|
.option("--format <format>", "Output format: pretty, json, raw, or text", "pretty")
|
package/build/curl.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface RenderCurlCommandOptions {
|
|
2
|
+
method: string;
|
|
3
|
+
url: string;
|
|
4
|
+
headers: Record<string, string>;
|
|
5
|
+
body?: string;
|
|
6
|
+
maskTokens: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Renders a pipe-friendly multiline curl command that matches the request
|
|
10
|
+
* Phoenix CLI would send over `fetch`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function renderCurlCommand({ method, url, headers, body, maskTokens, }: RenderCurlCommandOptions): string;
|
|
13
|
+
//# sourceMappingURL=curl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curl.d.ts","sourceRoot":"","sources":["../src/curl.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,OAAO,CAAC;CACrB;AAqDD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,GAAG,EACH,OAAO,EACP,IAAI,EACJ,UAAU,GACX,EAAE,wBAAwB,GAAG,MAAM,CAkBnC"}
|
package/build/curl.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { obscureApiKey } from "./commands/auth.js";
|
|
2
|
+
function shellEscape(value) {
|
|
3
|
+
return "'" + value.replace(/'/g, "'\"'\"'") + "'";
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Normalize headers through the platform `Headers` implementation so curl
|
|
7
|
+
* output mirrors how `fetch` combines duplicate logical headers such as
|
|
8
|
+
* `authorization` + `Authorization`.
|
|
9
|
+
*/
|
|
10
|
+
function normalizeHeaders(headers) {
|
|
11
|
+
const normalizedHeaders = new Headers();
|
|
12
|
+
const headerNames = new Map();
|
|
13
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
14
|
+
normalizedHeaders.append(key, value);
|
|
15
|
+
headerNames.set(key.toLowerCase(), headerNames.get(key.toLowerCase()) ?? key);
|
|
16
|
+
}
|
|
17
|
+
return Array.from(normalizedHeaders.entries()).map(([key, value]) => [
|
|
18
|
+
headerNames.get(key) ?? key,
|
|
19
|
+
value,
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
function maskHeaderValue({ key, value, maskTokens, }) {
|
|
23
|
+
if (!maskTokens || key.toLowerCase() !== "authorization") {
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
const match = value.match(/^(\S+)\s+(.+)$/);
|
|
27
|
+
if (match) {
|
|
28
|
+
const [, prefix, token] = match;
|
|
29
|
+
return `${prefix} ${obscureApiKey(token)}`;
|
|
30
|
+
}
|
|
31
|
+
return obscureApiKey(value);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Renders a pipe-friendly multiline curl command that matches the request
|
|
35
|
+
* Phoenix CLI would send over `fetch`.
|
|
36
|
+
*/
|
|
37
|
+
export function renderCurlCommand({ method, url, headers, body, maskTokens, }) {
|
|
38
|
+
const lines = ["curl \\"];
|
|
39
|
+
lines.push(` -X ${method.toUpperCase()} \\`);
|
|
40
|
+
for (const [key, value] of normalizeHeaders(headers)) {
|
|
41
|
+
lines.push(` -H ${shellEscape(`${key}: ${maskHeaderValue({ key, value, maskTokens })}`)} \\`);
|
|
42
|
+
}
|
|
43
|
+
if (body !== undefined) {
|
|
44
|
+
lines.push(` --data-raw ${shellEscape(body)} \\`);
|
|
45
|
+
}
|
|
46
|
+
lines.push(` ${shellEscape(url)}`);
|
|
47
|
+
return lines.join("\n");
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=curl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curl.js","sourceRoot":"","sources":["../src/curl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAUhD,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,GAAG,GAAG,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,SAAS,gBAAgB,CACvB,OAA+B;IAE/B,MAAM,iBAAiB,GAAG,IAAI,OAAO,EAAE,CAAC;IACxC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE9C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,iBAAiB,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrC,WAAW,CAAC,GAAG,CACb,GAAG,CAAC,WAAW,EAAE,EACjB,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,IAAI,GAAG,CAC1C,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC;QACnE,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG;QAC3B,KAAK;KACN,CAAC,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CAAC,EACvB,GAAG,EACH,KAAK,EACL,UAAU,GAKX;IACC,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,eAAe,EAAE,CAAC;QACzD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAC5C,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC;QAChC,OAAO,GAAG,MAAM,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;IAC7C,CAAC;IAED,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAChC,MAAM,EACN,GAAG,EACH,OAAO,EACP,IAAI,EACJ,UAAU,GACe;IACzB,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC,CAAC;IAE1B,KAAK,CAAC,IAAI,CAAC,QAAQ,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAE9C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;QACrD,KAAK,CAAC,IAAI,CACR,QAAQ,WAAW,CAAC,GAAG,GAAG,KAAK,eAAe,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,KAAK,CACnF,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,gBAAgB,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAK,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEpC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
package/build/index.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Phoenix CLI Entry Point
|
|
3
3
|
import { main } from "./cli.js";
|
|
4
|
+
import { writeError } from "./io.js";
|
|
4
5
|
// Run CLI when executed directly
|
|
5
|
-
main()
|
|
6
|
+
void main().catch((error) => {
|
|
7
|
+
writeError({
|
|
8
|
+
message: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
9
|
+
});
|
|
10
|
+
process.exit(1);
|
|
11
|
+
});
|
|
6
12
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,0BAA0B;AAC1B,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,0BAA0B;AAC1B,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAElC,iCAAiC;AACjC,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAC1B,UAAU,CAAC;QACT,OAAO,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;KAC5E,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
type SemanticVersion = {
|
|
2
|
+
major: number;
|
|
3
|
+
minor: number;
|
|
4
|
+
patch: number;
|
|
5
|
+
prerelease?: string;
|
|
6
|
+
};
|
|
7
|
+
export interface CliVersionStatus {
|
|
8
|
+
currentVersion: string;
|
|
9
|
+
latestVersion?: string;
|
|
10
|
+
hasUpdate?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface FetchLatestPublishedCliVersionOptions {
|
|
13
|
+
fetchFn?: typeof fetch;
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
}
|
|
16
|
+
export declare const CLI_VERSION: string;
|
|
17
|
+
/**
|
|
18
|
+
* Returns the CLI version from package metadata.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getCliVersion(): string;
|
|
21
|
+
/**
|
|
22
|
+
* Parse a semver string so the CLI can compare local and published versions.
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseSemanticVersion({ rawVersion, }: {
|
|
25
|
+
rawVersion: string;
|
|
26
|
+
}): SemanticVersion | null;
|
|
27
|
+
/**
|
|
28
|
+
* Compare two semantic versions.
|
|
29
|
+
* Returns `1` when left is newer, `-1` when right is newer, and `0` when equal.
|
|
30
|
+
*/
|
|
31
|
+
export declare function compareSemanticVersions({ leftVersion, rightVersion, }: {
|
|
32
|
+
leftVersion: string;
|
|
33
|
+
rightVersion: string;
|
|
34
|
+
}): number | null;
|
|
35
|
+
/**
|
|
36
|
+
* Fetch the latest published CLI version from the npm registry.
|
|
37
|
+
*/
|
|
38
|
+
export declare function fetchLatestPublishedCliVersion({ fetchFn, timeoutMs, }?: FetchLatestPublishedCliVersionOptions): Promise<string | undefined>;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve the current CLI version and, when possible, the latest published version.
|
|
41
|
+
*/
|
|
42
|
+
export declare function getCliVersionStatus({ fetchFn, timeoutMs, }?: FetchLatestPublishedCliVersionOptions): Promise<CliVersionStatus>;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AASA,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAUF,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,qCAAqC;IACpD,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoCD,eAAO,MAAM,WAAW,QAGH,CAAC;AAEtB;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,UAAU,GACX,EAAE;IACD,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,eAAe,GAAG,IAAI,CAYzB;AA0DD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,WAAW,EACX,YAAY,GACb,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,GAAG,IAAI,CAsBhB;AAED;;GAEG;AACH,wBAAsB,8BAA8B,CAAC,EACnD,OAAe,EACf,SAA4C,GAC7C,GAAE,qCAA0C,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAuB1E;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,EACxC,OAAO,EACP,SAAS,GACV,GAAE,qCAA0C,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAyBxE"}
|
package/build/version.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
const CLI_PACKAGE_NAME = "@arizeai/phoenix-cli";
|
|
3
|
+
const CLI_LATEST_VERSION_URL = `https://registry.npmjs.org/${encodeURIComponent(CLI_PACKAGE_NAME)}/latest`;
|
|
4
|
+
const DEFAULT_VERSION_CHECK_TIMEOUT_MS = 1500;
|
|
5
|
+
const DEFAULT_CLI_VERSION = "unknown";
|
|
6
|
+
const SEMANTIC_VERSION_PATTERN = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
7
|
+
function getPackageJsonVersion({ packageJson, }) {
|
|
8
|
+
if (typeof packageJson.version !== "string") {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
const version = packageJson.version.trim();
|
|
12
|
+
return version.length > 0 ? version : undefined;
|
|
13
|
+
}
|
|
14
|
+
function readCliVersionFromPackageJson() {
|
|
15
|
+
try {
|
|
16
|
+
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
|
|
17
|
+
return getPackageJsonVersion({ packageJson });
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function readCliVersionFromEnvironment() {
|
|
24
|
+
if (typeof process.env.npm_package_version !== "string") {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
const version = process.env.npm_package_version.trim();
|
|
28
|
+
return version.length > 0 ? version : undefined;
|
|
29
|
+
}
|
|
30
|
+
export const CLI_VERSION = readCliVersionFromPackageJson() ??
|
|
31
|
+
readCliVersionFromEnvironment() ??
|
|
32
|
+
DEFAULT_CLI_VERSION;
|
|
33
|
+
/**
|
|
34
|
+
* Returns the CLI version from package metadata.
|
|
35
|
+
*/
|
|
36
|
+
export function getCliVersion() {
|
|
37
|
+
return CLI_VERSION;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Parse a semver string so the CLI can compare local and published versions.
|
|
41
|
+
*/
|
|
42
|
+
export function parseSemanticVersion({ rawVersion, }) {
|
|
43
|
+
const match = rawVersion.trim().match(SEMANTIC_VERSION_PATTERN);
|
|
44
|
+
if (!match) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
major: Number.parseInt(match[1], 10),
|
|
49
|
+
minor: Number.parseInt(match[2], 10),
|
|
50
|
+
patch: Number.parseInt(match[3], 10),
|
|
51
|
+
prerelease: match[4] || undefined,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function comparePrereleaseSegments({ leftPrerelease, rightPrerelease, }) {
|
|
55
|
+
if (leftPrerelease === rightPrerelease) {
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
if (!leftPrerelease) {
|
|
59
|
+
return 1;
|
|
60
|
+
}
|
|
61
|
+
if (!rightPrerelease) {
|
|
62
|
+
return -1;
|
|
63
|
+
}
|
|
64
|
+
const leftSegments = leftPrerelease.split(".");
|
|
65
|
+
const rightSegments = rightPrerelease.split(".");
|
|
66
|
+
const segmentCount = Math.max(leftSegments.length, rightSegments.length);
|
|
67
|
+
for (let index = 0; index < segmentCount; index += 1) {
|
|
68
|
+
const leftSegment = leftSegments[index];
|
|
69
|
+
const rightSegment = rightSegments[index];
|
|
70
|
+
if (leftSegment === rightSegment) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (leftSegment === undefined) {
|
|
74
|
+
return -1;
|
|
75
|
+
}
|
|
76
|
+
if (rightSegment === undefined) {
|
|
77
|
+
return 1;
|
|
78
|
+
}
|
|
79
|
+
const leftNumber = Number.parseInt(leftSegment, 10);
|
|
80
|
+
const rightNumber = Number.parseInt(rightSegment, 10);
|
|
81
|
+
const isLeftNumeric = String(leftNumber) === leftSegment;
|
|
82
|
+
const isRightNumeric = String(rightNumber) === rightSegment;
|
|
83
|
+
if (isLeftNumeric && isRightNumeric) {
|
|
84
|
+
return leftNumber === rightNumber ? 0 : leftNumber > rightNumber ? 1 : -1;
|
|
85
|
+
}
|
|
86
|
+
if (isLeftNumeric) {
|
|
87
|
+
return -1;
|
|
88
|
+
}
|
|
89
|
+
if (isRightNumeric) {
|
|
90
|
+
return 1;
|
|
91
|
+
}
|
|
92
|
+
return leftSegment.localeCompare(rightSegment);
|
|
93
|
+
}
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Compare two semantic versions.
|
|
98
|
+
* Returns `1` when left is newer, `-1` when right is newer, and `0` when equal.
|
|
99
|
+
*/
|
|
100
|
+
export function compareSemanticVersions({ leftVersion, rightVersion, }) {
|
|
101
|
+
const leftParsedVersion = parseSemanticVersion({ rawVersion: leftVersion });
|
|
102
|
+
const rightParsedVersion = parseSemanticVersion({ rawVersion: rightVersion });
|
|
103
|
+
if (!leftParsedVersion || !rightParsedVersion) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
if (leftParsedVersion.major !== rightParsedVersion.major) {
|
|
107
|
+
return leftParsedVersion.major > rightParsedVersion.major ? 1 : -1;
|
|
108
|
+
}
|
|
109
|
+
if (leftParsedVersion.minor !== rightParsedVersion.minor) {
|
|
110
|
+
return leftParsedVersion.minor > rightParsedVersion.minor ? 1 : -1;
|
|
111
|
+
}
|
|
112
|
+
if (leftParsedVersion.patch !== rightParsedVersion.patch) {
|
|
113
|
+
return leftParsedVersion.patch > rightParsedVersion.patch ? 1 : -1;
|
|
114
|
+
}
|
|
115
|
+
return comparePrereleaseSegments({
|
|
116
|
+
leftPrerelease: leftParsedVersion.prerelease,
|
|
117
|
+
rightPrerelease: rightParsedVersion.prerelease,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Fetch the latest published CLI version from the npm registry.
|
|
122
|
+
*/
|
|
123
|
+
export async function fetchLatestPublishedCliVersion({ fetchFn = fetch, timeoutMs = DEFAULT_VERSION_CHECK_TIMEOUT_MS, } = {}) {
|
|
124
|
+
const controller = new AbortController();
|
|
125
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
126
|
+
try {
|
|
127
|
+
const response = await fetchFn(CLI_LATEST_VERSION_URL, {
|
|
128
|
+
headers: {
|
|
129
|
+
Accept: "application/json",
|
|
130
|
+
},
|
|
131
|
+
signal: controller.signal,
|
|
132
|
+
});
|
|
133
|
+
if (!response.ok) {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
const payload = (await response.json());
|
|
137
|
+
return typeof payload.version === "string" ? payload.version : undefined;
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
clearTimeout(timeoutId);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Resolve the current CLI version and, when possible, the latest published version.
|
|
148
|
+
*/
|
|
149
|
+
export async function getCliVersionStatus({ fetchFn, timeoutMs, } = {}) {
|
|
150
|
+
const currentVersion = getCliVersion();
|
|
151
|
+
const latestVersion = await fetchLatestPublishedCliVersion({
|
|
152
|
+
fetchFn,
|
|
153
|
+
timeoutMs,
|
|
154
|
+
});
|
|
155
|
+
if (!latestVersion) {
|
|
156
|
+
return { currentVersion };
|
|
157
|
+
}
|
|
158
|
+
const comparison = compareSemanticVersions({
|
|
159
|
+
leftVersion: latestVersion,
|
|
160
|
+
rightVersion: currentVersion,
|
|
161
|
+
});
|
|
162
|
+
if (comparison === null) {
|
|
163
|
+
return { currentVersion };
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
currentVersion,
|
|
167
|
+
latestVersion,
|
|
168
|
+
hasUpdate: comparison > 0,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"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"}
|