@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.
- package/dist/_internal/client.d.ts +0 -2
- package/dist/_internal/client.js +3 -5
- package/dist/_internal/log-context.d.ts +0 -2
- package/dist/_internal/log-context.js +1 -2
- package/dist/_internal/server.d.ts +2 -10
- package/dist/_internal/server.js +9 -14
- package/dist/applet.js +64 -23
- package/dist/auth-DuMRqSGe.js +49 -0
- package/dist/{batch-_ZjAg-Kk.js → batch-CiLZ177G.js} +3 -4
- package/dist/build-C7hi2yg4.js +1 -0
- package/dist/{build-DkKTiIu7.js → build-FAQSHJgm.js} +4 -3
- package/dist/{ci-B5-mH-YW.js → ci-oWlUJKm9.js} +10 -6
- package/dist/client/hitch/client.d.ts +1 -1
- package/dist/client/hitch/client.js +1 -2
- package/dist/client/hitch/phone.d.ts +1 -1
- package/dist/client/hitch/phone.js +1 -2
- package/dist/client/hitch.d.ts +2 -2
- package/dist/client/hitch.js +2 -2
- package/dist/client/react/markdown-editor.d.ts +1 -1
- package/dist/client/react/markdown-editor.js +1 -2
- package/dist/client/react/markdown.d.ts +1 -1
- package/dist/client/react/markdown.js +1 -2
- package/dist/client/react.d.ts +2 -2
- package/dist/client/react.js +2 -2
- package/dist/client.d.ts +2 -4
- package/dist/client.js +3 -5
- package/dist/{contract-CJv-n1l3.d.ts → contract-CUc0B2rl.d.ts} +1 -3
- package/dist/{contract-BeKz1Qcs.js → contract-D9LCNGjD.js} +1 -2
- package/dist/create-BJqLT8Uq.d.ts +68 -0
- package/dist/{deploy-DODTE8ri.js → deploy-BM55ZoSp.js} +160 -152
- package/dist/{device-BgIfytaR.js → device-CZWWckCq.js} +54 -34
- package/dist/{email-protocol-B9u_dh2p.d.ts → email-protocol-CEqzASSx.d.ts} +0 -6
- package/dist/{generate-8yyxKRSz.js → generate-48pqFh5M.js} +57 -39
- package/dist/generate-BYK4aNud.js +1 -0
- package/dist/generated-agents-BUnJ0FQA.js +215 -0
- package/dist/git-credential-CU7-Erzs.js +24 -0
- package/dist/git-deploy-C12nMNB6.js +290 -0
- package/dist/git-deploy-CNz6mxiF.js +1 -0
- package/dist/git-migration-CIq-sN61.js +629 -0
- package/dist/git-safety-Ck3X7jvA.js +13 -0
- package/dist/{headers-CeRX-Xji.js → headers-BcEMIVCo.js} +1 -2
- package/dist/hitch-client-D33JOEOi.d.ts +22 -0
- package/dist/{hitch-client-Cw-WZ_8v.js → hitch-client-Dph_kzDd.js} +5 -7
- package/dist/{hitch-file-url-BPKj9zVG.js → hitch-file-url--AMjDOzP.js} +1 -2
- package/dist/index.d.ts +8 -15
- package/dist/index.js +32 -37
- package/dist/{init-DT0faD-q.js → init-Bb6WT8UB.js} +70 -18
- package/dist/{lazy-client-CwIzYAoE.js → lazy-client--QCL0wiu.js} +1 -2
- package/dist/{load-config-BYrBjPlr.js → load-config-Cffvj-aM.js} +27 -26
- package/dist/{log-context-DWznGjfz.js → log-context-BepwdjrR.js} +1 -2
- package/dist/login-BWZKo7Ui.js +21 -0
- package/dist/{logs-CEIikWzV.js → logs-glCVHI-8.js} +6 -6
- package/dist/{manifest-BBHD_EY9.d.ts → manifest-CpghlaJc.d.ts} +6 -7
- package/dist/manifest-patterns-BfxqImlp.js +4 -0
- package/dist/{markdown-CwlqzBtP.js → markdown-BA_XzFxq.js} +2 -3
- package/dist/{markdown-DSHOQIOb.d.ts → markdown-BXt65dDo.d.ts} +1 -3
- package/dist/{markdown-editor-BmEaBzd7.d.ts → markdown-editor-CB_nWLzj.d.ts} +1 -5
- package/dist/{markdown-editor-C5mLHGqu.js → markdown-editor-CaUuphfc.js} +3 -5
- package/dist/parent-D52Kxp8U.js +1 -0
- package/dist/parent-Zx8Eg1Ki.js +75 -0
- package/dist/{project-CWVwic2C.js → project-DZGk765E.js} +74 -58
- package/dist/{prompt-ChS-grYO.js → prompt-CW98R-Un.js} +1 -2
- package/dist/{query-cache-CXmAyLv3.js → query-cache-DQJy45RT.js} +1 -2
- package/dist/{query-utils-zz9pVjgp.d.ts → query-utils-okxIoKM3.d.ts} +0 -2
- package/dist/{schedules-B7xNl9oy.js → schedules-CSUb84e2.js} +5 -5
- package/dist/server.d.ts +6 -14
- package/dist/server.js +17 -20
- package/dist/source-hash-BbvtRaus.js +107 -0
- package/dist/store-E5NhITHl.js +448 -0
- package/dist/{upload-D_kkmne_.d.ts → upload-DXZyjZSS.d.ts} +6 -10
- package/dist/{upload-DRbVhuDm.js → upload-DtMavo8Q.js} +4 -6
- package/dist/{use-phone-ug4B5gQp.js → use-phone-CB_idmrz.js} +9 -13
- package/dist/{use-phone-M7c_HsB7.d.ts → use-phone-DBAkasPq.d.ts} +0 -4
- package/dist/{variables-DCbLJBr0.js → variables-CgZstC7I.js} +7 -8
- package/dist/vite.d.ts +1 -3
- package/dist/vite.js +42 -51
- package/dist/{workflow-DurM6Fwx.d.ts → workflow-BnBrJIzu.d.ts} +0 -2
- package/dist/{workflow-engine-BOTzURKM.js → workflow-engine-CyyaVENo.js} +2 -4
- package/dist/{workflow-CTo2kZF1.js → workflow-l2SlVePB.js} +2 -4
- package/dist/workspace-CtIKSgMD.js +76 -0
- package/package.json +6 -5
- package/scaffold/.agents/skills/hitch-applets/SKILL.md +28 -10
- package/scaffold/.agents/skills/hitch-applets/references/files.md +2 -2
- package/scaffold/.agents/skills/hitch-applets/references/manifest.md +8 -6
- package/scaffold/.agents/skills/hitch-applets/references/performance.md +2 -2
- package/scaffold/.agents/skills/hitch-applets/references/records.md +24 -9
- package/scaffold/.agents/skills/hitch-cli/SKILL.md +52 -43
- package/scaffold/AGENTS.md +6 -0
- package/dist/auth-D3CrCtZq.js +0 -21
- package/dist/batch-Qa4B4-Yp.d.ts +0 -30
- package/dist/build-DpkWOvd2.js +0 -2
- package/dist/generate-Df29-UJm.js +0 -2
- package/dist/hitch-client--qZVa2KM.d.ts +0 -23
- package/dist/login-CceGvlMi.js +0 -14
- package/dist/store-B8N_8JIN.js +0 -196
- package/dist/workspace-8yqXsvce.js +0 -31
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useEffect, useSyncExternalStore } from "react";
|
|
2
|
-
|
|
2
|
+
// src/telephony/api.ts
|
|
3
3
|
var TelephonyApiError = class extends Error {
|
|
4
4
|
code;
|
|
5
5
|
status;
|
|
@@ -14,7 +14,7 @@ const createTelephonyApi = (baseUrl = location.origin) => {
|
|
|
14
14
|
const request = async (path, init) => {
|
|
15
15
|
const headers = new Headers(init?.headers);
|
|
16
16
|
if (init?.body) headers.set("content-type", "application/json");
|
|
17
|
-
const response = await fetch(`${baseUrl.replace(/\/$/, "")}/api
|
|
17
|
+
const response = await fetch(`${baseUrl.replace(/\/$/, "")}/api/${path}`, {
|
|
18
18
|
credentials: "include",
|
|
19
19
|
...init,
|
|
20
20
|
headers
|
|
@@ -28,29 +28,28 @@ const createTelephonyApi = (baseUrl = location.origin) => {
|
|
|
28
28
|
return response.json();
|
|
29
29
|
};
|
|
30
30
|
return {
|
|
31
|
-
token: (deviceKey, acceptsCalls) => request("voice/token", {
|
|
31
|
+
token: (deviceKey, acceptsCalls) => request("applet/v1/telephony/voice/token", {
|
|
32
32
|
method: "POST",
|
|
33
33
|
body: JSON.stringify({
|
|
34
34
|
deviceKey,
|
|
35
35
|
acceptsCalls
|
|
36
36
|
})
|
|
37
37
|
}),
|
|
38
|
-
startCall: (numberId, to) => request("calls", {
|
|
38
|
+
startCall: (numberId, to) => request("applet/v1/telephony/calls", {
|
|
39
39
|
method: "POST",
|
|
40
40
|
body: JSON.stringify({
|
|
41
41
|
numberId,
|
|
42
42
|
to
|
|
43
43
|
})
|
|
44
44
|
}),
|
|
45
|
-
getCall: (callId) => request(`calls/${encodeURIComponent(callId)}`),
|
|
46
|
-
uploadUrl: (callId) => request(`calls/${encodeURIComponent(callId)}/recording`, {
|
|
45
|
+
getCall: (callId) => request(`resource/v1/telephony/calls/${encodeURIComponent(callId)}`),
|
|
46
|
+
uploadUrl: (callId) => request(`applet/v1/telephony/calls/${encodeURIComponent(callId)}/recording`, {
|
|
47
47
|
method: "POST",
|
|
48
48
|
body: "{}"
|
|
49
49
|
})
|
|
50
50
|
};
|
|
51
51
|
};
|
|
52
|
-
|
|
53
|
-
//#region src/telephony/recorder.ts
|
|
52
|
+
// src/telephony/recorder.ts
|
|
54
53
|
const DB_NAME = "hitch-telephony";
|
|
55
54
|
const STORE = "recordings";
|
|
56
55
|
const openDatabase = () => new Promise((resolve, reject) => {
|
|
@@ -162,8 +161,7 @@ const startRecording = async (callId, call, api, onError) => {
|
|
|
162
161
|
throw error;
|
|
163
162
|
}
|
|
164
163
|
};
|
|
165
|
-
|
|
166
|
-
//#region src/telephony/phone.ts
|
|
164
|
+
// src/telephony/phone.ts
|
|
167
165
|
const DEVICE_KEY = "hitch:telephony:device";
|
|
168
166
|
let singleton;
|
|
169
167
|
var Phone = class {
|
|
@@ -708,8 +706,7 @@ var Phone = class {
|
|
|
708
706
|
}
|
|
709
707
|
};
|
|
710
708
|
const createPhone = (options = {}) => singleton ??= new Phone(options);
|
|
711
|
-
|
|
712
|
-
//#region src/telephony/use-phone.ts
|
|
709
|
+
// src/telephony/use-phone.ts
|
|
713
710
|
const usePhone = () => {
|
|
714
711
|
const phone = createPhone();
|
|
715
712
|
const state = useSyncExternalStore(phone.subscribe, phone.getSnapshot);
|
|
@@ -722,5 +719,4 @@ const usePhone = () => {
|
|
|
722
719
|
active: phone.active
|
|
723
720
|
};
|
|
724
721
|
};
|
|
725
|
-
//#endregion
|
|
726
722
|
export { createPhone as n, usePhone as t };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//#region src/telephony/phone.d.ts
|
|
2
1
|
type PhoneState = {
|
|
3
2
|
owner: boolean;
|
|
4
3
|
status: "off" | "connecting" | "ready" | "error";
|
|
@@ -86,12 +85,9 @@ declare const createPhone: (options?: {
|
|
|
86
85
|
baseUrl?: string;
|
|
87
86
|
acceptsCalls?: boolean;
|
|
88
87
|
}) => Phone;
|
|
89
|
-
//#endregion
|
|
90
|
-
//#region src/telephony/use-phone.d.ts
|
|
91
88
|
declare const usePhone: () => {
|
|
92
89
|
state: PhoneState;
|
|
93
90
|
call: Phone["call"];
|
|
94
91
|
active: Phone["active"];
|
|
95
92
|
};
|
|
96
|
-
//#endregion
|
|
97
93
|
export { createPhone as i, Phone as n, PhoneState as r, usePhone as t };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as loadAppletConfig } from "./load-config-
|
|
3
|
-
import { t as question } from "./prompt-
|
|
1
|
+
import { n as fetchWithOrgAuth } from "./auth-DuMRqSGe.js";
|
|
2
|
+
import { t as loadAppletConfig } from "./load-config-Cffvj-aM.js";
|
|
3
|
+
import { t as question } from "./prompt-CW98R-Un.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
|
|
5
|
+
// src/variables.ts
|
|
6
6
|
const variableRowSchema = z.object({
|
|
7
7
|
key: z.string(),
|
|
8
8
|
secret: z.boolean(),
|
|
@@ -57,7 +57,7 @@ async function runVariablesSet(options) {
|
|
|
57
57
|
const manifest = await loadAppletConfig(process.cwd());
|
|
58
58
|
await confirmLiveChange(manifest.code, options);
|
|
59
59
|
const fetcher = globalThis.fetch;
|
|
60
|
-
const response = await fetchWithOrgAuth(manifest.org, (instanceUrl, accessToken) => fetcher(`${instanceUrl}/api/v1/applets/${encodeURIComponent(manifest.code)}/variables/${encodeURIComponent(options.key)}`, {
|
|
60
|
+
const response = await fetchWithOrgAuth(manifest.org, (instanceUrl, accessToken) => fetcher(`${instanceUrl}/api/manage/v1/applets/${encodeURIComponent(manifest.code)}/variables/${encodeURIComponent(options.key)}`, {
|
|
61
61
|
method: "PUT",
|
|
62
62
|
headers: {
|
|
63
63
|
Authorization: `Bearer ${accessToken}`,
|
|
@@ -77,7 +77,7 @@ async function runVariablesSet(options) {
|
|
|
77
77
|
}
|
|
78
78
|
async function runVariablesList() {
|
|
79
79
|
const fetcher = globalThis.fetch;
|
|
80
|
-
const { code, response } = await requestForApplet((instanceUrl, accessToken, appletCode) => fetcher(`${instanceUrl}/api/v1/applets/${encodeURIComponent(appletCode)}/variables`, { headers: { Authorization: `Bearer ${accessToken}` } }));
|
|
80
|
+
const { code, response } = await requestForApplet((instanceUrl, accessToken, appletCode) => fetcher(`${instanceUrl}/api/manage/v1/applets/${encodeURIComponent(appletCode)}/variables`, { headers: { Authorization: `Bearer ${accessToken}` } }));
|
|
81
81
|
if (!response.ok) {
|
|
82
82
|
const { code: errorCode, message } = await readErrorDetails(response);
|
|
83
83
|
throw variablesError(response.status, errorCode, message);
|
|
@@ -93,7 +93,7 @@ async function runVariablesDelete(options) {
|
|
|
93
93
|
const manifest = await loadAppletConfig(process.cwd());
|
|
94
94
|
await confirmLiveChange(manifest.code, options);
|
|
95
95
|
const fetcher = globalThis.fetch;
|
|
96
|
-
const response = await fetchWithOrgAuth(manifest.org, (instanceUrl, accessToken) => fetcher(`${instanceUrl}/api/v1/applets/${encodeURIComponent(manifest.code)}/variables/${encodeURIComponent(options.key)}`, {
|
|
96
|
+
const response = await fetchWithOrgAuth(manifest.org, (instanceUrl, accessToken) => fetcher(`${instanceUrl}/api/manage/v1/applets/${encodeURIComponent(manifest.code)}/variables/${encodeURIComponent(options.key)}`, {
|
|
97
97
|
method: "DELETE",
|
|
98
98
|
headers: { Authorization: `Bearer ${accessToken}` }
|
|
99
99
|
}));
|
|
@@ -104,5 +104,4 @@ async function runVariablesDelete(options) {
|
|
|
104
104
|
}
|
|
105
105
|
console.log(`Deleted ${options.key} from applet "${manifest.code}".`);
|
|
106
106
|
}
|
|
107
|
-
//#endregion
|
|
108
107
|
export { runVariablesDelete, runVariablesList, runVariablesSet };
|
package/dist/vite.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { o as RegisteredAppletSourceDefinition } from "./manifest-
|
|
1
|
+
import { o as RegisteredAppletSourceDefinition } from "./manifest-CpghlaJc.js";
|
|
2
2
|
import { PluginOption } from "vite";
|
|
3
|
-
//#region src/vite.d.ts
|
|
4
3
|
declare function applet<const M extends RegisteredAppletSourceDefinition>(sourceDefinition: M): PluginOption[];
|
|
5
|
-
//#endregion
|
|
6
4
|
export { applet };
|
package/dist/vite.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
|
-
import { t as pruneContract } from "./contract-
|
|
2
|
-
import { a as openQueryCacheDatabase } from "./query-cache-
|
|
3
|
-
import { d as HITCH_SESSION_HEADER, f as HITCH_USER_HEADER } from "./headers-
|
|
4
|
-
import { a as workflowOutcomeSchema, n as runWorkflowJournal } from "./workflow-engine-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { t as pruneContract } from "./contract-D9LCNGjD.js";
|
|
2
|
+
import { a as openQueryCacheDatabase } from "./query-cache-DQJy45RT.js";
|
|
3
|
+
import { d as HITCH_SESSION_HEADER, f as HITCH_USER_HEADER } from "./headers-BcEMIVCo.js";
|
|
4
|
+
import { a as workflowOutcomeSchema, n as runWorkflowJournal } from "./workflow-engine-CyyaVENo.js";
|
|
5
|
+
import { r as writeGeneratedAgents } from "./generated-agents-BUnJ0FQA.js";
|
|
6
|
+
import { d as rejectEnvironmentKey, i as bearerToken, l as organizationInstanceUrl, m as resolveInstanceUrl, p as resolveAuthForOrg } from "./store-E5NhITHl.js";
|
|
7
|
+
import { c as validateRootManifest, o as isRootLayout } from "./workspace-CtIKSgMD.js";
|
|
8
|
+
import { a as appletSourceDefinitionSchema, i as appletReleaseManifest, o as resolveWorkspaceOrg, r as appletMountPath } from "./load-config-Cffvj-aM.js";
|
|
9
|
+
import { a as writeRegisterDeclaration, c as writeAppletRoot, d as writeServerEntry, i as syncContract, l as writeClientEntry, n as routesModuleSource, u as writeManifestGen } from "./generate-48pqFh5M.js";
|
|
10
|
+
import { t as APPLET_CODE_PATTERN } from "./manifest-patterns-BfxqImlp.js";
|
|
8
11
|
import { z } from "zod";
|
|
9
12
|
import { randomUUID } from "node:crypto";
|
|
13
|
+
import { pathToFileURL } from "node:url";
|
|
10
14
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
11
15
|
import { appendFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
12
|
-
import { createServer } from "node:http";
|
|
13
16
|
import { basename, dirname, relative, resolve } from "node:path";
|
|
14
|
-
import {
|
|
17
|
+
import { createServer } from "node:http";
|
|
15
18
|
import { cloudflare } from "@cloudflare/vite-plugin";
|
|
16
19
|
import optimizeLocales from "@react-aria/optimize-locales-plugin";
|
|
17
20
|
import { tanstackRouter } from "@tanstack/router-plugin/vite";
|
|
@@ -19,7 +22,7 @@ import react from "@vitejs/plugin-react";
|
|
|
19
22
|
import { normalizePath } from "vite";
|
|
20
23
|
import { Readable } from "node:stream";
|
|
21
24
|
import { pipeline } from "node:stream/promises";
|
|
22
|
-
|
|
25
|
+
// src/dev-proxy.ts
|
|
23
26
|
const REQUEST_DROP = /* @__PURE__ */ new Set([
|
|
24
27
|
"host",
|
|
25
28
|
"connection",
|
|
@@ -56,7 +59,8 @@ function createDevProxy(options) {
|
|
|
56
59
|
if (intercepted !== void 0) return intercepted;
|
|
57
60
|
const headers = new Headers(request.headers);
|
|
58
61
|
[...headers.keys()].filter((name) => REQUEST_DROP.has(name) || name.startsWith("x-hitch-")).forEach((name) => headers.delete(name));
|
|
59
|
-
|
|
62
|
+
const token = typeof options.token === "string" ? options.token : await options.token();
|
|
63
|
+
headers.set("authorization", `Bearer ${token}`);
|
|
60
64
|
const url = new URL(request.url);
|
|
61
65
|
const upstream = await globalThis.fetch(`${options.orgUrl}${url.pathname}${url.search}`, {
|
|
62
66
|
method: request.method,
|
|
@@ -112,8 +116,7 @@ async function serveDevProxy(request, response, handler) {
|
|
|
112
116
|
response.off("close", onClose);
|
|
113
117
|
}
|
|
114
118
|
}
|
|
115
|
-
|
|
116
|
-
//#region src/dev-workflows.ts
|
|
119
|
+
// src/dev-workflows.ts
|
|
117
120
|
const RUN_STATUSES = [
|
|
118
121
|
"in_progress",
|
|
119
122
|
"sleeping",
|
|
@@ -228,10 +231,10 @@ function createDevWorkflows(options) {
|
|
|
228
231
|
};
|
|
229
232
|
const handle = (request) => {
|
|
230
233
|
const url = new URL(request.url);
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
const
|
|
234
|
-
const startMatch =
|
|
234
|
+
const applet = `/applets/${encodeURIComponent(options.appletCode)}`;
|
|
235
|
+
const startPrefix = `/api/applet/v1${applet}/workflows/`;
|
|
236
|
+
const runsPath = `/api/applet/v1${applet}/workflow-runs`;
|
|
237
|
+
const startMatch = url.pathname.startsWith(startPrefix) ? /^([^/]+)\/runs$/.exec(url.pathname.slice(startPrefix.length)) : null;
|
|
235
238
|
if (request.method === "POST" && startMatch !== null) return (async () => {
|
|
236
239
|
let body;
|
|
237
240
|
try {
|
|
@@ -257,27 +260,23 @@ function createDevWorkflows(options) {
|
|
|
257
260
|
status: "in_progress"
|
|
258
261
|
} }, { status: 201 });
|
|
259
262
|
})();
|
|
260
|
-
const getMatch =
|
|
263
|
+
const getMatch = url.pathname.startsWith(`${runsPath}/`) ? /^([^/]+)$/.exec(url.pathname.slice(runsPath.length + 1)) : null;
|
|
261
264
|
if (request.method === "GET" && getMatch !== null) {
|
|
262
|
-
let workflow;
|
|
263
265
|
let id;
|
|
264
266
|
try {
|
|
265
|
-
|
|
266
|
-
id = decodeURIComponent(getMatch[2]);
|
|
267
|
+
id = decodeURIComponent(getMatch[1]);
|
|
267
268
|
} catch (error) {
|
|
268
269
|
if (error instanceof URIError) return Promise.resolve(badRequest(error.message));
|
|
269
270
|
throw error;
|
|
270
271
|
}
|
|
271
|
-
const codeError = workflowCodeError(workflow);
|
|
272
|
-
if (codeError !== void 0) return Promise.resolve(codeError);
|
|
273
272
|
if (!UUID_PATTERN.test(id)) return Promise.resolve(badRequest("The run id must be a uuid."));
|
|
274
273
|
const run = runs.get(id);
|
|
275
|
-
return Promise.resolve(run
|
|
274
|
+
return Promise.resolve(run ? Response.json({ data: run }) : Response.json({
|
|
276
275
|
code: "workflow_run_not_found",
|
|
277
276
|
message: "The workflow run does not exist."
|
|
278
277
|
}, { status: 404 }));
|
|
279
278
|
}
|
|
280
|
-
if (request.method === "GET" &&
|
|
279
|
+
if (request.method === "GET" && url.pathname === runsPath) {
|
|
281
280
|
const status = url.searchParams.get("status");
|
|
282
281
|
const limitValue = url.searchParams.get("limit");
|
|
283
282
|
const limit = limitValue === null ? 50 : Number(limitValue);
|
|
@@ -295,8 +294,7 @@ function createDevWorkflows(options) {
|
|
|
295
294
|
stop: () => controller.abort()
|
|
296
295
|
};
|
|
297
296
|
}
|
|
298
|
-
|
|
299
|
-
//#region src/lazy-client-react.ts
|
|
297
|
+
// src/lazy-client-react.ts
|
|
300
298
|
const CLIENT_REACT = "@hitch42/applet/client/react";
|
|
301
299
|
const lazyClientReact = {
|
|
302
300
|
name: "hitch-lazy-client-react",
|
|
@@ -307,8 +305,7 @@ const lazyClientReact = {
|
|
|
307
305
|
return this.resolve(`${CLIENT_REACT}?lazy`, importer, { skipSelf: true });
|
|
308
306
|
}
|
|
309
307
|
};
|
|
310
|
-
|
|
311
|
-
//#region src/hitch/me-schemas.ts
|
|
308
|
+
// src/hitch/me-schemas.ts
|
|
312
309
|
const personSchema = z.object({
|
|
313
310
|
id: z.uuid(),
|
|
314
311
|
firstName: z.string(),
|
|
@@ -332,8 +329,7 @@ const meSchema = z.object({
|
|
|
332
329
|
}).nullable(),
|
|
333
330
|
multiOrg: z.boolean()
|
|
334
331
|
});
|
|
335
|
-
|
|
336
|
-
//#region src/vite.ts
|
|
332
|
+
// src/vite.ts
|
|
337
333
|
const APPLET_COMPATIBILITY_DATE = "2026-07-14";
|
|
338
334
|
const APPLET_COMPATIBILITY_FLAGS = ["nodejs_compat"];
|
|
339
335
|
let activeDevListener;
|
|
@@ -565,14 +561,10 @@ function clientBootstrapScript(parentOrigin, appletCode, cacheQueries) {
|
|
|
565
561
|
}
|
|
566
562
|
function applet(sourceDefinition) {
|
|
567
563
|
const parsedSourceDefinition = appletSourceDefinitionSchema.safeParse(sourceDefinition);
|
|
568
|
-
if (!parsedSourceDefinition.success) {
|
|
569
|
-
|
|
570
|
-
const orgMessage = typeof raw === "object" && raw !== null && "org" in raw ? " org now lives in hitch.config.ts, not in applet.manifest.ts." : "";
|
|
571
|
-
throw new Error(`applet(): ${parsedSourceDefinition.error.message}${orgMessage}`);
|
|
572
|
-
}
|
|
573
|
-
const { dependencies: _dependencies, devDependencies: _devDependencies, ...definition } = parsedSourceDefinition.data;
|
|
564
|
+
if (!parsedSourceDefinition.success) throw new Error(`applet(): ${parsedSourceDefinition.error.message}`);
|
|
565
|
+
const { dependencies: _dependencies, devDependencies: _devDependencies, sdk: _sdk, org: _org, ...definition } = parsedSourceDefinition.data;
|
|
574
566
|
const parsedDefinition = { data: definition };
|
|
575
|
-
const mountPath = definition
|
|
567
|
+
const mountPath = appletMountPath(definition);
|
|
576
568
|
let appletConfig;
|
|
577
569
|
let buildRootOutDir;
|
|
578
570
|
let clearedOutDir = false;
|
|
@@ -597,7 +589,8 @@ function applet(sourceDefinition) {
|
|
|
597
589
|
const resolvedRoot = resolve(root);
|
|
598
590
|
if (appletConfig?.root === resolvedRoot) return appletConfig;
|
|
599
591
|
const directoryCode = basename(resolvedRoot);
|
|
600
|
-
if (directoryCode !== parsedDefinition.data.code) throw new Error(`Applet directory "${directoryCode}" does not match code "${parsedDefinition.data.code}". Rename the directory or change the code.`);
|
|
592
|
+
if (!isRootLayout(resolvedRoot) && directoryCode !== parsedDefinition.data.code) throw new Error(`Applet directory "${directoryCode}" does not match code "${parsedDefinition.data.code}". Rename the directory or change the code.`);
|
|
593
|
+
if (isRootLayout(resolvedRoot)) validateRootManifest(sourceDefinition);
|
|
601
594
|
const org = resolveWorkspaceOrg(resolvedRoot);
|
|
602
595
|
const routesDirectory = resolve(resolvedRoot, "src/client/routes");
|
|
603
596
|
const hasClient = existsSync(routesDirectory);
|
|
@@ -611,10 +604,7 @@ function applet(sourceDefinition) {
|
|
|
611
604
|
if (hasClient && !existsSync(indexHtml)) throw new Error(`Missing index.html at ${indexHtml}. Create it with <div id="root"></div> and <script type="module" src="/.hitch/entry.gen.tsx"><\/script>.`);
|
|
612
605
|
appletConfig = {
|
|
613
606
|
root: resolvedRoot,
|
|
614
|
-
manifest:
|
|
615
|
-
org,
|
|
616
|
-
...parsedDefinition.data
|
|
617
|
-
}),
|
|
607
|
+
manifest: appletReleaseManifest(parsedSourceDefinition.data, org),
|
|
618
608
|
routesDirectory,
|
|
619
609
|
hasClient,
|
|
620
610
|
hasAuthorRoot: hasClient && existsSync(resolve(routesDirectory, "__root.tsx")),
|
|
@@ -630,10 +620,7 @@ function applet(sourceDefinition) {
|
|
|
630
620
|
};
|
|
631
621
|
let apiManifest;
|
|
632
622
|
const callerRoot = resolve(".");
|
|
633
|
-
if (basename(callerRoot) === parsedDefinition.data.code && basename(resolve(callerRoot, "..")) === "applets") apiManifest =
|
|
634
|
-
org: resolveWorkspaceOrg(callerRoot),
|
|
635
|
-
...parsedDefinition.data
|
|
636
|
-
});
|
|
623
|
+
if (basename(callerRoot) === parsedDefinition.data.code && (basename(resolve(callerRoot, "..")) === "applets" || isRootLayout(callerRoot))) apiManifest = appletReleaseManifest(parsedSourceDefinition.data, resolveWorkspaceOrg(callerRoot));
|
|
637
624
|
const clsxFromCn = {
|
|
638
625
|
name: "hitch-clsx",
|
|
639
626
|
resolveId: (id) => id === "clsx" ? "\0hitch:clsx" : void 0,
|
|
@@ -650,6 +637,7 @@ function applet(sourceDefinition) {
|
|
|
650
637
|
async config(config, environment) {
|
|
651
638
|
buildRoutes = environment.command === "build" && environment.mode !== "test";
|
|
652
639
|
const { root, manifest, hasClient, hasAuthorRoot, hasServer, hasRouter } = resolveAppletConfig(config.root ?? resolve("."));
|
|
640
|
+
if (isRootLayout(root)) await writeGeneratedAgents(root);
|
|
653
641
|
apiManifest = manifest;
|
|
654
642
|
buildRootOutDir = resolve(root, config.build?.outDir ?? "dist");
|
|
655
643
|
if (environment.command === "build" && !clearedOutDir) {
|
|
@@ -682,14 +670,18 @@ function applet(sourceDefinition) {
|
|
|
682
670
|
const auth = await resolveAuthForOrg(instanceUrl, manifest.org);
|
|
683
671
|
if (auth === void 0) throw new Error("Not logged in. Run applet login.");
|
|
684
672
|
const token = bearerToken(auth);
|
|
685
|
-
const meResponse = await globalThis.fetch(`${orgUrl}/api/v1
|
|
673
|
+
const meResponse = await globalThis.fetch(`${orgUrl}/api/me/v1`, { headers: { authorization: `Bearer ${token}` } });
|
|
686
674
|
rejectEnvironmentKey(meResponse, auth);
|
|
687
675
|
if (meResponse.status === 401) throw new Error("Your login expired. Run applet login.");
|
|
688
|
-
if (!meResponse.ok) throw new Error(`Hitch returned ${meResponse.status} for /api/v1
|
|
676
|
+
if (!meResponse.ok) throw new Error(`Hitch returned ${meResponse.status} for /api/me/v1.`);
|
|
689
677
|
const { person } = meSchema.parse(await meResponse.json());
|
|
690
678
|
const proxy = createDevProxy({
|
|
691
679
|
orgUrl,
|
|
692
|
-
token
|
|
680
|
+
token: async () => {
|
|
681
|
+
const current = await resolveAuthForOrg(instanceUrl, manifest.org);
|
|
682
|
+
if (current === void 0) throw new Error("Not logged in. Run applet login.");
|
|
683
|
+
return bearerToken(current);
|
|
684
|
+
},
|
|
693
685
|
source: auth.source,
|
|
694
686
|
warn: (message) => devLogger?.warn(message),
|
|
695
687
|
intercept: (request) => devWorkflows?.handle(request)
|
|
@@ -950,5 +942,4 @@ function applet(sourceDefinition) {
|
|
|
950
942
|
cloudflarePlugins
|
|
951
943
|
];
|
|
952
944
|
}
|
|
953
|
-
//#endregion
|
|
954
945
|
export { applet };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
//#region src/server/workflow.d.ts
|
|
3
2
|
type WorkflowDuration = {
|
|
4
3
|
milliseconds?: number;
|
|
5
4
|
seconds?: number;
|
|
@@ -24,5 +23,4 @@ type WorkflowDefinition<Payload, Result> = {
|
|
|
24
23
|
};
|
|
25
24
|
type AnyWorkflowDefinition = WorkflowDefinition<any, any>;
|
|
26
25
|
declare function createWorkflow<Payload, Result>(run: (step: WorkflowStep, payload: Payload) => Promise<Result>): WorkflowDefinition<Payload, Result>;
|
|
27
|
-
//#endregion
|
|
28
26
|
export { createWorkflow as a, WorkflowStep as i, WorkflowDefinition as n, WorkflowDuration as r, AnyWorkflowDefinition as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
|
|
2
|
+
// src/server/workflow-protocol.ts
|
|
3
3
|
const journalEntrySchema = z.discriminatedUnion("kind", [
|
|
4
4
|
z.object({
|
|
5
5
|
kind: z.literal("step"),
|
|
@@ -67,8 +67,7 @@ const workflowOutcomeSchema = z.discriminatedUnion("kind", [
|
|
|
67
67
|
message: z.string()
|
|
68
68
|
})
|
|
69
69
|
]);
|
|
70
|
-
|
|
71
|
-
//#region src/server/workflow-engine.ts
|
|
70
|
+
// src/server/workflow-engine.ts
|
|
72
71
|
var WorkflowFailedError = class extends Error {};
|
|
73
72
|
async function runWorkflowJournal(engine, invoke) {
|
|
74
73
|
const journal = [];
|
|
@@ -107,5 +106,4 @@ async function runWorkflowJournal(engine, invoke) {
|
|
|
107
106
|
}
|
|
108
107
|
}
|
|
109
108
|
}
|
|
110
|
-
//#endregion
|
|
111
109
|
export { workflowOutcomeSchema as a, workflowInvocationRequestSchema as i, runWorkflowJournal as n, journalEntrySchema as r, WorkflowFailedError as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
-
|
|
3
|
+
// src/server/identity.ts
|
|
4
4
|
const requestContext = new AsyncLocalStorage();
|
|
5
5
|
function runWithRequestContext(context, fn) {
|
|
6
6
|
return requestContext.run(context, fn);
|
|
@@ -16,8 +16,7 @@ function getRequestContext() {
|
|
|
16
16
|
function getIdentityBearer(identity) {
|
|
17
17
|
return identity.kind === "user" ? identity.sessionToken : identity.token;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
//#region src/server/workflow.ts
|
|
19
|
+
// src/server/workflow.ts
|
|
21
20
|
const DURATION_MULTIPLIERS = {
|
|
22
21
|
milliseconds: 1,
|
|
23
22
|
seconds: 1e3,
|
|
@@ -47,5 +46,4 @@ function toMilliseconds(duration) {
|
|
|
47
46
|
function createWorkflow(run) {
|
|
48
47
|
return { run };
|
|
49
48
|
}
|
|
50
|
-
//#endregion
|
|
51
49
|
export { getRequestContext as a, getIdentityBearer as i, createWorkflow as n, runWithRequestContext as o, toMilliseconds as r, tryGetRequestContext as s, MAX_DURATION_MS as t };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { createRequire, registerHooks } from "node:module";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { basename, dirname, resolve } from "node:path";
|
|
5
|
+
// ../shared/auth/src/workspace.mts
|
|
6
|
+
const ORG_CODE_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
var WorkspaceValidationError = class extends Error {};
|
|
9
|
+
const SDK_VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?$/;
|
|
10
|
+
function validateRootManifest(value) {
|
|
11
|
+
if (value === null || typeof value !== "object" || !("org" in value) || typeof value.org !== "string" || !ORG_CODE_PATTERN.test(value.org)) throw new WorkspaceValidationError("Invalid applet manifest: \"org\" must be an organization code.");
|
|
12
|
+
if (!("sdk" in value) || typeof value.sdk !== "string" || !SDK_VERSION_PATTERN.test(value.sdk)) throw new WorkspaceValidationError("Invalid applet manifest: \"sdk\" must be an exact version, for example \"0.2.0\".");
|
|
13
|
+
return {
|
|
14
|
+
org: value.org,
|
|
15
|
+
sdk: `@hitch42/applet@${value.sdk}`,
|
|
16
|
+
githubWorkflow: false
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function isRootLayout(dir) {
|
|
20
|
+
return fs.existsSync(resolve(dir, "applet.manifest.ts")) && !fs.existsSync(resolve(dir, "hitch.config.ts")) && !(basename(dirname(dir)) === "applets" && fs.existsSync(resolve(dir, "../../hitch.config.ts")));
|
|
21
|
+
}
|
|
22
|
+
function readWorkspaceConfig(dir) {
|
|
23
|
+
const rootLayout = isRootLayout(dir);
|
|
24
|
+
const path = resolve(dir, rootLayout ? "applet.manifest.ts" : "hitch.config.ts");
|
|
25
|
+
if (!fs.existsSync(path)) return void 0;
|
|
26
|
+
let module;
|
|
27
|
+
const configUrl = pathToFileURL(fs.realpathSync(path)).href;
|
|
28
|
+
const hooks = registerHooks({ load(url, context, nextLoad) {
|
|
29
|
+
return nextLoad(url, url === configUrl ? {
|
|
30
|
+
...context,
|
|
31
|
+
format: "module-typescript"
|
|
32
|
+
} : context);
|
|
33
|
+
} });
|
|
34
|
+
try {
|
|
35
|
+
delete require.cache[require.resolve(path)];
|
|
36
|
+
module = require(path);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
throw new Error(`Failed to load ${path}.`, { cause: error });
|
|
39
|
+
} finally {
|
|
40
|
+
hooks.deregister();
|
|
41
|
+
}
|
|
42
|
+
const config = module !== null && typeof module === "object" && "default" in module ? module.default : module;
|
|
43
|
+
if (rootLayout) return validateRootManifest(config);
|
|
44
|
+
if (config === null || typeof config !== "object" || !("sdk" in config) || typeof config.sdk !== "string" || config.sdk.length === 0 || !("org" in config) || typeof config.org !== "string" || !ORG_CODE_PATTERN.test(config.org)) throw new WorkspaceValidationError(`Invalid Hitch config in ${path}: "sdk" must be a package spec and "org" an organization code.`);
|
|
45
|
+
const githubWorkflow = "githubWorkflow" in config ? config.githubWorkflow : void 0;
|
|
46
|
+
if (githubWorkflow !== void 0 && typeof githubWorkflow !== "boolean") throw new WorkspaceValidationError(`Invalid Hitch config in ${path}: "githubWorkflow" must be a boolean.`);
|
|
47
|
+
return {
|
|
48
|
+
sdk: config.sdk,
|
|
49
|
+
org: config.org,
|
|
50
|
+
githubWorkflow
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function findWorkspaceRoot(cwd) {
|
|
54
|
+
const dir = resolve(cwd);
|
|
55
|
+
if (fs.existsSync(resolve(dir, ".hitchroot"))) return void 0;
|
|
56
|
+
if (fs.existsSync(resolve(dir, "hitch.config.ts"))) return dir;
|
|
57
|
+
if (fs.existsSync(resolve(dir, "applet.manifest.ts"))) return basename(dirname(dir)) === "applets" && fs.existsSync(resolve(dir, "../../hitch.config.ts")) ? resolve(dir, "../..") : dir;
|
|
58
|
+
return dirname(dir) === dir ? void 0 : findWorkspaceRoot(dirname(dir));
|
|
59
|
+
}
|
|
60
|
+
function findAppletRoot(cwd) {
|
|
61
|
+
const dir = resolve(cwd);
|
|
62
|
+
if (fs.existsSync(resolve(dir, ".hitchroot"))) return void 0;
|
|
63
|
+
if (fs.existsSync(resolve(dir, "applet.manifest.ts"))) return dir;
|
|
64
|
+
if (fs.existsSync(resolve(dir, "hitch.config.ts")) || dirname(dir) === dir) return void 0;
|
|
65
|
+
return findAppletRoot(dirname(dir));
|
|
66
|
+
}
|
|
67
|
+
function findParentRoot(cwd) {
|
|
68
|
+
const dir = resolve(cwd);
|
|
69
|
+
if (fs.existsSync(resolve(dir, ".hitchroot"))) return dir;
|
|
70
|
+
return dirname(dir) === dir ? void 0 : findParentRoot(dirname(dir));
|
|
71
|
+
}
|
|
72
|
+
function findWorkspaceConfig(cwd) {
|
|
73
|
+
const root = findWorkspaceRoot(cwd);
|
|
74
|
+
return root === void 0 ? void 0 : readWorkspaceConfig(root);
|
|
75
|
+
}
|
|
76
|
+
export { findWorkspaceRoot as a, validateRootManifest as c, findWorkspaceConfig as i, findAppletRoot as n, isRootLayout as o, findParentRoot as r, readWorkspaceConfig as s, SDK_VERSION_PATTERN as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hitch42/applet",
|
|
3
|
-
"version": "0.1.1-beta.
|
|
3
|
+
"version": "0.1.1-beta.21",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bin": {
|
|
6
6
|
"applet": "./dist/applet.js"
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
"@fontsource-variable/geist-mono": "^5.3.0",
|
|
60
60
|
"@fontsource-variable/inter": "^5.3.0",
|
|
61
61
|
"@hey-api/openapi-ts": "0.0.0-next-20260824173136",
|
|
62
|
+
"@napi-rs/keyring": "2.1.2",
|
|
62
63
|
"@orpc/client": "^1.15.0",
|
|
63
64
|
"@orpc/contract": "^1.15.0",
|
|
64
65
|
"@orpc/openapi-client": "^1.15.0",
|
|
@@ -88,14 +89,14 @@
|
|
|
88
89
|
"oxlint": "^1.87.0",
|
|
89
90
|
"oxlint-tsgolint": "^7.0.2003",
|
|
90
91
|
"react-aria-components": "^1.20.0",
|
|
91
|
-
"shadcn": "^4.
|
|
92
|
+
"shadcn": "^4.23.0",
|
|
92
93
|
"smol-toml": "^1.9.0",
|
|
93
94
|
"streamdown": "^2.6.0",
|
|
94
95
|
"tailwindcss": "^4.3.0",
|
|
95
96
|
"tw-animate-css": "^1.4.0",
|
|
96
|
-
"vite": "8.3.
|
|
97
|
-
"vitest": "4.1.
|
|
98
|
-
"zod": "^4.
|
|
97
|
+
"vite": "8.3.3",
|
|
98
|
+
"vitest": "4.1.12",
|
|
99
|
+
"zod": "^4.6.7"
|
|
99
100
|
},
|
|
100
101
|
"peerDependencies": {
|
|
101
102
|
"@orpc/server": "^1.15.0",
|
|
@@ -11,7 +11,7 @@ Treat each applet as an isolated microfrontend. Keep it separate from the data s
|
|
|
11
11
|
|
|
12
12
|
## Public applets
|
|
13
13
|
|
|
14
|
-
Set `public: true` for an applet that anonymous visitors can use. It is served at `https://{org}.hitch42.app/
|
|
14
|
+
Set `public: true` for an applet that anonymous visitors can use. It is served at `https://{org}.hitch42.app/pages/{code}`. It runs as the applet identity. Its manifest grants cap its access.
|
|
15
15
|
|
|
16
16
|
A public applet cannot use schedules, email, telephony, workflows, or `@hitch42/applet/client/hitch`. Client code calls its server procedures with `api` from `@hitch42/applet/client`.
|
|
17
17
|
|
|
@@ -40,11 +40,26 @@ Follow the Hitch applet rules for SDK-owned configuration, providers, and genera
|
|
|
40
40
|
|
|
41
41
|
## Work with the workspace
|
|
42
42
|
|
|
43
|
+
With Hitch git on, the applet is the repo root. Its manifest includes `org`
|
|
44
|
+
and an exact `sdk` version, such as `"0.2.0"`. There is no `hitch.config.ts`.
|
|
45
|
+
Run package scripts inside that root. In the legacy command examples below,
|
|
46
|
+
`applets/<code>` means the applet directory: `.` for a root applet or `<code>`
|
|
47
|
+
from a `.hitchroot` parent. The legacy layout stays for orgs with Hitch git off
|
|
48
|
+
and GitHub Actions.
|
|
49
|
+
|
|
50
|
+
A `.hitchroot` parent is local and has no git repo. Each child is one applet
|
|
51
|
+
repo. Parent deploy processes changed children in order. Parent bootstrap
|
|
52
|
+
prepares all children. Commit per child. Generated agent files live once in
|
|
53
|
+
the parent; children use gitignored links. Keep edited files when the CLI
|
|
54
|
+
reports them.
|
|
55
|
+
|
|
43
56
|
- Run package commands with `pnpm`.
|
|
44
|
-
- Run `pnpm exec applet login` from the workspace root or an applet directory to sign in. It uses the organization in `hitch.config.ts` and shares credentials with `hitch login`. Add `--no-browser` to print the sign-in URL without opening a browser.
|
|
57
|
+
- Run `pnpm exec applet login` from the workspace root or an applet directory to sign in. It uses the organization in `applet.manifest.ts` or legacy `hitch.config.ts` and shares credentials with `hitch login`. Add `--no-browser` to print the sign-in URL without opening a browser.
|
|
45
58
|
- A server permission error is not a login request.
|
|
46
|
-
-
|
|
47
|
-
- Run `pnpm exec applet
|
|
59
|
+
- Keep one applet in each repository. Run `pnpm exec applet deploy -m "<message>"` to commit changes and deploy through Hitch git.
|
|
60
|
+
- Run `pnpm exec applet clone <org>/<code> [dir]` to get an applet and its git history from Hitch.
|
|
61
|
+
- Run `pnpm exec applet rollback <release-id>` to make an earlier release live again.
|
|
62
|
+
- Run `pnpm exec applet new <code>` from a parent or workspace to create a full applet.
|
|
48
63
|
- Add `--client-only` or `--server-only` when the applet needs only one part.
|
|
49
64
|
- Use `--client-only` for a user interface that uses the current user's Hitch access and needs no server.
|
|
50
65
|
- Use `--server-only` for an API or schedule that needs no user interface.
|
|
@@ -179,10 +194,13 @@ If missing packages block a check, stop package checks. Do not retry the check t
|
|
|
179
194
|
|
|
180
195
|
If a command fails, report the exact blocker. Do not deploy as a verification step.
|
|
181
196
|
|
|
182
|
-
## Deploy
|
|
197
|
+
## Deploy through Hitch git
|
|
198
|
+
|
|
199
|
+
- Keep one applet per repository, with its manifest and source at the root.
|
|
200
|
+
- Let the SDK migrate old workspaces after its backup. Keep `.hitch-backup/`.
|
|
201
|
+
- Use `applet clone` for other copies after migration. Remove the old GitHub deploy workflow.
|
|
202
|
+
- Run `pnpm exec applet deploy -m "<message>"` from the workspace root or applet folder. The CLI commits changes, pushes the commit to Hitch, and moves `main` when the release goes live.
|
|
203
|
+
- Run `pnpm exec applet clone <org>/<code> [dir]` to work from the current Hitch history.
|
|
204
|
+
- Run `pnpm exec applet rollback <release-id>` to make an earlier release live again. Revert or reset local commits before the next deploy.
|
|
183
205
|
|
|
184
|
-
-
|
|
185
|
-
- An applet deploys when its folder or a file outside `applets/` differs from its current release, including a local `applet deploy`. Uncommitted and untracked files count. Gitignored files do not count. An applet whose current release has no source hash always deploys.
|
|
186
|
-
- The deploy skips other applets and logs the reason. A skip is expected, not a failure.
|
|
187
|
-
- A schema change in Hitch alone does not trigger CI.
|
|
188
|
-
- Do not import from a sibling applet folder. The change check does not follow such imports.
|
|
206
|
+
GitHub-linked applets still deploy through GitHub Actions CI until their organization moves to Hitch git.
|
|
@@ -77,7 +77,7 @@ Use the `get` query utilities when React needs file metadata as query state.
|
|
|
77
77
|
```ts
|
|
78
78
|
const fileQuery = useQuery(
|
|
79
79
|
hitch.files.get.queryOptions({
|
|
80
|
-
input: { params: { id } },
|
|
80
|
+
input: { params: { file: id } },
|
|
81
81
|
}),
|
|
82
82
|
);
|
|
83
83
|
|
|
@@ -100,7 +100,7 @@ Store `uploaded.id` as the value of an attachment attribute. A multi-value attac
|
|
|
100
100
|
const uploaded = await hitch.files.upload(file);
|
|
101
101
|
|
|
102
102
|
await hitch.records.claims.update.call({
|
|
103
|
-
params: {
|
|
103
|
+
params: { record: claimId },
|
|
104
104
|
body: { receipt_id: uploaded.id }, // multi-value: [uploaded.id]
|
|
105
105
|
});
|
|
106
106
|
```
|