@hitch42/applet 0.1.1-beta.8 → 0.1.1-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/client.js +120 -11
- package/dist/_internal/log-context.d.ts +34 -0
- package/dist/_internal/log-context.js +2 -0
- package/dist/_internal/server.d.ts +1 -1
- package/dist/_internal/server.js +112 -57
- package/dist/applet.js +12 -12
- package/dist/build-Bh_S5BUv.js +2 -0
- package/dist/{build-DANx9Hgg.js → build-CEfFoIZZ.js} +1 -1
- package/dist/{ci-5qWl7lT3.js → ci-BKw14X2h.js} +14 -13
- package/dist/client.d.ts +3 -3
- package/dist/{contract-rP_eV9PK.d.ts → contract-CsUpTBe0.d.ts} +1 -1
- package/dist/{deploy-MQWLG2EA.js → deploy-wGYjwXrx.js} +139 -88
- package/dist/{generate-BxYHdoAQ.js → generate-BEIYs17x.js} +65 -28
- package/dist/generate-Dox-OYt6.js +2 -0
- package/dist/headers-DkNr9MLJ.js +17 -0
- package/dist/index.d.ts +23 -22
- package/dist/index.js +2 -1
- package/dist/{init-jDEgYIXg.js → init-6oGPM46R.js} +15 -17
- package/dist/{load-config-BYSxDVAl.js → load-config-xEdTXs0y.js} +2 -2
- package/dist/log-context-zu8U9Sjm.js +73 -0
- package/dist/{login-C7RKmmTe.js → login-CUx3TmFQ.js} +1 -1
- package/dist/{logs-DgjgAxj2.js → logs-DSjuEN0Q.js} +20 -22
- package/dist/{manifest-DD_SGkS6.d.ts → manifest-C6_F4bL8.d.ts} +5 -1
- package/dist/{manifest-Bp87Uz0a.js → manifest-CJSL9GuC.js} +20 -4
- package/dist/{project-CbYPtpPq.js → project-BRZGd6xq.js} +199 -18
- package/dist/query-cache-CXmAyLv3.js +82 -0
- package/dist/react.d.ts +3 -2
- package/dist/react.js +98 -80
- package/dist/{schedules-dhU1yyFr.js → schedules-C8_Svr4h.js} +1 -1
- package/dist/server.d.ts +9 -4
- package/dist/server.js +29 -8
- package/dist/{telephony-protocol-DRgiYjqQ.d.ts → telephony-protocol-D-nf3Gca.d.ts} +15 -13
- package/dist/telephony.d.ts +24 -4
- package/dist/telephony.js +135 -16
- package/dist/{upload-YbRKEqR6.d.ts → upload-DKZzz5kW.d.ts} +6 -6
- package/dist/{variables-Bwnr7oxf.js → variables-DT5RyHdH.js} +13 -13
- package/dist/vite.d.ts +3 -60
- package/dist/vite.js +50 -15
- package/dist/{workflow-engine-MogejNfF.js → workflow-engine-BOTzURKM.js} +1 -7
- package/dist/{workspace-XVtM12ZC.js → workspace-D0dnnlxL.js} +33 -38
- package/package.json +13 -5
- package/scaffold/.agents/skills/hitch-applets/SKILL.md +30 -4
- package/scaffold/.agents/skills/hitch-applets/references/manifest.md +8 -0
- package/scaffold/.agents/skills/hitch-applets/references/markdown.md +2 -0
- package/scaffold/.agents/skills/hitch-applets/references/records.md +23 -1
- package/scaffold/.agents/skills/hitch-data/SKILL.md +2 -1
- package/scaffold/.agents/skills/hitch-data/references/attributes.md +7 -1
- package/scaffold/.agents/skills/hitch-data/references/limits.md +13 -13
- package/scaffold/.agents/skills/hitch-theory/SKILL.md +3 -2
- package/scaffold/.agents/skills/react-best-practices/SKILL.md +127 -0
- package/scaffold/.agents/skills/react-best-practices/rules/advanced-effect-event-deps.md +50 -0
- package/scaffold/.agents/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/scaffold/.agents/skills/react-best-practices/rules/advanced-init-once.md +42 -0
- package/scaffold/.agents/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/scaffold/.agents/skills/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
- package/scaffold/.agents/skills/react-best-practices/rules/async-defer-await.md +82 -0
- package/scaffold/.agents/skills/react-best-practices/rules/async-dependencies.md +48 -0
- package/scaffold/.agents/skills/react-best-practices/rules/async-parallel.md +24 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-analyzable-paths.md +42 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-barrel-imports.md +39 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-conditional.md +35 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-defer-third-party.md +46 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-dynamic-imports.md +38 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-preload.md +40 -0
- package/scaffold/.agents/skills/react-best-practices/rules/client-event-listeners.md +78 -0
- package/scaffold/.agents/skills/react-best-practices/rules/client-localstorage-schema.md +74 -0
- package/scaffold/.agents/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-batch-dom-css.md +110 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-cache-function-results.md +58 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-cache-storage.md +56 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-flatmap-filter.md +51 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-length-check-first.md +50 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-request-idle-callback.md +104 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-conditional-render.md +32 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-hoist-jsx.md +36 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-resource-hints.md +81 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-script-defer-async.md +36 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-usetransition-loading.md +43 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-functional-setstate.md +77 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-lazy-state-init.md +56 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo-with-default-value.md +36 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-no-inline-components.md +75 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/scaffold/.agents/skills/tanstack-query/SKILL.md +136 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/automatic-invalidation-after-mutations.md +124 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/broadcast-realtime-and-multi-tab-synchronization.md +150 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/compose-query-with-tanstack-router-and-start.md +248 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/enforce-query-best-practices-with-eslint.md +167 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/persist-offline-and-restore-caches.md +181 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/query-data-and-forms.md +156 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/build-query-abstractions.md +130 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/cancel-queries-and-consume-abort-signals.md +176 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/concurrent-optimistic-updates.md +135 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/coordinate-query-execution.md +188 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/design-query-keys-and-options.md +182 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/fetch-and-observe-queries.md +193 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/implement-optimistic-updates-and-cache-writes.md +168 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/paginate-and-build-infinite-queries.md +188 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/seed-placeholder-select-and-transform-data.md +188 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/selectors-and-derived-state.md +145 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/tune-defaults-freshness-retries-and-refetching.md +172 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/understand-query-internals-and-observers.md +104 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/write-mutations-and-invalidate-related-queries.md +183 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/debug-with-devtools.md +169 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/handle-status-and-errors.md +119 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/shape-data-and-render-efficiently.md +184 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/use-framework-adapter-reactivity.md +185 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/use-suspense-and-error-boundaries.md +208 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/migrate-major-versions-and-codemods.md +169 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/prefetch-and-remove-request-waterfalls.md +228 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/setup-query-client-and-providers.md +161 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/ssr-hydration-and-streaming.md +209 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/test-query-code.md +160 -0
- package/scaffold/.agents/skills/tanstack-router/SKILL.md +134 -0
- package/scaffold/.agents/skills/tanstack-router/references/compositions/router-query.md +412 -0
- package/scaffold/.agents/skills/tanstack-router/references/react-router.md +495 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/auth-and-guards.md +495 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/code-splitting.md +318 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/data-loading.md +490 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/index.md +158 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/navigation.md +433 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/not-found-and-errors.md +436 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/path-params.md +383 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/search-params.md +343 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/ssr.md +462 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/type-safety.md +493 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-plugin.md +250 -0
- package/scaffold/.agents/skills/tanstack-router/references/virtual-file-routes.md +215 -0
- package/scaffold/.agents/skills/web-design-guidelines/SKILL.md +184 -0
- package/scaffold/.github/workflows/hitch.yml +1 -1
- package/scaffold/AGENTS.md +2 -2
- package/scaffold/applet/src/client/components/ui/alert.tsx +1 -1
- package/scaffold/applet/src/client/components/ui/button.tsx +1 -1
- package/scaffold/applet/src/client/components/ui/checkbox.tsx +1 -1
- package/scaffold/applet/src/client/components/ui/dialog.tsx +2 -2
- package/scaffold/applet/src/client/components/ui/dropdown-menu.tsx +2 -2
- package/scaffold/applet/src/client/components/ui/input-group.tsx +2 -2
- package/scaffold/applet/src/client/components/ui/select.tsx +2 -2
- package/scaffold/applet/src/client/components/ui/sheet.tsx +2 -2
- package/scaffold/applet/src/client/components/ui/spinner.tsx +2 -1
- package/scaffold/applet/src/client/components/ui/tabs.tsx +1 -1
- package/scaffold/applet/src/client/lib/utils.ts +1 -6
- package/scaffold/applet/src/client/styles/globals.css +2 -0
- package/dist/build-CFCKKMn7.js +0 -2
- package/dist/generate-CQ07Hdpo.js +0 -2
package/dist/telephony.js
CHANGED
|
@@ -28,9 +28,12 @@ const createTelephonyApi = (baseUrl = location.origin) => {
|
|
|
28
28
|
return response.json();
|
|
29
29
|
};
|
|
30
30
|
return {
|
|
31
|
-
token: (deviceKey) => request("voice/token", {
|
|
31
|
+
token: (deviceKey, acceptsCalls) => request("voice/token", {
|
|
32
32
|
method: "POST",
|
|
33
|
-
body: JSON.stringify({
|
|
33
|
+
body: JSON.stringify({
|
|
34
|
+
deviceKey,
|
|
35
|
+
acceptsCalls
|
|
36
|
+
})
|
|
34
37
|
}),
|
|
35
38
|
startCall: (numberId, to) => request("calls", {
|
|
36
39
|
method: "POST",
|
|
@@ -165,14 +168,18 @@ const DEVICE_KEY = "hitch:telephony:device";
|
|
|
165
168
|
let singleton;
|
|
166
169
|
var Phone = class {
|
|
167
170
|
state = {
|
|
171
|
+
owner: false,
|
|
168
172
|
status: "off",
|
|
169
173
|
error: null,
|
|
174
|
+
incoming: null,
|
|
170
175
|
active: null
|
|
171
176
|
};
|
|
172
177
|
listeners = /* @__PURE__ */ new Set();
|
|
173
178
|
api;
|
|
174
179
|
client = null;
|
|
175
180
|
currentCall = null;
|
|
181
|
+
incomingCall = null;
|
|
182
|
+
acceptsCalls;
|
|
176
183
|
connectPromise = null;
|
|
177
184
|
releaseLock = null;
|
|
178
185
|
lockAbortController = null;
|
|
@@ -186,8 +193,11 @@ var Phone = class {
|
|
|
186
193
|
audio = null;
|
|
187
194
|
firstLogin = true;
|
|
188
195
|
callStarting = false;
|
|
196
|
+
reconnectOnPageShow = false;
|
|
197
|
+
connectionRequested = false;
|
|
189
198
|
constructor(options = {}) {
|
|
190
199
|
this.api = createTelephonyApi(options.baseUrl);
|
|
200
|
+
this.acceptsCalls = options.acceptsCalls ?? false;
|
|
191
201
|
}
|
|
192
202
|
subscribe = (listener) => {
|
|
193
203
|
this.listeners.add(listener);
|
|
@@ -248,6 +258,7 @@ var Phone = class {
|
|
|
248
258
|
};
|
|
249
259
|
}
|
|
250
260
|
connect = () => {
|
|
261
|
+
this.connectionRequested = true;
|
|
251
262
|
this.connectPromise ??= this.connectInternal().finally(() => {
|
|
252
263
|
this.connectPromise = null;
|
|
253
264
|
});
|
|
@@ -255,6 +266,8 @@ var Phone = class {
|
|
|
255
266
|
};
|
|
256
267
|
async connectInternal() {
|
|
257
268
|
if (this.state.status === "ready") return;
|
|
269
|
+
window.addEventListener("pagehide", this.pageHide);
|
|
270
|
+
window.addEventListener("pageshow", this.pageShow);
|
|
258
271
|
this.channel ??= new BroadcastChannel("hitch:telephony");
|
|
259
272
|
this.channel.onmessage = this.onChannelMessage;
|
|
260
273
|
this.update({
|
|
@@ -275,8 +288,10 @@ var Phone = class {
|
|
|
275
288
|
});
|
|
276
289
|
this.ownsPhone = true;
|
|
277
290
|
this.update({
|
|
291
|
+
owner: true,
|
|
278
292
|
status: "connecting",
|
|
279
293
|
error: null,
|
|
294
|
+
incoming: null,
|
|
280
295
|
active: null
|
|
281
296
|
});
|
|
282
297
|
await this.connectOwned();
|
|
@@ -297,6 +312,7 @@ var Phone = class {
|
|
|
297
312
|
return;
|
|
298
313
|
}
|
|
299
314
|
this.ownsPhone = true;
|
|
315
|
+
this.update({ owner: true });
|
|
300
316
|
await this.connectOwned();
|
|
301
317
|
}
|
|
302
318
|
async connectOwned() {
|
|
@@ -311,7 +327,7 @@ var Phone = class {
|
|
|
311
327
|
8e3
|
|
312
328
|
]) {
|
|
313
329
|
if (delay) await new Promise((resolve) => setTimeout(resolve, delay));
|
|
314
|
-
const { token } = await this.api.token(deviceKey);
|
|
330
|
+
const { token } = await this.api.token(deviceKey, this.acceptsCalls);
|
|
315
331
|
const { TelnyxRTC: Client } = await import("@telnyx/webrtc");
|
|
316
332
|
const client = new Client({
|
|
317
333
|
login_token: token,
|
|
@@ -320,15 +336,35 @@ var Phone = class {
|
|
|
320
336
|
this.client = client;
|
|
321
337
|
client.on("telnyx.notification", ({ type, call }) => {
|
|
322
338
|
if (type !== "callUpdate" || !call) return;
|
|
323
|
-
if (call
|
|
324
|
-
|
|
339
|
+
if (call === this.currentCall) {
|
|
340
|
+
this.onCallUpdate(call);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
if (call.direction !== "inbound") return;
|
|
344
|
+
if ([
|
|
345
|
+
"hangup",
|
|
346
|
+
"destroy",
|
|
347
|
+
"purge"
|
|
348
|
+
].includes(call.state)) {
|
|
349
|
+
if (call === this.incomingCall) {
|
|
350
|
+
this.incomingCall = null;
|
|
351
|
+
this.update({ incoming: null });
|
|
352
|
+
}
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
if (!this.acceptsCalls || this.currentCall || this.callStarting || this.incomingCall && this.incomingCall !== call) {
|
|
356
|
+
call.hangup().catch((error) => console.error("Call decline failed", error));
|
|
325
357
|
return;
|
|
326
358
|
}
|
|
327
|
-
|
|
359
|
+
this.incomingCall = call;
|
|
360
|
+
if (call.state === "ringing") this.update({ incoming: {
|
|
361
|
+
id: call.id,
|
|
362
|
+
from: call.options.remoteCallerNumber ?? ""
|
|
363
|
+
} });
|
|
328
364
|
});
|
|
329
365
|
client.on("telnyx.warning", (warning) => {
|
|
330
366
|
if (Number(warning.warning.code) !== 34001) return;
|
|
331
|
-
this.api.token(deviceKey).then(({ token: nextToken }) => client.login({ creds: { login_token: nextToken } })).catch((error) => {
|
|
367
|
+
this.api.token(deviceKey, this.acceptsCalls).then(({ token: nextToken }) => client.login({ creds: { login_token: nextToken } })).catch((error) => {
|
|
332
368
|
console.error("Phone token renewal failed", error);
|
|
333
369
|
this.update({ error: String(error) });
|
|
334
370
|
});
|
|
@@ -341,7 +377,6 @@ var Phone = class {
|
|
|
341
377
|
});
|
|
342
378
|
this.firstLogin = false;
|
|
343
379
|
this.update({ status: "ready" });
|
|
344
|
-
window.addEventListener("pagehide", this.disconnect);
|
|
345
380
|
return;
|
|
346
381
|
} catch (error) {
|
|
347
382
|
await client.disconnect().catch((disconnectError) => console.error("Phone disconnect failed", disconnectError));
|
|
@@ -351,6 +386,7 @@ var Phone = class {
|
|
|
351
386
|
}
|
|
352
387
|
} catch (error) {
|
|
353
388
|
this.update({
|
|
389
|
+
owner: false,
|
|
354
390
|
status: "error",
|
|
355
391
|
error: error instanceof Error ? error.message : String(error)
|
|
356
392
|
});
|
|
@@ -360,13 +396,16 @@ var Phone = class {
|
|
|
360
396
|
}
|
|
361
397
|
}
|
|
362
398
|
disconnect = () => {
|
|
399
|
+
this.connectionRequested = false;
|
|
363
400
|
this.lockAbortController?.abort();
|
|
364
401
|
this.lockAbortController = null;
|
|
365
402
|
this.connectResolve?.();
|
|
366
403
|
this.connectResolve = null;
|
|
367
404
|
if (this.pollTimer) clearTimeout(this.pollTimer);
|
|
368
405
|
this.pollTimer = null;
|
|
369
|
-
window.removeEventListener("pagehide", this.
|
|
406
|
+
window.removeEventListener("pagehide", this.pageHide);
|
|
407
|
+
window.removeEventListener("pageshow", this.pageShow);
|
|
408
|
+
this.reconnectOnPageShow = false;
|
|
370
409
|
window.removeEventListener("beforeunload", this.beforeUnload);
|
|
371
410
|
this.client?.disconnect().catch((error) => console.error("Phone disconnect failed", error));
|
|
372
411
|
this.client = null;
|
|
@@ -377,20 +416,35 @@ var Phone = class {
|
|
|
377
416
|
this.pendingCommands.clear();
|
|
378
417
|
this.releaseLock?.();
|
|
379
418
|
this.releaseLock = null;
|
|
419
|
+
this.currentCall = null;
|
|
420
|
+
this.incomingCall = null;
|
|
380
421
|
this.update({
|
|
422
|
+
owner: false,
|
|
381
423
|
status: "off",
|
|
424
|
+
incoming: null,
|
|
382
425
|
active: null
|
|
383
426
|
});
|
|
384
427
|
this.ownsPhone = false;
|
|
385
428
|
this.channel?.close();
|
|
386
429
|
this.channel = null;
|
|
387
430
|
};
|
|
431
|
+
pageHide = () => {
|
|
432
|
+
const reconnect = this.connectionRequested;
|
|
433
|
+
this.disconnect();
|
|
434
|
+
this.reconnectOnPageShow = reconnect;
|
|
435
|
+
if (reconnect) window.addEventListener("pageshow", this.pageShow);
|
|
436
|
+
};
|
|
437
|
+
pageShow = (event) => {
|
|
438
|
+
if (!event.persisted || !this.reconnectOnPageShow) return;
|
|
439
|
+
this.reconnectOnPageShow = false;
|
|
440
|
+
this.connect();
|
|
441
|
+
};
|
|
388
442
|
beforeUnload = (event) => {
|
|
389
443
|
event.preventDefault();
|
|
390
444
|
event.returnValue = "";
|
|
391
445
|
};
|
|
392
446
|
call = async ({ numberId, to }) => {
|
|
393
|
-
if (this.callStarting || this.state.active) throw new Error("A call is already in progress.");
|
|
447
|
+
if (this.callStarting || this.state.active || this.incomingCall || this.state.incoming) throw new Error("A call is already in progress.");
|
|
394
448
|
if (this.state.status !== "ready") throw new Error("The phone is not ready.");
|
|
395
449
|
if (!this.ownsPhone) return this.sendCommand("call", {
|
|
396
450
|
numberId,
|
|
@@ -417,6 +471,7 @@ var Phone = class {
|
|
|
417
471
|
this.update({
|
|
418
472
|
error: null,
|
|
419
473
|
active: {
|
|
474
|
+
direction: "outbound",
|
|
420
475
|
callId,
|
|
421
476
|
to,
|
|
422
477
|
from: callerNumber,
|
|
@@ -432,6 +487,62 @@ var Phone = class {
|
|
|
432
487
|
this.callStarting = false;
|
|
433
488
|
}
|
|
434
489
|
};
|
|
490
|
+
answer = async () => {
|
|
491
|
+
if (!this.state.incoming) throw new Error("There is no incoming call.");
|
|
492
|
+
if (!this.ownsPhone) return this.sendCommand("answer", this.state.incoming.id);
|
|
493
|
+
const call = this.incomingCall;
|
|
494
|
+
if (!call) throw new Error("There is no incoming call.");
|
|
495
|
+
if (!this.client) throw new Error("The phone is not ready.");
|
|
496
|
+
this.audio ??= document.createElement("audio");
|
|
497
|
+
this.audio.autoplay = true;
|
|
498
|
+
this.audio.hidden = true;
|
|
499
|
+
if (!this.audio.isConnected) document.body.append(this.audio);
|
|
500
|
+
this.client.remoteElement = this.audio;
|
|
501
|
+
call.options.remoteElement = this.audio;
|
|
502
|
+
this.currentCall = call;
|
|
503
|
+
this.incomingCall = null;
|
|
504
|
+
this.update({
|
|
505
|
+
incoming: null,
|
|
506
|
+
error: null,
|
|
507
|
+
active: {
|
|
508
|
+
direction: "inbound",
|
|
509
|
+
from: this.state.incoming.from,
|
|
510
|
+
state: "connecting",
|
|
511
|
+
muted: false,
|
|
512
|
+
startedAt: Date.now(),
|
|
513
|
+
recording: false
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
window.addEventListener("beforeunload", this.beforeUnload);
|
|
517
|
+
try {
|
|
518
|
+
await call.answer();
|
|
519
|
+
} catch (error) {
|
|
520
|
+
if (this.currentCall === call) {
|
|
521
|
+
this.currentCall = null;
|
|
522
|
+
this.incomingCall = call;
|
|
523
|
+
this.update({
|
|
524
|
+
active: null,
|
|
525
|
+
incoming: {
|
|
526
|
+
id: call.id,
|
|
527
|
+
from: call.options.remoteCallerNumber ?? ""
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
window.removeEventListener("beforeunload", this.beforeUnload);
|
|
531
|
+
}
|
|
532
|
+
throw error;
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
decline = async () => {
|
|
536
|
+
if (!this.state.incoming) throw new Error("There is no incoming call.");
|
|
537
|
+
if (!this.ownsPhone) return this.sendCommand("decline", this.state.incoming.id);
|
|
538
|
+
const call = this.incomingCall;
|
|
539
|
+
if (!call) throw new Error("There is no incoming call.");
|
|
540
|
+
await call.hangup();
|
|
541
|
+
if (this.incomingCall === call) {
|
|
542
|
+
this.incomingCall = null;
|
|
543
|
+
this.update({ incoming: null });
|
|
544
|
+
}
|
|
545
|
+
};
|
|
435
546
|
sendCommand(action, value) {
|
|
436
547
|
const id = crypto.randomUUID();
|
|
437
548
|
return new Promise((resolve, reject) => {
|
|
@@ -462,7 +573,10 @@ var Phone = class {
|
|
|
462
573
|
else if (data.type === "state" && !this.ownsPhone && "state" in data) {
|
|
463
574
|
const state = data.state;
|
|
464
575
|
if (typeof state !== "object" || state === null || !("status" in state)) return;
|
|
465
|
-
this.state =
|
|
576
|
+
this.state = {
|
|
577
|
+
...state,
|
|
578
|
+
owner: false
|
|
579
|
+
};
|
|
466
580
|
this.listeners.forEach((listener) => listener());
|
|
467
581
|
this.connectResolve?.();
|
|
468
582
|
this.connectResolve = null;
|
|
@@ -483,6 +597,10 @@ var Phone = class {
|
|
|
483
597
|
}));
|
|
484
598
|
};
|
|
485
599
|
async runCommand(data) {
|
|
600
|
+
if (data.action === "answer" || data.action === "decline") {
|
|
601
|
+
if (!this.incomingCall || data.value !== this.incomingCall.id) throw new Error("That call is no longer ringing.");
|
|
602
|
+
return data.action === "answer" ? this.answer() : this.decline();
|
|
603
|
+
}
|
|
486
604
|
if (data.action === "call") {
|
|
487
605
|
const value = data.value;
|
|
488
606
|
if (!value || typeof value !== "object" || !("numberId" in value) || !("to" in value) || typeof value.numberId !== "string" || typeof value.to !== "string") throw new Error("Invalid call command.");
|
|
@@ -518,7 +636,7 @@ var Phone = class {
|
|
|
518
636
|
}
|
|
519
637
|
}
|
|
520
638
|
async pollCall(callId) {
|
|
521
|
-
if (this.state.active?.callId !== callId || this.state.active.state === "active") return;
|
|
639
|
+
if (this.state.active?.direction !== "outbound" || this.state.active.callId !== callId || this.state.active.state === "active") return;
|
|
522
640
|
try {
|
|
523
641
|
const { status } = await this.api.getCall(callId);
|
|
524
642
|
if ([
|
|
@@ -533,7 +651,8 @@ var Phone = class {
|
|
|
533
651
|
} catch (error) {
|
|
534
652
|
console.error("Call status check failed", error);
|
|
535
653
|
}
|
|
536
|
-
|
|
654
|
+
const active = this.getSnapshot().active;
|
|
655
|
+
if (active?.direction === "outbound" && active.callId === callId) this.pollTimer = setTimeout(() => void this.pollCall(callId), 1e4);
|
|
537
656
|
}
|
|
538
657
|
onCallUpdate(call) {
|
|
539
658
|
const active = this.state.active;
|
|
@@ -562,15 +681,15 @@ var Phone = class {
|
|
|
562
681
|
return;
|
|
563
682
|
}
|
|
564
683
|
const mapped = state === "active" ? "active" : state === "held" ? "held" : state === "ringing" ? "ringing" : "connecting";
|
|
565
|
-
if (mapped === "active" && active.recording && !this.stopRecording && !this.recordingPromise) {
|
|
684
|
+
if (mapped === "active" && active.direction === "outbound" && active.recording && !this.stopRecording && !this.recordingPromise) {
|
|
566
685
|
this.recordingPromise = startRecording(active.callId, call, this.api, (error) => {
|
|
567
686
|
console.error("Call recording failed", error);
|
|
568
|
-
if (this.state.active?.callId === active.callId) this.update({ active: {
|
|
687
|
+
if (this.state.active?.direction === "outbound" && this.state.active.callId === active.callId) this.update({ active: {
|
|
569
688
|
...this.state.active,
|
|
570
689
|
recording: false
|
|
571
690
|
} });
|
|
572
691
|
}).then((stop) => {
|
|
573
|
-
if (this.state.active?.callId === active.callId) this.stopRecording = stop;
|
|
692
|
+
if (this.state.active?.direction === "outbound" && this.state.active.callId === active.callId) this.stopRecording = stop;
|
|
574
693
|
return stop;
|
|
575
694
|
});
|
|
576
695
|
this.recordingPromise.catch((error) => {
|
|
@@ -36,13 +36,13 @@ type FileOutput = {
|
|
|
36
36
|
data: HitchFile;
|
|
37
37
|
downloadUrl: string;
|
|
38
38
|
};
|
|
39
|
-
declare const fileSchema: z.ZodType<HitchFile>;
|
|
40
|
-
declare const createFileOutputSchema: z.ZodType<CreateFileOutput>;
|
|
41
|
-
declare const getFileOutputSchema: z.ZodType<FileOutput>;
|
|
39
|
+
declare const fileSchema: z.ZodType<HitchFile, HitchFile>;
|
|
40
|
+
declare const createFileOutputSchema: z.ZodType<CreateFileOutput, CreateFileOutput>;
|
|
41
|
+
declare const getFileOutputSchema: z.ZodType<FileOutput, FileOutput>;
|
|
42
42
|
type FilesContract = {
|
|
43
|
-
create: ContractProcedure<z.ZodType<CreateFileInput>, z.ZodType<CreateFileOutput>, Record<never, never>, Meta>;
|
|
44
|
-
confirm: ContractProcedure<z.ZodType<FileIdInput>, z.ZodType<FileOutput>, Record<never, never>, Meta>;
|
|
45
|
-
get: ContractProcedure<z.ZodType<FileIdInput>, z.ZodType<FileOutput>, Record<never, never>, Meta>;
|
|
43
|
+
create: ContractProcedure<z.ZodType<CreateFileInput, CreateFileInput>, z.ZodType<CreateFileOutput, CreateFileOutput>, Record<never, never>, Meta>;
|
|
44
|
+
confirm: ContractProcedure<z.ZodType<FileIdInput, FileIdInput>, z.ZodType<FileOutput, FileOutput>, Record<never, never>, Meta>;
|
|
45
|
+
get: ContractProcedure<z.ZodType<FileIdInput, FileIdInput>, z.ZodType<FileOutput, FileOutput>, Record<never, never>, Meta>;
|
|
46
46
|
};
|
|
47
47
|
declare const filesContract: FilesContract;
|
|
48
48
|
//#endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as fetchWithOrgAuth } from "./workspace-
|
|
2
|
-
import { t as loadAppletConfig } from "./load-config-
|
|
1
|
+
import { n as fetchWithOrgAuth } from "./workspace-D0dnnlxL.js";
|
|
2
|
+
import { t as loadAppletConfig } from "./load-config-xEdTXs0y.js";
|
|
3
3
|
import { t as question } from "./prompt-ChS-grYO.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
//#region src/variables.ts
|
|
@@ -14,12 +14,12 @@ const variableResponseSchema = z.object({ data: variableRowSchema });
|
|
|
14
14
|
const variablesResponseSchema = z.object({ data: z.array(variableRowSchema) });
|
|
15
15
|
async function getValue(options) {
|
|
16
16
|
if (options.value !== void 0) return options.value;
|
|
17
|
-
if (
|
|
17
|
+
if (process.stdin.isTTY !== true) throw new Error("A value is required when stdin is not a TTY.");
|
|
18
18
|
return question("Value: ", true);
|
|
19
19
|
}
|
|
20
20
|
async function confirmLiveChange(code, options) {
|
|
21
21
|
if (options.yes === true) return;
|
|
22
|
-
if (
|
|
22
|
+
if (process.stdin.isTTY !== true) throw new Error("Confirmation requires a TTY. Pass -y to continue.");
|
|
23
23
|
const answer = await question(`This modifies the live applet "${code}". Continue? [y/N] `);
|
|
24
24
|
if (!["y", "yes"].includes(answer.trim().toLowerCase())) throw new Error("Variable change cancelled.");
|
|
25
25
|
}
|
|
@@ -45,19 +45,19 @@ function variablesError(status, code, message) {
|
|
|
45
45
|
const details = [code, message].filter((value) => value !== void 0).join(": ");
|
|
46
46
|
return /* @__PURE__ */ new Error(`Variables request failed (${status})${details ? `: ${details}` : ""}.`);
|
|
47
47
|
}
|
|
48
|
-
async function requestForApplet(
|
|
48
|
+
async function requestForApplet(request) {
|
|
49
49
|
const { code, org } = await loadAppletConfig(process.cwd());
|
|
50
50
|
return {
|
|
51
51
|
code,
|
|
52
|
-
response: await fetchWithOrgAuth(org,
|
|
52
|
+
response: await fetchWithOrgAuth(org, (instanceUrl, accessToken) => request(instanceUrl, accessToken, code))
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
async function runVariablesSet(options) {
|
|
56
56
|
const value = await getValue(options);
|
|
57
57
|
const manifest = await loadAppletConfig(process.cwd());
|
|
58
58
|
await confirmLiveChange(manifest.code, options);
|
|
59
|
-
const fetcher =
|
|
60
|
-
const response = await fetchWithOrgAuth(manifest.org,
|
|
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)}`, {
|
|
61
61
|
method: "PUT",
|
|
62
62
|
headers: {
|
|
63
63
|
Authorization: `Bearer ${accessToken}`,
|
|
@@ -75,9 +75,9 @@ async function runVariablesSet(options) {
|
|
|
75
75
|
const { data } = variableResponseSchema.parse(await response.json());
|
|
76
76
|
console.log(`Set ${data.key} ${data.secret ? "(secret)" : data.value ?? value} for applet "${manifest.code}".`);
|
|
77
77
|
}
|
|
78
|
-
async function runVariablesList(
|
|
79
|
-
const fetcher =
|
|
80
|
-
const { code, response } = await requestForApplet(
|
|
78
|
+
async function runVariablesList() {
|
|
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}` } }));
|
|
81
81
|
if (!response.ok) {
|
|
82
82
|
const { code: errorCode, message } = await readErrorDetails(response);
|
|
83
83
|
throw variablesError(response.status, errorCode, message);
|
|
@@ -92,8 +92,8 @@ async function runVariablesList(options) {
|
|
|
92
92
|
async function runVariablesDelete(options) {
|
|
93
93
|
const manifest = await loadAppletConfig(process.cwd());
|
|
94
94
|
await confirmLiveChange(manifest.code, options);
|
|
95
|
-
const fetcher =
|
|
96
|
-
const response = await fetchWithOrgAuth(manifest.org,
|
|
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)}`, {
|
|
97
97
|
method: "DELETE",
|
|
98
98
|
headers: { Authorization: `Bearer ${accessToken}` }
|
|
99
99
|
}));
|
package/dist/vite.d.ts
CHANGED
|
@@ -1,63 +1,6 @@
|
|
|
1
|
-
import { o as RegisteredAppletSourceDefinition } from "./manifest-
|
|
1
|
+
import { o as RegisteredAppletSourceDefinition } from "./manifest-C6_F4bL8.js";
|
|
2
2
|
import { PluginOption } from "vite";
|
|
3
|
-
//#region ../shared/auth/src/store.d.mts
|
|
4
|
-
interface SessionCredentials {
|
|
5
|
-
type: "session";
|
|
6
|
-
accessToken: string;
|
|
7
|
-
expiresAt?: number;
|
|
8
|
-
organizationId: string;
|
|
9
|
-
orgCode: string;
|
|
10
|
-
}
|
|
11
|
-
interface StoreOptions {
|
|
12
|
-
env?: NodeJS.ProcessEnv;
|
|
13
|
-
homeDir?: string;
|
|
14
|
-
}
|
|
15
|
-
//#endregion
|
|
16
|
-
//#region ../shared/auth/src/device.d.mts
|
|
17
|
-
interface MeResponse {
|
|
18
|
-
memberships: Array<{
|
|
19
|
-
code: string;
|
|
20
|
-
name: string;
|
|
21
|
-
orgId: string;
|
|
22
|
-
}>;
|
|
23
|
-
organization: {
|
|
24
|
-
code: string;
|
|
25
|
-
id: string;
|
|
26
|
-
} | null;
|
|
27
|
-
person: {
|
|
28
|
-
email: string;
|
|
29
|
-
firstName: string;
|
|
30
|
-
id: string;
|
|
31
|
-
lastName: string;
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
interface DeviceLoginOptions {
|
|
35
|
-
expectedOrg?: string;
|
|
36
|
-
fetch?: typeof fetch;
|
|
37
|
-
noBrowser?: boolean;
|
|
38
|
-
now?: () => number;
|
|
39
|
-
openUrl?: (url: string) => void | Promise<void>;
|
|
40
|
-
print?: (message: string) => void;
|
|
41
|
-
sleep?: (milliseconds: number) => Promise<void>;
|
|
42
|
-
store?: StoreOptions;
|
|
43
|
-
}
|
|
44
|
-
interface DeviceLoginResult {
|
|
45
|
-
credentials: SessionCredentials;
|
|
46
|
-
me: MeResponse;
|
|
47
|
-
membership: MeResponse["memberships"][number];
|
|
48
|
-
}
|
|
49
|
-
declare function loginWithDevice(instanceUrl: string, options?: DeviceLoginOptions): Promise<DeviceLoginResult>;
|
|
50
|
-
//#endregion
|
|
51
|
-
//#region src/auth.d.ts
|
|
52
|
-
interface OrgAuthOptions {
|
|
53
|
-
fetch?: typeof fetch;
|
|
54
|
-
login?: typeof loginWithDevice;
|
|
55
|
-
stdinIsTTY?: boolean;
|
|
56
|
-
store?: StoreOptions;
|
|
57
|
-
}
|
|
58
|
-
//#endregion
|
|
59
3
|
//#region src/vite.d.ts
|
|
60
|
-
|
|
61
|
-
declare function applet<const M extends RegisteredAppletSourceDefinition>(sourceDefinition: M, options?: AppletOptions): PluginOption[];
|
|
4
|
+
declare function applet<const M extends RegisteredAppletSourceDefinition>(sourceDefinition: M): PluginOption[];
|
|
62
5
|
//#endregion
|
|
63
|
-
export {
|
|
6
|
+
export { applet };
|
package/dist/vite.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { n as meSchema } from "./me-BW7Paary.js";
|
|
2
|
-
import { i as APPLET_CODE_PATTERN, n as appletManifestSchema, r as appletSourceDefinitionSchema } from "./manifest-
|
|
3
|
-
import { a as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { i as APPLET_CODE_PATTERN, n as appletManifestSchema, r as appletSourceDefinitionSchema } from "./manifest-CJSL9GuC.js";
|
|
3
|
+
import { a as openQueryCacheDatabase } from "./query-cache-CXmAyLv3.js";
|
|
4
|
+
import { d as HITCH_USER_HEADER, u as HITCH_SESSION_HEADER } from "./headers-DkNr9MLJ.js";
|
|
5
|
+
import { a as workflowOutcomeSchema, n as runWorkflowJournal } from "./workflow-engine-BOTzURKM.js";
|
|
6
|
+
import { c as bearerToken, d as resolveAuthForOrg, f as resolveInstanceUrl, l as organizationInstanceUrl, t as resolveWorkspaceOrg, u as rejectEnvironmentKey } from "./workspace-D0dnnlxL.js";
|
|
7
|
+
import { c as writeClientEntry, i as writeRegisterDeclaration, l as writeManifestGen, r as syncContract, s as writeAppletRoot, u as writeServerEntry } from "./generate-BEIYs17x.js";
|
|
6
8
|
import { randomUUID } from "node:crypto";
|
|
7
9
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
8
10
|
import { appendFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
@@ -52,7 +54,7 @@ function createDevProxy(options) {
|
|
|
52
54
|
[...headers.keys()].filter((name) => REQUEST_DROP.has(name) || name.startsWith("x-hitch-")).forEach((name) => headers.delete(name));
|
|
53
55
|
headers.set("authorization", `Bearer ${options.token}`);
|
|
54
56
|
const url = new URL(request.url);
|
|
55
|
-
const upstream = await
|
|
57
|
+
const upstream = await globalThis.fetch(`${options.orgUrl}${url.pathname}${url.search}`, {
|
|
56
58
|
method: request.method,
|
|
57
59
|
headers,
|
|
58
60
|
body: request.body,
|
|
@@ -317,6 +319,20 @@ function clientBootstrapScript(parentOrigin, appletCode) {
|
|
|
317
319
|
: null
|
|
318
320
|
});
|
|
319
321
|
|
|
322
|
+
// Opened here so it is ready by the time the applet module restores its
|
|
323
|
+
// query cache. A failure is reported when the module reads the promise.
|
|
324
|
+
Object.defineProperty(window, "__hitchCacheDatabase", {
|
|
325
|
+
configurable: false,
|
|
326
|
+
writable: false,
|
|
327
|
+
value: window.parent !== window && parentOrigin !== null
|
|
328
|
+
? (function () {
|
|
329
|
+
var database = (${openQueryCacheDatabase.toString()})();
|
|
330
|
+
database.catch(function () {});
|
|
331
|
+
return database;
|
|
332
|
+
})()
|
|
333
|
+
: null
|
|
334
|
+
});
|
|
335
|
+
|
|
320
336
|
function applyTheme(theme) {
|
|
321
337
|
document.documentElement.classList.toggle("dark", theme === "dark");
|
|
322
338
|
}
|
|
@@ -421,7 +437,7 @@ function clientBootstrapScript(parentOrigin, appletCode) {
|
|
|
421
437
|
});
|
|
422
438
|
})();`;
|
|
423
439
|
}
|
|
424
|
-
function applet(sourceDefinition
|
|
440
|
+
function applet(sourceDefinition) {
|
|
425
441
|
const parsedSourceDefinition = appletSourceDefinitionSchema.safeParse(sourceDefinition);
|
|
426
442
|
if (!parsedSourceDefinition.success) {
|
|
427
443
|
const raw = sourceDefinition;
|
|
@@ -458,7 +474,7 @@ function applet(sourceDefinition, options = {}) {
|
|
|
458
474
|
const routesDirectory = resolve(resolvedRoot, "src/client/routes");
|
|
459
475
|
const hasClient = existsSync(routesDirectory);
|
|
460
476
|
const hasServer = existsSync(resolve(resolvedRoot, "src/server/main.ts"));
|
|
461
|
-
if (!hasServer && parsedDefinition.data.telephony?.events
|
|
477
|
+
if (!hasServer && parsedDefinition.data.telephony?.events?.length) throw new Error("An applet with telephony events must have src/server/main.ts.");
|
|
462
478
|
if (!hasServer && (parsedDefinition.data.schedules?.length ?? 0) > 0) throw new Error("An applet with schedules must have src/server/main.ts.");
|
|
463
479
|
const legacyMain = resolve(resolvedRoot, "src/client/main.tsx");
|
|
464
480
|
const indexHtml = resolve(resolvedRoot, "index.html");
|
|
@@ -489,6 +505,11 @@ function applet(sourceDefinition, options = {}) {
|
|
|
489
505
|
org: resolveWorkspaceOrg(callerRoot),
|
|
490
506
|
...parsedDefinition.data
|
|
491
507
|
});
|
|
508
|
+
const clsxFromCn = {
|
|
509
|
+
name: "hitch-clsx",
|
|
510
|
+
resolveId: (id) => id === "clsx" ? "\0hitch:clsx" : void 0,
|
|
511
|
+
load: (id) => id === "\0hitch:clsx" ? "export { clsx, clsx as default } from \"cn\";" : void 0
|
|
512
|
+
};
|
|
492
513
|
const orchestrator = {
|
|
493
514
|
name: "hitch-applet",
|
|
494
515
|
enforce: "pre",
|
|
@@ -508,9 +529,9 @@ function applet(sourceDefinition, options = {}) {
|
|
|
508
529
|
});
|
|
509
530
|
clearedOutDir = true;
|
|
510
531
|
}
|
|
511
|
-
if (environment.command === "build") themeStylesheetUrl = `${organizationInstanceUrl(await resolveInstanceUrl(
|
|
512
|
-
if (environment.command === "build"
|
|
513
|
-
contractSync ??= syncContract(resolve(root, ".hitch"), manifest
|
|
532
|
+
if (environment.command === "build") themeStylesheetUrl = `${organizationInstanceUrl(await resolveInstanceUrl(), manifest.org)}/theme.css`;
|
|
533
|
+
if (environment.command === "build") {
|
|
534
|
+
contractSync ??= syncContract(resolve(root, ".hitch"), manifest);
|
|
514
535
|
await contractSync;
|
|
515
536
|
}
|
|
516
537
|
const hasHitchGen = existsSync(resolve(root, ".hitch/index.ts"));
|
|
@@ -526,12 +547,12 @@ function applet(sourceDefinition, options = {}) {
|
|
|
526
547
|
hasHitchGen ? void 0 : writeRegisterDeclaration(resolve(root, ".hitch"))
|
|
527
548
|
]);
|
|
528
549
|
if (environment.command === "serve" && environment.mode !== "test" && environment.isPreview !== true) {
|
|
529
|
-
const instanceUrl = await resolveInstanceUrl(
|
|
550
|
+
const instanceUrl = await resolveInstanceUrl();
|
|
530
551
|
const orgUrl = organizationInstanceUrl(instanceUrl, manifest.org);
|
|
531
|
-
const auth = await resolveAuthForOrg(instanceUrl, manifest.org
|
|
552
|
+
const auth = await resolveAuthForOrg(instanceUrl, manifest.org);
|
|
532
553
|
if (auth === void 0) throw new Error("Not logged in. Run applet login.");
|
|
533
554
|
const token = bearerToken(auth);
|
|
534
|
-
const meResponse = await
|
|
555
|
+
const meResponse = await globalThis.fetch(`${orgUrl}/api/v1/me`, { headers: { authorization: `Bearer ${token}` } });
|
|
535
556
|
rejectEnvironmentKey(meResponse, auth);
|
|
536
557
|
if (meResponse.status === 401) throw new Error("Your login expired. Run applet login.");
|
|
537
558
|
if (!meResponse.ok) throw new Error(`Hitch returned ${meResponse.status} for /api/v1/me.`);
|
|
@@ -540,7 +561,6 @@ function applet(sourceDefinition, options = {}) {
|
|
|
540
561
|
orgUrl,
|
|
541
562
|
token,
|
|
542
563
|
source: auth.source,
|
|
543
|
-
fetch: options.fetch,
|
|
544
564
|
warn: (message) => devLogger?.warn(message),
|
|
545
565
|
intercept: (request) => devWorkflows?.handle(request)
|
|
546
566
|
});
|
|
@@ -585,8 +605,18 @@ function applet(sourceDefinition, options = {}) {
|
|
|
585
605
|
}
|
|
586
606
|
}
|
|
587
607
|
}
|
|
608
|
+
if (environment.mode === "test") {
|
|
609
|
+
const colocated = (await readdir(resolve(root, "src"), { recursive: true })).filter((path) => /\.(test|spec)\.[cm]?[jt]sx?$/.test(path));
|
|
610
|
+
if (colocated.length > 0) throw new Error(`Applet tests run only from the test folder. Move ${colocated.map((path) => `src/${path}`).join(", ")} to test/.`);
|
|
611
|
+
}
|
|
588
612
|
return {
|
|
589
613
|
base: `/${manifest.code}/`,
|
|
614
|
+
test: { include: ["test/**/*.test.{ts,tsx}"] },
|
|
615
|
+
resolve: { alias: {
|
|
616
|
+
"clsx/lite": "cn/lite",
|
|
617
|
+
"tailwind-merge": "cn"
|
|
618
|
+
} },
|
|
619
|
+
optimizeDeps: { rolldownOptions: { plugins: [clsxFromCn] } },
|
|
590
620
|
...hasServer && { environments: { worker: { build: { rollupOptions: { output: { codeSplitting: false } } } } } }
|
|
591
621
|
};
|
|
592
622
|
},
|
|
@@ -777,9 +807,14 @@ function applet(sourceDefinition, options = {}) {
|
|
|
777
807
|
...plugin,
|
|
778
808
|
apply: ((_config, { mode }) => mode !== "test")
|
|
779
809
|
}));
|
|
810
|
+
const hasClientSource = existsSync(resolve("src/client/routes"));
|
|
780
811
|
return [
|
|
781
812
|
orchestrator,
|
|
782
|
-
|
|
813
|
+
{
|
|
814
|
+
...clsxFromCn,
|
|
815
|
+
enforce: "pre"
|
|
816
|
+
},
|
|
817
|
+
...hasClientSource ? [tanstackRouter({
|
|
783
818
|
generatedRouteTree: ".hitch/routeTree.gen.ts",
|
|
784
819
|
routesDirectory: "src/client/routes",
|
|
785
820
|
routeFileIgnorePattern: "__root",
|
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
//#region src/headers.ts
|
|
3
|
-
const HITCH_USER_HEADER = "x-hitch-user";
|
|
4
|
-
const HITCH_SESSION_HEADER = "x-hitch-session";
|
|
5
|
-
const HITCH_APPLET_HEADER = "x-hitch-applet";
|
|
6
|
-
const HITCH_APPLET_TOKEN_HEADER = "x-hitch-applet-token";
|
|
7
|
-
//#endregion
|
|
8
2
|
//#region src/server/workflow-protocol.ts
|
|
9
3
|
const journalEntrySchema = z.discriminatedUnion("kind", [
|
|
10
4
|
z.object({
|
|
@@ -114,4 +108,4 @@ async function runWorkflowJournal(engine, invoke) {
|
|
|
114
108
|
}
|
|
115
109
|
}
|
|
116
110
|
//#endregion
|
|
117
|
-
export { workflowOutcomeSchema as a,
|
|
111
|
+
export { workflowOutcomeSchema as a, workflowInvocationRequestSchema as i, runWorkflowJournal as n, journalEntrySchema as r, WorkflowFailedError as t };
|