@getpaseo/cli 0.3.0 → 0.4.0-beta.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/dist/cli.js +0 -5
- package/dist/commands/hub/authority.d.ts +17 -0
- package/dist/commands/hub/authority.js +18 -0
- package/dist/commands/hub/connect.d.ts +21 -0
- package/dist/commands/hub/connect.js +34 -0
- package/dist/commands/hub/credentials.d.ts +21 -0
- package/dist/commands/hub/credentials.js +143 -0
- package/dist/commands/hub/daemon-client.d.ts +27 -0
- package/dist/commands/hub/daemon-client.js +14 -0
- package/dist/commands/hub/deploy-bundle.d.ts +16 -0
- package/dist/commands/hub/deploy-bundle.js +248 -0
- package/dist/commands/hub/deploy.d.ts +25 -4
- package/dist/commands/hub/deploy.js +64 -48
- package/dist/commands/hub/disconnect.d.ts +16 -0
- package/dist/commands/hub/disconnect.js +24 -0
- package/dist/commands/hub/error.d.ts +1 -1
- package/dist/commands/hub/error.js +2 -2
- package/dist/commands/hub/help.d.ts +3 -0
- package/dist/commands/hub/help.js +5 -0
- package/dist/commands/hub/hub-client/index.d.ts +18 -0
- package/dist/commands/hub/hub-client/index.js +88 -0
- package/dist/commands/hub/hub-client/internal/contracts.d.ts +65 -0
- package/dist/commands/hub/hub-client/internal/contracts.js +47 -0
- package/dist/commands/hub/hub-client/internal/problem.d.ts +3 -0
- package/dist/commands/hub/hub-client/internal/problem.js +72 -0
- package/dist/commands/hub/hub-client/internal/transport.d.ts +15 -0
- package/dist/commands/hub/hub-client/internal/transport.js +30 -0
- package/dist/commands/hub/index.d.ts +15 -25
- package/dist/commands/hub/index.js +64 -74
- package/dist/commands/hub/{device-authorization.d.ts → login-flow.d.ts} +12 -15
- package/dist/commands/hub/login-flow.js +78 -0
- package/dist/commands/hub/login.d.ts +21 -0
- package/dist/commands/hub/login.js +34 -0
- package/dist/commands/hub/logout.d.ts +31 -0
- package/dist/commands/hub/logout.js +65 -0
- package/dist/commands/hub/origin.d.ts +2 -0
- package/dist/commands/hub/origin.js +27 -0
- package/dist/commands/hub/projects.d.ts +24 -0
- package/dist/commands/hub/projects.js +49 -0
- package/dist/commands/hub/reporter.d.ts +10 -0
- package/dist/commands/hub/reporter.js +11 -0
- package/dist/commands/hub/status-output.d.ts +13 -0
- package/dist/commands/hub/status-output.js +30 -0
- package/dist/commands/provider/diagnostic.d.ts +12 -0
- package/dist/commands/provider/diagnostic.js +31 -0
- package/dist/commands/provider/index.js +5 -0
- package/dist/commands/schedule/types.d.ts +1 -4
- package/dist/commands/workspace/index.js +10 -0
- package/dist/commands/workspace/rename.d.ts +22 -0
- package/dist/commands/workspace/rename.js +61 -0
- package/dist/output/types.d.ts +1 -1
- package/package.json +4 -4
- package/dist/commands/chat/create.d.ts +0 -9
- package/dist/commands/chat/create.js +0 -23
- package/dist/commands/chat/delete.d.ts +0 -6
- package/dist/commands/chat/delete.js +0 -20
- package/dist/commands/chat/index.d.ts +0 -3
- package/dist/commands/chat/index.js +0 -47
- package/dist/commands/chat/inspect.d.ts +0 -6
- package/dist/commands/chat/inspect.js +0 -20
- package/dist/commands/chat/ls.d.ts +0 -6
- package/dist/commands/chat/ls.js +0 -20
- package/dist/commands/chat/post.d.ts +0 -9
- package/dist/commands/chat/post.js +0 -28
- package/dist/commands/chat/read.d.ts +0 -11
- package/dist/commands/chat/read.js +0 -40
- package/dist/commands/chat/schema.d.ts +0 -36
- package/dist/commands/chat/schema.js +0 -81
- package/dist/commands/chat/shared.d.ts +0 -19
- package/dist/commands/chat/shared.js +0 -118
- package/dist/commands/chat/wait.d.ts +0 -9
- package/dist/commands/chat/wait.js +0 -45
- package/dist/commands/hub/client.d.ts +0 -19
- package/dist/commands/hub/client.js +0 -114
- package/dist/commands/hub/cloud-device-authorization.d.ts +0 -45
- package/dist/commands/hub/cloud-device-authorization.js +0 -92
- package/dist/commands/hub/deploy-input.d.ts +0 -17
- package/dist/commands/hub/deploy-input.js +0 -264
- package/dist/commands/hub/device-authorization.js +0 -87
- package/dist/commands/loop/index.d.ts +0 -3
- package/dist/commands/loop/index.js +0 -18
- package/dist/commands/loop/inspect.d.ts +0 -13
- package/dist/commands/loop/inspect.js +0 -100
- package/dist/commands/loop/logs.d.ts +0 -8
- package/dist/commands/loop/logs.js +0 -69
- package/dist/commands/loop/ls.d.ts +0 -18
- package/dist/commands/loop/ls.js +0 -62
- package/dist/commands/loop/run.d.ts +0 -30
- package/dist/commands/loop/run.js +0 -162
- package/dist/commands/loop/stop.d.ts +0 -15
- package/dist/commands/loop/stop.js +0 -56
- package/dist/commands/loop/types.d.ts +0 -138
- package/dist/commands/loop/types.js +0 -2
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { withOutput } from "../../output/index.js";
|
|
2
2
|
import { addJsonOption } from "../../utils/command-options.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { resolveHubCredential, resolveHubOrigin } from "./authority.js";
|
|
4
|
+
import { HubHttpClient, } from "./hub-client/index.js";
|
|
5
|
+
import { PrivateHubCredentialStore } from "./credentials.js";
|
|
6
|
+
import { discoverHubBundle } from "./deploy-bundle.js";
|
|
7
|
+
import { processHubReporter, reportHubProgress } from "./reporter.js";
|
|
8
|
+
import { addHubResolutionHelp } from "./help.js";
|
|
6
9
|
const resultSchema = {
|
|
7
10
|
idField: "versionId",
|
|
8
11
|
columns: [
|
|
@@ -10,62 +13,75 @@ const resultSchema = {
|
|
|
10
13
|
{ header: "VERSION", field: "version" },
|
|
11
14
|
{ header: "VERSION ID", field: "versionId" },
|
|
12
15
|
{ header: "ACTIVE", field: "active" },
|
|
16
|
+
{ header: "WORKFLOWS", field: "workflows" },
|
|
17
|
+
{ header: "HUB", field: "origin" },
|
|
13
18
|
],
|
|
14
19
|
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
const validationSchema = {
|
|
21
|
+
idField: "projectSlug",
|
|
22
|
+
columns: [
|
|
23
|
+
{ header: "PROJECT", field: "projectSlug" },
|
|
24
|
+
{ header: "VALID", field: "valid" },
|
|
25
|
+
{ header: "WORKFLOWS", field: "workflows" },
|
|
26
|
+
{ header: "HUB", field: "origin" },
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
export async function runHubDeploy(options, environment = {
|
|
30
|
+
cwd: process.cwd(),
|
|
31
|
+
env: process.env,
|
|
32
|
+
credentials: new PrivateHubCredentialStore(),
|
|
33
|
+
hub: new HubHttpClient(),
|
|
34
|
+
}) {
|
|
35
|
+
const credentials = environment.credentials ?? new PrivateHubCredentialStore(environment.env);
|
|
36
|
+
const resolution = {
|
|
37
|
+
options: { origin: options.hub, apiKey: options.apiKey },
|
|
38
|
+
env: environment.env,
|
|
39
|
+
credentials,
|
|
40
|
+
};
|
|
41
|
+
const origin = resolveHubOrigin(resolution);
|
|
42
|
+
const deployInput = await discoverHubBundle({
|
|
26
43
|
cwd: environment.cwd,
|
|
27
|
-
...(options.file === undefined ? {} : { file: options.file }),
|
|
28
44
|
...(options.project === undefined ? {} : { project: options.project }),
|
|
29
45
|
});
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
46
|
+
const action = options.dryRun === true ? "Validating" : "Deploying";
|
|
47
|
+
reportHubProgress(environment.reporter ?? processHubReporter, options, `${action} ${deployInput.projectSlug} ${options.dryRun === true ? "against" : "to"} ${origin}`);
|
|
48
|
+
const credential = resolveHubCredential({ ...resolution, origin });
|
|
49
|
+
const request = {
|
|
50
|
+
origin,
|
|
51
|
+
apiKey: credential,
|
|
33
52
|
...deployInput,
|
|
34
|
-
}
|
|
35
|
-
|
|
53
|
+
};
|
|
54
|
+
if (options.dryRun === true) {
|
|
55
|
+
const validated = await (environment.hub ?? new HubHttpClient()).validateConfiguration(request);
|
|
56
|
+
return {
|
|
57
|
+
type: "single",
|
|
58
|
+
data: { ...validated, workflows: deployInput.workflowCount, origin },
|
|
59
|
+
schema: validationSchema,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const deployed = await (environment.hub ?? new HubHttpClient()).installConfiguration(request);
|
|
63
|
+
return {
|
|
64
|
+
type: "single",
|
|
65
|
+
data: { ...deployed, workflows: deployInput.workflowCount, origin },
|
|
66
|
+
schema: resultSchema,
|
|
67
|
+
};
|
|
36
68
|
}
|
|
37
|
-
export function addHubDeployCommand(hub) {
|
|
38
|
-
addJsonOption(hub
|
|
69
|
+
export function addHubDeployCommand(hub, dependencies) {
|
|
70
|
+
addJsonOption(addHubResolutionHelp(hub
|
|
39
71
|
.command("deploy")
|
|
40
|
-
.description("
|
|
41
|
-
.argument("[file]", "Hub configuration YAML", ".paseo/hub.yml")
|
|
72
|
+
.description("Discover, validate, and activate the canonical .paseo Hub bundle")
|
|
42
73
|
.option("-p, --project <slug>", "Target project slug")
|
|
43
74
|
.option("--hub <origin>", "Paseo Hub origin")
|
|
44
|
-
.option("--api-key <secret>", "Organization API key")
|
|
45
|
-
|
|
75
|
+
.option("--api-key <secret>", "Organization API key")
|
|
76
|
+
.option("--dry-run", "Validate without installing or activating"))).action(withOutput(async (...args) => {
|
|
46
77
|
const options = args.at(-2);
|
|
47
|
-
return runHubDeploy(
|
|
78
|
+
return runHubDeploy(options, {
|
|
79
|
+
cwd: dependencies.cwd(),
|
|
80
|
+
env: dependencies.env,
|
|
81
|
+
credentials: dependencies.credentials,
|
|
82
|
+
hub: dependencies.hub,
|
|
83
|
+
reporter: dependencies.reporter,
|
|
84
|
+
});
|
|
48
85
|
}));
|
|
49
86
|
}
|
|
50
|
-
function parseHubOrigin(value) {
|
|
51
|
-
let url;
|
|
52
|
-
try {
|
|
53
|
-
url = new URL(value);
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
56
|
-
throw invalidHubOrigin();
|
|
57
|
-
}
|
|
58
|
-
if (!["http:", "https:"].includes(url.protocol) ||
|
|
59
|
-
url.username ||
|
|
60
|
-
url.password ||
|
|
61
|
-
url.pathname !== "/" ||
|
|
62
|
-
url.search ||
|
|
63
|
-
url.hash) {
|
|
64
|
-
throw invalidHubOrigin();
|
|
65
|
-
}
|
|
66
|
-
return url.origin;
|
|
67
|
-
}
|
|
68
|
-
function invalidHubOrigin() {
|
|
69
|
-
return new HubDeployError("HUB_INVALID_ORIGIN", "Hub URL must be an HTTP or HTTPS origin without credentials, path, query, or hash.");
|
|
70
|
-
}
|
|
71
87
|
//# sourceMappingURL=deploy.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { HubDaemonConnection } from "./daemon-client.js";
|
|
3
|
+
import { type HubReporter } from "./reporter.js";
|
|
4
|
+
interface HubDisconnectOptions {
|
|
5
|
+
force?: boolean;
|
|
6
|
+
host?: string;
|
|
7
|
+
json?: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface HubDisconnectDependencies {
|
|
10
|
+
daemon: HubDaemonConnection;
|
|
11
|
+
reporter: HubReporter;
|
|
12
|
+
}
|
|
13
|
+
export declare function runHubDisconnect(options: HubDisconnectOptions, dependencies: HubDisconnectDependencies): Promise<import("../../output/types.js").ListResult<import("./status-output.js").HubRow>>;
|
|
14
|
+
export declare function addHubDisconnectCommand(parent: Command, dependencies: HubDisconnectDependencies): void;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=disconnect.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { withOutput } from "../../output/index.js";
|
|
2
|
+
import { addJsonAndDaemonHostOptions } from "../../utils/command-options.js";
|
|
3
|
+
import { withHubDaemon } from "./daemon-client.js";
|
|
4
|
+
import { reportHubProgress } from "./reporter.js";
|
|
5
|
+
import { hubStatusResult } from "./status-output.js";
|
|
6
|
+
export function runHubDisconnect(options, dependencies) {
|
|
7
|
+
return withHubDaemon(dependencies.daemon, options.host, async (client) => {
|
|
8
|
+
const current = (await client.getHubStatus()).status;
|
|
9
|
+
if (current.hubOrigin !== null) {
|
|
10
|
+
reportHubProgress(dependencies.reporter, options, `Disconnecting this daemon from ${current.hubOrigin}`);
|
|
11
|
+
}
|
|
12
|
+
const response = await client.disconnectHub(options.force ?? false);
|
|
13
|
+
return hubStatusResult(response.status, response.warning, current.hubOrigin);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export function addHubDisconnectCommand(parent, dependencies) {
|
|
17
|
+
addJsonAndDaemonHostOptions(parent
|
|
18
|
+
.command("disconnect")
|
|
19
|
+
.option("--force", "Remove local authority even if the Hub is offline")).action(withOutput(async (...args) => {
|
|
20
|
+
const options = args.at(-2);
|
|
21
|
+
return runHubDisconnect(options, dependencies);
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=disconnect.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export class
|
|
1
|
+
export class HubCommandError extends Error {
|
|
2
2
|
constructor(code, message, details) {
|
|
3
3
|
super(message);
|
|
4
4
|
this.code = code;
|
|
5
5
|
this.details = details;
|
|
6
|
-
this.name = "
|
|
6
|
+
this.name = "HubCommandError";
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
//# sourceMappingURL=error.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const resolutionHelp = "\nHub origin precedence: command origin/--hub, PASEO_HUB_URL, active stored login, then https://hub.paseo.sh.\nCredential precedence: --api-key, PASEO_HUB_API_KEY, then a stored login for the exact resolved origin.\n";
|
|
2
|
+
export function addHubResolutionHelp(command) {
|
|
3
|
+
return command.addHelpText("after", resolutionHelp);
|
|
4
|
+
}
|
|
5
|
+
//# sourceMappingURL=help.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { HubBundleFile } from "../deploy-bundle.js";
|
|
2
|
+
import { type CliAuthorization, type CliAuthorizationPoll, type HubInstallResult, type HubProject, type HubValidationResult } from "./internal/contracts.js";
|
|
3
|
+
export type { CliAuthorization, CliAuthorizationPoll, HubInstallResult, HubProject, HubValidationResult, } from "./internal/contracts.js";
|
|
4
|
+
interface HubConfigurationInput {
|
|
5
|
+
origin: string;
|
|
6
|
+
apiKey: string;
|
|
7
|
+
projectSlug: string;
|
|
8
|
+
files: readonly HubBundleFile[];
|
|
9
|
+
}
|
|
10
|
+
export declare class HubHttpClient {
|
|
11
|
+
startCliAuthorization(origin: string): Promise<CliAuthorization>;
|
|
12
|
+
pollCliAuthorization(origin: string, deviceCode: string, timeoutMilliseconds: number): Promise<CliAuthorizationPoll>;
|
|
13
|
+
listProjects(origin: string, apiKey: string): Promise<HubProject[]>;
|
|
14
|
+
installConfiguration(input: HubConfigurationInput): Promise<HubInstallResult>;
|
|
15
|
+
validateConfiguration(input: HubConfigurationInput): Promise<HubValidationResult>;
|
|
16
|
+
issueEnrollmentToken(origin: string, apiKey: string): Promise<string>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { HubCommandError } from "../error.js";
|
|
2
|
+
import { authorizationPollSchema, authorizationSchema, enrollmentTokenSchema, installResponseSchema, projectsResponseSchema, validationResponseSchema, } from "./internal/contracts.js";
|
|
3
|
+
import { requestHub } from "./internal/transport.js";
|
|
4
|
+
export class HubHttpClient {
|
|
5
|
+
startCliAuthorization(origin) {
|
|
6
|
+
return requestHub({
|
|
7
|
+
origin,
|
|
8
|
+
path: "/api/v1/cli-authorizations",
|
|
9
|
+
method: "POST",
|
|
10
|
+
body: {},
|
|
11
|
+
successStatus: 201,
|
|
12
|
+
schema: authorizationSchema,
|
|
13
|
+
failureMessage: "Hub CLI login could not be started",
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
async pollCliAuthorization(origin, deviceCode, timeoutMilliseconds) {
|
|
17
|
+
try {
|
|
18
|
+
return await requestHub({
|
|
19
|
+
origin,
|
|
20
|
+
path: "/api/v1/cli-authorizations/poll",
|
|
21
|
+
method: "POST",
|
|
22
|
+
body: { deviceCode },
|
|
23
|
+
successStatus: 200,
|
|
24
|
+
schema: authorizationPollSchema,
|
|
25
|
+
timeoutMilliseconds,
|
|
26
|
+
failureMessage: "Hub CLI login polling failed",
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
if (error instanceof HubCommandError && error.code === "HUB_NETWORK_ERROR") {
|
|
31
|
+
return { status: "retry_later" };
|
|
32
|
+
}
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async listProjects(origin, apiKey) {
|
|
37
|
+
const response = await requestHub({
|
|
38
|
+
origin,
|
|
39
|
+
path: "/api/v1/projects",
|
|
40
|
+
method: "GET",
|
|
41
|
+
apiKey,
|
|
42
|
+
successStatus: 200,
|
|
43
|
+
schema: projectsResponseSchema,
|
|
44
|
+
failureMessage: "Hub project listing failed",
|
|
45
|
+
});
|
|
46
|
+
return response.projects;
|
|
47
|
+
}
|
|
48
|
+
installConfiguration(input) {
|
|
49
|
+
return requestHub({
|
|
50
|
+
origin: input.origin,
|
|
51
|
+
path: "/api/v1/configurations/install",
|
|
52
|
+
method: "POST",
|
|
53
|
+
apiKey: input.apiKey,
|
|
54
|
+
body: configurationBody(input),
|
|
55
|
+
successStatus: 201,
|
|
56
|
+
schema: installResponseSchema,
|
|
57
|
+
failureMessage: "Hub deployment failed",
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
validateConfiguration(input) {
|
|
61
|
+
return requestHub({
|
|
62
|
+
origin: input.origin,
|
|
63
|
+
path: "/api/v1/configurations/validate",
|
|
64
|
+
method: "POST",
|
|
65
|
+
apiKey: input.apiKey,
|
|
66
|
+
body: configurationBody(input),
|
|
67
|
+
successStatus: 200,
|
|
68
|
+
schema: validationResponseSchema,
|
|
69
|
+
failureMessage: "Hub configuration validation failed",
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async issueEnrollmentToken(origin, apiKey) {
|
|
73
|
+
const response = await requestHub({
|
|
74
|
+
origin,
|
|
75
|
+
path: "/api/v1/daemons/enrollment-tokens",
|
|
76
|
+
method: "POST",
|
|
77
|
+
apiKey,
|
|
78
|
+
successStatus: 201,
|
|
79
|
+
schema: enrollmentTokenSchema,
|
|
80
|
+
failureMessage: "Hub daemon enrollment authorization failed",
|
|
81
|
+
});
|
|
82
|
+
return response.token;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function configurationBody(input) {
|
|
86
|
+
return { projectSlug: input.projectSlug, files: input.files };
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const authorizationSchema: z.ZodObject<{
|
|
3
|
+
deviceCode: z.ZodString;
|
|
4
|
+
userCode: z.ZodString;
|
|
5
|
+
verificationUri: z.ZodURL;
|
|
6
|
+
verificationUriComplete: z.ZodURL;
|
|
7
|
+
expiresAt: z.ZodString;
|
|
8
|
+
interval: z.ZodNumber;
|
|
9
|
+
}, z.core.$strict>;
|
|
10
|
+
export declare const authorizationPollSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
11
|
+
status: z.ZodLiteral<"pending">;
|
|
12
|
+
interval: z.ZodNumber;
|
|
13
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
14
|
+
status: z.ZodLiteral<"slow_down">;
|
|
15
|
+
interval: z.ZodNumber;
|
|
16
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
17
|
+
status: z.ZodLiteral<"authorized">;
|
|
18
|
+
interval: z.ZodNumber;
|
|
19
|
+
credential: z.ZodString;
|
|
20
|
+
organizationId: z.ZodString;
|
|
21
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
22
|
+
status: z.ZodLiteral<"denied">;
|
|
23
|
+
interval: z.ZodNumber;
|
|
24
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
25
|
+
status: z.ZodLiteral<"expired">;
|
|
26
|
+
interval: z.ZodNumber;
|
|
27
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
28
|
+
status: z.ZodLiteral<"disclosed">;
|
|
29
|
+
interval: z.ZodNumber;
|
|
30
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
31
|
+
status: z.ZodLiteral<"retry_later">;
|
|
32
|
+
}, z.core.$strict>], "status">;
|
|
33
|
+
declare const projectSchema: z.ZodObject<{
|
|
34
|
+
id: z.ZodString;
|
|
35
|
+
slug: z.ZodString;
|
|
36
|
+
name: z.ZodString;
|
|
37
|
+
}, z.core.$strict>;
|
|
38
|
+
export declare const projectsResponseSchema: z.ZodObject<{
|
|
39
|
+
projects: z.ZodArray<z.ZodObject<{
|
|
40
|
+
id: z.ZodString;
|
|
41
|
+
slug: z.ZodString;
|
|
42
|
+
name: z.ZodString;
|
|
43
|
+
}, z.core.$strict>>;
|
|
44
|
+
}, z.core.$strict>;
|
|
45
|
+
export declare const installResponseSchema: z.ZodObject<{
|
|
46
|
+
projectSlug: z.ZodString;
|
|
47
|
+
version: z.ZodNumber;
|
|
48
|
+
versionId: z.ZodString;
|
|
49
|
+
active: z.ZodLiteral<true>;
|
|
50
|
+
}, z.core.$strict>;
|
|
51
|
+
export declare const validationResponseSchema: z.ZodObject<{
|
|
52
|
+
projectSlug: z.ZodString;
|
|
53
|
+
valid: z.ZodLiteral<true>;
|
|
54
|
+
}, z.core.$strict>;
|
|
55
|
+
export declare const enrollmentTokenSchema: z.ZodObject<{
|
|
56
|
+
token: z.ZodString;
|
|
57
|
+
expiresAt: z.ZodString;
|
|
58
|
+
}, z.core.$strict>;
|
|
59
|
+
export type CliAuthorization = z.infer<typeof authorizationSchema>;
|
|
60
|
+
export type CliAuthorizationPoll = z.infer<typeof authorizationPollSchema>;
|
|
61
|
+
export type HubProject = z.infer<typeof projectSchema>;
|
|
62
|
+
export type HubInstallResult = z.infer<typeof installResponseSchema>;
|
|
63
|
+
export type HubValidationResult = z.infer<typeof validationResponseSchema>;
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=contracts.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const activationUrlSchema = z.url({ protocol: /^https?$/u });
|
|
3
|
+
export const authorizationSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
deviceCode: z.string().min(32),
|
|
6
|
+
userCode: z.string().min(1),
|
|
7
|
+
verificationUri: activationUrlSchema,
|
|
8
|
+
verificationUriComplete: activationUrlSchema,
|
|
9
|
+
expiresAt: z.string().datetime(),
|
|
10
|
+
interval: z.number().int().min(1),
|
|
11
|
+
})
|
|
12
|
+
.strict();
|
|
13
|
+
export const authorizationPollSchema = z.discriminatedUnion("status", [
|
|
14
|
+
z.object({ status: z.literal("pending"), interval: z.number().int().min(1) }).strict(),
|
|
15
|
+
z.object({ status: z.literal("slow_down"), interval: z.number().int().min(1) }).strict(),
|
|
16
|
+
z
|
|
17
|
+
.object({
|
|
18
|
+
status: z.literal("authorized"),
|
|
19
|
+
interval: z.number().int().min(1),
|
|
20
|
+
credential: z.string().min(32),
|
|
21
|
+
organizationId: z.string().min(1),
|
|
22
|
+
})
|
|
23
|
+
.strict(),
|
|
24
|
+
z.object({ status: z.literal("denied"), interval: z.number().int().min(1) }).strict(),
|
|
25
|
+
z.object({ status: z.literal("expired"), interval: z.number().int().min(1) }).strict(),
|
|
26
|
+
z.object({ status: z.literal("disclosed"), interval: z.number().int().min(1) }).strict(),
|
|
27
|
+
z.object({ status: z.literal("retry_later") }).strict(),
|
|
28
|
+
]);
|
|
29
|
+
const projectSchema = z
|
|
30
|
+
.object({ id: z.string().uuid(), slug: z.string().min(1), name: z.string().min(1) })
|
|
31
|
+
.strict();
|
|
32
|
+
export const projectsResponseSchema = z.object({ projects: z.array(projectSchema) }).strict();
|
|
33
|
+
export const installResponseSchema = z
|
|
34
|
+
.object({
|
|
35
|
+
projectSlug: z.string().min(1),
|
|
36
|
+
version: z.number().int().positive(),
|
|
37
|
+
versionId: z.string().uuid(),
|
|
38
|
+
active: z.literal(true),
|
|
39
|
+
})
|
|
40
|
+
.strict();
|
|
41
|
+
export const validationResponseSchema = z
|
|
42
|
+
.object({ projectSlug: z.string().min(1), valid: z.literal(true) })
|
|
43
|
+
.strict();
|
|
44
|
+
export const enrollmentTokenSchema = z
|
|
45
|
+
.object({ token: z.string().min(32), expiresAt: z.string().datetime() })
|
|
46
|
+
.strict();
|
|
47
|
+
//# sourceMappingURL=contracts.js.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { HubCommandError } from "../../error.js";
|
|
3
|
+
const issuePathSchema = z.union([z.string(), z.array(z.union([z.string(), z.number()]))]);
|
|
4
|
+
const fieldIssueSchema = z.object({
|
|
5
|
+
field: z.string().optional(),
|
|
6
|
+
path: issuePathSchema.optional(),
|
|
7
|
+
message: z.string(),
|
|
8
|
+
});
|
|
9
|
+
const problemSchema = z.object({
|
|
10
|
+
type: z.string().optional(),
|
|
11
|
+
title: z.string().optional(),
|
|
12
|
+
status: z.number().int().optional(),
|
|
13
|
+
detail: z.string().optional(),
|
|
14
|
+
instance: z.string().optional(),
|
|
15
|
+
errors: z
|
|
16
|
+
.union([z.array(fieldIssueSchema), z.record(z.string(), z.array(z.string()))])
|
|
17
|
+
.optional(),
|
|
18
|
+
issues: z.array(fieldIssueSchema).optional(),
|
|
19
|
+
});
|
|
20
|
+
export async function hubRequestFailure(response, failureMessage, apiKey) {
|
|
21
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
22
|
+
if (!contentType.toLowerCase().includes("application/problem+json")) {
|
|
23
|
+
return new HubCommandError("HUB_REQUEST_FAILED", `${failureMessage} with HTTP ${response.status}.`);
|
|
24
|
+
}
|
|
25
|
+
let body;
|
|
26
|
+
try {
|
|
27
|
+
body = await response.json();
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return new HubCommandError("HUB_INVALID_RESPONSE", `Hub returned malformed problem details for HTTP ${response.status}.`);
|
|
31
|
+
}
|
|
32
|
+
const parsed = problemSchema.safeParse(body);
|
|
33
|
+
if (!parsed.success ||
|
|
34
|
+
(parsed.data.status !== undefined && parsed.data.status !== response.status)) {
|
|
35
|
+
return new HubCommandError("HUB_INVALID_RESPONSE", `Hub returned nonconforming problem details for HTTP ${response.status}.`);
|
|
36
|
+
}
|
|
37
|
+
const title = parsed.data.title ?? `${failureMessage} with HTTP ${response.status}`;
|
|
38
|
+
const message = parsed.data.detail === undefined ? title : `${title}: ${parsed.data.detail}`;
|
|
39
|
+
const details = formatFieldIssues(parsed.data.errors, parsed.data.issues);
|
|
40
|
+
const code = response.status === 422 ? "HUB_VALIDATION_FAILED" : "HUB_REQUEST_FAILED";
|
|
41
|
+
return new HubCommandError(code, redactSecret(message, apiKey), details === undefined ? undefined : redactSecret(details, apiKey));
|
|
42
|
+
}
|
|
43
|
+
function formatFieldIssues(errors, issues) {
|
|
44
|
+
const fieldIssues = Array.isArray(errors) ? errors : issues;
|
|
45
|
+
if (fieldIssues !== undefined) {
|
|
46
|
+
const lines = fieldIssues.map((issue) => {
|
|
47
|
+
const field = issue.field ?? formatIssuePath(issue.path);
|
|
48
|
+
return field === undefined ? issue.message : `${field}: ${issue.message}`;
|
|
49
|
+
});
|
|
50
|
+
return lines.length === 0 ? undefined : lines.join("\n");
|
|
51
|
+
}
|
|
52
|
+
if (errors === undefined)
|
|
53
|
+
return undefined;
|
|
54
|
+
const lines = Object.entries(errors).flatMap(([field, messages]) => messages.map((message) => `${field}: ${message}`));
|
|
55
|
+
return lines.length === 0 ? undefined : lines.join("\n");
|
|
56
|
+
}
|
|
57
|
+
function formatIssuePath(path) {
|
|
58
|
+
if (path === undefined || typeof path === "string")
|
|
59
|
+
return path;
|
|
60
|
+
let formatted = "";
|
|
61
|
+
for (const segment of path) {
|
|
62
|
+
if (typeof segment === "number")
|
|
63
|
+
formatted += `[${segment}]`;
|
|
64
|
+
else
|
|
65
|
+
formatted += formatted.length === 0 ? segment : `.${segment}`;
|
|
66
|
+
}
|
|
67
|
+
return formatted || undefined;
|
|
68
|
+
}
|
|
69
|
+
function redactSecret(value, secret) {
|
|
70
|
+
return secret === undefined ? value : value.split(secret).join("[redacted]");
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=problem.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
interface HubRequest<T> {
|
|
3
|
+
origin: string;
|
|
4
|
+
path: string;
|
|
5
|
+
method: "GET" | "POST";
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
body?: unknown;
|
|
8
|
+
successStatus: number;
|
|
9
|
+
schema: z.ZodType<T>;
|
|
10
|
+
timeoutMilliseconds?: number;
|
|
11
|
+
failureMessage: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function requestHub<T>(input: HubRequest<T>): Promise<T>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { HubCommandError } from "../../error.js";
|
|
2
|
+
import { hubRequestFailure } from "./problem.js";
|
|
3
|
+
export async function requestHub(input) {
|
|
4
|
+
const signal = AbortSignal.timeout(input.timeoutMilliseconds ?? 15000);
|
|
5
|
+
let response;
|
|
6
|
+
try {
|
|
7
|
+
response = await fetch(`${input.origin}${input.path}`, {
|
|
8
|
+
method: input.method,
|
|
9
|
+
headers: {
|
|
10
|
+
...(input.apiKey === undefined ? {} : { authorization: `Bearer ${input.apiKey}` }),
|
|
11
|
+
...(input.body === undefined ? {} : { "content-type": "application/json" }),
|
|
12
|
+
},
|
|
13
|
+
...(input.body === undefined ? {} : { body: JSON.stringify(input.body) }),
|
|
14
|
+
signal,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
throw new HubCommandError("HUB_NETWORK_ERROR", `Could not reach Paseo Hub at ${input.origin}. Check the Hub URL and network connection.`);
|
|
19
|
+
}
|
|
20
|
+
if (response.status !== input.successStatus) {
|
|
21
|
+
throw await hubRequestFailure(response, input.failureMessage, input.apiKey);
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
return input.schema.parse(await response.json());
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new HubCommandError("HUB_INVALID_RESPONSE", "Hub returned a malformed response.");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -1,30 +1,20 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
status: HubStatus;
|
|
8
|
-
}>;
|
|
9
|
-
disconnectHub(force: boolean): Promise<{
|
|
10
|
-
status: HubStatus;
|
|
11
|
-
warning?: string;
|
|
12
|
-
}>;
|
|
13
|
-
close(): Promise<void>;
|
|
14
|
-
}
|
|
15
|
-
interface HubStatus {
|
|
16
|
-
state: string;
|
|
17
|
-
daemonId: string | null;
|
|
18
|
-
hubOrigin: string | null;
|
|
19
|
-
scopes: string[];
|
|
20
|
-
connectedAt: string | null;
|
|
21
|
-
lastError: string | null;
|
|
22
|
-
}
|
|
2
|
+
import { HubHttpClient } from "./hub-client/index.js";
|
|
3
|
+
import { type HubCredentialStore } from "./credentials.js";
|
|
4
|
+
import { type HubDaemonConnection } from "./daemon-client.js";
|
|
5
|
+
import { type CliLoginFlow } from "./login-flow.js";
|
|
6
|
+
import { type HubReporter } from "./reporter.js";
|
|
23
7
|
interface HubCommandEnvironment {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
8
|
+
env: Readonly<Record<string, string | undefined>>;
|
|
9
|
+
credentials: HubCredentialStore;
|
|
10
|
+
hub: HubHttpClient;
|
|
11
|
+
login: Pick<CliLoginFlow, "authorize">;
|
|
12
|
+
daemon: HubDaemonConnection;
|
|
13
|
+
isInteractive(): boolean;
|
|
14
|
+
confirmDisconnect(origin: string): Promise<boolean>;
|
|
15
|
+
reporter: HubReporter;
|
|
16
|
+
cwd(): string;
|
|
27
17
|
}
|
|
28
|
-
export declare function createHubCommand(
|
|
18
|
+
export declare function createHubCommand(overrides?: Partial<HubCommandEnvironment>): Command;
|
|
29
19
|
export {};
|
|
30
20
|
//# sourceMappingURL=index.d.ts.map
|