@hitch42/applet 0.1.1-beta.19 → 0.1.1-beta.20

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/applet.js CHANGED
@@ -99,23 +99,23 @@ async function main() {
99
99
  const noLogFlags = values.run === void 0 && values.filter === void 0 && values.level === void 0 && values.limit === void 0 && values.live === void 0 && values.search === void 0 && values.since === void 0;
100
100
  const noModeFlags = values["client-only"] === void 0 && values["server-only"] === void 0;
101
101
  if (positionals.length === 1 && positionals[0] === "bootstrap" && noModeFlags && noGitFlags && noVariableFlags && noLogFlags) {
102
- await (await import("./init-DT0faD-q.js")).runBootstrap({ install: values["no-install"] !== true });
102
+ await (await import("./init-BKUBf6i9.js")).runBootstrap({ install: values["no-install"] !== true });
103
103
  return;
104
104
  }
105
105
  if (positionals.length === 1 && positionals[0] === "generate" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noVariableFlags && noLogFlags) {
106
- await (await import("./generate-Df29-UJm.js")).runGenerate();
106
+ await (await import("./generate-COCRy1Bs.js")).runGenerate();
107
107
  return;
108
108
  }
109
109
  if (positionals.length === 1 && positionals[0] === "build" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noVariableFlags && noLogFlags) {
110
- await (await import("./build-DpkWOvd2.js")).runBuild();
110
+ await (await import("./build-JtbY8q2p.js")).runBuild();
111
111
  return;
112
112
  }
113
113
  if (positionals.length === 1 && positionals[0] === "deploy" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noVariableFlags && noLogFlags) {
114
- await (await import("./deploy-DODTE8ri.js")).runDeploy({});
114
+ await (await import("./deploy-BbqyK5Ik.js")).runDeploy({});
115
115
  return;
116
116
  }
117
117
  if (positionals.length === 2 && positionals[0] === "init" && noModeFlags && noVariableFlags && noLogFlags) {
118
- await (await import("./init-DT0faD-q.js")).runInit(positionals[1], {
118
+ await (await import("./init-BKUBf6i9.js")).runInit(positionals[1], {
119
119
  commit: values["no-commit"] !== true,
120
120
  git: values["no-git"] !== true,
121
121
  install: values["no-install"] !== true
@@ -123,7 +123,7 @@ async function main() {
123
123
  return;
124
124
  }
125
125
  if (positionals.length === 2 && positionals[0] === "new" && noGitFlags && noVariableFlags && noLogFlags) {
126
- await (await import("./init-DT0faD-q.js")).runNew({
126
+ await (await import("./init-BKUBf6i9.js")).runNew({
127
127
  code: positionals[1],
128
128
  clientOnly: values["client-only"],
129
129
  install: values["no-install"] !== true,
@@ -132,7 +132,7 @@ async function main() {
132
132
  return;
133
133
  }
134
134
  if ((positionals.length === 1 || positionals.length === 2) && positionals[0] === "logs" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noVariableFlags) {
135
- await (await import("./logs-CEIikWzV.js")).runLogs({
135
+ await (await import("./logs-Cv5z1e2w.js")).runLogs({
136
136
  code: positionals[1],
137
137
  filter: values.filter,
138
138
  run: values.run,
@@ -145,14 +145,14 @@ async function main() {
145
145
  return;
146
146
  }
147
147
  if (positionals.length === 3 && positionals[0] === "schedules" && positionals[1] === "run" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noLogFlags && values.secret === void 0) {
148
- await (await import("./schedules-B7xNl9oy.js")).runSchedule({
148
+ await (await import("./schedules-Dajgni_z.js")).runSchedule({
149
149
  code: positionals[2],
150
150
  yes: values.yes
151
151
  });
152
152
  return;
153
153
  }
154
154
  if ((positionals.length === 3 || positionals.length === 4) && positionals[0] === "variables" && positionals[1] === "set" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noLogFlags) {
155
- await (await import("./variables-DCbLJBr0.js")).runVariablesSet({
155
+ await (await import("./variables-B-CLu8cY.js")).runVariablesSet({
156
156
  key: positionals[2],
157
157
  secret: values.secret,
158
158
  value: positionals[3],
@@ -161,11 +161,11 @@ async function main() {
161
161
  return;
162
162
  }
163
163
  if (positionals.length === 2 && positionals[0] === "variables" && positionals[1] === "list" && values["no-install"] === void 0 && noModeFlags && noGitFlags && noVariableFlags && noLogFlags) {
164
- await (await import("./variables-DCbLJBr0.js")).runVariablesList();
164
+ await (await import("./variables-B-CLu8cY.js")).runVariablesList();
165
165
  return;
166
166
  }
167
167
  if (positionals.length === 3 && positionals[0] === "variables" && positionals[1] === "delete" && values["no-install"] === void 0 && noModeFlags && noGitFlags && values.secret === void 0 && noLogFlags) {
168
- await (await import("./variables-DCbLJBr0.js")).runVariablesDelete({
168
+ await (await import("./variables-B-CLu8cY.js")).runVariablesDelete({
169
169
  key: positionals[2],
170
170
  yes: values.yes
171
171
  });
@@ -1,4 +1,4 @@
1
- import { i as prepareAppletProjects, r as prepareAppletProject } from "./project-CWVwic2C.js";
1
+ import { i as prepareAppletProjects, r as prepareAppletProject } from "./project-CrxdZR0B.js";
2
2
  import { rm } from "node:fs/promises";
3
3
  import { resolve } from "node:path";
4
4
  import { spawn } from "node:child_process";
@@ -0,0 +1,2 @@
1
+ import { i as runBuild } from "./build-D47vK5aa.js";
2
+ export { runBuild };
@@ -1,4 +1,5 @@
1
1
  import { c as resolveInstanceUrl } from "./store-B8N_8JIN.js";
2
+ import { a as userAgent } from "./project-CrxdZR0B.js";
2
3
  //#region src/ci.ts
3
4
  function githubActionsContext() {
4
5
  const env = process.env;
@@ -38,9 +39,13 @@ async function fetchWithGitHubActions(context, request) {
38
39
  async function loadGitHubActionsBuildInputs(context, requiresChangeset) {
39
40
  const fetcher = globalThis.fetch;
40
41
  const query = requiresChangeset === void 0 ? "" : `?changeset_id=${encodeURIComponent(requiresChangeset)}`;
42
+ const agent = await userAgent();
41
43
  const response = await fetchWithGitHubActions(context, (instanceUrl, accessToken) => fetcher(`${instanceUrl}/api/ci/v1/build-inputs${query}`, {
42
44
  method: "POST",
43
- headers: { Authorization: `Bearer ${accessToken}` }
45
+ headers: {
46
+ Authorization: `Bearer ${accessToken}`,
47
+ "User-Agent": agent
48
+ }
44
49
  }));
45
50
  if (!response.ok) throw await hitchResponseError(response, "Failed to load the CI build inputs");
46
51
  const body = await response.json();
@@ -1,2 +1,2 @@
1
- import { t as hitch } from "../../hitch-client--qZVa2KM.js";
1
+ import { t as hitch } from "../../hitch-client-DtyTZzP5.js";
2
2
  export { hitch };
@@ -1,3 +1,3 @@
1
- import { t as hitch } from "../hitch-client--qZVa2KM.js";
1
+ import { t as hitch } from "../hitch-client-DtyTZzP5.js";
2
2
  import { i as createPhone, n as Phone, r as PhoneState, t as usePhone } from "../use-phone-M7c_HsB7.js";
3
3
  export { type Phone, type PhoneState, createPhone, hitch, usePhone };
@@ -0,0 +1,72 @@
1
+ import { AnyContractRouter } from "@orpc/contract";
2
+ import { ClientPromiseResult } from "@orpc/client";
3
+ //#region src/hitch/batch.d.ts
4
+ type BatchVerb = "create" | "update" | "delete" | "updateWhere";
5
+ type BatchTxRecords<Records> = { [Code in keyof Records]: { [Verb in keyof Records[Code] & BatchVerb]: Records[Code][Verb] extends ((...args: infer Args) => unknown) ? (input: Verb extends "create" ? Args[0] extends {
6
+ body: infer Body;
7
+ } ? Omit<Args[0], "body"> & {
8
+ body: Exclude<Body, readonly unknown[]>;
9
+ } : Args[0] : Args[0]) => void : never; }; };
10
+ type BatchTx<T> = T extends {
11
+ records: infer Records;
12
+ } ? BatchTxRecords<Records> : never;
13
+ type BatchRecorderOptions = {
14
+ dryRun?: boolean;
15
+ idempotencyKey?: string;
16
+ };
17
+ type BatchRecorderCall<T, Batch> = Batch extends ((...args: infer _Args) => infer Result) ? (record: (tx: BatchTx<T>) => void | Promise<void>, options?: BatchRecorderOptions) => Result : never;
18
+ type WithBatchRecorder<T> = T extends {
19
+ records: unknown;
20
+ batch: infer Batch;
21
+ } ? Omit<T, "batch"> & {
22
+ /**
23
+ * Record record writes inside `record` and send them as one atomic batch.
24
+ *
25
+ * The callback receives a `tx` whose `create` / `update` / `updateWhere` /
26
+ * `delete` calls are buffered, not sent immediately; the whole batch runs
27
+ * in a single transaction when the callback resolves.
28
+ *
29
+ * @remarks A batch may contain at most **100** requests. More than that is
30
+ * rejected with a `400` before any write runs.
31
+ */
32
+ batch: BatchRecorderCall<T, Batch> & Batch;
33
+ } : T;
34
+ //#endregion
35
+ //#region src/hitch/create.d.ts
36
+ type Many<T> = Extract<T, readonly unknown[]>;
37
+ type One<T> = Exclude<T, readonly unknown[]>;
38
+ type SplitCreate<F> = F extends ((input: infer Input extends {
39
+ body: unknown;
40
+ }, ...rest: infer Rest) => ClientPromiseResult<infer Output, infer TError>) ? [Many<Input["body"]>] extends [never] ? F : {
41
+ (input: Omit<Input, "body"> & {
42
+ body: Many<Input["body"]>;
43
+ }, ...rest: Rest): ClientPromiseResult<Many<Output>, TError>;
44
+ (input: Omit<Input, "body"> & {
45
+ body: One<Input["body"]>;
46
+ }, ...rest: Rest): ClientPromiseResult<One<Output>, TError>;
47
+ } : F extends {
48
+ call: infer Call;
49
+ } ? Omit<F, "call"> & {
50
+ call: SplitCreate<Call>;
51
+ } : F;
52
+ type WithRecordCreates<T> = T extends {
53
+ records: infer Records;
54
+ } ? Omit<T, "records"> & {
55
+ records: { [Code in keyof Records]: { [Verb in keyof Records[Code]]: Verb extends "create" ? SplitCreate<Records[Code][Verb]> : Records[Code][Verb]; }; };
56
+ } : T;
57
+ type WithSingleRecordCreates<T> = T extends {
58
+ records: infer Records;
59
+ } ? Omit<T, "records"> & {
60
+ records: { [Code in keyof Records]: { [Verb in keyof Records[Code]]: Verb extends "create" ? SplitCreate<Records[Code][Verb]> extends ((...args: infer Args) => infer Result) ? (...args: Args) => Result : Records[Code][Verb] : Records[Code][Verb]; }; };
61
+ } : T;
62
+ type WithRecordCreateCalls<Utils, Client> = Utils extends {
63
+ records: infer Records;
64
+ } ? Client extends {
65
+ records: infer Clients;
66
+ } ? Omit<Utils, "records"> & {
67
+ records: { [Code in keyof Records]: { [Verb in keyof Records[Code]]: Verb extends "create" ? Code extends keyof Clients ? Verb extends keyof Clients[Code] ? Omit<Records[Code][Verb], "call"> & {
68
+ call: SplitCreate<Clients[Code][Verb]>;
69
+ } : Records[Code][Verb] : Records[Code][Verb] : Records[Code][Verb]; }; };
70
+ } : Utils : Utils;
71
+ //#endregion
72
+ export { WithBatchRecorder as i, WithRecordCreates as n, WithSingleRecordCreates as r, WithRecordCreateCalls as t };
@@ -1,7 +1,7 @@
1
1
  import { n as readWorkspaceConfig } from "./workspace-8yqXsvce.js";
2
2
  import { t as fetchWithOrgAuth } from "./auth-D3CrCtZq.js";
3
- import { a as loadGitHubActionsSources, n as githubActionsContext, r as hitchResponseError, t as fetchWithGitHubActions } from "./ci-B5-mH-YW.js";
4
- import { n as buildPreparedApplet, r as prepareWorkspaceBuild, t as buildApplet } from "./build-DkKTiIu7.js";
3
+ import { a as loadGitHubActionsSources, n as githubActionsContext, r as hitchResponseError, t as fetchWithGitHubActions } from "./ci-BTFTCBgy.js";
4
+ import { n as buildPreparedApplet, r as prepareWorkspaceBuild, t as buildApplet } from "./build-D47vK5aa.js";
5
5
  import { createRequire } from "node:module";
6
6
  import { createHash } from "node:crypto";
7
7
  import { existsSync } from "node:fs";
@@ -1,8 +1,8 @@
1
1
  import { a as organizationInstanceUrl, c as resolveInstanceUrl } from "./store-B8N_8JIN.js";
2
2
  import { t as fetchWithOrgAuth } from "./auth-D3CrCtZq.js";
3
- import { t as loadAppletConfig } from "./load-config-BYrBjPlr.js";
4
- import { i as loadGitHubActionsBuildInputs, n as githubActionsContext } from "./ci-B5-mH-YW.js";
5
- import { r as prepareAppletProject } from "./project-CWVwic2C.js";
3
+ import { t as loadAppletConfig } from "./load-config-DGALUExv.js";
4
+ import { a as userAgent, r as prepareAppletProject } from "./project-CrxdZR0B.js";
5
+ import { i as loadGitHubActionsBuildInputs, n as githubActionsContext, r as hitchResponseError } from "./ci-BTFTCBgy.js";
6
6
  import { createRequire } from "node:module";
7
7
  import { isContractProcedure, minifyContractRouter } from "@orpc/contract";
8
8
  import { randomUUID } from "node:crypto";
@@ -58,6 +58,20 @@ export default createWorkerEntry(server, { code: ${JSON.stringify(appletCode)} }
58
58
  `);
59
59
  }
60
60
  //#endregion
61
+ //#region src/typegen/create-schema.ts
62
+ function isObject$3(value) {
63
+ return value !== null && typeof value === "object" && !Array.isArray(value);
64
+ }
65
+ function isComponentRef(value) {
66
+ return isObject$3(value) && typeof value.$ref === "string" && /^#\/components\/schemas\/[^/]+$/.test(value.$ref);
67
+ }
68
+ function singleCreateSchema(value) {
69
+ if (isComponentRef(value)) return value;
70
+ if (!isObject$3(value) || !Array.isArray(value.oneOf) || value.oneOf.length !== 2) return void 0;
71
+ const [single, array] = value.oneOf;
72
+ return isComponentRef(single) && isObject$3(array) && array.type === "array" && isComponentRef(array.items) && array.items.$ref === single.$ref ? single : void 0;
73
+ }
74
+ //#endregion
61
75
  //#region src/typegen/operations.ts
62
76
  const RECORD_ROUTE = /^\/v1\/([^/]+)(?:\/(\{id\}(?:\/history)?|query|update|aggregate))?$/;
63
77
  const COMPONENT_REF_PREFIX$1 = "#/components/schemas/";
@@ -195,9 +209,15 @@ function prepareRecordSpec(spec, manifest) {
195
209
  const content = isObject$2(response?.content) ? response.content : void 0;
196
210
  const mediaType = isObject$2(content?.["application/json"]) ? content["application/json"] : void 0;
197
211
  const schema = isObject$2(mediaType) ? mediaType.schema : void 0;
198
- const ref = isObject$2(schema) ? schema.$ref : void 0;
212
+ const ref = record.verb === "create" ? singleCreateSchema(schema)?.$ref : isObject$2(schema) ? schema.$ref : void 0;
199
213
  if (typeof ref !== "string" || !ref.startsWith(COMPONENT_REF_PREFIX$1) || ref.slice(21).length === 0 || ref.slice(21).includes("/")) throw new Error(`object "${record.objectCode}": paths.${path}.${method}.responses.${status}.content.application/json.schema expected a component schema $ref, found ${describeValue$1(schema, true)}`);
200
214
  }
215
+ if (record.verb === "create") {
216
+ const request = isObject$2(operation.requestBody) ? operation.requestBody : void 0;
217
+ const content = isObject$2(request?.content) ? request.content : void 0;
218
+ const body = isObject$2(content?.["application/json"]) ? content["application/json"] : void 0;
219
+ if (singleCreateSchema(body?.schema) === void 0) throw new Error(`object "${record.objectCode}": paths.${path}.${method}.requestBody.content.application/json.schema expected a component schema $ref or single/array oneOf, found ${describeValue$1(body?.schema, true)}`);
220
+ }
201
221
  const prepared = withRecordOperationId(path, method, operation);
202
222
  return prepared ? [[method, prepared]] : [];
203
223
  });
@@ -262,7 +282,7 @@ function describeValue(value, objectDescription = "an object") {
262
282
  return `${typeof value} ${JSON.stringify(value)}`;
263
283
  }
264
284
  function componentName(value, path, objectCode) {
265
- const ref = isObject$1(value) ? value.$ref : void 0;
285
+ const ref = singleCreateSchema(value)?.$ref;
266
286
  if (typeof ref !== "string" || !ref.startsWith(COMPONENT_REF_PREFIX)) throw new Error(`object "${objectCode}": ${path} expected a component schema $ref, found ${describeValue(value, "an object without a $ref")}`);
267
287
  const name = ref.slice(21);
268
288
  if (name.length === 0 || name.includes("/")) throw new Error(`object "${objectCode}": ${path} expected a direct component schema $ref, found ${JSON.stringify(ref)}`);
@@ -427,8 +447,12 @@ async function responseJson(response) {
427
447
  async function loadAuthenticatedSpec(manifest) {
428
448
  const github = githubActionsContext();
429
449
  if (github !== void 0) return (await loadGitHubActionsBuildInputs(github, manifest.requiresChangeset)).openapi;
430
- 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}` } }));
431
- if (!response.ok) throw new Error(`Failed to load the organization's OpenAPI spec (${response.status}).`);
450
+ const agent = await userAgent();
451
+ 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: {
452
+ Authorization: `Bearer ${accessToken}`,
453
+ "User-Agent": agent
454
+ } }));
455
+ if (!response.ok) throw await hitchResponseError(response, "Failed to load the organization's OpenAPI spec");
432
456
  return responseJson(response);
433
457
  }
434
458
  async function loadThemeStylesheet(orgCode) {
@@ -0,0 +1,2 @@
1
+ import { r as runGenerate } from "./generate-BLD0DoCk.js";
2
+ export { runGenerate };
@@ -1,15 +1,16 @@
1
1
  import { l as RegisteredContract, u as RegisteredManifest } from "./manifest-BBHD_EY9.js";
2
2
  import { t as NarrowContract } from "./contract-CJv-n1l3.js";
3
- import { t as WithBatchRecorder } from "./batch-Qa4B4-Yp.js";
3
+ import { i as WithBatchRecorder, n as WithRecordCreates, r as WithSingleRecordCreates, t as WithRecordCreateCalls } from "./create-C2UrZYSK.js";
4
4
  import { o as WithFilesUpload } from "./upload-D_kkmne_.js";
5
5
  import { t as ExactRouterUtils } from "./query-utils-zz9pVjgp.js";
6
6
  import { ContractRouterClient } from "@orpc/contract";
7
7
  //#region src/author/hitch-client.d.ts
8
8
  type AuthorContract = NarrowContract<RegisteredContract, RegisteredManifest>;
9
9
  type BaseHitchClient = ContractRouterClient<AuthorContract>;
10
- type AuthorHitchClient = WithBatchRecorder<BaseHitchClient>;
11
- type BaseHitchUtils = ExactRouterUtils<BaseHitchClient>;
12
- type AuthorHitchUtils = AuthorHitchClient extends {
10
+ type AuthorHitchClient = WithRecordCreates<WithBatchRecorder<BaseHitchClient>>;
11
+ type BaseHitchUtils = ExactRouterUtils<WithSingleRecordCreates<BaseHitchClient>>;
12
+ type AuthorHitchUtils = WithRecordCreateCalls<BatchHitchUtils, BaseHitchClient>;
13
+ type BatchHitchUtils = AuthorHitchClient extends {
13
14
  batch: infer Batch;
14
15
  } ? BaseHitchUtils extends {
15
16
  batch: infer BatchUtils;
@@ -1,8 +1,8 @@
1
1
  import { c as resolveInstanceUrl, s as resolveAuthForOrg } from "./store-B8N_8JIN.js";
2
2
  import { n as readWorkspaceConfig } from "./workspace-8yqXsvce.js";
3
- import { r as runGenerate } from "./generate-8yyxKRSz.js";
4
- import { n as loadAppletSourceDefinition, o as APPLET_CODE_PATTERN, s as ORG_CODE_PATTERN } from "./load-config-BYrBjPlr.js";
5
- import { a as writeAppletSupport, n as loadCliManifest, o as writeWorkspaceSupport, t as assertWorkspaceCli } from "./project-CWVwic2C.js";
3
+ import { r as runGenerate } from "./generate-BLD0DoCk.js";
4
+ import { c as ORG_CODE_PATTERN, n as loadAppletSourceDefinition, s as APPLET_CODE_PATTERN } from "./load-config-DGALUExv.js";
5
+ import { n as loadCliManifest, o as writeAppletSupport, s as writeWorkspaceSupport, t as assertWorkspaceCli } from "./project-CrxdZR0B.js";
6
6
  import { access, cp, mkdir, readdir, writeFile } from "node:fs/promises";
7
7
  import { relative, resolve } from "node:path";
8
8
  import { spawn } from "node:child_process";
@@ -135,6 +135,9 @@ z.strictObject({
135
135
  variables: appletManifestShape.variables,
136
136
  objects: appletManifestShape.objects
137
137
  }).superRefine(checkDuplicateCodes).superRefine(checkPublicFields);
138
+ function appletMountPath({ code, public: isPublic }) {
139
+ return isPublic ? `pages/${code}` : code;
140
+ }
138
141
  const packageVersionsSchema = z.record(z.string().min(1), z.string().min(1)).readonly();
139
142
  const RESERVED_APPLET_PACKAGES = /* @__PURE__ */ new Set([
140
143
  "@fontsource-variable/geist-mono",
@@ -247,4 +250,4 @@ async function loadAppletConfig(root) {
247
250
  };
248
251
  }
249
252
  //#endregion
250
- export { appletSourceDefinitionSchema as a, appletManifestSchema as i, loadAppletSourceDefinition as n, APPLET_CODE_PATTERN as o, resolveWorkspaceOrg as r, ORG_CODE_PATTERN as s, loadAppletConfig as t };
253
+ export { appletMountPath as a, ORG_CODE_PATTERN as c, appletManifestSchema as i, loadAppletSourceDefinition as n, appletSourceDefinitionSchema as o, resolveWorkspaceOrg as r, APPLET_CODE_PATTERN as s, loadAppletConfig as t };
@@ -1,6 +1,6 @@
1
1
  import { n as readWorkspaceConfig } from "./workspace-8yqXsvce.js";
2
2
  import { t as fetchWithOrgAuth } from "./auth-D3CrCtZq.js";
3
- import { o as APPLET_CODE_PATTERN, r as resolveWorkspaceOrg, t as loadAppletConfig } from "./load-config-BYrBjPlr.js";
3
+ import { r as resolveWorkspaceOrg, s as APPLET_CODE_PATTERN, t as loadAppletConfig } from "./load-config-DGALUExv.js";
4
4
  import { z } from "zod";
5
5
  //#region src/logs.ts
6
6
  const LOG_LEVELS = [
@@ -1,6 +1,6 @@
1
1
  import { a as organizationInstanceUrl, n as DEFAULT_INSTANCE_URL } from "./store-B8N_8JIN.js";
2
2
  import { n as readWorkspaceConfig } from "./workspace-8yqXsvce.js";
3
- import { n as loadAppletSourceDefinition } from "./load-config-BYrBjPlr.js";
3
+ import { a as appletMountPath, n as loadAppletSourceDefinition } from "./load-config-DGALUExv.js";
4
4
  import { z } from "zod";
5
5
  import { existsSync } from "node:fs";
6
6
  import { cp, mkdir, readFile, readdir, rm, symlink, writeFile } from "node:fs/promises";
@@ -115,19 +115,26 @@ const cliManifestSchema = z.object({
115
115
  typescript: cliManifestValueSchema
116
116
  })
117
117
  });
118
- async function loadCliManifest(options) {
118
+ async function loadPackageManifest() {
119
119
  const result = cliManifestSchema.safeParse(JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8")));
120
120
  if (!result.success) {
121
121
  const issue = result.error.issues.at(0);
122
122
  if (issue === void 0) throw new Error("Invalid CLI package manifest.");
123
123
  throw new Error(`Invalid CLI package manifest field "${issue.path.join(".")}": ${issue.message}.`);
124
124
  }
125
- 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:"));
125
+ return result.data;
126
+ }
127
+ async function userAgent() {
128
+ return `hitch-applet-sdk/${(await loadPackageManifest()).version}`;
129
+ }
130
+ async function loadCliManifest(options) {
131
+ const cli = await loadPackageManifest();
132
+ const catalogEntry = [...Object.entries(cli.dependencies).map(([name, value]) => [`dependencies.${name}`, value]), ...Object.entries(cli.peerDependencies).map(([name, value]) => [`peerDependencies.${name}`, value])].find(([, value]) => value.startsWith("catalog:"));
126
133
  if (catalogEntry !== void 0) {
127
134
  if (options?.allowDevelopment === true) return void 0;
128
135
  throw new Error(`Invalid CLI package manifest field "${catalogEntry[0]}": "catalog:" identifies an unpublished development build. Run the published @hitch42/applet CLI instead.`);
129
136
  }
130
- return result.data;
137
+ return cli;
131
138
  }
132
139
  function assertWorkspaceCli(config, cli) {
133
140
  const runningCli = `${cli.name}@${cli.version}`;
@@ -497,7 +504,7 @@ export default defineConfig({
497
504
  children: [{
498
505
  type: "physical",
499
506
  directory: ".",
500
- pathPrefix: definition.code
507
+ pathPrefix: appletMountPath(definition)
501
508
  }]
502
509
  }
503
510
  }, null, 2)}\n`) : rm(resolve(root, "tsr.config.json"), { force: true }),
@@ -562,4 +569,4 @@ async function prepareAppletProject(appletRoot = process.cwd()) {
562
569
  return workspaceRoot;
563
570
  }
564
571
  //#endregion
565
- export { writeAppletSupport as a, prepareAppletProjects as i, loadCliManifest as n, writeWorkspaceSupport as o, prepareAppletProject as r, assertWorkspaceCli as t };
572
+ export { userAgent as a, prepareAppletProjects as i, loadCliManifest as n, writeAppletSupport as o, prepareAppletProject as r, writeWorkspaceSupport as s, assertWorkspaceCli as t };
@@ -1,4 +1,4 @@
1
- import { t as loadAppletConfig } from "./load-config-BYrBjPlr.js";
1
+ import { t as loadAppletConfig } from "./load-config-DGALUExv.js";
2
2
  import { t as question } from "./prompt-ChS-grYO.js";
3
3
  import { RPCLink } from "@orpc/client/fetch";
4
4
  import { readFile } from "node:fs/promises";
package/dist/server.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { a as createWorkflow, i as WorkflowStep, n as WorkflowDefinition, r as WorkflowDuration } from "./workflow-DurM6Fwx.js";
2
2
  import { l as RegisteredContract, m as RegisteredWorkflows, p as RegisteredVariables, u as RegisteredManifest } from "./manifest-BBHD_EY9.js";
3
3
  import { t as NarrowContract } from "./contract-CJv-n1l3.js";
4
- import { t as WithBatchRecorder } from "./batch-Qa4B4-Yp.js";
4
+ import { i as WithBatchRecorder, n as WithRecordCreates } from "./create-C2UrZYSK.js";
5
5
  import { o as WithFilesUpload } from "./upload-D_kkmne_.js";
6
6
  import { ContractRouterClient } from "@orpc/contract";
7
7
  //#region src/server/workflows-client.d.ts
@@ -43,7 +43,7 @@ declare const log: {
43
43
  //#endregion
44
44
  //#region src/author/server.d.ts
45
45
  type AuthorContract = NarrowContract<RegisteredContract, RegisteredManifest>;
46
- type AuthorHitchClient = WithBatchRecorder<ContractRouterClient<AuthorContract>>;
46
+ type AuthorHitchClient = WithRecordCreates<WithBatchRecorder<ContractRouterClient<AuthorContract>>>;
47
47
  type AuthorHitch = WithFilesUpload<AuthorHitchClient> & (RegisteredManifest extends {
48
48
  public: true;
49
49
  } ? {} : {
@@ -1,5 +1,5 @@
1
1
  import { t as fetchWithOrgAuth } from "./auth-D3CrCtZq.js";
2
- import { t as loadAppletConfig } from "./load-config-BYrBjPlr.js";
2
+ import { t as loadAppletConfig } from "./load-config-DGALUExv.js";
3
3
  import { t as question } from "./prompt-ChS-grYO.js";
4
4
  import { z } from "zod";
5
5
  //#region src/variables.ts
package/dist/vite.js CHANGED
@@ -3,8 +3,8 @@ import { a as openQueryCacheDatabase } from "./query-cache-CXmAyLv3.js";
3
3
  import { d as HITCH_SESSION_HEADER, f as HITCH_USER_HEADER } from "./headers-CeRX-Xji.js";
4
4
  import { a as workflowOutcomeSchema, n as runWorkflowJournal } from "./workflow-engine-BOTzURKM.js";
5
5
  import { a as organizationInstanceUrl, c as resolveInstanceUrl, o as rejectEnvironmentKey, r as bearerToken, s as resolveAuthForOrg } from "./store-B8N_8JIN.js";
6
- import { a as writeRegisterDeclaration, c as writeAppletRoot, d as writeServerEntry, i as syncContract, l as writeClientEntry, n as routesModuleSource, u as writeManifestGen } from "./generate-8yyxKRSz.js";
7
- import { a as appletSourceDefinitionSchema, i as appletManifestSchema, o as APPLET_CODE_PATTERN, r as resolveWorkspaceOrg } from "./load-config-BYrBjPlr.js";
6
+ import { a as writeRegisterDeclaration, c as writeAppletRoot, d as writeServerEntry, i as syncContract, l as writeClientEntry, n as routesModuleSource, u as writeManifestGen } from "./generate-BLD0DoCk.js";
7
+ import { a as appletMountPath, i as appletManifestSchema, o as appletSourceDefinitionSchema, r as resolveWorkspaceOrg, s as APPLET_CODE_PATTERN } from "./load-config-DGALUExv.js";
8
8
  import { z } from "zod";
9
9
  import { randomUUID } from "node:crypto";
10
10
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
@@ -572,7 +572,7 @@ function applet(sourceDefinition) {
572
572
  }
573
573
  const { dependencies: _dependencies, devDependencies: _devDependencies, ...definition } = parsedSourceDefinition.data;
574
574
  const parsedDefinition = { data: definition };
575
- const mountPath = definition.public ? `app/${definition.code}` : definition.code;
575
+ const mountPath = appletMountPath(definition);
576
576
  let appletConfig;
577
577
  let buildRootOutDir;
578
578
  let clearedOutDir = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hitch42/applet",
3
- "version": "0.1.1-beta.19",
3
+ "version": "0.1.1-beta.20",
4
4
  "license": "MIT",
5
5
  "bin": {
6
6
  "applet": "./dist/applet.js"
@@ -11,7 +11,7 @@ Treat each applet as an isolated microfrontend. Keep it separate from the data s
11
11
 
12
12
  ## Public applets
13
13
 
14
- Set `public: true` for an applet that anonymous visitors can use. It is served at `https://{org}.hitch42.app/app/{code}`. It runs as the applet identity. Its manifest grants cap its access.
14
+ Set `public: true` for an applet that anonymous visitors can use. It is served at `https://{org}.hitch42.app/pages/{code}`. It runs as the applet identity. Its manifest grants cap its access.
15
15
 
16
16
  A public applet cannot use schedules, email, telephony, workflows, or `@hitch42/applet/client/hitch`. Client code calls its server procedures with `api` from `@hitch42/applet/client`.
17
17
 
@@ -14,7 +14,7 @@ Use the generated Hitch contract as the typed data plane.
14
14
  ## Use record verbs
15
15
 
16
16
  - `list` sends `GET /v1/<objectCode>` and lists records with query parameters.
17
- - `create` sends `POST /v1/<objectCode>` and creates one record.
17
+ - `create` sends `POST /v1/<objectCode>` and creates one record or an array of records.
18
18
  - `get` sends `GET /v1/<objectCode>/{id}` and gets one record.
19
19
  - `history` sends `GET /v1/<objectCode>/{id}/history` and gets record changes.
20
20
  - `update` sends `PATCH /v1/<objectCode>/{id}` and updates one record.
@@ -74,6 +74,21 @@ const deal = await hitch.records.deals.get({
74
74
  - Do not use `.queryOptions(...)` or `.mutationOptions(...)` on the server.
75
75
  - Use the server SDK for imperative data access, secrets, or external services.
76
76
 
77
+ ## Create records
78
+
79
+ Pass one object in `body` to create one record. The call returns one record.
80
+ Use server SDK `create(...)` or client `create.call(...)` with an array to create up to 1000 records. The call returns an array in the same order.
81
+
82
+ ```ts
83
+ const deals = await hitch.records.deals.create({
84
+ body: [{ name: "First deal" }, { name: "Second deal" }],
85
+ });
86
+ ```
87
+
88
+ The call creates all records or none. If one record fails, the error gives its index in `entry_index`.
89
+ The first record has index 0. An empty array returns an empty array and requires the create grant.
90
+ `mutationOptions` creates one record. Batch recorder calls accept one record per create call.
91
+
77
92
  ## Read history
78
93
 
79
94
  ```ts
@@ -1,30 +0,0 @@
1
- import { AnyContractRouter } from "@orpc/contract";
2
- //#region src/hitch/batch.d.ts
3
- type BatchVerb = "create" | "update" | "delete" | "updateWhere";
4
- type BatchTxRecords<Records> = { [Code in keyof Records]: { [Verb in keyof Records[Code] & BatchVerb]: Records[Code][Verb] extends ((...args: infer Args) => unknown) ? (input: Args[0]) => void : never; }; };
5
- type BatchTx<T> = T extends {
6
- records: infer Records;
7
- } ? BatchTxRecords<Records> : never;
8
- type BatchRecorderOptions = {
9
- dryRun?: boolean;
10
- idempotencyKey?: string;
11
- };
12
- type BatchRecorderCall<T, Batch> = Batch extends ((...args: infer _Args) => infer Result) ? (record: (tx: BatchTx<T>) => void | Promise<void>, options?: BatchRecorderOptions) => Result : never;
13
- type WithBatchRecorder<T> = T extends {
14
- records: unknown;
15
- batch: infer Batch;
16
- } ? Omit<T, "batch"> & {
17
- /**
18
- * Record record writes inside `record` and send them as one atomic batch.
19
- *
20
- * The callback receives a `tx` whose `create` / `update` / `updateWhere` /
21
- * `delete` calls are buffered, not sent immediately; the whole batch runs
22
- * in a single transaction when the callback resolves.
23
- *
24
- * @remarks A batch may contain at most **100** requests. More than that is
25
- * rejected with a `400` before any write runs.
26
- */
27
- batch: BatchRecorderCall<T, Batch> & Batch;
28
- } : T;
29
- //#endregion
30
- export { WithBatchRecorder as t };
@@ -1,2 +0,0 @@
1
- import { i as runBuild } from "./build-DkKTiIu7.js";
2
- export { runBuild };
@@ -1,2 +0,0 @@
1
- import { r as runGenerate } from "./generate-8yyxKRSz.js";
2
- export { runGenerate };