@hitch42/applet 0.1.1-beta.20 → 0.1.1-beta.21

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 (94) hide show
  1. package/dist/_internal/client.d.ts +0 -2
  2. package/dist/_internal/client.js +3 -5
  3. package/dist/_internal/log-context.d.ts +0 -2
  4. package/dist/_internal/log-context.js +1 -2
  5. package/dist/_internal/server.d.ts +2 -10
  6. package/dist/_internal/server.js +9 -14
  7. package/dist/applet.js +64 -23
  8. package/dist/auth-DuMRqSGe.js +49 -0
  9. package/dist/{batch-_ZjAg-Kk.js → batch-CiLZ177G.js} +3 -4
  10. package/dist/build-C7hi2yg4.js +1 -0
  11. package/dist/{build-D47vK5aa.js → build-FAQSHJgm.js} +4 -3
  12. package/dist/{ci-BTFTCBgy.js → ci-oWlUJKm9.js} +5 -6
  13. package/dist/client/hitch/client.d.ts +1 -1
  14. package/dist/client/hitch/client.js +1 -2
  15. package/dist/client/hitch/phone.d.ts +1 -1
  16. package/dist/client/hitch/phone.js +1 -2
  17. package/dist/client/hitch.d.ts +2 -2
  18. package/dist/client/hitch.js +2 -2
  19. package/dist/client/react/markdown-editor.d.ts +1 -1
  20. package/dist/client/react/markdown-editor.js +1 -2
  21. package/dist/client/react/markdown.d.ts +1 -1
  22. package/dist/client/react/markdown.js +1 -2
  23. package/dist/client/react.d.ts +2 -2
  24. package/dist/client/react.js +2 -2
  25. package/dist/client.d.ts +2 -4
  26. package/dist/client.js +3 -5
  27. package/dist/{contract-CJv-n1l3.d.ts → contract-CUc0B2rl.d.ts} +1 -3
  28. package/dist/{contract-BeKz1Qcs.js → contract-D9LCNGjD.js} +1 -2
  29. package/dist/{create-C2UrZYSK.d.ts → create-BJqLT8Uq.d.ts} +0 -4
  30. package/dist/{deploy-BbqyK5Ik.js → deploy-BM55ZoSp.js} +160 -152
  31. package/dist/{device-BgIfytaR.js → device-CZWWckCq.js} +54 -34
  32. package/dist/{email-protocol-B9u_dh2p.d.ts → email-protocol-CEqzASSx.d.ts} +0 -6
  33. package/dist/{generate-BLD0DoCk.js → generate-48pqFh5M.js} +31 -37
  34. package/dist/generate-BYK4aNud.js +1 -0
  35. package/dist/generated-agents-BUnJ0FQA.js +215 -0
  36. package/dist/git-credential-CU7-Erzs.js +24 -0
  37. package/dist/git-deploy-C12nMNB6.js +290 -0
  38. package/dist/git-deploy-CNz6mxiF.js +1 -0
  39. package/dist/git-migration-CIq-sN61.js +629 -0
  40. package/dist/git-safety-Ck3X7jvA.js +13 -0
  41. package/dist/{headers-CeRX-Xji.js → headers-BcEMIVCo.js} +1 -2
  42. package/dist/{hitch-client-DtyTZzP5.d.ts → hitch-client-D33JOEOi.d.ts} +5 -7
  43. package/dist/{hitch-client-Cw-WZ_8v.js → hitch-client-Dph_kzDd.js} +5 -7
  44. package/dist/{hitch-file-url-BPKj9zVG.js → hitch-file-url--AMjDOzP.js} +1 -2
  45. package/dist/index.d.ts +8 -15
  46. package/dist/index.js +32 -37
  47. package/dist/{init-BKUBf6i9.js → init-Bb6WT8UB.js} +70 -18
  48. package/dist/{lazy-client-CwIzYAoE.js → lazy-client--QCL0wiu.js} +1 -2
  49. package/dist/{load-config-DGALUExv.js → load-config-Cffvj-aM.js} +24 -26
  50. package/dist/{log-context-DWznGjfz.js → log-context-BepwdjrR.js} +1 -2
  51. package/dist/login-BWZKo7Ui.js +21 -0
  52. package/dist/{logs-Cv5z1e2w.js → logs-glCVHI-8.js} +6 -6
  53. package/dist/{manifest-BBHD_EY9.d.ts → manifest-CpghlaJc.d.ts} +6 -7
  54. package/dist/manifest-patterns-BfxqImlp.js +4 -0
  55. package/dist/{markdown-CwlqzBtP.js → markdown-BA_XzFxq.js} +2 -3
  56. package/dist/{markdown-DSHOQIOb.d.ts → markdown-BXt65dDo.d.ts} +1 -3
  57. package/dist/{markdown-editor-BmEaBzd7.d.ts → markdown-editor-CB_nWLzj.d.ts} +1 -5
  58. package/dist/{markdown-editor-C5mLHGqu.js → markdown-editor-CaUuphfc.js} +3 -5
  59. package/dist/parent-D52Kxp8U.js +1 -0
  60. package/dist/parent-Zx8Eg1Ki.js +75 -0
  61. package/dist/{project-CrxdZR0B.js → project-DZGk765E.js} +63 -54
  62. package/dist/{prompt-ChS-grYO.js → prompt-CW98R-Un.js} +1 -2
  63. package/dist/{query-cache-CXmAyLv3.js → query-cache-DQJy45RT.js} +1 -2
  64. package/dist/{query-utils-zz9pVjgp.d.ts → query-utils-okxIoKM3.d.ts} +0 -2
  65. package/dist/{schedules-Dajgni_z.js → schedules-CSUb84e2.js} +5 -5
  66. package/dist/server.d.ts +5 -13
  67. package/dist/server.js +17 -20
  68. package/dist/source-hash-BbvtRaus.js +107 -0
  69. package/dist/store-E5NhITHl.js +448 -0
  70. package/dist/{upload-D_kkmne_.d.ts → upload-DXZyjZSS.d.ts} +6 -10
  71. package/dist/{upload-DRbVhuDm.js → upload-DtMavo8Q.js} +4 -6
  72. package/dist/{use-phone-ug4B5gQp.js → use-phone-CB_idmrz.js} +9 -13
  73. package/dist/{use-phone-M7c_HsB7.d.ts → use-phone-DBAkasPq.d.ts} +0 -4
  74. package/dist/{variables-B-CLu8cY.js → variables-CgZstC7I.js} +7 -8
  75. package/dist/vite.d.ts +1 -3
  76. package/dist/vite.js +41 -50
  77. package/dist/{workflow-DurM6Fwx.d.ts → workflow-BnBrJIzu.d.ts} +0 -2
  78. package/dist/{workflow-engine-BOTzURKM.js → workflow-engine-CyyaVENo.js} +2 -4
  79. package/dist/{workflow-CTo2kZF1.js → workflow-l2SlVePB.js} +2 -4
  80. package/dist/workspace-CtIKSgMD.js +76 -0
  81. package/package.json +6 -5
  82. package/scaffold/.agents/skills/hitch-applets/SKILL.md +27 -9
  83. package/scaffold/.agents/skills/hitch-applets/references/files.md +2 -2
  84. package/scaffold/.agents/skills/hitch-applets/references/manifest.md +8 -6
  85. package/scaffold/.agents/skills/hitch-applets/references/performance.md +2 -2
  86. package/scaffold/.agents/skills/hitch-applets/references/records.md +8 -8
  87. package/scaffold/.agents/skills/hitch-cli/SKILL.md +52 -43
  88. package/scaffold/AGENTS.md +6 -0
  89. package/dist/auth-D3CrCtZq.js +0 -21
  90. package/dist/build-JtbY8q2p.js +0 -2
  91. package/dist/generate-COCRy1Bs.js +0 -2
  92. package/dist/login-CceGvlMi.js +0 -14
  93. package/dist/store-B8N_8JIN.js +0 -196
  94. package/dist/workspace-8yqXsvce.js +0 -31
@@ -1,8 +1,8 @@
1
- import { n as cachedDownloadUrl, r as invalidateDownloadUrl, t as HITCH_FILE_PREFIX } from "./hitch-file-url-BPKj9zVG.js";
1
+ import { n as cachedDownloadUrl, r as invalidateDownloadUrl, t as HITCH_FILE_PREFIX } from "./hitch-file-url--AMjDOzP.js";
2
2
  import { useEffect, useMemo, useState } from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  import { Streamdown, defaultRehypePlugins, defaultUrlTransform } from "streamdown";
5
- //#region src/react/markdown.tsx
5
+ // src/react/markdown.tsx
6
6
  function withHitchFileProtocol() {
7
7
  const sanitize = defaultRehypePlugins.sanitize;
8
8
  if (!Array.isArray(sanitize)) throw new Error("streamdown's default sanitize plugin is no longer [plugin, schema].");
@@ -84,5 +84,4 @@ function Markdown({ children, files, className }) {
84
84
  children
85
85
  });
86
86
  }
87
- //#endregion
88
87
  export { Markdown as t };
@@ -1,6 +1,5 @@
1
- import { a as UploadedHitchFile } from "./upload-D_kkmne_.js";
1
+ import { a as UploadedHitchFile } from "./upload-DXZyjZSS.js";
2
2
  import { ReactElement } from "react";
3
- //#region src/react/markdown.d.ts
4
3
  type MarkdownFiles = {
5
4
  download: (id: string) => Promise<Pick<UploadedHitchFile, "downloadUrl">>;
6
5
  };
@@ -10,5 +9,4 @@ type MarkdownProps = {
10
9
  className?: string;
11
10
  };
12
11
  declare function Markdown({ children, files, className }: MarkdownProps): ReactElement;
13
- //#endregion
14
12
  export { MarkdownFiles as n, MarkdownProps as r, Markdown as t };
@@ -1,13 +1,10 @@
1
- import { a as UploadedHitchFile } from "./upload-D_kkmne_.js";
1
+ import { a as UploadedHitchFile } from "./upload-DXZyjZSS.js";
2
2
  import { ReactElement } from "react";
3
3
  import "@tiptap/core";
4
- //#region src/react/markdown-editor-extensions.d.ts
5
4
  type MarkdownEditorFiles = {
6
5
  upload: (file: File) => Promise<Pick<UploadedHitchFile, "id" | "downloadUrl">>;
7
6
  download: (id: string) => Promise<Pick<UploadedHitchFile, "downloadUrl">>;
8
7
  };
9
- //#endregion
10
- //#region src/react/markdown-editor.d.ts
11
8
  type MarkdownEditorProps = {
12
9
  value: string;
13
10
  onChange: (value: string) => void;
@@ -23,5 +20,4 @@ type MarkdownEditorProps = {
23
20
  onUploadError?: (error: unknown, file: File) => void;
24
21
  };
25
22
  declare function MarkdownEditor({ value, onChange, files, id, placeholder, required, minLength, maxLength, disabled, autoFocus, className, onUploadError }: MarkdownEditorProps): ReactElement;
26
- //#endregion
27
23
  export { MarkdownEditorProps as n, MarkdownEditorFiles as r, MarkdownEditor as t };
@@ -1,4 +1,4 @@
1
- import { i as seedDownloadUrl, n as cachedDownloadUrl, r as invalidateDownloadUrl, t as HITCH_FILE_PREFIX } from "./hitch-file-url-BPKj9zVG.js";
1
+ import { i as seedDownloadUrl, n as cachedDownloadUrl, r as invalidateDownloadUrl, t as HITCH_FILE_PREFIX } from "./hitch-file-url--AMjDOzP.js";
2
2
  import { useEffect, useMemo, useRef, useState } from "react";
3
3
  import { BetweenHorizontalEnd, BetweenVerticalEnd, Bold, Code, Heading, Italic, Link, List, ListMinus, ListOrdered, ListTodo, Quote, Strikethrough, Table, Trash2, X } from "lucide-react";
4
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -14,7 +14,7 @@ import { Table as Table$1, TableCell, TableHeader, TableRow, renderTableToMarkdo
14
14
  import { Placeholder } from "@tiptap/extensions";
15
15
  import { Markdown } from "@tiptap/markdown";
16
16
  import StarterKit from "@tiptap/starter-kit";
17
- //#region src/react/markdown-editor-extensions.tsx
17
+ // src/react/markdown-editor-extensions.tsx
18
18
  function sanitizeAltText(text) {
19
19
  return text.replaceAll(/[[\]()\\]/g, "").replaceAll(/\s+/g, " ");
20
20
  }
@@ -109,8 +109,7 @@ function markdownEditorExtensions(files, placeholder = "") {
109
109
  }));
110
110
  return extensions;
111
111
  }
112
- //#endregion
113
- //#region src/react/markdown-editor.tsx
112
+ // src/react/markdown-editor.tsx
114
113
  const buttonClassName = "inline-flex size-7 shrink-0 items-center justify-center rounded-2xl border border-transparent text-muted-foreground outline-none transition-all select-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0";
115
114
  const editorClassName = "min-h-32 w-full px-2.5 py-2 text-base md:text-sm outline-none whitespace-pre-wrap space-y-4 [&>*:first-child]:mt-0 [&>*:last-child]:mb-0 [&_h1]:mt-6 [&_h1]:mb-2 [&_h1]:font-semibold [&_h1]:text-3xl [&_h2]:mt-6 [&_h2]:mb-2 [&_h2]:font-semibold [&_h2]:text-2xl [&_h3]:mt-6 [&_h3]:mb-2 [&_h3]:font-semibold [&_h3]:text-xl [&_h4]:mt-6 [&_h4]:mb-2 [&_h4]:font-semibold [&_h4]:text-lg [&_h5]:mt-6 [&_h5]:mb-2 [&_h5]:font-semibold [&_h5]:text-base [&_h6]:mt-6 [&_h6]:mb-2 [&_h6]:font-semibold [&_h6]:text-sm [&_ul]:list-disc [&_ul]:pl-5 [&_ol]:list-decimal [&_ol]:pl-5 [&_blockquote]:my-4 [&_blockquote]:border-l-4 [&_blockquote]:border-muted-foreground/30 [&_blockquote]:pl-4 [&_blockquote]:text-muted-foreground [&_blockquote]:italic [&_code]:rounded [&_code]:bg-muted [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-sm [&_pre]:overflow-x-auto [&_pre]:rounded-md [&_pre]:border [&_pre]:border-border [&_pre]:bg-background [&_pre]:p-4 [&_pre]:text-sm [&_pre_code]:bg-transparent [&_pre_code]:p-0 [&_a]:font-medium [&_a]:text-primary [&_a]:underline [&_a]:wrap-anywhere [&_hr]:my-4 [&_hr]:border-border [&_table]:my-4 [&_table]:w-full [&_table]:border-collapse [&_th]:border [&_th]:border-border [&_th]:px-4 [&_th]:py-2 [&_th]:text-left [&_th]:font-semibold [&_th]:text-sm [&_td]:border [&_td]:border-border [&_td]:px-4 [&_td]:py-2 [&_td]:text-sm [&_ul[data-type=taskList]]:list-none [&_ul[data-type=taskList]]:pl-0 [&_li[data-type=taskItem]]:flex [&_li[data-type=taskItem]]:items-start [&_li[data-type=taskItem]]:gap-2 [&_li[data-type=taskItem]>div]:flex-1 [&_p.is-editor-empty:first-child]:before:content-[attr(data-placeholder)] [&_p.is-editor-empty:first-child]:before:float-left [&_p.is-editor-empty:first-child]:before:h-0 [&_p.is-editor-empty:first-child]:before:pointer-events-none [&_p.is-editor-empty:first-child]:before:text-muted-foreground";
116
115
  function findImage(view, src) {
@@ -424,5 +423,4 @@ function MarkdownEditor({ value, onChange, files, id, placeholder, required, min
424
423
  ]
425
424
  });
426
425
  }
427
- //#endregion
428
426
  export { MarkdownEditor as t };
@@ -0,0 +1 @@
1
+ export { i as runParent } from "./parent-Zx8Eg1Ki.js";
@@ -0,0 +1,75 @@
1
+ import { r as writeGeneratedAgents } from "./generated-agents-BUnJ0FQA.js";
2
+ import { a as findWorkspaceRoot, o as isRootLayout, r as findParentRoot } from "./workspace-CtIKSgMD.js";
3
+ import { n as gitEnvironment } from "./source-hash-BbvtRaus.js";
4
+ import { existsSync } from "node:fs";
5
+ import { readdir, writeFile } from "node:fs/promises";
6
+ import { dirname, resolve } from "node:path";
7
+ import { spawn } from "node:child_process";
8
+ // src/git-local.ts
9
+ async function gitLocal(root, args, input, environment) {
10
+ return new Promise((resolveCommand, reject) => {
11
+ const child = spawn("git", args, {
12
+ cwd: root,
13
+ env: {
14
+ ...gitEnvironment(),
15
+ ...environment,
16
+ GIT_TERMINAL_PROMPT: "0"
17
+ },
18
+ stdio: [
19
+ "pipe",
20
+ "pipe",
21
+ "pipe"
22
+ ]
23
+ });
24
+ const stdout = [];
25
+ const stderr = [];
26
+ child.stdout.on("data", (chunk) => stdout.push(chunk));
27
+ child.stderr.on("data", (chunk) => stderr.push(chunk));
28
+ child.once("error", reject);
29
+ child.stdin.once("error", reject);
30
+ child.once("close", (code) => {
31
+ if (code === 0) resolveCommand(Buffer.concat(stdout));
32
+ else reject(/* @__PURE__ */ new Error(`git ${args[0]} failed: ${Buffer.concat(stderr).toString("utf8").trim()}`));
33
+ });
34
+ child.stdin.end(input);
35
+ });
36
+ }
37
+ // src/parent.ts
38
+ var ParentError = class extends Error {};
39
+ async function childApplets(root) {
40
+ return (await readdir(root, { withFileTypes: true })).filter((entry) => entry.isDirectory() && isRootLayout(resolve(root, entry.name))).map((entry) => resolve(root, entry.name)).sort();
41
+ }
42
+ function selectParentDeploy(input) {
43
+ return input.dirty || !input.hasMain || input.ahead;
44
+ }
45
+ async function childHasChanges(root) {
46
+ const dirty = (await gitLocal(root, ["status", "--porcelain"])).length > 0;
47
+ const hasMain = (await gitLocal(root, [
48
+ "for-each-ref",
49
+ "--format=%(refname)",
50
+ "refs/remotes/hitch/main"
51
+ ])).length > 0;
52
+ return selectParentDeploy({
53
+ dirty,
54
+ hasMain,
55
+ ahead: hasMain && (await gitLocal(root, [
56
+ "rev-list",
57
+ "HEAD",
58
+ "--not",
59
+ "refs/remotes/hitch/main"
60
+ ])).length > 0
61
+ });
62
+ }
63
+ function assertOutsideRepository(root) {
64
+ if (existsSync(resolve(root, ".git"))) throw new ParentError("A Hitch parent must not be inside a git repo.");
65
+ if (dirname(root) !== root) assertOutsideRepository(dirname(root));
66
+ }
67
+ async function runParent() {
68
+ const root = process.cwd();
69
+ if (findWorkspaceRoot(root) !== void 0 || findParentRoot(root) !== void 0) throw new ParentError("Run applet parent outside an applet or another parent.");
70
+ assertOutsideRepository(resolve(root));
71
+ await writeFile(resolve(root, ".hitchroot"), "", { flag: "wx" });
72
+ await writeGeneratedAgents(root);
73
+ console.log(`Created Hitch parent ${root}. Each child folder holds one applet repo.`);
74
+ }
75
+ export { selectParentDeploy as a, runParent as i, childApplets as n, gitLocal as o, childHasChanges as r, ParentError as t };
@@ -1,12 +1,13 @@
1
- import { a as organizationInstanceUrl, n as DEFAULT_INSTANCE_URL } from "./store-B8N_8JIN.js";
2
- import { n as readWorkspaceConfig } from "./workspace-8yqXsvce.js";
3
- import { a as appletMountPath, n as loadAppletSourceDefinition } from "./load-config-DGALUExv.js";
1
+ import { r as writeGeneratedAgents, t as GENERATED_SKILLS } from "./generated-agents-BUnJ0FQA.js";
2
+ import { l as organizationInstanceUrl, n as DEFAULT_INSTANCE_URL } from "./store-E5NhITHl.js";
3
+ import { a as findWorkspaceRoot, n as findAppletRoot, o as isRootLayout, s as readWorkspaceConfig } from "./workspace-CtIKSgMD.js";
4
+ import { n as loadAppletSourceDefinition, r as appletMountPath } from "./load-config-Cffvj-aM.js";
4
5
  import { z } from "zod";
5
6
  import { existsSync } from "node:fs";
6
- import { cp, mkdir, readFile, readdir, rm, symlink, writeFile } from "node:fs/promises";
7
+ import { cp, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
7
8
  import { dirname, relative, resolve } from "node:path";
8
9
  import { TomlError, parse, stringify } from "smol-toml";
9
- //#region src/agent-support.ts
10
+ // src/agent-support.ts
10
11
  var AgentConfigError = class extends Error {};
11
12
  async function ensureAgentConfigs(root, org) {
12
13
  const servers = {
@@ -67,8 +68,7 @@ async function ensureAgentConfigs(root, org) {
67
68
  await mkdir(resolve(root, ".codex"), { recursive: true });
68
69
  await Promise.all(configs.filter((config) => config !== void 0).map(({ path, contents }) => writeFile(path, contents)));
69
70
  }
70
- //#endregion
71
- //#region src/project.ts
71
+ // src/project.ts
72
72
  const PACKAGE_MANAGER = "pnpm@11.18.0+sha512.33d83c77da82f49fba836925c6f1b841181ec3132b670639bd012f7075f5c7cf634c5f870147c19aae7478fac01df09d8892e880454896edd23ee9b33757563c";
73
73
  const cliManifestValueSchema = z.string().min(1, "must be a non-empty string");
74
74
  const cliManifestSchema = z.object({
@@ -136,8 +136,8 @@ async function loadCliManifest(options) {
136
136
  }
137
137
  return cli;
138
138
  }
139
- function assertWorkspaceCli(config, cli) {
140
- const runningCli = `${cli.name}@${cli.version}`;
139
+ function assertWorkspaceCli(config, cli, rootLayout = false) {
140
+ const runningCli = `${rootLayout ? "@hitch42/applet" : cli.name}@${cli.version}`;
141
141
  if (config.sdk !== runningCli) throw new Error(`This workspace requires ${config.sdk}, but this command uses ${runningCli}. Run pnpm dlx ${config.sdk} bootstrap.`);
142
142
  }
143
143
  function workspacePackage(org) {
@@ -262,12 +262,12 @@ const oxlintConfigFile = (publicOverrides = "") => `{
262
262
  async function oxlintConfig(root) {
263
263
  const appletsRoot = resolve(root, "applets");
264
264
  const applets = existsSync(appletsRoot) ? await readdir(appletsRoot, { withFileTypes: true }) : [];
265
- const publicApplets = (await Promise.all(applets.filter((applet) => applet.isDirectory() && existsSync(resolve(appletsRoot, applet.name, "applet.manifest.ts"))).map(async (applet) => {
265
+ const publicApplets = isRootLayout(root) ? (await loadAppletSourceDefinition(root)).public === true ? ["."] : [] : (await Promise.all(applets.filter((applet) => applet.isDirectory() && existsSync(resolve(appletsRoot, applet.name, "applet.manifest.ts"))).map(async (applet) => {
266
266
  return (await loadAppletSourceDefinition(resolve(appletsRoot, applet.name))).public === true ? applet.name : null;
267
267
  }))).filter((code) => code !== null).sort();
268
268
  return oxlintConfigFile(publicApplets.map((name) => `,
269
269
  {
270
- "files": [${JSON.stringify(`applets/${name}/**`)}],
270
+ "files": [${JSON.stringify(name === "." ? "**" : `applets/${name}/**`)}],
271
271
  "rules": {
272
272
  "eslint/no-restricted-imports": [
273
273
  "error",
@@ -304,18 +304,10 @@ async function oxfmtConfig(root) {
304
304
  }
305
305
  const GITIGNORE_START = "# BEGIN Hitch generated files";
306
306
  const GITIGNORE_END = "# END Hitch generated files";
307
- const SKILLS = [
308
- "hitch-applets",
309
- "hitch-cli",
310
- "hitch-data",
311
- "hitch-theory",
312
- "react-best-practices",
313
- "tanstack-query",
314
- "tanstack-router",
315
- "web-design-guidelines"
316
- ];
307
+ const SKILLS = GENERATED_SKILLS;
317
308
  const GITIGNORE = `${GITIGNORE_START}
318
- ${SKILLS.map((skill) => `/.agents/skills/${skill}/`).join("\n")}
309
+ /.agents/.hitch-generated.json
310
+ ${SKILLS.map((skill) => `/.agents/skills/${skill}`).join("\n")}
319
311
  ${SKILLS.map((skill) => `/.claude/skills/${skill}`).join("\n")}
320
312
  /.node-version
321
313
  /.oxfmtrc.json
@@ -337,12 +329,18 @@ ${SKILLS.map((skill) => `/.claude/skills/${skill}`).join("\n")}
337
329
  **/.wrangler/
338
330
  **/dist/
339
331
  **/node_modules/
332
+ .env
333
+ .env.*
334
+ !.env.example
335
+ .dev.vars
336
+ .dev.vars.*
340
337
  ${GITIGNORE_END}
341
338
  `;
342
- async function writeGitignore(root) {
339
+ async function writeGitignore(root, rootLayout = isRootLayout(root)) {
340
+ const generated = rootLayout ? GITIGNORE.replaceAll("/applets/**/", "/").replace("/pnpm-workspace.yaml", "/pnpm-workspace.yaml\n/.hitch-backup/") : GITIGNORE;
343
341
  const path = resolve(root, ".gitignore");
344
342
  if (!existsSync(path)) {
345
- await writeFile(path, `${GITIGNORE}\n# Add custom rules below.\n`);
343
+ await writeFile(path, `${generated}\n# Add custom rules below.\n`);
346
344
  return;
347
345
  }
348
346
  const current = await readFile(path, "utf8");
@@ -350,52 +348,51 @@ async function writeGitignore(root) {
350
348
  const end = current.indexOf(GITIGNORE_END, start);
351
349
  if (start >= 0 && end >= 0) {
352
350
  const suffix = current.slice(end + 27).replace(/^\r?\n/, "");
353
- await writeFile(path, `${current.slice(0, start)}${GITIGNORE}${suffix}`);
351
+ await writeFile(path, `${current.slice(0, start)}${generated}${suffix}`);
354
352
  return;
355
353
  }
356
- await writeFile(path, `${GITIGNORE}\n${current}`);
354
+ await writeFile(path, `${generated}\n${current}`);
355
+ }
356
+ async function writeRootSupport(root, definition, cli) {
357
+ const config = readWorkspaceConfig(root);
358
+ if (config === void 0) throw new Error(`No applet at ${root}.`);
359
+ assertWorkspaceCli(config, cli, true);
360
+ await writeWorkspaceSupport(root, config, cli);
361
+ await writeAppletSupport(root, definition);
357
362
  }
358
363
  async function writeWorkspaceSupport(root, config, cli) {
359
364
  const resolvedCli = cli ?? await loadCliManifest();
360
365
  if (resolvedCli === void 0) throw new Error("The CLI package manifest is not published.");
361
- assertWorkspaceCli(config, resolvedCli);
366
+ assertWorkspaceCli(config, resolvedCli, isRootLayout(root));
362
367
  await ensureAgentConfigs(root, config.org);
363
368
  const deployWorkflowTarget = resolve(root, ".github/workflows/hitch.yml");
364
- const agents = await readFile(new URL("../scaffold/AGENTS.md", import.meta.url), "utf8");
369
+ const rootLayout = isRootLayout(root);
365
370
  const [lintConfig, formatConfig] = await Promise.all([oxlintConfig(root), oxfmtConfig(root)]);
371
+ if (config.githubWorkflow !== false) await mkdir(resolve(root, ".github/workflows"), { recursive: true });
366
372
  await Promise.all([
367
- mkdir(resolve(root, ".agents/skills"), { recursive: true }),
368
- mkdir(resolve(root, ".claude/skills"), { recursive: true }),
369
- config.githubWorkflow === false ? void 0 : mkdir(resolve(root, ".github/workflows"), { recursive: true }),
370
- ...SKILLS.map((skill) => rm(resolve(root, ".agents/skills", skill), {
371
- force: true,
372
- recursive: true
373
- }))
374
- ]);
375
- await Promise.all([
376
- ...SKILLS.map((skill) => cp(new URL(`../scaffold/.agents/skills/${skill}`, import.meta.url), resolve(root, ".agents/skills", skill), { recursive: true })),
373
+ writeGeneratedAgents(root),
377
374
  writeFile(resolve(root, "package.json"), `${JSON.stringify(workspacePackage(config.org), null, 2)}\n`),
378
- writeFile(resolve(root, "pnpm-workspace.yaml"), workspaceFile(resolvedCli)),
375
+ writeFile(resolve(root, "pnpm-workspace.yaml"), rootLayout ? workspaceFile({
376
+ ...resolvedCli,
377
+ name: "@hitch42/applet"
378
+ }).replace(" - applets/*", " - .") : workspaceFile(resolvedCli)),
379
379
  config.githubWorkflow === false || existsSync(deployWorkflowTarget) ? void 0 : cp(new URL("../scaffold/.github/workflows/hitch.yml", import.meta.url), deployWorkflowTarget),
380
380
  writeFile(resolve(root, ".node-version"), "24\n"),
381
- writeFile(resolve(root, ".oxlintrc.json"), lintConfig),
382
- writeFile(resolve(root, ".oxfmtrc.json"), formatConfig),
383
- writeGitignore(root),
384
- writeFile(resolve(root, "AGENTS.md"), agents)
381
+ writeFile(resolve(root, ".oxlintrc.json"), rootLayout ? lintConfig.replaceAll("applets/*/", "") : lintConfig),
382
+ writeFile(resolve(root, ".oxfmtrc.json"), rootLayout ? `${JSON.stringify({
383
+ $schema: "./node_modules/oxfmt/configuration_schema.json",
384
+ sortImports: true,
385
+ ...existsSync(resolve(root, "src/client/styles/globals.css")) ? { sortTailwindcss: { stylesheet: "./src/client/styles/globals.css" } } : {}
386
+ }, null, 2)}\n` : formatConfig),
387
+ writeGitignore(root)
385
388
  ]);
386
- await rm(resolve(root, "CLAUDE.md"), { force: true });
387
- await symlink("AGENTS.md", resolve(root, "CLAUDE.md"));
388
- await Promise.all(SKILLS.map(async (skill) => {
389
- const target = resolve(root, ".claude/skills", skill);
390
- await rm(target, { force: true });
391
- await symlink(`../../.agents/skills/${skill}`, target, "dir");
392
- }));
393
389
  }
394
390
  function sortedByName(packages) {
395
391
  return Object.fromEntries(Object.entries(packages).sort(([a], [b]) => a < b ? -1 : 1));
396
392
  }
397
393
  function appletPackage(definition, options) {
398
394
  return {
395
+ ...options.rootLayout ? { packageManager: PACKAGE_MANAGER } : {},
399
396
  name: definition.code.replaceAll("_", "-"),
400
397
  private: true,
401
398
  type: "module",
@@ -441,6 +438,11 @@ function appletPackage(definition, options) {
441
438
  ...definition.dependencies
442
439
  }),
443
440
  devDependencies: sortedByName({
441
+ ...options.rootLayout ? {
442
+ oxfmt: "catalog:",
443
+ oxlint: "catalog:",
444
+ "oxlint-tsgolint": "catalog:"
445
+ } : {},
444
446
  "@types/node": "catalog:",
445
447
  typescript: "catalog:",
446
448
  vite: "catalog:",
@@ -468,6 +470,7 @@ async function replaceLegacyCnHelper(root) {
468
470
  await cp(new URL("../scaffold/applet/src/client/lib/utils.ts", import.meta.url), path);
469
471
  }
470
472
  async function writeAppletSupport(root, definition) {
473
+ if (isRootLayout(root)) await writeGeneratedAgents(root);
471
474
  const hasClient = existsSync(resolve(root, "src/client/routes"));
472
475
  const hasAuthorRoot = existsSync(resolve(root, "src/client/routes/__root.tsx"));
473
476
  const hasServer = existsSync(resolve(root, "src/server/main.ts"));
@@ -478,7 +481,8 @@ async function writeAppletSupport(root, definition) {
478
481
  replaceLegacyCnHelper(root),
479
482
  writeFile(resolve(root, "package.json"), `${JSON.stringify(appletPackage(definition, {
480
483
  hasClient,
481
- hasServer
484
+ hasServer,
485
+ rootLayout: isRootLayout(root)
482
486
  }), null, 2)}\n`),
483
487
  writeFile(resolve(root, "vite.config.ts"), `import { resolve } from "node:path";
484
488
 
@@ -561,12 +565,17 @@ async function prepareAppletProjects(workspaceRoot, appletRoots) {
561
565
  const workspace = readWorkspaceConfig(workspaceRoot);
562
566
  if (workspace === void 0) throw new Error(`No Hitch workspace found at ${workspaceRoot}.`);
563
567
  const cli = await loadCliManifest({ allowDevelopment: true });
568
+ if (isRootLayout(workspaceRoot)) {
569
+ if (cli === void 0) await writeAppletSupport(workspaceRoot, definitions[0]);
570
+ else await writeRootSupport(workspaceRoot, definitions[0], cli);
571
+ return;
572
+ }
564
573
  await Promise.all([cli === void 0 ? void 0 : writeWorkspaceSupport(workspaceRoot, workspace, cli), ...appletRoots.map((root, index) => writeAppletSupport(root, definitions[index]))]);
565
574
  }
566
575
  async function prepareAppletProject(appletRoot = process.cwd()) {
567
- const workspaceRoot = dirname(dirname(resolve(appletRoot)));
576
+ appletRoot = findAppletRoot(appletRoot) ?? resolve(appletRoot);
577
+ const workspaceRoot = findWorkspaceRoot(appletRoot) ?? dirname(dirname(appletRoot));
568
578
  await prepareAppletProjects(workspaceRoot, [appletRoot]);
569
579
  return workspaceRoot;
570
580
  }
571
- //#endregion
572
- export { userAgent as a, prepareAppletProjects as i, loadCliManifest as n, writeAppletSupport as o, prepareAppletProject as r, writeWorkspaceSupport as s, assertWorkspaceCli as t };
581
+ export { prepareAppletProjects as a, writeGitignore as c, prepareAppletProject as i, writeRootSupport as l, loadCliManifest as n, userAgent as o, loadPackageManifest as r, writeAppletSupport as s, assertWorkspaceCli as t, writeWorkspaceSupport as u };
@@ -1,6 +1,6 @@
1
1
  import { Writable } from "node:stream";
2
2
  import { createInterface } from "node:readline";
3
- //#region src/prompt.ts
3
+ // src/prompt.ts
4
4
  function question(prompt, hidden = false) {
5
5
  return new Promise((resolveAnswer, rejectAnswer) => {
6
6
  let muted = false;
@@ -25,5 +25,4 @@ function question(prompt, hidden = false) {
25
25
  });
26
26
  });
27
27
  }
28
- //#endregion
29
28
  export { question as t };
@@ -1,4 +1,4 @@
1
- //#region src/internal/query-cache.ts
1
+ // src/internal/query-cache.ts
2
2
  const STORE = "clients";
3
3
  const TIMESTAMP_INDEX = "timestamp";
4
4
  const TAB_KEY = "hitch:query-tab";
@@ -78,5 +78,4 @@ function sweepExpiredQueryCaches(maxAge) {
78
78
  function clearAppletQueryCaches(appletCode) {
79
79
  return inStore("readwrite", (store) => store.delete(IDBKeyRange.bound(`${appletCode}:`, `${appletCode}:\uffff`)));
80
80
  }
81
- //#endregion
82
81
  export { openQueryCacheDatabase as a, openCacheDatabase as i, clearAppletQueryCaches as n, sweepExpiredQueryCaches as o, indexedDbPersister as r, cacheTabId as t };
@@ -1,6 +1,5 @@
1
1
  import { NestedClient } from "@orpc/client";
2
2
  import { RouterUtils } from "@orpc/tanstack-query";
3
- //#region src/query-utils.d.ts
4
3
  type Exact<Expected, Actual> = Actual extends symbol ? Actual : Actual extends Expected ? Actual extends readonly unknown[] ? Actual : Actual extends object ? NonNullable<Expected> extends object ? { [Key in keyof Actual]: Key extends keyof NonNullable<Expected> ? Exact<NonNullable<Expected>[Key], Actual[Key]> : never; } : Actual : Actual : never;
5
4
  type QueryOptionsFunction<Utils> = Extract<Utils extends {
6
5
  queryOptions: infer Function;
@@ -21,5 +20,4 @@ type ClientTree = NestedClient<Record<never, never>>;
21
20
  type ExactRouterUtils<Client extends ClientTree> = Client extends ((...args: infer Arguments) => unknown) ? Omit<RouterUtils<Client>, "queryOptions"> & {
22
21
  queryOptions: ExactQueryOptions<RouterUtils<Client>, Arguments[0]>;
23
22
  } : Omit<RouterUtils<Client>, keyof Client> & { [Key in keyof Client]: Client[Key] extends ClientTree ? ExactRouterUtils<Client[Key]> : never; };
24
- //#endregion
25
23
  export { ExactRouterUtils as t };
@@ -1,9 +1,10 @@
1
- import { t as loadAppletConfig } from "./load-config-DGALUExv.js";
2
- import { t as question } from "./prompt-ChS-grYO.js";
1
+ import { n as findAppletRoot } from "./workspace-CtIKSgMD.js";
2
+ import { t as loadAppletConfig } from "./load-config-Cffvj-aM.js";
3
+ import { t as question } from "./prompt-CW98R-Un.js";
3
4
  import { RPCLink } from "@orpc/client/fetch";
4
5
  import { readFile } from "node:fs/promises";
5
6
  import { resolve } from "node:path";
6
- //#region src/schedules.ts
7
+ // src/schedules.ts
7
8
  async function runSchedule(options) {
8
9
  const manifest = await loadAppletConfig(process.cwd());
9
10
  const schedules = manifest.schedules ?? [];
@@ -13,7 +14,7 @@ async function runSchedule(options) {
13
14
  const unavailable = "The dev server is not running. Start it with pnpm dev.";
14
15
  let url;
15
16
  try {
16
- const file = JSON.parse(await readFile(resolve(process.cwd(), ".hitch/dev-server.json"), "utf8"));
17
+ const file = JSON.parse(await readFile(resolve(findAppletRoot(process.cwd()) ?? process.cwd(), ".hitch/dev-server.json"), "utf8"));
17
18
  if (file === null || typeof file !== "object" || !("url" in file) || typeof file.url !== "string" || !("pid" in file) || typeof file.pid !== "number" || !Number.isInteger(file.pid) || file.pid < 1) throw new Error(unavailable);
18
19
  try {
19
20
  process.kill(file.pid, 0);
@@ -38,5 +39,4 @@ async function runSchedule(options) {
38
39
  });
39
40
  console.log(`Schedule "${options.code}" finished.`);
40
41
  }
41
- //#endregion
42
42
  export { runSchedule };
package/dist/server.d.ts CHANGED
@@ -1,10 +1,9 @@
1
- import { a as createWorkflow, i as WorkflowStep, n as WorkflowDefinition, r as WorkflowDuration } from "./workflow-DurM6Fwx.js";
2
- import { l as RegisteredContract, m as RegisteredWorkflows, p as RegisteredVariables, u as RegisteredManifest } from "./manifest-BBHD_EY9.js";
3
- import { t as NarrowContract } from "./contract-CJv-n1l3.js";
4
- import { i as WithBatchRecorder, n as WithRecordCreates } from "./create-C2UrZYSK.js";
5
- import { o as WithFilesUpload } from "./upload-D_kkmne_.js";
1
+ import { a as createWorkflow, i as WorkflowStep, n as WorkflowDefinition, r as WorkflowDuration } from "./workflow-BnBrJIzu.js";
2
+ import { l as RegisteredContract, m as RegisteredWorkflows, p as RegisteredVariables, u as RegisteredManifest } from "./manifest-CpghlaJc.js";
3
+ import { t as NarrowContract } from "./contract-CUc0B2rl.js";
4
+ import { i as WithBatchRecorder, n as WithRecordCreates } from "./create-BJqLT8Uq.js";
5
+ import { o as WithFilesUpload } from "./upload-DXZyjZSS.js";
6
6
  import { ContractRouterClient } from "@orpc/contract";
7
- //#region src/server/workflows-client.d.ts
8
7
  type WorkflowRunStatus<Result> = {
9
8
  id: string;
10
9
  workflow: string;
@@ -26,8 +25,6 @@ type WorkflowsClient<Workflows> = { [Code in keyof Workflows]: Workflows[Code] e
26
25
  limit?: number;
27
26
  }): Promise<WorkflowRunSummary[]>;
28
27
  } : never; };
29
- //#endregion
30
- //#region src/server/env.d.ts
31
28
  type AppletEnv<Variables extends AppletManifestVariables = RegisteredVariables> = { readonly [Key in keyof Variables]: Variables[Key] extends {
32
29
  optional: true;
33
30
  } ? string | undefined : string; };
@@ -35,13 +32,9 @@ type AppletManifestVariables = Readonly<Record<string, {
35
32
  optional?: boolean;
36
33
  }>>;
37
34
  declare const env: AppletEnv;
38
- //#endregion
39
- //#region src/server/log.d.ts
40
35
  declare const log: {
41
36
  set(fields: Record<string, unknown>): void;
42
37
  };
43
- //#endregion
44
- //#region src/author/server.d.ts
45
38
  type AuthorContract = NarrowContract<RegisteredContract, RegisteredManifest>;
46
39
  type AuthorHitchClient = WithRecordCreates<WithBatchRecorder<ContractRouterClient<AuthorContract>>>;
47
40
  type AuthorHitch = WithFilesUpload<AuthorHitchClient> & (RegisteredManifest extends {
@@ -50,5 +43,4 @@ type AuthorHitch = WithFilesUpload<AuthorHitchClient> & (RegisteredManifest exte
50
43
  workflows: WorkflowsClient<RegisteredWorkflows>;
51
44
  });
52
45
  declare const hitch: AuthorHitch;
53
- //#endregion
54
46
  export { type AppletEnv, type WorkflowDefinition, type WorkflowDuration, type WorkflowStep, createWorkflow, env, hitch, log };
package/dist/server.js CHANGED
@@ -1,12 +1,12 @@
1
- import { n as withFilesUpload, r as getRegisteredHitchContract } from "./upload-DRbVhuDm.js";
2
- import { t as HITCH_APPLET_CODE_HEADER } from "./headers-CeRX-Xji.js";
3
- import { a as getRequestContext, i as getIdentityBearer, n as createWorkflow, s as tryGetRequestContext } from "./workflow-CTo2kZF1.js";
4
- import { s as publishNote, t as APP_CONTEXT_CHANNEL } from "./log-context-DWznGjfz.js";
5
- import { t as withBatchRecorder } from "./batch-_ZjAg-Kk.js";
6
- import { t as createLazyClientProxy } from "./lazy-client-CwIzYAoE.js";
1
+ import { n as withFilesUpload, r as getRegisteredHitchContract } from "./upload-DtMavo8Q.js";
2
+ import { t as HITCH_APPLET_CODE_HEADER } from "./headers-BcEMIVCo.js";
3
+ import { a as getRequestContext, i as getIdentityBearer, n as createWorkflow, s as tryGetRequestContext } from "./workflow-l2SlVePB.js";
4
+ import { s as publishNote, t as APP_CONTEXT_CHANNEL } from "./log-context-BepwdjrR.js";
5
+ import { t as withBatchRecorder } from "./batch-CiLZ177G.js";
6
+ import { t as createLazyClientProxy } from "./lazy-client--QCL0wiu.js";
7
7
  import { createORPCClient } from "@orpc/client";
8
8
  import { OpenAPILink } from "@orpc/openapi-client/fetch";
9
- //#region src/hitch/server.ts
9
+ // src/hitch/server.ts
10
10
  const DEFAULT_API_URL = "https://app.hitch42.com";
11
11
  const resolveTransport = () => {
12
12
  const context = tryGetRequestContext();
@@ -42,8 +42,7 @@ function createHitchClient(contract) {
42
42
  headers: () => resolveTransport().headers
43
43
  }));
44
44
  }
45
- //#endregion
46
- //#region src/server/workflows-client.ts
45
+ // src/server/workflows-client.ts
47
46
  function mapWorkflowRun(data) {
48
47
  const { sleep_until: sleepUntil, started_at: startedAt, finished_at: finishedAt, ...run } = data;
49
48
  return {
@@ -67,7 +66,7 @@ function createWorkflowsClient() {
67
66
  return {
68
67
  async start(payload) {
69
68
  const context = getRequestContext();
70
- return { id: (await getResponseData(await context.api.fetch(`${context.api.baseUrl}/v1/applets/${encodeURIComponent(context.appletCode)}/workflows/${encodeURIComponent(code)}/runs`, {
69
+ return { id: (await getResponseData(await context.api.fetch(`${context.api.baseUrl}/applet/v1/applets/${encodeURIComponent(context.appletCode)}/workflows/${encodeURIComponent(code)}/runs`, {
71
70
  method: "POST",
72
71
  headers: {
73
72
  authorization: `Bearer ${getIdentityBearer(context.identity)}`,
@@ -78,17 +77,19 @@ function createWorkflowsClient() {
78
77
  },
79
78
  async get(id) {
80
79
  const context = getRequestContext();
81
- return mapWorkflowRun(await getResponseData(await context.api.fetch(`${context.api.baseUrl}/v1/applets/${encodeURIComponent(context.appletCode)}/workflows/${encodeURIComponent(code)}/runs/${encodeURIComponent(id)}`, {
80
+ const data = await getResponseData(await context.api.fetch(`${context.api.baseUrl}/applet/v1/applets/${encodeURIComponent(context.appletCode)}/workflow-runs/${encodeURIComponent(id)}`, {
82
81
  method: "GET",
83
82
  headers: { authorization: `Bearer ${getIdentityBearer(context.identity)}` }
84
- }), "get"));
83
+ }), "get");
84
+ if (data.workflow !== code) throw new Error("Workflow get failed (404): workflow_run_not_found: The workflow run does not exist.");
85
+ return mapWorkflowRun(data);
85
86
  },
86
87
  async list(options) {
87
88
  const context = getRequestContext();
88
89
  const query = new URLSearchParams({ workflow: code });
89
90
  if (options?.status !== void 0) query.set("status", options.status);
90
91
  if (options?.limit !== void 0) query.set("limit", String(options.limit));
91
- return (await getResponseData(await context.api.fetch(`${context.api.baseUrl}/v1/applets/${encodeURIComponent(context.appletCode)}/workflow-runs?${query}`, {
92
+ return (await getResponseData(await context.api.fetch(`${context.api.baseUrl}/applet/v1/applets/${encodeURIComponent(context.appletCode)}/workflow-runs?${query}`, {
92
93
  method: "GET",
93
94
  headers: { authorization: `Bearer ${getIdentityBearer(context.identity)}` }
94
95
  }), "list")).map(mapWorkflowRun);
@@ -96,11 +97,9 @@ function createWorkflowsClient() {
96
97
  };
97
98
  } });
98
99
  }
99
- //#endregion
100
- //#region src/server/env.ts
100
+ // src/server/env.ts
101
101
  const env = process.env;
102
- //#endregion
103
- //#region src/server/log.ts
102
+ // src/server/log.ts
104
103
  const log = { set(fields) {
105
104
  const context = tryGetRequestContext();
106
105
  if (context === void 0) {
@@ -109,8 +108,7 @@ const log = { set(fields) {
109
108
  }
110
109
  publishNote(context.requestId, fields, APP_CONTEXT_CHANNEL);
111
110
  } };
112
- //#endregion
113
- //#region src/author/server.ts
111
+ // src/author/server.ts
114
112
  function buildHitchClient() {
115
113
  const contract = getRegisteredHitchContract();
116
114
  if (contract === void 0) throw new Error("`hitch` is unavailable: run `applet generate` first. The framework imports your .hitch automatically at build; in plain node import your .hitch once before calling hitch.");
@@ -122,5 +120,4 @@ const workflows = createWorkflowsClient();
122
120
  const hitch = new Proxy(filesClient, { get(target, property, receiver) {
123
121
  return property === "workflows" ? workflows : Reflect.get(target, property, receiver);
124
122
  } });
125
- //#endregion
126
123
  export { createWorkflow, env, hitch, log };