@hitch42/applet 0.1.1-beta.7 → 0.1.1-beta.9

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 (177) hide show
  1. package/dist/_internal/client.js +120 -11
  2. package/dist/_internal/log-context.d.ts +34 -0
  3. package/dist/_internal/log-context.js +2 -0
  4. package/dist/_internal/server.d.ts +14 -1
  5. package/dist/_internal/server.js +122 -118
  6. package/dist/applet.js +22 -11
  7. package/dist/build-Bh_S5BUv.js +2 -0
  8. package/dist/{build-DauirTcY.js → build-CEfFoIZZ.js} +1 -1
  9. package/dist/{ci-gPrwo6C0.js → ci-BKw14X2h.js} +14 -13
  10. package/dist/client.d.ts +3 -3
  11. package/dist/{contract-DB9QQhD9.d.ts → contract-CsUpTBe0.d.ts} +1 -1
  12. package/dist/{deploy-CqrtNJ1x.js → deploy-wGYjwXrx.js} +139 -88
  13. package/dist/email-DBTVhNB_.js +62 -0
  14. package/dist/{generate-BIifT6PK.js → generate-BEIYs17x.js} +70 -32
  15. package/dist/generate-Dox-OYt6.js +2 -0
  16. package/dist/headers-DkNr9MLJ.js +17 -0
  17. package/dist/index.d.ts +122 -10
  18. package/dist/index.js +142 -26
  19. package/dist/{init-Wu6XmyVc.js → init-6oGPM46R.js} +15 -17
  20. package/dist/{load-config-BknBkdRs.js → load-config-xEdTXs0y.js} +2 -2
  21. package/dist/log-context-zu8U9Sjm.js +73 -0
  22. package/dist/{login-iT9MRuaw.js → login-CUx3TmFQ.js} +1 -1
  23. package/dist/{logs-B-qZGXSK.js → logs-DSjuEN0Q.js} +20 -22
  24. package/dist/{manifest-C489nYUy.d.ts → manifest-C6_F4bL8.d.ts} +7 -0
  25. package/dist/{manifest-Bd04cWhu.js → manifest-CJSL9GuC.js} +22 -3
  26. package/dist/me-BW7Paary.js +32 -0
  27. package/dist/{project-C_rtpjp8.js → project-BRZGd6xq.js} +202 -20
  28. package/dist/prompt-ChS-grYO.js +29 -0
  29. package/dist/query-cache-CXmAyLv3.js +82 -0
  30. package/dist/react.d.ts +3 -2
  31. package/dist/react.js +98 -80
  32. package/dist/schedules-C8_Svr4h.js +42 -0
  33. package/dist/server.d.ts +9 -4
  34. package/dist/server.js +29 -8
  35. package/dist/telephony-protocol-D-nf3Gca.d.ts +76 -0
  36. package/dist/telephony.d.ts +97 -0
  37. package/dist/telephony.js +726 -0
  38. package/dist/{upload-YbRKEqR6.d.ts → upload-DKZzz5kW.d.ts} +6 -6
  39. package/dist/{variables-DcwMeIau.js → variables-DT5RyHdH.js} +14 -39
  40. package/dist/vite.d.ts +3 -60
  41. package/dist/vite.js +497 -27
  42. package/dist/workflow-engine-BOTzURKM.js +111 -0
  43. package/dist/{workspace-B6lenAS5.js → workspace-D0dnnlxL.js} +37 -39
  44. package/package.json +18 -5
  45. package/scaffold/.agents/skills/hitch-applets/SKILL.md +50 -18
  46. package/scaffold/.agents/skills/hitch-applets/references/email-tracking.md +49 -0
  47. package/scaffold/.agents/skills/hitch-applets/references/files.md +3 -3
  48. package/scaffold/.agents/skills/hitch-applets/references/manifest.md +12 -2
  49. package/scaffold/.agents/skills/hitch-applets/references/markdown.md +2 -0
  50. package/scaffold/.agents/skills/hitch-applets/references/performance.md +1 -1
  51. package/scaffold/.agents/skills/hitch-applets/references/records.md +27 -4
  52. package/scaffold/.agents/skills/hitch-applets/references/schedules.md +7 -2
  53. package/scaffold/.agents/skills/hitch-applets/references/server.md +0 -3
  54. package/scaffold/.agents/skills/hitch-applets/references/workflows.md +11 -3
  55. package/scaffold/.agents/skills/hitch-cli/SKILL.md +20 -20
  56. package/scaffold/.agents/skills/hitch-data/SKILL.md +3 -2
  57. package/scaffold/.agents/skills/hitch-data/references/attributes.md +7 -1
  58. package/scaffold/.agents/skills/hitch-data/references/limits.md +23 -23
  59. package/scaffold/.agents/skills/hitch-theory/SKILL.md +151 -0
  60. package/scaffold/.agents/skills/react-best-practices/SKILL.md +127 -0
  61. package/scaffold/.agents/skills/react-best-practices/rules/advanced-effect-event-deps.md +50 -0
  62. package/scaffold/.agents/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  63. package/scaffold/.agents/skills/react-best-practices/rules/advanced-init-once.md +42 -0
  64. package/scaffold/.agents/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
  65. package/scaffold/.agents/skills/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
  66. package/scaffold/.agents/skills/react-best-practices/rules/async-defer-await.md +82 -0
  67. package/scaffold/.agents/skills/react-best-practices/rules/async-dependencies.md +48 -0
  68. package/scaffold/.agents/skills/react-best-practices/rules/async-parallel.md +24 -0
  69. package/scaffold/.agents/skills/react-best-practices/rules/bundle-analyzable-paths.md +42 -0
  70. package/scaffold/.agents/skills/react-best-practices/rules/bundle-barrel-imports.md +39 -0
  71. package/scaffold/.agents/skills/react-best-practices/rules/bundle-conditional.md +35 -0
  72. package/scaffold/.agents/skills/react-best-practices/rules/bundle-defer-third-party.md +46 -0
  73. package/scaffold/.agents/skills/react-best-practices/rules/bundle-dynamic-imports.md +38 -0
  74. package/scaffold/.agents/skills/react-best-practices/rules/bundle-preload.md +40 -0
  75. package/scaffold/.agents/skills/react-best-practices/rules/client-event-listeners.md +78 -0
  76. package/scaffold/.agents/skills/react-best-practices/rules/client-localstorage-schema.md +74 -0
  77. package/scaffold/.agents/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  78. package/scaffold/.agents/skills/react-best-practices/rules/js-batch-dom-css.md +110 -0
  79. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-function-results.md +58 -0
  80. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  81. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-storage.md +56 -0
  82. package/scaffold/.agents/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  83. package/scaffold/.agents/skills/react-best-practices/rules/js-early-exit.md +50 -0
  84. package/scaffold/.agents/skills/react-best-practices/rules/js-flatmap-filter.md +51 -0
  85. package/scaffold/.agents/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  86. package/scaffold/.agents/skills/react-best-practices/rules/js-index-maps.md +37 -0
  87. package/scaffold/.agents/skills/react-best-practices/rules/js-length-check-first.md +50 -0
  88. package/scaffold/.agents/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  89. package/scaffold/.agents/skills/react-best-practices/rules/js-request-idle-callback.md +104 -0
  90. package/scaffold/.agents/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  91. package/scaffold/.agents/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  92. package/scaffold/.agents/skills/react-best-practices/rules/rendering-activity.md +26 -0
  93. package/scaffold/.agents/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
  94. package/scaffold/.agents/skills/react-best-practices/rules/rendering-conditional-render.md +32 -0
  95. package/scaffold/.agents/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  96. package/scaffold/.agents/skills/react-best-practices/rules/rendering-hoist-jsx.md +36 -0
  97. package/scaffold/.agents/skills/react-best-practices/rules/rendering-resource-hints.md +81 -0
  98. package/scaffold/.agents/skills/react-best-practices/rules/rendering-script-defer-async.md +36 -0
  99. package/scaffold/.agents/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  100. package/scaffold/.agents/skills/react-best-practices/rules/rendering-usetransition-loading.md +43 -0
  101. package/scaffold/.agents/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  102. package/scaffold/.agents/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  103. package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  104. package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  105. package/scaffold/.agents/skills/react-best-practices/rules/rerender-functional-setstate.md +77 -0
  106. package/scaffold/.agents/skills/react-best-practices/rules/rerender-lazy-state-init.md +56 -0
  107. package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo-with-default-value.md +36 -0
  108. package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo.md +44 -0
  109. package/scaffold/.agents/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  110. package/scaffold/.agents/skills/react-best-practices/rules/rerender-no-inline-components.md +75 -0
  111. package/scaffold/.agents/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  112. package/scaffold/.agents/skills/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  113. package/scaffold/.agents/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  114. package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  115. package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  116. package/scaffold/.agents/skills/tanstack-query/SKILL.md +136 -0
  117. package/scaffold/.agents/skills/tanstack-query/references/compositions/automatic-invalidation-after-mutations.md +124 -0
  118. package/scaffold/.agents/skills/tanstack-query/references/compositions/broadcast-realtime-and-multi-tab-synchronization.md +150 -0
  119. package/scaffold/.agents/skills/tanstack-query/references/compositions/compose-query-with-tanstack-router-and-start.md +248 -0
  120. package/scaffold/.agents/skills/tanstack-query/references/compositions/enforce-query-best-practices-with-eslint.md +167 -0
  121. package/scaffold/.agents/skills/tanstack-query/references/compositions/persist-offline-and-restore-caches.md +181 -0
  122. package/scaffold/.agents/skills/tanstack-query/references/compositions/query-data-and-forms.md +156 -0
  123. package/scaffold/.agents/skills/tanstack-query/references/core/build-query-abstractions.md +130 -0
  124. package/scaffold/.agents/skills/tanstack-query/references/core/cancel-queries-and-consume-abort-signals.md +176 -0
  125. package/scaffold/.agents/skills/tanstack-query/references/core/concurrent-optimistic-updates.md +135 -0
  126. package/scaffold/.agents/skills/tanstack-query/references/core/coordinate-query-execution.md +188 -0
  127. package/scaffold/.agents/skills/tanstack-query/references/core/design-query-keys-and-options.md +182 -0
  128. package/scaffold/.agents/skills/tanstack-query/references/core/fetch-and-observe-queries.md +193 -0
  129. package/scaffold/.agents/skills/tanstack-query/references/core/implement-optimistic-updates-and-cache-writes.md +168 -0
  130. package/scaffold/.agents/skills/tanstack-query/references/core/paginate-and-build-infinite-queries.md +188 -0
  131. package/scaffold/.agents/skills/tanstack-query/references/core/seed-placeholder-select-and-transform-data.md +188 -0
  132. package/scaffold/.agents/skills/tanstack-query/references/core/selectors-and-derived-state.md +145 -0
  133. package/scaffold/.agents/skills/tanstack-query/references/core/tune-defaults-freshness-retries-and-refetching.md +172 -0
  134. package/scaffold/.agents/skills/tanstack-query/references/core/understand-query-internals-and-observers.md +104 -0
  135. package/scaffold/.agents/skills/tanstack-query/references/core/write-mutations-and-invalidate-related-queries.md +183 -0
  136. package/scaffold/.agents/skills/tanstack-query/references/framework/debug-with-devtools.md +169 -0
  137. package/scaffold/.agents/skills/tanstack-query/references/framework/handle-status-and-errors.md +119 -0
  138. package/scaffold/.agents/skills/tanstack-query/references/framework/shape-data-and-render-efficiently.md +184 -0
  139. package/scaffold/.agents/skills/tanstack-query/references/framework/use-framework-adapter-reactivity.md +185 -0
  140. package/scaffold/.agents/skills/tanstack-query/references/framework/use-suspense-and-error-boundaries.md +208 -0
  141. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/migrate-major-versions-and-codemods.md +169 -0
  142. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/prefetch-and-remove-request-waterfalls.md +228 -0
  143. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/setup-query-client-and-providers.md +161 -0
  144. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/ssr-hydration-and-streaming.md +209 -0
  145. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/test-query-code.md +160 -0
  146. package/scaffold/.agents/skills/tanstack-router/SKILL.md +134 -0
  147. package/scaffold/.agents/skills/tanstack-router/references/compositions/router-query.md +412 -0
  148. package/scaffold/.agents/skills/tanstack-router/references/react-router.md +495 -0
  149. package/scaffold/.agents/skills/tanstack-router/references/router-core/auth-and-guards.md +495 -0
  150. package/scaffold/.agents/skills/tanstack-router/references/router-core/code-splitting.md +318 -0
  151. package/scaffold/.agents/skills/tanstack-router/references/router-core/data-loading.md +490 -0
  152. package/scaffold/.agents/skills/tanstack-router/references/router-core/index.md +158 -0
  153. package/scaffold/.agents/skills/tanstack-router/references/router-core/navigation.md +433 -0
  154. package/scaffold/.agents/skills/tanstack-router/references/router-core/not-found-and-errors.md +436 -0
  155. package/scaffold/.agents/skills/tanstack-router/references/router-core/path-params.md +383 -0
  156. package/scaffold/.agents/skills/tanstack-router/references/router-core/search-params.md +343 -0
  157. package/scaffold/.agents/skills/tanstack-router/references/router-core/ssr.md +462 -0
  158. package/scaffold/.agents/skills/tanstack-router/references/router-core/type-safety.md +493 -0
  159. package/scaffold/.agents/skills/tanstack-router/references/router-plugin.md +250 -0
  160. package/scaffold/.agents/skills/tanstack-router/references/virtual-file-routes.md +215 -0
  161. package/scaffold/.agents/skills/web-design-guidelines/SKILL.md +184 -0
  162. package/scaffold/.github/workflows/hitch.yml +1 -1
  163. package/scaffold/AGENTS.md +2 -2
  164. package/scaffold/applet/src/client/components/ui/alert.tsx +1 -1
  165. package/scaffold/applet/src/client/components/ui/button.tsx +1 -1
  166. package/scaffold/applet/src/client/components/ui/checkbox.tsx +1 -1
  167. package/scaffold/applet/src/client/components/ui/dialog.tsx +2 -2
  168. package/scaffold/applet/src/client/components/ui/dropdown-menu.tsx +2 -2
  169. package/scaffold/applet/src/client/components/ui/input-group.tsx +2 -2
  170. package/scaffold/applet/src/client/components/ui/select.tsx +2 -2
  171. package/scaffold/applet/src/client/components/ui/sheet.tsx +2 -2
  172. package/scaffold/applet/src/client/components/ui/spinner.tsx +2 -1
  173. package/scaffold/applet/src/client/components/ui/tabs.tsx +1 -1
  174. package/scaffold/applet/src/client/lib/utils.ts +1 -6
  175. package/scaffold/applet/src/client/styles/globals.css +2 -0
  176. package/dist/build-DhNDp7ji.js +0 -2
  177. package/dist/generate-DSk8ihsC.js +0 -2
package/dist/client.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { f as RegisteredContract, m as RegisteredRouter, p as RegisteredManifest } from "./manifest-C489nYUy.js";
2
- import { t as NarrowContract } from "./contract-DB9QQhD9.js";
1
+ import { f as RegisteredContract, m as RegisteredRouter, p as RegisteredManifest } from "./manifest-C6_F4bL8.js";
2
+ import { t as NarrowContract } from "./contract-CsUpTBe0.js";
3
3
  import { t as WithBatchRecorder } from "./batch-Qa4B4-Yp.js";
4
- import { o as WithFilesUpload } from "./upload-YbRKEqR6.js";
4
+ import { o as WithFilesUpload } from "./upload-DKZzz5kW.js";
5
5
  import { RouterClient } from "@orpc/server";
6
6
  import { ContractRouterClient } from "@orpc/contract";
7
7
  import { NestedClient } from "@orpc/client";
@@ -1,4 +1,4 @@
1
- import { n as AppletManifest } from "./manifest-C489nYUy.js";
1
+ import { n as AppletManifest } from "./manifest-C6_F4bL8.js";
2
2
  import { AnyContractRouter } from "@orpc/contract";
3
3
  //#region src/hitch/contract.d.ts
4
4
  type ManifestObjectFor<Manifest, Code> = Manifest extends {
@@ -1,11 +1,12 @@
1
- import { i as readWorkspaceConfig, n as fetchWithOrgAuth } from "./workspace-B6lenAS5.js";
2
- import { a as loadGitHubActionsSources, n as githubActionsContext, r as hitchResponseError, t as fetchWithGitHubActions } from "./ci-gPrwo6C0.js";
3
- import { n as buildPreparedApplet, r as prepareWorkspaceBuild, t as buildApplet } from "./build-DauirTcY.js";
1
+ import { i as readWorkspaceConfig, n as fetchWithOrgAuth } from "./workspace-D0dnnlxL.js";
2
+ import { a as loadGitHubActionsSources, n as githubActionsContext, r as hitchResponseError, t as fetchWithGitHubActions } from "./ci-BKw14X2h.js";
3
+ import { n as buildPreparedApplet, r as prepareWorkspaceBuild, t as buildApplet } from "./build-CEfFoIZZ.js";
4
4
  import { createRequire } from "node:module";
5
+ import { createHash } from "node:crypto";
5
6
  import { existsSync } from "node:fs";
6
- import { readFile, readdir } from "node:fs/promises";
7
- import { relative, resolve, sep } from "node:path";
8
- import { execFile } from "node:child_process";
7
+ import { lstat, readFile, readdir, readlink } from "node:fs/promises";
8
+ import { dirname, relative, resolve, sep } from "node:path";
9
+ import { execFile, spawn } from "node:child_process";
9
10
  import { promisify } from "node:util";
10
11
  import { createGzip } from "node:zlib";
11
12
  //#region \0rolldown/runtime.js
@@ -2307,11 +2308,112 @@ var require_pack = /* @__PURE__ */ __commonJSMin(((exports, module) => {
2307
2308
  }
2308
2309
  }));
2309
2310
  //#endregion
2310
- //#region src/deploy.ts
2311
+ //#region src/source-hash.ts
2311
2312
  var import_tar_stream = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports) => {
2312
2313
  exports.extract = require_extract();
2313
2314
  exports.pack = require_pack();
2314
2315
  })))(), 1);
2316
+ const execFileAsync$1 = promisify(execFile);
2317
+ function gitEnvironment() {
2318
+ return Object.fromEntries(Object.entries(process.env).filter(([key]) => !key.startsWith("GIT_")));
2319
+ }
2320
+ var SourceHashUnavailableError = class extends Error {
2321
+ constructor() {
2322
+ super("Git is unavailable or the applet is outside a git repository.");
2323
+ }
2324
+ };
2325
+ function isMissingPath(error) {
2326
+ return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
2327
+ }
2328
+ async function hashFiles(topLevel, paths, env) {
2329
+ if (paths.length === 0) return [];
2330
+ return new Promise((resolveHashes, reject) => {
2331
+ const child = spawn("git", ["hash-object", "--stdin-paths"], {
2332
+ cwd: topLevel,
2333
+ env
2334
+ });
2335
+ const stdout = [];
2336
+ const stderr = [];
2337
+ child.stdout.on("data", (chunk) => stdout.push(chunk));
2338
+ child.stderr.on("data", (chunk) => stderr.push(chunk));
2339
+ child.stdin.on("error", reject);
2340
+ child.on("error", reject);
2341
+ child.on("close", (code) => {
2342
+ if (code !== 0) {
2343
+ reject(/* @__PURE__ */ new Error(`git hash-object failed (${code}): ${Buffer.concat(stderr).toString("utf8").trim()}`));
2344
+ return;
2345
+ }
2346
+ const hashes = Buffer.concat(stdout).toString("utf8").trimEnd().split("\n");
2347
+ if (hashes.length !== paths.length || hashes.some((hash) => !/^[0-9a-f]{40,64}$/.test(hash))) {
2348
+ reject(/* @__PURE__ */ new Error("git hash-object returned an unexpected number of hashes."));
2349
+ return;
2350
+ }
2351
+ resolveHashes(hashes);
2352
+ });
2353
+ child.stdin.end(paths.map((path) => `"${path.split("").map((character) => character < " " || character === "" || character === "\"" || character === "\\" ? `\\${character.charCodeAt(0).toString(8).padStart(3, "0")}` : character).join("")}"\n`).join(""));
2354
+ });
2355
+ }
2356
+ async function sourceHashes(appletRoots) {
2357
+ if (appletRoots.length === 0) return /* @__PURE__ */ new Map();
2358
+ const env = gitEnvironment();
2359
+ const workspaceRoot = dirname(dirname(appletRoots[0]));
2360
+ let topLevel;
2361
+ try {
2362
+ const { stdout } = await execFileAsync$1("git", ["rev-parse", "--show-toplevel"], {
2363
+ cwd: workspaceRoot,
2364
+ env
2365
+ });
2366
+ topLevel = stdout.trim();
2367
+ } catch (error) {
2368
+ if (isMissingPath(error) || error instanceof Error && error.message.includes("not a git repository")) throw new SourceHashUnavailableError();
2369
+ throw error;
2370
+ }
2371
+ const { stdout } = await execFileAsync$1("git", [
2372
+ "ls-files",
2373
+ "-z",
2374
+ "--cached",
2375
+ "--others",
2376
+ "--exclude-standard"
2377
+ ], {
2378
+ cwd: topLevel,
2379
+ env,
2380
+ maxBuffer: 67108864
2381
+ });
2382
+ const paths = [...new Set(stdout.split("\0").filter(Boolean))];
2383
+ const present = (await Promise.all(paths.map(async (path) => {
2384
+ const absolutePath = resolve(topLevel, path);
2385
+ try {
2386
+ const stat = await lstat(absolutePath);
2387
+ if (stat.isFile()) return {
2388
+ path,
2389
+ kind: "file"
2390
+ };
2391
+ if (stat.isSymbolicLink()) return {
2392
+ path,
2393
+ kind: "link",
2394
+ contentId: await readlink(absolutePath)
2395
+ };
2396
+ return;
2397
+ } catch (error) {
2398
+ if (isMissingPath(error)) return void 0;
2399
+ throw error;
2400
+ }
2401
+ }))).filter((entry) => entry !== void 0);
2402
+ const regularPaths = present.filter((entry) => entry.kind === "file").map((entry) => entry.path);
2403
+ const hashes = await hashFiles(topLevel, regularPaths, env);
2404
+ const contentIds = /* @__PURE__ */ new Map();
2405
+ present.filter((entry) => entry.kind === "link").forEach((entry) => contentIds.set(entry.path, entry.contentId));
2406
+ regularPaths.forEach((path, index) => contentIds.set(path, hashes[index]));
2407
+ const appletsDirectory = relative(topLevel, resolve(workspaceRoot, "applets")).split(sep).join("/");
2408
+ return new Map(appletRoots.map((appletRoot) => {
2409
+ const appletDirectory = relative(topLevel, appletRoot).split(sep).join("/");
2410
+ const digest = createHash("sha256");
2411
+ [...contentIds.entries()].filter(([path]) => path !== appletsDirectory && !path.startsWith(`${appletsDirectory}/`) || path.startsWith(`${appletDirectory}/`)).sort(([left], [right]) => Buffer.compare(Buffer.from(left), Buffer.from(right))).forEach(([path, contentId]) => digest.update(`${path}\0${contentId}\n`));
2412
+ return [appletRoot, digest.digest("hex")];
2413
+ }));
2414
+ }
2415
+ //#endregion
2416
+ //#region src/deploy.ts
2315
2417
  const execFileAsync = promisify(execFile);
2316
2418
  var WorkspaceDeployError = class extends Error {
2317
2419
  constructor(failedApplets) {
@@ -2363,9 +2465,6 @@ async function createBundle(distDir) {
2363
2465
  body.set(bundle);
2364
2466
  return body;
2365
2467
  }
2366
- function gitEnvironment() {
2367
- return Object.fromEntries(Object.entries(process.env).filter(([key]) => !key.startsWith("GIT_")));
2368
- }
2369
2468
  async function readGitInfo(appletRoot) {
2370
2469
  const env = gitEnvironment();
2371
2470
  try {
@@ -2399,13 +2498,14 @@ function releaseForm(manifest, bundle) {
2399
2498
  body.set("bundle", new File([bundle], "bundle.tar.gz", { type: "application/gzip" }));
2400
2499
  return body;
2401
2500
  }
2402
- async function deployWithOrgAuth(appletRoot, distDir, manifest, options) {
2403
- const fetcher = options.fetch ?? globalThis.fetch;
2501
+ async function deployWithOrgAuth(appletRoot, distDir, manifest, sourceHash) {
2502
+ const fetcher = globalThis.fetch;
2404
2503
  const [bundle, git] = await Promise.all([createBundle(distDir), readGitInfo(appletRoot)]);
2405
- return fetchWithOrgAuth(manifest.org, options, (instanceUrl, accessToken) => {
2504
+ return fetchWithOrgAuth(manifest.org, (instanceUrl, accessToken) => {
2406
2505
  const body = releaseForm(manifest, bundle);
2407
2506
  body.set("gitDirty", String(git.gitDirty));
2408
2507
  if (git.gitSha !== void 0) body.set("gitSha", git.gitSha);
2508
+ if (sourceHash !== void 0) body.set("sourceHash", sourceHash);
2409
2509
  return fetcher(`${instanceUrl}/api/v1/applets/${manifest.code}/releases`, {
2410
2510
  method: "POST",
2411
2511
  headers: { Authorization: `Bearer ${accessToken}` },
@@ -2413,12 +2513,13 @@ async function deployWithOrgAuth(appletRoot, distDir, manifest, options) {
2413
2513
  });
2414
2514
  });
2415
2515
  }
2416
- async function deployWithGitHubActions(context, appletRoot, distDir, manifest, options) {
2417
- const fetcher = options.fetch ?? globalThis.fetch;
2516
+ async function deployWithGitHubActions(context, appletRoot, distDir, manifest, sourceHash) {
2517
+ const fetcher = globalThis.fetch;
2418
2518
  const [bundle, sourceDirectory] = await Promise.all([createBundle(distDir), repositoryDirectory(appletRoot)]);
2419
- return fetchWithGitHubActions(context, options, (instanceUrl, accessToken) => {
2519
+ return fetchWithGitHubActions(context, (instanceUrl, accessToken) => {
2420
2520
  const body = releaseForm(manifest, bundle);
2421
2521
  body.set("source_directory", sourceDirectory);
2522
+ if (sourceHash !== void 0) body.set("source_hash", sourceHash);
2422
2523
  return fetcher(`${instanceUrl}/api/ci/v1/applets/${manifest.code}/releases`, {
2423
2524
  method: "POST",
2424
2525
  headers: { Authorization: `Bearer ${accessToken}` },
@@ -2426,12 +2527,13 @@ async function deployWithGitHubActions(context, appletRoot, distDir, manifest, o
2426
2527
  });
2427
2528
  });
2428
2529
  }
2429
- async function deployApplet(appletRoot, options, logPrefix = "") {
2430
- const github = githubActionsContext(options.store?.env ?? process.env);
2530
+ async function deployApplet(appletRoot, options, logPrefix = "", sourceHash) {
2531
+ const github = githubActionsContext();
2532
+ sourceHash ??= (await computeSourceHash([appletRoot], github !== void 0)).get(appletRoot);
2431
2533
  if (options.dist === void 0) await buildApplet(appletRoot);
2432
2534
  const distDir = resolve(appletRoot, options.dist ?? ".hitch/dist");
2433
2535
  const manifest = await readManifest(distDir);
2434
- const response = github === void 0 ? await deployWithOrgAuth(appletRoot, distDir, manifest, options) : await deployWithGitHubActions(github, appletRoot, distDir, manifest, options);
2536
+ const response = github === void 0 ? await deployWithOrgAuth(appletRoot, distDir, manifest, sourceHash) : await deployWithGitHubActions(github, appletRoot, distDir, manifest, sourceHash);
2435
2537
  if (!response.ok) throw await hitchResponseError(response, "Deploy failed");
2436
2538
  const result = await response.json();
2437
2539
  console.log(`${logPrefix}Deployed release ${result.data.id} (${result.promoted ? "promoted" : "not promoted"}).`);
@@ -2452,95 +2554,44 @@ async function workspaceAppletRoots(workspaceRoot) {
2452
2554
  if (roots.length === 0) throw new Error(`No applets were found under ${appletsDir}.`);
2453
2555
  return roots;
2454
2556
  }
2455
- async function gitChanged(topLevel, base, pathspecs, env) {
2557
+ async function computeSourceHash(appletRoots, required) {
2456
2558
  try {
2457
- await execFileAsync("git", [
2458
- "diff",
2459
- "--quiet",
2460
- base,
2461
- "HEAD",
2462
- "--",
2463
- ...pathspecs
2464
- ], {
2465
- cwd: topLevel,
2466
- env
2467
- });
2468
- return false;
2559
+ return await sourceHashes(appletRoots);
2469
2560
  } catch (error) {
2470
- if (error instanceof Error && "code" in error && error.code === 1) return true;
2561
+ if (!required && error instanceof SourceHashUnavailableError) return /* @__PURE__ */ new Map();
2471
2562
  throw error;
2472
2563
  }
2473
2564
  }
2474
- async function hasCommit(topLevel, sha, env) {
2475
- const git = (args) => execFileAsync("git", args, {
2476
- cwd: topLevel,
2477
- env
2478
- });
2479
- return git([
2480
- "cat-file",
2481
- "-e",
2482
- `${sha}^{commit}`
2483
- ]).catch(() => git([
2484
- "fetch",
2485
- "--depth=1",
2486
- "origin",
2487
- sha
2488
- ])).then(() => true, () => false);
2489
- }
2490
- async function ciDeployDecisions(github, workspaceRoot, appletRoots, options) {
2491
- const env = gitEnvironment();
2492
- const [sources, { stdout: topLevelOutput }, directories] = await Promise.all([
2493
- loadGitHubActionsSources(github, options),
2494
- execFileAsync("git", ["rev-parse", "--show-toplevel"], {
2495
- cwd: workspaceRoot,
2496
- env
2497
- }),
2498
- Promise.all(appletRoots.map((appletRoot) => repositoryDirectory(appletRoot)))
2499
- ]);
2500
- const topLevel = topLevelOutput.trim();
2501
- const appletsDirectory = relative(topLevel, resolve(workspaceRoot, "applets")).split(sep).join("/");
2502
- const baseByDirectory = new Map(sources.map((source) => [source.sourceDirectory, source.gitSha]));
2503
- const bases = new Set(directories.flatMap((directory) => baseByDirectory.get(directory) ?? []));
2504
- const sharedChanges = /* @__PURE__ */ new Map();
2505
- for (const base of bases) sharedChanges.set(base, await hasCommit(topLevel, base, env) ? await gitChanged(topLevel, base, [`:(exclude)${appletsDirectory}`], env) : void 0);
2506
- const decisions = await Promise.all(appletRoots.map(async (appletRoot, index) => {
2507
- const directory = directories[index];
2508
- const base = baseByDirectory.get(directory) ?? null;
2509
- if (base === null) return [appletRoot, {
2510
- deploy: true,
2511
- reason: "no CI release to compare"
2512
- }];
2513
- const short = base.slice(0, 7);
2514
- const sharedChanged = sharedChanges.get(base);
2515
- if (sharedChanged === void 0) return [appletRoot, {
2516
- deploy: true,
2517
- reason: `commit ${short} is not in the repository`
2518
- }];
2519
- if (await gitChanged(topLevel, base, [directory], env)) return [appletRoot, {
2565
+ async function ciDeployDecisions(github, appletRoots, hashes) {
2566
+ const [sources, directories] = await Promise.all([loadGitHubActionsSources(github), Promise.all(appletRoots.map((appletRoot) => repositoryDirectory(appletRoot)))]);
2567
+ const hashByDirectory = new Map(sources.map((source) => [source.sourceDirectory, source.sourceHash]));
2568
+ return new Map(appletRoots.map((appletRoot, index) => {
2569
+ const sourceHash = hashByDirectory.get(directories[index]);
2570
+ if (sourceHash === null || sourceHash === void 0) return [appletRoot, {
2520
2571
  deploy: true,
2521
- reason: `${directory} changed since ${short}`
2572
+ reason: "no release with a source hash to compare"
2522
2573
  }];
2523
- if (sharedChanged) return [appletRoot, {
2574
+ if (sourceHash !== hashes.get(appletRoot)) return [appletRoot, {
2524
2575
  deploy: true,
2525
- reason: `files outside ${appletsDirectory} changed since ${short}`
2576
+ reason: "files changed since the current release"
2526
2577
  }];
2527
2578
  return [appletRoot, {
2528
2579
  deploy: false,
2529
- reason: `no changes since ${short}`
2580
+ reason: "no changes since the current release"
2530
2581
  }];
2531
2582
  }));
2532
- return new Map(decisions);
2533
2583
  }
2534
2584
  async function runDeploy(options) {
2535
2585
  const root = process.cwd();
2536
- const github = githubActionsContext(options.store?.env ?? process.env);
2586
+ const github = githubActionsContext();
2537
2587
  if (existsSync(resolve(root, "applet.manifest.ts"))) {
2538
2588
  await deployApplet(root, options);
2539
2589
  return;
2540
2590
  }
2541
2591
  if (readWorkspaceConfig(root) === void 0) throw new Error("Run applet deploy in an applet folder or in the workspace root.");
2542
2592
  const appletRoots = await workspaceAppletRoots(root);
2543
- const decisions = github === void 0 ? void 0 : await ciDeployDecisions(github, root, appletRoots, options);
2593
+ const hashes = await computeSourceHash(appletRoots, github !== void 0);
2594
+ const decisions = github === void 0 ? void 0 : await ciDeployDecisions(github, appletRoots, hashes);
2544
2595
  const selectedRoots = appletRoots.filter((appletRoot) => {
2545
2596
  const name = relative(root, appletRoot);
2546
2597
  const decision = decisions?.get(appletRoot);
@@ -2554,14 +2605,14 @@ async function runDeploy(options) {
2554
2605
  });
2555
2606
  if (selectedRoots.length === 0) return;
2556
2607
  if (options.dist === void 0) await prepareWorkspaceBuild(root, appletRoots);
2557
- const interactive = github === void 0 && (options.stdinIsTTY ?? process.stdin.isTTY === true);
2608
+ const interactive = github === void 0 && process.stdin.isTTY === true;
2558
2609
  const deploy = async (appletRoot) => {
2559
2610
  const logPrefix = `[${relative(root, appletRoot)}] `;
2560
2611
  if (options.dist === void 0) await buildPreparedApplet(appletRoot, ".hitch/dist", interactive ? "" : logPrefix);
2561
2612
  await deployApplet(appletRoot, {
2562
2613
  ...options,
2563
2614
  dist: options.dist ?? ".hitch/dist"
2564
- }, logPrefix);
2615
+ }, logPrefix, hashes.get(appletRoot));
2565
2616
  };
2566
2617
  if (interactive) {
2567
2618
  for (const appletRoot of selectedRoots) await deploy(appletRoot);
@@ -0,0 +1,62 @@
1
+ import { oc } from "@orpc/contract";
2
+ import { z } from "zod";
3
+ //#region src/hitch/email.ts
4
+ const emailTagKeySchema = z.string().regex(/^[A-Za-z][A-Za-z0-9_]{0,63}$/);
5
+ const emailTagsSchema = z.record(emailTagKeySchema, z.string().min(1).max(200)).refine((tags) => Object.keys(tags).length <= 10);
6
+ const createEmailPixelInputSchema = z.object({ tags: emailTagsSchema.optional() }).strict();
7
+ const createEmailPixelOutputSchema = z.object({
8
+ id: z.uuid(),
9
+ url: z.url()
10
+ });
11
+ const getEmailTrackerInputSchema = z.object({ id: z.uuid() });
12
+ const markEmailTrackerSentInputSchema = z.object({
13
+ id: z.uuid(),
14
+ sentAt: z.iso.datetime({ offset: true }).optional()
15
+ }).strict();
16
+ const markEmailTrackerSentBodySchema = z.object({ sentAt: z.iso.datetime({ offset: true }).optional() }).strict();
17
+ const emailTrackerSchema = z.object({
18
+ id: z.uuid(),
19
+ url: z.url(),
20
+ tags: emailTagsSchema,
21
+ createdAt: z.iso.datetime(),
22
+ sentAt: z.iso.datetime().nullable(),
23
+ firstHitAt: z.iso.datetime().nullable(),
24
+ lastHitAt: z.iso.datetime().nullable()
25
+ });
26
+ const listEmailTrackersInputSchema = z.object({
27
+ filter: emailTagsSchema.optional(),
28
+ sentAt: z.object({
29
+ $gte: z.iso.datetime({ offset: true }).optional(),
30
+ $lt: z.iso.datetime({ offset: true }).optional()
31
+ }).strict().optional(),
32
+ cursor: z.uuid().optional(),
33
+ limit: z.number().int().min(1).max(200).optional()
34
+ }).strict();
35
+ const listEmailTrackersOutputSchema = z.object({
36
+ trackers: z.array(emailTrackerSchema),
37
+ nextCursor: z.uuid().nullable()
38
+ });
39
+ function emailContract(appletCode) {
40
+ const path = `/v1/applets/${encodeURIComponent(appletCode)}/email/tracking`;
41
+ return { tracking: {
42
+ createPixel: oc.route({
43
+ method: "POST",
44
+ path: `${path}/pixels`,
45
+ successStatus: 201
46
+ }).input(createEmailPixelInputSchema.optional()).output(createEmailPixelOutputSchema),
47
+ markSent: oc.route({
48
+ method: "POST",
49
+ path: `${path}/{id}/sent`
50
+ }).input(markEmailTrackerSentInputSchema).output(emailTrackerSchema),
51
+ get: oc.route({
52
+ method: "GET",
53
+ path: `${path}/{id}`
54
+ }).input(getEmailTrackerInputSchema).output(emailTrackerSchema),
55
+ list: oc.route({
56
+ method: "POST",
57
+ path: `${path}/list`
58
+ }).input(listEmailTrackersInputSchema.optional()).output(listEmailTrackersOutputSchema)
59
+ } };
60
+ }
61
+ //#endregion
62
+ export { emailTagsSchema as a, listEmailTrackersInputSchema as c, markEmailTrackerSentInputSchema as d, emailTagKeySchema as i, listEmailTrackersOutputSchema as l, createEmailPixelOutputSchema as n, emailTrackerSchema as o, emailContract as r, getEmailTrackerInputSchema as s, createEmailPixelInputSchema as t, markEmailTrackerSentBodySchema as u };
@@ -1,7 +1,7 @@
1
- import { l as resolveInstanceUrl, n as fetchWithOrgAuth, s as organizationInstanceUrl } from "./workspace-B6lenAS5.js";
2
- import { i as loadGitHubActionsBuildInputs, n as githubActionsContext } from "./ci-gPrwo6C0.js";
3
- import { t as loadAppletConfig } from "./load-config-BknBkdRs.js";
4
- import { r as prepareAppletProject } from "./project-C_rtpjp8.js";
1
+ import { f as resolveInstanceUrl, l as organizationInstanceUrl, n as fetchWithOrgAuth } from "./workspace-D0dnnlxL.js";
2
+ import { i as loadGitHubActionsBuildInputs, n as githubActionsContext } from "./ci-BKw14X2h.js";
3
+ import { r as prepareAppletProject } from "./project-BRZGd6xq.js";
4
+ import { t as loadAppletConfig } from "./load-config-xEdTXs0y.js";
5
5
  import { createRequire } from "node:module";
6
6
  import { existsSync } from "node:fs";
7
7
  import { access, mkdir, mkdtemp, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
@@ -55,7 +55,7 @@ export default createWorkerEntry(server, { code: ${JSON.stringify(appletCode)} }
55
55
  }
56
56
  //#endregion
57
57
  //#region src/typegen/operations.ts
58
- const RECORD_ROUTE = /^\/v1\/([^/]+)(?:\/(\{id\}|query|update|aggregate))?$/;
58
+ const RECORD_ROUTE = /^\/v1\/([^/]+)(?:\/(\{id\}(?:\/history)?|query|update|aggregate))?$/;
59
59
  const COMPONENT_REF_PREFIX$1 = "#/components/schemas/";
60
60
  const BATCH_PATH = "/v1/batch";
61
61
  const BATCH_ITEM_PATH = "paths./v1/batch.post.requestBody.content.application/json.schema.properties.requests.items";
@@ -64,6 +64,7 @@ const VERBS = {
64
64
  "get:": "list",
65
65
  "post:": "create",
66
66
  "get:{id}": "get",
67
+ "get:{id}/history": "history",
67
68
  "patch:{id}": "update",
68
69
  "delete:{id}": "delete",
69
70
  "post:query": "query",
@@ -74,6 +75,7 @@ const COMPONENT_RESPONSE_STATUS = {
74
75
  list: "200",
75
76
  create: "201",
76
77
  get: "200",
78
+ history: "200",
77
79
  update: "200",
78
80
  query: "200"
79
81
  };
@@ -149,10 +151,13 @@ function prepareBatchOperation(operation, manifest) {
149
151
  if (manifest === void 0) return true;
150
152
  const object = manifest.objects.find(({ code }) => code === objectCode);
151
153
  if (object === void 0) return false;
152
- if (verb === "create") return object.canCreate;
153
- if (verb === "delete") return object.canDelete;
154
- if (verb === "update" || verb === "updateWhere") return object.readWrite.length > 0;
155
- return true;
154
+ switch (verb) {
155
+ case "create": return object.canCreate;
156
+ case "delete": return object.canDelete;
157
+ case "update":
158
+ case "updateWhere": return object.readWrite.length > 0;
159
+ default: return true;
160
+ }
156
161
  });
157
162
  if (entries.length === 0) return void 0;
158
163
  items.oneOf = entries;
@@ -166,7 +171,7 @@ function prepareRecordSpec(spec, manifest) {
166
171
  const prepared = structuredClone(spec);
167
172
  prepared.paths = Object.fromEntries(Object.entries(prepared.paths).flatMap(([path, pathItem]) => {
168
173
  if (path === BATCH_PATH) {
169
- if (!isObject$2(pathItem) || pathItem.post === void 0) return [];
174
+ if (!isObject$2(pathItem)) return [];
170
175
  const operation = prepareBatchOperation(pathItem.post, manifest);
171
176
  return operation === void 0 ? [] : [[path, { post: operation }]];
172
177
  }
@@ -194,6 +199,37 @@ function prepareRecordSpec(spec, manifest) {
194
199
  });
195
200
  return operations.length > 0 ? [[path, Object.fromEntries(operations)]] : [];
196
201
  }));
202
+ manifest?.objects.forEach(({ code, optionalAttributes }) => {
203
+ if (optionalAttributes === void 0 || optionalAttributes.length === 0) return;
204
+ const responsePath = `/v1/${code}/{id}`;
205
+ const response = prepared.paths[responsePath]?.get?.responses;
206
+ const schema = isObject$2(response) && isObject$2(response["200"]) ? response["200"].content : void 0;
207
+ const mediaType = isObject$2(schema) && isObject$2(schema["application/json"]) ? schema["application/json"] : void 0;
208
+ const ref = isObject$2(mediaType) && isObject$2(mediaType.schema) ? mediaType.schema.$ref : void 0;
209
+ const recordPath = `paths.${responsePath}.get.responses.200.content.application/json.schema`;
210
+ if (typeof ref !== "string" || !ref.startsWith(COMPONENT_REF_PREFIX$1)) throw new Error(`object "${code}": ${recordPath} expected a component schema $ref, found ${describeValue$1(mediaType)}`);
211
+ const componentName = ref.slice(21);
212
+ const components = isObject$2(prepared.components) ? prepared.components : void 0;
213
+ const record = (isObject$2(components?.schemas) ? components.schemas : void 0)?.[componentName];
214
+ const componentPath = `components.schemas.${componentName}`;
215
+ if (!isObject$2(record) || !isObject$2(record.properties)) throw new Error(`object "${code}": ${componentPath}.properties expected an object, found ${describeValue$1(isObject$2(record) ? record.properties : record)}`);
216
+ const properties = record.properties;
217
+ optionalAttributes.forEach((attributeCode) => {
218
+ const property = properties[attributeCode];
219
+ const propertyPath = `${componentPath}.properties.${attributeCode}`;
220
+ if (!isObject$2(property)) throw new Error(`object "${code}": ${propertyPath} expected an object, found ${describeValue$1(property)}`);
221
+ const types = Array.isArray(property.type) ? property.type : [property.type];
222
+ properties[attributeCode] = property.type !== void 0 ? {
223
+ ...property,
224
+ type: types.includes("null") ? types : [...types, "null"],
225
+ ...Array.isArray(property.enum) && !property.enum.includes(null) ? { enum: [...property.enum, null] } : {}
226
+ } : Array.isArray(property.oneOf) ? {
227
+ ...property,
228
+ oneOf: [...property.oneOf, { type: "null" }]
229
+ } : Array.isArray(property.anyOf) && property.anyOf.some((item) => isObject$2(item) && item.type === "null") ? property : { anyOf: [property, { type: "null" }] };
230
+ });
231
+ if (Array.isArray(record.required)) record.required = record.required.filter((name) => !optionalAttributes.includes(name));
232
+ });
197
233
  return prepared;
198
234
  }
199
235
  function describeValue$1(value, expectedRef = false) {
@@ -274,7 +310,7 @@ ${Object.entries(catalog).map(([objectCode, attributeCodes]) => ` ${JSON.string
274
310
  };`;
275
311
  return `// Generated by @hitch42/applet — do not edit.
276
312
  import type manifest from "./manifest.gen.ts";
277
- ${options.hasServer ? "import type server from \"../src/server/main.ts\";\nimport type * as serverModule from \"../src/server/main.ts\";\n" : ""}${options.hasClient ? "import type { Route as indexRoute } from \"../src/client/routes/index.tsx\";\n" : ""}${options.hasServer ? "import type { AnyRouter } from \"@orpc/server\";\n" : ""}${options.hasClient ? "import type { AnyRoute } from \"@tanstack/react-router\";\n" : ""}${options.hasServer ? "import type { WorkflowDefinition } from \"@hitch42/applet/server\";\n" : ""}
313
+ ${options.hasServer ? "import type server from \"../src/server/main.ts\";\nimport type * as serverModule from \"../src/server/main.ts\";\n" : ""}${options.hasClient ? "import type { Route as indexRoute } from \"../src/client/routes/index.tsx\";\n" : ""}${options.hasServer ? "import type { AnyRouter } from \"@orpc/server\";\n" : ""}${options.hasClient ? "import type { AnyRoute } from \"@tanstack/react-router\";\n" : ""}${options.hasServer ? "import type { WorkflowDefinition } from \"@hitch42/applet/server\";\nimport type { TelephonyMessageReceivedEvent } from \"@hitch42/applet\";\n" : ""}
278
314
  ${catalogType}
279
315
 
280
316
  type Expect<T extends true> = T;
@@ -287,6 +323,7 @@ type _SrcServerMainMustDefaultExportRouterAndValidWorkflows = Expect<
287
323
  typeof server extends {
288
324
  router: AnyRouter;
289
325
  workflows?: Record<string, WorkflowDefinition<any, any>>;
326
+ telephony?: { onMessageReceived?: (event: TelephonyMessageReceivedEvent) => void | Promise<void> };
290
327
  }
291
328
  ? true
292
329
  : false
@@ -352,33 +389,31 @@ async function responseJson(response) {
352
389
  throw new Error("Failed to parse the organization's OpenAPI spec.", { cause: error });
353
390
  }
354
391
  }
355
- async function loadAuthenticatedSpec(manifest, options) {
356
- const github = githubActionsContext(options.store?.env ?? process.env);
357
- if (github !== void 0) return (await loadGitHubActionsBuildInputs(github, options, manifest.requiresChangeset)).openapi;
358
- const fetcher = options.fetch ?? globalThis.fetch;
359
- const response = await fetchWithOrgAuth(manifest.org, options, (instanceUrl, accessToken) => fetcher(`${instanceUrl}/api/v1/openapi.json${manifest.requiresChangeset === void 0 ? "" : `?changeset_id=${encodeURIComponent(manifest.requiresChangeset)}`}`, { headers: { Authorization: `Bearer ${accessToken}` } }));
392
+ async function loadAuthenticatedSpec(manifest) {
393
+ const github = githubActionsContext();
394
+ if (github !== void 0) return (await loadGitHubActionsBuildInputs(github, manifest.requiresChangeset)).openapi;
395
+ const response = await fetchWithOrgAuth(manifest.org, (instanceUrl, accessToken) => globalThis.fetch(`${instanceUrl}/api/v1/openapi.json${manifest.requiresChangeset === void 0 ? "" : `?changeset_id=${encodeURIComponent(manifest.requiresChangeset)}`}`, { headers: { Authorization: `Bearer ${accessToken}` } }));
360
396
  if (!response.ok) throw new Error(`Failed to load the organization's OpenAPI spec (${response.status}).`);
361
397
  return responseJson(response);
362
398
  }
363
- async function loadThemeStylesheet(orgCode, options) {
364
- const fetcher = options.fetch ?? globalThis.fetch;
365
- const instanceUrl = await resolveInstanceUrl(void 0, options.store);
366
- const response = await fetcher(`${organizationInstanceUrl(instanceUrl, orgCode)}/theme.css`);
399
+ async function loadThemeStylesheet(orgCode) {
400
+ const instanceUrl = await resolveInstanceUrl();
401
+ const response = await globalThis.fetch(`${organizationInstanceUrl(instanceUrl, orgCode)}/theme.css`);
367
402
  if (!response.ok) throw new Error(`Failed to load the organization's theme (${response.status}).`);
368
403
  return response.text();
369
404
  }
370
- async function loadBuildInputs(manifest, options) {
371
- const github = githubActionsContext(options.store?.env ?? process.env);
405
+ async function loadBuildInputs(manifest) {
406
+ const github = githubActionsContext();
372
407
  if (github !== void 0) {
373
- const inputs = await loadGitHubActionsBuildInputs(github, options, manifest.requiresChangeset);
408
+ const inputs = await loadGitHubActionsBuildInputs(github, manifest.requiresChangeset);
374
409
  return {
375
410
  spec: inputs.openapi,
376
411
  theme: inputs.theme
377
412
  };
378
413
  }
379
414
  return {
380
- spec: await loadAuthenticatedSpec(manifest, options),
381
- theme: await loadThemeStylesheet(manifest.org, options)
415
+ spec: await loadAuthenticatedSpec(manifest),
416
+ theme: await loadThemeStylesheet(manifest.org)
382
417
  };
383
418
  }
384
419
  async function generateContract(spec, outDir) {
@@ -420,16 +455,16 @@ async function writeContractFiles(outDir, manifest, spec) {
420
455
  await writeManifestGen(outDir, manifest);
421
456
  await writeRegisterDeclaration(outDir, catalog);
422
457
  await writeFile(resolve(outDir, "index.ts"), `// Generated by applet generate — do not edit.
423
- import { filesContract as files, meContract as me, pruneContract, registerHitchContract, teamsContract as teams } from "@hitch42/applet";
458
+ import { emailContract, filesContract as files, meContract as me, pruneContract, registerHitchContract, teamsContract as teams, telephonyContract as telephony } from "@hitch42/applet";
424
459
  import manifest from "./manifest.gen.ts";
425
460
 
426
461
  ${Object.hasOwn(preparedSpec.paths, "/v1/batch") ? `import { contract as generated } from "./orpc.gen.ts";
427
462
 
428
463
  const { batch, ...records } = generated;
429
464
 
430
- export const contract = { records, batch, files, me, teams } as const;` : `import { contract as records } from "./orpc.gen.ts";
465
+ export const contract = { records, batch, email: emailContract(manifest.code), files, me, teams, telephony } as const;` : `import { contract as records } from "./orpc.gen.ts";
431
466
 
432
- export const contract = { records, files, me, teams } as const;`}
467
+ export const contract = { records, email: emailContract(manifest.code), files, me, teams, telephony } as const;`}
433
468
  registerHitchContract(pruneContract(contract, manifest));
434
469
 
435
470
  declare module "@hitch42/applet" {
@@ -441,15 +476,18 @@ declare module "@hitch42/applet" {
441
476
  export type * from "./zod.gen.ts";
442
477
  `);
443
478
  }
444
- async function syncContract(outDir, manifest, options = {}) {
445
- await writeContractFiles(outDir, manifest, await loadAuthenticatedSpec(manifest, options));
479
+ async function syncContract(outDir, manifest) {
480
+ await writeContractFiles(outDir, manifest, manifest.objects.length === 0 ? {
481
+ paths: {},
482
+ components: { schemas: {} }
483
+ } : await loadAuthenticatedSpec(manifest));
446
484
  }
447
- async function runGenerate(options) {
485
+ async function runGenerate() {
448
486
  await prepareAppletProject();
449
487
  const root = process.cwd();
450
488
  const outDir = resolve("./.hitch");
451
489
  const manifest = await loadAppletConfig(process.cwd());
452
- const { spec, theme: themeStylesheet } = await loadBuildInputs(manifest, options);
490
+ const { spec, theme: themeStylesheet } = await loadBuildInputs(manifest);
453
491
  const stagedDir = await mkdtemp(resolve("./.hitch.tmp-"));
454
492
  const backupDir = `${stagedDir}.backup`;
455
493
  let staged = true;
@@ -0,0 +1,2 @@
1
+ import { n as runGenerate } from "./generate-BEIYs17x.js";
2
+ export { runGenerate };
@@ -0,0 +1,17 @@
1
+ //#region src/headers.ts
2
+ const HITCH_USER_HEADER = "x-hitch-user";
3
+ const HITCH_SESSION_HEADER = "x-hitch-session";
4
+ const HITCH_APPLET_HEADER = "x-hitch-applet";
5
+ const HITCH_APPLET_CODE_HEADER = "x-hitch-applet-code";
6
+ const HITCH_APPLET_TOKEN_HEADER = "x-hitch-applet-token";
7
+ const HITCH_SCHEDULE_RUN_HEADER = "x-hitch-schedule-run";
8
+ const HITCH_SCHEDULE_HEADER = "x-hitch-schedule";
9
+ const HITCH_ORG_CODE_HEADER = "x-hitch-org-code";
10
+ const HITCH_ORGANIZATION_HEADER = "x-hitch-organization";
11
+ const HITCH_RELEASE_HEADER = "x-hitch-release";
12
+ const HITCH_REQUEST_HOST_HEADER = "x-hitch-request-host";
13
+ const HITCH_WORKFLOW_RUN_HEADER = "x-hitch-workflow-run";
14
+ const HITCH_WORKFLOW_HEADER = "x-hitch-workflow";
15
+ const HITCH_WORKFLOW_INVOCATION_HEADER = "x-hitch-workflow-invocation";
16
+ //#endregion
17
+ export { HITCH_ORG_CODE_HEADER as a, HITCH_SCHEDULE_HEADER as c, HITCH_USER_HEADER as d, HITCH_WORKFLOW_HEADER as f, HITCH_ORGANIZATION_HEADER as i, HITCH_SCHEDULE_RUN_HEADER as l, HITCH_WORKFLOW_RUN_HEADER as m, HITCH_APPLET_HEADER as n, HITCH_RELEASE_HEADER as o, HITCH_WORKFLOW_INVOCATION_HEADER as p, HITCH_APPLET_TOKEN_HEADER as r, HITCH_REQUEST_HOST_HEADER as s, HITCH_APPLET_CODE_HEADER as t, HITCH_SESSION_HEADER as u };