@ultimat3/query 27.3.0 → 27.5.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 +7 -7
- package/src/client.ts +3 -2
- package/src/record-answer.ts +15 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultimat3/query",
|
|
3
|
-
"version": "27.
|
|
3
|
+
"version": "27.5.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.
|
|
41
|
-
"@ultimat3/core": "27.
|
|
42
|
-
"@ultimat3/entity": "27.
|
|
43
|
-
"@ultimat3/http": "27.
|
|
44
|
-
"@ultimat3/policy": "27.
|
|
45
|
-
"@ultimat3/schema": "27.
|
|
40
|
+
"@ultimat3/cache": "27.5.0",
|
|
41
|
+
"@ultimat3/core": "27.5.0",
|
|
42
|
+
"@ultimat3/entity": "27.5.0",
|
|
43
|
+
"@ultimat3/http": "27.5.0",
|
|
44
|
+
"@ultimat3/policy": "27.5.0",
|
|
45
|
+
"@ultimat3/schema": "27.5.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
|
|
10
|
-
*
|
|
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
|
package/src/record-answer.ts
CHANGED
|
@@ -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
|
|