@hitch42/applet 0.1.1-beta.1 → 0.1.1-beta.11

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 (178) 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 +53 -29
  7. package/dist/build-Bh_S5BUv.js +2 -0
  8. package/dist/{build-Rk3xDZV7.js → build-CEfFoIZZ.js} +30 -14
  9. package/dist/ci-BKw14X2h.js +69 -0
  10. package/dist/client.d.ts +3 -3
  11. package/dist/{contract-DMrpbaLJ.d.ts → contract-CsUpTBe0.d.ts} +1 -1
  12. package/dist/{deploy-D3BGDqgC.js → deploy-wGYjwXrx.js} +249 -35
  13. package/dist/email-DBTVhNB_.js +62 -0
  14. package/dist/{generate-CH0VQmUi.js → generate-BEIYs17x.js} +79 -25
  15. package/dist/generate-Dox-OYt6.js +2 -0
  16. package/dist/headers-DkNr9MLJ.js +17 -0
  17. package/dist/index.d.ts +123 -11
  18. package/dist/index.js +142 -26
  19. package/dist/{init-BS1Y-eNL.js → init-6oGPM46R.js} +17 -18
  20. package/dist/load-config-xEdTXs0y.js +27 -0
  21. package/dist/log-context-zu8U9Sjm.js +73 -0
  22. package/dist/login-CUx3TmFQ.js +12 -0
  23. package/dist/{logs-m00pzr_O.js → logs-DSjuEN0Q.js} +20 -22
  24. package/dist/{manifest-BQCAxATS.d.ts → manifest-C6_F4bL8.d.ts} +9 -0
  25. package/dist/{manifest-DyoJ1MIL.js → manifest-CJSL9GuC.js} +25 -3
  26. package/dist/me-BW7Paary.js +32 -0
  27. package/dist/{project-CxN-Dtc7.js → project-BRZGd6xq.js} +227 -34
  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-CP7Ce3Np.js → variables-DT5RyHdH.js} +14 -39
  40. package/dist/vite.d.ts +3 -60
  41. package/dist/vite.js +503 -34
  42. package/dist/workflow-engine-BOTzURKM.js +111 -0
  43. package/dist/{auth-DaVK0k5R.js → workspace-D0dnnlxL.js} +75 -40
  44. package/package.json +19 -6
  45. package/scaffold/.agents/skills/hitch-applets/SKILL.md +60 -15
  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 +29 -2
  49. package/scaffold/.agents/skills/hitch-applets/references/markdown.md +2 -0
  50. package/scaffold/.agents/skills/hitch-applets/references/performance.md +74 -0
  51. package/scaffold/.agents/skills/hitch-applets/references/records.md +32 -8
  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 +129 -0
  56. package/scaffold/.agents/skills/hitch-data/SKILL.md +52 -0
  57. package/scaffold/.agents/skills/hitch-data/references/attributes.md +127 -0
  58. package/scaffold/.agents/skills/hitch-data/references/limits.md +64 -0
  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 +15 -0
  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-CEku1lyb.js +0 -2
  177. package/dist/generate-6Nbt7uii.js +0 -2
  178. package/dist/load-config-BnxocLAQ.js +0 -56
@@ -1,8 +1,72 @@
1
- import { n as loadAppletSourceDefinition, r as readWorkspaceConfig } from "./load-config-BnxocLAQ.js";
1
+ import { i as readWorkspaceConfig, l as organizationInstanceUrl, s as DEFAULT_INSTANCE_URL } from "./workspace-D0dnnlxL.js";
2
+ import { n as loadAppletSourceDefinition } from "./load-config-xEdTXs0y.js";
2
3
  import { z } from "zod";
3
4
  import { existsSync } from "node:fs";
4
- import { cp, mkdir, readFile, rm, symlink, writeFile } from "node:fs/promises";
5
+ import { cp, mkdir, readFile, readdir, rm, symlink, writeFile } from "node:fs/promises";
5
6
  import { dirname, relative, resolve } from "node:path";
7
+ import { TomlError, parse, stringify } from "smol-toml";
8
+ //#region src/agent-support.ts
9
+ var AgentConfigError = class extends Error {};
10
+ async function ensureAgentConfigs(root, org) {
11
+ const servers = {
12
+ hitch: {
13
+ type: "http",
14
+ url: `${organizationInstanceUrl(DEFAULT_INSTANCE_URL, org)}/mcp`
15
+ },
16
+ "chrome-devtools": {
17
+ type: "stdio",
18
+ command: "pnpx",
19
+ args: ["chrome-devtools-mcp@latest", "--headless"]
20
+ }
21
+ };
22
+ const configs = await Promise.all([{
23
+ path: resolve(root, ".mcp.json"),
24
+ format: "json",
25
+ key: "mcpServers"
26
+ }, {
27
+ path: resolve(root, ".codex/config.toml"),
28
+ format: "toml",
29
+ key: "mcp_servers"
30
+ }].map(async ({ path, format, key }) => {
31
+ const current = existsSync(path) ? await readFile(path, "utf8") : void 0;
32
+ let config;
33
+ let additions;
34
+ try {
35
+ config = z.record(z.string(), z.unknown()).parse(current === void 0 ? {} : format === "json" ? JSON.parse(current) : parse(current, { integersAsBigInt: true }));
36
+ const existing = config[key] === void 0 ? {} : z.record(z.string(), z.unknown()).parse(config[key]);
37
+ const missing = Object.entries(servers).filter(([name]) => !Object.hasOwn(existing, name));
38
+ if (current !== void 0 && missing.length === 0) return void 0;
39
+ additions = Object.fromEntries(missing.map(([name, server]) => [name, format === "json" ? server : Object.fromEntries(Object.entries(server).filter(([field]) => field !== "type"))]));
40
+ config[key] = {
41
+ ...existing,
42
+ ...additions
43
+ };
44
+ } catch (cause) {
45
+ throw new AgentConfigError(`Invalid agent configuration in ${path}.`, { cause });
46
+ }
47
+ if (format === "json") return {
48
+ path,
49
+ contents: `${JSON.stringify(config, null, 2)}\n`
50
+ };
51
+ const contents = `${current ?? ""}${current ? "\n" : ""}${stringify({ [key]: additions })}`;
52
+ try {
53
+ parse(contents, { integersAsBigInt: true });
54
+ return {
55
+ path,
56
+ contents
57
+ };
58
+ } catch (error) {
59
+ if (!(error instanceof TomlError)) throw error;
60
+ return {
61
+ path,
62
+ contents: stringify(config, { numbersAsFloat: true })
63
+ };
64
+ }
65
+ }));
66
+ await mkdir(resolve(root, ".codex"), { recursive: true });
67
+ await Promise.all(configs.filter((config) => config !== void 0).map(({ path, contents }) => writeFile(path, contents)));
68
+ }
69
+ //#endregion
6
70
  //#region src/project.ts
7
71
  const PACKAGE_MANAGER = "pnpm@11.18.0+sha512.33d83c77da82f49fba836925c6f1b841181ec3132b670639bd012f7075f5c7cf634c5f870147c19aae7478fac01df09d8892e880454896edd23ee9b33757563c";
8
72
  const cliManifestValueSchema = z.string().min(1, "must be a non-empty string");
@@ -10,6 +74,7 @@ const cliManifestSchema = z.object({
10
74
  name: cliManifestValueSchema,
11
75
  version: cliManifestValueSchema,
12
76
  dependencies: z.object({
77
+ "@fontsource-variable/geist-mono": cliManifestValueSchema,
13
78
  "@fontsource-variable/inter": cliManifestValueSchema,
14
79
  "@orpc/contract": cliManifestValueSchema,
15
80
  "@tiptap/core": cliManifestValueSchema,
@@ -23,12 +88,14 @@ const cliManifestSchema = z.object({
23
88
  "@tailwindcss/vite": cliManifestValueSchema,
24
89
  "@tanstack/router-cli": cliManifestValueSchema,
25
90
  "class-variance-authority": cliManifestValueSchema,
26
- clsx: cliManifestValueSchema,
91
+ cn: cliManifestValueSchema,
27
92
  "lucide-react": cliManifestValueSchema,
93
+ oxfmt: cliManifestValueSchema,
94
+ oxlint: cliManifestValueSchema,
95
+ "oxlint-tsgolint": cliManifestValueSchema,
28
96
  "react-aria-components": cliManifestValueSchema,
29
97
  shadcn: cliManifestValueSchema,
30
98
  streamdown: cliManifestValueSchema,
31
- "tailwind-merge": cliManifestValueSchema,
32
99
  tailwindcss: cliManifestValueSchema,
33
100
  "tw-animate-css": cliManifestValueSchema,
34
101
  vite: cliManifestValueSchema,
@@ -50,11 +117,11 @@ const cliManifestSchema = z.object({
50
117
  async function loadCliManifest(options) {
51
118
  const result = cliManifestSchema.safeParse(JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8")));
52
119
  if (!result.success) {
53
- const issue = result.error.issues[0];
120
+ const issue = result.error.issues.at(0);
54
121
  if (issue === void 0) throw new Error("Invalid CLI package manifest.");
55
122
  throw new Error(`Invalid CLI package manifest field "${issue.path.join(".")}": ${issue.message}.`);
56
123
  }
57
- const catalogEntry = [...Object.entries(result.data.dependencies).map(([name, value]) => [`dependencies.${name}`, value]), ...Object.entries(result.data.peerDependencies).map(([name, value]) => [`peerDependencies.${name}`, value])].find(([, value]) => value?.startsWith("catalog:"));
124
+ const catalogEntry = [...Object.entries(result.data.dependencies).map(([name, value]) => [`dependencies.${name}`, value]), ...Object.entries(result.data.peerDependencies).map(([name, value]) => [`peerDependencies.${name}`, value])].find(([, value]) => value.startsWith("catalog:"));
58
125
  if (catalogEntry !== void 0) {
59
126
  if (options?.allowDevelopment === true) return void 0;
60
127
  throw new Error(`Invalid CLI package manifest field "${catalogEntry[0]}": "catalog:" identifies an unpublished development build. Run the published @hitch42/applet CLI instead.`);
@@ -70,8 +137,16 @@ function workspacePackage(org) {
70
137
  name: `${org.replaceAll("_", "-")}-applets`,
71
138
  private: true,
72
139
  type: "module",
140
+ scripts: {
141
+ lint: "oxlint",
142
+ fmt: "oxfmt",
143
+ check: "oxfmt --check && oxlint"
144
+ },
73
145
  devDependencies: {
74
146
  "@hitch42/applet": "catalog:",
147
+ oxfmt: "catalog:",
148
+ oxlint: "catalog:",
149
+ "oxlint-tsgolint": "catalog:",
75
150
  typescript: "catalog:",
76
151
  vite: "catalog:",
77
152
  vitest: "catalog:"
@@ -84,6 +159,7 @@ function workspaceFile(cli) {
84
159
  - applets/*
85
160
  catalog:
86
161
  "@hitch42/applet": npm:${cli.name}@${cli.version}
162
+ "@fontsource-variable/geist-mono": "${cli.dependencies["@fontsource-variable/geist-mono"]}"
87
163
  "@fontsource-variable/inter": "${cli.dependencies["@fontsource-variable/inter"]}"
88
164
  "@orpc/contract": "${cli.dependencies["@orpc/contract"]}"
89
165
  "@orpc/server": "${cli.peerDependencies["@orpc/server"]}"
@@ -103,14 +179,16 @@ catalog:
103
179
  "@types/react-dom": "${cli.peerDependencies["@types/react-dom"]}"
104
180
  "@tailwindcss/vite": "${cli.dependencies["@tailwindcss/vite"]}"
105
181
  class-variance-authority: "${cli.dependencies["class-variance-authority"]}"
106
- clsx: "${cli.dependencies.clsx}"
182
+ cn: "${cli.dependencies.cn}"
107
183
  lucide-react: "${cli.dependencies["lucide-react"]}"
184
+ oxfmt: "${cli.dependencies.oxfmt}"
185
+ oxlint: "${cli.dependencies.oxlint}"
186
+ oxlint-tsgolint: "${cli.dependencies["oxlint-tsgolint"]}"
108
187
  react: "${cli.peerDependencies.react}"
109
188
  react-aria-components: "${cli.dependencies["react-aria-components"]}"
110
189
  react-dom: "${cli.peerDependencies["react-dom"]}"
111
190
  shadcn: "${cli.dependencies.shadcn}"
112
191
  streamdown: "${cli.dependencies.streamdown}"
113
- tailwind-merge: "${cli.dependencies["tailwind-merge"]}"
114
192
  tailwindcss: "${cli.dependencies.tailwindcss}"
115
193
  tw-animate-css: "${cli.dependencies["tw-animate-css"]}"
116
194
  typescript: "${cli.peerDependencies.typescript}"
@@ -122,14 +200,94 @@ allowBuilds:
122
200
  workerd: true
123
201
  minimumReleaseAge: 4320
124
202
  minimumReleaseAgeExclude:
125
- - "${cli.name}"
203
+ - "@hitch42/*"
204
+ `;
205
+ }
206
+ const OXLINT_CONFIG = `{
207
+ "$schema": "./node_modules/oxlint/configuration_schema.json",
208
+ "plugins": ["eslint", "typescript", "unicorn", "import", "node"],
209
+ "options": { "typeAware": true, "typeCheck": true },
210
+ "env": { "node": true },
211
+ "overrides": [
212
+ {
213
+ "files": ["applets/*/src/client/**"],
214
+ "plugins": ["eslint", "typescript", "unicorn", "import", "react", "react-perf"],
215
+ "env": { "node": false, "browser": true },
216
+ "rules": {
217
+ "react/capitalized-calls": "error",
218
+ "react/error-boundaries": "error",
219
+ "react/exhaustive-effect-dependencies": "error",
220
+ "react/globals": "error",
221
+ "react/hooks": "error",
222
+ "react/immutability": "error",
223
+ "react/incompatible-library": "error",
224
+ "react/invariant": "error",
225
+ "react/memo-dependencies": "error",
226
+ "react/no-deriving-state-in-effects": "error",
227
+ "react/preserve-manual-memoization": "error",
228
+ "react/purity": "error",
229
+ "react/refs": "error",
230
+ "react/rule-suppression": "error",
231
+ "react/set-state-in-effect": "error",
232
+ "react/set-state-in-render": "error",
233
+ "react/static-components": "error",
234
+ "react/syntax": "error",
235
+ "react/todo": "error",
236
+ "react/unsupported-syntax": "error",
237
+ "react/use-memo": "error",
238
+ "react/void-use-memo": "error"
239
+ }
240
+ },
241
+ {
242
+ "files": ["applets/*/test/**"],
243
+ "plugins": ["eslint", "typescript", "unicorn", "import", "vitest"],
244
+ "rules": {
245
+ "vitest/expect-expect": [
246
+ "warn",
247
+ { "assertFunctionNames": ["expect", "expect*", "assert", "assert.*", "assert*"] }
248
+ ]
249
+ }
250
+ }
251
+ ]
252
+ }
253
+ `;
254
+ async function oxfmtConfig(root) {
255
+ const appletsRoot = resolve(root, "applets");
256
+ const overrides = (existsSync(appletsRoot) ? await readdir(appletsRoot) : []).filter((code) => existsSync(resolve(appletsRoot, code, "src/client/styles/globals.css"))).sort().map((code) => `
257
+ {
258
+ "files": ["applets/${code}/**"],
259
+ "options": {
260
+ "sortTailwindcss": {
261
+ "stylesheet": "applets/${code}/src/client/styles/globals.css",
262
+ "functions": ["cn", "cva"]
263
+ }
264
+ }
265
+ }`);
266
+ return `{
267
+ "$schema": "./node_modules/oxfmt/configuration_schema.json",
268
+ "sortImports": true,
269
+ "overrides": [${overrides.join(",")}${overrides.length > 0 ? "\n " : ""}]
270
+ }
126
271
  `;
127
272
  }
128
273
  const GITIGNORE_START = "# BEGIN Hitch generated files";
129
274
  const GITIGNORE_END = "# END Hitch generated files";
275
+ const SKILLS = [
276
+ "hitch-applets",
277
+ "hitch-cli",
278
+ "hitch-data",
279
+ "hitch-theory",
280
+ "react-best-practices",
281
+ "tanstack-query",
282
+ "tanstack-router",
283
+ "web-design-guidelines"
284
+ ];
130
285
  const GITIGNORE = `${GITIGNORE_START}
131
- /.agents/skills/hitch-applets/
286
+ ${SKILLS.map((skill) => `/.agents/skills/${skill}/`).join("\n")}
287
+ ${SKILLS.map((skill) => `/.claude/skills/${skill}`).join("\n")}
132
288
  /.node-version
289
+ /.oxfmtrc.json
290
+ /.oxlintrc.json
133
291
  /AGENTS.md
134
292
  /CLAUDE.md
135
293
  /package.json
@@ -169,22 +327,39 @@ async function writeWorkspaceSupport(root, config, cli) {
169
327
  const resolvedCli = cli ?? await loadCliManifest();
170
328
  if (resolvedCli === void 0) throw new Error("The CLI package manifest is not published.");
171
329
  assertWorkspaceCli(config, resolvedCli);
172
- const skillTarget = resolve(root, ".agents/skills/hitch-applets");
330
+ await ensureAgentConfigs(root, config.org);
331
+ const deployWorkflowTarget = resolve(root, ".github/workflows/hitch.yml");
173
332
  const agents = await readFile(new URL("../scaffold/AGENTS.md", import.meta.url), "utf8");
174
- await Promise.all([mkdir(resolve(root, ".agents/skills"), { recursive: true }), rm(skillTarget, {
175
- force: true,
176
- recursive: true
177
- })]);
178
333
  await Promise.all([
179
- cp(new URL("../scaffold/.agents/skills/hitch-applets", import.meta.url), skillTarget, { recursive: true }),
334
+ mkdir(resolve(root, ".agents/skills"), { recursive: true }),
335
+ mkdir(resolve(root, ".claude/skills"), { recursive: true }),
336
+ config.githubWorkflow === false ? void 0 : mkdir(resolve(root, ".github/workflows"), { recursive: true }),
337
+ ...SKILLS.map((skill) => rm(resolve(root, ".agents/skills", skill), {
338
+ force: true,
339
+ recursive: true
340
+ }))
341
+ ]);
342
+ await Promise.all([
343
+ ...SKILLS.map((skill) => cp(new URL(`../scaffold/.agents/skills/${skill}`, import.meta.url), resolve(root, ".agents/skills", skill), { recursive: true })),
180
344
  writeFile(resolve(root, "package.json"), `${JSON.stringify(workspacePackage(config.org), null, 2)}\n`),
181
345
  writeFile(resolve(root, "pnpm-workspace.yaml"), workspaceFile(resolvedCli)),
346
+ config.githubWorkflow === false || existsSync(deployWorkflowTarget) ? void 0 : cp(new URL("../scaffold/.github/workflows/hitch.yml", import.meta.url), deployWorkflowTarget),
182
347
  writeFile(resolve(root, ".node-version"), "24\n"),
348
+ writeFile(resolve(root, ".oxlintrc.json"), OXLINT_CONFIG),
349
+ oxfmtConfig(root).then((config) => writeFile(resolve(root, ".oxfmtrc.json"), config)),
183
350
  writeGitignore(root),
184
351
  writeFile(resolve(root, "AGENTS.md"), agents)
185
352
  ]);
186
353
  await rm(resolve(root, "CLAUDE.md"), { force: true });
187
354
  await symlink("AGENTS.md", resolve(root, "CLAUDE.md"));
355
+ await Promise.all(SKILLS.map(async (skill) => {
356
+ const target = resolve(root, ".claude/skills", skill);
357
+ await rm(target, { force: true });
358
+ await symlink(`../../.agents/skills/${skill}`, target, "dir");
359
+ }));
360
+ }
361
+ function sortedByName(packages) {
362
+ return Object.fromEntries(Object.entries(packages).sort(([a], [b]) => a < b ? -1 : 1));
188
363
  }
189
364
  function appletPackage(definition, options) {
190
365
  return {
@@ -197,14 +372,18 @@ function appletPackage(definition, options) {
197
372
  generate: "applet generate",
198
373
  deploy: "applet deploy",
199
374
  test: "vitest run",
200
- typecheck: "tsc --noEmit"
375
+ typecheck: "tsc --noEmit",
376
+ lint: "oxlint",
377
+ fmt: "oxfmt",
378
+ check: "oxfmt --check && oxlint"
201
379
  },
202
- dependencies: {
380
+ dependencies: sortedByName({
203
381
  "@hitch42/applet": "catalog:",
204
382
  "@orpc/contract": "catalog:",
205
383
  zod: "catalog:",
206
384
  ...options.hasServer ? { "@orpc/server": "catalog:" } : {},
207
385
  ...options.hasClient ? {
386
+ "@fontsource-variable/geist-mono": "catalog:",
208
387
  "@fontsource-variable/inter": "catalog:",
209
388
  "@tanstack/react-query": "catalog:",
210
389
  "@tanstack/react-router": "catalog:",
@@ -217,19 +396,18 @@ function appletPackage(definition, options) {
217
396
  "@tiptap/react": "catalog:",
218
397
  "@tiptap/starter-kit": "catalog:",
219
398
  "class-variance-authority": "catalog:",
220
- clsx: "catalog:",
399
+ cn: "catalog:",
221
400
  "lucide-react": "catalog:",
222
401
  react: "catalog:",
223
402
  "react-aria-components": "catalog:",
224
403
  "react-dom": "catalog:",
225
404
  shadcn: "catalog:",
226
405
  streamdown: "catalog:",
227
- "tailwind-merge": "catalog:",
228
406
  "tw-animate-css": "catalog:"
229
407
  } : {},
230
408
  ...definition.dependencies
231
- },
232
- devDependencies: {
409
+ }),
410
+ devDependencies: sortedByName({
233
411
  "@types/node": "catalog:",
234
412
  typescript: "catalog:",
235
413
  vite: "catalog:",
@@ -241,9 +419,21 @@ function appletPackage(definition, options) {
241
419
  tailwindcss: "catalog:"
242
420
  } : {},
243
421
  ...definition.devDependencies
244
- }
422
+ })
245
423
  };
246
424
  }
425
+ const LEGACY_CN_HELPER = `import { clsx, type ClassValue } from "clsx";
426
+ import { twMerge } from "tailwind-merge";
427
+
428
+ export function cn(...inputs: ClassValue[]) {
429
+ return twMerge(clsx(inputs));
430
+ }
431
+ `;
432
+ async function replaceLegacyCnHelper(root) {
433
+ const path = resolve(root, "src/client/lib/utils.ts");
434
+ if (!existsSync(path) || await readFile(path, "utf8") !== LEGACY_CN_HELPER) return;
435
+ await cp(new URL("../scaffold/applet/src/client/lib/utils.ts", import.meta.url), path);
436
+ }
247
437
  async function writeAppletSupport(root, definition) {
248
438
  const hasClient = existsSync(resolve(root, "src/client/routes"));
249
439
  const hasAuthorRoot = existsSync(resolve(root, "src/client/routes/__root.tsx"));
@@ -252,6 +442,7 @@ async function writeAppletSupport(root, definition) {
252
442
  if (!hasServer && (definition.schedules?.length ?? 0) > 0) throw new Error("An applet with schedules must have src/server/main.ts.");
253
443
  await Promise.all(hasClient ? [] : [rm(resolve(root, "index.html"), { force: true }), rm(resolve(root, "components.json"), { force: true })]);
254
444
  await Promise.all([
445
+ replaceLegacyCnHelper(root),
255
446
  writeFile(resolve(root, "package.json"), `${JSON.stringify(appletPackage(definition, {
256
447
  hasClient,
257
448
  hasServer
@@ -323,24 +514,26 @@ export default defineConfig({
323
514
  "./.hitch/*.ts",
324
515
  "./.hitch/*.tsx",
325
516
  "./src/**/*.ts",
326
- "./src/**/*.tsx"
517
+ "./src/**/*.tsx",
518
+ "./test/**/*.ts",
519
+ "./test/**/*.tsx"
327
520
  ]
328
521
  }
329
522
  `),
330
523
  hasClient ? writeFile(resolve(root, "components.json"), await readFile(new URL("../scaffold/applet/components.json", import.meta.url), "utf8")) : void 0
331
524
  ]);
332
525
  }
333
- async function prepareAppletProject(appletRoot = process.cwd()) {
334
- const definition = await loadAppletSourceDefinition(appletRoot);
335
- const workspaceRoot = dirname(dirname(resolve(appletRoot)));
526
+ async function prepareAppletProjects(workspaceRoot, appletRoots) {
527
+ const definitions = await Promise.all(appletRoots.map((root) => loadAppletSourceDefinition(root)));
336
528
  const workspace = readWorkspaceConfig(workspaceRoot);
337
- if (workspace === void 0) throw new Error(`No Hitch workspace found for ${appletRoot}.`);
529
+ if (workspace === void 0) throw new Error(`No Hitch workspace found at ${workspaceRoot}.`);
338
530
  const cli = await loadCliManifest({ allowDevelopment: true });
339
- await Promise.all([cli === void 0 ? void 0 : writeWorkspaceSupport(workspaceRoot, workspace, cli), writeAppletSupport(appletRoot, definition)]);
340
- return {
341
- definition,
342
- workspaceRoot
343
- };
531
+ await Promise.all([cli === void 0 ? void 0 : writeWorkspaceSupport(workspaceRoot, workspace, cli), ...appletRoots.map((root, index) => writeAppletSupport(root, definitions[index]))]);
532
+ }
533
+ async function prepareAppletProject(appletRoot = process.cwd()) {
534
+ const workspaceRoot = dirname(dirname(resolve(appletRoot)));
535
+ await prepareAppletProjects(workspaceRoot, [appletRoot]);
536
+ return workspaceRoot;
344
537
  }
345
538
  //#endregion
346
- export { writeWorkspaceSupport as a, writeAppletSupport as i, loadCliManifest as n, prepareAppletProject as r, assertWorkspaceCli as t };
539
+ export { writeAppletSupport as a, prepareAppletProjects as i, loadCliManifest as n, writeWorkspaceSupport as o, prepareAppletProject as r, assertWorkspaceCli as t };
@@ -0,0 +1,29 @@
1
+ import { Writable } from "node:stream";
2
+ import { createInterface } from "node:readline";
3
+ //#region src/prompt.ts
4
+ function question(prompt, hidden = false) {
5
+ return new Promise((resolveAnswer, rejectAnswer) => {
6
+ let muted = false;
7
+ const output = hidden ? new Writable({ write(chunk, encoding, callback) {
8
+ if (!muted) process.stdout.write(chunk, encoding);
9
+ callback();
10
+ } }) : process.stdout;
11
+ const readline = createInterface({
12
+ input: process.stdin,
13
+ output,
14
+ terminal: true
15
+ });
16
+ readline.once("error", rejectAnswer);
17
+ if (hidden) {
18
+ process.stdout.write(prompt);
19
+ muted = true;
20
+ }
21
+ readline.question(hidden ? "" : prompt, (answer) => {
22
+ readline.close();
23
+ if (hidden) process.stdout.write("\n");
24
+ resolveAnswer(answer);
25
+ });
26
+ });
27
+ }
28
+ //#endregion
29
+ export { question as t };
@@ -0,0 +1,82 @@
1
+ //#region src/internal/query-cache.ts
2
+ const STORE = "clients";
3
+ const TIMESTAMP_INDEX = "timestamp";
4
+ const TAB_KEY = "hitch:query-tab";
5
+ const SAVE_INTERVAL = 1e3;
6
+ function openQueryCacheDatabase() {
7
+ return new Promise((resolve, reject) => {
8
+ const open = indexedDB.open("hitch-query-cache", 1);
9
+ open.onupgradeneeded = () => {
10
+ open.result.createObjectStore("clients").createIndex("timestamp", "timestamp");
11
+ };
12
+ open.onblocked = () => reject(/* @__PURE__ */ new Error("The query cache is open in an older tab."));
13
+ open.onsuccess = () => {
14
+ open.result.onversionchange = () => open.result.close();
15
+ resolve(open.result);
16
+ };
17
+ open.onerror = () => reject(open.error);
18
+ });
19
+ }
20
+ let database;
21
+ function openCacheDatabase() {
22
+ database ??= window.__hitchCacheDatabase ?? openQueryCacheDatabase();
23
+ return database;
24
+ }
25
+ async function inStore(mode, run) {
26
+ const transaction = (await openCacheDatabase()).transaction(STORE, mode);
27
+ const request = run(transaction.objectStore(STORE));
28
+ return new Promise((resolve, reject) => {
29
+ transaction.oncomplete = () => resolve(request.result);
30
+ transaction.onabort = () => reject(transaction.error ?? request.error);
31
+ });
32
+ }
33
+ function cacheTabId() {
34
+ const existing = sessionStorage.getItem(TAB_KEY);
35
+ if (existing) return existing;
36
+ const id = crypto.randomUUID();
37
+ sessionStorage.setItem(TAB_KEY, id);
38
+ return id;
39
+ }
40
+ function indexedDbPersister(key) {
41
+ let pending;
42
+ let throttled = false;
43
+ const save = (client) => inStore("readwrite", (store) => store.put(client, key)).then(() => void 0, (error) => console.error("Could not persist the applet query cache.", error));
44
+ const release = () => {
45
+ if (!pending) {
46
+ throttled = false;
47
+ return;
48
+ }
49
+ save(pending);
50
+ pending = void 0;
51
+ setTimeout(release, SAVE_INTERVAL);
52
+ };
53
+ return {
54
+ persistClient: (client) => {
55
+ if (throttled) {
56
+ pending = client;
57
+ return;
58
+ }
59
+ throttled = true;
60
+ setTimeout(release, SAVE_INTERVAL);
61
+ return save(client);
62
+ },
63
+ restoreClient: () => inStore("readonly", (store) => store.get(key)),
64
+ removeClient: () => inStore("readwrite", (store) => store.delete(key))
65
+ };
66
+ }
67
+ function sweepExpiredQueryCaches(maxAge) {
68
+ return inStore("readwrite", (store) => {
69
+ const cursor = store.index(TIMESTAMP_INDEX).openKeyCursor(IDBKeyRange.upperBound(Date.now() - maxAge));
70
+ cursor.onsuccess = () => {
71
+ if (!cursor.result) return;
72
+ store.delete(cursor.result.primaryKey);
73
+ cursor.result.continue();
74
+ };
75
+ return cursor;
76
+ });
77
+ }
78
+ function clearAppletQueryCaches(appletCode) {
79
+ return inStore("readwrite", (store) => store.delete(IDBKeyRange.bound(`${appletCode}:`, `${appletCode}:\uffff`)));
80
+ }
81
+ //#endregion
82
+ export { openQueryCacheDatabase as a, openCacheDatabase as i, clearAppletQueryCaches as n, sweepExpiredQueryCaches as o, indexedDbPersister as r, cacheTabId as t };
package/dist/react.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as UploadedHitchFile } from "./upload-YbRKEqR6.js";
1
+ import { a as UploadedHitchFile } from "./upload-DKZzz5kW.js";
2
2
  import { ReactElement } from "react";
3
3
  import "@tiptap/core";
4
4
  //#region src/react/markdown.d.ts
@@ -29,9 +29,10 @@ type MarkdownEditorProps = {
29
29
  minLength?: number;
30
30
  maxLength?: number;
31
31
  disabled?: boolean;
32
+ autoFocus?: boolean;
32
33
  className?: string;
33
34
  onUploadError?: (error: unknown, file: File) => void;
34
35
  };
35
- declare function MarkdownEditor({ value, onChange, files, id, placeholder, required, minLength, maxLength, disabled, className, onUploadError }: MarkdownEditorProps): ReactElement;
36
+ declare function MarkdownEditor({ value, onChange, files, id, placeholder, required, minLength, maxLength, disabled, autoFocus, className, onUploadError }: MarkdownEditorProps): ReactElement;
36
37
  //#endregion
37
38
  export { Markdown, MarkdownEditor, type MarkdownEditorFiles, type MarkdownEditorProps, type MarkdownFiles, type MarkdownProps };