@hitch42/applet 0.1.1-beta.23 → 0.1.1-beta.24
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/applet.js +17 -17
- package/dist/auth-DGCFAqPX.js +47 -0
- package/dist/build-C3LFcX0i.js +1 -0
- package/dist/{build-CrrTAX6T.js → build-Cnh7Owss.js} +2 -2
- package/dist/{ci-B1XyXpHa.js → ci-PuUsFgnN.js} +2 -2
- package/dist/{deploy-WdARFHmA.js → deploy-oCP6VmLT.js} +10 -10
- package/dist/device-CcsD_wOD.js +155 -0
- package/dist/{generate-Ct-Rbh0f.js → generate-DIgN2KC4.js} +6 -5
- package/dist/generate-cwMuaQE9.js +1 -0
- package/dist/{generated-agents-BUnJ0FQA.js → generated-agents-XYtnda2w.js} +1 -1
- package/dist/{git-credential-DuLNowIb.js → git-credential-CK0sHQ5a.js} +1 -1
- package/dist/git-deploy-CCVbXqbO.js +1 -0
- package/dist/{git-deploy-BjSAv5Qm.js → git-deploy-Cz-FCa93.js} +4 -3
- package/dist/{git-migration-6V31iafL.js → git-migration-BIw2cVoP.js} +6 -6
- package/dist/{init-C5HqIRt8.js → init-CAyEoy4P.js} +9 -8
- package/dist/{load-config-Df-zmfrd.js → load-config-0lXPytAo.js} +1 -2
- package/dist/{login-B41-WWtD.js → login-ChKZbUOt.js} +3 -2
- package/dist/{logs-DrL2ytmg.js → logs-C4QXSsBW.js} +3 -3
- package/dist/{parent-Zx8Eg1Ki.js → parent-BGZHFiDn.js} +3 -3
- package/dist/parent-QxKvaC2E.js +1 -0
- package/dist/{project-BbpU_VN2.js → project-BRwNCUCi.js} +4 -4
- package/dist/{schedules-2Q_fkY_a.js → schedules-CThe3MC1.js} +2 -2
- package/dist/{source-hash-BbvtRaus.js → source-hash-Bp8v9JY1.js} +1 -1
- package/dist/{auth-OvyoB6M-.js → store-Dq9l7Qmw.js} +9 -217
- package/dist/{variables-CGwbmUom.js → variables-Cpd05u5N.js} +2 -2
- package/dist/vite.js +5 -5
- package/dist/{workspace-CtIKSgMD.js → workspace-BRRW36wG.js} +1 -1
- package/package.json +2 -3
- package/dist/build-YzjhhLw0.js +0 -1
- package/dist/generate-_u-zFzrv.js +0 -1
- package/dist/git-deploy-CByu_uli.js +0 -1
- package/dist/parent-D52Kxp8U.js +0 -1
package/dist/applet.js
CHANGED
|
@@ -76,7 +76,7 @@ async function main() {
|
|
|
76
76
|
if (process.argv[2] === "git-credential") {
|
|
77
77
|
const args = process.argv.slice(3);
|
|
78
78
|
if (args[0] !== "--instance" || args.length !== 3) throw new Error("Use applet git-credential --instance <url> <get|store|erase>.");
|
|
79
|
-
await (await import("./git-credential-
|
|
79
|
+
await (await import("./git-credential-CK0sHQ5a.js")).runGitCredential(args[2] ?? "", args[1]);
|
|
80
80
|
return;
|
|
81
81
|
}
|
|
82
82
|
const { positionals, values } = parseArgs({
|
|
@@ -109,19 +109,19 @@ async function main() {
|
|
|
109
109
|
strict: true
|
|
110
110
|
});
|
|
111
111
|
if ((positionals.length === 2 || positionals.length === 3) && positionals[0] === "clone" && Object.keys(values).every((key) => key === "message")) {
|
|
112
|
-
await (await import("./git-deploy-
|
|
112
|
+
await (await import("./git-deploy-CCVbXqbO.js")).runClone(positionals[1], positionals[2], values.message);
|
|
113
113
|
return;
|
|
114
114
|
}
|
|
115
115
|
if (positionals.length === 1 && positionals[0] === "logout" && Object.keys(values).length === 0) {
|
|
116
|
-
await (await import("./login-
|
|
116
|
+
await (await import("./login-ChKZbUOt.js")).runLogout();
|
|
117
117
|
return;
|
|
118
118
|
}
|
|
119
119
|
if (positionals.length === 1 && positionals[0] === "login" && Object.keys(values).every((key) => key === "no-browser")) {
|
|
120
|
-
await (await import("./login-
|
|
120
|
+
await (await import("./login-ChKZbUOt.js")).runLogin({ noBrowser: values["no-browser"] });
|
|
121
121
|
return;
|
|
122
122
|
}
|
|
123
123
|
if (positionals.length === 1 && positionals[0] === "parent" && Object.keys(values).length === 0) {
|
|
124
|
-
await (await import("./parent-
|
|
124
|
+
await (await import("./parent-QxKvaC2E.js")).runParent();
|
|
125
125
|
return;
|
|
126
126
|
}
|
|
127
127
|
if (values["no-browser"] !== void 0) throw new Error(usage);
|
|
@@ -130,33 +130,33 @@ async function main() {
|
|
|
130
130
|
const noLogFlags = values.run === void 0 && values.filter === void 0 && values.level === void 0 && values.limit === void 0 && values.live === void 0 && values.search === void 0 && values.since === void 0;
|
|
131
131
|
const noModeFlags = values["client-only"] === void 0 && values["server-only"] === void 0;
|
|
132
132
|
if (positionals.length === 1 && positionals[0] === "bootstrap" && noModeFlags && noGitFlags && noVariableFlags && noLogFlags && values.dist === void 0) {
|
|
133
|
-
await (await import("./init-
|
|
133
|
+
await (await import("./init-CAyEoy4P.js")).runBootstrap({
|
|
134
134
|
message: values.message,
|
|
135
135
|
install: values["no-install"] !== true
|
|
136
136
|
});
|
|
137
137
|
return;
|
|
138
138
|
}
|
|
139
139
|
if (positionals.length === 1 && positionals[0] === "generate" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noVariableFlags && noLogFlags && values.message === void 0 && values.dist === void 0) {
|
|
140
|
-
await (await import("./generate-
|
|
140
|
+
await (await import("./generate-cwMuaQE9.js")).runGenerate();
|
|
141
141
|
return;
|
|
142
142
|
}
|
|
143
143
|
if (positionals.length === 1 && positionals[0] === "build" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noVariableFlags && noLogFlags && values.message === void 0 && values.dist === void 0) {
|
|
144
|
-
await (await import("./build-
|
|
144
|
+
await (await import("./build-C3LFcX0i.js")).runBuild();
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
147
|
if (positionals.length === 1 && positionals[0] === "deploy" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noVariableFlags && noLogFlags) {
|
|
148
|
-
await (await import("./deploy-
|
|
148
|
+
await (await import("./deploy-oCP6VmLT.js")).runDeploy({
|
|
149
149
|
message: values.message,
|
|
150
150
|
dist: values.dist
|
|
151
151
|
});
|
|
152
152
|
return;
|
|
153
153
|
}
|
|
154
154
|
if (positionals.length === 2 && positionals[0] === "rollback" && values.message === void 0 && values.dist === void 0 && values["no-install"] === void 0 && noModeFlags && noGitFlags && noVariableFlags && noLogFlags) {
|
|
155
|
-
await (await import("./deploy-
|
|
155
|
+
await (await import("./deploy-oCP6VmLT.js")).runRollback(positionals[1]);
|
|
156
156
|
return;
|
|
157
157
|
}
|
|
158
158
|
if (positionals.length === 2 && positionals[0] === "init" && noModeFlags && noVariableFlags && noLogFlags) {
|
|
159
|
-
await (await import("./init-
|
|
159
|
+
await (await import("./init-CAyEoy4P.js")).runInit(positionals[1], {
|
|
160
160
|
commit: values["no-commit"] !== true,
|
|
161
161
|
git: values["no-git"] !== true,
|
|
162
162
|
install: values["no-install"] !== true
|
|
@@ -164,7 +164,7 @@ async function main() {
|
|
|
164
164
|
return;
|
|
165
165
|
}
|
|
166
166
|
if (positionals.length === 2 && positionals[0] === "new" && noGitFlags && noVariableFlags && noLogFlags) {
|
|
167
|
-
await (await import("./init-
|
|
167
|
+
await (await import("./init-CAyEoy4P.js")).runNew({
|
|
168
168
|
code: positionals[1],
|
|
169
169
|
message: values.message,
|
|
170
170
|
clientOnly: values["client-only"],
|
|
@@ -174,7 +174,7 @@ async function main() {
|
|
|
174
174
|
return;
|
|
175
175
|
}
|
|
176
176
|
if ((positionals.length === 1 || positionals.length === 2) && positionals[0] === "logs" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noVariableFlags) {
|
|
177
|
-
await (await import("./logs-
|
|
177
|
+
await (await import("./logs-C4QXSsBW.js")).runLogs({
|
|
178
178
|
code: positionals[1],
|
|
179
179
|
filter: values.filter,
|
|
180
180
|
run: values.run,
|
|
@@ -187,14 +187,14 @@ async function main() {
|
|
|
187
187
|
return;
|
|
188
188
|
}
|
|
189
189
|
if (positionals.length === 3 && positionals[0] === "schedules" && positionals[1] === "run" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noLogFlags && values.secret === void 0) {
|
|
190
|
-
await (await import("./schedules-
|
|
190
|
+
await (await import("./schedules-CThe3MC1.js")).runSchedule({
|
|
191
191
|
code: positionals[2],
|
|
192
192
|
yes: values.yes
|
|
193
193
|
});
|
|
194
194
|
return;
|
|
195
195
|
}
|
|
196
196
|
if ((positionals.length === 3 || positionals.length === 4) && positionals[0] === "variables" && positionals[1] === "set" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noLogFlags) {
|
|
197
|
-
await (await import("./variables-
|
|
197
|
+
await (await import("./variables-Cpd05u5N.js")).runVariablesSet({
|
|
198
198
|
key: positionals[2],
|
|
199
199
|
secret: values.secret,
|
|
200
200
|
value: positionals[3],
|
|
@@ -203,11 +203,11 @@ async function main() {
|
|
|
203
203
|
return;
|
|
204
204
|
}
|
|
205
205
|
if (positionals.length === 2 && positionals[0] === "variables" && positionals[1] === "list" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noVariableFlags && noLogFlags) {
|
|
206
|
-
await (await import("./variables-
|
|
206
|
+
await (await import("./variables-Cpd05u5N.js")).runVariablesList();
|
|
207
207
|
return;
|
|
208
208
|
}
|
|
209
209
|
if (positionals.length === 3 && positionals[0] === "variables" && positionals[1] === "delete" && values["no-install"] === void 0 && noModeFlags && noGitFlags && values.secret === void 0 && noLogFlags) {
|
|
210
|
-
await (await import("./variables-
|
|
210
|
+
await (await import("./variables-Cpd05u5N.js")).runVariablesDelete({
|
|
211
211
|
key: positionals[2],
|
|
212
212
|
yes: values.yes
|
|
213
213
|
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { c as organizationInstanceUrl, f as resolveAuthForOrg, i as bearerToken, l as readCredentialStore, p as resolveInstanceUrl, r as LoginRequiredError, t as AuthenticationError, u as rejectEnvironmentKey } from "./store-Dq9l7Qmw.js";
|
|
2
|
+
import { n as parseMe, t as loginWithDevice } from "./device-CcsD_wOD.js";
|
|
3
|
+
import "./workspace-BRRW36wG.js";
|
|
4
|
+
// src/auth.ts
|
|
5
|
+
async function fetchWithOrgAuth(orgCode, request) {
|
|
6
|
+
return withOrgAuth(orgCode, async (organizationUrl, accessToken) => {
|
|
7
|
+
const response = await request(organizationUrl, accessToken);
|
|
8
|
+
return {
|
|
9
|
+
response,
|
|
10
|
+
unauthorized: response.status === 401
|
|
11
|
+
};
|
|
12
|
+
}).then(({ response }) => response);
|
|
13
|
+
}
|
|
14
|
+
async function withOrgAuth(orgCode, request) {
|
|
15
|
+
const instanceUrl = await resolveInstanceUrl();
|
|
16
|
+
const organizationUrl = organizationInstanceUrl(instanceUrl, orgCode);
|
|
17
|
+
const auth = await resolveAuthForOrg(instanceUrl, orgCode).catch((error) => {
|
|
18
|
+
if (error instanceof LoginRequiredError && process.stdin.isTTY === true) return void 0;
|
|
19
|
+
throw error;
|
|
20
|
+
});
|
|
21
|
+
if (auth !== void 0) {
|
|
22
|
+
const result = await request(organizationUrl, bearerToken(auth));
|
|
23
|
+
if ("response" in result && result.response instanceof Response) rejectEnvironmentKey(result.response, auth);
|
|
24
|
+
if (!result.unauthorized) return result;
|
|
25
|
+
if (auth.source === "environment") throw new AuthenticationError("HITCH_API_KEY was rejected.");
|
|
26
|
+
}
|
|
27
|
+
if (process.stdin.isTTY !== true) throw new LoginRequiredError();
|
|
28
|
+
await loginWithDevice(instanceUrl, { expectedOrg: orgCode });
|
|
29
|
+
const credentials = await resolveAuthForOrg(instanceUrl, orgCode);
|
|
30
|
+
if (credentials === void 0) throw new Error(`login did not provide credentials for organization "${orgCode}"`);
|
|
31
|
+
return request(organizationUrl, bearerToken(credentials));
|
|
32
|
+
}
|
|
33
|
+
async function orgUsesHitchGit(org) {
|
|
34
|
+
const response = await fetchWithOrgAuth(org, (organizationUrl, token) => fetch(`${organizationUrl}/api/me/v1`, { headers: { Authorization: `Bearer ${token}` } }));
|
|
35
|
+
if (!response.ok) throw new AuthenticationError(`Could not read organization membership (${response.status}).`);
|
|
36
|
+
const membership = parseMe(await response.json()).memberships.find((item) => item.code === org);
|
|
37
|
+
if (membership === void 0) throw new AuthenticationError(`You are not a member of ${org}.`);
|
|
38
|
+
if (typeof membership.gitEnabled !== "boolean") throw new Error("The membership response has no \"gitEnabled\" flag. Update the Hitch server.");
|
|
39
|
+
return membership.gitEnabled;
|
|
40
|
+
}
|
|
41
|
+
async function canCheckHitchGit() {
|
|
42
|
+
if (process.env.GITHUB_ACTIONS === "true") return false;
|
|
43
|
+
if (process.env.HITCH_API_KEY) return true;
|
|
44
|
+
const instance = await resolveInstanceUrl();
|
|
45
|
+
return Object.entries((await readCredentialStore()).instances).some(([url, credentials]) => url === instance && Object.keys(credentials).length > 0);
|
|
46
|
+
}
|
|
47
|
+
export { withOrgAuth as i, fetchWithOrgAuth as n, orgUsesHitchGit as r, canCheckHitchGit as t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { i as runBuild } from "./build-Cnh7Owss.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as findAppletRoot } from "./workspace-
|
|
2
|
-
import { a as prepareAppletProjects, i as prepareAppletProject } from "./project-
|
|
1
|
+
import { n as findAppletRoot } from "./workspace-BRRW36wG.js";
|
|
2
|
+
import { a as prepareAppletProjects, i as prepareAppletProject } from "./project-BRwNCUCi.js";
|
|
3
3
|
import { rm } from "node:fs/promises";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { o as userAgent } from "./project-
|
|
1
|
+
import { p as resolveInstanceUrl } from "./store-Dq9l7Qmw.js";
|
|
2
|
+
import { o as userAgent } from "./project-BRwNCUCi.js";
|
|
3
3
|
// src/ci.ts
|
|
4
4
|
function githubActionsContext() {
|
|
5
5
|
const env = process.env;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import {
|
|
3
|
-
import { n as loadAppletSourceDefinition } from "./load-config-
|
|
4
|
-
import { i as prepareAppletProject } from "./project-
|
|
5
|
-
import { a as loadGitHubActionsSources, n as githubActionsContext, t as fetchWithGitHubActions } from "./ci-
|
|
6
|
-
import { n as buildPreparedApplet, r as prepareWorkspaceBuild, t as buildApplet } from "./build-
|
|
7
|
-
import { n as gitEnvironment, r as sourceHashes, t as SourceHashUnavailableError } from "./source-hash-
|
|
8
|
-
import { a as prepareGitDeploy, o as pushStagedCommit, s as refreshHitchMain, t as deployErrorMessage } from "./git-deploy-
|
|
9
|
-
import { n as childApplets, r as childHasChanges } from "./parent-
|
|
10
|
-
import { n as migrateWorkspace } from "./git-migration-
|
|
1
|
+
import { a as findWorkspaceRoot, n as findAppletRoot, o as isRootLayout, r as findParentRoot, s as readWorkspaceConfig } from "./workspace-BRRW36wG.js";
|
|
2
|
+
import { n as fetchWithOrgAuth, r as orgUsesHitchGit, t as canCheckHitchGit } from "./auth-DGCFAqPX.js";
|
|
3
|
+
import { n as loadAppletSourceDefinition } from "./load-config-0lXPytAo.js";
|
|
4
|
+
import { i as prepareAppletProject } from "./project-BRwNCUCi.js";
|
|
5
|
+
import { a as loadGitHubActionsSources, n as githubActionsContext, t as fetchWithGitHubActions } from "./ci-PuUsFgnN.js";
|
|
6
|
+
import { n as buildPreparedApplet, r as prepareWorkspaceBuild, t as buildApplet } from "./build-Cnh7Owss.js";
|
|
7
|
+
import { n as gitEnvironment, r as sourceHashes, t as SourceHashUnavailableError } from "./source-hash-Bp8v9JY1.js";
|
|
8
|
+
import { a as prepareGitDeploy, o as pushStagedCommit, s as refreshHitchMain, t as deployErrorMessage } from "./git-deploy-Cz-FCa93.js";
|
|
9
|
+
import { n as childApplets, r as childHasChanges } from "./parent-BGZHFiDn.js";
|
|
10
|
+
import { n as migrateWorkspace } from "./git-migration-BIw2cVoP.js";
|
|
11
11
|
import { createRequire } from "node:module";
|
|
12
12
|
import { existsSync } from "node:fs";
|
|
13
13
|
import { readFile, readdir } from "node:fs/promises";
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { a as credentialStorageMessage, c as organizationInstanceUrl, h as saveOAuthCredentials, l as readCredentialStore, s as normalizeInstanceUrl, t as AuthenticationError, u as rejectEnvironmentKey } from "./store-Dq9l7Qmw.js";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import readline from "node:readline/promises";
|
|
4
|
+
// ../shared/auth/src/device.ts
|
|
5
|
+
const CLIENT_ID = "hitch-cli-oauth";
|
|
6
|
+
const DEVICE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
7
|
+
function defaultOpenUrl(url) {
|
|
8
|
+
try {
|
|
9
|
+
const child = spawn(process.platform === "darwin" ? "open" : "xdg-open", [url], {
|
|
10
|
+
detached: true,
|
|
11
|
+
stdio: "ignore"
|
|
12
|
+
});
|
|
13
|
+
child.on("error", () => void 0);
|
|
14
|
+
child.unref();
|
|
15
|
+
} catch {}
|
|
16
|
+
}
|
|
17
|
+
function requiredObject(value, message) {
|
|
18
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(message);
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
async function jsonResponse(response) {
|
|
22
|
+
try {
|
|
23
|
+
return requiredObject(await response.json(), "Expected a JSON object response.");
|
|
24
|
+
} catch (error) {
|
|
25
|
+
throw new Error(`Invalid JSON response from ${response.url || "Hitch"}.`, { cause: error });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function postJson(fetcher, url, body) {
|
|
29
|
+
const response = await fetcher(url, {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: { "content-type": "application/json" },
|
|
32
|
+
body: JSON.stringify(body)
|
|
33
|
+
});
|
|
34
|
+
return {
|
|
35
|
+
body: await jsonResponse(response),
|
|
36
|
+
response
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function parseDeviceCode(value) {
|
|
40
|
+
if (typeof value.device_code !== "string" || typeof value.user_code !== "string" || typeof value.verification_uri !== "string" || typeof value.verification_uri_complete !== "string" || typeof value.expires_in !== "number" || value.interval !== void 0 && typeof value.interval !== "number") throw new AuthenticationError("Hitch returned an invalid device authorization response.");
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
function parseToken(value) {
|
|
44
|
+
return typeof value.access_token === "string" && typeof value.refresh_token === "string" && typeof value.expires_in === "number" && typeof value.token_type === "string" ? value : void 0;
|
|
45
|
+
}
|
|
46
|
+
function parseMe(input) {
|
|
47
|
+
const value = requiredObject(input, "Hitch returned an invalid identity response.");
|
|
48
|
+
const person = requiredObject(value.person, "Hitch returned an invalid identity response.");
|
|
49
|
+
if (typeof person.id !== "string" || typeof person.firstName !== "string" || typeof person.lastName !== "string" || typeof person.email !== "string" || !Array.isArray(value.memberships)) throw new Error("Hitch returned an invalid identity response.");
|
|
50
|
+
const organization = value.organization === void 0 || value.organization === null ? null : requiredObject(value.organization, "Hitch returned an invalid identity response.");
|
|
51
|
+
if (organization !== null && (typeof organization.id !== "string" || typeof organization.code !== "string")) throw new Error("Hitch returned an invalid identity response.");
|
|
52
|
+
return {
|
|
53
|
+
memberships: value.memberships.map((membership) => {
|
|
54
|
+
const item = requiredObject(membership, "Hitch returned an invalid membership.");
|
|
55
|
+
if (typeof item.orgId !== "string" || typeof item.code !== "string" || typeof item.name !== "string") throw new Error("Hitch returned an invalid membership.");
|
|
56
|
+
return item;
|
|
57
|
+
}),
|
|
58
|
+
organization,
|
|
59
|
+
person
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async function fetchMe(fetcher, instanceUrl, auth) {
|
|
63
|
+
const response = await fetcher(`${instanceUrl}/api/me/v1`, { headers: { Authorization: `Bearer ${auth.accessToken}` } });
|
|
64
|
+
rejectEnvironmentKey(response, auth);
|
|
65
|
+
if (auth.credentialType === "apiKey" && response.status === 401) throw new AuthenticationError("API key rejected.");
|
|
66
|
+
const body = await jsonResponse(response);
|
|
67
|
+
if (!response.ok) throw new AuthenticationError(typeof body.message === "string" ? body.message : `Failed to load the signed-in identity (${response.status}).`);
|
|
68
|
+
return parseMe(body);
|
|
69
|
+
}
|
|
70
|
+
async function pollForToken(fetcher, instanceUrl, resource, device, now, sleep) {
|
|
71
|
+
const deadline = now() + device.expires_in * 1e3;
|
|
72
|
+
let interval = (device.interval ?? 5) * 1e3;
|
|
73
|
+
while (now() < deadline) {
|
|
74
|
+
await sleep(Math.min(interval, deadline - now()));
|
|
75
|
+
if (now() >= deadline) break;
|
|
76
|
+
const response = await fetcher(`${instanceUrl}/api/auth/oauth2/token`, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
79
|
+
body: new URLSearchParams({
|
|
80
|
+
grant_type: DEVICE_GRANT,
|
|
81
|
+
device_code: device.device_code,
|
|
82
|
+
client_id: CLIENT_ID,
|
|
83
|
+
resource
|
|
84
|
+
})
|
|
85
|
+
});
|
|
86
|
+
const body = await jsonResponse(response);
|
|
87
|
+
const token = parseToken(body);
|
|
88
|
+
if (response.ok && token !== void 0) return token;
|
|
89
|
+
switch (body.error) {
|
|
90
|
+
case "authorization_pending": break;
|
|
91
|
+
case "slow_down":
|
|
92
|
+
interval += 5e3;
|
|
93
|
+
break;
|
|
94
|
+
case "expired_token": throw new AuthenticationError("The sign-in request expired. Run hitch login again.");
|
|
95
|
+
case "access_denied": throw new AuthenticationError("Sign-in was denied.");
|
|
96
|
+
default: throw new AuthenticationError(typeof body.error_description === "string" ? body.error_description : `Sign-in failed (${response.status}).`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
throw new AuthenticationError("The sign-in request expired. Run hitch login again.");
|
|
100
|
+
}
|
|
101
|
+
async function loginWithDevice(instanceUrl, options = {}) {
|
|
102
|
+
const fetcher = globalThis.fetch;
|
|
103
|
+
const now = Date.now;
|
|
104
|
+
const storedOrgs = Object.keys((await readCredentialStore()).instances[normalizeInstanceUrl(instanceUrl)] ?? {});
|
|
105
|
+
let orgCode = options.expectedOrg ?? process.env.HITCH_DEFAULT_ORG ?? (storedOrgs.length === 1 ? storedOrgs[0] : void 0);
|
|
106
|
+
if (orgCode === void 0 && process.stdin.isTTY === true) {
|
|
107
|
+
const terminal = readline.createInterface({
|
|
108
|
+
input: process.stdin,
|
|
109
|
+
output: process.stdout
|
|
110
|
+
});
|
|
111
|
+
try {
|
|
112
|
+
orgCode = (await terminal.question("Organization code: ")).trim();
|
|
113
|
+
} finally {
|
|
114
|
+
terminal.close();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (!orgCode) throw new AuthenticationError("Select an organization with --org or HITCH_DEFAULT_ORG.");
|
|
118
|
+
const organizationUrl = organizationInstanceUrl(instanceUrl, orgCode);
|
|
119
|
+
const resource = `${organizationUrl}/mcp`;
|
|
120
|
+
const { body, response } = await postJson(fetcher, `${instanceUrl}/api/auth/device/code`, {
|
|
121
|
+
client_id: CLIENT_ID,
|
|
122
|
+
scope: "openid offline_access",
|
|
123
|
+
resource
|
|
124
|
+
});
|
|
125
|
+
if (!response.ok) throw new AuthenticationError(typeof body.error_description === "string" ? body.error_description : `Could not start sign-in (${response.status}).`);
|
|
126
|
+
const device = parseDeviceCode(body);
|
|
127
|
+
const verificationUrl = device.verification_uri_complete;
|
|
128
|
+
console.log(`Open ${verificationUrl} and confirm code ${device.user_code}.`);
|
|
129
|
+
if (!options.noBrowser) try {
|
|
130
|
+
defaultOpenUrl(verificationUrl);
|
|
131
|
+
} catch {}
|
|
132
|
+
const token = await pollForToken(fetcher, instanceUrl, resource, device, now, (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)));
|
|
133
|
+
const me = await fetchMe(fetcher, organizationUrl, {
|
|
134
|
+
accessToken: token.access_token,
|
|
135
|
+
credentialType: "session",
|
|
136
|
+
source: "store"
|
|
137
|
+
});
|
|
138
|
+
const membership = me.memberships.find(({ code }) => code === orgCode);
|
|
139
|
+
if (membership === void 0) throw new AuthenticationError(`You are not a member of the Hitch organization "${orgCode}".`);
|
|
140
|
+
const credentials = await saveOAuthCredentials(instanceUrl, {
|
|
141
|
+
type: "oauth",
|
|
142
|
+
accessToken: token.access_token,
|
|
143
|
+
expiresAt: now() + token.expires_in * 1e3,
|
|
144
|
+
organizationId: membership.orgId,
|
|
145
|
+
orgCode
|
|
146
|
+
}, token.refresh_token);
|
|
147
|
+
const storageMessage = credentialStorageMessage();
|
|
148
|
+
if (storageMessage !== void 0) console.log(storageMessage);
|
|
149
|
+
return {
|
|
150
|
+
credentials,
|
|
151
|
+
me,
|
|
152
|
+
membership
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
export { parseMe as n, loginWithDevice as t };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as findAppletRoot } from "./workspace-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { i as
|
|
1
|
+
import { c as organizationInstanceUrl, p as resolveInstanceUrl } from "./store-Dq9l7Qmw.js";
|
|
2
|
+
import { n as findAppletRoot } from "./workspace-BRRW36wG.js";
|
|
3
|
+
import { n as fetchWithOrgAuth } from "./auth-DGCFAqPX.js";
|
|
4
|
+
import { t as loadAppletConfig } from "./load-config-0lXPytAo.js";
|
|
5
|
+
import { i as prepareAppletProject, o as userAgent } from "./project-BRwNCUCi.js";
|
|
6
|
+
import { i as loadGitHubActionsBuildInputs, n as githubActionsContext, r as hitchResponseError } from "./ci-PuUsFgnN.js";
|
|
6
7
|
import { createRequire } from "node:module";
|
|
7
8
|
import { isContractProcedure, minifyContractRouter } from "@orpc/contract";
|
|
8
9
|
import { randomUUID } from "node:crypto";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { r as runGenerate } from "./generate-DIgN2KC4.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as
|
|
1
|
+
import { c as organizationInstanceUrl, f as resolveAuthForOrg, r as LoginRequiredError, t as AuthenticationError } from "./store-Dq9l7Qmw.js";
|
|
2
2
|
// src/git-credential.ts
|
|
3
3
|
function parseGitCredentialHost(input, instanceUrl) {
|
|
4
4
|
const host = input.split(/\r?\n/).find((line) => line.startsWith("host="))?.slice(5);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { c as runClone } from "./git-deploy-Cz-FCa93.js";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as findWorkspaceRoot, o as isRootLayout, r as findParentRoot, t as SDK_VERSION_PATTERN } from "./workspace-
|
|
1
|
+
import { p as resolveInstanceUrl } from "./store-Dq9l7Qmw.js";
|
|
2
|
+
import { a as findWorkspaceRoot, o as isRootLayout, r as findParentRoot, t as SDK_VERSION_PATTERN } from "./workspace-BRRW36wG.js";
|
|
3
|
+
import { i as withOrgAuth } from "./auth-DGCFAqPX.js";
|
|
3
4
|
import { n as ORG_CODE_PATTERN, t as APPLET_CODE_PATTERN } from "./manifest-patterns-BfxqImlp.js";
|
|
4
|
-
import { n as gitEnvironment } from "./source-hash-
|
|
5
|
+
import { n as gitEnvironment } from "./source-hash-Bp8v9JY1.js";
|
|
5
6
|
import { n as stagedSecretPaths, t as StagedSecretsError } from "./git-safety-Ck3X7jvA.js";
|
|
6
7
|
import { existsSync } from "node:fs";
|
|
7
8
|
import { readFile } from "node:fs/promises";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { n as generatedAgentContents, r as writeGeneratedAgents } from "./generated-agents-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { n as loadAppletSourceDefinition } from "./load-config-
|
|
5
|
-
import { c as writeGitignore, r as loadPackageManifest } from "./project-
|
|
1
|
+
import { n as generatedAgentContents, r as writeGeneratedAgents } from "./generated-agents-XYtnda2w.js";
|
|
2
|
+
import { a as findWorkspaceRoot, n as findAppletRoot, o as isRootLayout, s as readWorkspaceConfig } from "./workspace-BRRW36wG.js";
|
|
3
|
+
import { r as orgUsesHitchGit, t as canCheckHitchGit } from "./auth-DGCFAqPX.js";
|
|
4
|
+
import { n as loadAppletSourceDefinition } from "./load-config-0lXPytAo.js";
|
|
5
|
+
import { c as writeGitignore, r as loadPackageManifest } from "./project-BRwNCUCi.js";
|
|
6
6
|
import { n as stagedSecretPaths, t as StagedSecretsError } from "./git-safety-Ck3X7jvA.js";
|
|
7
|
-
import { o as gitLocal } from "./parent-
|
|
7
|
+
import { o as gitLocal } from "./parent-BGZHFiDn.js";
|
|
8
8
|
import fs from "node:fs";
|
|
9
9
|
import fs$1 from "node:fs/promises";
|
|
10
10
|
import { basename, dirname, posix, resolve, sep } from "node:path";
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { r as writeGeneratedAgents } from "./generated-agents-
|
|
2
|
-
import {
|
|
3
|
-
import { a as findWorkspaceRoot, i as findWorkspaceConfig, o as isRootLayout, r as findParentRoot, s as readWorkspaceConfig } from "./workspace-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { r as writeGeneratedAgents } from "./generated-agents-XYtnda2w.js";
|
|
2
|
+
import { d as resolveAuth, f as resolveAuthForOrg, p as resolveInstanceUrl } from "./store-Dq9l7Qmw.js";
|
|
3
|
+
import { a as findWorkspaceRoot, i as findWorkspaceConfig, o as isRootLayout, r as findParentRoot, s as readWorkspaceConfig } from "./workspace-BRRW36wG.js";
|
|
4
|
+
import { r as orgUsesHitchGit, t as canCheckHitchGit } from "./auth-DGCFAqPX.js";
|
|
5
|
+
import { n as loadAppletSourceDefinition } from "./load-config-0lXPytAo.js";
|
|
6
|
+
import { r as runGenerate } from "./generate-DIgN2KC4.js";
|
|
6
7
|
import { n as ORG_CODE_PATTERN, t as APPLET_CODE_PATTERN } from "./manifest-patterns-BfxqImlp.js";
|
|
7
|
-
import { l as writeRootSupport, n as loadCliManifest, r as loadPackageManifest, s as writeAppletSupport, t as assertWorkspaceCli, u as writeWorkspaceSupport } from "./project-
|
|
8
|
-
import { n as childApplets } from "./parent-
|
|
9
|
-
import { t as migrateIfEnabled } from "./git-migration-
|
|
8
|
+
import { l as writeRootSupport, n as loadCliManifest, r as loadPackageManifest, s as writeAppletSupport, t as assertWorkspaceCli, u as writeWorkspaceSupport } from "./project-BRwNCUCi.js";
|
|
9
|
+
import { n as childApplets } from "./parent-BGZHFiDn.js";
|
|
10
|
+
import { t as migrateIfEnabled } from "./git-migration-BIw2cVoP.js";
|
|
10
11
|
import { access, cp, mkdir, readdir, writeFile } from "node:fs/promises";
|
|
11
12
|
import { relative, resolve } from "node:path";
|
|
12
13
|
import { spawn } from "node:child_process";
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import "./
|
|
2
|
-
import { c as validateRootManifest, i as findWorkspaceConfig, n as findAppletRoot, o as isRootLayout } from "./workspace-CtIKSgMD.js";
|
|
1
|
+
import { c as validateRootManifest, i as findWorkspaceConfig, n as findAppletRoot, o as isRootLayout } from "./workspace-BRRW36wG.js";
|
|
3
2
|
import { n as ORG_CODE_PATTERN, t as APPLET_CODE_PATTERN } from "./manifest-patterns-BfxqImlp.js";
|
|
4
3
|
import { z } from "zod";
|
|
5
4
|
import { existsSync } from "node:fs";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { l as readCredentialStore, m as revokeOAuthCredentials, o as deleteCredentials, p as resolveInstanceUrl, s as normalizeInstanceUrl, t as AuthenticationError } from "./store-Dq9l7Qmw.js";
|
|
2
|
+
import { t as loginWithDevice } from "./device-CcsD_wOD.js";
|
|
3
|
+
import { i as findWorkspaceConfig } from "./workspace-BRRW36wG.js";
|
|
3
4
|
// src/login.ts
|
|
4
5
|
async function runLogin(options) {
|
|
5
6
|
if (process.env.HITCH_API_KEY !== void 0) throw new AuthenticationError("HITCH_API_KEY is set — unset it to manage stored logins.");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { o as resolveWorkspaceOrg, t as loadAppletConfig } from "./load-config-
|
|
1
|
+
import { s as readWorkspaceConfig } from "./workspace-BRRW36wG.js";
|
|
2
|
+
import { n as fetchWithOrgAuth } from "./auth-DGCFAqPX.js";
|
|
3
|
+
import { o as resolveWorkspaceOrg, t as loadAppletConfig } from "./load-config-0lXPytAo.js";
|
|
4
4
|
import { t as APPLET_CODE_PATTERN } from "./manifest-patterns-BfxqImlp.js";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
// src/logs.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { r as writeGeneratedAgents } from "./generated-agents-
|
|
2
|
-
import { a as findWorkspaceRoot, o as isRootLayout, r as findParentRoot } from "./workspace-
|
|
3
|
-
import { n as gitEnvironment } from "./source-hash-
|
|
1
|
+
import { r as writeGeneratedAgents } from "./generated-agents-XYtnda2w.js";
|
|
2
|
+
import { a as findWorkspaceRoot, o as isRootLayout, r as findParentRoot } from "./workspace-BRRW36wG.js";
|
|
3
|
+
import { n as gitEnvironment } from "./source-hash-Bp8v9JY1.js";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import { readdir, writeFile } from "node:fs/promises";
|
|
6
6
|
import { dirname, resolve } from "node:path";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { i as runParent } from "./parent-BGZHFiDn.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { r as writeGeneratedAgents, t as GENERATED_SKILLS } from "./generated-agents-
|
|
2
|
-
import {
|
|
3
|
-
import { a as findWorkspaceRoot, n as findAppletRoot, o as isRootLayout, s as readWorkspaceConfig } from "./workspace-
|
|
4
|
-
import { n as loadAppletSourceDefinition, r as appletMountPath } from "./load-config-
|
|
1
|
+
import { r as writeGeneratedAgents, t as GENERATED_SKILLS } from "./generated-agents-XYtnda2w.js";
|
|
2
|
+
import { c as organizationInstanceUrl, n as DEFAULT_INSTANCE_URL } from "./store-Dq9l7Qmw.js";
|
|
3
|
+
import { a as findWorkspaceRoot, n as findAppletRoot, o as isRootLayout, s as readWorkspaceConfig } from "./workspace-BRRW36wG.js";
|
|
4
|
+
import { n as loadAppletSourceDefinition, r as appletMountPath } from "./load-config-0lXPytAo.js";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { cp, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as findAppletRoot } from "./workspace-
|
|
2
|
-
import { t as loadAppletConfig } from "./load-config-
|
|
1
|
+
import { n as findAppletRoot } from "./workspace-BRRW36wG.js";
|
|
2
|
+
import { t as loadAppletConfig } from "./load-config-0lXPytAo.js";
|
|
3
3
|
import { t as question } from "./prompt-CW98R-Un.js";
|
|
4
4
|
import { RPCLink } from "@orpc/client/fetch";
|
|
5
5
|
import { readFile } from "node:fs/promises";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as findWorkspaceRoot } from "./workspace-
|
|
1
|
+
import { a as findWorkspaceRoot } from "./workspace-BRRW36wG.js";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { lstat, readlink } from "node:fs/promises";
|
|
4
4
|
import { dirname, relative, resolve, sep } from "node:path";
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import "./workspace-CtIKSgMD.js";
|
|
2
1
|
import { randomUUID } from "node:crypto";
|
|
3
2
|
import fs from "node:fs/promises";
|
|
4
3
|
import { dirname, join } from "node:path";
|
|
5
|
-
import { spawn } from "node:child_process";
|
|
6
|
-
import readline from "node:readline/promises";
|
|
7
4
|
import { homedir } from "node:os";
|
|
8
5
|
import { Entry, findCredentials } from "@napi-rs/keyring";
|
|
9
|
-
// ../shared/auth/src/lock.
|
|
6
|
+
// ../shared/auth/src/lock.ts
|
|
10
7
|
const LOCK_AGE = 3e4;
|
|
11
8
|
function canTakeOverRefreshLock(age) {
|
|
12
9
|
return age > LOCK_AGE;
|
|
@@ -48,8 +45,8 @@ async function withFileLock(path, action) {
|
|
|
48
45
|
}
|
|
49
46
|
throw new AuthenticationError("Timed out while waiting for the credential lock.");
|
|
50
47
|
}
|
|
51
|
-
// ../shared/auth/src/oauth.
|
|
52
|
-
const CLIENT_ID
|
|
48
|
+
// ../shared/auth/src/oauth.ts
|
|
49
|
+
const CLIENT_ID = "hitch-cli-oauth";
|
|
53
50
|
const REFRESH_GRANT = "refresh_token";
|
|
54
51
|
async function saveOAuthCredentials(instanceUrl, credentials, refreshToken) {
|
|
55
52
|
const stored = {
|
|
@@ -82,7 +79,7 @@ async function refreshAccessToken(instanceUrl, orgCode) {
|
|
|
82
79
|
body: new URLSearchParams({
|
|
83
80
|
grant_type: REFRESH_GRANT,
|
|
84
81
|
refresh_token: refreshToken,
|
|
85
|
-
client_id: CLIENT_ID
|
|
82
|
+
client_id: CLIENT_ID,
|
|
86
83
|
resource: `${organizationInstanceUrl(instanceUrl, orgCode)}/mcp`
|
|
87
84
|
})
|
|
88
85
|
});
|
|
@@ -118,7 +115,7 @@ async function revokeOAuthCredentials(instanceUrl, credentials, warn = console.w
|
|
|
118
115
|
body: new URLSearchParams({
|
|
119
116
|
token: credentials.refreshToken,
|
|
120
117
|
token_type_hint: "refresh_token",
|
|
121
|
-
client_id: CLIENT_ID
|
|
118
|
+
client_id: CLIENT_ID
|
|
122
119
|
})
|
|
123
120
|
});
|
|
124
121
|
if (!response.ok) warn(`Warning: server sign-out failed (${response.status}).`);
|
|
@@ -128,7 +125,7 @@ async function revokeOAuthCredentials(instanceUrl, credentials, warn = console.w
|
|
|
128
125
|
await removeOAuthCredentials(instanceUrl, credentials.orgCode);
|
|
129
126
|
}
|
|
130
127
|
}
|
|
131
|
-
// ../shared/auth/src/store.
|
|
128
|
+
// ../shared/auth/src/store.ts
|
|
132
129
|
const DEFAULT_INSTANCE_URL = "https://app.hitch42.com";
|
|
133
130
|
var AuthenticationError = class extends Error {};
|
|
134
131
|
var LoginRequiredError = class extends AuthenticationError {
|
|
@@ -137,21 +134,12 @@ var LoginRequiredError = class extends AuthenticationError {
|
|
|
137
134
|
}
|
|
138
135
|
};
|
|
139
136
|
let selectedStore;
|
|
140
|
-
let keyringClass;
|
|
141
|
-
let findKeyringCredentials;
|
|
142
|
-
function configureKeyring(entryClass, findCredentials) {
|
|
143
|
-
keyringClass = entryClass;
|
|
144
|
-
findKeyringCredentials = findCredentials;
|
|
145
|
-
selectedStore = void 0;
|
|
146
|
-
}
|
|
147
137
|
function keyringEntry(account) {
|
|
148
|
-
if (keyringClass === void 0) throw new Error("Keyring is not configured.");
|
|
149
138
|
const options = process.platform === "linux" ? { linux: { store: "secret-service" } } : void 0;
|
|
150
|
-
return new
|
|
139
|
+
return new Entry("hitch", account, options);
|
|
151
140
|
}
|
|
152
141
|
function credentialStorage() {
|
|
153
142
|
if (selectedStore !== void 0) return selectedStore;
|
|
154
|
-
if (keyringClass === void 0) throw new Error("Keyring is not configured.");
|
|
155
143
|
selectedStore = (process.platform === "linux" || process.platform === "darwin" || process.platform === "win32" ? ["secret"] : []).find((candidate) => {
|
|
156
144
|
const probe = `__probe__${randomUUID()}`;
|
|
157
145
|
try {
|
|
@@ -177,8 +165,7 @@ function account(instanceUrl, orgCode) {
|
|
|
177
165
|
return `${normalizeInstanceUrl(instanceUrl)} ${orgCode}`;
|
|
178
166
|
}
|
|
179
167
|
function listKeyringCredentials() {
|
|
180
|
-
|
|
181
|
-
return findKeyringCredentials("hitch").filter(({ account }) => account !== "__index__");
|
|
168
|
+
return findCredentials("hitch").filter(({ account }) => account !== "__index__");
|
|
182
169
|
}
|
|
183
170
|
function readKeychainCredential(instanceUrl, orgCode) {
|
|
184
171
|
const value = keyringEntry(account(instanceUrl, orgCode)).getPassword();
|
|
@@ -449,199 +436,4 @@ async function updateFileCredentialStore(path, update) {
|
|
|
449
436
|
}
|
|
450
437
|
});
|
|
451
438
|
}
|
|
452
|
-
|
|
453
|
-
const CLIENT_ID = "hitch-cli-oauth";
|
|
454
|
-
const DEVICE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
455
|
-
function defaultOpenUrl(url) {
|
|
456
|
-
try {
|
|
457
|
-
const child = spawn(process.platform === "darwin" ? "open" : "xdg-open", [url], {
|
|
458
|
-
detached: true,
|
|
459
|
-
stdio: "ignore"
|
|
460
|
-
});
|
|
461
|
-
child.on("error", () => void 0);
|
|
462
|
-
child.unref();
|
|
463
|
-
} catch {}
|
|
464
|
-
}
|
|
465
|
-
function requiredObject(value, message) {
|
|
466
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(message);
|
|
467
|
-
return value;
|
|
468
|
-
}
|
|
469
|
-
async function jsonResponse(response) {
|
|
470
|
-
try {
|
|
471
|
-
return requiredObject(await response.json(), "Expected a JSON object response.");
|
|
472
|
-
} catch (error) {
|
|
473
|
-
throw new Error(`Invalid JSON response from ${response.url || "Hitch"}.`, { cause: error });
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
async function postJson(fetcher, url, body) {
|
|
477
|
-
const response = await fetcher(url, {
|
|
478
|
-
method: "POST",
|
|
479
|
-
headers: { "content-type": "application/json" },
|
|
480
|
-
body: JSON.stringify(body)
|
|
481
|
-
});
|
|
482
|
-
return {
|
|
483
|
-
body: await jsonResponse(response),
|
|
484
|
-
response
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
function parseDeviceCode(value) {
|
|
488
|
-
if (typeof value.device_code !== "string" || typeof value.user_code !== "string" || typeof value.verification_uri !== "string" || typeof value.verification_uri_complete !== "string" || typeof value.expires_in !== "number" || value.interval !== void 0 && typeof value.interval !== "number") throw new AuthenticationError("Hitch returned an invalid device authorization response.");
|
|
489
|
-
return value;
|
|
490
|
-
}
|
|
491
|
-
function parseToken(value) {
|
|
492
|
-
return typeof value.access_token === "string" && typeof value.refresh_token === "string" && typeof value.expires_in === "number" && typeof value.token_type === "string" ? value : void 0;
|
|
493
|
-
}
|
|
494
|
-
function parseMe(input) {
|
|
495
|
-
const value = requiredObject(input, "Hitch returned an invalid identity response.");
|
|
496
|
-
const person = requiredObject(value.person, "Hitch returned an invalid identity response.");
|
|
497
|
-
if (typeof person.id !== "string" || typeof person.firstName !== "string" || typeof person.lastName !== "string" || typeof person.email !== "string" || !Array.isArray(value.memberships)) throw new Error("Hitch returned an invalid identity response.");
|
|
498
|
-
const organization = value.organization === void 0 || value.organization === null ? null : requiredObject(value.organization, "Hitch returned an invalid identity response.");
|
|
499
|
-
if (organization !== null && (typeof organization.id !== "string" || typeof organization.code !== "string")) throw new Error("Hitch returned an invalid identity response.");
|
|
500
|
-
return {
|
|
501
|
-
memberships: value.memberships.map((membership) => {
|
|
502
|
-
const item = requiredObject(membership, "Hitch returned an invalid membership.");
|
|
503
|
-
if (typeof item.orgId !== "string" || typeof item.code !== "string" || typeof item.name !== "string") throw new Error("Hitch returned an invalid membership.");
|
|
504
|
-
return item;
|
|
505
|
-
}),
|
|
506
|
-
organization,
|
|
507
|
-
person
|
|
508
|
-
};
|
|
509
|
-
}
|
|
510
|
-
async function fetchMe(fetcher, instanceUrl, auth) {
|
|
511
|
-
const response = await fetcher(`${instanceUrl}/api/me/v1`, { headers: { Authorization: `Bearer ${auth.accessToken}` } });
|
|
512
|
-
rejectEnvironmentKey(response, auth);
|
|
513
|
-
if (auth.credentialType === "apiKey" && response.status === 401) throw new AuthenticationError("API key rejected.");
|
|
514
|
-
const body = await jsonResponse(response);
|
|
515
|
-
if (!response.ok) throw new AuthenticationError(typeof body.message === "string" ? body.message : `Failed to load the signed-in identity (${response.status}).`);
|
|
516
|
-
return parseMe(body);
|
|
517
|
-
}
|
|
518
|
-
async function pollForToken(fetcher, instanceUrl, resource, device, now, sleep) {
|
|
519
|
-
const deadline = now() + device.expires_in * 1e3;
|
|
520
|
-
let interval = (device.interval ?? 5) * 1e3;
|
|
521
|
-
while (now() < deadline) {
|
|
522
|
-
await sleep(Math.min(interval, deadline - now()));
|
|
523
|
-
if (now() >= deadline) break;
|
|
524
|
-
const response = await fetcher(`${instanceUrl}/api/auth/oauth2/token`, {
|
|
525
|
-
method: "POST",
|
|
526
|
-
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
527
|
-
body: new URLSearchParams({
|
|
528
|
-
grant_type: DEVICE_GRANT,
|
|
529
|
-
device_code: device.device_code,
|
|
530
|
-
client_id: CLIENT_ID,
|
|
531
|
-
resource
|
|
532
|
-
})
|
|
533
|
-
});
|
|
534
|
-
const body = await jsonResponse(response);
|
|
535
|
-
const token = parseToken(body);
|
|
536
|
-
if (response.ok && token !== void 0) return token;
|
|
537
|
-
switch (body.error) {
|
|
538
|
-
case "authorization_pending": break;
|
|
539
|
-
case "slow_down":
|
|
540
|
-
interval += 5e3;
|
|
541
|
-
break;
|
|
542
|
-
case "expired_token": throw new AuthenticationError("The sign-in request expired. Run hitch login again.");
|
|
543
|
-
case "access_denied": throw new AuthenticationError("Sign-in was denied.");
|
|
544
|
-
default: throw new AuthenticationError(typeof body.error_description === "string" ? body.error_description : `Sign-in failed (${response.status}).`);
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
throw new AuthenticationError("The sign-in request expired. Run hitch login again.");
|
|
548
|
-
}
|
|
549
|
-
async function loginWithDevice(instanceUrl, options = {}) {
|
|
550
|
-
const fetcher = globalThis.fetch;
|
|
551
|
-
const now = Date.now;
|
|
552
|
-
const storedOrgs = Object.keys((await readCredentialStore()).instances[normalizeInstanceUrl(instanceUrl)] ?? {});
|
|
553
|
-
let orgCode = options.expectedOrg ?? process.env.HITCH_DEFAULT_ORG ?? (storedOrgs.length === 1 ? storedOrgs[0] : void 0);
|
|
554
|
-
if (orgCode === void 0 && process.stdin.isTTY === true) {
|
|
555
|
-
const terminal = readline.createInterface({
|
|
556
|
-
input: process.stdin,
|
|
557
|
-
output: process.stdout
|
|
558
|
-
});
|
|
559
|
-
try {
|
|
560
|
-
orgCode = (await terminal.question("Organization code: ")).trim();
|
|
561
|
-
} finally {
|
|
562
|
-
terminal.close();
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
if (!orgCode) throw new AuthenticationError("Select an organization with --org or HITCH_DEFAULT_ORG.");
|
|
566
|
-
const organizationUrl = organizationInstanceUrl(instanceUrl, orgCode);
|
|
567
|
-
const resource = `${organizationUrl}/mcp`;
|
|
568
|
-
const { body, response } = await postJson(fetcher, `${instanceUrl}/api/auth/device/code`, {
|
|
569
|
-
client_id: CLIENT_ID,
|
|
570
|
-
scope: "openid offline_access",
|
|
571
|
-
resource
|
|
572
|
-
});
|
|
573
|
-
if (!response.ok) throw new AuthenticationError(typeof body.error_description === "string" ? body.error_description : `Could not start sign-in (${response.status}).`);
|
|
574
|
-
const device = parseDeviceCode(body);
|
|
575
|
-
const verificationUrl = device.verification_uri_complete;
|
|
576
|
-
console.log(`Open ${verificationUrl} and confirm code ${device.user_code}.`);
|
|
577
|
-
if (!options.noBrowser) try {
|
|
578
|
-
defaultOpenUrl(verificationUrl);
|
|
579
|
-
} catch {}
|
|
580
|
-
const token = await pollForToken(fetcher, instanceUrl, resource, device, now, (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)));
|
|
581
|
-
const me = await fetchMe(fetcher, organizationUrl, {
|
|
582
|
-
accessToken: token.access_token,
|
|
583
|
-
credentialType: "session",
|
|
584
|
-
source: "store"
|
|
585
|
-
});
|
|
586
|
-
const membership = me.memberships.find(({ code }) => code === orgCode);
|
|
587
|
-
if (membership === void 0) throw new AuthenticationError(`You are not a member of the Hitch organization "${orgCode}".`);
|
|
588
|
-
const credentials = await saveOAuthCredentials(instanceUrl, {
|
|
589
|
-
type: "oauth",
|
|
590
|
-
accessToken: token.access_token,
|
|
591
|
-
expiresAt: now() + token.expires_in * 1e3,
|
|
592
|
-
organizationId: membership.orgId,
|
|
593
|
-
orgCode
|
|
594
|
-
}, token.refresh_token);
|
|
595
|
-
const storageMessage = credentialStorageMessage();
|
|
596
|
-
if (storageMessage !== void 0) console.log(storageMessage);
|
|
597
|
-
return {
|
|
598
|
-
credentials,
|
|
599
|
-
me,
|
|
600
|
-
membership
|
|
601
|
-
};
|
|
602
|
-
}
|
|
603
|
-
// src/auth.ts
|
|
604
|
-
configureKeyring(Entry, findCredentials);
|
|
605
|
-
async function fetchWithOrgAuth(orgCode, request) {
|
|
606
|
-
return withOrgAuth(orgCode, async (organizationUrl, accessToken) => {
|
|
607
|
-
const response = await request(organizationUrl, accessToken);
|
|
608
|
-
return {
|
|
609
|
-
response,
|
|
610
|
-
unauthorized: response.status === 401
|
|
611
|
-
};
|
|
612
|
-
}).then(({ response }) => response);
|
|
613
|
-
}
|
|
614
|
-
async function withOrgAuth(orgCode, request) {
|
|
615
|
-
const instanceUrl = await resolveInstanceUrl();
|
|
616
|
-
const organizationUrl = organizationInstanceUrl(instanceUrl, orgCode);
|
|
617
|
-
const auth = await resolveAuthForOrg(instanceUrl, orgCode).catch((error) => {
|
|
618
|
-
if (error instanceof LoginRequiredError && process.stdin.isTTY === true) return void 0;
|
|
619
|
-
throw error;
|
|
620
|
-
});
|
|
621
|
-
if (auth !== void 0) {
|
|
622
|
-
const result = await request(organizationUrl, bearerToken(auth));
|
|
623
|
-
if ("response" in result && result.response instanceof Response) rejectEnvironmentKey(result.response, auth);
|
|
624
|
-
if (!result.unauthorized) return result;
|
|
625
|
-
if (auth.source === "environment") throw new AuthenticationError("HITCH_API_KEY was rejected.");
|
|
626
|
-
}
|
|
627
|
-
if (process.stdin.isTTY !== true) throw new LoginRequiredError();
|
|
628
|
-
await loginWithDevice(instanceUrl, { expectedOrg: orgCode });
|
|
629
|
-
const credentials = await resolveAuthForOrg(instanceUrl, orgCode);
|
|
630
|
-
if (credentials === void 0) throw new Error(`login did not provide credentials for organization "${orgCode}"`);
|
|
631
|
-
return request(organizationUrl, bearerToken(credentials));
|
|
632
|
-
}
|
|
633
|
-
async function orgUsesHitchGit(org) {
|
|
634
|
-
const response = await fetchWithOrgAuth(org, (organizationUrl, token) => fetch(`${organizationUrl}/api/me/v1`, { headers: { Authorization: `Bearer ${token}` } }));
|
|
635
|
-
if (!response.ok) throw new AuthenticationError(`Could not read organization membership (${response.status}).`);
|
|
636
|
-
const membership = parseMe(await response.json()).memberships.find((item) => item.code === org);
|
|
637
|
-
if (membership === void 0) throw new AuthenticationError(`You are not a member of ${org}.`);
|
|
638
|
-
if (typeof membership.gitEnabled !== "boolean") throw new Error("The membership response has no \"gitEnabled\" flag. Update the Hitch server.");
|
|
639
|
-
return membership.gitEnabled;
|
|
640
|
-
}
|
|
641
|
-
async function canCheckHitchGit() {
|
|
642
|
-
if (process.env.GITHUB_ACTIONS === "true") return false;
|
|
643
|
-
if (process.env.HITCH_API_KEY) return true;
|
|
644
|
-
const instance = await resolveInstanceUrl();
|
|
645
|
-
return Object.entries((await readCredentialStore()).instances).some(([url, credentials]) => url === instance && Object.keys(credentials).length > 0);
|
|
646
|
-
}
|
|
647
|
-
export { resolveInstanceUrl as _, loginWithDevice as a, LoginRequiredError as c, normalizeInstanceUrl as d, organizationInstanceUrl as f, resolveAuthForOrg as g, resolveAuth as h, withOrgAuth as i, bearerToken as l, rejectEnvironmentKey as m, fetchWithOrgAuth as n, AuthenticationError as o, readCredentialStore as p, orgUsesHitchGit as r, DEFAULT_INSTANCE_URL as s, canCheckHitchGit as t, deleteCredentials as u, revokeOAuthCredentials as v };
|
|
439
|
+
export { credentialStorageMessage as a, organizationInstanceUrl as c, resolveAuth as d, resolveAuthForOrg as f, saveOAuthCredentials as h, bearerToken as i, readCredentialStore as l, revokeOAuthCredentials as m, DEFAULT_INSTANCE_URL as n, deleteCredentials as o, resolveInstanceUrl as p, LoginRequiredError as r, normalizeInstanceUrl as s, AuthenticationError as t, rejectEnvironmentKey as u };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as fetchWithOrgAuth } from "./auth-
|
|
2
|
-
import { t as loadAppletConfig } from "./load-config-
|
|
1
|
+
import { n as fetchWithOrgAuth } from "./auth-DGCFAqPX.js";
|
|
2
|
+
import { t as loadAppletConfig } from "./load-config-0lXPytAo.js";
|
|
3
3
|
import { t as question } from "./prompt-CW98R-Un.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
// src/variables.ts
|
package/dist/vite.js
CHANGED
|
@@ -2,11 +2,11 @@ import { t as pruneContract } from "./contract-D9LCNGjD.js";
|
|
|
2
2
|
import { a as openQueryCacheDatabase } from "./query-cache-DQJy45RT.js";
|
|
3
3
|
import { d as HITCH_SESSION_HEADER, f as HITCH_USER_HEADER } from "./headers-BcEMIVCo.js";
|
|
4
4
|
import { a as workflowOutcomeSchema, n as runWorkflowJournal } from "./workflow-engine-CyyaVENo.js";
|
|
5
|
-
import { r as writeGeneratedAgents } from "./generated-agents-
|
|
6
|
-
import {
|
|
7
|
-
import { c as validateRootManifest, o as isRootLayout } from "./workspace-
|
|
8
|
-
import { a as appletSourceDefinitionSchema, i as appletReleaseManifest, o as resolveWorkspaceOrg, r as appletMountPath } from "./load-config-
|
|
9
|
-
import { a as writeRegisterDeclaration, c as writeAppletRoot, d as writeServerEntry, i as syncContract, l as writeClientEntry, n as routesModuleSource, u as writeManifestGen } from "./generate-
|
|
5
|
+
import { r as writeGeneratedAgents } from "./generated-agents-XYtnda2w.js";
|
|
6
|
+
import { c as organizationInstanceUrl, f as resolveAuthForOrg, i as bearerToken, p as resolveInstanceUrl, u as rejectEnvironmentKey } from "./store-Dq9l7Qmw.js";
|
|
7
|
+
import { c as validateRootManifest, o as isRootLayout } from "./workspace-BRRW36wG.js";
|
|
8
|
+
import { a as appletSourceDefinitionSchema, i as appletReleaseManifest, o as resolveWorkspaceOrg, r as appletMountPath } from "./load-config-0lXPytAo.js";
|
|
9
|
+
import { a as writeRegisterDeclaration, c as writeAppletRoot, d as writeServerEntry, i as syncContract, l as writeClientEntry, n as routesModuleSource, u as writeManifestGen } from "./generate-DIgN2KC4.js";
|
|
10
10
|
import { t as APPLET_CODE_PATTERN } from "./manifest-patterns-BfxqImlp.js";
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
import { randomUUID } from "node:crypto";
|
|
@@ -2,7 +2,7 @@ import { createRequire, registerHooks } from "node:module";
|
|
|
2
2
|
import { pathToFileURL } from "node:url";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import { basename, dirname, resolve } from "node:path";
|
|
5
|
-
// ../shared/auth/src/workspace.
|
|
5
|
+
// ../shared/auth/src/workspace.ts
|
|
6
6
|
const ORG_CODE_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
7
7
|
const require = createRequire(import.meta.url);
|
|
8
8
|
var WorkspaceValidationError = class extends Error {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hitch42/applet",
|
|
3
|
-
"version": "0.1.1-beta.
|
|
3
|
+
"version": "0.1.1-beta.24",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bin": {
|
|
6
6
|
"applet": "./dist/applet.js"
|
|
@@ -13,8 +13,7 @@
|
|
|
13
13
|
],
|
|
14
14
|
"type": "module",
|
|
15
15
|
"sideEffects": [
|
|
16
|
-
"*.css"
|
|
17
|
-
"./src/auth.ts"
|
|
16
|
+
"*.css"
|
|
18
17
|
],
|
|
19
18
|
"exports": {
|
|
20
19
|
".": {
|
package/dist/build-YzjhhLw0.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { i as runBuild } from "./build-CrrTAX6T.js";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { r as runGenerate } from "./generate-Ct-Rbh0f.js";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { c as runClone } from "./git-deploy-BjSAv5Qm.js";
|
package/dist/parent-D52Kxp8U.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { i as runParent } from "./parent-Zx8Eg1Ki.js";
|