@@ -1762,10 +1762,16 @@ function sendMetaItemAbsent(res: any): void {
17621762 * unguarded too.
17631763 *
17641764 * Returns the refusal's sentence, or `undefined` when the token is absent or
1765- * judged. The runtime dispatcher's `/data` domain carries this function
1766- * statement for statement (`versionTokenRefusal` in
1767- * `packages/runtime/src/domains/data.ts`), so the two doors answer every token
1768- * alike; `data-update-expected-version.test.ts` and
1765+ * judged. Both doors build the refusal with the one constructor,
1766+ * `validationFailure(sentence, [])` (`@objectstack/types`), and render it with
1767+ * their own classifier: this file THROWS it into the route's catch
1768+ * (`mapDataError`, the envelope the protocol's `""` refusal gets here), and the
1769+ * dispatcher hands it to `deps.errorFromThrown` and RETURNS the answer (a throw
1770+ * out of `dispatch()` reaches a `createHonoApp` host's catch-all, which reads
1771+ * only `statusCode` and would answer `500`). The runtime dispatcher's `/data`
1772+ * domain carries this function statement for statement (`versionTokenRefusal`
1773+ * in `packages/runtime/src/domains/data.ts`), so the two doors answer every
1774+ * token alike; `data-update-expected-version.test.ts` and
17691775 * `data-delete-expected-version.test.ts` hold them to it.
17701776 */
17711777function versionTokenRefusal(token: unknown, spelling: string): string | undefined {
@@ -9118,20 +9124,15 @@ export class RestServer {
91189124 // [#23492] A token that can never carry a version is
91199125 // refused here, before anything is asked, and every
91209126 // other present token is forwarded below: no token the
9121- // caller sent is read as "no token".
9127+ // caller sent is read as "no token". THROWN as
9128+ // `validationFailure`, so this route's catch answers it
9129+ // through `mapDataError`, in the envelope it already
9130+ // gives the protocol's own refusal of `""`.
91229131 const versionRefusal = versionTokenRefusal(
91239132 expectedVersion,
91249133 bodyVersion != null ? 'The body\'s `expectedVersion`' : 'The `If-Match` header',
91259134 );
9126- if (versionRefusal) {
9127- res.status(400).json({
9128- error: versionRefusal,
9129- code: 'VALIDATION_FAILED',
9130- fields: [],
9131- object: req.params?.object,
9132- });
9133- return;
9134- }
9135+ if (versionRefusal) throw validationFailure(versionRefusal, []);
91359136 if (await this.enforceApiAccess(req, res, p, environmentId, 'update')) return;
91369137 // [#3899] Same gate as create: the wire body is the bare
91379138 // field patch (`expectedVersion` already stripped above),
@@ -9207,22 +9208,14 @@ export class RestServer {
92079208 ? (req.query as any).expectedVersion
92089209 : undefined;
92099210 const expectedVersion = queryVersion ?? ifMatchHeader;
9210- // [#23492] The `PATCH` above's rule: a token that can
9211- // never carry a version is refused, every other present
9212- // token is forwarded.
9211+ // [#23492] The `PATCH` above's rule, thrown the same
9212+ // way: a token that can never carry a version is
9213+ // refused, every other present token is forwarded.
92139214 const versionRefusal = versionTokenRefusal(
92149215 expectedVersion,
92159216 queryVersion != null ? 'The `expectedVersion` query parameter' : 'The `If-Match` header',
92169217 );
9217- if (versionRefusal) {
9218- res.status(400).json({
9219- error: versionRefusal,
9220- code: 'VALIDATION_FAILED',
9221- fields: [],
9222- object: req.params?.object,
9223- });
9224- return;
9225- }
9218+ if (versionRefusal) throw validationFailure(versionRefusal, []);
92269219 if (await this.enforceApiAccess(req, res, p, environmentId, 'delete')) return;
92279220 const deleteRequest: ServerScopedDataRequest<DeleteDataRequest> = {
92289221 object: req.params.object,
0 commit comments