@getquick/content 0.1.0 → 0.3.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/README.md +155 -6
- package/dist/consent-astro.js +1 -1
- package/dist/consent.js +1 -1
- package/dist/dist-D4-CMkrf.js +7047 -0
- package/dist/index.d.ts +20 -4
- package/dist/index.js +24 -5
- package/dist/metadata-content.d.ts +36 -0
- package/dist/metadata-content.js +51 -0
- package/dist/metadata-testing.d.ts +34 -0
- package/dist/metadata-testing.js +142 -0
- package/dist/metadata.d.ts +94 -0
- package/dist/metadata.js +218 -0
- package/dist/server.d.ts +2 -2
- package/dist/server.js +943 -58
- package/dist/{formatting-wOk2jz6J.js → site-language-cBP8SFrS.js} +302 -50
- package/dist/{version-Dn6VLZJO.js → version-D_Ao31D3.js} +1 -1
- package/dist/wordpress-D_HG2rEt.d.ts +606 -0
- package/package.json +13 -1
- package/dist/wordpress-CPL40-vq.d.ts +0 -318
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
import { r as ConsentConfiguration, t as AnalyticsSettings } from "./configuration-C_JGygQI.js";
|
|
2
|
+
import { r as LegalLanguage } from "./legal-C5Xiq59W.js";
|
|
3
|
+
declare namespace content_types_d_exports {
|
|
4
|
+
export { Archives, CmsFailure, CmsFailureReason, CollectionMembership, CollectionTerm, Delivery, DesignPresets, EntryContent, Extended, Found, HomeContent, Missing, PublishedEntry, SiteChrome, Translation, Unavailable, WordPressImage, WordPressMenuItem, WordPressPost, WordPressSettings };
|
|
5
|
+
}
|
|
6
|
+
interface WordPressImage {
|
|
7
|
+
sourceUrl: string;
|
|
8
|
+
altText: string;
|
|
9
|
+
}
|
|
10
|
+
interface WordPressPost {
|
|
11
|
+
id: string;
|
|
12
|
+
title: string;
|
|
13
|
+
excerpt: string;
|
|
14
|
+
content: string;
|
|
15
|
+
uri: string;
|
|
16
|
+
date: string;
|
|
17
|
+
featuredImage: WordPressImage | null;
|
|
18
|
+
hasVideoHero: boolean;
|
|
19
|
+
}
|
|
20
|
+
interface WordPressMenuItem {
|
|
21
|
+
id: string;
|
|
22
|
+
label: string;
|
|
23
|
+
href: string;
|
|
24
|
+
target: string | null;
|
|
25
|
+
children: WordPressMenuItem[];
|
|
26
|
+
}
|
|
27
|
+
interface WordPressSettings {
|
|
28
|
+
title: string;
|
|
29
|
+
description: string;
|
|
30
|
+
}
|
|
31
|
+
interface DesignPresets {
|
|
32
|
+
spacingSizes: Array<{
|
|
33
|
+
slug: string;
|
|
34
|
+
size: string;
|
|
35
|
+
}>;
|
|
36
|
+
colors: Array<{
|
|
37
|
+
slug: string;
|
|
38
|
+
color: string;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A page or post's own content as the Site's extension read it
|
|
43
|
+
* (ContentConfig's `extension`): present only when the Site declares one and
|
|
44
|
+
* its read returned a value for that page or post.
|
|
45
|
+
*/
|
|
46
|
+
interface Extended<X = unknown> {
|
|
47
|
+
extension?: X;
|
|
48
|
+
}
|
|
49
|
+
interface HomeContent<X = unknown> extends DesignPresets {
|
|
50
|
+
/** The front page's WordPress entry (WPGraphQL's global id), if WordPress gave it. */
|
|
51
|
+
nodeId: string | null;
|
|
52
|
+
settings: WordPressSettings;
|
|
53
|
+
page: {
|
|
54
|
+
title: string;
|
|
55
|
+
content: string;
|
|
56
|
+
hasVideoHero: boolean;
|
|
57
|
+
} & Extended<X>;
|
|
58
|
+
/** WordPress failed on the blocks, so this is the page without them. */
|
|
59
|
+
blocksOmitted: boolean;
|
|
60
|
+
}
|
|
61
|
+
/** A term of one of a collection's taxonomies, as an item carries it. */
|
|
62
|
+
interface CollectionTerm {
|
|
63
|
+
slug: string;
|
|
64
|
+
name: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The collection an entry is an item of (ContentConfig's `collections`): its
|
|
68
|
+
* name, and its terms in each of the collection's taxonomies.
|
|
69
|
+
*/
|
|
70
|
+
interface CollectionMembership {
|
|
71
|
+
name: string;
|
|
72
|
+
terms: Record<string, CollectionTerm[]>;
|
|
73
|
+
}
|
|
74
|
+
/** A published translation of an entry: its URI and its language's slug. */
|
|
75
|
+
interface Translation {
|
|
76
|
+
uri: string;
|
|
77
|
+
language: string;
|
|
78
|
+
}
|
|
79
|
+
interface EntryContent<X = unknown> extends WordPressPost, DesignPresets, Extended<X> {
|
|
80
|
+
/** Its language's slug, on a multilingual Site. */
|
|
81
|
+
language?: string;
|
|
82
|
+
/** Its published translations into the site's other languages, on a multilingual Site. */
|
|
83
|
+
translations?: Translation[];
|
|
84
|
+
/** WordPress failed on the blocks, so this is the entry without them. */
|
|
85
|
+
blocksOmitted: boolean;
|
|
86
|
+
/** When WordPress last modified it (ms, the CMS's clock), if it said. */
|
|
87
|
+
modifiedAt: number | null;
|
|
88
|
+
/** The collection it is an item of, when it is one (not a page or post). */
|
|
89
|
+
collection?: CollectionMembership;
|
|
90
|
+
}
|
|
91
|
+
/** A published page or post as WordPress lists it: its id, URI and last modification. */
|
|
92
|
+
interface PublishedEntry {
|
|
93
|
+
/** WPGraphQL's global id, when WordPress gives it. */
|
|
94
|
+
id: string | null;
|
|
95
|
+
uri: string;
|
|
96
|
+
/** When WordPress last modified it (ms, the CMS's clock), if it said. */
|
|
97
|
+
modifiedAt: number | null;
|
|
98
|
+
}
|
|
99
|
+
/** Where each collection's archive is (a path), by its post type. */
|
|
100
|
+
type Archives = Record<string, string>;
|
|
101
|
+
interface SiteChrome {
|
|
102
|
+
menuItems: WordPressMenuItem[];
|
|
103
|
+
siteIcon: WordPressImage | null;
|
|
104
|
+
siteLogo: WordPressImage | null;
|
|
105
|
+
/**
|
|
106
|
+
* The patterns GQ Design's Header & Footer selects for the Site's header and
|
|
107
|
+
* footer (render them with `renderDesignPattern`). Null when the region uses
|
|
108
|
+
* an ordinary template part, or nothing published is selected: the Site
|
|
109
|
+
* keeps its own header or footer then.
|
|
110
|
+
*/
|
|
111
|
+
header: DesignPattern | null;
|
|
112
|
+
footer: DesignPattern | null;
|
|
113
|
+
/**
|
|
114
|
+
* This language's LEGAL-1 Contract from gq-config, on a Site with consent
|
|
115
|
+
* CMS settings enabled (null when gq-config has none for it).
|
|
116
|
+
*/
|
|
117
|
+
legal?: LegalLanguage | null;
|
|
118
|
+
/** gq-config's GA4 settings, on a Site with consent CMS settings enabled. */
|
|
119
|
+
analytics?: AnalyticsSettings;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Why WordPress couldn't deliver: it didn't answer in time (`timeout`), couldn't
|
|
123
|
+
* be reached (`network`), answered with an HTTP error (`http`) or GraphQL errors
|
|
124
|
+
* (`graphql`), or answered with data missing the fields the Frontend requires
|
|
125
|
+
* (`schema`).
|
|
126
|
+
*/
|
|
127
|
+
type CmsFailureReason = "timeout" | "network" | "http" | "graphql" | "schema";
|
|
128
|
+
interface CmsFailure {
|
|
129
|
+
reason: CmsFailureReason;
|
|
130
|
+
message: string;
|
|
131
|
+
httpStatus?: number;
|
|
132
|
+
}
|
|
133
|
+
interface Found<T> {
|
|
134
|
+
kind: "found";
|
|
135
|
+
content: T;
|
|
136
|
+
}
|
|
137
|
+
/** WordPress answered with valid data, and has nothing published there. */
|
|
138
|
+
interface Missing {
|
|
139
|
+
kind: "missing";
|
|
140
|
+
}
|
|
141
|
+
/** The content couldn't be read. This says nothing about whether it exists. */
|
|
142
|
+
interface Unavailable {
|
|
143
|
+
kind: "unavailable";
|
|
144
|
+
failure: CmsFailure;
|
|
145
|
+
}
|
|
146
|
+
type Delivery<T> = Found<T> | Missing | Unavailable;
|
|
147
|
+
//#endregion
|
|
148
|
+
//#region frontend/src/design-patterns.d.ts
|
|
149
|
+
/**
|
|
150
|
+
* A block of a GQ Design pattern, as its layout API shapes it (`blocksJson`):
|
|
151
|
+
* its name, its public attributes (including those a Site's serializer adds,
|
|
152
|
+
* such as `getquick/header-navigation`'s `menuItems`), the HTML WordPress saved
|
|
153
|
+
* for it (null for a dynamic block, such as `core/site-logo`), and its inner
|
|
154
|
+
* blocks, with synced patterns already inlined.
|
|
155
|
+
*/
|
|
156
|
+
interface DesignBlock {
|
|
157
|
+
name: string;
|
|
158
|
+
attributes: Record<string, unknown>;
|
|
159
|
+
content: string | null;
|
|
160
|
+
children: DesignBlock[];
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* The published synced pattern GQ Design's Header & Footer selects for a
|
|
164
|
+
* region of the Site chrome (`designPattern`), as its block tree.
|
|
165
|
+
*/
|
|
166
|
+
interface DesignPattern {
|
|
167
|
+
title: string;
|
|
168
|
+
blocks: DesignBlock[];
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* A complete pattern tree from JSON text or a parsed list. Malformed nodes
|
|
172
|
+
* fail the whole read: dropping one could promote a partial header or footer.
|
|
173
|
+
* PHP's empty attributes (`[]`) normalize to an object.
|
|
174
|
+
*/
|
|
175
|
+
declare function parseDesignBlocks(value: unknown): DesignBlock[] | undefined;
|
|
176
|
+
declare function escapeHtml(value: string): string;
|
|
177
|
+
/** What a block renderer is given besides its block. */
|
|
178
|
+
interface DesignRenderContext {
|
|
179
|
+
/** The block's children, rendered in order by the same renderers (when read). */
|
|
180
|
+
children: string;
|
|
181
|
+
/** The blocks it is inside, outermost first. */
|
|
182
|
+
ancestors: DesignBlock[];
|
|
183
|
+
/** Renders other blocks (a subset of the children, say) by the same renderers. */
|
|
184
|
+
render(this: void, blocks: DesignBlock[]): string;
|
|
185
|
+
/**
|
|
186
|
+
* A link from CMS data as the Frontend serves it: one into this Site (the
|
|
187
|
+
* CMS or the Site origin) becomes its path, another http(s) link stays
|
|
188
|
+
* absolute, and anything else (`javascript:`, say) becomes "#".
|
|
189
|
+
*/
|
|
190
|
+
href(this: void, url: unknown): string;
|
|
191
|
+
/** The home page of the language being served ("/" unless the options say). */
|
|
192
|
+
home: string;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Renders one block as HTML. Its output is not escaped again: escape what the
|
|
196
|
+
* CMS supplied (`escapeHtml`) and pass links through `context.href`.
|
|
197
|
+
*/
|
|
198
|
+
type DesignBlockRenderer = (block: DesignBlock, context: DesignRenderContext) => string;
|
|
199
|
+
interface DesignRenderOptions {
|
|
200
|
+
/**
|
|
201
|
+
* The Site's renderers, by block name: its own blocks (such as
|
|
202
|
+
* `getquick/header-navigation`), and any core block it renders itself.
|
|
203
|
+
* They take precedence over the built-in ones.
|
|
204
|
+
*/
|
|
205
|
+
blocks?: Record<string, DesignBlockRenderer>;
|
|
206
|
+
/** The origins whose links are this Site's: the CMS's and the Site's. */
|
|
207
|
+
internalOrigins?: string[];
|
|
208
|
+
/**
|
|
209
|
+
* Told about each block without children that has neither a renderer nor
|
|
210
|
+
* saved HTML (a dynamic block): it renders nothing.
|
|
211
|
+
*/
|
|
212
|
+
onUnrendered?: (block: DesignBlock) => void;
|
|
213
|
+
/** The home page of the language being served, for home links: "/" by default. */
|
|
214
|
+
home?: string;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* A pattern (or blocks of one) as HTML. Each block is rendered by the Site's
|
|
218
|
+
* renderer for its name, else a built-in one, else as the HTML WordPress saved
|
|
219
|
+
* for it, else, with children, as a WordPress container wrapping them. A block
|
|
220
|
+
* with none of those (a dynamic block, such as a Site's own) renders nothing
|
|
221
|
+
* and is reported to `onUnrendered`. Null renders nothing, so the Site keeps
|
|
222
|
+
* its own header or footer.
|
|
223
|
+
*/
|
|
224
|
+
declare function renderDesignPattern(pattern: DesignPattern | DesignBlock[] | null | undefined, options?: DesignRenderOptions): string;
|
|
225
|
+
/**
|
|
226
|
+
* A menu a Site block carries in its attributes (a flat list of `{ id,
|
|
227
|
+
* parentId, label, url, target }`, as GQ Design's serializer filter documents
|
|
228
|
+
* for `getquick/header-navigation`) as a tree, with each link as the
|
|
229
|
+
* Frontend serves it. Items that aren't menu items are left out; one whose
|
|
230
|
+
* parent isn't listed, or that is in a cycle of parents, is a top-level item.
|
|
231
|
+
*/
|
|
232
|
+
declare function designMenuItems(value: unknown, href?: (url: unknown) => string): WordPressMenuItem[];
|
|
233
|
+
//#endregion
|
|
234
|
+
//#region frontend/src/site-language.d.ts
|
|
235
|
+
/**
|
|
236
|
+
* The `<html lang>` for a WordPress locale: its language and region as a
|
|
237
|
+
* BCP 47 tag (pt_PT_ao90 → pt-PT). WordPress's variants (ao90, formal) aren't
|
|
238
|
+
* BCP 47 subtags, so they are left out; no locale means English.
|
|
239
|
+
*/
|
|
240
|
+
declare function htmlLang(locale: string | undefined): string;
|
|
241
|
+
/** A language the site serves. */
|
|
242
|
+
interface SiteLanguage {
|
|
243
|
+
/** Its WordPress locale (pt_PT_ao90); empty when configuration names none. */
|
|
244
|
+
locale: string;
|
|
245
|
+
/** Polylang's slug, its URL directory: the default language's is its language code. */
|
|
246
|
+
slug: string;
|
|
247
|
+
/** Its GraphQL LanguageCodeEnum value: the slug in upper case (pt-br → PT_BR). */
|
|
248
|
+
code: string;
|
|
249
|
+
/** Its `<html lang>`. */
|
|
250
|
+
lang: string;
|
|
251
|
+
isDefault: boolean;
|
|
252
|
+
/** Its home route: / for the default language, /<slug>/ for the others. */
|
|
253
|
+
home: string;
|
|
254
|
+
}
|
|
255
|
+
interface WordPressLanguages {
|
|
256
|
+
locale?: string;
|
|
257
|
+
languages?: readonly {
|
|
258
|
+
locale: string;
|
|
259
|
+
slug: string;
|
|
260
|
+
}[];
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* configuration's languages: wordpress.locale, the default, served at /, then
|
|
264
|
+
* each of wordpress.languages under its slug. A monolingual Site has one.
|
|
265
|
+
*/
|
|
266
|
+
declare function siteLanguages(wordpress: WordPressLanguages | undefined): SiteLanguage[];
|
|
267
|
+
/**
|
|
268
|
+
* A route's language: the one whose slug is its first segment, else the
|
|
269
|
+
* default language, which has no directory.
|
|
270
|
+
*/
|
|
271
|
+
declare function routeLanguage(route: string, among: readonly SiteLanguage[]): SiteLanguage;
|
|
272
|
+
/**
|
|
273
|
+
* How logs and reports name something a language has: "the front page" for
|
|
274
|
+
* the default language's, "the en front page" for another's.
|
|
275
|
+
*/
|
|
276
|
+
declare function languageSubject(language: SiteLanguage, what: string): string;
|
|
277
|
+
/** Whether a route is a language's home (/, /en/): served as a home, never as an entry. */
|
|
278
|
+
declare function isLanguageHome(route: string, among: readonly SiteLanguage[]): boolean;
|
|
279
|
+
//#endregion
|
|
280
|
+
//#region frontend/src/bindings.d.ts
|
|
281
|
+
interface SqlStatement {
|
|
282
|
+
bind(...values: unknown[]): SqlStatement;
|
|
283
|
+
first<T = Record<string, unknown>>(): Promise<T | null>;
|
|
284
|
+
all<T = Record<string, unknown>>(): Promise<{
|
|
285
|
+
results: T[];
|
|
286
|
+
}>;
|
|
287
|
+
run(): Promise<{
|
|
288
|
+
meta: {
|
|
289
|
+
changes: number;
|
|
290
|
+
};
|
|
291
|
+
}>;
|
|
292
|
+
}
|
|
293
|
+
interface SqlDatabase {
|
|
294
|
+
prepare(query: string): SqlStatement;
|
|
295
|
+
/** Runs the statements in order as one transaction: all of them apply, or none. */
|
|
296
|
+
batch<T = Record<string, unknown>>(statements: SqlStatement[]): Promise<Array<{
|
|
297
|
+
results: T[];
|
|
298
|
+
}>>;
|
|
299
|
+
}
|
|
300
|
+
interface ContentBindings {
|
|
301
|
+
/** The publication store (D1). */
|
|
302
|
+
PUBLICATION_DB?: SqlDatabase;
|
|
303
|
+
/** The trusted refresh's bearer token (a Worker secret). */
|
|
304
|
+
FRONTEND_REFRESH_TOKEN?: string;
|
|
305
|
+
/** The key the CMS signs its publication events with (a Worker secret). */
|
|
306
|
+
PUBLICATION_EVENT_SECRET?: string;
|
|
307
|
+
/** Read-only CMS edge identity; never the automation service or public env. */
|
|
308
|
+
GQ_AUTH_GRAPHQL_CLIENT_ID?: string;
|
|
309
|
+
GQ_AUTH_GRAPHQL_CLIENT_SECRET?: string;
|
|
310
|
+
}
|
|
311
|
+
//#endregion
|
|
312
|
+
//#region frontend/src/page-types.d.ts
|
|
313
|
+
/** The front page as stored: what WordPress delivered, without read details. */
|
|
314
|
+
type HomePublication<X = unknown> = Omit<HomeContent<X>, "blocksOmitted" | "nodeId">;
|
|
315
|
+
/** A published page or post as stored, with the design presets it was read with. */
|
|
316
|
+
type EntryPublication<X = unknown> = Omit<EntryContent<X>, "blocksOmitted" | "modifiedAt">;
|
|
317
|
+
/**
|
|
318
|
+
* A page in another language that a visitor of this one may switch to: its
|
|
319
|
+
* published translation (`translation`), or else that language's home.
|
|
320
|
+
*/
|
|
321
|
+
interface Alternate {
|
|
322
|
+
language: SiteLanguage;
|
|
323
|
+
route: string;
|
|
324
|
+
translation: boolean;
|
|
325
|
+
}
|
|
326
|
+
interface HomePage<X = unknown> {
|
|
327
|
+
home: HomePublication<X>;
|
|
328
|
+
chrome: SiteChrome;
|
|
329
|
+
/** The other languages' homes that are served; none on a monolingual Site. */
|
|
330
|
+
alternates: Alternate[];
|
|
331
|
+
}
|
|
332
|
+
interface EntryPage<X = unknown> {
|
|
333
|
+
entry: EntryPublication<X>;
|
|
334
|
+
chrome: SiteChrome;
|
|
335
|
+
/** Where its readers may switch language; none on a monolingual Site. */
|
|
336
|
+
alternates: Alternate[];
|
|
337
|
+
}
|
|
338
|
+
/** The entry a route served is published at another URI now: the route redirects there. */
|
|
339
|
+
interface Moved {
|
|
340
|
+
kind: "moved";
|
|
341
|
+
uri: string;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Why there is nothing to serve: the CMS failed (live reads, in explicit development),
|
|
345
|
+
* the store couldn't be read (`store`), or the Site has never been refreshed,
|
|
346
|
+
* or holds only state this Frontend can't read (`not-ready`).
|
|
347
|
+
*/
|
|
348
|
+
type DeliveryFailureReason = CmsFailureReason | "store" | "not-ready";
|
|
349
|
+
interface NotServed {
|
|
350
|
+
kind: "unavailable";
|
|
351
|
+
failure: {
|
|
352
|
+
reason: DeliveryFailureReason;
|
|
353
|
+
message: string;
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
type HomeDelivery<X = unknown> = Found<HomePage<X>> | (Missing & {
|
|
357
|
+
chrome: SiteChrome | null;
|
|
358
|
+
}) | NotServed;
|
|
359
|
+
type EntryDelivery<X = unknown> = Found<EntryPage<X>> | (Missing & {
|
|
360
|
+
chrome: SiteChrome | null;
|
|
361
|
+
}) | Moved | NotServed;
|
|
362
|
+
/** Which of a collection's items to list, from the publication store. */
|
|
363
|
+
interface CollectionQuery {
|
|
364
|
+
/** The collection's name, as ContentConfig's `collections` declares it. */
|
|
365
|
+
collection: string;
|
|
366
|
+
/**
|
|
367
|
+
* Only items with one of these terms (slugs) in each of these taxonomies:
|
|
368
|
+
* any slug of a taxonomy, and every taxonomy given.
|
|
369
|
+
*/
|
|
370
|
+
terms?: Record<string, readonly string[]>;
|
|
371
|
+
/** Only items whose title or excerpt contains this text (ignoring case and accents). */
|
|
372
|
+
search?: string;
|
|
373
|
+
/** The page of items, from 1 (the default). */
|
|
374
|
+
page?: number;
|
|
375
|
+
/** Items per page, 1 to 100; 12 by default. */
|
|
376
|
+
perPage?: number;
|
|
377
|
+
/** A multilingual Site's language (its slug); the default language's by default. */
|
|
378
|
+
language?: string;
|
|
379
|
+
}
|
|
380
|
+
/** An item as a collection lists it. */
|
|
381
|
+
interface CollectionItem<X = unknown> {
|
|
382
|
+
uri: string;
|
|
383
|
+
title: string;
|
|
384
|
+
/** When it was published, as WordPress gives it (its date, without a zone). */
|
|
385
|
+
date: string;
|
|
386
|
+
/** When WordPress last modified it (ms, the CMS's clock), if it said. */
|
|
387
|
+
modifiedAt: number | null;
|
|
388
|
+
excerpt: string;
|
|
389
|
+
featuredImage: WordPressImage | null;
|
|
390
|
+
/** Its terms in each of the collection's taxonomies. */
|
|
391
|
+
terms: Record<string, CollectionTerm[]>;
|
|
392
|
+
/** The Site's own content on it (ContentConfig's `extension`), when it has one. */
|
|
393
|
+
extension?: X;
|
|
394
|
+
/** Its language's slug, on a multilingual Site. */
|
|
395
|
+
language?: string;
|
|
396
|
+
}
|
|
397
|
+
/** A page of a collection's items, newest first, and how many there are in all. */
|
|
398
|
+
interface CollectionPage<X = unknown> {
|
|
399
|
+
items: CollectionItem<X>[];
|
|
400
|
+
/** Items matching the query, on every page. */
|
|
401
|
+
total: number;
|
|
402
|
+
page: number;
|
|
403
|
+
/** Pages of items matching the query (0 when none does). */
|
|
404
|
+
pages: number;
|
|
405
|
+
}
|
|
406
|
+
type CollectionListing<X = unknown> = ({
|
|
407
|
+
kind: "found";
|
|
408
|
+
} & CollectionPage<X>) | NotServed;
|
|
409
|
+
/** A term of a collection's taxonomy, and how many of its stored items have it. */
|
|
410
|
+
interface CollectionTermCount extends CollectionTerm {
|
|
411
|
+
count: number;
|
|
412
|
+
}
|
|
413
|
+
type CollectionTermListing = {
|
|
414
|
+
kind: "found";
|
|
415
|
+
terms: CollectionTermCount[];
|
|
416
|
+
} | NotServed;
|
|
417
|
+
//#endregion
|
|
418
|
+
//#region frontend/src/server.d.ts
|
|
419
|
+
interface ContentConfig<X = never> {
|
|
420
|
+
site: string;
|
|
421
|
+
graphqlEndpoint: string;
|
|
422
|
+
cmsOrigin: string;
|
|
423
|
+
wordpress?: WordPressLanguages;
|
|
424
|
+
/**
|
|
425
|
+
* The GQ Design route (Design → Header & Footer) whose header and footer
|
|
426
|
+
* patterns are the Site chrome's: "page" by default; "front-page", "home",
|
|
427
|
+
* "archive", "single-post" or a route a Site plugin defines.
|
|
428
|
+
*/
|
|
429
|
+
designTemplate?: string;
|
|
430
|
+
/** Live delivery without a publication store is opt-in; false by default. */
|
|
431
|
+
development?: boolean;
|
|
432
|
+
isServer: () => boolean;
|
|
433
|
+
bindings: () => ContentBindings | Promise<ContentBindings>;
|
|
434
|
+
fetch?: typeof globalThis.fetch;
|
|
435
|
+
/**
|
|
436
|
+
* CONSENT-1 for this Site. Present, every published body's third-party
|
|
437
|
+
* embeds are rewritten into consent placeholders (unknown hosts blocked) on
|
|
438
|
+
* delivery; absent, bodies are delivered as published.
|
|
439
|
+
*/
|
|
440
|
+
consent?: ContentConsentConfig;
|
|
441
|
+
/**
|
|
442
|
+
* The Site's own content on its pages and posts: GraphQL fields the runtime
|
|
443
|
+
* reads with each of them, and the value the Site makes of them, stored with
|
|
444
|
+
* the publication and served as its `extension`.
|
|
445
|
+
*/
|
|
446
|
+
extension?: ContentExtension<X>;
|
|
447
|
+
/**
|
|
448
|
+
* The content types the runtime stores besides pages and posts, by the
|
|
449
|
+
* Site's name for each (`biblioteca`). Their items are stored, refreshed,
|
|
450
|
+
* withdrawn and reconciled as pages and posts are, served by
|
|
451
|
+
* `publishedEntry`, and listed from the store by `list`.
|
|
452
|
+
*/
|
|
453
|
+
collections?: Record<string, CollectionConfig>;
|
|
454
|
+
}
|
|
455
|
+
/** A content type (a WordPress custom post type) whose items the runtime stores. */
|
|
456
|
+
interface CollectionConfig {
|
|
457
|
+
/** WordPress's name for the post type (register_post_type's), e.g. `biblioteca`. */
|
|
458
|
+
postType: string;
|
|
459
|
+
/** Its WPGraphQL type (its `graphql_single_name`), e.g. `Biblioteca`. */
|
|
460
|
+
graphqlType: string;
|
|
461
|
+
/**
|
|
462
|
+
* The taxonomies (WordPress's names) whose terms are stored with each item,
|
|
463
|
+
* for filtering and showing them. Each must be shown in WPGraphQL.
|
|
464
|
+
*/
|
|
465
|
+
taxonomies?: readonly string[];
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* A Site's own content on its pages and posts, beyond what the runtime reads:
|
|
469
|
+
* fields a plugin adds to WPGraphQL (a block tree, a page setting), read with
|
|
470
|
+
* every front page, page and post, stored with it, and served with it through
|
|
471
|
+
* outages, as the rest of it is.
|
|
472
|
+
*/
|
|
473
|
+
interface ContentExtension<X> {
|
|
474
|
+
/**
|
|
475
|
+
* GraphQL selections added to each kind of node the runtime reads: `page`
|
|
476
|
+
* to front pages and pages, `post` to posts (e.g. `wpBlocksJson`). They are
|
|
477
|
+
* read with the blocks: a read WordPress can only complete without its
|
|
478
|
+
* blocks leaves them out too, and isn't stored. A kind without fields has
|
|
479
|
+
* no extension. `collections`: each collection's items' fields, by its name.
|
|
480
|
+
*/
|
|
481
|
+
fields: {
|
|
482
|
+
page?: string;
|
|
483
|
+
post?: string;
|
|
484
|
+
collections?: Partial<Record<string, string>>;
|
|
485
|
+
};
|
|
486
|
+
/**
|
|
487
|
+
* The Site's value for a node WordPress returned (its fields, the runtime's
|
|
488
|
+
* among them), or undefined when it has none (`extension` is then left
|
|
489
|
+
* out). It is stored as JSON, so it must survive JSON. Throwing fails the
|
|
490
|
+
* read as WordPress answering with the wrong schema: what is stored stays
|
|
491
|
+
* served.
|
|
492
|
+
*/
|
|
493
|
+
read(node: ExtensionNode): X | undefined;
|
|
494
|
+
/**
|
|
495
|
+
* The value read back from the store, or from a read about to be stored
|
|
496
|
+
* (JSON), or undefined when the Site can't serve it. A stored row whose
|
|
497
|
+
* extension doesn't parse is unusable, as any body that doesn't; one stored
|
|
498
|
+
* without an extension (before the Site declared it) still serves, without.
|
|
499
|
+
* Return a valid value as it is: reconciliation compares it with new reads.
|
|
500
|
+
*/
|
|
501
|
+
parse(stored: unknown): X | undefined;
|
|
502
|
+
}
|
|
503
|
+
/** A front page, page, post or collection item as WordPress returned it, for a Site's extension. */
|
|
504
|
+
interface ExtensionNode {
|
|
505
|
+
kind: "page" | "post" | "item";
|
|
506
|
+
/** The collection's name, for an item. */
|
|
507
|
+
collection?: string;
|
|
508
|
+
fields: Readonly<Record<string, unknown>>;
|
|
509
|
+
}
|
|
510
|
+
interface ContentConsentConfig {
|
|
511
|
+
/** The catalog services the Site declares in code (e.g. "youtube", "google_maps"). */
|
|
512
|
+
services?: readonly string[];
|
|
513
|
+
/**
|
|
514
|
+
* Hosts that are the Site itself besides relative URLs: its Frontend and its
|
|
515
|
+
* CMS/media origin. The CMS origin is included by default.
|
|
516
|
+
*/
|
|
517
|
+
firstPartyHosts?: readonly string[];
|
|
518
|
+
/**
|
|
519
|
+
* Read gq-config's Legal Contract and GA4 settings into each language's
|
|
520
|
+
* chrome (requires gq-config with the `getquickLegal` field). Their changes
|
|
521
|
+
* arrive as `legal` and `analytics` settings events.
|
|
522
|
+
*/
|
|
523
|
+
cmsSettings?: boolean;
|
|
524
|
+
}
|
|
525
|
+
declare function createContentRuntime<X = never>(input: ContentConfig<X>): {
|
|
526
|
+
languages: SiteLanguage[];
|
|
527
|
+
defaultLanguage: SiteLanguage;
|
|
528
|
+
multilingual: boolean;
|
|
529
|
+
routeLanguage: (route: string) => SiteLanguage;
|
|
530
|
+
isLanguageHome: (route: string) => boolean;
|
|
531
|
+
wordpress: WordPressClient<X>;
|
|
532
|
+
handleEvent: (request: Request, context?: {
|
|
533
|
+
siteOrigin?: string;
|
|
534
|
+
}) => Promise<Response>;
|
|
535
|
+
handleRefresh: (request: Request, context?: {
|
|
536
|
+
siteOrigin?: string;
|
|
537
|
+
}) => Promise<Response>;
|
|
538
|
+
publishedHome: (siteOrigin?: string, language?: SiteLanguage) => Promise<HomeDelivery<X>>;
|
|
539
|
+
publishedEntry: (path: string, siteOrigin?: string) => Promise<EntryDelivery<X>>;
|
|
540
|
+
/**
|
|
541
|
+
* A page of a collection's items, from the publication store alone (never
|
|
542
|
+
* WordPress), newest first: those with the given terms and text, in the
|
|
543
|
+
* language. Unavailable when the store can't be read, or there is none.
|
|
544
|
+
*/
|
|
545
|
+
list: (query: CollectionQuery) => Promise<CollectionListing<X>>;
|
|
546
|
+
/**
|
|
547
|
+
* The terms of a collection's taxonomy that its stored items have, with how
|
|
548
|
+
* many of them have each, by name: for filters.
|
|
549
|
+
*/
|
|
550
|
+
terms: (name: string, taxonomy: string, options?: {
|
|
551
|
+
language?: string;
|
|
552
|
+
}) => Promise<CollectionTermListing>;
|
|
553
|
+
/**
|
|
554
|
+
* Where a collection's archive is: the Page assigned to it in GETQUICK →
|
|
555
|
+
* Archives, else its post type's own archive. Null when it has neither, or
|
|
556
|
+
* the store can't be read.
|
|
557
|
+
*/
|
|
558
|
+
archiveUri: (collection: string) => Promise<string | null>;
|
|
559
|
+
pageChrome: (siteOrigin?: string) => Promise<SiteChrome | null>;
|
|
560
|
+
/**
|
|
561
|
+
* A chrome pattern as HTML, by the Site's block renderers (see
|
|
562
|
+
* `renderDesignPattern`), with links into the CMS or `siteOrigin` served
|
|
563
|
+
* as this Site's paths.
|
|
564
|
+
*/
|
|
565
|
+
renderDesignPattern: (pattern: DesignPattern | DesignBlock[] | null | undefined, options?: DesignRenderOptions & {
|
|
566
|
+
siteOrigin?: string;
|
|
567
|
+
}) => string;
|
|
568
|
+
/**
|
|
569
|
+
* The design presets every page shares (GQ Design's spacing sizes and
|
|
570
|
+
* colors), for a page that isn't a publication: the stored ones when there
|
|
571
|
+
* is a store, else (in explicit development) a live read. Null when
|
|
572
|
+
* neither has them.
|
|
573
|
+
*/
|
|
574
|
+
designPresets: () => Promise<DesignPresets | null>;
|
|
575
|
+
/**
|
|
576
|
+
* The origins a link into this Site may use: WordPress's, and the
|
|
577
|
+
* Frontend's when given. `menuItemHref` turns links at them into paths.
|
|
578
|
+
*/
|
|
579
|
+
internalOrigins: (siteOrigin?: string) => string[];
|
|
580
|
+
/**
|
|
581
|
+
* The Site's consent configuration for a page served with this chrome:
|
|
582
|
+
* declared services, GA4 when gq-config's toggle is on, and the
|
|
583
|
+
* controller from the Legal Contract. Null when consent isn't configured.
|
|
584
|
+
*/
|
|
585
|
+
consentConfiguration: (chrome?: SiteChrome | null) => ConsentConfiguration | null;
|
|
586
|
+
};
|
|
587
|
+
type ContentRuntime<X = never> = ReturnType<typeof createContentRuntime<X>>;
|
|
588
|
+
//#endregion
|
|
589
|
+
//#region frontend/src/wordpress.d.ts
|
|
590
|
+
interface WordPressClient<X = unknown> {
|
|
591
|
+
getHomeContent(this: void, language?: SiteLanguage): Promise<Delivery<HomeContent<X>>>;
|
|
592
|
+
getEntryByUri(this: void, uri: string): Promise<Delivery<EntryContent<X>>>;
|
|
593
|
+
getDesignPresets(this: void): Promise<Found<DesignPresets> | Unavailable>;
|
|
594
|
+
getPublishedEntries(this: void): Promise<Found<{
|
|
595
|
+
entries: PublishedEntry[];
|
|
596
|
+
requests: number;
|
|
597
|
+
}> | Unavailable>;
|
|
598
|
+
getPublishedRoutes(this: void): Promise<Found<string[]> | Unavailable>;
|
|
599
|
+
getArchives(this: void): Promise<Found<Archives> | Unavailable>;
|
|
600
|
+
getSiteChrome(this: void, siteOrigin?: string, options?: {
|
|
601
|
+
location?: string;
|
|
602
|
+
language?: SiteLanguage;
|
|
603
|
+
}): Promise<Found<SiteChrome> | Unavailable>;
|
|
604
|
+
}
|
|
605
|
+
//#endregion
|
|
606
|
+
export { Found as $, htmlLang as A, designMenuItems as B, Moved as C, SqlStatement as D, SqlDatabase as E, DesignBlock as F, CmsFailure as G, parseDesignBlocks as H, DesignBlockRenderer as I, CollectionTerm as J, CmsFailureReason as K, DesignPattern as L, languageSubject as M, routeLanguage as N, SiteLanguage as O, siteLanguages as P, Extended as Q, DesignRenderContext as R, HomePublication as S, ContentBindings as T, renderDesignPattern as U, escapeHtml as V, Archives as W, DesignPresets as X, Delivery as Y, EntryContent as Z, EntryDelivery as _, ContentExtension as a, Unavailable as at, HomeDelivery as b, createContentRuntime as c, WordPressPost as ct, CollectionListing as d, HomeContent as et, CollectionPage as f, DeliveryFailureReason as g, CollectionTermListing as h, ContentConsentConfig as i, Translation as it, isLanguageHome as j, WordPressLanguages as k, Alternate as l, WordPressSettings as lt, CollectionTermCount as m, CollectionConfig as n, PublishedEntry as nt, ContentRuntime as o, WordPressImage as ot, CollectionQuery as p, CollectionMembership as q, ContentConfig as r, SiteChrome as rt, ExtensionNode as s, WordPressMenuItem as st, WordPressClient as t, Missing as tt, CollectionItem as u, EntryPage as v, NotServed as w, HomePage as x, EntryPublication as y, DesignRenderOptions as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getquick/content",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -45,6 +45,18 @@
|
|
|
45
45
|
"./consent/testing": {
|
|
46
46
|
"types": "./dist/consent-testing.d.ts",
|
|
47
47
|
"import": "./dist/consent-testing.js"
|
|
48
|
+
},
|
|
49
|
+
"./metadata": {
|
|
50
|
+
"types": "./dist/metadata.d.ts",
|
|
51
|
+
"import": "./dist/metadata.js"
|
|
52
|
+
},
|
|
53
|
+
"./metadata/testing": {
|
|
54
|
+
"types": "./dist/metadata-testing.d.ts",
|
|
55
|
+
"import": "./dist/metadata-testing.js"
|
|
56
|
+
},
|
|
57
|
+
"./metadata/content": {
|
|
58
|
+
"types": "./dist/metadata-content.d.ts",
|
|
59
|
+
"import": "./dist/metadata-content.js"
|
|
48
60
|
}
|
|
49
61
|
},
|
|
50
62
|
"publishConfig": {
|