@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.
Files changed (32) hide show
  1. package/dist/applet.js +17 -17
  2. package/dist/auth-DGCFAqPX.js +47 -0
  3. package/dist/build-C3LFcX0i.js +1 -0
  4. package/dist/{build-CrrTAX6T.js → build-Cnh7Owss.js} +2 -2
  5. package/dist/{ci-B1XyXpHa.js → ci-PuUsFgnN.js} +2 -2
  6. package/dist/{deploy-WdARFHmA.js → deploy-oCP6VmLT.js} +10 -10
  7. package/dist/device-CcsD_wOD.js +155 -0
  8. package/dist/{generate-Ct-Rbh0f.js → generate-DIgN2KC4.js} +6 -5
  9. package/dist/generate-cwMuaQE9.js +1 -0
  10. package/dist/{generated-agents-BUnJ0FQA.js → generated-agents-XYtnda2w.js} +1 -1
  11. package/dist/{git-credential-DuLNowIb.js → git-credential-CK0sHQ5a.js} +1 -1
  12. package/dist/git-deploy-CCVbXqbO.js +1 -0
  13. package/dist/{git-deploy-BjSAv5Qm.js → git-deploy-Cz-FCa93.js} +4 -3
  14. package/dist/{git-migration-6V31iafL.js → git-migration-BIw2cVoP.js} +6 -6
  15. package/dist/{init-C5HqIRt8.js → init-CAyEoy4P.js} +9 -8
  16. package/dist/{load-config-Df-zmfrd.js → load-config-0lXPytAo.js} +1 -2
  17. package/dist/{login-B41-WWtD.js → login-ChKZbUOt.js} +3 -2
  18. package/dist/{logs-DrL2ytmg.js → logs-C4QXSsBW.js} +3 -3
  19. package/dist/{parent-Zx8Eg1Ki.js → parent-BGZHFiDn.js} +3 -3
  20. package/dist/parent-QxKvaC2E.js +1 -0
  21. package/dist/{project-BbpU_VN2.js → project-BRwNCUCi.js} +4 -4
  22. package/dist/{schedules-2Q_fkY_a.js → schedules-CThe3MC1.js} +2 -2
  23. package/dist/{source-hash-BbvtRaus.js → source-hash-Bp8v9JY1.js} +1 -1
  24. package/dist/{auth-OvyoB6M-.js → store-Dq9l7Qmw.js} +9 -217
  25. package/dist/{variables-CGwbmUom.js → variables-Cpd05u5N.js} +2 -2
  26. package/dist/vite.js +5 -5
  27. package/dist/{workspace-CtIKSgMD.js → workspace-BRRW36wG.js} +1 -1
  28. package/package.json +2 -3
  29. package/dist/build-YzjhhLw0.js +0 -1
  30. package/dist/generate-_u-zFzrv.js +0 -1
  31. package/dist/git-deploy-CByu_uli.js +0 -1
  32. 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-DuLNowIb.js")).runGitCredential(args[2] ?? "", args[1]);
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-CByu_uli.js")).runClone(positionals[1], positionals[2], values.message);
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-B41-WWtD.js")).runLogout();
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-B41-WWtD.js")).runLogin({ noBrowser: values["no-browser"] });
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-D52Kxp8U.js")).runParent();
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-C5HqIRt8.js")).runBootstrap({
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-_u-zFzrv.js")).runGenerate();
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-YzjhhLw0.js")).runBuild();
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-WdARFHmA.js")).runDeploy({
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-WdARFHmA.js")).runRollback(positionals[1]);
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-C5HqIRt8.js")).runInit(positionals[1], {
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-C5HqIRt8.js")).runNew({
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-DrL2ytmg.js")).runLogs({
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-2Q_fkY_a.js")).runSchedule({
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-CGwbmUom.js")).runVariablesSet({
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-CGwbmUom.js")).runVariablesList();
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-CGwbmUom.js")).runVariablesDelete({
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-CtIKSgMD.js";
2
- import { a as prepareAppletProjects, i as prepareAppletProject } from "./project-BbpU_VN2.js";
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 { _ as resolveInstanceUrl } from "./auth-OvyoB6M-.js";
2
- import { o as userAgent } from "./project-BbpU_VN2.js";
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 fetchWithOrgAuth, r as orgUsesHitchGit, t as canCheckHitchGit } from "./auth-OvyoB6M-.js";
2
- import { a as findWorkspaceRoot, n as findAppletRoot, o as isRootLayout, r as findParentRoot, s as readWorkspaceConfig } from "./workspace-CtIKSgMD.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
- 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-BjSAv5Qm.js";
9
- import { n as childApplets, r as childHasChanges } from "./parent-Zx8Eg1Ki.js";
10
- import { n as migrateWorkspace } from "./git-migration-6V31iafL.js";
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 { _ as resolveInstanceUrl, f as organizationInstanceUrl, n as fetchWithOrgAuth } from "./auth-OvyoB6M-.js";
2
- import { n as findAppletRoot } from "./workspace-CtIKSgMD.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";
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 { r as findParentRoot } from "./workspace-CtIKSgMD.js";
1
+ import { r as findParentRoot } from "./workspace-BRRW36wG.js";
2
2
  import { createHash, randomUUID } from "node:crypto";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { existsSync } from "node:fs";
@@ -1,4 +1,4 @@
1
- import { c as LoginRequiredError, f as organizationInstanceUrl, g as resolveAuthForOrg, o as AuthenticationError } from "./auth-OvyoB6M-.js";
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 { _ as resolveInstanceUrl, i as withOrgAuth } from "./auth-OvyoB6M-.js";
2
- import { a as findWorkspaceRoot, o as isRootLayout, r as findParentRoot, t as SDK_VERSION_PATTERN } from "./workspace-CtIKSgMD.js";
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-BbvtRaus.js";
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-BUnJ0FQA.js";
2
- import { r as orgUsesHitchGit, t as canCheckHitchGit } from "./auth-OvyoB6M-.js";
3
- import { a as findWorkspaceRoot, n as findAppletRoot, o as isRootLayout, s as readWorkspaceConfig } from "./workspace-CtIKSgMD.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";
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-Zx8Eg1Ki.js";
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-BUnJ0FQA.js";
2
- import { _ as resolveInstanceUrl, g as resolveAuthForOrg, h as resolveAuth, r as orgUsesHitchGit, t as canCheckHitchGit } from "./auth-OvyoB6M-.js";
3
- import { a as findWorkspaceRoot, i as findWorkspaceConfig, o as isRootLayout, r as findParentRoot, s as readWorkspaceConfig } from "./workspace-CtIKSgMD.js";
4
- import { n as loadAppletSourceDefinition } from "./load-config-Df-zmfrd.js";
5
- import { r as runGenerate } from "./generate-Ct-Rbh0f.js";
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-BbpU_VN2.js";
8
- import { n as childApplets } from "./parent-Zx8Eg1Ki.js";
9
- import { t as migrateIfEnabled } from "./git-migration-6V31iafL.js";
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 "./auth-OvyoB6M-.js";
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 { _ as resolveInstanceUrl, a as loginWithDevice, d as normalizeInstanceUrl, o as AuthenticationError, p as readCredentialStore, u as deleteCredentials, v as revokeOAuthCredentials } from "./auth-OvyoB6M-.js";
2
- import { i as findWorkspaceConfig } from "./workspace-CtIKSgMD.js";
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 { n as fetchWithOrgAuth } from "./auth-OvyoB6M-.js";
2
- import { s as readWorkspaceConfig } from "./workspace-CtIKSgMD.js";
3
- import { o as resolveWorkspaceOrg, t as loadAppletConfig } from "./load-config-Df-zmfrd.js";
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-BUnJ0FQA.js";
2
- import { a as findWorkspaceRoot, o as isRootLayout, r as findParentRoot } from "./workspace-CtIKSgMD.js";
3
- import { n as gitEnvironment } from "./source-hash-BbvtRaus.js";
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-BUnJ0FQA.js";
2
- import { f as organizationInstanceUrl, s as DEFAULT_INSTANCE_URL } from "./auth-OvyoB6M-.js";
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-Df-zmfrd.js";
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-CtIKSgMD.js";
2
- import { t as loadAppletConfig } from "./load-config-Df-zmfrd.js";
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-CtIKSgMD.js";
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.mts
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.mts
52
- const CLIENT_ID$1 = "hitch-cli-oauth";
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$1,
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$1
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.mts
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 keyringClass("hitch", account, options);
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
- if (findKeyringCredentials === void 0) throw new Error("Keyring listing is not configured.");
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
- // ../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 };
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-OvyoB6M-.js";
2
- import { t as loadAppletConfig } from "./load-config-Df-zmfrd.js";
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-BUnJ0FQA.js";
6
- import { _ as resolveInstanceUrl, f as organizationInstanceUrl, g as resolveAuthForOrg, l as bearerToken, m as rejectEnvironmentKey } from "./auth-OvyoB6M-.js";
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-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";
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.mts
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.23",
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
  ".": {
@@ -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";
@@ -1 +0,0 @@
1
- export { i as runParent } from "./parent-Zx8Eg1Ki.js";