@happyvertical/smrt-content 0.43.4 → 0.43.5
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/AGENTS.md +9 -86
- package/agents/content-list.md +869 -0
- package/dist/content-query.d.ts +310 -0
- package/dist/content-query.d.ts.map +1 -0
- package/dist/contents.d.ts +22 -0
- package/dist/contents.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +672 -4
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +22 -2
- package/dist/smrt-knowledge.json +38 -5
- package/dist/svelte/components/ContentList.svelte +941 -30
- package/dist/svelte/components/ContentList.svelte.d.ts +44 -1
- package/dist/svelte/components/ContentList.svelte.d.ts.map +1 -1
- package/dist/svelte/content-list-controller.d.ts +98 -1
- package/dist/svelte/content-list-controller.d.ts.map +1 -1
- package/dist/svelte/content-list-controller.js +290 -19
- package/dist/svelte/content-list-query.d.ts +498 -0
- package/dist/svelte/content-list-query.d.ts.map +1 -0
- package/dist/svelte/content-list-query.js +1294 -0
- package/dist/svelte/content-list-saved-views.d.ts +172 -0
- package/dist/svelte/content-list-saved-views.d.ts.map +1 -0
- package/dist/svelte/content-list-saved-views.js +298 -0
- package/dist/svelte/content-list-url-state.d.ts +211 -0
- package/dist/svelte/content-list-url-state.d.ts.map +1 -0
- package/dist/svelte/content-list-url-state.js +856 -0
- package/dist/svelte/i18n.contribution.d.ts +24 -0
- package/dist/svelte/i18n.contribution.d.ts.map +1 -1
- package/dist/svelte/i18n.contribution.js +26 -0
- package/dist/svelte/index.d.ts +5 -1
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +8 -1
- package/package.json +16 -15
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-backed ContentList queries (#2452).
|
|
3
|
+
*
|
|
4
|
+
* This module is the seam between the ContentList adapter's *view state* and
|
|
5
|
+
* the canonical bounded data-query protocol (#2444) that
|
|
6
|
+
* `POST /api/v1/contents/query` speaks. It owns three things:
|
|
7
|
+
*
|
|
8
|
+
* 1. {@link contentListViewStateToDataQueryRequest} — the translator. It turns
|
|
9
|
+
* search, declarative filters, sorting, and paging into a
|
|
10
|
+
* `DataQueryRequest`, dropping (never throwing on) anything the protocol
|
|
11
|
+
* cannot express and reporting what it dropped.
|
|
12
|
+
* 2. {@link createContentListQueryTransport} — a `fetch` transport for that
|
|
13
|
+
* route, which unwraps the generated `{ action, result }` envelope and turns
|
|
14
|
+
* the `{ error: { … } }` envelope into a thrown, coded error.
|
|
15
|
+
* 3. {@link ContentListQueryBinding} — the structural seam a caller binds a
|
|
16
|
+
* remote query through.
|
|
17
|
+
*
|
|
18
|
+
* ## Three id namespaces
|
|
19
|
+
*
|
|
20
|
+
* A content list value crosses three vocabularies, and they do not agree:
|
|
21
|
+
*
|
|
22
|
+
* | Namespace | Example | Owner |
|
|
23
|
+
* |---|---|---|
|
|
24
|
+
* | adapter column id | `updated` | `content-list-controller.ts` |
|
|
25
|
+
* | `ContentData` client field | `updatedAt` | `mock-smrt-client.ts` |
|
|
26
|
+
* | server data-query field id | `updated_at` | the registered `Content` model |
|
|
27
|
+
*
|
|
28
|
+
* {@link CONTENT_LIST_QUERY_FIELDS} is the single explicit column → server
|
|
29
|
+
* field map, and `content-list-query.test.ts` asserts it against the field ids
|
|
30
|
+
* and declared operators of the real `buildContentQuerySchema()`. A model
|
|
31
|
+
* rename therefore breaks a test rather than production.
|
|
32
|
+
*
|
|
33
|
+
* A column with no server field is not queryable server-side and is dropped
|
|
34
|
+
* from the request: `site` is derived in the browser from `url`/`source`, so
|
|
35
|
+
* there is nothing for the server to filter or sort on.
|
|
36
|
+
*
|
|
37
|
+
* ## Deliberate structural mirror
|
|
38
|
+
*
|
|
39
|
+
* The request/result types here mirror `@happyvertical/smrt-types` (and
|
|
40
|
+
* `@happyvertical/smrt-web`'s browser copy) structurally rather than by import.
|
|
41
|
+
* `@happyvertical/smrt-content` must not pull the browser data runtime into its
|
|
42
|
+
* Svelte barrel: that runtime is code-split precisely so it never loads on
|
|
43
|
+
* public content pages, and a barrel-level import would defeat that. The mirror
|
|
44
|
+
* is exact, so a `RemoteQueryBinding` from
|
|
45
|
+
* `@happyvertical/smrt-svelte/web` satisfies {@link ContentListQueryBinding}
|
|
46
|
+
* without a cast.
|
|
47
|
+
*
|
|
48
|
+
* ## Documented limits
|
|
49
|
+
*
|
|
50
|
+
* - **Offset paging only.** The content query schema declares
|
|
51
|
+
* `supports.cursorPagination: false`.
|
|
52
|
+
* - **`body` is not queryable.** It is a document, not list data.
|
|
53
|
+
* - **`metadata` path filtering is unavailable.** JSON columns have no portable
|
|
54
|
+
* predicate, so the schema declares no filter operators for them.
|
|
55
|
+
* - **No ETag/version slot.** The canonical envelope carries a
|
|
56
|
+
* `queryFingerprint` plus `freshness.asOf` instead.
|
|
57
|
+
* - **Filters compare exactly.** The server compares the stored value. The
|
|
58
|
+
* adapter folds case only for the token columns (`type`, `status`, `state`),
|
|
59
|
+
* because free text has to reach the server as the operator typed it.
|
|
60
|
+
* - **NULL semantics are aligned end to end.** `ne`/`notIn` union `IS NULL`
|
|
61
|
+
* server-side, as `in` already did — unless the caller listed `null`, which
|
|
62
|
+
* inverts the meaning, and a NEGATED ordered comparison unions so that a
|
|
63
|
+
* predicate and its negation stay complements. The ordered comparisons,
|
|
64
|
+
* `isNull`/`isNotNull`, and the `type`/`title` display fallbacks were aligned
|
|
65
|
+
* on the local side instead, by consulting the original `ContentData` rather
|
|
66
|
+
* than the flattened display text. See `agents/content-list.md`.
|
|
67
|
+
*/
|
|
68
|
+
import type { DataTableViewState } from '@happyvertical/smrt-ui/data';
|
|
69
|
+
import type { ContentData } from '../mock-smrt-client.js';
|
|
70
|
+
import type { ContentListColumnId } from './content-list-controller.js';
|
|
71
|
+
import { type ContentListStateDropScope } from './content-list-url-state.js';
|
|
72
|
+
export type ContentListQueryScalar = string | number | boolean | null;
|
|
73
|
+
export type ContentListQueryFilterOperator = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'notIn' | 'like';
|
|
74
|
+
export type ContentListQueryFilter = {
|
|
75
|
+
kind: 'condition';
|
|
76
|
+
field: string;
|
|
77
|
+
operator: ContentListQueryFilterOperator;
|
|
78
|
+
value: ContentListQueryScalar | ContentListQueryScalar[];
|
|
79
|
+
} | {
|
|
80
|
+
kind: 'all' | 'any';
|
|
81
|
+
filters: ContentListQueryFilter[];
|
|
82
|
+
} | {
|
|
83
|
+
kind: 'not';
|
|
84
|
+
filter: ContentListQueryFilter;
|
|
85
|
+
};
|
|
86
|
+
export interface ContentListDataQueryRequest {
|
|
87
|
+
version: 1;
|
|
88
|
+
requestId: string;
|
|
89
|
+
mode: 'rows' | 'count' | 'facets';
|
|
90
|
+
projection?: string[];
|
|
91
|
+
filter?: ContentListQueryFilter;
|
|
92
|
+
sort?: Array<{
|
|
93
|
+
field: string;
|
|
94
|
+
direction: 'asc' | 'desc';
|
|
95
|
+
}>;
|
|
96
|
+
page?: {
|
|
97
|
+
kind: 'offset';
|
|
98
|
+
offset: number;
|
|
99
|
+
limit: number;
|
|
100
|
+
} | {
|
|
101
|
+
kind: 'cursor';
|
|
102
|
+
after?: string;
|
|
103
|
+
limit: number;
|
|
104
|
+
};
|
|
105
|
+
consistency?: {
|
|
106
|
+
mode: 'eventual' | 'snapshot';
|
|
107
|
+
asOf?: string;
|
|
108
|
+
};
|
|
109
|
+
facets?: Array<{
|
|
110
|
+
field: string;
|
|
111
|
+
limit: number;
|
|
112
|
+
}>;
|
|
113
|
+
}
|
|
114
|
+
export type ContentListQueryTotal = {
|
|
115
|
+
kind: 'exact' | 'estimated';
|
|
116
|
+
value: number;
|
|
117
|
+
asOf?: string;
|
|
118
|
+
} | {
|
|
119
|
+
kind: 'unavailable';
|
|
120
|
+
reason?: string;
|
|
121
|
+
};
|
|
122
|
+
export interface ContentListDataQueryResult {
|
|
123
|
+
version: 1;
|
|
124
|
+
requestId: string;
|
|
125
|
+
queryFingerprint: string;
|
|
126
|
+
identityField: string;
|
|
127
|
+
rows: Array<Record<string, unknown>>;
|
|
128
|
+
page?: {
|
|
129
|
+
kind: 'offset';
|
|
130
|
+
limit: number;
|
|
131
|
+
offset: number;
|
|
132
|
+
hasMore: boolean;
|
|
133
|
+
} | {
|
|
134
|
+
kind: 'cursor';
|
|
135
|
+
limit: number;
|
|
136
|
+
nextCursor?: string;
|
|
137
|
+
hasMore: boolean;
|
|
138
|
+
};
|
|
139
|
+
total: ContentListQueryTotal;
|
|
140
|
+
freshness: {
|
|
141
|
+
state: 'fresh' | 'stale' | 'unknown';
|
|
142
|
+
asOf?: string;
|
|
143
|
+
};
|
|
144
|
+
warnings: string[];
|
|
145
|
+
truncated: boolean;
|
|
146
|
+
}
|
|
147
|
+
/** The declared type of a server field, mirroring `DataQueryFieldDescriptor`. */
|
|
148
|
+
export type ContentListQueryFieldType = 'string' | 'number' | 'boolean' | 'datetime' | 'json';
|
|
149
|
+
export interface ContentListQueryField {
|
|
150
|
+
/** Server data-query field id (an SMRT field name). */
|
|
151
|
+
field: string;
|
|
152
|
+
type: ContentListQueryFieldType;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* The single explicit adapter-column → server-field map.
|
|
156
|
+
*
|
|
157
|
+
* `null` means the column has no server field at all and is therefore neither
|
|
158
|
+
* filterable nor sortable server-side. Only `site` is in that state: it is
|
|
159
|
+
* derived from `url`/`source` in the browser, so the server has nothing to
|
|
160
|
+
* order or compare.
|
|
161
|
+
*/
|
|
162
|
+
export declare const CONTENT_LIST_QUERY_FIELDS: Readonly<Record<ContentListColumnId, ContentListQueryField | null>>;
|
|
163
|
+
/** Row identity, matching `CONTENT_QUERY_IDENTITY_FIELD`. */
|
|
164
|
+
export declare const CONTENT_LIST_QUERY_IDENTITY_FIELD = "id";
|
|
165
|
+
/**
|
|
166
|
+
* The schema's `defaultSort`, mirrored so the translator can send it rather
|
|
167
|
+
* than let the normalizer inject it. Cross-asserted against the real schema in
|
|
168
|
+
* `content-list-query.test.ts`.
|
|
169
|
+
*/
|
|
170
|
+
export declare const CONTENT_LIST_QUERY_DEFAULT_SORT: ReadonlyArray<{
|
|
171
|
+
field: string;
|
|
172
|
+
direction: 'asc' | 'desc';
|
|
173
|
+
}>;
|
|
174
|
+
/**
|
|
175
|
+
* The server fields the list actually renders. Kept deliberately narrow: the
|
|
176
|
+
* envelope has a byte budget, and a projection is the cheapest place to keep a
|
|
177
|
+
* page inside it.
|
|
178
|
+
*/
|
|
179
|
+
export declare const CONTENT_LIST_QUERY_PROJECTION: readonly string[];
|
|
180
|
+
/**
|
|
181
|
+
* Every server field the content query schema declares as projectable.
|
|
182
|
+
*
|
|
183
|
+
* A host may override `query.request.projection` with any of these. Naming
|
|
184
|
+
* anything else — a typo, a field that was removed, `body`, `tenantId` — is
|
|
185
|
+
* refused by the normalizer with `DATA_QUERY_PROJECTION_NOT_ALLOWED`, which
|
|
186
|
+
* fails the whole list rather than degrading it, so the translator drops the
|
|
187
|
+
* entry instead. Cross-asserted against `buildContentQuerySchema()`.
|
|
188
|
+
*/
|
|
189
|
+
export declare const CONTENT_LIST_QUERY_PROJECTABLE_FIELDS: readonly string[];
|
|
190
|
+
/** `stringValue()`'s default ceiling, applied to every field id in a request. */
|
|
191
|
+
export declare const CONTENT_LIST_QUERY_MAX_FIELD_ID_LENGTH = 256;
|
|
192
|
+
/**
|
|
193
|
+
* Fields free-text search reaches, mirroring the adapter's searchable columns
|
|
194
|
+
* (`title`, `author`, and the hidden search-only `description`).
|
|
195
|
+
*/
|
|
196
|
+
export declare const CONTENT_LIST_QUERY_SEARCH_FIELDS: readonly string[];
|
|
197
|
+
/**
|
|
198
|
+
* Page size used when the view state carries none. Matches the server's
|
|
199
|
+
* `CONTENT_QUERY_DEFAULT_PAGE_LIMIT`, so a client default and a server default
|
|
200
|
+
* never disagree about how many rows a page holds.
|
|
201
|
+
*/
|
|
202
|
+
export declare const CONTENT_LIST_QUERY_DEFAULT_PAGE_SIZE = 50;
|
|
203
|
+
/** Mirrors `MAX_DATA_QUERY_OFFSET`; a larger offset is refused outright. */
|
|
204
|
+
export declare const CONTENT_LIST_QUERY_MAX_OFFSET = 1000000;
|
|
205
|
+
/**
|
|
206
|
+
* The request normalizer's input caps, mirrored from
|
|
207
|
+
* `@happyvertical/smrt-core`. Exceeding any of them fails the *entire* request
|
|
208
|
+
* with a 400 — which turns the translator's "drop, never fail" contract into an
|
|
209
|
+
* error panel — so each one is enforced client-side and reported as a drop.
|
|
210
|
+
*
|
|
211
|
+
* - `MAX_DATA_QUERY_IN_VALUES` — entries in one `in`/`notIn` list.
|
|
212
|
+
* - `MAX_DATA_QUERY_FILTERS` — total filter nodes, counting every `all`/`any`
|
|
213
|
+
* container as a node exactly the way `normalizeFilter` does.
|
|
214
|
+
* - the scalar cap — characters in any one filter value, wildcards included.
|
|
215
|
+
*/
|
|
216
|
+
export declare const CONTENT_LIST_QUERY_MAX_IN_VALUES = 100;
|
|
217
|
+
export declare const CONTENT_LIST_QUERY_MAX_FILTER_NODES = 50;
|
|
218
|
+
export declare const CONTENT_LIST_QUERY_MAX_VALUE_LENGTH = 4096;
|
|
219
|
+
/** `MAX_DATA_QUERY_REQUEST_BYTES` — the whole serialized request. */
|
|
220
|
+
export declare const CONTENT_LIST_QUERY_MAX_REQUEST_BYTES = 100000;
|
|
221
|
+
/** `MAX_DATA_QUERY_FILTERS` also caps the projection array. */
|
|
222
|
+
export declare const CONTENT_LIST_QUERY_MAX_PROJECTION_FIELDS = 50;
|
|
223
|
+
/** `stringValue(object.requestId, …, 128)` — non-empty, at most 128 chars. */
|
|
224
|
+
export declare const CONTENT_LIST_QUERY_MAX_REQUEST_ID_LENGTH = 128;
|
|
225
|
+
/**
|
|
226
|
+
* `MAX_CONTENT_QUERY_OR_BRANCHES` — the executor's ceiling on the disjunctive
|
|
227
|
+
* normal form it lowers a filter into. Null-safe `ne`/`notIn` cost two branches
|
|
228
|
+
* each and an `all` multiplies, so this one is reachable from a crafted link.
|
|
229
|
+
*/
|
|
230
|
+
export declare const CONTENT_LIST_QUERY_MAX_OR_BRANCHES = 128;
|
|
231
|
+
/**
|
|
232
|
+
* Why one part of a view state could not be expressed as a server query.
|
|
233
|
+
*
|
|
234
|
+
* A superset of `ContentListStateDropReason` so one notice can list restore
|
|
235
|
+
* drops and translation drops together.
|
|
236
|
+
*/
|
|
237
|
+
export type ContentListQueryDropReason =
|
|
238
|
+
/** The column carries no server field (only `site` today). */
|
|
239
|
+
'no-server-field'
|
|
240
|
+
/** The column id is not published by the adapter at all. */
|
|
241
|
+
| 'unknown-column'
|
|
242
|
+
/** The operator has no sound server expression. */
|
|
243
|
+
| 'unsupported-operator'
|
|
244
|
+
/** The value cannot be expressed for the server field's declared type. */
|
|
245
|
+
| 'unsupported-value'
|
|
246
|
+
/** The value was clamped to stay inside a protocol or policy bound. */
|
|
247
|
+
| 'out-of-range'
|
|
248
|
+
/**
|
|
249
|
+
* A bound could not be met without changing which rows come back, and the
|
|
250
|
+
* change is one the operator did not ask for: a filter that had to be left
|
|
251
|
+
* out entirely, or one applied more loosely than requested.
|
|
252
|
+
*
|
|
253
|
+
* Kept distinct from `out-of-range` deliberately. A clamp that NARROWS — an
|
|
254
|
+
* `in` list cut to its first hundred values, a page size reduced — still
|
|
255
|
+
* answers a subset of the question. A filter that widens hands back rows the
|
|
256
|
+
* operator excluded, and calling that "clamped" tells them the opposite of
|
|
257
|
+
* what happened.
|
|
258
|
+
*/
|
|
259
|
+
| 'filter-widened'
|
|
260
|
+
/**
|
|
261
|
+
* The value is live and applied, but outside the vocabulary the toolbar can
|
|
262
|
+
* display. Reported so an operator is never shown an apparently unfiltered
|
|
263
|
+
* toolbar over an empty list.
|
|
264
|
+
*/
|
|
265
|
+
| 'unlisted-value'
|
|
266
|
+
/**
|
|
267
|
+
* A live filter a single-select control cannot express at all — a non-`equals`
|
|
268
|
+
* operator, a list value, or a valueless one. Reported so the toolbar never
|
|
269
|
+
* silently states something other than the query being run.
|
|
270
|
+
*/
|
|
271
|
+
| 'unrepresentable-filter'
|
|
272
|
+
/**
|
|
273
|
+
* An unpaginated view was requested, which a server query cannot express —
|
|
274
|
+
* the endpoint always applies a page limit. Coerced to the page size.
|
|
275
|
+
*/
|
|
276
|
+
| 'unpaginated-unsupported';
|
|
277
|
+
/** One discarded piece of a translated query, reported rather than thrown. */
|
|
278
|
+
export interface ContentListQueryDrop {
|
|
279
|
+
scope: ContentListStateDropScope;
|
|
280
|
+
reason: ContentListQueryDropReason;
|
|
281
|
+
columnId?: string;
|
|
282
|
+
detail?: string;
|
|
283
|
+
}
|
|
284
|
+
export interface ContentListQueryTranslation {
|
|
285
|
+
request: ContentListDataQueryRequest;
|
|
286
|
+
/** Everything the translator refused, for reporting to the operator. */
|
|
287
|
+
dropped: ContentListQueryDrop[];
|
|
288
|
+
/**
|
|
289
|
+
* The 1-based page this request actually reads. Equal to `state.page` unless
|
|
290
|
+
* the offset had to be capped, in which case the caller must move its own
|
|
291
|
+
* page marker here — otherwise the UI labels the answer with a page the
|
|
292
|
+
* server never read, and paging from it is meaningless.
|
|
293
|
+
*/
|
|
294
|
+
effectivePage: number;
|
|
295
|
+
}
|
|
296
|
+
export interface ContentListQueryRequestOptions {
|
|
297
|
+
/** Overrides the projected server fields. */
|
|
298
|
+
projection?: readonly string[];
|
|
299
|
+
/** Page size used when the view state has none. */
|
|
300
|
+
defaultPageSize?: number;
|
|
301
|
+
/** Ceiling on a requested page size. Defaults to `CONTENT_LIST_MAX_PAGE_SIZE`. */
|
|
302
|
+
maxPageSize?: number;
|
|
303
|
+
/** Injectable id factory, for deterministic tests. */
|
|
304
|
+
createRequestId?: () => string;
|
|
305
|
+
}
|
|
306
|
+
export declare function escapeContentListQueryLikeValue(value: string): string;
|
|
307
|
+
/**
|
|
308
|
+
* The one page-size ceiling, resolved from every configured limit.
|
|
309
|
+
*
|
|
310
|
+
* Every candidate narrows: a host that sets a server row budget through
|
|
311
|
+
* `query.request.maxPageSize` must not have it discarded because a looser
|
|
312
|
+
* `urlState.options.maxPageSize` also exists. The schema's `maxPageLimit`
|
|
313
|
+
* (mirrored by `CONTENT_LIST_MAX_PAGE_SIZE`) is always one of the candidates,
|
|
314
|
+
* so the result can never exceed what the endpoint itself enforces.
|
|
315
|
+
*
|
|
316
|
+
* Callers pass this ONE value to the controller seed, the URL sanitizer, the
|
|
317
|
+
* saved-view sanitizer, and the translator, which is what makes it impossible
|
|
318
|
+
* for the page the UI reports and the page the server returns to disagree.
|
|
319
|
+
*/
|
|
320
|
+
export declare function resolveContentListMaxPageSize(...candidates: ReadonlyArray<number | null | undefined>): number;
|
|
321
|
+
/**
|
|
322
|
+
* Translates a content-list view state into a bounded `DataQueryRequest`.
|
|
323
|
+
*
|
|
324
|
+
* Everything unmappable is dropped and reported rather than thrown: a stale
|
|
325
|
+
* saved view or a crafted link must still produce a valid query, minus the
|
|
326
|
+
* parts the server cannot express.
|
|
327
|
+
*
|
|
328
|
+
* Selection and expansion are never translated — they address rendered rows,
|
|
329
|
+
* not a query.
|
|
330
|
+
*/
|
|
331
|
+
export declare function contentListViewStateToDataQueryRequest(state: Partial<DataTableViewState>, options?: ContentListQueryRequestOptions): ContentListQueryTranslation;
|
|
332
|
+
/**
|
|
333
|
+
* A stable identity for the *semantics* of a request.
|
|
334
|
+
*
|
|
335
|
+
* `requestId` is correlation metadata, not query identity, so it is excluded:
|
|
336
|
+
* a component can compare two translations to decide whether the query actually
|
|
337
|
+
* changed rather than re-fetching on every state transition.
|
|
338
|
+
*/
|
|
339
|
+
export declare function contentListQueryRequestKey(request: ContentListDataQueryRequest): string;
|
|
340
|
+
/**
|
|
341
|
+
* Maps one result row onto the `ContentData` shape the presentations render.
|
|
342
|
+
* Unprojected and unknown fields are simply absent; `toContentListRows` already
|
|
343
|
+
* treats a missing field as empty text.
|
|
344
|
+
*/
|
|
345
|
+
export declare function contentFromContentListQueryRow(row: Record<string, unknown>): ContentData;
|
|
346
|
+
/** Maps a whole result page. Order is preserved: the server already sorted. */
|
|
347
|
+
export declare function contentListQueryRowsToContents(rows: ReadonlyArray<Record<string, unknown>>): ContentData[];
|
|
348
|
+
/**
|
|
349
|
+
* The row count to DISPLAY a pager against, or `undefined` when the server
|
|
350
|
+
* could not produce one (`total.kind === 'unavailable'`).
|
|
351
|
+
*
|
|
352
|
+
* Accepts an estimate: an approximate page count is what an estimate is for.
|
|
353
|
+
* Do NOT clamp a page against this — see
|
|
354
|
+
* {@link contentListQueryExactTotal}.
|
|
355
|
+
*/
|
|
356
|
+
export declare function contentListQueryTotalValue(total: ContentListQueryTotal | undefined): number | undefined;
|
|
357
|
+
/**
|
|
358
|
+
* The row count a page may be CLAMPED against, or `undefined` when none exists.
|
|
359
|
+
*
|
|
360
|
+
* Clamping moves the operator, so it may only act on a count that is exactly
|
|
361
|
+
* right. `DataQueryTotal` has three kinds and only one of them qualifies:
|
|
362
|
+
*
|
|
363
|
+
* - `exact` — authoritative. Clamp.
|
|
364
|
+
* - `estimated` — an approximation, and clamping on one can strand a page that
|
|
365
|
+
* really exists: an estimate of 100 rows on a 300-row query hides pages 3
|
|
366
|
+
* onward, and the operator has no way to reach content that is there. The
|
|
367
|
+
* opposite risk, offering a page that turns out to be empty, is visible and
|
|
368
|
+
* self-correcting — they navigate, see nothing, and come back. Refusing to
|
|
369
|
+
* hide reachable rows is the same rule as "truncation only when it narrows".
|
|
370
|
+
* - `unavailable` — the total is UNKNOWN. Not zero, and emphatically not the
|
|
371
|
+
* length of the page in hand, which would send every page above the first
|
|
372
|
+
* back to page one the moment the request settled.
|
|
373
|
+
*/
|
|
374
|
+
export declare function contentListQueryExactTotal(total: ContentListQueryTotal | undefined): number | undefined;
|
|
375
|
+
/** A content query failure carrying the server's machine-readable code. */
|
|
376
|
+
export declare class ContentListQueryError extends Error {
|
|
377
|
+
/** Server error code, for example `DATA_QUERY_FILTER_NOT_ALLOWED`. */
|
|
378
|
+
readonly code: string;
|
|
379
|
+
/** HTTP status, when the failure came from a response. */
|
|
380
|
+
readonly status: number | undefined;
|
|
381
|
+
constructor(message: string, options?: {
|
|
382
|
+
code?: string;
|
|
383
|
+
status?: number;
|
|
384
|
+
cause?: unknown;
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
/** The transport seam `createContentListQueryTransport` implements. */
|
|
388
|
+
export interface ContentListQueryTransport {
|
|
389
|
+
query(request: ContentListDataQueryRequest, options?: {
|
|
390
|
+
signal?: AbortSignal;
|
|
391
|
+
}): Promise<unknown>;
|
|
392
|
+
}
|
|
393
|
+
export interface ContentListQueryTransportOptions {
|
|
394
|
+
/** REST base path. Defaults to `/api/v1`, matching `ContentList`. */
|
|
395
|
+
apiBaseUrl?: string;
|
|
396
|
+
/** Route path under the base. Defaults to `contents/query`. */
|
|
397
|
+
path?: string;
|
|
398
|
+
/** Injectable fetch, for tests and for server-side rendering. */
|
|
399
|
+
fetch?: typeof globalThis.fetch;
|
|
400
|
+
/** Extra headers (an auth header, a tenant hint). Resolved per request. */
|
|
401
|
+
headers?: HeadersInit | (() => HeadersInit | Promise<HeadersInit>);
|
|
402
|
+
/** Forwarded to `fetch`; set `'include'` for cookie-authenticated hosts. */
|
|
403
|
+
credentials?: RequestCredentials;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* A `fetch` transport for `POST /api/v1/contents/query`.
|
|
407
|
+
*
|
|
408
|
+
* The generated route wraps a success as `{ action: 'queryAction', result }`
|
|
409
|
+
* and a refusal as `{ error: { ok: false, status, code, message } }`. This
|
|
410
|
+
* unwraps the first and throws the second as a {@link ContentListQueryError} so
|
|
411
|
+
* a binding's error state carries the server's code rather than a generic
|
|
412
|
+
* "request failed".
|
|
413
|
+
*
|
|
414
|
+
* Non-JSON bodies and HTTP failures are never swallowed, and an `AbortError`
|
|
415
|
+
* propagates untouched so cancellation stays distinguishable from a failure.
|
|
416
|
+
*/
|
|
417
|
+
export declare function createContentListQueryTransport(options?: ContentListQueryTransportOptions): ContentListQueryTransport;
|
|
418
|
+
/**
|
|
419
|
+
* The reactive query binding `ContentList` reads.
|
|
420
|
+
*
|
|
421
|
+
* Structurally satisfied by `RemoteQueryBinding<Record<string, unknown>>` from
|
|
422
|
+
* `@happyvertical/smrt-svelte/web`, which is the intended implementation:
|
|
423
|
+
*
|
|
424
|
+
* ```ts
|
|
425
|
+
* import { remoteQuery } from '@happyvertical/smrt-svelte/web';
|
|
426
|
+
* import { createContentListQueryTransport } from '@happyvertical/smrt-content/svelte';
|
|
427
|
+
*
|
|
428
|
+
* const transport = createContentListQueryTransport({ apiBaseUrl: '/api/v1' });
|
|
429
|
+
* // inside the host component's initialization
|
|
430
|
+
* const query = { bind: () => remoteQuery(collection, transport) };
|
|
431
|
+
* ```
|
|
432
|
+
*
|
|
433
|
+
* It is declared structurally rather than imported so the content Svelte barrel
|
|
434
|
+
* does not drag the browser data runtime onto every page that renders content.
|
|
435
|
+
*/
|
|
436
|
+
export interface ContentListQueryBinding {
|
|
437
|
+
/** The current page of result rows, keyed by server field id. */
|
|
438
|
+
readonly rows: ReadonlyArray<Record<string, unknown>>;
|
|
439
|
+
/** Row count for the whole query, not just this page. */
|
|
440
|
+
readonly total: ContentListQueryTotal | undefined;
|
|
441
|
+
/** True while a first fill is in flight. */
|
|
442
|
+
readonly loading: boolean;
|
|
443
|
+
/** True while a revalidation over already-rendered rows is in flight. */
|
|
444
|
+
readonly refreshing: boolean;
|
|
445
|
+
/**
|
|
446
|
+
* True when the rendered rows are known to be out of date. Part of the seam
|
|
447
|
+
* so a binding satisfies it structurally; the freshness affordance that reads
|
|
448
|
+
* it lands with #2455.
|
|
449
|
+
*/
|
|
450
|
+
readonly stale: boolean;
|
|
451
|
+
/** The last failure, or a falsy value when the query is healthy. */
|
|
452
|
+
readonly error: unknown;
|
|
453
|
+
/**
|
|
454
|
+
* True when the server had to shorten the answer to fit its byte budget.
|
|
455
|
+
* Optional because `RemoteQueryBinding` does not surface it; when a binding
|
|
456
|
+
* omits it, `ContentList` reads it off the result its own `execute` resolved.
|
|
457
|
+
*/
|
|
458
|
+
readonly truncated?: boolean;
|
|
459
|
+
/** Server-side warnings for the same reason, and for shortened values. */
|
|
460
|
+
readonly warnings?: ReadonlyArray<string>;
|
|
461
|
+
execute(request: ContentListDataQueryRequest, options?: {
|
|
462
|
+
signal?: AbortSignal;
|
|
463
|
+
}): Promise<unknown>;
|
|
464
|
+
retry(): Promise<unknown>;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* What the server said about the completeness of an answer.
|
|
468
|
+
*
|
|
469
|
+
* `executeContentQuery` drops trailing rows to stay inside `maxResultBytes` and
|
|
470
|
+
* shortens over-long values, flagging both. That matters to a paging client:
|
|
471
|
+
* the next page is computed from `page * limit`, so rows the server dropped are
|
|
472
|
+
* skipped on the following page too. Reporting it is the difference between a
|
|
473
|
+
* short page and silently missing content.
|
|
474
|
+
*/
|
|
475
|
+
export interface ContentListQueryNotices {
|
|
476
|
+
truncated: boolean;
|
|
477
|
+
warnings: string[];
|
|
478
|
+
}
|
|
479
|
+
/** Reads the completeness flags off a result envelope, defensively. */
|
|
480
|
+
export declare function readContentListQueryNotices(result: unknown): ContentListQueryNotices;
|
|
481
|
+
/**
|
|
482
|
+
* The opt-in server-query prop.
|
|
483
|
+
*
|
|
484
|
+
* `bind` is called exactly once, during `ContentList` initialization, so a
|
|
485
|
+
* binding created by `remoteQuery(...)` registers its teardown in the
|
|
486
|
+
* component's own effect scope and is disposed with it.
|
|
487
|
+
*/
|
|
488
|
+
export interface ContentListQuerySource {
|
|
489
|
+
bind(): ContentListQueryBinding;
|
|
490
|
+
/** Translator options — projection, default page size, page-size ceiling. */
|
|
491
|
+
request?: ContentListQueryRequestOptions;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* A human-readable message for a binding error, for the list's error panel.
|
|
495
|
+
* Returns `null` when there is no error.
|
|
496
|
+
*/
|
|
497
|
+
export declare function contentListQueryErrorMessage(error: unknown): string | null;
|
|
498
|
+
//# sourceMappingURL=content-list-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-list-query.d.ts","sourceRoot":"","sources":["../../src/svelte/content-list-query.ts"],"names":[],"mappings":"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"}
|