@hitch42/applet 0.1.1-beta.19 → 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 (96) 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-DkKTiIu7.js → build-FAQSHJgm.js} +4 -3
  12. package/dist/{ci-B5-mH-YW.js → ci-oWlUJKm9.js} +10 -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-BJqLT8Uq.d.ts +68 -0
  30. package/dist/{deploy-DODTE8ri.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-8yyxKRSz.js → generate-48pqFh5M.js} +57 -39
  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-D33JOEOi.d.ts +22 -0
  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-DT0faD-q.js → init-Bb6WT8UB.js} +70 -18
  48. package/dist/{lazy-client-CwIzYAoE.js → lazy-client--QCL0wiu.js} +1 -2
  49. package/dist/{load-config-BYrBjPlr.js → load-config-Cffvj-aM.js} +27 -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-CEIikWzV.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-CWVwic2C.js → project-DZGk765E.js} +74 -58
  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-B7xNl9oy.js → schedules-CSUb84e2.js} +5 -5
  66. package/dist/server.d.ts +6 -14
  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-DCbLJBr0.js → variables-CgZstC7I.js} +7 -8
  75. package/dist/vite.d.ts +1 -3
  76. package/dist/vite.js +42 -51
  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 +28 -10
  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 +24 -9
  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/batch-Qa4B4-Yp.d.ts +0 -30
  91. package/dist/build-DpkWOvd2.js +0 -2
  92. package/dist/generate-Df29-UJm.js +0 -2
  93. package/dist/hitch-client--qZVa2KM.d.ts +0 -23
  94. package/dist/login-CceGvlMi.js +0 -14
  95. package/dist/store-B8N_8JIN.js +0 -196
  96. package/dist/workspace-8yqXsvce.js +0 -31
@@ -1,4 +1,4 @@
1
- //#region src/hitch/contract.ts
1
+ // src/hitch/contract.ts
2
2
  function isObject(value) {
3
3
  return value !== null && typeof value === "object" && !Array.isArray(value);
4
4
  }
@@ -24,5 +24,4 @@ function pruneContract(contract, manifest) {
24
24
  }
25
25
  return Object.assign(platform, { records });
26
26
  }
27
- //#endregion
28
27
  export { pruneContract as t };
@@ -0,0 +1,68 @@
1
+ import { AnyContractRouter } from "@orpc/contract";
2
+ import { ClientPromiseResult } from "@orpc/client";
3
+ type BatchVerb = "create" | "update" | "delete" | "updateWhere";
4
+ type BatchTxRecords<Records> = { [Code in keyof Records]: { [Verb in keyof Records[Code] & BatchVerb]: Records[Code][Verb] extends ((...args: infer Args) => unknown) ? (input: Verb extends "create" ? Args[0] extends {
5
+ body: infer Body;
6
+ } ? Omit<Args[0], "body"> & {
7
+ body: Exclude<Body, readonly unknown[]>;
8
+ } : Args[0] : Args[0]) => void : never; }; };
9
+ type BatchTx<T> = T extends {
10
+ records: infer Records;
11
+ } ? BatchTxRecords<Records> : never;
12
+ type BatchRecorderOptions = {
13
+ dryRun?: boolean;
14
+ idempotencyKey?: string;
15
+ };
16
+ type BatchRecorderCall<T, Batch> = Batch extends ((...args: infer _Args) => infer Result) ? (record: (tx: BatchTx<T>) => void | Promise<void>, options?: BatchRecorderOptions) => Result : never;
17
+ type WithBatchRecorder<T> = T extends {
18
+ records: unknown;
19
+ batch: infer Batch;
20
+ } ? Omit<T, "batch"> & {
21
+ /**
22
+ * Record record writes inside `record` and send them as one atomic batch.
23
+ *
24
+ * The callback receives a `tx` whose `create` / `update` / `updateWhere` /
25
+ * `delete` calls are buffered, not sent immediately; the whole batch runs
26
+ * in a single transaction when the callback resolves.
27
+ *
28
+ * @remarks A batch may contain at most **100** requests. More than that is
29
+ * rejected with a `400` before any write runs.
30
+ */
31
+ batch: BatchRecorderCall<T, Batch> & Batch;
32
+ } : T;
33
+ type Many<T> = Extract<T, readonly unknown[]>;
34
+ type One<T> = Exclude<T, readonly unknown[]>;
35
+ type SplitCreate<F> = F extends ((input: infer Input extends {
36
+ body: unknown;
37
+ }, ...rest: infer Rest) => ClientPromiseResult<infer Output, infer TError>) ? [Many<Input["body"]>] extends [never] ? F : {
38
+ (input: Omit<Input, "body"> & {
39
+ body: Many<Input["body"]>;
40
+ }, ...rest: Rest): ClientPromiseResult<Many<Output>, TError>;
41
+ (input: Omit<Input, "body"> & {
42
+ body: One<Input["body"]>;
43
+ }, ...rest: Rest): ClientPromiseResult<One<Output>, TError>;
44
+ } : F extends {
45
+ call: infer Call;
46
+ } ? Omit<F, "call"> & {
47
+ call: SplitCreate<Call>;
48
+ } : F;
49
+ type WithRecordCreates<T> = T extends {
50
+ records: infer Records;
51
+ } ? Omit<T, "records"> & {
52
+ records: { [Code in keyof Records]: { [Verb in keyof Records[Code]]: Verb extends "create" ? SplitCreate<Records[Code][Verb]> : Records[Code][Verb]; }; };
53
+ } : T;
54
+ type WithSingleRecordCreates<T> = T extends {
55
+ records: infer Records;
56
+ } ? Omit<T, "records"> & {
57
+ records: { [Code in keyof Records]: { [Verb in keyof Records[Code]]: Verb extends "create" ? SplitCreate<Records[Code][Verb]> extends ((...args: infer Args) => infer Result) ? (...args: Args) => Result : Records[Code][Verb] : Records[Code][Verb]; }; };
58
+ } : T;
59
+ type WithRecordCreateCalls<Utils, Client> = Utils extends {
60
+ records: infer Records;
61
+ } ? Client extends {
62
+ records: infer Clients;
63
+ } ? Omit<Utils, "records"> & {
64
+ records: { [Code in keyof Records]: { [Verb in keyof Records[Code]]: Verb extends "create" ? Code extends keyof Clients ? Verb extends keyof Clients[Code] ? Omit<Records[Code][Verb], "call"> & {
65
+ call: SplitCreate<Clients[Code][Verb]>;
66
+ } : Records[Code][Verb] : Records[Code][Verb] : Records[Code][Verb]; }; };
67
+ } : Utils : Utils;
68
+ export { WithBatchRecorder as i, WithRecordCreates as n, WithSingleRecordCreates as r, WithRecordCreateCalls as t };
@@ -1,23 +1,28 @@
1
- import { n as readWorkspaceConfig } from "./workspace-8yqXsvce.js";
2
- import { t as fetchWithOrgAuth } from "./auth-D3CrCtZq.js";
3
- import { a as loadGitHubActionsSources, n as githubActionsContext, r as hitchResponseError, t as fetchWithGitHubActions } from "./ci-B5-mH-YW.js";
4
- import { n as buildPreparedApplet, r as prepareWorkspaceBuild, t as buildApplet } from "./build-DkKTiIu7.js";
1
+ import { a as findWorkspaceRoot, n as findAppletRoot, o as isRootLayout, r as findParentRoot, s as readWorkspaceConfig } from "./workspace-CtIKSgMD.js";
2
+ import { n as fetchWithOrgAuth, r as orgUsesHitchGit, t as canCheckHitchGit } from "./auth-DuMRqSGe.js";
3
+ import { n as loadAppletSourceDefinition } from "./load-config-Cffvj-aM.js";
4
+ import { i as prepareAppletProject } from "./project-DZGk765E.js";
5
+ import { a as loadGitHubActionsSources, n as githubActionsContext, t as fetchWithGitHubActions } from "./ci-oWlUJKm9.js";
6
+ import { n as buildPreparedApplet, r as prepareWorkspaceBuild, t as buildApplet } from "./build-FAQSHJgm.js";
7
+ import { n as gitEnvironment, r as sourceHashes, t as SourceHashUnavailableError } from "./source-hash-BbvtRaus.js";
8
+ import { a as prepareGitDeploy, o as pushStagedCommit, s as refreshHitchMain, t as deployErrorMessage } from "./git-deploy-C12nMNB6.js";
9
+ import { n as childApplets, r as childHasChanges } from "./parent-Zx8Eg1Ki.js";
10
+ import { n as migrateWorkspace } from "./git-migration-CIq-sN61.js";
5
11
  import { createRequire } from "node:module";
6
- import { createHash } from "node:crypto";
7
12
  import { existsSync } from "node:fs";
8
- import { lstat, readFile, readdir, readlink } from "node:fs/promises";
9
- import { dirname, relative, resolve, sep } from "node:path";
10
- import { execFile, spawn } from "node:child_process";
13
+ import { readFile, readdir } from "node:fs/promises";
14
+ import { basename, dirname, relative, resolve, sep } from "node:path";
15
+ import { execFile } from "node:child_process";
11
16
  import { promisify } from "node:util";
12
17
  import { createGzip } from "node:zlib";
13
- //#region \0rolldown/runtime.js
18
+ // \0rolldown/runtime.js
14
19
  var __create = Object.create;
15
20
  var __defProp = Object.defineProperty;
16
21
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
17
22
  var __getOwnPropNames = Object.getOwnPropertyNames;
18
23
  var __getProtoOf = Object.getPrototypeOf;
19
24
  var __hasOwnProp = Object.prototype.hasOwnProperty;
20
- var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
25
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod, mod.exports), cb = null), mod.exports);
21
26
  var __copyProps = (to, from, except, desc) => {
22
27
  if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
23
28
  key = keys[i];
@@ -33,13 +38,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
33
38
  enumerable: true
34
39
  }) : target, mod));
35
40
  var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
36
- //#endregion
37
- //#region ../../node_modules/.pnpm/events-universal@1.0.1/node_modules/events-universal/default.js
41
+ // ../../node_modules/.pnpm/events-universal@1.0.1/node_modules/events-universal/default.js
38
42
  var require_default = /* @__PURE__ */ __commonJSMin(((exports, module) => {
39
43
  module.exports = __require("events");
40
44
  }));
41
- //#endregion
42
- //#region ../../node_modules/.pnpm/fast-fifo@1.3.2/node_modules/fast-fifo/fixed-size.js
45
+ // ../../node_modules/.pnpm/fast-fifo@1.3.2/node_modules/fast-fifo/fixed-size.js
43
46
  var require_fixed_size = /* @__PURE__ */ __commonJSMin(((exports, module) => {
44
47
  module.exports = class FixedFIFO {
45
48
  constructor(hwm) {
@@ -76,8 +79,7 @@ var require_fixed_size = /* @__PURE__ */ __commonJSMin(((exports, module) => {
76
79
  }
77
80
  };
78
81
  }));
79
- //#endregion
80
- //#region ../../node_modules/.pnpm/fast-fifo@1.3.2/node_modules/fast-fifo/index.js
82
+ // ../../node_modules/.pnpm/fast-fifo@1.3.2/node_modules/fast-fifo/index.js
81
83
  var require_fast_fifo = /* @__PURE__ */ __commonJSMin(((exports, module) => {
82
84
  const FixedFIFO = require_fixed_size();
83
85
  module.exports = class FastFIFO {
@@ -121,8 +123,7 @@ var require_fast_fifo = /* @__PURE__ */ __commonJSMin(((exports, module) => {
121
123
  }
122
124
  };
123
125
  }));
124
- //#endregion
125
- //#region ../../node_modules/.pnpm/b4a@1.8.1/node_modules/b4a/index.js
126
+ // ../../node_modules/.pnpm/b4a@1.8.1/node_modules/b4a/index.js
126
127
  var require_b4a = /* @__PURE__ */ __commonJSMin(((exports, module) => {
127
128
  function isBuffer(value) {
128
129
  return Buffer.isBuffer(value) || value instanceof Uint8Array;
@@ -276,8 +277,7 @@ var require_b4a = /* @__PURE__ */ __commonJSMin(((exports, module) => {
276
277
  writeUInt32LE
277
278
  };
278
279
  }));
279
- //#endregion
280
- //#region ../../node_modules/.pnpm/text-decoder@1.2.7/node_modules/text-decoder/lib/pass-through-decoder.js
280
+ // ../../node_modules/.pnpm/text-decoder@1.2.7/node_modules/text-decoder/lib/pass-through-decoder.js
281
281
  var require_pass_through_decoder = /* @__PURE__ */ __commonJSMin(((exports, module) => {
282
282
  const b4a = require_b4a();
283
283
  module.exports = class PassThroughDecoder {
@@ -295,8 +295,7 @@ var require_pass_through_decoder = /* @__PURE__ */ __commonJSMin(((exports, modu
295
295
  }
296
296
  };
297
297
  }));
298
- //#endregion
299
- //#region ../../node_modules/.pnpm/text-decoder@1.2.7/node_modules/text-decoder/lib/utf8-decoder.js
298
+ // ../../node_modules/.pnpm/text-decoder@1.2.7/node_modules/text-decoder/lib/utf8-decoder.js
300
299
  var require_utf8_decoder = /* @__PURE__ */ __commonJSMin(((exports, module) => {
301
300
  const b4a = require_b4a();
302
301
  /**
@@ -443,8 +442,7 @@ var require_utf8_decoder = /* @__PURE__ */ __commonJSMin(((exports, module) => {
443
442
  return 0;
444
443
  }
445
444
  }));
446
- //#endregion
447
- //#region ../../node_modules/.pnpm/text-decoder@1.2.7/node_modules/text-decoder/index.js
445
+ // ../../node_modules/.pnpm/text-decoder@1.2.7/node_modules/text-decoder/index.js
448
446
  var require_text_decoder = /* @__PURE__ */ __commonJSMin(((exports, module) => {
449
447
  const PassThroughDecoder = require_pass_through_decoder();
450
448
  const UTF8Decoder = require_utf8_decoder();
@@ -495,8 +493,7 @@ var require_text_decoder = /* @__PURE__ */ __commonJSMin(((exports, module) => {
495
493
  }
496
494
  }
497
495
  }));
498
- //#endregion
499
- //#region ../../node_modules/.pnpm/streamx@2.28.1/node_modules/streamx/lib/errors.js
496
+ // ../../node_modules/.pnpm/streamx@2.28.1/node_modules/streamx/lib/errors.js
500
497
  var require_errors = /* @__PURE__ */ __commonJSMin(((exports, module) => {
501
498
  module.exports = class StreamError extends Error {
502
499
  constructor(msg, code, fn = StreamError) {
@@ -533,8 +530,7 @@ var require_errors = /* @__PURE__ */ __commonJSMin(((exports, module) => {
533
530
  }
534
531
  };
535
532
  }));
536
- //#endregion
537
- //#region ../../node_modules/.pnpm/streamx@2.28.1/node_modules/streamx/index.js
533
+ // ../../node_modules/.pnpm/streamx@2.28.1/node_modules/streamx/index.js
538
534
  var require_streamx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
539
535
  const { EventEmitter } = require_default();
540
536
  const FIFO = require_fast_fifo();
@@ -1485,8 +1481,7 @@ var require_streamx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
1485
1481
  PassThrough
1486
1482
  };
1487
1483
  }));
1488
- //#endregion
1489
- //#region ../../node_modules/.pnpm/tar-stream@3.2.1/node_modules/tar-stream/headers.js
1484
+ // ../../node_modules/.pnpm/tar-stream@3.2.1/node_modules/tar-stream/headers.js
1490
1485
  var require_headers = /* @__PURE__ */ __commonJSMin(((exports) => {
1491
1486
  const b4a = require_b4a();
1492
1487
  const ZEROS = "0000000000000000000";
@@ -1721,8 +1716,7 @@ var require_headers = /* @__PURE__ */ __commonJSMin(((exports) => {
1721
1716
  return len + digits + str;
1722
1717
  }
1723
1718
  }));
1724
- //#endregion
1725
- //#region ../../node_modules/.pnpm/tar-stream@3.2.1/node_modules/tar-stream/extract.js
1719
+ // ../../node_modules/.pnpm/tar-stream@3.2.1/node_modules/tar-stream/extract.js
1726
1720
  var require_extract = /* @__PURE__ */ __commonJSMin(((exports, module) => {
1727
1721
  const { Writable, Readable, getStreamError } = require_streamx();
1728
1722
  const FIFO = require_fast_fifo();
@@ -2070,8 +2064,7 @@ var require_extract = /* @__PURE__ */ __commonJSMin(((exports, module) => {
2070
2064
  return size && 512 - size;
2071
2065
  }
2072
2066
  }));
2073
- //#endregion
2074
- //#region ../../node_modules/.pnpm/tar-stream@3.2.1/node_modules/tar-stream/constants.js
2067
+ // ../../node_modules/.pnpm/tar-stream@3.2.1/node_modules/tar-stream/constants.js
2075
2068
  var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
2076
2069
  const constants = {
2077
2070
  S_IFMT: 61440,
@@ -2087,8 +2080,7 @@ var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
2087
2080
  module.exports = constants;
2088
2081
  }
2089
2082
  }));
2090
- //#endregion
2091
- //#region ../../node_modules/.pnpm/tar-stream@3.2.1/node_modules/tar-stream/pack.js
2083
+ // ../../node_modules/.pnpm/tar-stream@3.2.1/node_modules/tar-stream/pack.js
2092
2084
  var require_pack = /* @__PURE__ */ __commonJSMin(((exports, module) => {
2093
2085
  const { Readable, Writable, getStreamError } = require_streamx();
2094
2086
  const b4a = require_b4a();
@@ -2308,113 +2300,17 @@ var require_pack = /* @__PURE__ */ __commonJSMin(((exports, module) => {
2308
2300
  return b4a.isBuffer(buf) ? buf : b4a.from(buf);
2309
2301
  }
2310
2302
  }));
2311
- //#endregion
2312
- //#region src/source-hash.ts
2303
+ // src/response-error.ts
2313
2304
  var import_tar_stream = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports) => {
2314
2305
  exports.extract = require_extract();
2315
2306
  exports.pack = require_pack();
2316
2307
  })))(), 1);
2317
- const execFileAsync$1 = promisify(execFile);
2318
- function gitEnvironment() {
2319
- return Object.fromEntries(Object.entries(process.env).filter(([key]) => !key.startsWith("GIT_")));
2308
+ async function hitchResponseError(response, summary) {
2309
+ const body = await response.json().catch(() => null);
2310
+ const details = body !== null && typeof body === "object" ? ["code" in body && typeof body.code === "string" ? body.code : void 0, "message" in body && typeof body.message === "string" ? body.message : void 0].filter((value) => value !== void 0).join(": ") : "";
2311
+ return /* @__PURE__ */ new Error(`${summary} (${response.status})${details ? `: ${details}` : ""}.`);
2320
2312
  }
2321
- var SourceHashUnavailableError = class extends Error {
2322
- constructor() {
2323
- super("Git is unavailable or the applet is outside a git repository.");
2324
- }
2325
- };
2326
- function isMissingPath(error) {
2327
- return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
2328
- }
2329
- async function hashFiles(topLevel, paths, env) {
2330
- if (paths.length === 0) return [];
2331
- return new Promise((resolveHashes, reject) => {
2332
- const child = spawn("git", ["hash-object", "--stdin-paths"], {
2333
- cwd: topLevel,
2334
- env
2335
- });
2336
- const stdout = [];
2337
- const stderr = [];
2338
- child.stdout.on("data", (chunk) => stdout.push(chunk));
2339
- child.stderr.on("data", (chunk) => stderr.push(chunk));
2340
- child.stdin.on("error", reject);
2341
- child.on("error", reject);
2342
- child.on("close", (code) => {
2343
- if (code !== 0) {
2344
- reject(/* @__PURE__ */ new Error(`git hash-object failed (${code}): ${Buffer.concat(stderr).toString("utf8").trim()}`));
2345
- return;
2346
- }
2347
- const hashes = Buffer.concat(stdout).toString("utf8").trimEnd().split("\n");
2348
- if (hashes.length !== paths.length || hashes.some((hash) => !/^[0-9a-f]{40,64}$/.test(hash))) {
2349
- reject(/* @__PURE__ */ new Error("git hash-object returned an unexpected number of hashes."));
2350
- return;
2351
- }
2352
- resolveHashes(hashes);
2353
- });
2354
- 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(""));
2355
- });
2356
- }
2357
- async function sourceHashes(appletRoots) {
2358
- if (appletRoots.length === 0) return /* @__PURE__ */ new Map();
2359
- const env = gitEnvironment();
2360
- const workspaceRoot = dirname(dirname(appletRoots[0]));
2361
- let topLevel;
2362
- try {
2363
- const { stdout } = await execFileAsync$1("git", ["rev-parse", "--show-toplevel"], {
2364
- cwd: workspaceRoot,
2365
- env
2366
- });
2367
- topLevel = stdout.trim();
2368
- } catch (error) {
2369
- if (isMissingPath(error) || error instanceof Error && error.message.includes("not a git repository")) throw new SourceHashUnavailableError();
2370
- throw error;
2371
- }
2372
- const { stdout } = await execFileAsync$1("git", [
2373
- "ls-files",
2374
- "-z",
2375
- "--cached",
2376
- "--others",
2377
- "--exclude-standard"
2378
- ], {
2379
- cwd: topLevel,
2380
- env,
2381
- maxBuffer: 67108864
2382
- });
2383
- const paths = [...new Set(stdout.split("\0").filter(Boolean))];
2384
- const present = (await Promise.all(paths.map(async (path) => {
2385
- const absolutePath = resolve(topLevel, path);
2386
- try {
2387
- const stat = await lstat(absolutePath);
2388
- if (stat.isFile()) return {
2389
- path,
2390
- kind: "file"
2391
- };
2392
- if (stat.isSymbolicLink()) return {
2393
- path,
2394
- kind: "link",
2395
- contentId: await readlink(absolutePath)
2396
- };
2397
- return;
2398
- } catch (error) {
2399
- if (isMissingPath(error)) return void 0;
2400
- throw error;
2401
- }
2402
- }))).filter((entry) => entry !== void 0);
2403
- const regularPaths = present.filter((entry) => entry.kind === "file").map((entry) => entry.path);
2404
- const hashes = await hashFiles(topLevel, regularPaths, env);
2405
- const contentIds = /* @__PURE__ */ new Map();
2406
- present.filter((entry) => entry.kind === "link").forEach((entry) => contentIds.set(entry.path, entry.contentId));
2407
- regularPaths.forEach((path, index) => contentIds.set(path, hashes[index]));
2408
- const appletsDirectory = relative(topLevel, resolve(workspaceRoot, "applets")).split(sep).join("/");
2409
- return new Map(appletRoots.map((appletRoot) => {
2410
- const appletDirectory = relative(topLevel, appletRoot).split(sep).join("/");
2411
- const digest = createHash("sha256");
2412
- [...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`));
2413
- return [appletRoot, digest.digest("hex")];
2414
- }));
2415
- }
2416
- //#endregion
2417
- //#region src/deploy.ts
2313
+ // src/deploy.ts
2418
2314
  const execFileAsync = promisify(execFile);
2419
2315
  var WorkspaceDeployError = class extends Error {
2420
2316
  constructor(failedApplets) {
@@ -2499,15 +2395,18 @@ function releaseForm(manifest, bundle) {
2499
2395
  body.set("bundle", new File([bundle], "bundle.tar.gz", { type: "application/gzip" }));
2500
2396
  return body;
2501
2397
  }
2502
- async function deployWithOrgAuth(appletRoot, distDir, manifest, sourceHash) {
2398
+ async function deployWithOrgAuth(appletRoot, distDir, manifest, sourceHash, gitSha) {
2503
2399
  const fetcher = globalThis.fetch;
2504
- const [bundle, git] = await Promise.all([createBundle(distDir), readGitInfo(appletRoot)]);
2400
+ const [bundle, git] = await Promise.all([createBundle(distDir), gitSha === void 0 ? readGitInfo(appletRoot) : Promise.resolve({
2401
+ gitDirty: false,
2402
+ gitSha
2403
+ })]);
2505
2404
  return fetchWithOrgAuth(manifest.org, (instanceUrl, accessToken) => {
2506
2405
  const body = releaseForm(manifest, bundle);
2507
2406
  body.set("gitDirty", String(git.gitDirty));
2508
2407
  if (git.gitSha !== void 0) body.set("gitSha", git.gitSha);
2509
2408
  if (sourceHash !== void 0) body.set("sourceHash", sourceHash);
2510
- return fetcher(`${instanceUrl}/api/v1/applets/${manifest.code}/releases`, {
2409
+ return fetcher(`${instanceUrl}/api/applet/v1/applets/${manifest.code}/releases`, {
2511
2410
  method: "POST",
2512
2411
  headers: { Authorization: `Bearer ${accessToken}` },
2513
2412
  body
@@ -2521,23 +2420,35 @@ async function deployWithGitHubActions(context, appletRoot, distDir, manifest, s
2521
2420
  const body = releaseForm(manifest, bundle);
2522
2421
  body.set("source_directory", sourceDirectory);
2523
2422
  if (sourceHash !== void 0) body.set("source_hash", sourceHash);
2524
- return fetcher(`${instanceUrl}/api/ci/v1/applets/${manifest.code}/releases`, {
2423
+ return fetcher(`${instanceUrl}/api/applet/v1/ci/applets/${manifest.code}/releases`, {
2525
2424
  method: "POST",
2526
2425
  headers: { Authorization: `Bearer ${accessToken}` },
2527
2426
  body
2528
2427
  });
2529
2428
  });
2530
2429
  }
2531
- async function deployApplet(appletRoot, options, logPrefix = "", sourceHash) {
2532
- const github = githubActionsContext();
2533
- sourceHash ??= (await computeSourceHash([appletRoot], github !== void 0)).get(appletRoot);
2430
+ async function buildRelease(appletRoot, options) {
2534
2431
  if (options.dist === void 0) await buildApplet(appletRoot);
2535
2432
  const distDir = resolve(appletRoot, options.dist ?? ".hitch/dist");
2536
- const manifest = await readManifest(distDir);
2537
- const response = github === void 0 ? await deployWithOrgAuth(appletRoot, distDir, manifest, sourceHash) : await deployWithGitHubActions(github, appletRoot, distDir, manifest, sourceHash);
2538
- if (!response.ok) throw await hitchResponseError(response, "Deploy failed");
2433
+ return {
2434
+ distDir,
2435
+ manifest: await readManifest(distDir)
2436
+ };
2437
+ }
2438
+ async function uploadRelease(appletRoot, distDir, manifest, stagedSha, logPrefix = "", sourceHash) {
2439
+ const github = githubActionsContext();
2440
+ sourceHash ??= (await computeSourceHash([appletRoot], github !== void 0)).get(appletRoot);
2441
+ const response = github === void 0 ? await deployWithOrgAuth(appletRoot, distDir, manifest, sourceHash, stagedSha) : await deployWithGitHubActions(github, appletRoot, distDir, manifest, sourceHash);
2442
+ if (!response.ok) {
2443
+ const body = await response.clone().json().catch(() => null);
2444
+ const code = body !== null && typeof body === "object" && "code" in body && typeof body.code === "string" ? body.code : void 0;
2445
+ const message = deployErrorMessage(code);
2446
+ if (message !== void 0) throw new Error(message);
2447
+ throw await hitchResponseError(response, "Deploy failed");
2448
+ }
2539
2449
  const result = await response.json();
2540
2450
  console.log(`${logPrefix}Deployed release ${result.data.id} (${result.promoted ? "promoted" : "not promoted"}).`);
2451
+ if (stagedSha !== void 0 && result.promoted) console.log(`${logPrefix}main is now ${stagedSha.slice(0, 7)}.`);
2541
2452
  if (result.changeset_id !== void 0) console.log(`${logPrefix}The release goes live when changeset ${result.changeset_id} applies.`);
2542
2453
  if (result.warnings?.length) {
2543
2454
  for (const warning of result.warnings) console.warn(`${logPrefix}Warning: ${warning.message}`);
@@ -2546,6 +2457,15 @@ async function deployApplet(appletRoot, options, logPrefix = "", sourceHash) {
2546
2457
  if (result.unset_variables?.length) console.warn(`${logPrefix}Warning: declared variables not set: ${result.unset_variables.join(", ")}. Set them with applet variables set.`);
2547
2458
  return result;
2548
2459
  }
2460
+ async function deployApplet(appletRoot, options, logPrefix = "", sourceHash, stagedSha) {
2461
+ const github = githubActionsContext();
2462
+ sourceHash ??= (await computeSourceHash([appletRoot], github !== void 0)).get(appletRoot);
2463
+ const { distDir, manifest } = await buildRelease(appletRoot, options);
2464
+ if (stagedSha !== void 0 && manifest.code !== basename(appletRoot)) throw new Error(`The built applet code ${manifest.code} must match its folder ${basename(appletRoot)}.`);
2465
+ if (stagedSha !== void 0 && manifest.org !== readWorkspaceConfig(findWorkspaceRoot(appletRoot) ?? dirname(dirname(appletRoot)))?.org) throw new Error("The built applet organization must match hitch.config.ts.");
2466
+ if (stagedSha !== void 0) await pushStagedCommit(findWorkspaceRoot(appletRoot) ?? dirname(dirname(appletRoot)), manifest.org, stagedSha);
2467
+ return uploadRelease(appletRoot, distDir, manifest, stagedSha, logPrefix, sourceHash);
2468
+ }
2549
2469
  function buildConcurrency() {
2550
2470
  const value = process.env.APPLET_BUILD_CONCURRENCY;
2551
2471
  if (value === void 0) return Infinity;
@@ -2568,15 +2488,20 @@ function semaphore(limit) {
2568
2488
  }
2569
2489
  };
2570
2490
  }
2571
- async function workspaceAppletRoots(workspaceRoot) {
2491
+ async function workspaceAppletRoots(workspaceRoot, allowEmpty = false) {
2572
2492
  const appletsDir = resolve(workspaceRoot, "applets");
2573
2493
  const roots = (await readdir(appletsDir, { withFileTypes: true }).catch((error) => {
2574
2494
  if (isErrno(error, "ENOENT")) return [];
2575
2495
  throw error;
2576
2496
  })).filter((entry) => entry.isDirectory()).map((entry) => resolve(appletsDir, entry.name)).filter((root) => existsSync(resolve(root, "applet.manifest.ts"))).sort();
2577
- if (roots.length === 0) throw new Error(`No applets were found under ${appletsDir}.`);
2497
+ if (!allowEmpty && roots.length === 0) throw new Error(`No applets were found under ${appletsDir}.`);
2578
2498
  return roots;
2579
2499
  }
2500
+ function validateSingleApplet(roots) {
2501
+ if (roots.length === 1) return;
2502
+ const names = roots.map((root) => basename(root)).join(", ");
2503
+ throw new Error(`Hitch git keeps one applet per repo. This workspace has ${roots.length} applets: ${names}. Move each applet into its own workspace.`);
2504
+ }
2580
2505
  async function computeSourceHash(appletRoots, required) {
2581
2506
  try {
2582
2507
  return await sourceHashes(appletRoots);
@@ -2604,9 +2529,70 @@ async function ciDeployDecisions(github, appletRoots, hashes) {
2604
2529
  }];
2605
2530
  }));
2606
2531
  }
2532
+ async function deployRootApplet(root, options, flagChecked = false) {
2533
+ const config = readWorkspaceConfig(root);
2534
+ if (!flagChecked && !await orgUsesHitchGit(config.org)) throw new Error(`Hitch git is not switched on for ${config.org}.`);
2535
+ await prepareAppletProject(root);
2536
+ const definition = await loadAppletSourceDefinition(root);
2537
+ const sha = await prepareGitDeploy(root, definition.code, config.org, options.message, options.dist !== void 0);
2538
+ const { distDir, manifest } = await buildRelease(root, options);
2539
+ if (manifest.code !== definition.code || manifest.org !== config.org) throw new Error("The built applet identity must match applet.manifest.ts.");
2540
+ await pushStagedCommit(root, manifest.org, sha);
2541
+ await uploadRelease(root, distDir, manifest, sha);
2542
+ }
2607
2543
  async function runDeploy(options) {
2608
2544
  const root = process.cwd();
2609
2545
  const github = githubActionsContext();
2546
+ if (process.env.GITHUB_ACTIONS !== "true") {
2547
+ const workspaceRoot = findWorkspaceRoot(root);
2548
+ const parent = workspaceRoot === void 0 ? findParentRoot(root) : void 0;
2549
+ if (parent !== void 0) {
2550
+ const failed = [];
2551
+ for (const child of await childApplets(parent)) try {
2552
+ const config = readWorkspaceConfig(child);
2553
+ if (!await orgUsesHitchGit(config.org)) throw new Error(`Hitch git is not switched on for ${config.org}.`);
2554
+ await refreshHitchMain(child, config.org, (await loadAppletSourceDefinition(child)).code);
2555
+ if (!await childHasChanges(child)) {
2556
+ console.log(`[${basename(child)}] Skipped: no changes.`);
2557
+ continue;
2558
+ }
2559
+ await deployRootApplet(child, options, true);
2560
+ console.log(`[${basename(child)}] Deployed.`);
2561
+ } catch (error) {
2562
+ failed.push(basename(child));
2563
+ console.error(`[${basename(child)}] ${error instanceof Error ? error.message : String(error)}`);
2564
+ }
2565
+ if (failed.length > 0) throw new WorkspaceDeployError(failed);
2566
+ return;
2567
+ }
2568
+ if (workspaceRoot === void 0) throw new Error("Run applet deploy in an applet, workspace or parent folder.");
2569
+ const config = readWorkspaceConfig(workspaceRoot);
2570
+ const enabled = isRootLayout(workspaceRoot) ? await orgUsesHitchGit(config.org) : await canCheckHitchGit() && await orgUsesHitchGit(config.org);
2571
+ if (isRootLayout(workspaceRoot)) {
2572
+ if (!enabled) throw new Error(`Hitch git is not switched on for ${config.org}.`);
2573
+ await deployRootApplet(workspaceRoot, options, true);
2574
+ return;
2575
+ }
2576
+ if (enabled) {
2577
+ const selected = findAppletRoot(root);
2578
+ const migrated = await migrateWorkspace(workspaceRoot, options.message);
2579
+ const roots = selected === void 0 ? migrated : migrated.filter((path) => migrated.length === 1 || basename(path) === basename(selected));
2580
+ const failed = [];
2581
+ for (const appletRoot of roots) try {
2582
+ await deployRootApplet(appletRoot, options, true);
2583
+ } catch (error) {
2584
+ failed.push(appletRoot);
2585
+ console.error(`[${basename(appletRoot)}] ${error instanceof Error ? error.message : String(error)}`);
2586
+ }
2587
+ if (failed.length > 0) throw new WorkspaceDeployError(failed);
2588
+ return;
2589
+ }
2590
+ if (root !== workspaceRoot && !existsSync(resolve(root, "applet.manifest.ts"))) throw new Error("Run applet deploy in an applet folder or in the workspace root.");
2591
+ if (root !== workspaceRoot) {
2592
+ await deployApplet(findAppletRoot(root), options);
2593
+ return;
2594
+ }
2595
+ }
2610
2596
  if (existsSync(resolve(root, "applet.manifest.ts"))) {
2611
2597
  await deployApplet(root, options);
2612
2598
  return;
@@ -2650,5 +2636,27 @@ async function runDeploy(options) {
2650
2636
  });
2651
2637
  if (failedApplets.length > 0) throw new WorkspaceDeployError(failedApplets);
2652
2638
  }
2653
- //#endregion
2654
- export { runDeploy };
2639
+ async function runRollback(releaseId) {
2640
+ const cwd = process.cwd();
2641
+ const workspaceRoot = findWorkspaceRoot(cwd);
2642
+ const config = workspaceRoot === void 0 ? void 0 : readWorkspaceConfig(workspaceRoot);
2643
+ if (config === void 0 || workspaceRoot === void 0) throw new Error("Run applet rollback in an applet folder or in the workspace root.");
2644
+ const roots = isRootLayout(workspaceRoot) ? [workspaceRoot] : await workspaceAppletRoots(workspaceRoot, true);
2645
+ validateSingleApplet(roots);
2646
+ const code = (await loadAppletSourceDefinition(roots[0])).code;
2647
+ const response = await fetchWithOrgAuth(config.org, (organizationUrl, accessToken) => globalThis.fetch(`${organizationUrl}/api/manage/v1/applets/${code}/releases/${encodeURIComponent(releaseId)}/promote`, {
2648
+ method: "POST",
2649
+ headers: {
2650
+ Authorization: `Bearer ${accessToken}`,
2651
+ "Content-Type": "application/json"
2652
+ },
2653
+ body: JSON.stringify({ rollback: true })
2654
+ }));
2655
+ if (!response.ok) throw await hitchResponseError(response, "Rollback failed");
2656
+ const result = await response.json();
2657
+ const release = result !== null && typeof result === "object" && "data" in result ? result.data : void 0;
2658
+ const sha = release !== null && typeof release === "object" && "git_sha" in release && typeof release.git_sha === "string" ? release.git_sha : void 0;
2659
+ if (sha === void 0) throw new Error("The rollback response has no commit id.");
2660
+ console.log(`Rolled back ${code} to release ${releaseId} (commit ${sha.slice(0, 7)}). main moved back. Your local branch still has the newer commits: revert or reset them before the next deploy.`);
2661
+ }
2662
+ export { runDeploy, runRollback };