@ultimat3/query 27.2.3 → 27.4.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultimat3/query",
3
- "version": "27.2.3",
3
+ "version": "27.4.0",
4
4
  "description": "The query primitive: a policy-checked read, optionally live, with cursor pagination and an incremental matcher",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -37,11 +37,11 @@
37
37
  "test": "bun test"
38
38
  },
39
39
  "dependencies": {
40
- "@ultimat3/cache": "27.2.3",
41
- "@ultimat3/core": "27.2.3",
42
- "@ultimat3/entity": "27.2.3",
43
- "@ultimat3/http": "27.2.3",
44
- "@ultimat3/policy": "27.2.3",
45
- "@ultimat3/schema": "27.2.3"
40
+ "@ultimat3/cache": "27.4.0",
41
+ "@ultimat3/core": "27.4.0",
42
+ "@ultimat3/entity": "27.4.0",
43
+ "@ultimat3/http": "27.4.0",
44
+ "@ultimat3/policy": "27.4.0",
45
+ "@ultimat3/schema": "27.4.0"
46
46
  }
47
47
  }
package/src/client.ts CHANGED
@@ -6,8 +6,9 @@
6
6
  *
7
7
  * Every read goes through `@ultimat3/core`'s `clientTransport`, the one browser HTTP function —
8
8
  * there is no `fetch` call here, only the injected `fetch` option handed on as `fetchImpl`. Rows
9
- * are handed back as parsed: an instant reaches a caller as the ISO string `JSON.stringify` wrote,
10
- * and a surface that formats one converts at its own edge. A record envelope is unwrapped by the
9
+ * are handed back as parsed, with every value the server answered as a `Date` revived as one — the
10
+ * route names them in `x-ultimate-dates` (`@ultimat3/core`'s `wire-dates.ts`), so a row typed
11
+ * `Date` is a `Date` here, and never an ISO string to convert. A record envelope is unwrapped by the
11
12
  * transport, its rows adopted into the page's store, so the return type is the rows either way.
12
13
  *
13
14
  * `ClientFlight` is a TYPE here and never a value: dedup, retry, the deadline and the fence are
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import type { RecordRows, Row } from '@ultimat3/core';
11
- import { encodeRecordEnvelope, RECORDS_HEADER } from '@ultimat3/core';
11
+ import { DATES_HEADER, encodeRecordEnvelope, RECORDS_HEADER, wireDatePaths } from '@ultimat3/core';
12
12
  import { hasEntityRows, rowsOf } from '@ultimat3/entity';
13
13
  import { jsonResponse } from '@ultimat3/http';
14
14
  import type { StandardSchemaV1 } from '@ultimat3/schema';
@@ -23,25 +23,35 @@ export type RecordAnswer = (answer: readonly object[] | Page<object>) => Respons
23
23
  * `Page` — is the route's, not the declaration's.
24
24
  */
25
25
  export function recordAnswerFor(rows: StandardSchemaV1 | undefined): RecordAnswer {
26
- if (!answersRecords(rows)) return (answer) => jsonResponse(answer);
26
+ if (!answersRecords(rows)) return (answer) => jsonResponse(answer, datesOf(answer));
27
27
  return (answer) => {
28
28
  const records = collect(rows, isPage(answer) ? answer.rows : answer);
29
29
  return jsonResponse(encodeRecordEnvelope(answer, records), {
30
- headers: { [RECORDS_HEADER]: '1' },
30
+ headers: { [RECORDS_HEADER]: '1', ...datesOf(answer).headers },
31
31
  });
32
32
  };
33
33
  }
34
34
 
35
+ /**
36
+ * The instants of a read's DATA — the rows, the `Page` or the one row — by path
37
+ * (`@ultimat3/core`'s `wire-dates.ts`), so the typed client hands back the `Date` the row type
38
+ * promises. A header, never the body: the body and the OpenAPI document stay what they were.
39
+ */
40
+ function datesOf(data: unknown): { readonly headers: Record<string, string> } {
41
+ const dates = wireDatePaths(data);
42
+ return { headers: dates === undefined ? {} : { [DATES_HEADER]: dates } };
43
+ }
44
+
35
45
  /**
36
46
  * The same decision for a `single: true` read, whose answer is ONE row: the row itself, or the
37
47
  * envelope with that row as `data` and its records beside it — the shape an action's record wire
38
48
  * answers for a single output, so the transport unwraps both the same way.
39
49
  */
40
50
  export function recordRowAnswerFor(rows: StandardSchemaV1 | undefined): (row: object) => Response {
41
- if (!answersRecords(rows)) return (row) => jsonResponse(row);
51
+ if (!answersRecords(rows)) return (row) => jsonResponse(row, datesOf(row));
42
52
  return (row) =>
43
53
  jsonResponse(encodeRecordEnvelope(row, collect(rows, [row])), {
44
- headers: { [RECORDS_HEADER]: '1' },
54
+ headers: { [RECORDS_HEADER]: '1', ...datesOf(row).headers },
45
55
  });
46
56
  }
47
57