@tdacorp/hyle-sdk 0.1.1 → 0.2.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 +39 -6
- package/dist/chunk-7VCMJUPC.js +35 -0
- package/dist/{chunk-RI3BP4MI.js → chunk-HFUJRNFP.js} +42 -1
- package/dist/{chunk-XODMIT6N.js → chunk-MHVWHSKC.js} +21 -3
- package/dist/index.cjs +42 -0
- package/dist/index.d.cts +30 -1
- package/dist/index.d.ts +30 -1
- package/dist/index.js +3 -1
- package/dist/next.cjs +178 -54
- package/dist/next.d.cts +62 -4
- package/dist/next.d.ts +62 -4
- package/dist/next.js +120 -51
- package/dist/react.cjs +22 -3
- package/dist/react.d.cts +6 -1
- package/dist/react.d.ts +6 -1
- package/dist/react.js +3 -1
- package/dist/resolve-B_p0p4Zn.d.cts +29 -0
- package/dist/resolve-fMx2W8RR.d.ts +29 -0
- package/dist/use-cache.cjs +3 -3
- package/dist/use-cache.d.cts +1 -1
- package/dist/use-cache.d.ts +1 -1
- package/dist/use-cache.js +6 -6
- package/package.json +1 -1
- package/dist/chunk-HVAWEEHG.js +0 -29
- package/dist/resolve-Cz-3Q7T-.d.ts +0 -16
- package/dist/resolve-DrmTGaCr.d.cts +0 -16
package/README.md
CHANGED
|
@@ -49,9 +49,9 @@ Register that URL as the workspace's webhook endpoint in hyle. Set `metadataBase
|
|
|
49
49
|
|
|
50
50
|
| Import | Contents | Needs |
|
|
51
51
|
|---|---|---|
|
|
52
|
-
| `@tdacorp/hyle-sdk` | `createHyleClient` (typed `resolve`), `Cp1ClientError`, `verifyHyleSignature`, `parseSignatureHeader`, `isValidCacheTag`, `DeliveryDedupe`, `createRevalidationCallbackRoute`, the result types | nothing (no framework) |
|
|
53
|
-
| `@tdacorp/hyle-sdk/react` | `ArticlePage`, `ListPage`, `DocsPage`, `NotFound`, `Redirecting`, `HastContent`, `TrustedServerHtml`, `sanitizeHast` | react >= 19 |
|
|
54
|
-
| `@tdacorp/hyle-sdk/next` | `hylePage`, `hyleMetadata`, `createRevalidateRoute` | next >= 16 |
|
|
52
|
+
| `@tdacorp/hyle-sdk` | `createHyleClient` (typed `resolve`), `listPublicationPaths`, `Cp1ClientError`, `verifyHyleSignature`, `parseSignatureHeader`, `isValidCacheTag`, `DeliveryDedupe`, `createRevalidationCallbackRoute`, the result types | nothing (no framework) |
|
|
53
|
+
| `@tdacorp/hyle-sdk/react` | `ArticlePage`, `ListPage`, `DocsPage`, `NotFound`, `Redirecting`, `Unavailable`, `HastContent`, `TrustedServerHtml`, `sanitizeHast` | react >= 19 |
|
|
54
|
+
| `@tdacorp/hyle-sdk/next` | `hylePage`, `hyleMetadata`, `hyleSitemap`, `createRevalidateRoute`, `fetchResolver`, `workspaceTags` | next >= 16 |
|
|
55
55
|
| `@tdacorp/hyle-sdk/next/use-cache` | `cachedResolver` | next >= 16 with `cacheComponents: true` |
|
|
56
56
|
| `@tdacorp/hyle-sdk/styles.css` | the stylesheet | |
|
|
57
57
|
|
|
@@ -90,7 +90,40 @@ The credential is never part of a cache key: entries are keyed by `baseUrl` plus
|
|
|
90
90
|
|
|
91
91
|
The revalidate route expires tags immediately (`revalidateTag(tag, { expire: 0 })`), so no stale page is served after a purge. `HYLE_CONTENT_ENABLED=0` (or `false`) answers 404 from the route, the site-side rollback switch; nothing configured is also 404; partly configured is 503.
|
|
92
92
|
|
|
93
|
-
List pages
|
|
93
|
+
### List pages
|
|
94
|
+
|
|
95
|
+
`list: { title, description }` sets the list page's h1, `<title>`, description and Open Graph. Each wins over hyle's section title (which is the slug, "Posts") and falls back separately: no `list.title` keeps the section title, no `list.description` shows none. Articles are unaffected.
|
|
96
|
+
|
|
97
|
+
List pages show the first page of results (`listLimit`, server default 20, maximum 100). `paginate: "searchParams"` turns on cursor pagination: `?cursor=` is read (it must be 1 to 256 characters of `A-Za-z0-9_-`, otherwise it is ignored; a well-formed cursor hyle rejects is a 404), sent to hyle, and "Older posts" links to `?cursor=<next_cursor>`. It is off by default because reading `searchParams` makes the route dynamic: it can no longer be statically generated or served from ISR (hyle's fetch cache and tags still apply per request). Leave it off when one page is enough. `generateMetadata` does not read the cursor, so page 2 shares page 1's title.
|
|
98
|
+
|
|
99
|
+
## Errors
|
|
100
|
+
|
|
101
|
+
How `hylePage` treats a hyle failure is chosen so a bad moment never replaces a good cached page:
|
|
102
|
+
|
|
103
|
+
| Failure | Behaviour |
|
|
104
|
+
|---|---|
|
|
105
|
+
| A 4xx rejection of the request (`VALIDATION_ERROR`, `NOT_FOUND`, any 4xx except 401, 403 and 429), a path over 1024 characters, a non-NFC segment | `notFound()` (a real 404; the last two never reach hyle) |
|
|
106
|
+
| Network error, timeout, 5xx, 401, 403, 429, a malformed response, a refused redirect target | **Rethrown.** Under ISR, Next keeps serving the last good page when a revalidation fails; a failure on a first render is an uncached 500 |
|
|
107
|
+
| `notFound()` and redirects | Next control flow, always propagated (`unstable_rethrow`) |
|
|
108
|
+
|
|
109
|
+
Why rethrow: a rendered "unavailable" page is a normal 200 render, so ISR would cache it and replace the last good article for everyone for the revalidate window. `onError: (error) => ReactElement` is the opt-in for a custom UI anyway; its element IS cached like any render, and the `error` it receives can contain `Cp1ClientError.message` and `requestId`, so never render it (only its name is logged, never the token or message). The `Unavailable` component (en, fr, es; `data-hyle-page="unavailable"`, `role="status"`, no error text) is exported from `./react` for `onError` or your own `error.tsx`. `hyleMetadata` follows the same split: a 4xx rejection gives `{}`, anything else is rethrown, so a transient outage never caches a noindex page.
|
|
110
|
+
|
|
111
|
+
## Sitemap
|
|
112
|
+
|
|
113
|
+
The contract has no "list every page" endpoint, so the helper pages the list result at each section index (100 per page, `next_cursor`, at most 20 pages per index by default). Spread it into your sitemap:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { hyleSitemap } from "@tdacorp/hyle-sdk/next";
|
|
117
|
+
export default async function sitemap() {
|
|
118
|
+
return [...staticEntries, ...(await hyleSitemap({ ...options, origin: "https://tdacorp.in", sections: ["docs"] }))];
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`origin` must be a bare https origin (anything else throws). URLs are percent-encoded and use `localePrefix`; the locale is `options.locale` when it is a string, and a function of the route params is never called (the sitemap is for the default locale). `lastModified` is `published_at` (omitted if it is not an ISO date): the list carries no `updated_at`. Only the default section and the `sections` you list are covered (a section's index resolves at `basePath/<slug>`), at most 2000 pages per index. `onIncomplete` decides what a hyle failure (or a listing cut off by the page limit) does: `"partial"` returns what was collected, `"throw"` throws so a build during an outage fails; the default throws only when nothing was collected. The core `listPublicationPaths({ client, basePath, sections?, locale?, maxPages? })` never throws and returns `{ paths: { path, publishedAt }[], complete }`, where `complete: false` means `paths` is partial.
|
|
123
|
+
|
|
124
|
+
## Building blocks
|
|
125
|
+
|
|
126
|
+
`fetchResolver(options)` is the default fetch-cache resolver, and `workspaceTags(workspaceId, sections?)` builds its tags (`hyle:1:ws:<id>`, `hyle:1:sec:<ws>:<section>`). Wrap `fetchResolver` to adjust a result (pass the wrapper as `resolver`) instead of copying it.
|
|
94
127
|
|
|
95
128
|
## Host requirements
|
|
96
129
|
|
|
@@ -127,9 +160,9 @@ Chrome strings exist for en, fr and es (fr and es are unreviewed drafts). The pa
|
|
|
127
160
|
- The `hast` tree is rendered through an allowlist (`sanitizeHast`) even though hyle sanitizes server-side: only known tags and properties with accepted value shapes survive; no `on*` attributes, `style` only inside KaTeX output and only for the properties KaTeX emits with small values (no `position:absolute`, `z-index`, `left` or large sizes), ids and in-page fragments scoped with the server's `user-content-` prefix (so heading ids, footnote links and TOC links still resolve), `href` and `src` limited to site-relative paths and `http(s)` (and `mailto` for links), unknown tags are unwrapped, `script` and `style` are dropped, and an `iframe` is kept only with `sandbox="allow-scripts"` and a `srcdoc` that is exactly the document hyle's renderer builds for a Mermaid fence (pinned script URL, at most 64 KiB); the SDK adds `referrerpolicy="no-referrer"` and a `csp` that allows only that script (checked in headless Chromium: the diagram still renders). A tree over 20,000 nodes or 512 KiB of text fails closed with `HastLimitError` and a safe notice. `dangerouslySetInnerHTML` is used in exactly one place, `TrustedServerHtml`, the escape hatch for `content.format === "html"`: it renders HTML as is, so pass it only HTML that came straight from hyle's resolve endpoint, never user input.
|
|
128
161
|
- Webhooks are verified with HMAC-SHA256 over the raw body (read with a running 64 KiB cap), a 300 s timestamp tolerance and constant-time comparison, with dual-secret rotation (empty secrets are never candidates), a payload shape check (400, not 500), tag validation, and delivery-id dedupe that records an id only after every purge succeeded, so a failed delivery can be retried.
|
|
129
162
|
|
|
130
|
-
## Not
|
|
163
|
+
## Not included
|
|
131
164
|
|
|
132
|
-
|
|
165
|
+
Docs versions, reading time, scroll-spy, "closest matches" on the 404 page and a copy-code button: hyle does not provide that data or the page would need client JavaScript. Image URLs in content such as `/assets/<id>` are passed through unchanged; map them with the `Image` slot if they live on hyle's origin.
|
|
133
166
|
|
|
134
167
|
## Contract
|
|
135
168
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createHyleClient,
|
|
3
|
+
isValidCacheTag
|
|
4
|
+
} from "./chunk-HFUJRNFP.js";
|
|
5
|
+
|
|
6
|
+
// src/next/resolve.ts
|
|
7
|
+
var DEFAULT_REVALIDATE = 300;
|
|
8
|
+
var MAX_TAGS = 64;
|
|
9
|
+
function workspaceTags(workspaceId, sections = []) {
|
|
10
|
+
const workspaceTag = `hyle:1:ws:${workspaceId}`;
|
|
11
|
+
if (!isValidCacheTag(workspaceTag)) throw new TypeError("hyle: `workspaceId` is not a valid workspace id (a uuid)");
|
|
12
|
+
const slugs = /* @__PURE__ */ new Set(["posts", ...sections]);
|
|
13
|
+
const tags = [...slugs].map((slug) => `hyle:1:sec:${workspaceId}:${slug}`);
|
|
14
|
+
if (!tags.every(isValidCacheTag)) throw new TypeError("hyle: a configured `sections` slug cannot be used in a cache tag (printable ASCII, at most 200 characters)");
|
|
15
|
+
return [workspaceTag, ...tags].slice(0, MAX_TAGS);
|
|
16
|
+
}
|
|
17
|
+
function fetchResolver(options) {
|
|
18
|
+
if (!options.workspaceId) throw new TypeError("hylePage: `workspaceId` is required for the fetch cache (or pass a cachedResolver)");
|
|
19
|
+
const client = createHyleClient({ baseUrl: options.baseUrl, token: options.token });
|
|
20
|
+
const revalidate = options.revalidate ?? DEFAULT_REVALIDATE;
|
|
21
|
+
const tags = workspaceTags(options.workspaceId, options.sections);
|
|
22
|
+
return (path, locale, limit, cursor) => client.resolve({
|
|
23
|
+
path,
|
|
24
|
+
...locale !== void 0 ? { locale } : {},
|
|
25
|
+
...limit !== void 0 ? { limit } : {},
|
|
26
|
+
...cursor !== void 0 ? { cursor } : {},
|
|
27
|
+
init: { next: { revalidate, tags } }
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
DEFAULT_REVALIDATE,
|
|
33
|
+
workspaceTags,
|
|
34
|
+
fetchResolver
|
|
35
|
+
};
|
|
@@ -237,6 +237,46 @@ function okResponse(purged) {
|
|
|
237
237
|
});
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
// src/sitemap.ts
|
|
241
|
+
var PAGE_LIMIT = 100;
|
|
242
|
+
var DEFAULT_MAX_PAGES = 20;
|
|
243
|
+
var SECTION_SLUG = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
244
|
+
var UNSAFE_PATH = /[\\?#<>&"'\u0000- \u007f]/;
|
|
245
|
+
async function listPublicationPaths(options) {
|
|
246
|
+
const maxPages = options.maxPages ?? DEFAULT_MAX_PAGES;
|
|
247
|
+
const prefix = `${options.basePath}/`;
|
|
248
|
+
const indexes = [options.basePath || "/"];
|
|
249
|
+
for (const slug of options.sections ?? []) if (slug !== "posts" && SECTION_SLUG.test(slug)) indexes.push(`${options.basePath}/${slug}`);
|
|
250
|
+
const found = /* @__PURE__ */ new Map();
|
|
251
|
+
let complete = true;
|
|
252
|
+
try {
|
|
253
|
+
for (const index of new Set(indexes)) {
|
|
254
|
+
let cursor;
|
|
255
|
+
for (let page = 0; page < maxPages; page++) {
|
|
256
|
+
const result = await options.client.resolve({
|
|
257
|
+
path: index,
|
|
258
|
+
limit: PAGE_LIMIT,
|
|
259
|
+
...options.locale !== void 0 ? { locale: options.locale } : {},
|
|
260
|
+
...cursor !== void 0 ? { cursor } : {}
|
|
261
|
+
});
|
|
262
|
+
if (result.kind !== "list") {
|
|
263
|
+
complete = false;
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
for (const item of result.items) {
|
|
267
|
+
if (item.canonical_path.startsWith(prefix) && !UNSAFE_PATH.test(item.canonical_path)) found.set(item.canonical_path, item.published_at);
|
|
268
|
+
}
|
|
269
|
+
if (!result.next_cursor) break;
|
|
270
|
+
if (page === maxPages - 1) complete = false;
|
|
271
|
+
cursor = result.next_cursor;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
} catch {
|
|
275
|
+
complete = false;
|
|
276
|
+
}
|
|
277
|
+
return { paths: [...found].map(([path, publishedAt]) => ({ path, publishedAt })), complete };
|
|
278
|
+
}
|
|
279
|
+
|
|
240
280
|
export {
|
|
241
281
|
Cp1ClientError,
|
|
242
282
|
createHyleClient,
|
|
@@ -245,5 +285,6 @@ export {
|
|
|
245
285
|
verifyHyleSignature,
|
|
246
286
|
CACHE_TAG_PATTERN,
|
|
247
287
|
isValidCacheTag,
|
|
248
|
-
createRevalidationCallbackRoute
|
|
288
|
+
createRevalidationCallbackRoute,
|
|
289
|
+
listPublicationPaths
|
|
249
290
|
};
|
|
@@ -243,7 +243,10 @@ var en = {
|
|
|
243
243
|
rdBody: "You are being taken to its new address.",
|
|
244
244
|
from: "From",
|
|
245
245
|
to: "To",
|
|
246
|
-
rdFallback: "If nothing happens, go to the new address."
|
|
246
|
+
rdFallback: "If nothing happens, go to the new address.",
|
|
247
|
+
unKind: "Unavailable",
|
|
248
|
+
unTitle: "This page is temporarily unavailable",
|
|
249
|
+
unBody: "The content could not be loaded. Please try again in a moment."
|
|
247
250
|
};
|
|
248
251
|
var fr = {
|
|
249
252
|
toc: "Sur cette page",
|
|
@@ -279,7 +282,10 @@ var fr = {
|
|
|
279
282
|
rdBody: "Vous \xEAtes redirig\xE9 vers sa nouvelle adresse.",
|
|
280
283
|
from: "De",
|
|
281
284
|
to: "Vers",
|
|
282
|
-
rdFallback: "Si rien ne se passe, allez \xE0 la nouvelle adresse."
|
|
285
|
+
rdFallback: "Si rien ne se passe, allez \xE0 la nouvelle adresse.",
|
|
286
|
+
unKind: "Indisponible",
|
|
287
|
+
unTitle: "Cette page est momentan\xE9ment indisponible",
|
|
288
|
+
unBody: "Le contenu n'a pas pu \xEAtre charg\xE9. R\xE9essayez dans un instant."
|
|
283
289
|
};
|
|
284
290
|
var es = {
|
|
285
291
|
toc: "En esta p\xE1gina",
|
|
@@ -315,7 +321,10 @@ var es = {
|
|
|
315
321
|
rdBody: "Te estamos llevando a su nueva direcci\xF3n.",
|
|
316
322
|
from: "Desde",
|
|
317
323
|
to: "A",
|
|
318
|
-
rdFallback: "Si no pasa nada, ve a la nueva direcci\xF3n."
|
|
324
|
+
rdFallback: "Si no pasa nada, ve a la nueva direcci\xF3n.",
|
|
325
|
+
unKind: "No disponible",
|
|
326
|
+
unTitle: "Esta p\xE1gina no est\xE1 disponible por el momento",
|
|
327
|
+
unBody: "No se pudo cargar el contenido. Int\xE9ntalo de nuevo en un momento."
|
|
319
328
|
};
|
|
320
329
|
var TABLE = { en, fr, es };
|
|
321
330
|
function stringsFor(locale) {
|
|
@@ -679,6 +688,14 @@ function NotFound({ path, homeHref = "/", ...base }) {
|
|
|
679
688
|
] })
|
|
680
689
|
] }) });
|
|
681
690
|
}
|
|
691
|
+
function Unavailable(base) {
|
|
692
|
+
const c = ctx(base, "en");
|
|
693
|
+
return /* @__PURE__ */ jsx4(Shell, { children: /* @__PURE__ */ jsxs4("section", { className: "hyle-state", "data-hyle-page": "unavailable", lang: c.locale, role: "status", children: [
|
|
694
|
+
/* @__PURE__ */ jsx4("span", { className: "kind", children: c.s.unKind }),
|
|
695
|
+
/* @__PURE__ */ jsx4("h1", { children: c.s.unTitle }),
|
|
696
|
+
/* @__PURE__ */ jsx4("p", { children: c.s.unBody })
|
|
697
|
+
] }) });
|
|
698
|
+
}
|
|
682
699
|
function Redirecting({ from, to, ...base }) {
|
|
683
700
|
const c = ctx(base, "en");
|
|
684
701
|
const { Link, s } = c;
|
|
@@ -714,5 +731,6 @@ export {
|
|
|
714
731
|
ListPage,
|
|
715
732
|
DocsPage,
|
|
716
733
|
NotFound,
|
|
734
|
+
Unavailable,
|
|
717
735
|
Redirecting
|
|
718
736
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ __export(src_exports, {
|
|
|
26
26
|
createHyleClient: () => createHyleClient,
|
|
27
27
|
createRevalidationCallbackRoute: () => createRevalidationCallbackRoute,
|
|
28
28
|
isValidCacheTag: () => isValidCacheTag,
|
|
29
|
+
listPublicationPaths: () => listPublicationPaths,
|
|
29
30
|
parseSignatureHeader: () => parseSignatureHeader,
|
|
30
31
|
verifyHyleSignature: () => verifyHyleSignature
|
|
31
32
|
});
|
|
@@ -269,6 +270,46 @@ function okResponse(purged) {
|
|
|
269
270
|
headers: { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-store" }
|
|
270
271
|
});
|
|
271
272
|
}
|
|
273
|
+
|
|
274
|
+
// src/sitemap.ts
|
|
275
|
+
var PAGE_LIMIT = 100;
|
|
276
|
+
var DEFAULT_MAX_PAGES = 20;
|
|
277
|
+
var SECTION_SLUG = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
278
|
+
var UNSAFE_PATH = /[\\?#<>&"'\u0000- \u007f]/;
|
|
279
|
+
async function listPublicationPaths(options) {
|
|
280
|
+
const maxPages = options.maxPages ?? DEFAULT_MAX_PAGES;
|
|
281
|
+
const prefix = `${options.basePath}/`;
|
|
282
|
+
const indexes = [options.basePath || "/"];
|
|
283
|
+
for (const slug of options.sections ?? []) if (slug !== "posts" && SECTION_SLUG.test(slug)) indexes.push(`${options.basePath}/${slug}`);
|
|
284
|
+
const found = /* @__PURE__ */ new Map();
|
|
285
|
+
let complete = true;
|
|
286
|
+
try {
|
|
287
|
+
for (const index of new Set(indexes)) {
|
|
288
|
+
let cursor;
|
|
289
|
+
for (let page = 0; page < maxPages; page++) {
|
|
290
|
+
const result = await options.client.resolve({
|
|
291
|
+
path: index,
|
|
292
|
+
limit: PAGE_LIMIT,
|
|
293
|
+
...options.locale !== void 0 ? { locale: options.locale } : {},
|
|
294
|
+
...cursor !== void 0 ? { cursor } : {}
|
|
295
|
+
});
|
|
296
|
+
if (result.kind !== "list") {
|
|
297
|
+
complete = false;
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
for (const item of result.items) {
|
|
301
|
+
if (item.canonical_path.startsWith(prefix) && !UNSAFE_PATH.test(item.canonical_path)) found.set(item.canonical_path, item.published_at);
|
|
302
|
+
}
|
|
303
|
+
if (!result.next_cursor) break;
|
|
304
|
+
if (page === maxPages - 1) complete = false;
|
|
305
|
+
cursor = result.next_cursor;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
} catch {
|
|
309
|
+
complete = false;
|
|
310
|
+
}
|
|
311
|
+
return { paths: [...found].map(([path, publishedAt]) => ({ path, publishedAt })), complete };
|
|
312
|
+
}
|
|
272
313
|
// Annotate the CommonJS export names for ESM import in node:
|
|
273
314
|
0 && (module.exports = {
|
|
274
315
|
CACHE_TAG_PATTERN,
|
|
@@ -277,6 +318,7 @@ function okResponse(purged) {
|
|
|
277
318
|
createHyleClient,
|
|
278
319
|
createRevalidationCallbackRoute,
|
|
279
320
|
isValidCacheTag,
|
|
321
|
+
listPublicationPaths,
|
|
280
322
|
parseSignatureHeader,
|
|
281
323
|
verifyHyleSignature
|
|
282
324
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -99,4 +99,33 @@ declare class DeliveryDedupe {
|
|
|
99
99
|
add(deliveryId: string): void;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
interface PublicationPath {
|
|
103
|
+
/** The publication's canonical site path, for example "/learn/hello". */
|
|
104
|
+
readonly path: string;
|
|
105
|
+
/** ISO 8601 `published_at` (the list endpoint carries no `updated_at`). */
|
|
106
|
+
readonly publishedAt: string;
|
|
107
|
+
}
|
|
108
|
+
interface PublicationPaths {
|
|
109
|
+
readonly paths: PublicationPath[];
|
|
110
|
+
/** False when any index failed, answered something other than a list, or was cut off by `maxPages`: `paths` is then partial. */
|
|
111
|
+
readonly complete: boolean;
|
|
112
|
+
}
|
|
113
|
+
interface ListPublicationPathsOptions {
|
|
114
|
+
/** Anything with `resolve`: a `createHyleClient(...)`, or a wrapper around a host's own resolver. */
|
|
115
|
+
readonly client: Pick<HyleClient, "resolve">;
|
|
116
|
+
/** The mount prefix, "" or "/learn": the same value as `basePath` of `hylePage`. */
|
|
117
|
+
readonly basePath: string;
|
|
118
|
+
/** Section slugs to list besides the default section, whose index is `basePath` itself. A section's index is `basePath/<slug>`. */
|
|
119
|
+
readonly sections?: readonly string[];
|
|
120
|
+
readonly locale?: string;
|
|
121
|
+
/** Pages fetched per index (default 20, of 100 items each), so a workspace larger than 2000 per section is truncated. */
|
|
122
|
+
readonly maxPages?: number;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Every published page under a mount, for a sitemap. The contract has no "list everything" endpoint, so this pages the list
|
|
126
|
+
* result at each section index (`limit` 100, following `next_cursor`) up to `maxPages` per index. Only the default section and
|
|
127
|
+
* the listed `sections` are covered. Never throws: on any error it returns what it collected with `complete: false`, so the caller decides whether a partial listing is acceptable.
|
|
128
|
+
*/
|
|
129
|
+
declare function listPublicationPaths(options: ListPublicationPathsOptions): Promise<PublicationPaths>;
|
|
130
|
+
|
|
131
|
+
export { CACHE_TAG_PATTERN, Cp1ClientError, DeliveryDedupe, type HyleClient, type HyleClientOptions, type HyleRequestInit, type ListPublicationPathsOptions, type ParsedSignatureHeader, type PublicationPath, type PublicationPaths, type ResolveOptions, Resolved, type VerifySignatureParams, createHyleClient, isValidCacheTag, listPublicationPaths, parseSignatureHeader, verifyHyleSignature };
|
package/dist/index.d.ts
CHANGED
|
@@ -99,4 +99,33 @@ declare class DeliveryDedupe {
|
|
|
99
99
|
add(deliveryId: string): void;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
interface PublicationPath {
|
|
103
|
+
/** The publication's canonical site path, for example "/learn/hello". */
|
|
104
|
+
readonly path: string;
|
|
105
|
+
/** ISO 8601 `published_at` (the list endpoint carries no `updated_at`). */
|
|
106
|
+
readonly publishedAt: string;
|
|
107
|
+
}
|
|
108
|
+
interface PublicationPaths {
|
|
109
|
+
readonly paths: PublicationPath[];
|
|
110
|
+
/** False when any index failed, answered something other than a list, or was cut off by `maxPages`: `paths` is then partial. */
|
|
111
|
+
readonly complete: boolean;
|
|
112
|
+
}
|
|
113
|
+
interface ListPublicationPathsOptions {
|
|
114
|
+
/** Anything with `resolve`: a `createHyleClient(...)`, or a wrapper around a host's own resolver. */
|
|
115
|
+
readonly client: Pick<HyleClient, "resolve">;
|
|
116
|
+
/** The mount prefix, "" or "/learn": the same value as `basePath` of `hylePage`. */
|
|
117
|
+
readonly basePath: string;
|
|
118
|
+
/** Section slugs to list besides the default section, whose index is `basePath` itself. A section's index is `basePath/<slug>`. */
|
|
119
|
+
readonly sections?: readonly string[];
|
|
120
|
+
readonly locale?: string;
|
|
121
|
+
/** Pages fetched per index (default 20, of 100 items each), so a workspace larger than 2000 per section is truncated. */
|
|
122
|
+
readonly maxPages?: number;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Every published page under a mount, for a sitemap. The contract has no "list everything" endpoint, so this pages the list
|
|
126
|
+
* result at each section index (`limit` 100, following `next_cursor`) up to `maxPages` per index. Only the default section and
|
|
127
|
+
* the listed `sections` are covered. Never throws: on any error it returns what it collected with `complete: false`, so the caller decides whether a partial listing is acceptable.
|
|
128
|
+
*/
|
|
129
|
+
declare function listPublicationPaths(options: ListPublicationPathsOptions): Promise<PublicationPaths>;
|
|
130
|
+
|
|
131
|
+
export { CACHE_TAG_PATTERN, Cp1ClientError, DeliveryDedupe, type HyleClient, type HyleClientOptions, type HyleRequestInit, type ListPublicationPathsOptions, type ParsedSignatureHeader, type PublicationPath, type PublicationPaths, type ResolveOptions, Resolved, type VerifySignatureParams, createHyleClient, isValidCacheTag, listPublicationPaths, parseSignatureHeader, verifyHyleSignature };
|
package/dist/index.js
CHANGED
|
@@ -5,9 +5,10 @@ import {
|
|
|
5
5
|
createHyleClient,
|
|
6
6
|
createRevalidationCallbackRoute,
|
|
7
7
|
isValidCacheTag,
|
|
8
|
+
listPublicationPaths,
|
|
8
9
|
parseSignatureHeader,
|
|
9
10
|
verifyHyleSignature
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-HFUJRNFP.js";
|
|
11
12
|
export {
|
|
12
13
|
CACHE_TAG_PATTERN,
|
|
13
14
|
Cp1ClientError,
|
|
@@ -15,6 +16,7 @@ export {
|
|
|
15
16
|
createHyleClient,
|
|
16
17
|
createRevalidationCallbackRoute,
|
|
17
18
|
isValidCacheTag,
|
|
19
|
+
listPublicationPaths,
|
|
18
20
|
parseSignatureHeader,
|
|
19
21
|
verifyHyleSignature
|
|
20
22
|
};
|