@hitch42/applet 0.1.1-beta.21 → 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.
Files changed (54) hide show
  1. package/dist/_internal/server.d.ts +1 -1
  2. package/dist/applet.js +16 -16
  3. package/dist/{store-E5NhITHl.js → auth-OvyoB6M-.js} +203 -4
  4. package/dist/{batch-CiLZ177G.js → batch-DwyWmiaE.js} +1 -1
  5. package/dist/{build-FAQSHJgm.js → build-CrrTAX6T.js} +1 -1
  6. package/dist/build-YzjhhLw0.js +1 -0
  7. package/dist/{ci-oWlUJKm9.js → ci-B1XyXpHa.js} +2 -2
  8. package/dist/client/hitch/client.d.ts +1 -1
  9. package/dist/client/hitch/client.js +1 -1
  10. package/dist/client/hitch.d.ts +1 -1
  11. package/dist/client/hitch.js +1 -1
  12. package/dist/client/react/markdown-editor.d.ts +1 -1
  13. package/dist/client/react/markdown.d.ts +1 -1
  14. package/dist/client/react/markdown.js +1 -1
  15. package/dist/client/react.d.ts +2 -2
  16. package/dist/client/react.js +1 -1
  17. package/dist/{deploy-BM55ZoSp.js → deploy-WdARFHmA.js} +7 -7
  18. package/dist/{email-protocol-CEqzASSx.d.ts → email-protocol-BWja_v7c.d.ts} +16 -10
  19. package/dist/{generate-48pqFh5M.js → generate-Ct-Rbh0f.js} +11 -11
  20. package/dist/generate-_u-zFzrv.js +1 -0
  21. package/dist/{git-credential-CU7-Erzs.js → git-credential-DuLNowIb.js} +1 -1
  22. package/dist/{git-deploy-C12nMNB6.js → git-deploy-BjSAv5Qm.js} +1 -2
  23. package/dist/git-deploy-CByu_uli.js +1 -0
  24. package/dist/{git-migration-CIq-sN61.js → git-migration-6V31iafL.js} +3 -3
  25. package/dist/{hitch-client-Dph_kzDd.js → hitch-client-CNN-dU6d.js} +2 -2
  26. package/dist/{hitch-client-D33JOEOi.d.ts → hitch-client-k7_jIjPw.d.ts} +1 -1
  27. package/dist/index.d.ts +8 -5
  28. package/dist/index.js +12 -12
  29. package/dist/{init-Bb6WT8UB.js → init-C5HqIRt8.js} +5 -6
  30. package/dist/{load-config-Cffvj-aM.js → load-config-Df-zmfrd.js} +1 -0
  31. package/dist/{login-BWZKo7Ui.js → login-B41-WWtD.js} +1 -2
  32. package/dist/{logs-glCVHI-8.js → logs-DrL2ytmg.js} +2 -2
  33. package/dist/{markdown-BXt65dDo.d.ts → markdown-CnB35mjc.d.ts} +1 -1
  34. package/dist/{markdown-BA_XzFxq.js → markdown-DLdJOJ59.js} +2 -0
  35. package/dist/{markdown-editor-CB_nWLzj.d.ts → markdown-editor-xF3uATBp.d.ts} +1 -1
  36. package/dist/{project-DZGk765E.js → project-BbpU_VN2.js} +2 -2
  37. package/dist/{schedules-CSUb84e2.js → schedules-2Q_fkY_a.js} +1 -1
  38. package/dist/server.d.ts +1 -1
  39. package/dist/server.js +2 -2
  40. package/dist/{upload-DtMavo8Q.js → upload-D1mzpsSk.js} +2 -2
  41. package/dist/{upload-DXZyjZSS.d.ts → upload-wp-Ilsv6.d.ts} +3 -3
  42. package/dist/{variables-CgZstC7I.js → variables-CGwbmUom.js} +2 -2
  43. package/dist/vite.js +3 -3
  44. package/package.json +8 -7
  45. package/scaffold/.agents/skills/hitch-applets/references/email-tracking.md +4 -4
  46. package/scaffold/.agents/skills/hitch-applets/references/files.md +2 -2
  47. package/scaffold/.agents/skills/hitch-applets/references/performance.md +2 -2
  48. package/scaffold/.agents/skills/hitch-applets/references/records.md +7 -7
  49. package/scaffold/.agents/skills/hitch-cli/SKILL.md +21 -21
  50. package/dist/auth-DuMRqSGe.js +0 -49
  51. package/dist/build-C7hi2yg4.js +0 -1
  52. package/dist/device-CZWWckCq.js +0 -155
  53. package/dist/generate-BYK4aNud.js +0 -1
  54. package/dist/git-deploy-CNz6mxiF.js +0 -1
@@ -1,5 +1,5 @@
1
1
  import { t as AnyWorkflowDefinition } from "../workflow-BnBrJIzu.js";
2
- import { d as ListEmailTrackersInput, n as TelephonyMessageReceivedEvent, r as CreateEmailPixelInput, t as EmailMessageReceivedEvent } from "../email-protocol-CEqzASSx.js";
2
+ import { d as ListEmailTrackersInput, n as TelephonyMessageReceivedEvent, r as CreateEmailPixelInput, t as EmailMessageReceivedEvent } from "../email-protocol-BWja_v7c.js";
3
3
  import { z } from "zod";
4
4
  declare function createWorkerEntry(server: {
5
5
  router: object;
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-CU7-Erzs.js")).runGitCredential(args[2] ?? "", args[1]);
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-CNz6mxiF.js")).runClone(positionals[1], positionals[2], values.message);
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-BWZKo7Ui.js")).runLogout();
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-BWZKo7Ui.js")).runLogin({ noBrowser: values["no-browser"] });
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-Bb6WT8UB.js")).runBootstrap({
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-BYK4aNud.js")).runGenerate();
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-C7hi2yg4.js")).runBuild();
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-BM55ZoSp.js")).runDeploy({
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-BM55ZoSp.js")).runRollback(positionals[1]);
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-Bb6WT8UB.js")).runInit(positionals[1], {
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-Bb6WT8UB.js")).runNew({
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-glCVHI-8.js")).runLogs({
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-CSUb84e2.js")).runSchedule({
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-CgZstC7I.js")).runVariablesSet({
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-CgZstC7I.js")).runVariablesList();
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-CgZstC7I.js")).runVariablesDelete({
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
- export { configureKeyring as a, normalizeInstanceUrl as c, rejectEnvironmentKey as d, resolveAuth as f, saveOAuthCredentials as g, revokeOAuthCredentials as h, bearerToken as i, organizationInstanceUrl as l, resolveInstanceUrl as m, DEFAULT_INSTANCE_URL as n, credentialStorageMessage as o, resolveAuthForOrg as p, LoginRequiredError as r, deleteCredentials as s, AuthenticationError as t, readCredentialStore as u };
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 };
@@ -23,7 +23,7 @@ function withBatchRecorder(target, contract) {
23
23
  const tx = Object.fromEntries(Object.entries(records).map(([code, procedures]) => [code, Object.fromEntries(BATCH_VERBS.filter((verb) => typeof procedures === "object" && procedures !== null && isContractProcedure(Reflect.get(procedures, verb))).map((verb) => [verb, (procedureInput) => {
24
24
  if (!active) throw new Error("The batch was already sent.");
25
25
  const body = Reflect.get(procedureInput, "body");
26
- const record = verb === "update" || verb === "delete" ? Reflect.get(Reflect.get(procedureInput, "params"), "record") : void 0;
26
+ const record = verb === "update" || verb === "delete" ? Reflect.get(Reflect.get(procedureInput, "params"), "recordId") : void 0;
27
27
  requests.push({
28
28
  method: verb === "create" || verb === "updateWhere" ? "POST" : verb === "update" ? "PATCH" : "DELETE",
29
29
  path: verb === "create" ? `/v1/${code}` : verb === "updateWhere" ? `/v1/${code}/bulk-update` : `/v1/${code}/${String(record)}`,
@@ -1,5 +1,5 @@
1
1
  import { n as findAppletRoot } from "./workspace-CtIKSgMD.js";
2
- import { a as prepareAppletProjects, i as prepareAppletProject } from "./project-DZGk765E.js";
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 { m as resolveInstanceUrl } from "./store-E5NhITHl.js";
2
- import { o as userAgent } from "./project-DZGk765E.js";
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,2 +1,2 @@
1
- import { t as hitch } from "../../hitch-client-D33JOEOi.js";
1
+ import { t as hitch } from "../../hitch-client-k7_jIjPw.js";
2
2
  export { hitch };
@@ -1 +1 @@
1
- export { t as hitch } from "../../hitch-client-Dph_kzDd.js";
1
+ export { t as hitch } from "../../hitch-client-CNN-dU6d.js";
@@ -1,3 +1,3 @@
1
- import { t as hitch } from "../hitch-client-D33JOEOi.js";
1
+ import { t as hitch } from "../hitch-client-k7_jIjPw.js";
2
2
  import { i as createPhone, n as Phone, r as PhoneState, t as usePhone } from "../use-phone-DBAkasPq.js";
3
3
  export { type Phone, type PhoneState, createPhone, hitch, usePhone };
@@ -1,3 +1,3 @@
1
- import { t as hitch } from "../hitch-client-Dph_kzDd.js";
1
+ import { t as hitch } from "../hitch-client-CNN-dU6d.js";
2
2
  import { n as createPhone, t as usePhone } from "../use-phone-CB_idmrz.js";
3
3
  export { createPhone, hitch, usePhone };
@@ -1,2 +1,2 @@
1
- import { n as MarkdownEditorProps, r as MarkdownEditorFiles, t as MarkdownEditor } from "../../markdown-editor-CB_nWLzj.js";
1
+ import { n as MarkdownEditorProps, r as MarkdownEditorFiles, t as MarkdownEditor } from "../../markdown-editor-xF3uATBp.js";
2
2
  export { MarkdownEditor, type MarkdownEditorFiles, MarkdownEditorProps };
@@ -1,2 +1,2 @@
1
- import { n as MarkdownFiles, r as MarkdownProps, t as Markdown } from "../../markdown-BXt65dDo.js";
1
+ import { n as MarkdownFiles, r as MarkdownProps, t as Markdown } from "../../markdown-CnB35mjc.js";
2
2
  export { Markdown, MarkdownFiles, MarkdownProps };
@@ -1 +1 @@
1
- export { t as Markdown } from "../../markdown-BA_XzFxq.js";
1
+ export { t as Markdown } from "../../markdown-DLdJOJ59.js";
@@ -1,3 +1,3 @@
1
- import { n as MarkdownFiles, r as MarkdownProps, t as Markdown } from "../markdown-BXt65dDo.js";
2
- import { n as MarkdownEditorProps, r as MarkdownEditorFiles, t as MarkdownEditor } from "../markdown-editor-CB_nWLzj.js";
1
+ import { n as MarkdownFiles, r as MarkdownProps, t as Markdown } from "../markdown-CnB35mjc.js";
2
+ import { n as MarkdownEditorProps, r as MarkdownEditorFiles, t as MarkdownEditor } from "../markdown-editor-xF3uATBp.js";
3
3
  export { Markdown, MarkdownEditor, type MarkdownEditorFiles, type MarkdownEditorProps, type MarkdownFiles, type MarkdownProps };
@@ -1,3 +1,3 @@
1
- import { t as Markdown } from "../markdown-BA_XzFxq.js";
1
+ import { t as Markdown } from "../markdown-DLdJOJ59.js";
2
2
  import { t as MarkdownEditor } from "../markdown-editor-CaUuphfc.js";
3
3
  export { Markdown, MarkdownEditor };
@@ -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 fetchWithOrgAuth, r as orgUsesHitchGit, t as canCheckHitchGit } from "./auth-DuMRqSGe.js";
3
- import { n as loadAppletSourceDefinition } from "./load-config-Cffvj-aM.js";
4
- import { i as prepareAppletProject } from "./project-DZGk765E.js";
5
- import { a as loadGitHubActionsSources, n as githubActionsContext, t as fetchWithGitHubActions } from "./ci-oWlUJKm9.js";
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-C12nMNB6.js";
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-CIq-sN61.js";
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";
@@ -9,10 +9,10 @@ type CreateEmailPixelOutput = {
9
9
  url: string;
10
10
  };
11
11
  type GetEmailTrackerInput = {
12
- id: string;
12
+ trackerId: string;
13
13
  };
14
14
  type MarkEmailTrackerSentInput = {
15
- id: string;
15
+ trackerId: string;
16
16
  sentAt?: string;
17
17
  };
18
18
  type EmailTracker = {
@@ -43,17 +43,17 @@ type EmailContract = {
43
43
  };
44
44
  threads: {
45
45
  list: ContractProcedure<Schema<ListHitchEmailThreadsInput, ListHitchEmailThreadsInput>, Schema<HitchEmailThreadsOutput, HitchEmailThreadsOutput>, Record<never, never>, Meta>;
46
- get: ContractProcedure<Schema<HitchEmailIdInput, HitchEmailIdInput>, Schema<HitchEmailThread, HitchEmailThread>, Record<never, never>, Meta>;
46
+ get: ContractProcedure<Schema<HitchEmailThreadInput, HitchEmailThreadInput>, Schema<HitchEmailThread, HitchEmailThread>, Record<never, never>, Meta>;
47
47
  };
48
48
  messages: {
49
49
  /** Newest first. Pass threadId to page through one thread. */
50
50
  list: ContractProcedure<Schema<ListHitchEmailMessagesInput, ListHitchEmailMessagesInput>, Schema<HitchEmailMessagesOutput, HitchEmailMessagesOutput>, Record<never, never>, Meta>;
51
- get: ContractProcedure<Schema<HitchEmailIdInput, HitchEmailIdInput>, Schema<HitchEmailMessage, HitchEmailMessage>, Record<never, never>, Meta>;
51
+ get: ContractProcedure<Schema<HitchEmailMessageInput, HitchEmailMessageInput>, Schema<HitchEmailMessage, HitchEmailMessage>, Record<never, never>, Meta>;
52
52
  send: ContractProcedure<Schema<SendHitchEmailInput, SendHitchEmailInput>, Schema<HitchEmailMessage, HitchEmailMessage>, Record<never, never>, Meta>;
53
- raw: ContractProcedure<Schema<HitchEmailIdInput, HitchEmailIdInput>, Schema<HitchEmailRawOutput, HitchEmailRawOutput>, Record<never, never>, Meta>;
53
+ raw: ContractProcedure<Schema<HitchEmailMessageInput, HitchEmailMessageInput>, Schema<HitchEmailRawOutput, HitchEmailRawOutput>, Record<never, never>, Meta>;
54
54
  };
55
55
  attachments: {
56
- get: ContractProcedure<Schema<HitchEmailIdInput, HitchEmailIdInput>, Schema<HitchEmailAttachmentOutput, HitchEmailAttachmentOutput>, Record<never, never>, Meta>;
56
+ get: ContractProcedure<Schema<HitchEmailAttachmentInput, HitchEmailAttachmentInput>, Schema<HitchEmailAttachmentOutput, HitchEmailAttachmentOutput>, Record<never, never>, Meta>;
57
57
  };
58
58
  tracking: {
59
59
  createPixel: ContractProcedure<Schema<CreateEmailPixelInput | undefined, CreateEmailPixelInput | undefined>, Schema<CreateEmailPixelOutput, CreateEmailPixelOutput>, Record<never, never>, Meta>;
@@ -151,8 +151,14 @@ type SendHitchEmailInput = {
151
151
  attachmentFileIds?: string[];
152
152
  requestId?: string;
153
153
  };
154
- type HitchEmailIdInput = {
155
- id: string;
154
+ type HitchEmailThreadInput = {
155
+ threadId: string;
156
+ };
157
+ type HitchEmailMessageInput = {
158
+ messageId: string;
159
+ };
160
+ type HitchEmailAttachmentInput = {
161
+ attachmentId: string;
156
162
  };
157
163
  type HitchEmailMailboxesOutput = {
158
164
  data: HitchMailbox[];
@@ -175,7 +181,7 @@ type HitchEmailAttachmentOutput = {
175
181
  sizeBytes: number;
176
182
  };
177
183
  /** Handle events at least once and without order. Use eventId for idempotency.
178
- * Read the message with hitch.telephony.messages.get({ id: messageId }). */
184
+ * Read the message with hitch.telephony.messages.get({ messageId }). */
179
185
  type TelephonyMessageReceivedEvent = {
180
186
  eventId: string;
181
187
  type: "message.received";
@@ -184,7 +190,7 @@ type TelephonyMessageReceivedEvent = {
184
190
  occurredAt: string;
185
191
  };
186
192
  /** Handle events at least once and without order. Use eventId for idempotency.
187
- * Read the message with hitch.email.messages.get({ id: messageId }). */
193
+ * Read the message with hitch.email.messages.get({ messageId }). */
188
194
  type EmailMessageReceivedEvent = {
189
195
  eventId: string;
190
196
  type: "message.received";
@@ -1,9 +1,8 @@
1
- import { l as organizationInstanceUrl, m as resolveInstanceUrl } from "./store-E5NhITHl.js";
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 { n as fetchWithOrgAuth } from "./auth-DuMRqSGe.js";
4
- import { t as loadAppletConfig } from "./load-config-Cffvj-aM.js";
5
- import { i as prepareAppletProject, o as userAgent } from "./project-DZGk765E.js";
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";
@@ -72,7 +71,7 @@ function singleCreateSchema(value) {
72
71
  return isComponentRef(single) && isObject$3(array) && array.type === "array" && isComponentRef(array.items) && array.items.$ref === single.$ref ? single : void 0;
73
72
  }
74
73
  // src/typegen/operations.ts
75
- const RECORD_ROUTE = /^\/v1\/([^/]+)(?:\/(\{record\}(?:\/history)?|query|bulk-update|aggregate))?$/;
74
+ const RECORD_ROUTE = /^\/v1\/([^/]+)(?:\/(\{recordId\}(?:\/history)?|query|bulk-update|aggregate))?$/;
76
75
  const COMPONENT_REF_PREFIX$1 = "#/components/schemas/";
77
76
  const BATCH_PATH = "/v1/batch/run";
78
77
  const BATCH_ITEM_PATH = "paths./v1/batch/run.post.requestBody.content.application/json.schema.properties.requests.items";
@@ -80,10 +79,10 @@ const BATCH_ID_PATH = /^\^\/v1\/([^/]+)\/\[0-9a-fA-F-\]\{36\}\$$/;
80
79
  const VERBS = {
81
80
  "get:": "list",
82
81
  "post:": "create",
83
- "get:{record}": "get",
84
- "get:{record}/history": "history",
85
- "patch:{record}": "update",
86
- "delete:{record}": "delete",
82
+ "get:{recordId}": "get",
83
+ "get:{recordId}/history": "history",
84
+ "patch:{recordId}": "update",
85
+ "delete:{recordId}": "delete",
87
86
  "post:query": "query",
88
87
  "post:bulk-update": "updateWhere",
89
88
  "post:aggregate": "aggregate"
@@ -193,6 +192,7 @@ function prepareRecordSpec(spec, manifest) {
193
192
  return operation === void 0 ? [] : [[path, { post: operation }]];
194
193
  }
195
194
  const objectCode = recordObjectCode(path);
195
+ if (objectCode === void 0 && /^\/v1\/(?!objects\/)[^/]+\/\{/.test(path)) throw new Error(`paths.${path} is a record route that this SDK cannot read. Use the @hitch42/applet version that matches the Hitch server.`);
196
196
  if (!isObject$2(pathItem)) {
197
197
  if (objectCode === void 0) return [];
198
198
  throw new Error(`object "${objectCode}": paths.${path} expected an object, found ${describeValue$1(pathItem)}`);
@@ -224,7 +224,7 @@ function prepareRecordSpec(spec, manifest) {
224
224
  }));
225
225
  manifest?.objects.forEach(({ code, optionalAttributes }) => {
226
226
  if (optionalAttributes === void 0 || optionalAttributes.length === 0) return;
227
- const responsePath = `/v1/${code}/{record}`;
227
+ const responsePath = `/v1/${code}/{recordId}`;
228
228
  const response = prepared.paths[responsePath]?.get?.responses;
229
229
  const schema = isObject$2(response) && isObject$2(response["200"]) ? response["200"].content : void 0;
230
230
  const mediaType = isObject$2(schema) && isObject$2(schema["application/json"]) ? schema["application/json"] : void 0;
@@ -0,0 +1 @@
1
+ export { r as runGenerate } from "./generate-Ct-Rbh0f.js";
@@ -1,4 +1,4 @@
1
- import { l as organizationInstanceUrl, p as resolveAuthForOrg, r as LoginRequiredError, t as AuthenticationError } from "./store-E5NhITHl.js";
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 { m as resolveInstanceUrl } from "./store-E5NhITHl.js";
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 { r as orgUsesHitchGit, t as canCheckHitchGit } from "./auth-DuMRqSGe.js";
4
- import { n as loadAppletSourceDefinition } from "./load-config-Cffvj-aM.js";
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";