@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
|
@@ -31,13 +31,22 @@ const appletManifestObjectSchema = z.strictObject({
|
|
|
31
31
|
canCreate: z.boolean(),
|
|
32
32
|
canDelete: z.boolean(),
|
|
33
33
|
readOnly: attributeCodesSchema,
|
|
34
|
-
readWrite: attributeCodesSchema
|
|
34
|
+
readWrite: attributeCodesSchema,
|
|
35
|
+
optional: z.boolean().optional(),
|
|
36
|
+
optionalAttributes: attributeCodesSchema.optional()
|
|
35
37
|
}).superRefine((object, context) => {
|
|
36
38
|
const overlap = object.readOnly.find((code) => object.readWrite.includes(code));
|
|
37
39
|
if (overlap !== void 0) context.addIssue({
|
|
38
40
|
code: "custom",
|
|
39
41
|
message: `readOnly and readWrite both contain "${overlap}".`
|
|
40
42
|
});
|
|
43
|
+
object.optionalAttributes?.forEach((code, index) => {
|
|
44
|
+
if (!object.readOnly.includes(code) && !object.readWrite.includes(code)) context.addIssue({
|
|
45
|
+
code: "custom",
|
|
46
|
+
message: `optionalAttributes contains undeclared attribute code "${code}".`,
|
|
47
|
+
path: ["optionalAttributes", index]
|
|
48
|
+
});
|
|
49
|
+
});
|
|
41
50
|
});
|
|
42
51
|
const appletManifestObjectsSchema = z.array(appletManifestObjectSchema).readonly();
|
|
43
52
|
const appletManifestSchedulesSchema = z.array(z.strictObject({
|
|
@@ -64,6 +73,11 @@ const appletManifestShape = {
|
|
|
64
73
|
name: nameSchema,
|
|
65
74
|
code: codeSchema,
|
|
66
75
|
requiresChangeset: z.uuid().optional(),
|
|
76
|
+
telephony: z.strictObject({
|
|
77
|
+
read: z.boolean().optional(),
|
|
78
|
+
send: z.boolean().optional(),
|
|
79
|
+
events: z.array(z.literal("message.received")).min(1).refine((events) => new Set(events).size === events.length).readonly().optional()
|
|
80
|
+
}).refine((telephony) => telephony.events === void 0 || telephony.read === true, "telephony.events needs telephony.read").optional(),
|
|
67
81
|
schedules: appletManifestSchedulesSchema.optional(),
|
|
68
82
|
variables: appletManifestVariablesSchema.optional(),
|
|
69
83
|
objects: appletManifestObjectsSchema
|
|
@@ -96,12 +110,14 @@ const appletDefinitionSchema = z.strictObject({
|
|
|
96
110
|
name: appletManifestShape.name,
|
|
97
111
|
code: appletManifestShape.code,
|
|
98
112
|
requiresChangeset: appletManifestShape.requiresChangeset,
|
|
113
|
+
telephony: appletManifestShape.telephony,
|
|
99
114
|
schedules: appletManifestShape.schedules,
|
|
100
115
|
variables: appletManifestShape.variables,
|
|
101
116
|
objects: appletManifestShape.objects
|
|
102
117
|
}).superRefine(checkDuplicateCodes);
|
|
103
118
|
const packageVersionsSchema = z.record(z.string().min(1), z.string().min(1)).readonly();
|
|
104
119
|
const RESERVED_APPLET_PACKAGES = /* @__PURE__ */ new Set([
|
|
120
|
+
"@fontsource-variable/geist-mono",
|
|
105
121
|
"@fontsource-variable/inter",
|
|
106
122
|
"@hitch42/applet",
|
|
107
123
|
"@orpc/contract",
|
|
@@ -121,14 +137,16 @@ const RESERVED_APPLET_PACKAGES = /* @__PURE__ */ new Set([
|
|
|
121
137
|
"@types/react",
|
|
122
138
|
"@types/react-dom",
|
|
123
139
|
"class-variance-authority",
|
|
124
|
-
"
|
|
140
|
+
"cn",
|
|
125
141
|
"lucide-react",
|
|
142
|
+
"oxfmt",
|
|
143
|
+
"oxlint",
|
|
144
|
+
"oxlint-tsgolint",
|
|
126
145
|
"react",
|
|
127
146
|
"react-aria-components",
|
|
128
147
|
"react-dom",
|
|
129
148
|
"shadcn",
|
|
130
149
|
"streamdown",
|
|
131
|
-
"tailwind-merge",
|
|
132
150
|
"tailwindcss",
|
|
133
151
|
"tw-animate-css",
|
|
134
152
|
"typescript",
|
|
@@ -164,6 +182,7 @@ const appletSourceDefinitionSchema = z.strictObject({
|
|
|
164
182
|
name: appletManifestShape.name,
|
|
165
183
|
code: appletManifestShape.code,
|
|
166
184
|
requiresChangeset: appletManifestShape.requiresChangeset,
|
|
185
|
+
telephony: appletManifestShape.telephony,
|
|
167
186
|
schedules: appletManifestShape.schedules,
|
|
168
187
|
variables: appletManifestShape.variables,
|
|
169
188
|
objects: appletManifestShape.objects,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/hitch/me.ts
|
|
4
|
+
const personSchema = z.object({
|
|
5
|
+
id: z.uuid(),
|
|
6
|
+
firstName: z.string(),
|
|
7
|
+
lastName: z.string(),
|
|
8
|
+
email: z.email()
|
|
9
|
+
});
|
|
10
|
+
const membershipSchema = z.object({
|
|
11
|
+
orgId: z.uuid(),
|
|
12
|
+
code: z.string(),
|
|
13
|
+
name: z.string(),
|
|
14
|
+
iconFileId: z.uuid().nullable(),
|
|
15
|
+
role: z.enum(["member", "owner"]),
|
|
16
|
+
capabilities: z.array(z.string())
|
|
17
|
+
});
|
|
18
|
+
const meSchema = z.object({
|
|
19
|
+
person: personSchema,
|
|
20
|
+
memberships: z.array(membershipSchema),
|
|
21
|
+
organization: z.object({
|
|
22
|
+
id: z.uuid(),
|
|
23
|
+
code: z.string()
|
|
24
|
+
}).nullable(),
|
|
25
|
+
multiOrg: z.boolean()
|
|
26
|
+
});
|
|
27
|
+
const meContract = { get: oc.route({
|
|
28
|
+
method: "GET",
|
|
29
|
+
path: "/v1/me"
|
|
30
|
+
}).input(z.void()).output(meSchema) };
|
|
31
|
+
//#endregion
|
|
32
|
+
export { meSchema as n, meContract as t };
|
|
@@ -1,9 +1,72 @@
|
|
|
1
|
-
import { i as readWorkspaceConfig } from "./workspace-
|
|
2
|
-
import { n as loadAppletSourceDefinition } from "./load-config-
|
|
1
|
+
import { i as readWorkspaceConfig, l as organizationInstanceUrl, s as DEFAULT_INSTANCE_URL } from "./workspace-D0dnnlxL.js";
|
|
2
|
+
import { n as loadAppletSourceDefinition } from "./load-config-xEdTXs0y.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
|
-
import { cp, mkdir, readFile, rm, symlink, writeFile } from "node:fs/promises";
|
|
5
|
+
import { cp, mkdir, readFile, readdir, rm, symlink, writeFile } from "node:fs/promises";
|
|
6
6
|
import { dirname, relative, resolve } from "node:path";
|
|
7
|
+
import { TomlError, parse, stringify } from "smol-toml";
|
|
8
|
+
//#region src/agent-support.ts
|
|
9
|
+
var AgentConfigError = class extends Error {};
|
|
10
|
+
async function ensureAgentConfigs(root, org) {
|
|
11
|
+
const servers = {
|
|
12
|
+
hitch: {
|
|
13
|
+
type: "http",
|
|
14
|
+
url: `${organizationInstanceUrl(DEFAULT_INSTANCE_URL, org)}/mcp`
|
|
15
|
+
},
|
|
16
|
+
"chrome-devtools": {
|
|
17
|
+
type: "stdio",
|
|
18
|
+
command: "pnpx",
|
|
19
|
+
args: ["chrome-devtools-mcp@latest", "--headless"]
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
const configs = await Promise.all([{
|
|
23
|
+
path: resolve(root, ".mcp.json"),
|
|
24
|
+
format: "json",
|
|
25
|
+
key: "mcpServers"
|
|
26
|
+
}, {
|
|
27
|
+
path: resolve(root, ".codex/config.toml"),
|
|
28
|
+
format: "toml",
|
|
29
|
+
key: "mcp_servers"
|
|
30
|
+
}].map(async ({ path, format, key }) => {
|
|
31
|
+
const current = existsSync(path) ? await readFile(path, "utf8") : void 0;
|
|
32
|
+
let config;
|
|
33
|
+
let additions;
|
|
34
|
+
try {
|
|
35
|
+
config = z.record(z.string(), z.unknown()).parse(current === void 0 ? {} : format === "json" ? JSON.parse(current) : parse(current, { integersAsBigInt: true }));
|
|
36
|
+
const existing = config[key] === void 0 ? {} : z.record(z.string(), z.unknown()).parse(config[key]);
|
|
37
|
+
const missing = Object.entries(servers).filter(([name]) => !Object.hasOwn(existing, name));
|
|
38
|
+
if (current !== void 0 && missing.length === 0) return void 0;
|
|
39
|
+
additions = Object.fromEntries(missing.map(([name, server]) => [name, format === "json" ? server : Object.fromEntries(Object.entries(server).filter(([field]) => field !== "type"))]));
|
|
40
|
+
config[key] = {
|
|
41
|
+
...existing,
|
|
42
|
+
...additions
|
|
43
|
+
};
|
|
44
|
+
} catch (cause) {
|
|
45
|
+
throw new AgentConfigError(`Invalid agent configuration in ${path}.`, { cause });
|
|
46
|
+
}
|
|
47
|
+
if (format === "json") return {
|
|
48
|
+
path,
|
|
49
|
+
contents: `${JSON.stringify(config, null, 2)}\n`
|
|
50
|
+
};
|
|
51
|
+
const contents = `${current ?? ""}${current ? "\n" : ""}${stringify({ [key]: additions })}`;
|
|
52
|
+
try {
|
|
53
|
+
parse(contents, { integersAsBigInt: true });
|
|
54
|
+
return {
|
|
55
|
+
path,
|
|
56
|
+
contents
|
|
57
|
+
};
|
|
58
|
+
} catch (error) {
|
|
59
|
+
if (!(error instanceof TomlError)) throw error;
|
|
60
|
+
return {
|
|
61
|
+
path,
|
|
62
|
+
contents: stringify(config, { numbersAsFloat: true })
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}));
|
|
66
|
+
await mkdir(resolve(root, ".codex"), { recursive: true });
|
|
67
|
+
await Promise.all(configs.filter((config) => config !== void 0).map(({ path, contents }) => writeFile(path, contents)));
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
7
70
|
//#region src/project.ts
|
|
8
71
|
const PACKAGE_MANAGER = "pnpm@11.18.0+sha512.33d83c77da82f49fba836925c6f1b841181ec3132b670639bd012f7075f5c7cf634c5f870147c19aae7478fac01df09d8892e880454896edd23ee9b33757563c";
|
|
9
72
|
const cliManifestValueSchema = z.string().min(1, "must be a non-empty string");
|
|
@@ -11,6 +74,7 @@ const cliManifestSchema = z.object({
|
|
|
11
74
|
name: cliManifestValueSchema,
|
|
12
75
|
version: cliManifestValueSchema,
|
|
13
76
|
dependencies: z.object({
|
|
77
|
+
"@fontsource-variable/geist-mono": cliManifestValueSchema,
|
|
14
78
|
"@fontsource-variable/inter": cliManifestValueSchema,
|
|
15
79
|
"@orpc/contract": cliManifestValueSchema,
|
|
16
80
|
"@tiptap/core": cliManifestValueSchema,
|
|
@@ -24,12 +88,14 @@ const cliManifestSchema = z.object({
|
|
|
24
88
|
"@tailwindcss/vite": cliManifestValueSchema,
|
|
25
89
|
"@tanstack/router-cli": cliManifestValueSchema,
|
|
26
90
|
"class-variance-authority": cliManifestValueSchema,
|
|
27
|
-
|
|
91
|
+
cn: cliManifestValueSchema,
|
|
28
92
|
"lucide-react": cliManifestValueSchema,
|
|
93
|
+
oxfmt: cliManifestValueSchema,
|
|
94
|
+
oxlint: cliManifestValueSchema,
|
|
95
|
+
"oxlint-tsgolint": cliManifestValueSchema,
|
|
29
96
|
"react-aria-components": cliManifestValueSchema,
|
|
30
97
|
shadcn: cliManifestValueSchema,
|
|
31
98
|
streamdown: cliManifestValueSchema,
|
|
32
|
-
"tailwind-merge": cliManifestValueSchema,
|
|
33
99
|
tailwindcss: cliManifestValueSchema,
|
|
34
100
|
"tw-animate-css": cliManifestValueSchema,
|
|
35
101
|
vite: cliManifestValueSchema,
|
|
@@ -51,11 +117,11 @@ const cliManifestSchema = z.object({
|
|
|
51
117
|
async function loadCliManifest(options) {
|
|
52
118
|
const result = cliManifestSchema.safeParse(JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8")));
|
|
53
119
|
if (!result.success) {
|
|
54
|
-
const issue = result.error.issues
|
|
120
|
+
const issue = result.error.issues.at(0);
|
|
55
121
|
if (issue === void 0) throw new Error("Invalid CLI package manifest.");
|
|
56
122
|
throw new Error(`Invalid CLI package manifest field "${issue.path.join(".")}": ${issue.message}.`);
|
|
57
123
|
}
|
|
58
|
-
const catalogEntry = [...Object.entries(result.data.dependencies).map(([name, value]) => [`dependencies.${name}`, value]), ...Object.entries(result.data.peerDependencies).map(([name, value]) => [`peerDependencies.${name}`, value])].find(([, value]) => value
|
|
124
|
+
const catalogEntry = [...Object.entries(result.data.dependencies).map(([name, value]) => [`dependencies.${name}`, value]), ...Object.entries(result.data.peerDependencies).map(([name, value]) => [`peerDependencies.${name}`, value])].find(([, value]) => value.startsWith("catalog:"));
|
|
59
125
|
if (catalogEntry !== void 0) {
|
|
60
126
|
if (options?.allowDevelopment === true) return void 0;
|
|
61
127
|
throw new Error(`Invalid CLI package manifest field "${catalogEntry[0]}": "catalog:" identifies an unpublished development build. Run the published @hitch42/applet CLI instead.`);
|
|
@@ -71,8 +137,16 @@ function workspacePackage(org) {
|
|
|
71
137
|
name: `${org.replaceAll("_", "-")}-applets`,
|
|
72
138
|
private: true,
|
|
73
139
|
type: "module",
|
|
140
|
+
scripts: {
|
|
141
|
+
lint: "oxlint",
|
|
142
|
+
fmt: "oxfmt",
|
|
143
|
+
check: "oxfmt --check && oxlint"
|
|
144
|
+
},
|
|
74
145
|
devDependencies: {
|
|
75
146
|
"@hitch42/applet": "catalog:",
|
|
147
|
+
oxfmt: "catalog:",
|
|
148
|
+
oxlint: "catalog:",
|
|
149
|
+
"oxlint-tsgolint": "catalog:",
|
|
76
150
|
typescript: "catalog:",
|
|
77
151
|
vite: "catalog:",
|
|
78
152
|
vitest: "catalog:"
|
|
@@ -85,6 +159,7 @@ function workspaceFile(cli) {
|
|
|
85
159
|
- applets/*
|
|
86
160
|
catalog:
|
|
87
161
|
"@hitch42/applet": npm:${cli.name}@${cli.version}
|
|
162
|
+
"@fontsource-variable/geist-mono": "${cli.dependencies["@fontsource-variable/geist-mono"]}"
|
|
88
163
|
"@fontsource-variable/inter": "${cli.dependencies["@fontsource-variable/inter"]}"
|
|
89
164
|
"@orpc/contract": "${cli.dependencies["@orpc/contract"]}"
|
|
90
165
|
"@orpc/server": "${cli.peerDependencies["@orpc/server"]}"
|
|
@@ -104,14 +179,16 @@ catalog:
|
|
|
104
179
|
"@types/react-dom": "${cli.peerDependencies["@types/react-dom"]}"
|
|
105
180
|
"@tailwindcss/vite": "${cli.dependencies["@tailwindcss/vite"]}"
|
|
106
181
|
class-variance-authority: "${cli.dependencies["class-variance-authority"]}"
|
|
107
|
-
|
|
182
|
+
cn: "${cli.dependencies.cn}"
|
|
108
183
|
lucide-react: "${cli.dependencies["lucide-react"]}"
|
|
184
|
+
oxfmt: "${cli.dependencies.oxfmt}"
|
|
185
|
+
oxlint: "${cli.dependencies.oxlint}"
|
|
186
|
+
oxlint-tsgolint: "${cli.dependencies["oxlint-tsgolint"]}"
|
|
109
187
|
react: "${cli.peerDependencies.react}"
|
|
110
188
|
react-aria-components: "${cli.dependencies["react-aria-components"]}"
|
|
111
189
|
react-dom: "${cli.peerDependencies["react-dom"]}"
|
|
112
190
|
shadcn: "${cli.dependencies.shadcn}"
|
|
113
191
|
streamdown: "${cli.dependencies.streamdown}"
|
|
114
|
-
tailwind-merge: "${cli.dependencies["tailwind-merge"]}"
|
|
115
192
|
tailwindcss: "${cli.dependencies.tailwindcss}"
|
|
116
193
|
tw-animate-css: "${cli.dependencies["tw-animate-css"]}"
|
|
117
194
|
typescript: "${cli.peerDependencies.typescript}"
|
|
@@ -126,16 +203,91 @@ minimumReleaseAgeExclude:
|
|
|
126
203
|
- "@hitch42/*"
|
|
127
204
|
`;
|
|
128
205
|
}
|
|
206
|
+
const OXLINT_CONFIG = `{
|
|
207
|
+
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
|
208
|
+
"plugins": ["eslint", "typescript", "unicorn", "import", "node"],
|
|
209
|
+
"options": { "typeAware": true, "typeCheck": true },
|
|
210
|
+
"env": { "node": true },
|
|
211
|
+
"overrides": [
|
|
212
|
+
{
|
|
213
|
+
"files": ["applets/*/src/client/**"],
|
|
214
|
+
"plugins": ["eslint", "typescript", "unicorn", "import", "react", "react-perf"],
|
|
215
|
+
"env": { "node": false, "browser": true },
|
|
216
|
+
"rules": {
|
|
217
|
+
"react/capitalized-calls": "error",
|
|
218
|
+
"react/error-boundaries": "error",
|
|
219
|
+
"react/exhaustive-effect-dependencies": "error",
|
|
220
|
+
"react/globals": "error",
|
|
221
|
+
"react/hooks": "error",
|
|
222
|
+
"react/immutability": "error",
|
|
223
|
+
"react/incompatible-library": "error",
|
|
224
|
+
"react/invariant": "error",
|
|
225
|
+
"react/memo-dependencies": "error",
|
|
226
|
+
"react/no-deriving-state-in-effects": "error",
|
|
227
|
+
"react/preserve-manual-memoization": "error",
|
|
228
|
+
"react/purity": "error",
|
|
229
|
+
"react/refs": "error",
|
|
230
|
+
"react/rule-suppression": "error",
|
|
231
|
+
"react/set-state-in-effect": "error",
|
|
232
|
+
"react/set-state-in-render": "error",
|
|
233
|
+
"react/static-components": "error",
|
|
234
|
+
"react/syntax": "error",
|
|
235
|
+
"react/todo": "error",
|
|
236
|
+
"react/unsupported-syntax": "error",
|
|
237
|
+
"react/use-memo": "error",
|
|
238
|
+
"react/void-use-memo": "error"
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"files": ["applets/*/test/**"],
|
|
243
|
+
"plugins": ["eslint", "typescript", "unicorn", "import", "vitest"],
|
|
244
|
+
"rules": {
|
|
245
|
+
"vitest/expect-expect": [
|
|
246
|
+
"warn",
|
|
247
|
+
{ "assertFunctionNames": ["expect", "expect*", "assert", "assert.*", "assert*"] }
|
|
248
|
+
]
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
]
|
|
252
|
+
}
|
|
253
|
+
`;
|
|
254
|
+
async function oxfmtConfig(root) {
|
|
255
|
+
const appletsRoot = resolve(root, "applets");
|
|
256
|
+
const overrides = (existsSync(appletsRoot) ? await readdir(appletsRoot) : []).filter((code) => existsSync(resolve(appletsRoot, code, "src/client/styles/globals.css"))).sort().map((code) => `
|
|
257
|
+
{
|
|
258
|
+
"files": ["applets/${code}/**"],
|
|
259
|
+
"options": {
|
|
260
|
+
"sortTailwindcss": {
|
|
261
|
+
"stylesheet": "applets/${code}/src/client/styles/globals.css",
|
|
262
|
+
"functions": ["cn", "cva"]
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}`);
|
|
266
|
+
return `{
|
|
267
|
+
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
|
268
|
+
"sortImports": true,
|
|
269
|
+
"overrides": [${overrides.join(",")}${overrides.length > 0 ? "\n " : ""}]
|
|
270
|
+
}
|
|
271
|
+
`;
|
|
272
|
+
}
|
|
129
273
|
const GITIGNORE_START = "# BEGIN Hitch generated files";
|
|
130
274
|
const GITIGNORE_END = "# END Hitch generated files";
|
|
131
275
|
const SKILLS = [
|
|
132
276
|
"hitch-applets",
|
|
133
277
|
"hitch-cli",
|
|
134
|
-
"hitch-data"
|
|
278
|
+
"hitch-data",
|
|
279
|
+
"hitch-theory",
|
|
280
|
+
"react-best-practices",
|
|
281
|
+
"tanstack-query",
|
|
282
|
+
"tanstack-router",
|
|
283
|
+
"web-design-guidelines"
|
|
135
284
|
];
|
|
136
285
|
const GITIGNORE = `${GITIGNORE_START}
|
|
137
286
|
${SKILLS.map((skill) => `/.agents/skills/${skill}/`).join("\n")}
|
|
287
|
+
${SKILLS.map((skill) => `/.claude/skills/${skill}`).join("\n")}
|
|
138
288
|
/.node-version
|
|
289
|
+
/.oxfmtrc.json
|
|
290
|
+
/.oxlintrc.json
|
|
139
291
|
/AGENTS.md
|
|
140
292
|
/CLAUDE.md
|
|
141
293
|
/package.json
|
|
@@ -175,11 +327,13 @@ async function writeWorkspaceSupport(root, config, cli) {
|
|
|
175
327
|
const resolvedCli = cli ?? await loadCliManifest();
|
|
176
328
|
if (resolvedCli === void 0) throw new Error("The CLI package manifest is not published.");
|
|
177
329
|
assertWorkspaceCli(config, resolvedCli);
|
|
330
|
+
await ensureAgentConfigs(root, config.org);
|
|
178
331
|
const deployWorkflowTarget = resolve(root, ".github/workflows/hitch.yml");
|
|
179
332
|
const agents = await readFile(new URL("../scaffold/AGENTS.md", import.meta.url), "utf8");
|
|
180
333
|
await Promise.all([
|
|
181
334
|
mkdir(resolve(root, ".agents/skills"), { recursive: true }),
|
|
182
|
-
mkdir(resolve(root, ".
|
|
335
|
+
mkdir(resolve(root, ".claude/skills"), { recursive: true }),
|
|
336
|
+
config.githubWorkflow === false ? void 0 : mkdir(resolve(root, ".github/workflows"), { recursive: true }),
|
|
183
337
|
...SKILLS.map((skill) => rm(resolve(root, ".agents/skills", skill), {
|
|
184
338
|
force: true,
|
|
185
339
|
recursive: true
|
|
@@ -189,13 +343,23 @@ async function writeWorkspaceSupport(root, config, cli) {
|
|
|
189
343
|
...SKILLS.map((skill) => cp(new URL(`../scaffold/.agents/skills/${skill}`, import.meta.url), resolve(root, ".agents/skills", skill), { recursive: true })),
|
|
190
344
|
writeFile(resolve(root, "package.json"), `${JSON.stringify(workspacePackage(config.org), null, 2)}\n`),
|
|
191
345
|
writeFile(resolve(root, "pnpm-workspace.yaml"), workspaceFile(resolvedCli)),
|
|
192
|
-
existsSync(deployWorkflowTarget) ? void 0 : cp(new URL("../scaffold/.github/workflows/hitch.yml", import.meta.url), deployWorkflowTarget),
|
|
346
|
+
config.githubWorkflow === false || existsSync(deployWorkflowTarget) ? void 0 : cp(new URL("../scaffold/.github/workflows/hitch.yml", import.meta.url), deployWorkflowTarget),
|
|
193
347
|
writeFile(resolve(root, ".node-version"), "24\n"),
|
|
348
|
+
writeFile(resolve(root, ".oxlintrc.json"), OXLINT_CONFIG),
|
|
349
|
+
oxfmtConfig(root).then((config) => writeFile(resolve(root, ".oxfmtrc.json"), config)),
|
|
194
350
|
writeGitignore(root),
|
|
195
351
|
writeFile(resolve(root, "AGENTS.md"), agents)
|
|
196
352
|
]);
|
|
197
353
|
await rm(resolve(root, "CLAUDE.md"), { force: true });
|
|
198
354
|
await symlink("AGENTS.md", resolve(root, "CLAUDE.md"));
|
|
355
|
+
await Promise.all(SKILLS.map(async (skill) => {
|
|
356
|
+
const target = resolve(root, ".claude/skills", skill);
|
|
357
|
+
await rm(target, { force: true });
|
|
358
|
+
await symlink(`../../.agents/skills/${skill}`, target, "dir");
|
|
359
|
+
}));
|
|
360
|
+
}
|
|
361
|
+
function sortedByName(packages) {
|
|
362
|
+
return Object.fromEntries(Object.entries(packages).sort(([a], [b]) => a < b ? -1 : 1));
|
|
199
363
|
}
|
|
200
364
|
function appletPackage(definition, options) {
|
|
201
365
|
return {
|
|
@@ -208,14 +372,18 @@ function appletPackage(definition, options) {
|
|
|
208
372
|
generate: "applet generate",
|
|
209
373
|
deploy: "applet deploy",
|
|
210
374
|
test: "vitest run",
|
|
211
|
-
typecheck: "tsc --noEmit"
|
|
375
|
+
typecheck: "tsc --noEmit",
|
|
376
|
+
lint: "oxlint",
|
|
377
|
+
fmt: "oxfmt",
|
|
378
|
+
check: "oxfmt --check && oxlint"
|
|
212
379
|
},
|
|
213
|
-
dependencies: {
|
|
380
|
+
dependencies: sortedByName({
|
|
214
381
|
"@hitch42/applet": "catalog:",
|
|
215
382
|
"@orpc/contract": "catalog:",
|
|
216
383
|
zod: "catalog:",
|
|
217
384
|
...options.hasServer ? { "@orpc/server": "catalog:" } : {},
|
|
218
385
|
...options.hasClient ? {
|
|
386
|
+
"@fontsource-variable/geist-mono": "catalog:",
|
|
219
387
|
"@fontsource-variable/inter": "catalog:",
|
|
220
388
|
"@tanstack/react-query": "catalog:",
|
|
221
389
|
"@tanstack/react-router": "catalog:",
|
|
@@ -228,19 +396,18 @@ function appletPackage(definition, options) {
|
|
|
228
396
|
"@tiptap/react": "catalog:",
|
|
229
397
|
"@tiptap/starter-kit": "catalog:",
|
|
230
398
|
"class-variance-authority": "catalog:",
|
|
231
|
-
|
|
399
|
+
cn: "catalog:",
|
|
232
400
|
"lucide-react": "catalog:",
|
|
233
401
|
react: "catalog:",
|
|
234
402
|
"react-aria-components": "catalog:",
|
|
235
403
|
"react-dom": "catalog:",
|
|
236
404
|
shadcn: "catalog:",
|
|
237
405
|
streamdown: "catalog:",
|
|
238
|
-
"tailwind-merge": "catalog:",
|
|
239
406
|
"tw-animate-css": "catalog:"
|
|
240
407
|
} : {},
|
|
241
408
|
...definition.dependencies
|
|
242
|
-
},
|
|
243
|
-
devDependencies: {
|
|
409
|
+
}),
|
|
410
|
+
devDependencies: sortedByName({
|
|
244
411
|
"@types/node": "catalog:",
|
|
245
412
|
typescript: "catalog:",
|
|
246
413
|
vite: "catalog:",
|
|
@@ -252,9 +419,21 @@ function appletPackage(definition, options) {
|
|
|
252
419
|
tailwindcss: "catalog:"
|
|
253
420
|
} : {},
|
|
254
421
|
...definition.devDependencies
|
|
255
|
-
}
|
|
422
|
+
})
|
|
256
423
|
};
|
|
257
424
|
}
|
|
425
|
+
const LEGACY_CN_HELPER = `import { clsx, type ClassValue } from "clsx";
|
|
426
|
+
import { twMerge } from "tailwind-merge";
|
|
427
|
+
|
|
428
|
+
export function cn(...inputs: ClassValue[]) {
|
|
429
|
+
return twMerge(clsx(inputs));
|
|
430
|
+
}
|
|
431
|
+
`;
|
|
432
|
+
async function replaceLegacyCnHelper(root) {
|
|
433
|
+
const path = resolve(root, "src/client/lib/utils.ts");
|
|
434
|
+
if (!existsSync(path) || await readFile(path, "utf8") !== LEGACY_CN_HELPER) return;
|
|
435
|
+
await cp(new URL("../scaffold/applet/src/client/lib/utils.ts", import.meta.url), path);
|
|
436
|
+
}
|
|
258
437
|
async function writeAppletSupport(root, definition) {
|
|
259
438
|
const hasClient = existsSync(resolve(root, "src/client/routes"));
|
|
260
439
|
const hasAuthorRoot = existsSync(resolve(root, "src/client/routes/__root.tsx"));
|
|
@@ -263,6 +442,7 @@ async function writeAppletSupport(root, definition) {
|
|
|
263
442
|
if (!hasServer && (definition.schedules?.length ?? 0) > 0) throw new Error("An applet with schedules must have src/server/main.ts.");
|
|
264
443
|
await Promise.all(hasClient ? [] : [rm(resolve(root, "index.html"), { force: true }), rm(resolve(root, "components.json"), { force: true })]);
|
|
265
444
|
await Promise.all([
|
|
445
|
+
replaceLegacyCnHelper(root),
|
|
266
446
|
writeFile(resolve(root, "package.json"), `${JSON.stringify(appletPackage(definition, {
|
|
267
447
|
hasClient,
|
|
268
448
|
hasServer
|
|
@@ -334,7 +514,9 @@ export default defineConfig({
|
|
|
334
514
|
"./.hitch/*.ts",
|
|
335
515
|
"./.hitch/*.tsx",
|
|
336
516
|
"./src/**/*.ts",
|
|
337
|
-
"./src/**/*.tsx"
|
|
517
|
+
"./src/**/*.tsx",
|
|
518
|
+
"./test/**/*.ts",
|
|
519
|
+
"./test/**/*.tsx"
|
|
338
520
|
]
|
|
339
521
|
}
|
|
340
522
|
`),
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Writable } from "node:stream";
|
|
2
|
+
import { createInterface } from "node:readline";
|
|
3
|
+
//#region src/prompt.ts
|
|
4
|
+
function question(prompt, hidden = false) {
|
|
5
|
+
return new Promise((resolveAnswer, rejectAnswer) => {
|
|
6
|
+
let muted = false;
|
|
7
|
+
const output = hidden ? new Writable({ write(chunk, encoding, callback) {
|
|
8
|
+
if (!muted) process.stdout.write(chunk, encoding);
|
|
9
|
+
callback();
|
|
10
|
+
} }) : process.stdout;
|
|
11
|
+
const readline = createInterface({
|
|
12
|
+
input: process.stdin,
|
|
13
|
+
output,
|
|
14
|
+
terminal: true
|
|
15
|
+
});
|
|
16
|
+
readline.once("error", rejectAnswer);
|
|
17
|
+
if (hidden) {
|
|
18
|
+
process.stdout.write(prompt);
|
|
19
|
+
muted = true;
|
|
20
|
+
}
|
|
21
|
+
readline.question(hidden ? "" : prompt, (answer) => {
|
|
22
|
+
readline.close();
|
|
23
|
+
if (hidden) process.stdout.write("\n");
|
|
24
|
+
resolveAnswer(answer);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { question as t };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
//#region src/internal/query-cache.ts
|
|
2
|
+
const STORE = "clients";
|
|
3
|
+
const TIMESTAMP_INDEX = "timestamp";
|
|
4
|
+
const TAB_KEY = "hitch:query-tab";
|
|
5
|
+
const SAVE_INTERVAL = 1e3;
|
|
6
|
+
function openQueryCacheDatabase() {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
const open = indexedDB.open("hitch-query-cache", 1);
|
|
9
|
+
open.onupgradeneeded = () => {
|
|
10
|
+
open.result.createObjectStore("clients").createIndex("timestamp", "timestamp");
|
|
11
|
+
};
|
|
12
|
+
open.onblocked = () => reject(/* @__PURE__ */ new Error("The query cache is open in an older tab."));
|
|
13
|
+
open.onsuccess = () => {
|
|
14
|
+
open.result.onversionchange = () => open.result.close();
|
|
15
|
+
resolve(open.result);
|
|
16
|
+
};
|
|
17
|
+
open.onerror = () => reject(open.error);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
let database;
|
|
21
|
+
function openCacheDatabase() {
|
|
22
|
+
database ??= window.__hitchCacheDatabase ?? openQueryCacheDatabase();
|
|
23
|
+
return database;
|
|
24
|
+
}
|
|
25
|
+
async function inStore(mode, run) {
|
|
26
|
+
const transaction = (await openCacheDatabase()).transaction(STORE, mode);
|
|
27
|
+
const request = run(transaction.objectStore(STORE));
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
transaction.oncomplete = () => resolve(request.result);
|
|
30
|
+
transaction.onabort = () => reject(transaction.error ?? request.error);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function cacheTabId() {
|
|
34
|
+
const existing = sessionStorage.getItem(TAB_KEY);
|
|
35
|
+
if (existing) return existing;
|
|
36
|
+
const id = crypto.randomUUID();
|
|
37
|
+
sessionStorage.setItem(TAB_KEY, id);
|
|
38
|
+
return id;
|
|
39
|
+
}
|
|
40
|
+
function indexedDbPersister(key) {
|
|
41
|
+
let pending;
|
|
42
|
+
let throttled = false;
|
|
43
|
+
const save = (client) => inStore("readwrite", (store) => store.put(client, key)).then(() => void 0, (error) => console.error("Could not persist the applet query cache.", error));
|
|
44
|
+
const release = () => {
|
|
45
|
+
if (!pending) {
|
|
46
|
+
throttled = false;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
save(pending);
|
|
50
|
+
pending = void 0;
|
|
51
|
+
setTimeout(release, SAVE_INTERVAL);
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
persistClient: (client) => {
|
|
55
|
+
if (throttled) {
|
|
56
|
+
pending = client;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
throttled = true;
|
|
60
|
+
setTimeout(release, SAVE_INTERVAL);
|
|
61
|
+
return save(client);
|
|
62
|
+
},
|
|
63
|
+
restoreClient: () => inStore("readonly", (store) => store.get(key)),
|
|
64
|
+
removeClient: () => inStore("readwrite", (store) => store.delete(key))
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function sweepExpiredQueryCaches(maxAge) {
|
|
68
|
+
return inStore("readwrite", (store) => {
|
|
69
|
+
const cursor = store.index(TIMESTAMP_INDEX).openKeyCursor(IDBKeyRange.upperBound(Date.now() - maxAge));
|
|
70
|
+
cursor.onsuccess = () => {
|
|
71
|
+
if (!cursor.result) return;
|
|
72
|
+
store.delete(cursor.result.primaryKey);
|
|
73
|
+
cursor.result.continue();
|
|
74
|
+
};
|
|
75
|
+
return cursor;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function clearAppletQueryCaches(appletCode) {
|
|
79
|
+
return inStore("readwrite", (store) => store.delete(IDBKeyRange.bound(`${appletCode}:`, `${appletCode}:\uffff`)));
|
|
80
|
+
}
|
|
81
|
+
//#endregion
|
|
82
|
+
export { openQueryCacheDatabase as a, openCacheDatabase as i, clearAppletQueryCaches as n, sweepExpiredQueryCaches as o, indexedDbPersister as r, cacheTabId as t };
|
package/dist/react.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as UploadedHitchFile } from "./upload-
|
|
1
|
+
import { a as UploadedHitchFile } from "./upload-DKZzz5kW.js";
|
|
2
2
|
import { ReactElement } from "react";
|
|
3
3
|
import "@tiptap/core";
|
|
4
4
|
//#region src/react/markdown.d.ts
|
|
@@ -29,9 +29,10 @@ type MarkdownEditorProps = {
|
|
|
29
29
|
minLength?: number;
|
|
30
30
|
maxLength?: number;
|
|
31
31
|
disabled?: boolean;
|
|
32
|
+
autoFocus?: boolean;
|
|
32
33
|
className?: string;
|
|
33
34
|
onUploadError?: (error: unknown, file: File) => void;
|
|
34
35
|
};
|
|
35
|
-
declare function MarkdownEditor({ value, onChange, files, id, placeholder, required, minLength, maxLength, disabled, className, onUploadError }: MarkdownEditorProps): ReactElement;
|
|
36
|
+
declare function MarkdownEditor({ value, onChange, files, id, placeholder, required, minLength, maxLength, disabled, autoFocus, className, onUploadError }: MarkdownEditorProps): ReactElement;
|
|
36
37
|
//#endregion
|
|
37
38
|
export { Markdown, MarkdownEditor, type MarkdownEditorFiles, type MarkdownEditorProps, type MarkdownFiles, type MarkdownProps };
|