@obelism/content 0.6.0 → 0.8.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 +43 -5
- package/dist/bridge.d.mts +27 -3
- package/dist/bridge.d.mts.map +1 -1
- package/dist/bridge.d.ts +27 -3
- package/dist/bridge.d.ts.map +1 -1
- package/dist/bridge.global.js +26 -2
- package/dist/bridge.js +203 -3
- package/dist/bridge.mjs +202 -4
- package/dist/index.d.mts +22 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +22 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -6
- package/dist/index.mjs +53 -6
- package/dist/{types-nyvor49r.d.ts → types-2evub96q.d.ts} +14 -2
- package/dist/types-2evub96q.d.ts.map +1 -0
- package/dist/webhooks.d.mts +2 -0
- package/dist/webhooks.d.mts.map +1 -1
- package/dist/webhooks.d.ts +2 -0
- package/dist/webhooks.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/types-nyvor49r.d.ts.map +0 -1
package/dist/bridge.mjs
CHANGED
|
@@ -2,6 +2,167 @@ import { P as PREVIEW_PARAMS, U as UID_ATTRIBUTE, E as ENTRY_ATTRIBUTE } from '.
|
|
|
2
2
|
import { SITE_EDITING_COOKIE, SITE_REQUEST_HEADER } from './site.mjs';
|
|
3
3
|
import { n as normalizeUrl, D as DEFAULT_URL } from './config-c6qktlz6.mjs';
|
|
4
4
|
|
|
5
|
+
// Click rates on the page: in the visual editor, a small label on each block
|
|
6
|
+
// that numbers has clicks for ("24% clicked"), from the editor's `stats`
|
|
7
|
+
// message. The editor's "Show click rates" switch turns it on and off. Plain
|
|
8
|
+
// DOM in a shadow root, like the prompt box, in a fixed layer that follows
|
|
9
|
+
// the blocks as the page scrolls, resizes and re-renders.
|
|
10
|
+
//
|
|
11
|
+
// Sites tag a block's clickable element with `data-numbers-id={block._uid}`
|
|
12
|
+
// and load Obelism numbers' script; the CMS reads the rates from numbers
|
|
13
|
+
// (the CMS's content/docs/guides/visual-editor.mdx, "Click rates").
|
|
14
|
+
const DEFAULT_STATS_LABELS = {
|
|
15
|
+
clicked: '{rate}% clicked',
|
|
16
|
+
title: '{clickers} of {viewers} visitors of its page clicked it in the last 30 days ({clicks} clicks)'
|
|
17
|
+
};
|
|
18
|
+
const fill = (template, values)=>template.replace(/\{(\w+)\}/g, (match, key)=>key in values ? String(values[key]) : match);
|
|
19
|
+
// The same tokens as the prompt box: near-black pill, beige text, the orange
|
|
20
|
+
// accent for the rate.
|
|
21
|
+
const CSS$1 = `
|
|
22
|
+
:host { all: initial; }
|
|
23
|
+
.layer {
|
|
24
|
+
position: fixed; inset: 0; pointer-events: none;
|
|
25
|
+
z-index: 2147483646;
|
|
26
|
+
font: 600 12px/1 'InterVariable', 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
27
|
+
-webkit-font-smoothing: antialiased;
|
|
28
|
+
}
|
|
29
|
+
.badge {
|
|
30
|
+
position: absolute; transform: translateX(-100%);
|
|
31
|
+
display: inline-flex; gap: 6px; align-items: center;
|
|
32
|
+
padding: 6px 10px; white-space: nowrap; cursor: pointer;
|
|
33
|
+
pointer-events: auto; border: 0;
|
|
34
|
+
color: rgb(238 236 233); background: rgb(12 12 12 / .88);
|
|
35
|
+
border-radius: 5em; box-shadow: 0 6px 16px -8px rgb(12 12 12 / .5);
|
|
36
|
+
font: inherit;
|
|
37
|
+
}
|
|
38
|
+
.badge::before {
|
|
39
|
+
content: ''; width: 8px; height: 8px; border-radius: 50%;
|
|
40
|
+
background: rgb(212 130 30);
|
|
41
|
+
}
|
|
42
|
+
.badge[data-place='beside'] { transform: translateY(-50%); }
|
|
43
|
+
.badge[data-place='above'] { transform: translate(-100%, -100%); }
|
|
44
|
+
.badge:focus-visible { outline: 2px solid rgb(212 130 30); outline-offset: 2px; }
|
|
45
|
+
`;
|
|
46
|
+
// Inset from a block's top-right corner, or gap beside a small element.
|
|
47
|
+
const INSET = 8;
|
|
48
|
+
// Below this an element is a button or a link, not a section: its label goes
|
|
49
|
+
// beside it (or above, without room on the right) so it doesn't cover it.
|
|
50
|
+
const SMALL_HEIGHT = 64;
|
|
51
|
+
// Room a label needs beside an element.
|
|
52
|
+
const LABEL_WIDTH = 140;
|
|
53
|
+
// Where a label goes for an element's box: inside the top-right corner of a
|
|
54
|
+
// block, beside a small element, or above one at the right edge.
|
|
55
|
+
const placeLabel = (rect, viewportWidth)=>{
|
|
56
|
+
if (rect.height >= SMALL_HEIGHT) return {
|
|
57
|
+
place: 'inside',
|
|
58
|
+
top: Math.max(rect.top, 0) + INSET,
|
|
59
|
+
left: rect.right - INSET
|
|
60
|
+
};
|
|
61
|
+
if (rect.right + INSET + LABEL_WIDTH <= viewportWidth) return {
|
|
62
|
+
place: 'beside',
|
|
63
|
+
top: rect.top + rect.height / 2,
|
|
64
|
+
left: rect.right + INSET
|
|
65
|
+
};
|
|
66
|
+
return {
|
|
67
|
+
place: 'above',
|
|
68
|
+
top: rect.top - INSET / 2,
|
|
69
|
+
left: rect.right
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
const mountStatsOverlay = (win, { selector, onSelect, labels: labelOverrides })=>{
|
|
73
|
+
const doc = win.document;
|
|
74
|
+
const labels = {
|
|
75
|
+
...DEFAULT_STATS_LABELS,
|
|
76
|
+
...labelOverrides
|
|
77
|
+
};
|
|
78
|
+
const host = doc.createElement('div');
|
|
79
|
+
host.setAttribute('data-obelism-stats', '');
|
|
80
|
+
const shadow = host.attachShadow({
|
|
81
|
+
mode: 'open'
|
|
82
|
+
});
|
|
83
|
+
const style = doc.createElement('style');
|
|
84
|
+
style.textContent = CSS$1;
|
|
85
|
+
const layer = doc.createElement('div');
|
|
86
|
+
layer.className = 'layer';
|
|
87
|
+
shadow.append(style, layer);
|
|
88
|
+
doc.body.appendChild(host);
|
|
89
|
+
let stats = {};
|
|
90
|
+
let visible = false;
|
|
91
|
+
let frame = null;
|
|
92
|
+
const render = ()=>{
|
|
93
|
+
frame = null;
|
|
94
|
+
layer.replaceChildren();
|
|
95
|
+
layer.hidden = !visible;
|
|
96
|
+
if (!visible) return;
|
|
97
|
+
const height = win.innerHeight;
|
|
98
|
+
for (const [uid, block] of Object.entries(stats)){
|
|
99
|
+
const element = doc.querySelector(selector(uid));
|
|
100
|
+
if (!element) continue;
|
|
101
|
+
const rect = element.getBoundingClientRect();
|
|
102
|
+
// Not rendered, or off screen.
|
|
103
|
+
if (!rect.width && !rect.height) continue;
|
|
104
|
+
if (rect.bottom < 0 || rect.top > height) continue;
|
|
105
|
+
const badge = doc.createElement('button');
|
|
106
|
+
badge.type = 'button';
|
|
107
|
+
badge.className = 'badge';
|
|
108
|
+
badge.dataset.uid = uid;
|
|
109
|
+
badge.textContent = fill(labels.clicked, {
|
|
110
|
+
rate: Math.round(block.rate * 100)
|
|
111
|
+
});
|
|
112
|
+
badge.title = fill(labels.title, {
|
|
113
|
+
clickers: block.clickers,
|
|
114
|
+
viewers: block.viewers,
|
|
115
|
+
clicks: block.clicks
|
|
116
|
+
});
|
|
117
|
+
const { place, top, left } = placeLabel(rect, win.innerWidth);
|
|
118
|
+
badge.dataset.place = place;
|
|
119
|
+
badge.style.top = `${top}px`;
|
|
120
|
+
badge.style.left = `${left}px`;
|
|
121
|
+
badge.addEventListener('click', ()=>onSelect(uid));
|
|
122
|
+
layer.appendChild(badge);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
// At most once a frame, however many scroll and mutation events come in.
|
|
126
|
+
const schedule = ()=>{
|
|
127
|
+
if (frame !== null || !visible) return;
|
|
128
|
+
frame = win.requestAnimationFrame(render);
|
|
129
|
+
};
|
|
130
|
+
win.addEventListener('scroll', schedule, {
|
|
131
|
+
capture: true,
|
|
132
|
+
passive: true
|
|
133
|
+
});
|
|
134
|
+
win.addEventListener('resize', schedule);
|
|
135
|
+
// The site re-renders blocks on every `update`; follow them. Our own
|
|
136
|
+
// layer lives in a shadow root, so its changes don't come back here.
|
|
137
|
+
const Observer = win.MutationObserver;
|
|
138
|
+
const observer = typeof Observer === 'function' ? new Observer(schedule) : null;
|
|
139
|
+
observer?.observe(doc.body, {
|
|
140
|
+
childList: true,
|
|
141
|
+
subtree: true
|
|
142
|
+
});
|
|
143
|
+
return {
|
|
144
|
+
update (nextStats, nextVisible) {
|
|
145
|
+
stats = nextStats;
|
|
146
|
+
visible = nextVisible;
|
|
147
|
+
if (frame !== null) {
|
|
148
|
+
win.cancelAnimationFrame?.(frame);
|
|
149
|
+
frame = null;
|
|
150
|
+
}
|
|
151
|
+
render();
|
|
152
|
+
},
|
|
153
|
+
refresh: schedule,
|
|
154
|
+
destroy () {
|
|
155
|
+
if (frame !== null) win.cancelAnimationFrame?.(frame);
|
|
156
|
+
win.removeEventListener('scroll', schedule, {
|
|
157
|
+
capture: true
|
|
158
|
+
});
|
|
159
|
+
win.removeEventListener('resize', schedule);
|
|
160
|
+
observer?.disconnect();
|
|
161
|
+
host.remove();
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
|
|
5
166
|
// The site's half of the visual editor (the CMS's public/bridge.js, as a
|
|
6
167
|
// module). Inside the editor's iframe it outlines blocks, tells the editor
|
|
7
168
|
// which one was clicked, hands the editor's live, unsaved entry to listeners
|
|
@@ -13,7 +174,7 @@ import { n as normalizeUrl, D as DEFAULT_URL } from './config-c6qktlz6.mjs';
|
|
|
13
174
|
// 'select' | 'prompt' | 'undo', uid?, id?, prompt? }
|
|
14
175
|
// - editor → site: { source: 'obelism-content-editor', type: 'connect' |
|
|
15
176
|
// 'update' | 'select' | 'saved' | 'published' | 'features' |
|
|
16
|
-
// 'promptResult' | 'promptState', … }
|
|
177
|
+
// 'promptResult' | 'promptState' | 'stats', … }
|
|
17
178
|
const BRIDGE_SOURCE = 'obelism-content-bridge';
|
|
18
179
|
const EDITOR_SOURCE = 'obelism-content-editor';
|
|
19
180
|
// How long a prompt may take before it counts as failed.
|
|
@@ -29,7 +190,9 @@ const INITIAL_STATE = {
|
|
|
29
190
|
unsaved: false,
|
|
30
191
|
saving: false,
|
|
31
192
|
publishing: false,
|
|
32
|
-
selecting: false
|
|
193
|
+
selecting: false,
|
|
194
|
+
stats: {},
|
|
195
|
+
statsVisible: false
|
|
33
196
|
};
|
|
34
197
|
const createEmitter = ()=>{
|
|
35
198
|
const listeners = {
|
|
@@ -70,6 +233,22 @@ const INERT_METHODS = {
|
|
|
70
233
|
select: ()=>{},
|
|
71
234
|
setSelecting: ()=>{}
|
|
72
235
|
};
|
|
236
|
+
const isCount = (value)=>typeof value === 'number' && Number.isFinite(value) && value >= 0;
|
|
237
|
+
// The editor's `stats`, keeping only well-formed entries.
|
|
238
|
+
const readStats = (value)=>{
|
|
239
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return {};
|
|
240
|
+
const stats = {};
|
|
241
|
+
for (const [uid, block] of Object.entries(value)){
|
|
242
|
+
const { clicks, clickers, viewers, rate } = block ?? {};
|
|
243
|
+
if (isCount(clicks) && isCount(clickers) && isCount(viewers) && isCount(rate)) stats[uid] = {
|
|
244
|
+
clicks,
|
|
245
|
+
clickers,
|
|
246
|
+
viewers,
|
|
247
|
+
rate
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
return stats;
|
|
251
|
+
};
|
|
73
252
|
// The selector of the element marked with a block's uid.
|
|
74
253
|
const blockSelector = (uid)=>`[${UID_ATTRIBUTE}="${uid.replace(/["\\]/g, '\\$&')}"]`;
|
|
75
254
|
// `cmsOrigin` is the only origin messages are accepted from and sent to.
|
|
@@ -198,6 +377,17 @@ const createBridge = (win, cmsOrigin)=>{
|
|
|
198
377
|
uid
|
|
199
378
|
});
|
|
200
379
|
};
|
|
380
|
+
// Mounted with the first rates, so pages without numbers never get it.
|
|
381
|
+
let overlay = null;
|
|
382
|
+
const showStats = ()=>{
|
|
383
|
+
if (!overlay && !Object.keys(state.stats).length) return;
|
|
384
|
+
overlay ??= mountStatsOverlay(win, {
|
|
385
|
+
selector: blockSelector,
|
|
386
|
+
onSelect: (uid)=>bridge.select(uid)
|
|
387
|
+
});
|
|
388
|
+
overlay.update(state.stats, state.statsVisible);
|
|
389
|
+
};
|
|
390
|
+
cleanup.push(()=>overlay?.destroy());
|
|
201
391
|
cleanup.push(()=>{
|
|
202
392
|
for (const id of pending.keys()){
|
|
203
393
|
settle(id)?.reject(new Error('The bridge was destroyed'));
|
|
@@ -218,6 +408,7 @@ const createBridge = (win, cmsOrigin)=>{
|
|
|
218
408
|
});
|
|
219
409
|
// Re-apply the selection to whatever the site rendered.
|
|
220
410
|
win.requestAnimationFrame(()=>highlight(data.selectedUid, false));
|
|
411
|
+
overlay?.refresh();
|
|
221
412
|
} else if (data.type === 'select') {
|
|
222
413
|
highlight(data.uid, true);
|
|
223
414
|
} else if (data.type === 'saved' || data.type === 'published') {
|
|
@@ -227,6 +418,13 @@ const createBridge = (win, cmsOrigin)=>{
|
|
|
227
418
|
setState({
|
|
228
419
|
features: data.features.filter((feature)=>typeof feature === 'string')
|
|
229
420
|
});
|
|
421
|
+
} else if (data.type === 'stats') {
|
|
422
|
+
// An editor from before the switch sends no `visible`: show them.
|
|
423
|
+
setState({
|
|
424
|
+
stats: readStats(data.stats),
|
|
425
|
+
statsVisible: data.visible !== false
|
|
426
|
+
});
|
|
427
|
+
showStats();
|
|
230
428
|
} else if (data.type === 'promptState') {
|
|
231
429
|
setState({
|
|
232
430
|
canUndo: data.canUndo === true
|
|
@@ -1019,7 +1217,7 @@ const createSiteBridge = (win, basePath, { pagePath = (path)=>`/${path}` } = {})
|
|
|
1019
1217
|
locale: locale(),
|
|
1020
1218
|
from: pageEntryId()
|
|
1021
1219
|
});
|
|
1022
|
-
const url = pagePath(created.path);
|
|
1220
|
+
const url = pagePath(created.path, locale() ?? '');
|
|
1023
1221
|
win.location.assign(url);
|
|
1024
1222
|
return {
|
|
1025
1223
|
summary: created.summary,
|
|
@@ -1187,4 +1385,4 @@ const getContentBridge = ({ url, prompt = true, pagePath } = {})=>{
|
|
|
1187
1385
|
return bridge;
|
|
1188
1386
|
};
|
|
1189
1387
|
|
|
1190
|
-
export { DEFAULT_PROMPT_LABELS, INITIAL_STATE, getContentBridge, mountPromptBox, peekContentBridge };
|
|
1388
|
+
export { DEFAULT_PROMPT_LABELS, DEFAULT_STATS_LABELS, INITIAL_STATE, getContentBridge, mountPromptBox, mountStatsOverlay, peekContentBridge };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as RichTextFormat, E as Entry, a as EntryList, M as ModelFile, A as Asset, B as Block, I as ImproveBlock,
|
|
2
|
-
export { C as ContentTypeDefinition,
|
|
1
|
+
import { R as RichTextFormat, E as Entry, a as RedirectList, b as Redirect, c as EntryList, M as ModelFile, A as Asset, B as Block, I as ImproveBlock, d as EntryStub, e as RichTextNode } from './types-2evub96q.js';
|
|
2
|
+
export { C as ContentTypeDefinition, f as ContentTypeKind, g as Environment, F as FieldDefinition, h as FieldType, i as RichTextDocument, j as RichTextMark } from './types-2evub96q.js';
|
|
3
3
|
|
|
4
4
|
type ContentClientOptions = {
|
|
5
5
|
token: string;
|
|
@@ -26,11 +26,29 @@ type EntriesQuery = RequestOptions & {
|
|
|
26
26
|
limit?: number | undefined;
|
|
27
27
|
skip?: number | undefined;
|
|
28
28
|
};
|
|
29
|
+
type RedirectsQuery = {
|
|
30
|
+
locale?: string | undefined;
|
|
31
|
+
limit?: number | undefined;
|
|
32
|
+
skip?: number | undefined;
|
|
33
|
+
init?: RequestInit | undefined;
|
|
34
|
+
};
|
|
35
|
+
type PageLookup<TEntry extends Entry = Entry> = {
|
|
36
|
+
entry: TEntry;
|
|
37
|
+
redirect?: undefined;
|
|
38
|
+
} | {
|
|
39
|
+
entry?: undefined;
|
|
40
|
+
redirect: {
|
|
41
|
+
path: string;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
29
44
|
declare class ContentClient {
|
|
30
45
|
#private;
|
|
31
46
|
readonly url: string;
|
|
32
47
|
constructor({ token, url, locale, depth, richText, timeout, init, fetch: fetchImpl, }: ContentClientOptions);
|
|
33
48
|
getPage: <TEntry extends Entry = Entry>(path: string, options?: RequestOptions) => Promise<TEntry | null>;
|
|
49
|
+
findPage: <TEntry extends Entry = Entry>(path: string, options?: RequestOptions) => Promise<PageLookup<TEntry> | null>;
|
|
50
|
+
getRedirects: ({ locale, limit, skip, init, }?: RedirectsQuery) => Promise<RedirectList>;
|
|
51
|
+
getAllRedirects(query?: Omit<RedirectsQuery, 'skip'>): AsyncGenerator<Redirect, void, undefined>;
|
|
34
52
|
getEntry: <TEntry extends Entry = Entry>(id: string, options?: RequestOptions) => Promise<TEntry | null>;
|
|
35
53
|
getEntries: <TEntry extends Entry = Entry>({ contentType, parentPath, fields, order, limit, skip, ...options }?: EntriesQuery) => Promise<EntryList<TEntry>>;
|
|
36
54
|
getFirstEntry: <TEntry extends Entry = Entry>(query?: Omit<EntriesQuery, "limit" | "skip">) => Promise<TEntry | null>;
|
|
@@ -98,6 +116,6 @@ declare const richTextToHtml: (doc: RichTextNode | null | undefined, { renderEnt
|
|
|
98
116
|
declare const headingLevel: (node: RichTextNode) => 1 | 2 | 3 | 4 | 5 | 6;
|
|
99
117
|
declare const richTextToPlainText: (doc: RichTextNode | null | undefined) => string;
|
|
100
118
|
|
|
101
|
-
export { Asset, Block, ContentApiError, ContentClient, DEFAULT_URL, ENTRY_ATTRIBUTE, Entry, EntryList, EntryStub, IMPROVE_BLOCK, ImproveBlock, ModelFile, PREVIEW_PARAMS, RichTextFormat, RichTextNode, SAFE_HREF, UID_ATTRIBUTE, editable, escapeHtml, headingLevel, imageSrcSet, imageUrl, isImproveBlock, pickImproveVariant, readPreviewParams, richTextToHtml, richTextToPlainText };
|
|
102
|
-
export type { ContentClientOptions, EntriesQuery, ImageTransform, PreviewParams, RequestOptions, RichTextHtmlOptions };
|
|
119
|
+
export { Asset, Block, ContentApiError, ContentClient, DEFAULT_URL, ENTRY_ATTRIBUTE, Entry, EntryList, EntryStub, IMPROVE_BLOCK, ImproveBlock, ModelFile, PREVIEW_PARAMS, Redirect, RedirectList, RichTextFormat, RichTextNode, SAFE_HREF, UID_ATTRIBUTE, editable, escapeHtml, headingLevel, imageSrcSet, imageUrl, isImproveBlock, pickImproveVariant, readPreviewParams, richTextToHtml, richTextToPlainText };
|
|
120
|
+
export type { ContentClientOptions, EntriesQuery, ImageTransform, PageLookup, PreviewParams, RedirectsQuery, RequestOptions, RichTextHtmlOptions };
|
|
103
121
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sources":["../src/client.ts","../src/config.ts","../src/editable.ts","../src/errors.ts","../src/images.ts","../src/improve.ts","../src/preview.ts","../src/richText.ts"],"mappings":";;;AACA,KAAK,oBAAoB;AACzB;AACA;AACA;AACA;AACA,eAAe,cAAc;AAC7B;AACA,WAAW,WAAW;AACtB,mBAAmB,KAAK;AACxB;AACA,KAAK,cAAc;AACnB;AACA;AACA,eAAe,cAAc;AAC7B,WAAW,WAAW;AACtB;AACA,KAAK,gBAAgB;AACrB,KAAK,YAAY,GAAG,cAAc;AAClC;AACA;AACA,aAAa,MAAM,SAAS,gBAAgB,YAAY,gBAAgB;AACxE;AACA;AACA;AACA;AACA,cAAc,aAAa;AAC3B;AACA;AACA,2FAA2F,oBAAoB;AAC/G,6BAA6B,KAAK,GAAG,KAAK,0BAA0B,cAAc,KAAK,OAAO;AAC9F,8BAA8B,KAAK,GAAG,KAAK,wBAAwB,cAAc,KAAK,OAAO;AAC7F,gCAAgC,KAAK,GAAG,KAAK,wEAAwE,YAAY,KAAK,OAAO,CAAC,SAAS;AACvJ,mCAAmC,KAAK,GAAG,KAAK,UAAU,IAAI,CAAC,YAAY,wBAAwB,OAAO;AAC1G,iCAAiC,KAAK,GAAG,KAAK,UAAU,IAAI,CAAC,YAAY,YAAY,cAAc;AACnG,gCAAgC,IAAI,CAAC,cAAc,cAAc,OAAO,CAAC,SAAS;AAClF;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","sources":["../src/client.ts","../src/config.ts","../src/editable.ts","../src/errors.ts","../src/images.ts","../src/improve.ts","../src/preview.ts","../src/richText.ts"],"mappings":";;;AACA,KAAK,oBAAoB;AACzB;AACA;AACA;AACA;AACA,eAAe,cAAc;AAC7B;AACA,WAAW,WAAW;AACtB,mBAAmB,KAAK;AACxB;AACA,KAAK,cAAc;AACnB;AACA;AACA,eAAe,cAAc;AAC7B,WAAW,WAAW;AACtB;AACA,KAAK,gBAAgB;AACrB,KAAK,YAAY,GAAG,cAAc;AAClC;AACA;AACA,aAAa,MAAM,SAAS,gBAAgB,YAAY,gBAAgB;AACxE;AACA;AACA;AACA;AACA,KAAK,cAAc;AACnB;AACA;AACA;AACA,WAAW,WAAW;AACtB;AACA,KAAK,UAAU,gBAAgB,KAAK,GAAG,KAAK;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc,aAAa;AAC3B;AACA;AACA,2FAA2F,oBAAoB;AAC/G,6BAA6B,KAAK,GAAG,KAAK,0BAA0B,cAAc,KAAK,OAAO;AAC9F,8BAA8B,KAAK,GAAG,KAAK,0BAA0B,cAAc,KAAK,OAAO,CAAC,UAAU;AAC1G,oDAAoD,cAAc,KAAK,OAAO,CAAC,YAAY;AAC3F,4BAA4B,IAAI,CAAC,cAAc,YAAY,cAAc,CAAC,QAAQ;AAClF,8BAA8B,KAAK,GAAG,KAAK,wBAAwB,cAAc,KAAK,OAAO;AAC7F,gCAAgC,KAAK,GAAG,KAAK,wEAAwE,YAAY,KAAK,OAAO,CAAC,SAAS;AACvJ,mCAAmC,KAAK,GAAG,KAAK,UAAU,IAAI,CAAC,YAAY,wBAAwB,OAAO;AAC1G,iCAAiC,KAAK,GAAG,KAAK,UAAU,IAAI,CAAC,YAAY,YAAY,cAAc;AACnG,gCAAgC,IAAI,CAAC,cAAc,cAAc,OAAO,CAAC,SAAS;AAClF;;ACtDA,cAAc,WAAW;;ACAzB,cAAc,aAAa;AAC3B,cAAc,eAAe;AAC7B,KAAK,QAAQ;AACb;AACA;AACA;AACA,cAAc,QAAQ;AACtB;AACA;AACA;AACA;AACA,yBAAyB,QAAQ;;ACXjC,cAAc,eAAe,SAAS,KAAK;AAC3C;AACA;AACA;AACA;AACA;;ACJA,KAAK,cAAc;AACnB;AACA;AACA;AACA;AACA;AACA;AACA,cAAc,QAAQ,UAAU,IAAI,CAAC,KAAK,+BAA+B,cAAc;AACvF,cAAc,WAAW,UAAU,IAAI,CAAC,KAAK,iDAAiD,IAAI,CAAC,cAAc;;ACRjH,cAAc,aAAa;AAC3B,cAAc,cAAc,UAAU,KAAK,cAAc,YAAY;AACrE,cAAc,kBAAkB,kBAAkB,KAAK,SAAS,YAAY;;ACH5E,cAAc,cAAc;AAC5B;AACA;AACA;AACA;AACA;AACA,KAAK,aAAa;AAClB;AACA;AACA;AACA;AACA,KAAK,iBAAiB,GAAG,GAAG,GAAG,eAAe,YAAY,MAAM;AAChE,cAAc,iBAAiB,UAAU,iBAAiB,KAAK,aAAa;;ACX5E,cAAc,SAAS,EAAE,MAAM;AAC/B,cAAc,UAAU;AACxB,KAAK,mBAAmB;AACxB,0BAA0B,KAAK,GAAG,SAAS,QAAQ,YAAY;AAC/D,0BAA0B,KAAK,QAAQ,YAAY;AACnD;AACA,cAAc,cAAc,QAAQ,YAAY,oDAAoD,mBAAmB;AACvH,cAAc,YAAY,SAAS,YAAY;AAC/C,cAAc,mBAAmB,QAAQ,YAAY;;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as RichTextFormat, E as Entry, a as EntryList, M as ModelFile, A as Asset, B as Block, I as ImproveBlock,
|
|
2
|
-
export { C as ContentTypeDefinition,
|
|
1
|
+
import { R as RichTextFormat, E as Entry, a as RedirectList, b as Redirect, c as EntryList, M as ModelFile, A as Asset, B as Block, I as ImproveBlock, d as EntryStub, e as RichTextNode } from './types-2evub96q.js';
|
|
2
|
+
export { C as ContentTypeDefinition, f as ContentTypeKind, g as Environment, F as FieldDefinition, h as FieldType, i as RichTextDocument, j as RichTextMark } from './types-2evub96q.js';
|
|
3
3
|
|
|
4
4
|
type ContentClientOptions = {
|
|
5
5
|
token: string;
|
|
@@ -26,11 +26,29 @@ type EntriesQuery = RequestOptions & {
|
|
|
26
26
|
limit?: number | undefined;
|
|
27
27
|
skip?: number | undefined;
|
|
28
28
|
};
|
|
29
|
+
type RedirectsQuery = {
|
|
30
|
+
locale?: string | undefined;
|
|
31
|
+
limit?: number | undefined;
|
|
32
|
+
skip?: number | undefined;
|
|
33
|
+
init?: RequestInit | undefined;
|
|
34
|
+
};
|
|
35
|
+
type PageLookup<TEntry extends Entry = Entry> = {
|
|
36
|
+
entry: TEntry;
|
|
37
|
+
redirect?: undefined;
|
|
38
|
+
} | {
|
|
39
|
+
entry?: undefined;
|
|
40
|
+
redirect: {
|
|
41
|
+
path: string;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
29
44
|
declare class ContentClient {
|
|
30
45
|
#private;
|
|
31
46
|
readonly url: string;
|
|
32
47
|
constructor({ token, url, locale, depth, richText, timeout, init, fetch: fetchImpl, }: ContentClientOptions);
|
|
33
48
|
getPage: <TEntry extends Entry = Entry>(path: string, options?: RequestOptions) => Promise<TEntry | null>;
|
|
49
|
+
findPage: <TEntry extends Entry = Entry>(path: string, options?: RequestOptions) => Promise<PageLookup<TEntry> | null>;
|
|
50
|
+
getRedirects: ({ locale, limit, skip, init, }?: RedirectsQuery) => Promise<RedirectList>;
|
|
51
|
+
getAllRedirects(query?: Omit<RedirectsQuery, 'skip'>): AsyncGenerator<Redirect, void, undefined>;
|
|
34
52
|
getEntry: <TEntry extends Entry = Entry>(id: string, options?: RequestOptions) => Promise<TEntry | null>;
|
|
35
53
|
getEntries: <TEntry extends Entry = Entry>({ contentType, parentPath, fields, order, limit, skip, ...options }?: EntriesQuery) => Promise<EntryList<TEntry>>;
|
|
36
54
|
getFirstEntry: <TEntry extends Entry = Entry>(query?: Omit<EntriesQuery, "limit" | "skip">) => Promise<TEntry | null>;
|
|
@@ -98,6 +116,6 @@ declare const richTextToHtml: (doc: RichTextNode | null | undefined, { renderEnt
|
|
|
98
116
|
declare const headingLevel: (node: RichTextNode) => 1 | 2 | 3 | 4 | 5 | 6;
|
|
99
117
|
declare const richTextToPlainText: (doc: RichTextNode | null | undefined) => string;
|
|
100
118
|
|
|
101
|
-
export { Asset, Block, ContentApiError, ContentClient, DEFAULT_URL, ENTRY_ATTRIBUTE, Entry, EntryList, EntryStub, IMPROVE_BLOCK, ImproveBlock, ModelFile, PREVIEW_PARAMS, RichTextFormat, RichTextNode, SAFE_HREF, UID_ATTRIBUTE, editable, escapeHtml, headingLevel, imageSrcSet, imageUrl, isImproveBlock, pickImproveVariant, readPreviewParams, richTextToHtml, richTextToPlainText };
|
|
102
|
-
export type { ContentClientOptions, EntriesQuery, ImageTransform, PreviewParams, RequestOptions, RichTextHtmlOptions };
|
|
119
|
+
export { Asset, Block, ContentApiError, ContentClient, DEFAULT_URL, ENTRY_ATTRIBUTE, Entry, EntryList, EntryStub, IMPROVE_BLOCK, ImproveBlock, ModelFile, PREVIEW_PARAMS, Redirect, RedirectList, RichTextFormat, RichTextNode, SAFE_HREF, UID_ATTRIBUTE, editable, escapeHtml, headingLevel, imageSrcSet, imageUrl, isImproveBlock, pickImproveVariant, readPreviewParams, richTextToHtml, richTextToPlainText };
|
|
120
|
+
export type { ContentClientOptions, EntriesQuery, ImageTransform, PageLookup, PreviewParams, RedirectsQuery, RequestOptions, RichTextHtmlOptions };
|
|
103
121
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sources":["../src/client.ts","../src/config.ts","../src/editable.ts","../src/errors.ts","../src/images.ts","../src/improve.ts","../src/preview.ts","../src/richText.ts"],"mappings":";;;AACA,KAAK,oBAAoB;AACzB;AACA;AACA;AACA;AACA,eAAe,cAAc;AAC7B;AACA,WAAW,WAAW;AACtB,mBAAmB,KAAK;AACxB;AACA,KAAK,cAAc;AACnB;AACA;AACA,eAAe,cAAc;AAC7B,WAAW,WAAW;AACtB;AACA,KAAK,gBAAgB;AACrB,KAAK,YAAY,GAAG,cAAc;AAClC;AACA;AACA,aAAa,MAAM,SAAS,gBAAgB,YAAY,gBAAgB;AACxE;AACA;AACA;AACA;AACA,cAAc,aAAa;AAC3B;AACA;AACA,2FAA2F,oBAAoB;AAC/G,6BAA6B,KAAK,GAAG,KAAK,0BAA0B,cAAc,KAAK,OAAO;AAC9F,8BAA8B,KAAK,GAAG,KAAK,wBAAwB,cAAc,KAAK,OAAO;AAC7F,gCAAgC,KAAK,GAAG,KAAK,wEAAwE,YAAY,KAAK,OAAO,CAAC,SAAS;AACvJ,mCAAmC,KAAK,GAAG,KAAK,UAAU,IAAI,CAAC,YAAY,wBAAwB,OAAO;AAC1G,iCAAiC,KAAK,GAAG,KAAK,UAAU,IAAI,CAAC,YAAY,YAAY,cAAc;AACnG,gCAAgC,IAAI,CAAC,cAAc,cAAc,OAAO,CAAC,SAAS;AAClF;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sources":["../src/client.ts","../src/config.ts","../src/editable.ts","../src/errors.ts","../src/images.ts","../src/improve.ts","../src/preview.ts","../src/richText.ts"],"mappings":";;;AACA,KAAK,oBAAoB;AACzB;AACA;AACA;AACA;AACA,eAAe,cAAc;AAC7B;AACA,WAAW,WAAW;AACtB,mBAAmB,KAAK;AACxB;AACA,KAAK,cAAc;AACnB;AACA;AACA,eAAe,cAAc;AAC7B,WAAW,WAAW;AACtB;AACA,KAAK,gBAAgB;AACrB,KAAK,YAAY,GAAG,cAAc;AAClC;AACA;AACA,aAAa,MAAM,SAAS,gBAAgB,YAAY,gBAAgB;AACxE;AACA;AACA;AACA;AACA,KAAK,cAAc;AACnB;AACA;AACA;AACA,WAAW,WAAW;AACtB;AACA,KAAK,UAAU,gBAAgB,KAAK,GAAG,KAAK;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc,aAAa;AAC3B;AACA;AACA,2FAA2F,oBAAoB;AAC/G,6BAA6B,KAAK,GAAG,KAAK,0BAA0B,cAAc,KAAK,OAAO;AAC9F,8BAA8B,KAAK,GAAG,KAAK,0BAA0B,cAAc,KAAK,OAAO,CAAC,UAAU;AAC1G,oDAAoD,cAAc,KAAK,OAAO,CAAC,YAAY;AAC3F,4BAA4B,IAAI,CAAC,cAAc,YAAY,cAAc,CAAC,QAAQ;AAClF,8BAA8B,KAAK,GAAG,KAAK,wBAAwB,cAAc,KAAK,OAAO;AAC7F,gCAAgC,KAAK,GAAG,KAAK,wEAAwE,YAAY,KAAK,OAAO,CAAC,SAAS;AACvJ,mCAAmC,KAAK,GAAG,KAAK,UAAU,IAAI,CAAC,YAAY,wBAAwB,OAAO;AAC1G,iCAAiC,KAAK,GAAG,KAAK,UAAU,IAAI,CAAC,YAAY,YAAY,cAAc;AACnG,gCAAgC,IAAI,CAAC,cAAc,cAAc,OAAO,CAAC,SAAS;AAClF;;ACtDA,cAAc,WAAW;;ACAzB,cAAc,aAAa;AAC3B,cAAc,eAAe;AAC7B,KAAK,QAAQ;AACb;AACA;AACA;AACA,cAAc,QAAQ;AACtB;AACA;AACA;AACA;AACA,yBAAyB,QAAQ;;ACXjC,cAAc,eAAe,SAAS,KAAK;AAC3C;AACA;AACA;AACA;AACA;;ACJA,KAAK,cAAc;AACnB;AACA;AACA;AACA;AACA;AACA;AACA,cAAc,QAAQ,UAAU,IAAI,CAAC,KAAK,+BAA+B,cAAc;AACvF,cAAc,WAAW,UAAU,IAAI,CAAC,KAAK,iDAAiD,IAAI,CAAC,cAAc;;ACRjH,cAAc,aAAa;AAC3B,cAAc,cAAc,UAAU,KAAK,cAAc,YAAY;AACrE,cAAc,kBAAkB,kBAAkB,KAAK,SAAS,YAAY;;ACH5E,cAAc,cAAc;AAC5B;AACA;AACA;AACA;AACA;AACA,KAAK,aAAa;AAClB;AACA;AACA;AACA;AACA,KAAK,iBAAiB,GAAG,GAAG,GAAG,eAAe,YAAY,MAAM;AAChE,cAAc,iBAAiB,UAAU,iBAAiB,KAAK,aAAa;;ACX5E,cAAc,SAAS,EAAE,MAAM;AAC/B,cAAc,UAAU;AACxB,KAAK,mBAAmB;AACxB,0BAA0B,KAAK,GAAG,SAAS,QAAQ,YAAY;AAC/D,0BAA0B,KAAK,QAAQ,YAAY;AACnD;AACA,cAAc,cAAc,QAAQ,YAAY,oDAAoD,mBAAmB;AACvH,cAAc,YAAY,SAAS,YAAY;AAC/C,cAAc,mBAAmB,QAAQ,YAAY;;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -42,17 +42,45 @@ class ContentClient {
|
|
|
42
42
|
#fetch;
|
|
43
43
|
constructor({ token, url, locale, depth, richText, timeout, init, fetch: fetchImpl }){
|
|
44
44
|
// The page at a path (`blog/hello`), or null when there is none. A site's
|
|
45
|
-
// catch-all route asks for this.
|
|
46
|
-
|
|
45
|
+
// catch-all route asks for this. The path is looked up in `locale`'s
|
|
46
|
+
// paths (the default locale's when left out or `*`): pages can have a
|
|
47
|
+
// slug per locale.
|
|
48
|
+
this.getPage = async (path, options = {})=>(await this.findPage(path, options))?.entry ?? null;
|
|
49
|
+
// Like getPage, but a path a page moved away from answers where it is
|
|
50
|
+
// now, so the site can send a 301 there instead of a 404.
|
|
51
|
+
//
|
|
52
|
+
// const found = await content.findPage(path, { locale })
|
|
53
|
+
// if (found?.redirect) return redirect(`/${locale}/${found.redirect.path}`, 301)
|
|
54
|
+
// if (!found) return notFound()
|
|
55
|
+
this.findPage = async (path, options = {})=>{
|
|
47
56
|
const trimmed = trimSlashes(path);
|
|
48
57
|
if (!trimmed) throw new Error('getPage needs a path');
|
|
49
58
|
const result = await this.#request('/pages', {
|
|
50
59
|
path: trimmed
|
|
51
60
|
}, options, {
|
|
52
|
-
notFound:
|
|
61
|
+
notFound: 'body'
|
|
53
62
|
});
|
|
54
|
-
|
|
63
|
+
if (result && 'entry' in result) return {
|
|
64
|
+
entry: result.entry
|
|
65
|
+
};
|
|
66
|
+
const to = result?.redirect?.path;
|
|
67
|
+
return typeof to === 'string' ? {
|
|
68
|
+
redirect: {
|
|
69
|
+
path: to
|
|
70
|
+
}
|
|
71
|
+
} : null;
|
|
55
72
|
};
|
|
73
|
+
// One page of redirects: every path a page moved away from, per locale,
|
|
74
|
+
// with where it is now. For redirect rules built ahead of time.
|
|
75
|
+
this.getRedirects = ({ locale, limit, skip, init } = {})=>this.#request('/redirects', {
|
|
76
|
+
limit,
|
|
77
|
+
skip
|
|
78
|
+
}, {
|
|
79
|
+
locale,
|
|
80
|
+
init
|
|
81
|
+
}, {
|
|
82
|
+
defaults: false
|
|
83
|
+
});
|
|
56
84
|
// An entry by id, or null when there is none (or it isn't published, for a
|
|
57
85
|
// delivery token).
|
|
58
86
|
this.getEntry = async (id, options = {})=>{
|
|
@@ -93,6 +121,21 @@ class ContentClient {
|
|
|
93
121
|
this.#init = init;
|
|
94
122
|
this.#fetch = fetchImpl ?? ((...args)=>fetch(...args));
|
|
95
123
|
}
|
|
124
|
+
// Every redirect, fetching pages of `limit` (default 1000) as it goes.
|
|
125
|
+
async *getAllRedirects(query = {}) {
|
|
126
|
+
const limit = query.limit ?? 1000;
|
|
127
|
+
let skip = 0;
|
|
128
|
+
while(true){
|
|
129
|
+
const page = await this.getRedirects({
|
|
130
|
+
...query,
|
|
131
|
+
limit,
|
|
132
|
+
skip
|
|
133
|
+
});
|
|
134
|
+
yield* page.items;
|
|
135
|
+
skip += page.items.length;
|
|
136
|
+
if (page.items.length === 0 || skip >= page.total) return;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
96
139
|
// Every entry matching the query, fetching pages of `limit` (default 100)
|
|
97
140
|
// as it goes.
|
|
98
141
|
//
|
|
@@ -111,7 +154,8 @@ class ContentClient {
|
|
|
111
154
|
if (page.items.length === 0 || skip >= page.total) return;
|
|
112
155
|
}
|
|
113
156
|
}
|
|
114
|
-
//
|
|
157
|
+
// For a 404, null when `notFound` is set, or the body as is for 'body';
|
|
158
|
+
// throws ContentApiError otherwise.
|
|
115
159
|
async #request(path, query, { init, ...options }, { notFound = false, defaults = true } = {}) {
|
|
116
160
|
// Checked here rather than in the constructor, so a module creating a
|
|
117
161
|
// client still loads (and a build still runs) without the variable.
|
|
@@ -149,7 +193,7 @@ class ContentClient {
|
|
|
149
193
|
timeout
|
|
150
194
|
]) : timeout
|
|
151
195
|
});
|
|
152
|
-
if (notFound && response.status === 404) return null;
|
|
196
|
+
if (notFound === true && response.status === 404) return null;
|
|
153
197
|
const text = await response.text();
|
|
154
198
|
let body = text;
|
|
155
199
|
try {
|
|
@@ -157,6 +201,9 @@ class ContentClient {
|
|
|
157
201
|
} catch {
|
|
158
202
|
// Not JSON: keep the text for the error.
|
|
159
203
|
}
|
|
204
|
+
if (notFound === 'body' && response.status === 404) {
|
|
205
|
+
return typeof body === 'object' && body !== null ? body : null;
|
|
206
|
+
}
|
|
160
207
|
if (!response.ok) throw new ContentApiError(response.status, url, body);
|
|
161
208
|
return body;
|
|
162
209
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -40,17 +40,45 @@ class ContentClient {
|
|
|
40
40
|
#fetch;
|
|
41
41
|
constructor({ token, url, locale, depth, richText, timeout, init, fetch: fetchImpl }){
|
|
42
42
|
// The page at a path (`blog/hello`), or null when there is none. A site's
|
|
43
|
-
// catch-all route asks for this.
|
|
44
|
-
|
|
43
|
+
// catch-all route asks for this. The path is looked up in `locale`'s
|
|
44
|
+
// paths (the default locale's when left out or `*`): pages can have a
|
|
45
|
+
// slug per locale.
|
|
46
|
+
this.getPage = async (path, options = {})=>(await this.findPage(path, options))?.entry ?? null;
|
|
47
|
+
// Like getPage, but a path a page moved away from answers where it is
|
|
48
|
+
// now, so the site can send a 301 there instead of a 404.
|
|
49
|
+
//
|
|
50
|
+
// const found = await content.findPage(path, { locale })
|
|
51
|
+
// if (found?.redirect) return redirect(`/${locale}/${found.redirect.path}`, 301)
|
|
52
|
+
// if (!found) return notFound()
|
|
53
|
+
this.findPage = async (path, options = {})=>{
|
|
45
54
|
const trimmed = trimSlashes(path);
|
|
46
55
|
if (!trimmed) throw new Error('getPage needs a path');
|
|
47
56
|
const result = await this.#request('/pages', {
|
|
48
57
|
path: trimmed
|
|
49
58
|
}, options, {
|
|
50
|
-
notFound:
|
|
59
|
+
notFound: 'body'
|
|
51
60
|
});
|
|
52
|
-
|
|
61
|
+
if (result && 'entry' in result) return {
|
|
62
|
+
entry: result.entry
|
|
63
|
+
};
|
|
64
|
+
const to = result?.redirect?.path;
|
|
65
|
+
return typeof to === 'string' ? {
|
|
66
|
+
redirect: {
|
|
67
|
+
path: to
|
|
68
|
+
}
|
|
69
|
+
} : null;
|
|
53
70
|
};
|
|
71
|
+
// One page of redirects: every path a page moved away from, per locale,
|
|
72
|
+
// with where it is now. For redirect rules built ahead of time.
|
|
73
|
+
this.getRedirects = ({ locale, limit, skip, init } = {})=>this.#request('/redirects', {
|
|
74
|
+
limit,
|
|
75
|
+
skip
|
|
76
|
+
}, {
|
|
77
|
+
locale,
|
|
78
|
+
init
|
|
79
|
+
}, {
|
|
80
|
+
defaults: false
|
|
81
|
+
});
|
|
54
82
|
// An entry by id, or null when there is none (or it isn't published, for a
|
|
55
83
|
// delivery token).
|
|
56
84
|
this.getEntry = async (id, options = {})=>{
|
|
@@ -91,6 +119,21 @@ class ContentClient {
|
|
|
91
119
|
this.#init = init;
|
|
92
120
|
this.#fetch = fetchImpl ?? ((...args)=>fetch(...args));
|
|
93
121
|
}
|
|
122
|
+
// Every redirect, fetching pages of `limit` (default 1000) as it goes.
|
|
123
|
+
async *getAllRedirects(query = {}) {
|
|
124
|
+
const limit = query.limit ?? 1000;
|
|
125
|
+
let skip = 0;
|
|
126
|
+
while(true){
|
|
127
|
+
const page = await this.getRedirects({
|
|
128
|
+
...query,
|
|
129
|
+
limit,
|
|
130
|
+
skip
|
|
131
|
+
});
|
|
132
|
+
yield* page.items;
|
|
133
|
+
skip += page.items.length;
|
|
134
|
+
if (page.items.length === 0 || skip >= page.total) return;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
94
137
|
// Every entry matching the query, fetching pages of `limit` (default 100)
|
|
95
138
|
// as it goes.
|
|
96
139
|
//
|
|
@@ -109,7 +152,8 @@ class ContentClient {
|
|
|
109
152
|
if (page.items.length === 0 || skip >= page.total) return;
|
|
110
153
|
}
|
|
111
154
|
}
|
|
112
|
-
//
|
|
155
|
+
// For a 404, null when `notFound` is set, or the body as is for 'body';
|
|
156
|
+
// throws ContentApiError otherwise.
|
|
113
157
|
async #request(path, query, { init, ...options }, { notFound = false, defaults = true } = {}) {
|
|
114
158
|
// Checked here rather than in the constructor, so a module creating a
|
|
115
159
|
// client still loads (and a build still runs) without the variable.
|
|
@@ -147,7 +191,7 @@ class ContentClient {
|
|
|
147
191
|
timeout
|
|
148
192
|
]) : timeout
|
|
149
193
|
});
|
|
150
|
-
if (notFound && response.status === 404) return null;
|
|
194
|
+
if (notFound === true && response.status === 404) return null;
|
|
151
195
|
const text = await response.text();
|
|
152
196
|
let body = text;
|
|
153
197
|
try {
|
|
@@ -155,6 +199,9 @@ class ContentClient {
|
|
|
155
199
|
} catch {
|
|
156
200
|
// Not JSON: keep the text for the error.
|
|
157
201
|
}
|
|
202
|
+
if (notFound === 'body' && response.status === 404) {
|
|
203
|
+
return typeof body === 'object' && body !== null ? body : null;
|
|
204
|
+
}
|
|
158
205
|
if (!response.ok) throw new ContentApiError(response.status, url, body);
|
|
159
206
|
return body;
|
|
160
207
|
}
|
|
@@ -17,6 +17,7 @@ type Entry<TFields extends Record<string, unknown> = Record<string, unknown>, TC
|
|
|
17
17
|
name: string;
|
|
18
18
|
slug: string | null;
|
|
19
19
|
path: string | null;
|
|
20
|
+
paths: Record<string, string>;
|
|
20
21
|
publishedAt: string | null;
|
|
21
22
|
firstPublishedAt: string | null;
|
|
22
23
|
updatedAt: string;
|
|
@@ -55,6 +56,17 @@ type EntryList<TEntry extends Entry = Entry> = {
|
|
|
55
56
|
limit: number;
|
|
56
57
|
skip: number;
|
|
57
58
|
};
|
|
59
|
+
type Redirect = {
|
|
60
|
+
locale: string;
|
|
61
|
+
from: string;
|
|
62
|
+
to: string;
|
|
63
|
+
};
|
|
64
|
+
type RedirectList = {
|
|
65
|
+
items: Redirect[];
|
|
66
|
+
total: number;
|
|
67
|
+
limit: number;
|
|
68
|
+
skip: number;
|
|
69
|
+
};
|
|
58
70
|
type ContentTypeKind = 'page' | 'data' | 'block';
|
|
59
71
|
type BaseField = {
|
|
60
72
|
apiId: string;
|
|
@@ -121,5 +133,5 @@ type ModelFile = {
|
|
|
121
133
|
contentTypes: ContentTypeDefinition[];
|
|
122
134
|
};
|
|
123
135
|
|
|
124
|
-
export type { Asset as A, Block as B, ContentTypeDefinition as C, Entry as E, FieldDefinition as F, ImproveBlock as I, ModelFile as M, RichTextFormat as R,
|
|
125
|
-
//# sourceMappingURL=types-
|
|
136
|
+
export type { Asset as A, Block as B, ContentTypeDefinition as C, Entry as E, FieldDefinition as F, ImproveBlock as I, ModelFile as M, RichTextFormat as R, RedirectList as a, Redirect as b, EntryList as c, EntryStub as d, RichTextNode as e, ContentTypeKind as f, Environment as g, FieldType as h, RichTextDocument as i, RichTextMark as j };
|
|
137
|
+
//# sourceMappingURL=types-2evub96q.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-2evub96q.d.ts","sources":["../src/types.ts"],"mappings":"AAAA,KAAK,WAAW;AAChB,KAAK,cAAc;AACnB,KAAK,KAAK;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB,MAAM;AAC1B,kBAAkB,MAAM;AACxB;AACA,KAAK,KAAK,iBAAiB,MAAM,oBAAoB,MAAM;AAC3D;AACA;AACA;AACA;AACA;AACA,WAAW,MAAM;AACjB;AACA;AACA;AACA;AACA;AACA,KAAK,SAAS;AACd;AACA;AACA;AACA,KAAK,KAAK,iBAAiB,MAAM,oBAAoB,MAAM;AAC3D;AACA;AACA;AACA,KAAK,YAAY,gBAAgB,KAAK,GAAG,KAAK,IAAI,KAAK;AACvD;AACA;AACA,cAAc,MAAM;AACpB;AACA,KAAK,YAAY;AACjB;AACA,YAAY,MAAM;AAClB;AACA,KAAK,YAAY;AACjB;AACA,YAAY,MAAM;AAClB,cAAc,YAAY;AAC1B;AACA,YAAY,YAAY;AACxB;AACA,KAAK,gBAAgB,GAAG,YAAY;AACpC;AACA;AACA,KAAK,SAAS,gBAAgB,KAAK,GAAG,KAAK;AAC3C;AACA;AACA;AACA;AACA;AACA,KAAK,QAAQ;AACb;AACA;AACA;AACA;AACA,KAAK,YAAY;AACjB,WAAW,QAAQ;AACnB;AACA;AACA;AACA;AACA,KAAK,eAAe;AACpB,KAAK,SAAS;AACd;AACA;AACA;AACA;AACA;AACA;AACA,KAAK,eAAe,GAAG,SAAS;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK,SAAS,GAAG,eAAe;AAChC,KAAK,qBAAqB;AAC1B;AACA;AACA,UAAU,eAAe;AACzB;AACA,YAAY,eAAe;AAC3B;AACA,KAAK,SAAS;AACd;AACA;AACA,kBAAkB,qBAAqB;AACvC;;","names":[]}
|
package/dist/webhooks.d.mts
CHANGED
|
@@ -5,6 +5,7 @@ type WebhookEntry = {
|
|
|
5
5
|
contentType: string;
|
|
6
6
|
name: string;
|
|
7
7
|
path: string | null;
|
|
8
|
+
paths: Record<string, string>;
|
|
8
9
|
};
|
|
9
10
|
type WebhookEventOf<TType extends string, TData> = {
|
|
10
11
|
type: TType;
|
|
@@ -25,6 +26,7 @@ type EntryDeletedEvent = WebhookEventOf<'entry.deleted', {
|
|
|
25
26
|
type EntryMovedEvent = WebhookEventOf<'entry.moved', {
|
|
26
27
|
entry: WebhookEntry;
|
|
27
28
|
previousPath: string | null;
|
|
29
|
+
previousPaths: Record<string, string>;
|
|
28
30
|
}>;
|
|
29
31
|
type AssetUpdatedEvent = WebhookEventOf<'asset.updated', {
|
|
30
32
|
asset: {
|
package/dist/webhooks.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.d.mts","sources":["../src/webhooks.ts"],"mappings":";;AACA,KAAK,YAAY;AACjB;AACA;AACA;AACA;AACA;AACA,KAAK,cAAc;AACnB;AACA;AACA;AACA,iBAAiB,WAAW;AAC5B;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC,WAAW,YAAY;AACvB;AACA,KAAK,qBAAqB,GAAG,cAAc;AAC3C,WAAW,YAAY;AACvB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC,WAAW,YAAY;AACvB;AACA,KAAK,eAAe,GAAG,cAAc;AACrC,WAAW,YAAY;AACvB;AACA;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC;AACA;AACA;AACA;AACA,aAAa,YAAY;AACzB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC;AACA;AACA;AACA;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC;AACA;AACA;AACA,KAAK,gBAAgB,GAAG,cAAc,iBAAiB,MAAM;AAC7D,KAAK,YAAY,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,iBAAiB,GAAG,eAAe,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,gBAAgB;AACtL,KAAK,gBAAgB,GAAG,YAAY;AACpC,cAAc,wBAAwB,SAAS,KAAK;AACpD;AACA;AACA,KAAK,cAAc;AACnB;AACA,aAAa,OAAO,GAAG,MAAM,0CAA0C,QAAQ;AAC/E;AACA,KAAK,oBAAoB;AACzB;AACA;AACA;AACA,cAAc,aAAa,YAAY,OAAO,GAAG,cAAc,wCAAwC,oBAAoB,KAAK,OAAO,CAAC,YAAY;AACpJ,KAAK,qBAAqB;AAC1B;AACA,qBAAqB,YAAY;AACjC;AACA;AACA;AACA;AACA,cAAc,oBAAoB,mCAAmC,qBAAqB,eAAe,OAAO,KAAK,OAAO,CAAC,QAAQ","names":[]}
|
|
1
|
+
{"version":3,"file":"webhooks.d.mts","sources":["../src/webhooks.ts"],"mappings":";;AACA,KAAK,YAAY;AACjB;AACA;AACA;AACA;AACA,WAAW,MAAM;AACjB;AACA,KAAK,cAAc;AACnB;AACA;AACA;AACA,iBAAiB,WAAW;AAC5B;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC,WAAW,YAAY;AACvB;AACA,KAAK,qBAAqB,GAAG,cAAc;AAC3C,WAAW,YAAY;AACvB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC,WAAW,YAAY;AACvB;AACA,KAAK,eAAe,GAAG,cAAc;AACrC,WAAW,YAAY;AACvB;AACA,mBAAmB,MAAM;AACzB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC;AACA;AACA;AACA;AACA,aAAa,YAAY;AACzB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC;AACA;AACA;AACA;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC;AACA;AACA;AACA,KAAK,gBAAgB,GAAG,cAAc,iBAAiB,MAAM;AAC7D,KAAK,YAAY,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,iBAAiB,GAAG,eAAe,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,gBAAgB;AACtL,KAAK,gBAAgB,GAAG,YAAY;AACpC,cAAc,wBAAwB,SAAS,KAAK;AACpD;AACA;AACA,KAAK,cAAc;AACnB;AACA,aAAa,OAAO,GAAG,MAAM,0CAA0C,QAAQ;AAC/E;AACA,KAAK,oBAAoB;AACzB;AACA;AACA;AACA,cAAc,aAAa,YAAY,OAAO,GAAG,cAAc,wCAAwC,oBAAoB,KAAK,OAAO,CAAC,YAAY;AACpJ,KAAK,qBAAqB;AAC1B;AACA,qBAAqB,YAAY;AACjC;AACA;AACA;AACA;AACA,cAAc,oBAAoB,mCAAmC,qBAAqB,eAAe,OAAO,KAAK,OAAO,CAAC,QAAQ","names":[]}
|