@hitch42/applet 0.1.1-beta.7 → 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 +14 -1
- package/dist/_internal/server.js +122 -118
- package/dist/applet.js +22 -11
- package/dist/build-Bh_S5BUv.js +2 -0
- package/dist/{build-DauirTcY.js → build-CEfFoIZZ.js} +1 -1
- package/dist/{ci-gPrwo6C0.js → ci-BKw14X2h.js} +14 -13
- package/dist/client.d.ts +3 -3
- package/dist/{contract-DB9QQhD9.d.ts → contract-CsUpTBe0.d.ts} +1 -1
- package/dist/{deploy-CqrtNJ1x.js → deploy-wGYjwXrx.js} +139 -88
- package/dist/email-DBTVhNB_.js +62 -0
- package/dist/{generate-BIifT6PK.js → generate-BEIYs17x.js} +70 -32
- package/dist/generate-Dox-OYt6.js +2 -0
- package/dist/headers-DkNr9MLJ.js +17 -0
- package/dist/index.d.ts +122 -10
- package/dist/index.js +142 -26
- package/dist/{init-Wu6XmyVc.js → init-6oGPM46R.js} +15 -17
- package/dist/{load-config-BknBkdRs.js → load-config-xEdTXs0y.js} +2 -2
- package/dist/log-context-zu8U9Sjm.js +73 -0
- package/dist/{login-iT9MRuaw.js → login-CUx3TmFQ.js} +1 -1
- package/dist/{logs-B-qZGXSK.js → logs-DSjuEN0Q.js} +20 -22
- package/dist/{manifest-C489nYUy.d.ts → manifest-C6_F4bL8.d.ts} +7 -0
- package/dist/{manifest-Bd04cWhu.js → manifest-CJSL9GuC.js} +22 -3
- package/dist/me-BW7Paary.js +32 -0
- package/dist/{project-C_rtpjp8.js → project-BRZGd6xq.js} +202 -20
- package/dist/prompt-ChS-grYO.js +29 -0
- package/dist/query-cache-CXmAyLv3.js +82 -0
- package/dist/react.d.ts +3 -2
- package/dist/react.js +98 -80
- package/dist/schedules-C8_Svr4h.js +42 -0
- package/dist/server.d.ts +9 -4
- package/dist/server.js +29 -8
- package/dist/telephony-protocol-D-nf3Gca.d.ts +76 -0
- package/dist/telephony.d.ts +97 -0
- package/dist/telephony.js +726 -0
- package/dist/{upload-YbRKEqR6.d.ts → upload-DKZzz5kW.d.ts} +6 -6
- package/dist/{variables-DcwMeIau.js → variables-DT5RyHdH.js} +14 -39
- package/dist/vite.d.ts +3 -60
- package/dist/vite.js +497 -27
- package/dist/workflow-engine-BOTzURKM.js +111 -0
- package/dist/{workspace-B6lenAS5.js → workspace-D0dnnlxL.js} +37 -39
- package/package.json +18 -5
- package/scaffold/.agents/skills/hitch-applets/SKILL.md +50 -18
- package/scaffold/.agents/skills/hitch-applets/references/email-tracking.md +49 -0
- package/scaffold/.agents/skills/hitch-applets/references/files.md +3 -3
- package/scaffold/.agents/skills/hitch-applets/references/manifest.md +12 -2
- package/scaffold/.agents/skills/hitch-applets/references/markdown.md +2 -0
- package/scaffold/.agents/skills/hitch-applets/references/performance.md +1 -1
- package/scaffold/.agents/skills/hitch-applets/references/records.md +27 -4
- package/scaffold/.agents/skills/hitch-applets/references/schedules.md +7 -2
- package/scaffold/.agents/skills/hitch-applets/references/server.md +0 -3
- package/scaffold/.agents/skills/hitch-applets/references/workflows.md +11 -3
- package/scaffold/.agents/skills/hitch-cli/SKILL.md +20 -20
- package/scaffold/.agents/skills/hitch-data/SKILL.md +3 -2
- package/scaffold/.agents/skills/hitch-data/references/attributes.md +7 -1
- package/scaffold/.agents/skills/hitch-data/references/limits.md +23 -23
- package/scaffold/.agents/skills/hitch-theory/SKILL.md +151 -0
- 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-DhNDp7ji.js +0 -2
- package/dist/generate-DSk8ihsC.js +0 -2
package/dist/client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { f as RegisteredContract, m as RegisteredRouter, p as RegisteredManifest } from "./manifest-
|
|
2
|
-
import { t as NarrowContract } from "./contract-
|
|
1
|
+
import { f as RegisteredContract, m as RegisteredRouter, p as RegisteredManifest } from "./manifest-C6_F4bL8.js";
|
|
2
|
+
import { t as NarrowContract } from "./contract-CsUpTBe0.js";
|
|
3
3
|
import { t as WithBatchRecorder } from "./batch-Qa4B4-Yp.js";
|
|
4
|
-
import { o as WithFilesUpload } from "./upload-
|
|
4
|
+
import { o as WithFilesUpload } from "./upload-DKZzz5kW.js";
|
|
5
5
|
import { RouterClient } from "@orpc/server";
|
|
6
6
|
import { ContractRouterClient } from "@orpc/contract";
|
|
7
7
|
import { NestedClient } from "@orpc/client";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as AppletManifest } from "./manifest-
|
|
1
|
+
import { n as AppletManifest } from "./manifest-C6_F4bL8.js";
|
|
2
2
|
import { AnyContractRouter } from "@orpc/contract";
|
|
3
3
|
//#region src/hitch/contract.d.ts
|
|
4
4
|
type ManifestObjectFor<Manifest, Code> = Manifest extends {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { i as readWorkspaceConfig, n as fetchWithOrgAuth } from "./workspace-
|
|
2
|
-
import { a as loadGitHubActionsSources, n as githubActionsContext, r as hitchResponseError, t as fetchWithGitHubActions } from "./ci-
|
|
3
|
-
import { n as buildPreparedApplet, r as prepareWorkspaceBuild, t as buildApplet } from "./build-
|
|
1
|
+
import { i as readWorkspaceConfig, n as fetchWithOrgAuth } from "./workspace-D0dnnlxL.js";
|
|
2
|
+
import { a as loadGitHubActionsSources, n as githubActionsContext, r as hitchResponseError, t as fetchWithGitHubActions } from "./ci-BKw14X2h.js";
|
|
3
|
+
import { n as buildPreparedApplet, r as prepareWorkspaceBuild, t as buildApplet } from "./build-CEfFoIZZ.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
5
6
|
import { existsSync } from "node:fs";
|
|
6
|
-
import { readFile, readdir } from "node:fs/promises";
|
|
7
|
-
import { relative, resolve, sep } from "node:path";
|
|
8
|
-
import { execFile } from "node:child_process";
|
|
7
|
+
import { lstat, readFile, readdir, readlink } from "node:fs/promises";
|
|
8
|
+
import { dirname, relative, resolve, sep } from "node:path";
|
|
9
|
+
import { execFile, spawn } from "node:child_process";
|
|
9
10
|
import { promisify } from "node:util";
|
|
10
11
|
import { createGzip } from "node:zlib";
|
|
11
12
|
//#region \0rolldown/runtime.js
|
|
@@ -2307,11 +2308,112 @@ var require_pack = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2307
2308
|
}
|
|
2308
2309
|
}));
|
|
2309
2310
|
//#endregion
|
|
2310
|
-
//#region src/
|
|
2311
|
+
//#region src/source-hash.ts
|
|
2311
2312
|
var import_tar_stream = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports) => {
|
|
2312
2313
|
exports.extract = require_extract();
|
|
2313
2314
|
exports.pack = require_pack();
|
|
2314
2315
|
})))(), 1);
|
|
2316
|
+
const execFileAsync$1 = promisify(execFile);
|
|
2317
|
+
function gitEnvironment() {
|
|
2318
|
+
return Object.fromEntries(Object.entries(process.env).filter(([key]) => !key.startsWith("GIT_")));
|
|
2319
|
+
}
|
|
2320
|
+
var SourceHashUnavailableError = class extends Error {
|
|
2321
|
+
constructor() {
|
|
2322
|
+
super("Git is unavailable or the applet is outside a git repository.");
|
|
2323
|
+
}
|
|
2324
|
+
};
|
|
2325
|
+
function isMissingPath(error) {
|
|
2326
|
+
return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
|
|
2327
|
+
}
|
|
2328
|
+
async function hashFiles(topLevel, paths, env) {
|
|
2329
|
+
if (paths.length === 0) return [];
|
|
2330
|
+
return new Promise((resolveHashes, reject) => {
|
|
2331
|
+
const child = spawn("git", ["hash-object", "--stdin-paths"], {
|
|
2332
|
+
cwd: topLevel,
|
|
2333
|
+
env
|
|
2334
|
+
});
|
|
2335
|
+
const stdout = [];
|
|
2336
|
+
const stderr = [];
|
|
2337
|
+
child.stdout.on("data", (chunk) => stdout.push(chunk));
|
|
2338
|
+
child.stderr.on("data", (chunk) => stderr.push(chunk));
|
|
2339
|
+
child.stdin.on("error", reject);
|
|
2340
|
+
child.on("error", reject);
|
|
2341
|
+
child.on("close", (code) => {
|
|
2342
|
+
if (code !== 0) {
|
|
2343
|
+
reject(/* @__PURE__ */ new Error(`git hash-object failed (${code}): ${Buffer.concat(stderr).toString("utf8").trim()}`));
|
|
2344
|
+
return;
|
|
2345
|
+
}
|
|
2346
|
+
const hashes = Buffer.concat(stdout).toString("utf8").trimEnd().split("\n");
|
|
2347
|
+
if (hashes.length !== paths.length || hashes.some((hash) => !/^[0-9a-f]{40,64}$/.test(hash))) {
|
|
2348
|
+
reject(/* @__PURE__ */ new Error("git hash-object returned an unexpected number of hashes."));
|
|
2349
|
+
return;
|
|
2350
|
+
}
|
|
2351
|
+
resolveHashes(hashes);
|
|
2352
|
+
});
|
|
2353
|
+
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(""));
|
|
2354
|
+
});
|
|
2355
|
+
}
|
|
2356
|
+
async function sourceHashes(appletRoots) {
|
|
2357
|
+
if (appletRoots.length === 0) return /* @__PURE__ */ new Map();
|
|
2358
|
+
const env = gitEnvironment();
|
|
2359
|
+
const workspaceRoot = dirname(dirname(appletRoots[0]));
|
|
2360
|
+
let topLevel;
|
|
2361
|
+
try {
|
|
2362
|
+
const { stdout } = await execFileAsync$1("git", ["rev-parse", "--show-toplevel"], {
|
|
2363
|
+
cwd: workspaceRoot,
|
|
2364
|
+
env
|
|
2365
|
+
});
|
|
2366
|
+
topLevel = stdout.trim();
|
|
2367
|
+
} catch (error) {
|
|
2368
|
+
if (isMissingPath(error) || error instanceof Error && error.message.includes("not a git repository")) throw new SourceHashUnavailableError();
|
|
2369
|
+
throw error;
|
|
2370
|
+
}
|
|
2371
|
+
const { stdout } = await execFileAsync$1("git", [
|
|
2372
|
+
"ls-files",
|
|
2373
|
+
"-z",
|
|
2374
|
+
"--cached",
|
|
2375
|
+
"--others",
|
|
2376
|
+
"--exclude-standard"
|
|
2377
|
+
], {
|
|
2378
|
+
cwd: topLevel,
|
|
2379
|
+
env,
|
|
2380
|
+
maxBuffer: 67108864
|
|
2381
|
+
});
|
|
2382
|
+
const paths = [...new Set(stdout.split("\0").filter(Boolean))];
|
|
2383
|
+
const present = (await Promise.all(paths.map(async (path) => {
|
|
2384
|
+
const absolutePath = resolve(topLevel, path);
|
|
2385
|
+
try {
|
|
2386
|
+
const stat = await lstat(absolutePath);
|
|
2387
|
+
if (stat.isFile()) return {
|
|
2388
|
+
path,
|
|
2389
|
+
kind: "file"
|
|
2390
|
+
};
|
|
2391
|
+
if (stat.isSymbolicLink()) return {
|
|
2392
|
+
path,
|
|
2393
|
+
kind: "link",
|
|
2394
|
+
contentId: await readlink(absolutePath)
|
|
2395
|
+
};
|
|
2396
|
+
return;
|
|
2397
|
+
} catch (error) {
|
|
2398
|
+
if (isMissingPath(error)) return void 0;
|
|
2399
|
+
throw error;
|
|
2400
|
+
}
|
|
2401
|
+
}))).filter((entry) => entry !== void 0);
|
|
2402
|
+
const regularPaths = present.filter((entry) => entry.kind === "file").map((entry) => entry.path);
|
|
2403
|
+
const hashes = await hashFiles(topLevel, regularPaths, env);
|
|
2404
|
+
const contentIds = /* @__PURE__ */ new Map();
|
|
2405
|
+
present.filter((entry) => entry.kind === "link").forEach((entry) => contentIds.set(entry.path, entry.contentId));
|
|
2406
|
+
regularPaths.forEach((path, index) => contentIds.set(path, hashes[index]));
|
|
2407
|
+
const appletsDirectory = relative(topLevel, resolve(workspaceRoot, "applets")).split(sep).join("/");
|
|
2408
|
+
return new Map(appletRoots.map((appletRoot) => {
|
|
2409
|
+
const appletDirectory = relative(topLevel, appletRoot).split(sep).join("/");
|
|
2410
|
+
const digest = createHash("sha256");
|
|
2411
|
+
[...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`));
|
|
2412
|
+
return [appletRoot, digest.digest("hex")];
|
|
2413
|
+
}));
|
|
2414
|
+
}
|
|
2415
|
+
//#endregion
|
|
2416
|
+
//#region src/deploy.ts
|
|
2315
2417
|
const execFileAsync = promisify(execFile);
|
|
2316
2418
|
var WorkspaceDeployError = class extends Error {
|
|
2317
2419
|
constructor(failedApplets) {
|
|
@@ -2363,9 +2465,6 @@ async function createBundle(distDir) {
|
|
|
2363
2465
|
body.set(bundle);
|
|
2364
2466
|
return body;
|
|
2365
2467
|
}
|
|
2366
|
-
function gitEnvironment() {
|
|
2367
|
-
return Object.fromEntries(Object.entries(process.env).filter(([key]) => !key.startsWith("GIT_")));
|
|
2368
|
-
}
|
|
2369
2468
|
async function readGitInfo(appletRoot) {
|
|
2370
2469
|
const env = gitEnvironment();
|
|
2371
2470
|
try {
|
|
@@ -2399,13 +2498,14 @@ function releaseForm(manifest, bundle) {
|
|
|
2399
2498
|
body.set("bundle", new File([bundle], "bundle.tar.gz", { type: "application/gzip" }));
|
|
2400
2499
|
return body;
|
|
2401
2500
|
}
|
|
2402
|
-
async function deployWithOrgAuth(appletRoot, distDir, manifest,
|
|
2403
|
-
const fetcher =
|
|
2501
|
+
async function deployWithOrgAuth(appletRoot, distDir, manifest, sourceHash) {
|
|
2502
|
+
const fetcher = globalThis.fetch;
|
|
2404
2503
|
const [bundle, git] = await Promise.all([createBundle(distDir), readGitInfo(appletRoot)]);
|
|
2405
|
-
return fetchWithOrgAuth(manifest.org,
|
|
2504
|
+
return fetchWithOrgAuth(manifest.org, (instanceUrl, accessToken) => {
|
|
2406
2505
|
const body = releaseForm(manifest, bundle);
|
|
2407
2506
|
body.set("gitDirty", String(git.gitDirty));
|
|
2408
2507
|
if (git.gitSha !== void 0) body.set("gitSha", git.gitSha);
|
|
2508
|
+
if (sourceHash !== void 0) body.set("sourceHash", sourceHash);
|
|
2409
2509
|
return fetcher(`${instanceUrl}/api/v1/applets/${manifest.code}/releases`, {
|
|
2410
2510
|
method: "POST",
|
|
2411
2511
|
headers: { Authorization: `Bearer ${accessToken}` },
|
|
@@ -2413,12 +2513,13 @@ async function deployWithOrgAuth(appletRoot, distDir, manifest, options) {
|
|
|
2413
2513
|
});
|
|
2414
2514
|
});
|
|
2415
2515
|
}
|
|
2416
|
-
async function deployWithGitHubActions(context, appletRoot, distDir, manifest,
|
|
2417
|
-
const fetcher =
|
|
2516
|
+
async function deployWithGitHubActions(context, appletRoot, distDir, manifest, sourceHash) {
|
|
2517
|
+
const fetcher = globalThis.fetch;
|
|
2418
2518
|
const [bundle, sourceDirectory] = await Promise.all([createBundle(distDir), repositoryDirectory(appletRoot)]);
|
|
2419
|
-
return fetchWithGitHubActions(context,
|
|
2519
|
+
return fetchWithGitHubActions(context, (instanceUrl, accessToken) => {
|
|
2420
2520
|
const body = releaseForm(manifest, bundle);
|
|
2421
2521
|
body.set("source_directory", sourceDirectory);
|
|
2522
|
+
if (sourceHash !== void 0) body.set("source_hash", sourceHash);
|
|
2422
2523
|
return fetcher(`${instanceUrl}/api/ci/v1/applets/${manifest.code}/releases`, {
|
|
2423
2524
|
method: "POST",
|
|
2424
2525
|
headers: { Authorization: `Bearer ${accessToken}` },
|
|
@@ -2426,12 +2527,13 @@ async function deployWithGitHubActions(context, appletRoot, distDir, manifest, o
|
|
|
2426
2527
|
});
|
|
2427
2528
|
});
|
|
2428
2529
|
}
|
|
2429
|
-
async function deployApplet(appletRoot, options, logPrefix = "") {
|
|
2430
|
-
const github = githubActionsContext(
|
|
2530
|
+
async function deployApplet(appletRoot, options, logPrefix = "", sourceHash) {
|
|
2531
|
+
const github = githubActionsContext();
|
|
2532
|
+
sourceHash ??= (await computeSourceHash([appletRoot], github !== void 0)).get(appletRoot);
|
|
2431
2533
|
if (options.dist === void 0) await buildApplet(appletRoot);
|
|
2432
2534
|
const distDir = resolve(appletRoot, options.dist ?? ".hitch/dist");
|
|
2433
2535
|
const manifest = await readManifest(distDir);
|
|
2434
|
-
const response = github === void 0 ? await deployWithOrgAuth(appletRoot, distDir, manifest,
|
|
2536
|
+
const response = github === void 0 ? await deployWithOrgAuth(appletRoot, distDir, manifest, sourceHash) : await deployWithGitHubActions(github, appletRoot, distDir, manifest, sourceHash);
|
|
2435
2537
|
if (!response.ok) throw await hitchResponseError(response, "Deploy failed");
|
|
2436
2538
|
const result = await response.json();
|
|
2437
2539
|
console.log(`${logPrefix}Deployed release ${result.data.id} (${result.promoted ? "promoted" : "not promoted"}).`);
|
|
@@ -2452,95 +2554,44 @@ async function workspaceAppletRoots(workspaceRoot) {
|
|
|
2452
2554
|
if (roots.length === 0) throw new Error(`No applets were found under ${appletsDir}.`);
|
|
2453
2555
|
return roots;
|
|
2454
2556
|
}
|
|
2455
|
-
async function
|
|
2557
|
+
async function computeSourceHash(appletRoots, required) {
|
|
2456
2558
|
try {
|
|
2457
|
-
await
|
|
2458
|
-
"diff",
|
|
2459
|
-
"--quiet",
|
|
2460
|
-
base,
|
|
2461
|
-
"HEAD",
|
|
2462
|
-
"--",
|
|
2463
|
-
...pathspecs
|
|
2464
|
-
], {
|
|
2465
|
-
cwd: topLevel,
|
|
2466
|
-
env
|
|
2467
|
-
});
|
|
2468
|
-
return false;
|
|
2559
|
+
return await sourceHashes(appletRoots);
|
|
2469
2560
|
} catch (error) {
|
|
2470
|
-
if (error instanceof
|
|
2561
|
+
if (!required && error instanceof SourceHashUnavailableError) return /* @__PURE__ */ new Map();
|
|
2471
2562
|
throw error;
|
|
2472
2563
|
}
|
|
2473
2564
|
}
|
|
2474
|
-
async function
|
|
2475
|
-
const
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
"cat-file",
|
|
2481
|
-
"-e",
|
|
2482
|
-
`${sha}^{commit}`
|
|
2483
|
-
]).catch(() => git([
|
|
2484
|
-
"fetch",
|
|
2485
|
-
"--depth=1",
|
|
2486
|
-
"origin",
|
|
2487
|
-
sha
|
|
2488
|
-
])).then(() => true, () => false);
|
|
2489
|
-
}
|
|
2490
|
-
async function ciDeployDecisions(github, workspaceRoot, appletRoots, options) {
|
|
2491
|
-
const env = gitEnvironment();
|
|
2492
|
-
const [sources, { stdout: topLevelOutput }, directories] = await Promise.all([
|
|
2493
|
-
loadGitHubActionsSources(github, options),
|
|
2494
|
-
execFileAsync("git", ["rev-parse", "--show-toplevel"], {
|
|
2495
|
-
cwd: workspaceRoot,
|
|
2496
|
-
env
|
|
2497
|
-
}),
|
|
2498
|
-
Promise.all(appletRoots.map((appletRoot) => repositoryDirectory(appletRoot)))
|
|
2499
|
-
]);
|
|
2500
|
-
const topLevel = topLevelOutput.trim();
|
|
2501
|
-
const appletsDirectory = relative(topLevel, resolve(workspaceRoot, "applets")).split(sep).join("/");
|
|
2502
|
-
const baseByDirectory = new Map(sources.map((source) => [source.sourceDirectory, source.gitSha]));
|
|
2503
|
-
const bases = new Set(directories.flatMap((directory) => baseByDirectory.get(directory) ?? []));
|
|
2504
|
-
const sharedChanges = /* @__PURE__ */ new Map();
|
|
2505
|
-
for (const base of bases) sharedChanges.set(base, await hasCommit(topLevel, base, env) ? await gitChanged(topLevel, base, [`:(exclude)${appletsDirectory}`], env) : void 0);
|
|
2506
|
-
const decisions = await Promise.all(appletRoots.map(async (appletRoot, index) => {
|
|
2507
|
-
const directory = directories[index];
|
|
2508
|
-
const base = baseByDirectory.get(directory) ?? null;
|
|
2509
|
-
if (base === null) return [appletRoot, {
|
|
2510
|
-
deploy: true,
|
|
2511
|
-
reason: "no CI release to compare"
|
|
2512
|
-
}];
|
|
2513
|
-
const short = base.slice(0, 7);
|
|
2514
|
-
const sharedChanged = sharedChanges.get(base);
|
|
2515
|
-
if (sharedChanged === void 0) return [appletRoot, {
|
|
2516
|
-
deploy: true,
|
|
2517
|
-
reason: `commit ${short} is not in the repository`
|
|
2518
|
-
}];
|
|
2519
|
-
if (await gitChanged(topLevel, base, [directory], env)) return [appletRoot, {
|
|
2565
|
+
async function ciDeployDecisions(github, appletRoots, hashes) {
|
|
2566
|
+
const [sources, directories] = await Promise.all([loadGitHubActionsSources(github), Promise.all(appletRoots.map((appletRoot) => repositoryDirectory(appletRoot)))]);
|
|
2567
|
+
const hashByDirectory = new Map(sources.map((source) => [source.sourceDirectory, source.sourceHash]));
|
|
2568
|
+
return new Map(appletRoots.map((appletRoot, index) => {
|
|
2569
|
+
const sourceHash = hashByDirectory.get(directories[index]);
|
|
2570
|
+
if (sourceHash === null || sourceHash === void 0) return [appletRoot, {
|
|
2520
2571
|
deploy: true,
|
|
2521
|
-
reason:
|
|
2572
|
+
reason: "no release with a source hash to compare"
|
|
2522
2573
|
}];
|
|
2523
|
-
if (
|
|
2574
|
+
if (sourceHash !== hashes.get(appletRoot)) return [appletRoot, {
|
|
2524
2575
|
deploy: true,
|
|
2525
|
-
reason:
|
|
2576
|
+
reason: "files changed since the current release"
|
|
2526
2577
|
}];
|
|
2527
2578
|
return [appletRoot, {
|
|
2528
2579
|
deploy: false,
|
|
2529
|
-
reason:
|
|
2580
|
+
reason: "no changes since the current release"
|
|
2530
2581
|
}];
|
|
2531
2582
|
}));
|
|
2532
|
-
return new Map(decisions);
|
|
2533
2583
|
}
|
|
2534
2584
|
async function runDeploy(options) {
|
|
2535
2585
|
const root = process.cwd();
|
|
2536
|
-
const github = githubActionsContext(
|
|
2586
|
+
const github = githubActionsContext();
|
|
2537
2587
|
if (existsSync(resolve(root, "applet.manifest.ts"))) {
|
|
2538
2588
|
await deployApplet(root, options);
|
|
2539
2589
|
return;
|
|
2540
2590
|
}
|
|
2541
2591
|
if (readWorkspaceConfig(root) === void 0) throw new Error("Run applet deploy in an applet folder or in the workspace root.");
|
|
2542
2592
|
const appletRoots = await workspaceAppletRoots(root);
|
|
2543
|
-
const
|
|
2593
|
+
const hashes = await computeSourceHash(appletRoots, github !== void 0);
|
|
2594
|
+
const decisions = github === void 0 ? void 0 : await ciDeployDecisions(github, appletRoots, hashes);
|
|
2544
2595
|
const selectedRoots = appletRoots.filter((appletRoot) => {
|
|
2545
2596
|
const name = relative(root, appletRoot);
|
|
2546
2597
|
const decision = decisions?.get(appletRoot);
|
|
@@ -2554,14 +2605,14 @@ async function runDeploy(options) {
|
|
|
2554
2605
|
});
|
|
2555
2606
|
if (selectedRoots.length === 0) return;
|
|
2556
2607
|
if (options.dist === void 0) await prepareWorkspaceBuild(root, appletRoots);
|
|
2557
|
-
const interactive = github === void 0 &&
|
|
2608
|
+
const interactive = github === void 0 && process.stdin.isTTY === true;
|
|
2558
2609
|
const deploy = async (appletRoot) => {
|
|
2559
2610
|
const logPrefix = `[${relative(root, appletRoot)}] `;
|
|
2560
2611
|
if (options.dist === void 0) await buildPreparedApplet(appletRoot, ".hitch/dist", interactive ? "" : logPrefix);
|
|
2561
2612
|
await deployApplet(appletRoot, {
|
|
2562
2613
|
...options,
|
|
2563
2614
|
dist: options.dist ?? ".hitch/dist"
|
|
2564
|
-
}, logPrefix);
|
|
2615
|
+
}, logPrefix, hashes.get(appletRoot));
|
|
2565
2616
|
};
|
|
2566
2617
|
if (interactive) {
|
|
2567
2618
|
for (const appletRoot of selectedRoots) await deploy(appletRoot);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/hitch/email.ts
|
|
4
|
+
const emailTagKeySchema = z.string().regex(/^[A-Za-z][A-Za-z0-9_]{0,63}$/);
|
|
5
|
+
const emailTagsSchema = z.record(emailTagKeySchema, z.string().min(1).max(200)).refine((tags) => Object.keys(tags).length <= 10);
|
|
6
|
+
const createEmailPixelInputSchema = z.object({ tags: emailTagsSchema.optional() }).strict();
|
|
7
|
+
const createEmailPixelOutputSchema = z.object({
|
|
8
|
+
id: z.uuid(),
|
|
9
|
+
url: z.url()
|
|
10
|
+
});
|
|
11
|
+
const getEmailTrackerInputSchema = z.object({ id: z.uuid() });
|
|
12
|
+
const markEmailTrackerSentInputSchema = z.object({
|
|
13
|
+
id: z.uuid(),
|
|
14
|
+
sentAt: z.iso.datetime({ offset: true }).optional()
|
|
15
|
+
}).strict();
|
|
16
|
+
const markEmailTrackerSentBodySchema = z.object({ sentAt: z.iso.datetime({ offset: true }).optional() }).strict();
|
|
17
|
+
const emailTrackerSchema = z.object({
|
|
18
|
+
id: z.uuid(),
|
|
19
|
+
url: z.url(),
|
|
20
|
+
tags: emailTagsSchema,
|
|
21
|
+
createdAt: z.iso.datetime(),
|
|
22
|
+
sentAt: z.iso.datetime().nullable(),
|
|
23
|
+
firstHitAt: z.iso.datetime().nullable(),
|
|
24
|
+
lastHitAt: z.iso.datetime().nullable()
|
|
25
|
+
});
|
|
26
|
+
const listEmailTrackersInputSchema = z.object({
|
|
27
|
+
filter: emailTagsSchema.optional(),
|
|
28
|
+
sentAt: z.object({
|
|
29
|
+
$gte: z.iso.datetime({ offset: true }).optional(),
|
|
30
|
+
$lt: z.iso.datetime({ offset: true }).optional()
|
|
31
|
+
}).strict().optional(),
|
|
32
|
+
cursor: z.uuid().optional(),
|
|
33
|
+
limit: z.number().int().min(1).max(200).optional()
|
|
34
|
+
}).strict();
|
|
35
|
+
const listEmailTrackersOutputSchema = z.object({
|
|
36
|
+
trackers: z.array(emailTrackerSchema),
|
|
37
|
+
nextCursor: z.uuid().nullable()
|
|
38
|
+
});
|
|
39
|
+
function emailContract(appletCode) {
|
|
40
|
+
const path = `/v1/applets/${encodeURIComponent(appletCode)}/email/tracking`;
|
|
41
|
+
return { tracking: {
|
|
42
|
+
createPixel: oc.route({
|
|
43
|
+
method: "POST",
|
|
44
|
+
path: `${path}/pixels`,
|
|
45
|
+
successStatus: 201
|
|
46
|
+
}).input(createEmailPixelInputSchema.optional()).output(createEmailPixelOutputSchema),
|
|
47
|
+
markSent: oc.route({
|
|
48
|
+
method: "POST",
|
|
49
|
+
path: `${path}/{id}/sent`
|
|
50
|
+
}).input(markEmailTrackerSentInputSchema).output(emailTrackerSchema),
|
|
51
|
+
get: oc.route({
|
|
52
|
+
method: "GET",
|
|
53
|
+
path: `${path}/{id}`
|
|
54
|
+
}).input(getEmailTrackerInputSchema).output(emailTrackerSchema),
|
|
55
|
+
list: oc.route({
|
|
56
|
+
method: "POST",
|
|
57
|
+
path: `${path}/list`
|
|
58
|
+
}).input(listEmailTrackersInputSchema.optional()).output(listEmailTrackersOutputSchema)
|
|
59
|
+
} };
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { emailTagsSchema as a, listEmailTrackersInputSchema as c, markEmailTrackerSentInputSchema as d, emailTagKeySchema as i, listEmailTrackersOutputSchema as l, createEmailPixelOutputSchema as n, emailTrackerSchema as o, emailContract as r, getEmailTrackerInputSchema as s, createEmailPixelInputSchema as t, markEmailTrackerSentBodySchema as u };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as loadGitHubActionsBuildInputs, n as githubActionsContext } from "./ci-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { f as resolveInstanceUrl, l as organizationInstanceUrl, n as fetchWithOrgAuth } from "./workspace-D0dnnlxL.js";
|
|
2
|
+
import { i as loadGitHubActionsBuildInputs, n as githubActionsContext } from "./ci-BKw14X2h.js";
|
|
3
|
+
import { r as prepareAppletProject } from "./project-BRZGd6xq.js";
|
|
4
|
+
import { t as loadAppletConfig } from "./load-config-xEdTXs0y.js";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { access, mkdir, mkdtemp, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
|
|
@@ -55,7 +55,7 @@ export default createWorkerEntry(server, { code: ${JSON.stringify(appletCode)} }
|
|
|
55
55
|
}
|
|
56
56
|
//#endregion
|
|
57
57
|
//#region src/typegen/operations.ts
|
|
58
|
-
const RECORD_ROUTE = /^\/v1\/([^/]+)(?:\/(\{id\}
|
|
58
|
+
const RECORD_ROUTE = /^\/v1\/([^/]+)(?:\/(\{id\}(?:\/history)?|query|update|aggregate))?$/;
|
|
59
59
|
const COMPONENT_REF_PREFIX$1 = "#/components/schemas/";
|
|
60
60
|
const BATCH_PATH = "/v1/batch";
|
|
61
61
|
const BATCH_ITEM_PATH = "paths./v1/batch.post.requestBody.content.application/json.schema.properties.requests.items";
|
|
@@ -64,6 +64,7 @@ const VERBS = {
|
|
|
64
64
|
"get:": "list",
|
|
65
65
|
"post:": "create",
|
|
66
66
|
"get:{id}": "get",
|
|
67
|
+
"get:{id}/history": "history",
|
|
67
68
|
"patch:{id}": "update",
|
|
68
69
|
"delete:{id}": "delete",
|
|
69
70
|
"post:query": "query",
|
|
@@ -74,6 +75,7 @@ const COMPONENT_RESPONSE_STATUS = {
|
|
|
74
75
|
list: "200",
|
|
75
76
|
create: "201",
|
|
76
77
|
get: "200",
|
|
78
|
+
history: "200",
|
|
77
79
|
update: "200",
|
|
78
80
|
query: "200"
|
|
79
81
|
};
|
|
@@ -149,10 +151,13 @@ function prepareBatchOperation(operation, manifest) {
|
|
|
149
151
|
if (manifest === void 0) return true;
|
|
150
152
|
const object = manifest.objects.find(({ code }) => code === objectCode);
|
|
151
153
|
if (object === void 0) return false;
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
switch (verb) {
|
|
155
|
+
case "create": return object.canCreate;
|
|
156
|
+
case "delete": return object.canDelete;
|
|
157
|
+
case "update":
|
|
158
|
+
case "updateWhere": return object.readWrite.length > 0;
|
|
159
|
+
default: return true;
|
|
160
|
+
}
|
|
156
161
|
});
|
|
157
162
|
if (entries.length === 0) return void 0;
|
|
158
163
|
items.oneOf = entries;
|
|
@@ -166,7 +171,7 @@ function prepareRecordSpec(spec, manifest) {
|
|
|
166
171
|
const prepared = structuredClone(spec);
|
|
167
172
|
prepared.paths = Object.fromEntries(Object.entries(prepared.paths).flatMap(([path, pathItem]) => {
|
|
168
173
|
if (path === BATCH_PATH) {
|
|
169
|
-
if (!isObject$2(pathItem)
|
|
174
|
+
if (!isObject$2(pathItem)) return [];
|
|
170
175
|
const operation = prepareBatchOperation(pathItem.post, manifest);
|
|
171
176
|
return operation === void 0 ? [] : [[path, { post: operation }]];
|
|
172
177
|
}
|
|
@@ -194,6 +199,37 @@ function prepareRecordSpec(spec, manifest) {
|
|
|
194
199
|
});
|
|
195
200
|
return operations.length > 0 ? [[path, Object.fromEntries(operations)]] : [];
|
|
196
201
|
}));
|
|
202
|
+
manifest?.objects.forEach(({ code, optionalAttributes }) => {
|
|
203
|
+
if (optionalAttributes === void 0 || optionalAttributes.length === 0) return;
|
|
204
|
+
const responsePath = `/v1/${code}/{id}`;
|
|
205
|
+
const response = prepared.paths[responsePath]?.get?.responses;
|
|
206
|
+
const schema = isObject$2(response) && isObject$2(response["200"]) ? response["200"].content : void 0;
|
|
207
|
+
const mediaType = isObject$2(schema) && isObject$2(schema["application/json"]) ? schema["application/json"] : void 0;
|
|
208
|
+
const ref = isObject$2(mediaType) && isObject$2(mediaType.schema) ? mediaType.schema.$ref : void 0;
|
|
209
|
+
const recordPath = `paths.${responsePath}.get.responses.200.content.application/json.schema`;
|
|
210
|
+
if (typeof ref !== "string" || !ref.startsWith(COMPONENT_REF_PREFIX$1)) throw new Error(`object "${code}": ${recordPath} expected a component schema $ref, found ${describeValue$1(mediaType)}`);
|
|
211
|
+
const componentName = ref.slice(21);
|
|
212
|
+
const components = isObject$2(prepared.components) ? prepared.components : void 0;
|
|
213
|
+
const record = (isObject$2(components?.schemas) ? components.schemas : void 0)?.[componentName];
|
|
214
|
+
const componentPath = `components.schemas.${componentName}`;
|
|
215
|
+
if (!isObject$2(record) || !isObject$2(record.properties)) throw new Error(`object "${code}": ${componentPath}.properties expected an object, found ${describeValue$1(isObject$2(record) ? record.properties : record)}`);
|
|
216
|
+
const properties = record.properties;
|
|
217
|
+
optionalAttributes.forEach((attributeCode) => {
|
|
218
|
+
const property = properties[attributeCode];
|
|
219
|
+
const propertyPath = `${componentPath}.properties.${attributeCode}`;
|
|
220
|
+
if (!isObject$2(property)) throw new Error(`object "${code}": ${propertyPath} expected an object, found ${describeValue$1(property)}`);
|
|
221
|
+
const types = Array.isArray(property.type) ? property.type : [property.type];
|
|
222
|
+
properties[attributeCode] = property.type !== void 0 ? {
|
|
223
|
+
...property,
|
|
224
|
+
type: types.includes("null") ? types : [...types, "null"],
|
|
225
|
+
...Array.isArray(property.enum) && !property.enum.includes(null) ? { enum: [...property.enum, null] } : {}
|
|
226
|
+
} : Array.isArray(property.oneOf) ? {
|
|
227
|
+
...property,
|
|
228
|
+
oneOf: [...property.oneOf, { type: "null" }]
|
|
229
|
+
} : Array.isArray(property.anyOf) && property.anyOf.some((item) => isObject$2(item) && item.type === "null") ? property : { anyOf: [property, { type: "null" }] };
|
|
230
|
+
});
|
|
231
|
+
if (Array.isArray(record.required)) record.required = record.required.filter((name) => !optionalAttributes.includes(name));
|
|
232
|
+
});
|
|
197
233
|
return prepared;
|
|
198
234
|
}
|
|
199
235
|
function describeValue$1(value, expectedRef = false) {
|
|
@@ -274,7 +310,7 @@ ${Object.entries(catalog).map(([objectCode, attributeCodes]) => ` ${JSON.string
|
|
|
274
310
|
};`;
|
|
275
311
|
return `// Generated by @hitch42/applet — do not edit.
|
|
276
312
|
import type manifest from "./manifest.gen.ts";
|
|
277
|
-
${options.hasServer ? "import type server from \"../src/server/main.ts\";\nimport type * as serverModule from \"../src/server/main.ts\";\n" : ""}${options.hasClient ? "import type { Route as indexRoute } from \"../src/client/routes/index.tsx\";\n" : ""}${options.hasServer ? "import type { AnyRouter } from \"@orpc/server\";\n" : ""}${options.hasClient ? "import type { AnyRoute } from \"@tanstack/react-router\";\n" : ""}${options.hasServer ? "import type { WorkflowDefinition } from \"@hitch42/applet/server\";\n" : ""}
|
|
313
|
+
${options.hasServer ? "import type server from \"../src/server/main.ts\";\nimport type * as serverModule from \"../src/server/main.ts\";\n" : ""}${options.hasClient ? "import type { Route as indexRoute } from \"../src/client/routes/index.tsx\";\n" : ""}${options.hasServer ? "import type { AnyRouter } from \"@orpc/server\";\n" : ""}${options.hasClient ? "import type { AnyRoute } from \"@tanstack/react-router\";\n" : ""}${options.hasServer ? "import type { WorkflowDefinition } from \"@hitch42/applet/server\";\nimport type { TelephonyMessageReceivedEvent } from \"@hitch42/applet\";\n" : ""}
|
|
278
314
|
${catalogType}
|
|
279
315
|
|
|
280
316
|
type Expect<T extends true> = T;
|
|
@@ -287,6 +323,7 @@ type _SrcServerMainMustDefaultExportRouterAndValidWorkflows = Expect<
|
|
|
287
323
|
typeof server extends {
|
|
288
324
|
router: AnyRouter;
|
|
289
325
|
workflows?: Record<string, WorkflowDefinition<any, any>>;
|
|
326
|
+
telephony?: { onMessageReceived?: (event: TelephonyMessageReceivedEvent) => void | Promise<void> };
|
|
290
327
|
}
|
|
291
328
|
? true
|
|
292
329
|
: false
|
|
@@ -352,33 +389,31 @@ async function responseJson(response) {
|
|
|
352
389
|
throw new Error("Failed to parse the organization's OpenAPI spec.", { cause: error });
|
|
353
390
|
}
|
|
354
391
|
}
|
|
355
|
-
async function loadAuthenticatedSpec(manifest
|
|
356
|
-
const github = githubActionsContext(
|
|
357
|
-
if (github !== void 0) return (await loadGitHubActionsBuildInputs(github,
|
|
358
|
-
const
|
|
359
|
-
const response = await fetchWithOrgAuth(manifest.org, options, (instanceUrl, accessToken) => fetcher(`${instanceUrl}/api/v1/openapi.json${manifest.requiresChangeset === void 0 ? "" : `?changeset_id=${encodeURIComponent(manifest.requiresChangeset)}`}`, { headers: { Authorization: `Bearer ${accessToken}` } }));
|
|
392
|
+
async function loadAuthenticatedSpec(manifest) {
|
|
393
|
+
const github = githubActionsContext();
|
|
394
|
+
if (github !== void 0) return (await loadGitHubActionsBuildInputs(github, manifest.requiresChangeset)).openapi;
|
|
395
|
+
const response = await fetchWithOrgAuth(manifest.org, (instanceUrl, accessToken) => globalThis.fetch(`${instanceUrl}/api/v1/openapi.json${manifest.requiresChangeset === void 0 ? "" : `?changeset_id=${encodeURIComponent(manifest.requiresChangeset)}`}`, { headers: { Authorization: `Bearer ${accessToken}` } }));
|
|
360
396
|
if (!response.ok) throw new Error(`Failed to load the organization's OpenAPI spec (${response.status}).`);
|
|
361
397
|
return responseJson(response);
|
|
362
398
|
}
|
|
363
|
-
async function loadThemeStylesheet(orgCode
|
|
364
|
-
const
|
|
365
|
-
const
|
|
366
|
-
const response = await fetcher(`${organizationInstanceUrl(instanceUrl, orgCode)}/theme.css`);
|
|
399
|
+
async function loadThemeStylesheet(orgCode) {
|
|
400
|
+
const instanceUrl = await resolveInstanceUrl();
|
|
401
|
+
const response = await globalThis.fetch(`${organizationInstanceUrl(instanceUrl, orgCode)}/theme.css`);
|
|
367
402
|
if (!response.ok) throw new Error(`Failed to load the organization's theme (${response.status}).`);
|
|
368
403
|
return response.text();
|
|
369
404
|
}
|
|
370
|
-
async function loadBuildInputs(manifest
|
|
371
|
-
const github = githubActionsContext(
|
|
405
|
+
async function loadBuildInputs(manifest) {
|
|
406
|
+
const github = githubActionsContext();
|
|
372
407
|
if (github !== void 0) {
|
|
373
|
-
const inputs = await loadGitHubActionsBuildInputs(github,
|
|
408
|
+
const inputs = await loadGitHubActionsBuildInputs(github, manifest.requiresChangeset);
|
|
374
409
|
return {
|
|
375
410
|
spec: inputs.openapi,
|
|
376
411
|
theme: inputs.theme
|
|
377
412
|
};
|
|
378
413
|
}
|
|
379
414
|
return {
|
|
380
|
-
spec: await loadAuthenticatedSpec(manifest
|
|
381
|
-
theme: await loadThemeStylesheet(manifest.org
|
|
415
|
+
spec: await loadAuthenticatedSpec(manifest),
|
|
416
|
+
theme: await loadThemeStylesheet(manifest.org)
|
|
382
417
|
};
|
|
383
418
|
}
|
|
384
419
|
async function generateContract(spec, outDir) {
|
|
@@ -420,16 +455,16 @@ async function writeContractFiles(outDir, manifest, spec) {
|
|
|
420
455
|
await writeManifestGen(outDir, manifest);
|
|
421
456
|
await writeRegisterDeclaration(outDir, catalog);
|
|
422
457
|
await writeFile(resolve(outDir, "index.ts"), `// Generated by applet generate — do not edit.
|
|
423
|
-
import { filesContract as files, meContract as me, pruneContract, registerHitchContract, teamsContract as teams } from "@hitch42/applet";
|
|
458
|
+
import { emailContract, filesContract as files, meContract as me, pruneContract, registerHitchContract, teamsContract as teams, telephonyContract as telephony } from "@hitch42/applet";
|
|
424
459
|
import manifest from "./manifest.gen.ts";
|
|
425
460
|
|
|
426
461
|
${Object.hasOwn(preparedSpec.paths, "/v1/batch") ? `import { contract as generated } from "./orpc.gen.ts";
|
|
427
462
|
|
|
428
463
|
const { batch, ...records } = generated;
|
|
429
464
|
|
|
430
|
-
export const contract = { records, batch, files, me, teams } as const;` : `import { contract as records } from "./orpc.gen.ts";
|
|
465
|
+
export const contract = { records, batch, email: emailContract(manifest.code), files, me, teams, telephony } as const;` : `import { contract as records } from "./orpc.gen.ts";
|
|
431
466
|
|
|
432
|
-
export const contract = { records, files, me, teams } as const;`}
|
|
467
|
+
export const contract = { records, email: emailContract(manifest.code), files, me, teams, telephony } as const;`}
|
|
433
468
|
registerHitchContract(pruneContract(contract, manifest));
|
|
434
469
|
|
|
435
470
|
declare module "@hitch42/applet" {
|
|
@@ -441,15 +476,18 @@ declare module "@hitch42/applet" {
|
|
|
441
476
|
export type * from "./zod.gen.ts";
|
|
442
477
|
`);
|
|
443
478
|
}
|
|
444
|
-
async function syncContract(outDir, manifest
|
|
445
|
-
await writeContractFiles(outDir, manifest,
|
|
479
|
+
async function syncContract(outDir, manifest) {
|
|
480
|
+
await writeContractFiles(outDir, manifest, manifest.objects.length === 0 ? {
|
|
481
|
+
paths: {},
|
|
482
|
+
components: { schemas: {} }
|
|
483
|
+
} : await loadAuthenticatedSpec(manifest));
|
|
446
484
|
}
|
|
447
|
-
async function runGenerate(
|
|
485
|
+
async function runGenerate() {
|
|
448
486
|
await prepareAppletProject();
|
|
449
487
|
const root = process.cwd();
|
|
450
488
|
const outDir = resolve("./.hitch");
|
|
451
489
|
const manifest = await loadAppletConfig(process.cwd());
|
|
452
|
-
const { spec, theme: themeStylesheet } = await loadBuildInputs(manifest
|
|
490
|
+
const { spec, theme: themeStylesheet } = await loadBuildInputs(manifest);
|
|
453
491
|
const stagedDir = await mkdtemp(resolve("./.hitch.tmp-"));
|
|
454
492
|
const backupDir = `${stagedDir}.backup`;
|
|
455
493
|
let staged = true;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/headers.ts
|
|
2
|
+
const HITCH_USER_HEADER = "x-hitch-user";
|
|
3
|
+
const HITCH_SESSION_HEADER = "x-hitch-session";
|
|
4
|
+
const HITCH_APPLET_HEADER = "x-hitch-applet";
|
|
5
|
+
const HITCH_APPLET_CODE_HEADER = "x-hitch-applet-code";
|
|
6
|
+
const HITCH_APPLET_TOKEN_HEADER = "x-hitch-applet-token";
|
|
7
|
+
const HITCH_SCHEDULE_RUN_HEADER = "x-hitch-schedule-run";
|
|
8
|
+
const HITCH_SCHEDULE_HEADER = "x-hitch-schedule";
|
|
9
|
+
const HITCH_ORG_CODE_HEADER = "x-hitch-org-code";
|
|
10
|
+
const HITCH_ORGANIZATION_HEADER = "x-hitch-organization";
|
|
11
|
+
const HITCH_RELEASE_HEADER = "x-hitch-release";
|
|
12
|
+
const HITCH_REQUEST_HOST_HEADER = "x-hitch-request-host";
|
|
13
|
+
const HITCH_WORKFLOW_RUN_HEADER = "x-hitch-workflow-run";
|
|
14
|
+
const HITCH_WORKFLOW_HEADER = "x-hitch-workflow";
|
|
15
|
+
const HITCH_WORKFLOW_INVOCATION_HEADER = "x-hitch-workflow-invocation";
|
|
16
|
+
//#endregion
|
|
17
|
+
export { HITCH_ORG_CODE_HEADER as a, HITCH_SCHEDULE_HEADER as c, HITCH_USER_HEADER as d, HITCH_WORKFLOW_HEADER as f, HITCH_ORGANIZATION_HEADER as i, HITCH_SCHEDULE_RUN_HEADER as l, HITCH_WORKFLOW_RUN_HEADER as m, HITCH_APPLET_HEADER as n, HITCH_RELEASE_HEADER as o, HITCH_WORKFLOW_INVOCATION_HEADER as p, HITCH_APPLET_TOKEN_HEADER as r, HITCH_REQUEST_HOST_HEADER as s, HITCH_APPLET_CODE_HEADER as t, HITCH_SESSION_HEADER as u };
|