@hitch42/applet 0.1.1-beta.22 → 0.1.1-beta.23
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 +16 -16
- package/dist/{store-E5NhITHl.js → auth-OvyoB6M-.js} +203 -4
- package/dist/{build-FAQSHJgm.js → build-CrrTAX6T.js} +1 -1
- package/dist/build-YzjhhLw0.js +1 -0
- package/dist/{ci-oWlUJKm9.js → ci-B1XyXpHa.js} +2 -2
- package/dist/client/react/markdown.js +1 -1
- package/dist/client/react.js +1 -1
- package/dist/{deploy-BM55ZoSp.js → deploy-WdARFHmA.js} +7 -7
- package/dist/{generate-DNgO44RO.js → generate-Ct-Rbh0f.js} +4 -5
- package/dist/generate-_u-zFzrv.js +1 -0
- package/dist/{git-credential-CU7-Erzs.js → git-credential-DuLNowIb.js} +1 -1
- package/dist/{git-deploy-C12nMNB6.js → git-deploy-BjSAv5Qm.js} +1 -2
- package/dist/git-deploy-CByu_uli.js +1 -0
- package/dist/{git-migration-CIq-sN61.js → git-migration-6V31iafL.js} +3 -3
- package/dist/{init-BD5mC_9L.js → init-C5HqIRt8.js} +5 -6
- package/dist/{load-config-Cffvj-aM.js → load-config-Df-zmfrd.js} +1 -0
- package/dist/{login-BWZKo7Ui.js → login-B41-WWtD.js} +1 -2
- package/dist/{logs-glCVHI-8.js → logs-DrL2ytmg.js} +2 -2
- package/dist/{markdown-BA_XzFxq.js → markdown-DLdJOJ59.js} +2 -0
- package/dist/{project-DZGk765E.js → project-BbpU_VN2.js} +2 -2
- package/dist/{schedules-CSUb84e2.js → schedules-2Q_fkY_a.js} +1 -1
- package/dist/{variables-CgZstC7I.js → variables-CGwbmUom.js} +2 -2
- package/dist/vite.js +3 -3
- package/package.json +8 -7
- package/dist/auth-DuMRqSGe.js +0 -49
- package/dist/build-C7hi2yg4.js +0 -1
- package/dist/device-CZWWckCq.js +0 -155
- package/dist/generate-DG9vVkBO.js +0 -1
- package/dist/git-deploy-CNz6mxiF.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-DuLNowIb.js")).runGitCredential(args[2] ?? "", args[1]);
|
|
80
80
|
return;
|
|
81
81
|
}
|
|
82
82
|
const { positionals, values } = parseArgs({
|
|
@@ -109,15 +109,15 @@ 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-CByu_uli.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-B41-WWtD.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-B41-WWtD.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) {
|
|
@@ -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-C5HqIRt8.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-_u-zFzrv.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-YzjhhLw0.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-WdARFHmA.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-WdARFHmA.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-C5HqIRt8.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-C5HqIRt8.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-DrL2ytmg.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-2Q_fkY_a.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-CGwbmUom.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-CGwbmUom.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-CGwbmUom.js")).runVariablesDelete({
|
|
211
211
|
key: positionals[2],
|
|
212
212
|
yes: values.yes
|
|
213
213
|
});
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import "./workspace-CtIKSgMD.js";
|
|
1
2
|
import { randomUUID } from "node:crypto";
|
|
2
3
|
import fs from "node:fs/promises";
|
|
3
4
|
import { dirname, join } from "node:path";
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
6
|
+
import readline from "node:readline/promises";
|
|
4
7
|
import { homedir } from "node:os";
|
|
8
|
+
import { Entry, findCredentials } from "@napi-rs/keyring";
|
|
5
9
|
// ../shared/auth/src/lock.mts
|
|
6
10
|
const LOCK_AGE = 3e4;
|
|
7
11
|
function canTakeOverRefreshLock(age) {
|
|
@@ -45,7 +49,7 @@ async function withFileLock(path, action) {
|
|
|
45
49
|
throw new AuthenticationError("Timed out while waiting for the credential lock.");
|
|
46
50
|
}
|
|
47
51
|
// ../shared/auth/src/oauth.mts
|
|
48
|
-
const CLIENT_ID = "hitch-cli-oauth";
|
|
52
|
+
const CLIENT_ID$1 = "hitch-cli-oauth";
|
|
49
53
|
const REFRESH_GRANT = "refresh_token";
|
|
50
54
|
async function saveOAuthCredentials(instanceUrl, credentials, refreshToken) {
|
|
51
55
|
const stored = {
|
|
@@ -78,7 +82,7 @@ async function refreshAccessToken(instanceUrl, orgCode) {
|
|
|
78
82
|
body: new URLSearchParams({
|
|
79
83
|
grant_type: REFRESH_GRANT,
|
|
80
84
|
refresh_token: refreshToken,
|
|
81
|
-
client_id: CLIENT_ID,
|
|
85
|
+
client_id: CLIENT_ID$1,
|
|
82
86
|
resource: `${organizationInstanceUrl(instanceUrl, orgCode)}/mcp`
|
|
83
87
|
})
|
|
84
88
|
});
|
|
@@ -114,7 +118,7 @@ async function revokeOAuthCredentials(instanceUrl, credentials, warn = console.w
|
|
|
114
118
|
body: new URLSearchParams({
|
|
115
119
|
token: credentials.refreshToken,
|
|
116
120
|
token_type_hint: "refresh_token",
|
|
117
|
-
client_id: CLIENT_ID
|
|
121
|
+
client_id: CLIENT_ID$1
|
|
118
122
|
})
|
|
119
123
|
});
|
|
120
124
|
if (!response.ok) warn(`Warning: server sign-out failed (${response.status}).`);
|
|
@@ -445,4 +449,199 @@ async function updateFileCredentialStore(path, update) {
|
|
|
445
449
|
}
|
|
446
450
|
});
|
|
447
451
|
}
|
|
448
|
-
|
|
452
|
+
// ../shared/auth/src/device.mts
|
|
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 };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as findAppletRoot } from "./workspace-CtIKSgMD.js";
|
|
2
|
-
import { a as prepareAppletProjects, i as prepareAppletProject } from "./project-
|
|
2
|
+
import { a as prepareAppletProjects, i as prepareAppletProject } from "./project-BbpU_VN2.js";
|
|
3
3
|
import { rm } from "node:fs/promises";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { i as runBuild } from "./build-CrrTAX6T.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { o as userAgent } from "./project-
|
|
1
|
+
import { _ as resolveInstanceUrl } from "./auth-OvyoB6M-.js";
|
|
2
|
+
import { o as userAgent } from "./project-BbpU_VN2.js";
|
|
3
3
|
// src/ci.ts
|
|
4
4
|
function githubActionsContext() {
|
|
5
5
|
const env = process.env;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as Markdown } from "../../markdown-
|
|
1
|
+
export { t as Markdown } from "../../markdown-DLdJOJ59.js";
|
package/dist/client/react.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import { n as fetchWithOrgAuth, r as orgUsesHitchGit, t as canCheckHitchGit } from "./auth-OvyoB6M-.js";
|
|
1
2
|
import { a as findWorkspaceRoot, n as findAppletRoot, o as isRootLayout, r as findParentRoot, s as readWorkspaceConfig } from "./workspace-CtIKSgMD.js";
|
|
2
|
-
import { n as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { n as buildPreparedApplet, r as prepareWorkspaceBuild, t as buildApplet } from "./build-FAQSHJgm.js";
|
|
3
|
+
import { n as loadAppletSourceDefinition } from "./load-config-Df-zmfrd.js";
|
|
4
|
+
import { i as prepareAppletProject } from "./project-BbpU_VN2.js";
|
|
5
|
+
import { a as loadGitHubActionsSources, n as githubActionsContext, t as fetchWithGitHubActions } from "./ci-B1XyXpHa.js";
|
|
6
|
+
import { n as buildPreparedApplet, r as prepareWorkspaceBuild, t as buildApplet } from "./build-CrrTAX6T.js";
|
|
7
7
|
import { n as gitEnvironment, r as sourceHashes, t as SourceHashUnavailableError } from "./source-hash-BbvtRaus.js";
|
|
8
|
-
import { a as prepareGitDeploy, o as pushStagedCommit, s as refreshHitchMain, t as deployErrorMessage } from "./git-deploy-
|
|
8
|
+
import { a as prepareGitDeploy, o as pushStagedCommit, s as refreshHitchMain, t as deployErrorMessage } from "./git-deploy-BjSAv5Qm.js";
|
|
9
9
|
import { n as childApplets, r as childHasChanges } from "./parent-Zx8Eg1Ki.js";
|
|
10
|
-
import { n as migrateWorkspace } from "./git-migration-
|
|
10
|
+
import { n as migrateWorkspace } from "./git-migration-6V31iafL.js";
|
|
11
11
|
import { createRequire } from "node:module";
|
|
12
12
|
import { existsSync } from "node:fs";
|
|
13
13
|
import { readFile, readdir } from "node:fs/promises";
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as resolveInstanceUrl, f as organizationInstanceUrl, n as fetchWithOrgAuth } from "./auth-OvyoB6M-.js";
|
|
2
2
|
import { n as findAppletRoot } from "./workspace-CtIKSgMD.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { i as
|
|
6
|
-
import { i as loadGitHubActionsBuildInputs, n as githubActionsContext, r as hitchResponseError } from "./ci-oWlUJKm9.js";
|
|
3
|
+
import { t as loadAppletConfig } from "./load-config-Df-zmfrd.js";
|
|
4
|
+
import { i as prepareAppletProject, o as userAgent } from "./project-BbpU_VN2.js";
|
|
5
|
+
import { i as loadGitHubActionsBuildInputs, n as githubActionsContext, r as hitchResponseError } from "./ci-B1XyXpHa.js";
|
|
7
6
|
import { createRequire } from "node:module";
|
|
8
7
|
import { isContractProcedure, minifyContractRouter } from "@orpc/contract";
|
|
9
8
|
import { randomUUID } from "node:crypto";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { r as runGenerate } from "./generate-Ct-Rbh0f.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as LoginRequiredError, f as organizationInstanceUrl, g as resolveAuthForOrg, o as AuthenticationError } from "./auth-OvyoB6M-.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);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as resolveInstanceUrl, i as withOrgAuth } from "./auth-OvyoB6M-.js";
|
|
2
2
|
import { a as findWorkspaceRoot, o as isRootLayout, r as findParentRoot, t as SDK_VERSION_PATTERN } from "./workspace-CtIKSgMD.js";
|
|
3
|
-
import { i as withOrgAuth } from "./auth-DuMRqSGe.js";
|
|
4
3
|
import { n as ORG_CODE_PATTERN, t as APPLET_CODE_PATTERN } from "./manifest-patterns-BfxqImlp.js";
|
|
5
4
|
import { n as gitEnvironment } from "./source-hash-BbvtRaus.js";
|
|
6
5
|
import { n as stagedSecretPaths, t as StagedSecretsError } from "./git-safety-Ck3X7jvA.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { c as runClone } from "./git-deploy-BjSAv5Qm.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { n as generatedAgentContents, r as writeGeneratedAgents } from "./generated-agents-BUnJ0FQA.js";
|
|
2
|
+
import { r as orgUsesHitchGit, t as canCheckHitchGit } from "./auth-OvyoB6M-.js";
|
|
2
3
|
import { a as findWorkspaceRoot, n as findAppletRoot, o as isRootLayout, s as readWorkspaceConfig } from "./workspace-CtIKSgMD.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { c as writeGitignore, r as loadPackageManifest } from "./project-DZGk765E.js";
|
|
4
|
+
import { n as loadAppletSourceDefinition } from "./load-config-Df-zmfrd.js";
|
|
5
|
+
import { c as writeGitignore, r as loadPackageManifest } from "./project-BbpU_VN2.js";
|
|
6
6
|
import { n as stagedSecretPaths, t as StagedSecretsError } from "./git-safety-Ck3X7jvA.js";
|
|
7
7
|
import { o as gitLocal } from "./parent-Zx8Eg1Ki.js";
|
|
8
8
|
import fs from "node:fs";
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { r as writeGeneratedAgents } from "./generated-agents-BUnJ0FQA.js";
|
|
2
|
-
import {
|
|
2
|
+
import { _ as resolveInstanceUrl, g as resolveAuthForOrg, h as resolveAuth, r as orgUsesHitchGit, t as canCheckHitchGit } from "./auth-OvyoB6M-.js";
|
|
3
3
|
import { a as findWorkspaceRoot, i as findWorkspaceConfig, o as isRootLayout, r as findParentRoot, s as readWorkspaceConfig } from "./workspace-CtIKSgMD.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { r as runGenerate } from "./generate-DNgO44RO.js";
|
|
4
|
+
import { n as loadAppletSourceDefinition } from "./load-config-Df-zmfrd.js";
|
|
5
|
+
import { r as runGenerate } from "./generate-Ct-Rbh0f.js";
|
|
7
6
|
import { n as ORG_CODE_PATTERN, t as APPLET_CODE_PATTERN } from "./manifest-patterns-BfxqImlp.js";
|
|
8
|
-
import { l as writeRootSupport, n as loadCliManifest, r as loadPackageManifest, s as writeAppletSupport, t as assertWorkspaceCli, u as writeWorkspaceSupport } from "./project-
|
|
7
|
+
import { l as writeRootSupport, n as loadCliManifest, r as loadPackageManifest, s as writeAppletSupport, t as assertWorkspaceCli, u as writeWorkspaceSupport } from "./project-BbpU_VN2.js";
|
|
9
8
|
import { n as childApplets } from "./parent-Zx8Eg1Ki.js";
|
|
10
|
-
import { t as migrateIfEnabled } from "./git-migration-
|
|
9
|
+
import { t as migrateIfEnabled } from "./git-migration-6V31iafL.js";
|
|
11
10
|
import { access, cp, mkdir, readdir, writeFile } from "node:fs/promises";
|
|
12
11
|
import { relative, resolve } from "node:path";
|
|
13
12
|
import { spawn } from "node:child_process";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "./auth-OvyoB6M-.js";
|
|
1
2
|
import { c as validateRootManifest, i as findWorkspaceConfig, n as findAppletRoot, o as isRootLayout } from "./workspace-CtIKSgMD.js";
|
|
2
3
|
import { n as ORG_CODE_PATTERN, t as APPLET_CODE_PATTERN } from "./manifest-patterns-BfxqImlp.js";
|
|
3
4
|
import { z } from "zod";
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as loginWithDevice } from "./device-CZWWckCq.js";
|
|
1
|
+
import { _ as resolveInstanceUrl, a as loginWithDevice, d as normalizeInstanceUrl, o as AuthenticationError, p as readCredentialStore, u as deleteCredentials, v as revokeOAuthCredentials } from "./auth-OvyoB6M-.js";
|
|
3
2
|
import { i as findWorkspaceConfig } from "./workspace-CtIKSgMD.js";
|
|
4
3
|
// src/login.ts
|
|
5
4
|
async function runLogin(options) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { n as fetchWithOrgAuth } from "./auth-OvyoB6M-.js";
|
|
1
2
|
import { s as readWorkspaceConfig } from "./workspace-CtIKSgMD.js";
|
|
2
|
-
import {
|
|
3
|
-
import { o as resolveWorkspaceOrg, t as loadAppletConfig } from "./load-config-Cffvj-aM.js";
|
|
3
|
+
import { o as resolveWorkspaceOrg, t as loadAppletConfig } from "./load-config-Df-zmfrd.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
|
|
@@ -70,6 +70,7 @@ function HitchImage({ src, alt, files, node: _node, ...props }) {
|
|
|
70
70
|
}
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
|
+
const LINK_SAFETY = { enabled: false };
|
|
73
74
|
function Markdown({ children, files, className }) {
|
|
74
75
|
const rehypePlugins = useMemo(withHitchFileProtocol, []);
|
|
75
76
|
const components = useMemo(() => ({ img: (props) => /* @__PURE__ */ jsx(HitchImage, {
|
|
@@ -79,6 +80,7 @@ function Markdown({ children, files, className }) {
|
|
|
79
80
|
return /* @__PURE__ */ jsx(Streamdown, {
|
|
80
81
|
className,
|
|
81
82
|
components,
|
|
83
|
+
linkSafety: LINK_SAFETY,
|
|
82
84
|
rehypePlugins,
|
|
83
85
|
urlTransform: (url, key, node) => url.startsWith("hitch-file://") ? url : defaultUrlTransform(url, key, node),
|
|
84
86
|
children
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { r as writeGeneratedAgents, t as GENERATED_SKILLS } from "./generated-agents-BUnJ0FQA.js";
|
|
2
|
-
import {
|
|
2
|
+
import { f as organizationInstanceUrl, s as DEFAULT_INSTANCE_URL } from "./auth-OvyoB6M-.js";
|
|
3
3
|
import { a as findWorkspaceRoot, n as findAppletRoot, o as isRootLayout, s as readWorkspaceConfig } from "./workspace-CtIKSgMD.js";
|
|
4
|
-
import { n as loadAppletSourceDefinition, r as appletMountPath } from "./load-config-
|
|
4
|
+
import { n as loadAppletSourceDefinition, r as appletMountPath } from "./load-config-Df-zmfrd.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
1
|
import { n as findAppletRoot } from "./workspace-CtIKSgMD.js";
|
|
2
|
-
import { t as loadAppletConfig } from "./load-config-
|
|
2
|
+
import { t as loadAppletConfig } from "./load-config-Df-zmfrd.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,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-OvyoB6M-.js";
|
|
2
|
+
import { t as loadAppletConfig } from "./load-config-Df-zmfrd.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
|
@@ -3,10 +3,10 @@ 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
5
|
import { r as writeGeneratedAgents } from "./generated-agents-BUnJ0FQA.js";
|
|
6
|
-
import {
|
|
6
|
+
import { _ as resolveInstanceUrl, f as organizationInstanceUrl, g as resolveAuthForOrg, l as bearerToken, m as rejectEnvironmentKey } from "./auth-OvyoB6M-.js";
|
|
7
7
|
import { c as validateRootManifest, o as isRootLayout } from "./workspace-CtIKSgMD.js";
|
|
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-
|
|
8
|
+
import { a as appletSourceDefinitionSchema, i as appletReleaseManifest, o as resolveWorkspaceOrg, r as appletMountPath } from "./load-config-Df-zmfrd.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-Ct-Rbh0f.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";
|
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.23",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bin": {
|
|
6
6
|
"applet": "./dist/applet.js"
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
],
|
|
14
14
|
"type": "module",
|
|
15
15
|
"sideEffects": [
|
|
16
|
-
"*.css"
|
|
16
|
+
"*.css",
|
|
17
|
+
"./src/auth.ts"
|
|
17
18
|
],
|
|
18
19
|
"exports": {
|
|
19
20
|
".": {
|
|
@@ -55,10 +56,10 @@
|
|
|
55
56
|
}
|
|
56
57
|
},
|
|
57
58
|
"dependencies": {
|
|
58
|
-
"@cloudflare/vite-plugin": "^1.
|
|
59
|
+
"@cloudflare/vite-plugin": "^1.66.0",
|
|
59
60
|
"@fontsource-variable/geist-mono": "^5.3.0",
|
|
60
61
|
"@fontsource-variable/inter": "^5.3.0",
|
|
61
|
-
"@hey-api/openapi-ts": "0.0.0-next-
|
|
62
|
+
"@hey-api/openapi-ts": "0.0.0-next-20260930190945",
|
|
62
63
|
"@napi-rs/keyring": "2.1.2",
|
|
63
64
|
"@orpc/client": "^1.15.0",
|
|
64
65
|
"@orpc/contract": "^1.15.0",
|
|
@@ -67,8 +68,8 @@
|
|
|
67
68
|
"@react-aria/optimize-locales-plugin": "^2.1.0",
|
|
68
69
|
"@tailwindcss/vite": "^4.3.0",
|
|
69
70
|
"@tanstack/react-query-persist-client": "5.101.4",
|
|
70
|
-
"@tanstack/router-cli": "^1.167.
|
|
71
|
-
"@tanstack/router-plugin": "^1.168.
|
|
71
|
+
"@tanstack/router-cli": "^1.167.46",
|
|
72
|
+
"@tanstack/router-plugin": "^1.168.48",
|
|
72
73
|
"@telnyx/webrtc": "^2.27.10",
|
|
73
74
|
"@tiptap/core": "^3.30.3",
|
|
74
75
|
"@tiptap/extension-image": "^3.30.3",
|
|
@@ -101,7 +102,7 @@
|
|
|
101
102
|
"peerDependencies": {
|
|
102
103
|
"@orpc/server": "^1.15.0",
|
|
103
104
|
"@tanstack/react-query": "5.101.4",
|
|
104
|
-
"@tanstack/react-router": "^1.170.
|
|
105
|
+
"@tanstack/react-router": "^1.170.46",
|
|
105
106
|
"@types/node": "^24",
|
|
106
107
|
"@types/react": "^19.2.0",
|
|
107
108
|
"@types/react-dom": "^19.2.0",
|
package/dist/auth-DuMRqSGe.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { a as configureKeyring, d as rejectEnvironmentKey, i as bearerToken, l as organizationInstanceUrl, m as resolveInstanceUrl, p as resolveAuthForOrg, r as LoginRequiredError, t as AuthenticationError, u as readCredentialStore } from "./store-E5NhITHl.js";
|
|
2
|
-
import { n as parseMe, t as loginWithDevice } from "./device-CZWWckCq.js";
|
|
3
|
-
import "./workspace-CtIKSgMD.js";
|
|
4
|
-
import { Entry, findCredentials } from "@napi-rs/keyring";
|
|
5
|
-
// src/auth.ts
|
|
6
|
-
configureKeyring(Entry, findCredentials);
|
|
7
|
-
async function fetchWithOrgAuth(orgCode, request) {
|
|
8
|
-
return withOrgAuth(orgCode, async (organizationUrl, accessToken) => {
|
|
9
|
-
const response = await request(organizationUrl, accessToken);
|
|
10
|
-
return {
|
|
11
|
-
response,
|
|
12
|
-
unauthorized: response.status === 401
|
|
13
|
-
};
|
|
14
|
-
}).then(({ response }) => response);
|
|
15
|
-
}
|
|
16
|
-
async function withOrgAuth(orgCode, request) {
|
|
17
|
-
const instanceUrl = await resolveInstanceUrl();
|
|
18
|
-
const organizationUrl = organizationInstanceUrl(instanceUrl, orgCode);
|
|
19
|
-
const auth = await resolveAuthForOrg(instanceUrl, orgCode).catch((error) => {
|
|
20
|
-
if (error instanceof LoginRequiredError && process.stdin.isTTY === true) return void 0;
|
|
21
|
-
throw error;
|
|
22
|
-
});
|
|
23
|
-
if (auth !== void 0) {
|
|
24
|
-
const result = await request(organizationUrl, bearerToken(auth));
|
|
25
|
-
if ("response" in result && result.response instanceof Response) rejectEnvironmentKey(result.response, auth);
|
|
26
|
-
if (!result.unauthorized) return result;
|
|
27
|
-
if (auth.source === "environment") throw new AuthenticationError("HITCH_API_KEY was rejected.");
|
|
28
|
-
}
|
|
29
|
-
if (process.stdin.isTTY !== true) throw new LoginRequiredError();
|
|
30
|
-
await loginWithDevice(instanceUrl, { expectedOrg: orgCode });
|
|
31
|
-
const credentials = await resolveAuthForOrg(instanceUrl, orgCode);
|
|
32
|
-
if (credentials === void 0) throw new Error(`login did not provide credentials for organization "${orgCode}"`);
|
|
33
|
-
return request(organizationUrl, bearerToken(credentials));
|
|
34
|
-
}
|
|
35
|
-
async function orgUsesHitchGit(org) {
|
|
36
|
-
const response = await fetchWithOrgAuth(org, (organizationUrl, token) => fetch(`${organizationUrl}/api/me/v1`, { headers: { Authorization: `Bearer ${token}` } }));
|
|
37
|
-
if (!response.ok) throw new AuthenticationError(`Could not read organization membership (${response.status}).`);
|
|
38
|
-
const membership = parseMe(await response.json()).memberships.find((item) => item.code === org);
|
|
39
|
-
if (membership === void 0) throw new AuthenticationError(`You are not a member of ${org}.`);
|
|
40
|
-
if (typeof membership.gitEnabled !== "boolean") throw new Error("The membership response has no \"gitEnabled\" flag. Update the Hitch server.");
|
|
41
|
-
return membership.gitEnabled;
|
|
42
|
-
}
|
|
43
|
-
async function canCheckHitchGit() {
|
|
44
|
-
if (process.env.GITHUB_ACTIONS === "true") return false;
|
|
45
|
-
if (process.env.HITCH_API_KEY) return true;
|
|
46
|
-
const instance = await resolveInstanceUrl();
|
|
47
|
-
return Object.entries((await readCredentialStore()).instances).some(([url, credentials]) => url === instance && Object.keys(credentials).length > 0);
|
|
48
|
-
}
|
|
49
|
-
export { withOrgAuth as i, fetchWithOrgAuth as n, orgUsesHitchGit as r, canCheckHitchGit as t };
|
package/dist/build-C7hi2yg4.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { i as runBuild } from "./build-FAQSHJgm.js";
|
package/dist/device-CZWWckCq.js
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { c as normalizeInstanceUrl, d as rejectEnvironmentKey, g as saveOAuthCredentials, l as organizationInstanceUrl, o as credentialStorageMessage, t as AuthenticationError, u as readCredentialStore } from "./store-E5NhITHl.js";
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
3
|
-
import readline from "node:readline/promises";
|
|
4
|
-
// ../shared/auth/src/device.mts
|
|
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 +0,0 @@
|
|
|
1
|
-
export { r as runGenerate } from "./generate-DNgO44RO.js";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { c as runClone } from "./git-deploy-C12nMNB6.js";
|