@zerolith/forms 0.1.0-alpha.5 → 0.1.0-alpha.6

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/form.d.ts CHANGED
@@ -28,7 +28,9 @@ export interface Submission {
28
28
  export interface SubmissionOutcome {
29
29
  /** The parsed body: JSON when the response says so, text otherwise, undefined for an empty body. */
30
30
  readonly result: unknown;
31
+ /** The successful response, as `fetch` or a custom `send` returned it; its body has already been read into `result` unless it was redirected. */
31
32
  readonly response: Response;
33
+ /** The form that was submitted, already reset when the `reset` option is set. */
32
34
  readonly element: HTMLFormElement;
33
35
  }
34
36
  /** Options for `createForm`. */
@@ -63,6 +65,7 @@ export interface Field {
63
65
  }
64
66
  /** The enhanced form. */
65
67
  export interface Form {
68
+ /** The current submission's stage: `pending` while in flight, then `success`, `failure` with a problem, or `error` when it did not complete; `idle` before the first submission and after `reset()`. */
66
69
  readonly status: ReadableSignal<FormStatus>;
67
70
  /** True while a submission is in flight. */
68
71
  readonly pending: ReadableSignal<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"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"}
package/dist/form.js CHANGED
@@ -8,6 +8,78 @@
8
8
  import { PROBLEM_MEDIA_TYPE, batch, computed, isProblem, signal } from "zerolith";
9
9
  import { validateForm } from "./schema.js";
10
10
  const EMPTY = [];
11
+ /** Calls an application callback, reporting what it throws as an uncaught error would be, without changing the form's state. */
12
+ function guarded(callback) {
13
+ try {
14
+ callback();
15
+ }
16
+ catch (thrown) {
17
+ if (typeof reportError === "function") {
18
+ reportError(thrown);
19
+ }
20
+ else {
21
+ queueMicrotask(() => {
22
+ throw thrown;
23
+ });
24
+ }
25
+ }
26
+ }
27
+ /** The `FormData` implementation probed, and whether its constructor adds the submitter's entry, which browsers before Chrome 112 and Firefox 111 skip. */
28
+ let probed;
29
+ /** The form's data as the browser submits it, with the submitter's entry added where `new FormData(form, submitter)` leaves it out. */
30
+ function submittedData(element, submitter) {
31
+ const data = new FormData(element, submitter ?? undefined);
32
+ if (submitter === null) {
33
+ return data;
34
+ }
35
+ if (probed?.implementation !== FormData) {
36
+ const form = document.createElement("form");
37
+ const button = document.createElement("button");
38
+ button.name = "probe";
39
+ button.value = "kept";
40
+ form.append(button);
41
+ probed = { implementation: FormData, keepsSubmitter: new FormData(form, button).get("probe") === "kept" };
42
+ }
43
+ const name = submitter.getAttribute("name");
44
+ if (probed.keepsSubmitter || name === null || name === "") {
45
+ return data;
46
+ }
47
+ if (submitter instanceof HTMLInputElement && submitter.type === "image") {
48
+ data.append(`${name}.x`, "0");
49
+ data.append(`${name}.y`, "0");
50
+ }
51
+ else {
52
+ data.append(name, submitter.value);
53
+ }
54
+ return data;
55
+ }
56
+ /**
57
+ * The problem a failed response describes: its body when that is a problem
58
+ * document, or one built from the status. The server is a trust boundary,
59
+ * so `fields` keeps only own keys whose value is a message or a list of
60
+ * messages, a lone message becoming a list of one.
61
+ */
62
+ function problemOf(body, response) {
63
+ if (!isProblem(body)) {
64
+ return { status: response.status, title: response.statusText === "" ? `HTTP ${response.status}` : response.statusText };
65
+ }
66
+ if (body.fields === undefined) {
67
+ return body;
68
+ }
69
+ const fields = Object.create(null);
70
+ for (const [name, value] of Object.entries(body.fields)) {
71
+ if (typeof value === "string") {
72
+ fields[name] = [value];
73
+ }
74
+ else if (Array.isArray(value)) {
75
+ const messages = value.filter((message) => typeof message === "string");
76
+ if (messages.length > 0) {
77
+ fields[name] = messages;
78
+ }
79
+ }
80
+ }
81
+ return { ...body, fields };
82
+ }
11
83
  function entries(data) {
12
84
  return [...data].map(([name, value]) => [name, typeof value === "string" ? value : value.name]);
13
85
  }
@@ -23,7 +95,7 @@ async function defaultSend(submission, headers, fetchImpl) {
23
95
  url.search = new URLSearchParams(entries(data)).toString();
24
96
  return fetchImpl(url, init);
25
97
  }
26
- const enctype = submitter?.getAttribute("formenctype") ?? element.enctype;
98
+ const enctype = submitter !== null && submitter.hasAttribute("formenctype") ? submitter.formEnctype : element.enctype;
27
99
  if (enctype === "multipart/form-data") {
28
100
  init.body = data;
29
101
  }
@@ -65,10 +137,10 @@ export function createForm(options = {}) {
65
137
  problem.set(found);
66
138
  status.set("failure");
67
139
  });
68
- options.onFailure?.(found, element);
140
+ guarded(() => options.onFailure?.(found, element));
69
141
  };
70
142
  const run = async (element, submitter, method, action, current) => {
71
- const data = new FormData(element, submitter ?? undefined);
143
+ const data = submittedData(element, submitter);
72
144
  batch(() => {
73
145
  status.set("pending");
74
146
  problem.set(undefined);
@@ -89,14 +161,13 @@ export function createForm(options = {}) {
89
161
  if (current.signal.aborted) {
90
162
  return;
91
163
  }
92
- const type = response.headers.get("content-type") ?? "";
93
- if (type.includes(PROBLEM_MEDIA_TYPE)) {
94
- fail((await response.json()), element);
95
- return;
96
- }
97
- if (!response.ok) {
164
+ const type = (response.headers.get("content-type") ?? "").toLowerCase();
165
+ if (type.includes(PROBLEM_MEDIA_TYPE) || !response.ok) {
98
166
  const body = type.includes("json") ? await response.json().catch(() => undefined) : undefined;
99
- fail(isProblem(body) ? body : { status: response.status, title: response.statusText === "" ? `HTTP ${response.status}` : response.statusText }, element);
167
+ if (current.signal.aborted) {
168
+ return;
169
+ }
170
+ fail(problemOf(body, response), element);
100
171
  return;
101
172
  }
102
173
  const parsed = response.redirected ? undefined : await parseBody(response);
@@ -110,7 +181,7 @@ export function createForm(options = {}) {
110
181
  if (options.reset === true) {
111
182
  element.reset();
112
183
  }
113
- options.onSuccess?.({ result: parsed, response, element });
184
+ guarded(() => options.onSuccess?.({ result: parsed, response, element }));
114
185
  if (response.redirected) {
115
186
  (options.navigate ?? ((url) => location.assign(url)))(response.url);
116
187
  }
@@ -124,7 +195,10 @@ export function createForm(options = {}) {
124
195
  field(name) {
125
196
  let field = fields.get(name);
126
197
  if (field === undefined) {
127
- const errors = computed(() => problem.get()?.fields?.[name] ?? EMPTY);
198
+ const errors = computed(() => {
199
+ const found = problem.get()?.fields;
200
+ return found !== undefined && Object.hasOwn(found, name) ? found[name] ?? EMPTY : EMPTY;
201
+ });
128
202
  field = {
129
203
  errors,
130
204
  error: computed(() => errors.get()[0]),
@@ -137,7 +211,7 @@ export function createForm(options = {}) {
137
211
  submit(event) {
138
212
  const element = event.currentTarget;
139
213
  const submitter = event.submitter;
140
- const method = (submitter?.getAttribute("formmethod") ?? element.getAttribute("method") ?? "get").toLowerCase();
214
+ const method = submitter !== null && submitter.hasAttribute("formmethod") ? submitter.formMethod : element.method;
141
215
  if (method === "dialog") {
142
216
  return;
143
217
  }
@@ -154,7 +228,7 @@ export function createForm(options = {}) {
154
228
  error.set(thrown);
155
229
  status.set("error");
156
230
  });
157
- options.onError?.(thrown, element);
231
+ guarded(() => options.onError?.(thrown, element));
158
232
  });
159
233
  },
160
234
  reset() {
package/dist/form.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"form.js","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,kBAAkB,EAAqC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACrH,OAAO,EAAuB,YAAY,EAAE,MAAM,aAAa,CAAC;AAqFhE,MAAM,KAAK,GAAsB,EAAE,CAAC;AAEpC,SAAS,OAAO,CAAC,IAAc;IAE3B,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACpG,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,UAAsB,EAAE,OAAgC,EAAE,SAAuB;IAExG,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC;IAC/E,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,EACjC,CAAC;QACG,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,qBAAqB,kBAAkB,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,IAAI,GAAgB,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;IAC/H,IAAI,MAAM,KAAK,KAAK,EACpB,CAAC;QACG,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5B,GAAG,CAAC,MAAM,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC3D,OAAO,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,OAAO,GAAG,SAAS,EAAE,YAAY,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC;IAC1E,IAAI,OAAO,KAAK,qBAAqB,EACrC,CAAC;QACG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC;SACI,IAAI,OAAO,KAAK,YAAY,EACjC,CAAC;QACG,cAAc,CAAC,GAAG,CAAC,cAAc,EAAE,2BAA2B,CAAC,CAAC;QAChE,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,KAAK,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;SAED,CAAC;QACG,IAAI,CAAC,IAAI,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,QAAkB;IAEvC,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EACtD,CAAC;QACG,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IACxD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EACzB,CAAC;QACG,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,OAAO,GAAgB,EAAE;IAEhD,MAAM,MAAM,GAAG,MAAM,CAAa,MAAM,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,MAAM,CAAsB,SAAS,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,MAAM,CAAU,SAAS,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAU,SAAS,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,SAAS,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiB,CAAC;IACxC,IAAI,UAAuC,CAAC;IAE5C,MAAM,IAAI,GAAG,CAAC,KAAc,EAAE,OAAwB,EAAQ,EAAE;QAE5D,KAAK,CAAC,GAAG,EAAE;YAEP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC,CAAC;IAEF,MAAM,GAAG,GAAG,KAAK,EAAE,OAAwB,EAAE,SAA6B,EAAE,MAAc,EAAE,MAAW,EAAE,OAAwB,EAAiB,EAAE;QAEhJ,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,OAAO,EAAE,SAAS,IAAI,SAAS,CAAC,CAAC;QAC3D,KAAK,CAAC,GAAG,EAAE;YAEP,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACvB,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;QACH,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAChC,CAAC;YACG,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC5D,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,EAC1B,CAAC;gBACG,OAAO;YACX,CAAC;YACD,IAAI,UAAU,CAAC,OAAO,KAAK,SAAS,EACpC,CAAC;gBACG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAClC,OAAO;YACX,CAAC;QACL,CAAC;QACD,MAAM,UAAU,GAAe,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QACpG,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QAClI,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,EAC1B,CAAC;YACG,OAAO;QACX,CAAC;QACD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QACxD,IAAI,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EACrC,CAAC;YACG,IAAI,CAAC,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAY,EAAE,OAAO,CAAC,CAAC;YAClD,OAAO;QACX,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAChB,CAAC;YACG,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC9F,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC;YACzJ,OAAO;QACX,CAAC;QACD,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC3E,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,EAC1B,CAAC;YACG,OAAO;QACX,CAAC;QACD,KAAK,CAAC,GAAG,EAAE;YAEP,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACnB,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,EAC1B,CAAC;YACG,OAAO,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;QACD,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3D,IAAI,QAAQ,CAAC,UAAU,EACvB,CAAC;YACG,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACxE,CAAC;IACL,CAAC,CAAC;IAEF,OAAO;QACH,MAAM;QACN,OAAO;QACP,OAAO;QACP,MAAM;QACN,KAAK;QACL,KAAK,CAAC,IAAY;YAEd,IAAI,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,KAAK,KAAK,SAAS,EACvB,CAAC;gBACG,MAAM,MAAM,GAAG,QAAQ,CAAoB,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;gBACzF,KAAK,GAAG;oBACJ,MAAM;oBACN,KAAK,EAAE,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;oBACtC,OAAO,EAAE,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;iBACnD,CAAC;gBACF,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC5B,CAAC;YACD,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,MAAM,CAAC,KAAkB;YAErB,MAAM,OAAO,GAAG,KAAK,CAAC,aAAgC,CAAC;YACvD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;YAClC,MAAM,MAAM,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;YAChH,IAAI,MAAM,KAAK,QAAQ,EACvB,CAAC;gBACG,OAAO;YACX,CAAC;YACD,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC,CAAC,CAAE,SAA+B,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACtI,UAAU,EAAE,KAAK,EAAE,CAAC;YACpB,MAAM,OAAO,GAAG,IAAI,eAAe,EAAE,CAAC;YACtC,UAAU,GAAG,OAAO,CAAC;YACrB,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,MAAe,EAAE,EAAE;gBAEvE,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,EAC1B,CAAC;oBACG,OAAO;gBACX,CAAC;gBACD,KAAK,CAAC,GAAG,EAAE;oBAEP,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBAClB,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBACxB,CAAC,CAAC,CAAC;gBACH,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACvC,CAAC,CAAC,CAAC;QACP,CAAC;QACD,KAAK;YAED,UAAU,EAAE,KAAK,EAAE,CAAC;YACpB,UAAU,GAAG,SAAS,CAAC;YACvB,KAAK,CAAC,GAAG,EAAE;gBAEP,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACnB,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBACvB,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBACtB,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACzB,CAAC,CAAC,CAAC;QACP,CAAC;KACJ,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"form.js","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"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"}
package/dist/schema.d.ts CHANGED
@@ -7,10 +7,12 @@
7
7
  import type { Problem } from "zerolith";
8
8
  /** One segment of an issue path in object form. */
9
9
  export interface StandardPathSegment {
10
+ /** The key representing the path segment; `problemFromIssues` converts it to a string and joins the path's keys with dots to name the field. */
10
11
  readonly key: PropertyKey;
11
12
  }
12
13
  /** One validation failure. */
13
14
  export interface StandardIssue {
15
+ /** The error message of the issue; `problemFromIssues` lists it under the field its path names, or in `detail` when the path is absent or empty. */
14
16
  readonly message: string;
15
17
  /** The path to the failing value; absent for an issue about the whole input. */
16
18
  readonly path?: ReadonlyArray<PropertyKey | StandardPathSegment> | undefined;
@@ -24,6 +26,7 @@ export type StandardResult<Output> = {
24
26
  };
25
27
  /** The Standard Schema V1 interface, as published at standardschema.dev. */
26
28
  export interface StandardSchema<Input = unknown, Output = Input> {
29
+ /** The Standard properties: the `version` of the specification, the `vendor` name of the schema library, the optional inferred `types`, and the `validate` function that `validateForm` calls and awaits. */
27
30
  readonly "~standard": {
28
31
  readonly version: 1;
29
32
  readonly vendor: string;
@@ -46,7 +49,7 @@ export type Validation<Output> = {
46
49
  readonly value?: undefined;
47
50
  readonly problem: Problem;
48
51
  };
49
- /** Turns `FormData` into a plain object. A name that appears once maps to its value; a name that appears more than once maps to an array of its values, in order. */
52
+ /** Turns `FormData` into a plain object with no prototype, so a field named `constructor` or `__proto__` is a field like any other. A name that appears once maps to its value; a name that appears more than once maps to an array of its values, in order. */
50
53
  export declare function formValues(data: FormData): FormValues;
51
54
  /** Groups issues into a problem: path-bearing issues under `fields`, the rest in `detail`. */
52
55
  export declare function problemFromIssues(issues: ReadonlyArray<StandardIssue>): Problem;
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAe,OAAO,EAAE,MAAM,UAAU,CAAC;AAErD,mDAAmD;AACnD,MAAM,WAAW,mBAAmB;IAEhC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;CAC7B;AAED,8BAA8B;AAC9B,MAAM,WAAW,aAAa;IAE1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,WAAW,GAAG,mBAAmB,CAAC,GAAG,SAAS,CAAC;CAChF;AAED,uDAAuD;AACvD,MAAM,MAAM,cAAc,CAAC,MAAM,IAC3B;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;CAAE,CAAC;AAExD,4EAA4E;AAC5E,MAAM,WAAW,cAAc,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK;IAE3D,QAAQ,CAAC,WAAW,EAAE;QAClB,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,cAAc,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;QAChG,QAAQ,CAAC,KAAK,CAAC,EAAE;YAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;KACnF,CAAC;CACL;AAED,mCAAmC;AACnC,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,cAAc,IAAI,CAAC,SAAS,cAAc,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC;AAErH,uEAAuE;AACvE,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,CAAC,CAAC;AAEnF,iFAAiF;AACjF,MAAM,MAAM,UAAU,CAAC,MAAM,IACvB;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAA;CAAE,GACxD;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEhE,qKAAqK;AACrK,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAoBrD;AAWD,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,OAAO,CAoB/E;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,CAAC,SAAS,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CASrJ"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAe,OAAO,EAAE,MAAM,UAAU,CAAC;AAErD,mDAAmD;AACnD,MAAM,WAAW,mBAAmB;IAEhC,gJAAgJ;IAChJ,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;CAC7B;AAED,8BAA8B;AAC9B,MAAM,WAAW,aAAa;IAE1B,oJAAoJ;IACpJ,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,WAAW,GAAG,mBAAmB,CAAC,GAAG,SAAS,CAAC;CAChF;AAED,uDAAuD;AACvD,MAAM,MAAM,cAAc,CAAC,MAAM,IAC3B;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;CAAE,CAAC;AAExD,4EAA4E;AAC5E,MAAM,WAAW,cAAc,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK;IAE3D,6MAA6M;IAC7M,QAAQ,CAAC,WAAW,EAAE;QAClB,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,cAAc,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;QAChG,QAAQ,CAAC,KAAK,CAAC,EAAE;YAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;KACnF,CAAC;CACL;AAED,mCAAmC;AACnC,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,cAAc,IAAI,CAAC,SAAS,cAAc,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC;AAErH,uEAAuE;AACvE,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,CAAC,CAAC;AAEnF,iFAAiF;AACjF,MAAM,MAAM,UAAU,CAAC,MAAM,IACvB;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAA;CAAE,GACxD;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEhE,gQAAgQ;AAChQ,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAoBrD;AAWD,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,OAAO,CAoB/E;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,CAAC,SAAS,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CASrJ"}
package/dist/schema.js CHANGED
@@ -1,6 +1,6 @@
1
- /** Turns `FormData` into a plain object. A name that appears once maps to its value; a name that appears more than once maps to an array of its values, in order. */
1
+ /** Turns `FormData` into a plain object with no prototype, so a field named `constructor` or `__proto__` is a field like any other. A name that appears once maps to its value; a name that appears more than once maps to an array of its values, in order. */
2
2
  export function formValues(data) {
3
- const values = {};
3
+ const values = Object.create(null);
4
4
  for (const [name, value] of data) {
5
5
  const current = values[name];
6
6
  if (current === undefined) {
@@ -23,7 +23,7 @@ function fieldName(path) {
23
23
  }
24
24
  /** Groups issues into a problem: path-bearing issues under `fields`, the rest in `detail`. */
25
25
  export function problemFromIssues(issues) {
26
- const fields = {};
26
+ const fields = Object.create(null);
27
27
  const general = [];
28
28
  for (const issue of issues) {
29
29
  const name = fieldName(issue.path);
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAiDA,qKAAqK;AACrK,MAAM,UAAU,UAAU,CAAC,IAAc;IAErC,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAChC,CAAC;QACG,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,OAAO,KAAK,SAAS,EACzB,CAAC;YACG,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QACzB,CAAC;aACI,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAC/B,CAAC;YACG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;aAED,CAAC;YACG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,SAAS,CAAC,IAAkE;IAEjF,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAC3C,CAAC;QACG,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxG,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,iBAAiB,CAAC,MAAoC;IAElE,MAAM,MAAM,GAA6B,EAAE,CAAC;IAC5C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAC1B,CAAC;QACG,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,IAAI,KAAK,SAAS,EACtB,CAAC;YACG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,SAAS;QACb,CAAC;QACD,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,OAAO,GAAY,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,mCAAmC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAqB,EAAE,CAAC;IACzI,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EACtB,CAAC;QACG,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAA2B,MAAS,EAAE,IAAwC;IAE5G,MAAM,KAAK,GAAG,IAAI,YAAY,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACzD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAC3D,CAAC;QACG,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IACzD,CAAC;IACD,OAAO,EAAE,KAAK,EAAG,MAAoC,CAAC,KAAK,EAAE,CAAC;AAClE,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAoDA,gQAAgQ;AAChQ,MAAM,UAAU,UAAU,CAAC,IAAc;IAErC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAe,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAChC,CAAC;QACG,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,OAAO,KAAK,SAAS,EACzB,CAAC;YACG,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QACzB,CAAC;aACI,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAC/B,CAAC;YACG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;aAED,CAAC;YACG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,SAAS,CAAC,IAAkE;IAEjF,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAC3C,CAAC;QACG,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxG,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,iBAAiB,CAAC,MAAoC;IAElE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAA6B,CAAC;IAC/D,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAC1B,CAAC;QACG,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,IAAI,KAAK,SAAS,EACtB,CAAC;YACG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,SAAS;QACb,CAAC;QACD,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,OAAO,GAAY,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,mCAAmC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAqB,EAAE,CAAC;IACzI,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EACtB,CAAC;QACG,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAA2B,MAAS,EAAE,IAAwC;IAE5G,MAAM,KAAK,GAAG,IAAI,YAAY,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACzD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAC3D,CAAC;QACG,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IACzD,CAAC;IACD,OAAO,EAAE,KAAK,EAAG,MAAoC,CAAC,KAAK,EAAE,CAAC;AAClE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerolith/forms",
3
- "version": "0.1.0-alpha.5",
3
+ "version": "0.1.0-alpha.6",
4
4
  "description": "Forms for zerolith: native forms that post FormData and work without JavaScript, enhanced with fetch, pending state, and RFC 9457 problem+json field errors when it runs, with Standard Schema validation shared by client and server",
5
5
  "license": "Apache-2.0",
6
6
  "author": "molexxxx",
@@ -42,9 +42,9 @@
42
42
  "build": "tsc -p tsconfig.build.json"
43
43
  },
44
44
  "peerDependencies": {
45
- "zerolith": "^0.1.0-alpha.5"
45
+ "zerolith": "^0.1.0-alpha.6"
46
46
  },
47
47
  "devDependencies": {
48
- "zerolith": "^0.1.0-alpha.5"
48
+ "zerolith": "^0.1.0-alpha.6"
49
49
  }
50
50
  }
package/src/form.ts CHANGED
@@ -33,7 +33,9 @@ export interface SubmissionOutcome
33
33
  {
34
34
  /** The parsed body: JSON when the response says so, text otherwise, undefined for an empty body. */
35
35
  readonly result: unknown;
36
+ /** The successful response, as `fetch` or a custom `send` returned it; its body has already been read into `result` unless it was redirected. */
36
37
  readonly response: Response;
38
+ /** The form that was submitted, already reset when the `reset` option is set. */
37
39
  readonly element: HTMLFormElement;
38
40
  }
39
41
 
@@ -74,6 +76,7 @@ export interface Field
74
76
  /** The enhanced form. */
75
77
  export interface Form
76
78
  {
79
+ /** The current submission's stage: `pending` while in flight, then `success`, `failure` with a problem, or `error` when it did not complete; `idle` before the first submission and after `reset()`. */
77
80
  readonly status: ReadableSignal<FormStatus>;
78
81
  /** True while a submission is in flight. */
79
82
  readonly pending: ReadableSignal<boolean>;
@@ -93,6 +96,101 @@ export interface Form
93
96
 
94
97
  const EMPTY: readonly string[] = [];
95
98
 
99
+ /** Calls an application callback, reporting what it throws as an uncaught error would be, without changing the form's state. */
100
+ function guarded(callback: () => void): void
101
+ {
102
+ try
103
+ {
104
+ callback();
105
+ }
106
+ catch (thrown)
107
+ {
108
+ if (typeof reportError === "function")
109
+ {
110
+ reportError(thrown);
111
+ }
112
+ else
113
+ {
114
+ queueMicrotask(() =>
115
+ {
116
+ throw thrown;
117
+ });
118
+ }
119
+ }
120
+ }
121
+
122
+ /** The `FormData` implementation probed, and whether its constructor adds the submitter's entry, which browsers before Chrome 112 and Firefox 111 skip. */
123
+ let probed: { implementation: typeof FormData; keepsSubmitter: boolean } | undefined;
124
+
125
+ /** The form's data as the browser submits it, with the submitter's entry added where `new FormData(form, submitter)` leaves it out. */
126
+ function submittedData(element: HTMLFormElement, submitter: HTMLElement | null): FormData
127
+ {
128
+ const data = new FormData(element, submitter ?? undefined);
129
+ if (submitter === null)
130
+ {
131
+ return data;
132
+ }
133
+ if (probed?.implementation !== FormData)
134
+ {
135
+ const form = document.createElement("form");
136
+ const button = document.createElement("button");
137
+ button.name = "probe";
138
+ button.value = "kept";
139
+ form.append(button);
140
+ probed = { implementation: FormData, keepsSubmitter: new FormData(form, button).get("probe") === "kept" };
141
+ }
142
+ const name = submitter.getAttribute("name");
143
+ if (probed.keepsSubmitter || name === null || name === "")
144
+ {
145
+ return data;
146
+ }
147
+ if (submitter instanceof HTMLInputElement && submitter.type === "image")
148
+ {
149
+ data.append(`${name}.x`, "0");
150
+ data.append(`${name}.y`, "0");
151
+ }
152
+ else
153
+ {
154
+ data.append(name, (submitter as HTMLButtonElement | HTMLInputElement).value);
155
+ }
156
+ return data;
157
+ }
158
+
159
+ /**
160
+ * The problem a failed response describes: its body when that is a problem
161
+ * document, or one built from the status. The server is a trust boundary,
162
+ * so `fields` keeps only own keys whose value is a message or a list of
163
+ * messages, a lone message becoming a list of one.
164
+ */
165
+ function problemOf(body: unknown, response: Response): Problem
166
+ {
167
+ if (!isProblem(body))
168
+ {
169
+ return { status: response.status, title: response.statusText === "" ? `HTTP ${response.status}` : response.statusText };
170
+ }
171
+ if (body.fields === undefined)
172
+ {
173
+ return body;
174
+ }
175
+ const fields: Record<string, readonly string[]> = Object.create(null) as Record<string, readonly string[]>;
176
+ for (const [name, value] of Object.entries(body.fields as Record<string, unknown>))
177
+ {
178
+ if (typeof value === "string")
179
+ {
180
+ fields[name] = [value];
181
+ }
182
+ else if (Array.isArray(value))
183
+ {
184
+ const messages = value.filter((message): message is string => typeof message === "string");
185
+ if (messages.length > 0)
186
+ {
187
+ fields[name] = messages;
188
+ }
189
+ }
190
+ }
191
+ return { ...body, fields };
192
+ }
193
+
96
194
  function entries(data: FormData): [string, string][]
97
195
  {
98
196
  return [...data].map(([name, value]) => [name, typeof value === "string" ? value : value.name]);
@@ -113,7 +211,7 @@ async function defaultSend(submission: Submission, headers: HeadersInit | undefi
113
211
  url.search = new URLSearchParams(entries(data)).toString();
114
212
  return fetchImpl(url, init);
115
213
  }
116
- const enctype = submitter?.getAttribute("formenctype") ?? element.enctype;
214
+ const enctype = submitter !== null && submitter.hasAttribute("formenctype") ? (submitter as HTMLButtonElement).formEnctype : element.enctype;
117
215
  if (enctype === "multipart/form-data")
118
216
  {
119
217
  init.body = data;
@@ -167,12 +265,12 @@ export function createForm(options: FormOptions = {}): Form
167
265
  problem.set(found);
168
266
  status.set("failure");
169
267
  });
170
- options.onFailure?.(found, element);
268
+ guarded(() => options.onFailure?.(found, element));
171
269
  };
172
270
 
173
271
  const run = async (element: HTMLFormElement, submitter: HTMLElement | null, method: string, action: URL, current: AbortController): Promise<void> =>
174
272
  {
175
- const data = new FormData(element, submitter ?? undefined);
273
+ const data = submittedData(element, submitter);
176
274
  batch(() =>
177
275
  {
178
276
  status.set("pending");
@@ -198,16 +296,15 @@ export function createForm(options: FormOptions = {}): Form
198
296
  {
199
297
  return;
200
298
  }
201
- const type = response.headers.get("content-type") ?? "";
202
- if (type.includes(PROBLEM_MEDIA_TYPE))
203
- {
204
- fail((await response.json()) as Problem, element);
205
- return;
206
- }
207
- if (!response.ok)
299
+ const type = (response.headers.get("content-type") ?? "").toLowerCase();
300
+ if (type.includes(PROBLEM_MEDIA_TYPE) || !response.ok)
208
301
  {
209
- const body = type.includes("json") ? await response.json().catch(() => undefined) : undefined;
210
- fail(isProblem(body) ? body : { status: response.status, title: response.statusText === "" ? `HTTP ${response.status}` : response.statusText }, element);
302
+ const body: unknown = type.includes("json") ? await response.json().catch(() => undefined) : undefined;
303
+ if (current.signal.aborted)
304
+ {
305
+ return;
306
+ }
307
+ fail(problemOf(body, response), element);
211
308
  return;
212
309
  }
213
310
  const parsed = response.redirected ? undefined : await parseBody(response);
@@ -224,7 +321,7 @@ export function createForm(options: FormOptions = {}): Form
224
321
  {
225
322
  element.reset();
226
323
  }
227
- options.onSuccess?.({ result: parsed, response, element });
324
+ guarded(() => options.onSuccess?.({ result: parsed, response, element }));
228
325
  if (response.redirected)
229
326
  {
230
327
  (options.navigate ?? ((url) => location.assign(url)))(response.url);
@@ -242,7 +339,11 @@ export function createForm(options: FormOptions = {}): Form
242
339
  let field = fields.get(name);
243
340
  if (field === undefined)
244
341
  {
245
- const errors = computed<readonly string[]>(() => problem.get()?.fields?.[name] ?? EMPTY);
342
+ const errors = computed<readonly string[]>(() =>
343
+ {
344
+ const found = problem.get()?.fields;
345
+ return found !== undefined && Object.hasOwn(found, name) ? found[name] ?? EMPTY : EMPTY;
346
+ });
246
347
  field = {
247
348
  errors,
248
349
  error: computed(() => errors.get()[0]),
@@ -256,7 +357,7 @@ export function createForm(options: FormOptions = {}): Form
256
357
  {
257
358
  const element = event.currentTarget as HTMLFormElement;
258
359
  const submitter = event.submitter;
259
- const method = (submitter?.getAttribute("formmethod") ?? element.getAttribute("method") ?? "get").toLowerCase();
360
+ const method = submitter !== null && submitter.hasAttribute("formmethod") ? (submitter as HTMLButtonElement).formMethod : element.method;
260
361
  if (method === "dialog")
261
362
  {
262
363
  return;
@@ -277,7 +378,7 @@ export function createForm(options: FormOptions = {}): Form
277
378
  error.set(thrown);
278
379
  status.set("error");
279
380
  });
280
- options.onError?.(thrown, element);
381
+ guarded(() => options.onError?.(thrown, element));
281
382
  });
282
383
  },
283
384
  reset(): void
package/src/schema.ts CHANGED
@@ -9,12 +9,14 @@ import type { FieldErrors, Problem } from "zerolith";
9
9
  /** One segment of an issue path in object form. */
10
10
  export interface StandardPathSegment
11
11
  {
12
+ /** The key representing the path segment; `problemFromIssues` converts it to a string and joins the path's keys with dots to name the field. */
12
13
  readonly key: PropertyKey;
13
14
  }
14
15
 
15
16
  /** One validation failure. */
16
17
  export interface StandardIssue
17
18
  {
19
+ /** The error message of the issue; `problemFromIssues` lists it under the field its path names, or in `detail` when the path is absent or empty. */
18
20
  readonly message: string;
19
21
  /** The path to the failing value; absent for an issue about the whole input. */
20
22
  readonly path?: ReadonlyArray<PropertyKey | StandardPathSegment> | undefined;
@@ -28,6 +30,7 @@ export type StandardResult<Output> =
28
30
  /** The Standard Schema V1 interface, as published at standardschema.dev. */
29
31
  export interface StandardSchema<Input = unknown, Output = Input>
30
32
  {
33
+ /** The Standard properties: the `version` of the specification, the `vendor` name of the schema library, the optional inferred `types`, and the `validate` function that `validateForm` calls and awaits. */
31
34
  readonly "~standard": {
32
35
  readonly version: 1;
33
36
  readonly vendor: string;
@@ -47,10 +50,10 @@ export type Validation<Output> =
47
50
  | { readonly value: Output; readonly problem?: undefined }
48
51
  | { readonly value?: undefined; readonly problem: Problem };
49
52
 
50
- /** Turns `FormData` into a plain object. A name that appears once maps to its value; a name that appears more than once maps to an array of its values, in order. */
53
+ /** Turns `FormData` into a plain object with no prototype, so a field named `constructor` or `__proto__` is a field like any other. A name that appears once maps to its value; a name that appears more than once maps to an array of its values, in order. */
51
54
  export function formValues(data: FormData): FormValues
52
55
  {
53
- const values: FormValues = {};
56
+ const values = Object.create(null) as FormValues;
54
57
  for (const [name, value] of data)
55
58
  {
56
59
  const current = values[name];
@@ -82,7 +85,7 @@ function fieldName(path: ReadonlyArray<PropertyKey | StandardPathSegment> | unde
82
85
  /** Groups issues into a problem: path-bearing issues under `fields`, the rest in `detail`. */
83
86
  export function problemFromIssues(issues: ReadonlyArray<StandardIssue>): Problem
84
87
  {
85
- const fields: Record<string, string[]> = {};
88
+ const fields = Object.create(null) as Record<string, string[]>;
86
89
  const general: string[] = [];
87
90
  for (const issue of issues)
88
91
  {