@aotter/mantle-web 0.1.0-alpha.15 → 0.1.0-alpha.17
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 +34 -0
- package/dist/dto/ComposeLlmsTxtRequest.d.ts +7 -3
- package/dist/dto/ComposeLlmsTxtRequest.d.ts.map +1 -1
- package/dist/dto/ComposeSitemapRequest.d.ts +6 -3
- package/dist/dto/ComposeSitemapRequest.d.ts.map +1 -1
- package/dist/dto/RenderListLiveRequest.d.ts +3 -0
- package/dist/dto/RenderListLiveRequest.d.ts.map +1 -1
- package/dist/service/PublicPathResolver.d.ts +2 -0
- package/dist/service/PublicPathResolver.d.ts.map +1 -1
- package/dist/service/PublicPathResolver.js +1 -0
- package/dist/service/PublicPathResolver.js.map +1 -1
- package/dist/service/SitemapSerializer.d.ts +1 -0
- package/dist/service/SitemapSerializer.d.ts.map +1 -1
- package/dist/service/SitemapSerializer.js +5 -0
- package/dist/service/SitemapSerializer.js.map +1 -1
- package/dist/usecase/ComposeLlmsTxtUseCase.d.ts +5 -9
- package/dist/usecase/ComposeLlmsTxtUseCase.d.ts.map +1 -1
- package/dist/usecase/ComposeLlmsTxtUseCase.js +14 -19
- package/dist/usecase/ComposeLlmsTxtUseCase.js.map +1 -1
- package/dist/usecase/ComposeSitemapUseCase.d.ts +9 -8
- package/dist/usecase/ComposeSitemapUseCase.d.ts.map +1 -1
- package/dist/usecase/ComposeSitemapUseCase.js +40 -13
- package/dist/usecase/ComposeSitemapUseCase.js.map +1 -1
- package/dist/usecase/RenderListLiveUseCase.d.ts +4 -1
- package/dist/usecase/RenderListLiveUseCase.d.ts.map +1 -1
- package/dist/usecase/RenderListLiveUseCase.js +6 -3
- package/dist/usecase/RenderListLiveUseCase.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -24,6 +24,40 @@ const html = await web.renderEntryLive.execute({
|
|
|
24
24
|
Omit this package when an application only needs Mantle parsing, planning, or
|
|
25
25
|
headless runtime operations.
|
|
26
26
|
|
|
27
|
+
## Public content pages
|
|
28
|
+
|
|
29
|
+
`renderListLive.execute` returns `{ html, nextCursor? } | null`.
|
|
30
|
+
`composeLlmsTxt.execute` returns `{ body, nextCursor? } | null`, where `body`
|
|
31
|
+
can be null for a page without serializable public documents.
|
|
32
|
+
`composeSitemap.execute` returns `{ body, nextCursor? }` for one sitemap part.
|
|
33
|
+
These alpha APIs now return explicit pages: a custom adapter must expose or
|
|
34
|
+
follow `nextCursor`, including when the current llms page has no body.
|
|
35
|
+
|
|
36
|
+
Lists and llms default to 50 entries. Pass `cursor` from the previous result and
|
|
37
|
+
optionally `limit` to change page size. Ordering is `updatedAt DESC, id DESC`;
|
|
38
|
+
these are live forward pages, not a snapshot during concurrent publication.
|
|
39
|
+
The reader limits each page to 2,000 rows and 1 MiB of data JSON, except a single
|
|
40
|
+
oversized entry is returned alone so iteration can advance.
|
|
41
|
+
|
|
42
|
+
For root llms, omit `locale`, pass `locales: site.locales`, and provide
|
|
43
|
+
`pathFor(entry, locale)` to expand shared entries without repeated database reads.
|
|
44
|
+
For a sitemap, `maxUrls` is entries per part (default 2,000). Serve an index with
|
|
45
|
+
`composeSitemap.index(request, cursor => partUrl(cursor))`; every part must use
|
|
46
|
+
the same request projection and limit. Parts have the standard 50,000-URL /
|
|
47
|
+
50-MiB protocol ceilings and fail explicitly if custom expansion exceeds them.
|
|
48
|
+
The index walks bounded metadata pages, so its database work is proportional
|
|
49
|
+
to site size. `additionalPaths` appears only in the first part.
|
|
50
|
+
|
|
51
|
+
A custom sitemap `pathFor` receives full bounded data unless `dataFields` names
|
|
52
|
+
its required top-level fields. Built-in path resolution projects only `slug`.
|
|
53
|
+
Custom `PublicPathResolver` implementations can declare `dataFields` for the
|
|
54
|
+
Cloudflare mount to use; omission retains full data. Missing projected keys
|
|
55
|
+
are null and envelope fields, including locale, remain available.
|
|
56
|
+
|
|
57
|
+
Cloudflare's public mount supplies visible Next navigation and HTTP continuation
|
|
58
|
+
links, and serves `/sitemap.xml?part=1&cursor=...` parts automatically. The
|
|
59
|
+
existing preview authorization and public-response cache policy still apply.
|
|
60
|
+
|
|
27
61
|
## WebMCP (opt in)
|
|
28
62
|
|
|
29
63
|
Browsers implementing the draft imperative WebMCP API can expose public Mantle
|
|
@@ -3,12 +3,16 @@ import type { WebSiteConfig } from "../model/WebSiteConfig.js";
|
|
|
3
3
|
export interface ComposeLlmsTxtRequest {
|
|
4
4
|
readonly site: WebSiteConfig;
|
|
5
5
|
/** locale: string → entries with that locale; locale: null →
|
|
6
|
-
* non-localized only
|
|
7
|
-
readonly locale
|
|
6
|
+
* non-localized only; omitted reads all locales for a root page. */
|
|
7
|
+
readonly locale?: string | null;
|
|
8
|
+
/** Root aggregate: read one canonical page, then expand shared entries per locale. */
|
|
9
|
+
readonly locales?: readonly string[];
|
|
10
|
+
readonly cursor?: string;
|
|
11
|
+
readonly limit?: number;
|
|
8
12
|
/** Include public non-localized entries alongside the requested locale. */
|
|
9
13
|
readonly includeUnlocalized?: boolean;
|
|
10
14
|
/** Optional collection limit used by collection-list markdown mirrors. */
|
|
11
15
|
readonly collection?: string;
|
|
12
|
-
readonly pathFor?: (entry: Entry) => string | null;
|
|
16
|
+
readonly pathFor?: (entry: Entry, locale: string) => string | null;
|
|
13
17
|
}
|
|
14
18
|
//# sourceMappingURL=ComposeLlmsTxtRequest.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComposeLlmsTxtRequest.d.ts","sourceRoot":"","sources":["../../src/dto/ComposeLlmsTxtRequest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B;
|
|
1
|
+
{"version":3,"file":"ComposeLlmsTxtRequest.d.ts","sourceRoot":"","sources":["../../src/dto/ComposeLlmsTxtRequest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B;yEACqE;IACrE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,sFAAsF;IACtF,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,2EAA2E;IAC3E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACpE"}
|
|
@@ -6,9 +6,12 @@ export interface ComposeSitemapRequest {
|
|
|
6
6
|
readonly pathFor?: (entry: Entry) => string | readonly string[] | null;
|
|
7
7
|
/** Public routes without a backing Entry, such as home and collection lists. */
|
|
8
8
|
readonly additionalPaths?: readonly string[];
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
11
|
-
* ceiling). */
|
|
9
|
+
/** Entries per part (default 2,000, bounded by the reader's byte budget).
|
|
10
|
+
* Follow nextCursor or serve the sitemap index to retain all URLs. */
|
|
12
11
|
readonly maxUrls?: number;
|
|
12
|
+
readonly cursor?: string;
|
|
13
|
+
/** Fields needed by a custom pathFor; omission preserves full entry data.
|
|
14
|
+
* The default mapper only reads slug and projects automatically. */
|
|
15
|
+
readonly dataFields?: readonly string[];
|
|
13
16
|
}
|
|
14
17
|
//# sourceMappingURL=ComposeSitemapRequest.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComposeSitemapRequest.d.ts","sourceRoot":"","sources":["../../src/dto/ComposeSitemapRequest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IACvE,gFAAgF;IAChF,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C
|
|
1
|
+
{"version":3,"file":"ComposeSitemapRequest.d.ts","sourceRoot":"","sources":["../../src/dto/ComposeSitemapRequest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IACvE,gFAAgF;IAChF,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C;0EACsE;IACtE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;wEACoE;IACpE,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC"}
|
|
@@ -5,6 +5,9 @@ import type { SeoMeta } from "../model/SeoMeta.js";
|
|
|
5
5
|
* list page from current DB state on demand (no KV read).
|
|
6
6
|
*/
|
|
7
7
|
export interface RenderListLiveRequest {
|
|
8
|
+
/** Forward continuation returned by the previous page. Defaults to 50 entries. */
|
|
9
|
+
readonly cursor?: string;
|
|
10
|
+
readonly limit?: number;
|
|
8
11
|
readonly collection: string;
|
|
9
12
|
readonly locale: string;
|
|
10
13
|
/** DB locale filter; null for non-localized collections mounted under a locale URL. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RenderListLiveRequest.d.ts","sourceRoot":"","sources":["../../src/dto/RenderListLiveRequest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,uFAAuF;IACvF,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB"}
|
|
1
|
+
{"version":3,"file":"RenderListLiveRequest.d.ts","sourceRoot":"","sources":["../../src/dto/RenderListLiveRequest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,kFAAkF;IAClF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,uFAAuF;IACvF,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB"}
|
|
@@ -35,6 +35,8 @@ export interface PublicPathResolverConfig {
|
|
|
35
35
|
readonly collectionRoutes: Readonly<Record<string, CollectionRoute>>;
|
|
36
36
|
}
|
|
37
37
|
export interface PublicPathResolver {
|
|
38
|
+
/** Entry data needed for path resolution; omitted custom resolvers receive full data. */
|
|
39
|
+
readonly dataFields?: readonly string[];
|
|
38
40
|
/** Returns `/{locale}/{segment}/{slug}` style path, or `null` if the
|
|
39
41
|
* entry has no public URL under this configuration. */
|
|
40
42
|
forEntry(entry: Entry): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PublicPathResolver.d.ts","sourceRoot":"","sources":["../../src/service/PublicPathResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE9D,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,MAAM,CAMtF;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAIpD;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;kDAE8C;IAC9C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,kBAAkB;IACjC;4DACwD;IACxD,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAAC;IACtC;uCACmC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;CAC3D;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,wBAAwB,GAC/B,kBAAkB,
|
|
1
|
+
{"version":3,"file":"PublicPathResolver.d.ts","sourceRoot":"","sources":["../../src/service/PublicPathResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE9D,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,MAAM,CAMtF;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAIpD;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;kDAE8C;IAC9C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,kBAAkB;IACjC,yFAAyF;IACzF,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC;4DACwD;IACxD,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAAC;IACtC;uCACmC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;CAC3D;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,wBAAwB,GAC/B,kBAAkB,CAoBpB"}
|
|
@@ -15,6 +15,7 @@ export function entryPublicPath(entry) {
|
|
|
15
15
|
export function createPublicPathResolver(config) {
|
|
16
16
|
const routes = config.collectionRoutes;
|
|
17
17
|
return {
|
|
18
|
+
dataFields: ["slug"],
|
|
18
19
|
forEntry(entry) {
|
|
19
20
|
const route = routes[entry.collection];
|
|
20
21
|
if (!route || route.segment === null)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PublicPathResolver.js","sourceRoot":"","sources":["../../src/service/PublicPathResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAc,MAAM,qBAAqB,CAAC;AAE9D,MAAM,UAAU,SAAS,CAAC,KAAoD;IAC5E,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1E,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC,EAAE,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAY;IAC1C,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,KAAK,CAAC,MAAM;QAAE,OAAO,IAAI,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;IACrF,OAAO,IAAI,KAAK,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;AACxC,CAAC;
|
|
1
|
+
{"version":3,"file":"PublicPathResolver.js","sourceRoot":"","sources":["../../src/service/PublicPathResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAc,MAAM,qBAAqB,CAAC;AAE9D,MAAM,UAAU,SAAS,CAAC,KAAoD;IAC5E,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1E,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC,EAAE,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAY;IAC1C,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,KAAK,CAAC,MAAM;QAAE,OAAO,IAAI,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;IACrF,OAAO,IAAI,KAAK,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;AACxC,CAAC;AA6CD,MAAM,UAAU,wBAAwB,CACtC,MAAgC;IAEhC,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC;IACvC,OAAO;QACL,UAAU,EAAE,CAAC,MAAM,CAAC;QACpB,QAAQ,CAAC,KAAY;YACnB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACvC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YAClD,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3D,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAC9C,OAAO,YAAY,IAAI,GAAG,CAAC;YAC7B,CAAC;YACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;YAC9B,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,YAAY,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,YAAY,IAAI,IAAI,EAAE,CAAC;QACpF,CAAC;QACD,QAAQ,CAAC,UAAkB;YACzB,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5B,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -17,4 +17,5 @@ export interface SitemapInput {
|
|
|
17
17
|
readonly entries: readonly SitemapEntry[];
|
|
18
18
|
}
|
|
19
19
|
export declare function serializeSitemap(input: SitemapInput): string;
|
|
20
|
+
export declare function serializeSitemapIndex(site: WebSiteConfig, paths: readonly string[]): string;
|
|
20
21
|
//# sourceMappingURL=SitemapSerializer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SitemapSerializer.d.ts","sourceRoot":"","sources":["../../src/service/SitemapSerializer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAG/D;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;CAC3C;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAgB5D"}
|
|
1
|
+
{"version":3,"file":"SitemapSerializer.d.ts","sourceRoot":"","sources":["../../src/service/SitemapSerializer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAG/D;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;CAC3C;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAgB5D;AAWD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAI3F"}
|
|
@@ -24,4 +24,9 @@ function escapeXml(s) {
|
|
|
24
24
|
.replace(/"/g, """)
|
|
25
25
|
.replace(/'/g, "'");
|
|
26
26
|
}
|
|
27
|
+
export function serializeSitemapIndex(site, paths) {
|
|
28
|
+
return `<?xml version="1.0" encoding="UTF-8"?>\n<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n`
|
|
29
|
+
+ paths.map((path) => ` <sitemap><loc>${escapeXml(absoluteUrl(site.origin ?? "", path))}</loc></sitemap>\n`).join("")
|
|
30
|
+
+ "</sitemapindex>\n";
|
|
31
|
+
}
|
|
27
32
|
//# sourceMappingURL=SitemapSerializer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SitemapSerializer.js","sourceRoot":"","sources":["../../src/service/SitemapSerializer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAoB/C,MAAM,UAAU,gBAAgB,CAAC,KAAmB;IAClD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAChC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,GAAG,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IACnD,GAAG,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;IACzE,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;QACjD,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACpB,GAAG,CAAC,IAAI,CAAC,YAAY,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,KAAK,EAAE,SAAS,EAAE,CAAC;YACrB,GAAG,CAAC,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QAChF,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvB,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtB,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAC/B,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC;SACL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC"}
|
|
1
|
+
{"version":3,"file":"SitemapSerializer.js","sourceRoot":"","sources":["../../src/service/SitemapSerializer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAoB/C,MAAM,UAAU,gBAAgB,CAAC,KAAmB;IAClD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAChC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,GAAG,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IACnD,GAAG,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;IACzE,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;QACjD,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACpB,GAAG,CAAC,IAAI,CAAC,YAAY,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,KAAK,EAAE,SAAS,EAAE,CAAC;YACrB,GAAG,CAAC,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QAChF,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvB,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtB,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAC/B,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC;SACL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAmB,EAAE,KAAwB;IACjF,OAAO,8GAA8G;UACjH,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,mBAAmB,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;UACpH,mBAAmB,CAAC;AAC1B,CAAC"}
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
import type { EntryReader } from "@aotter/mantle-runtime";
|
|
2
2
|
import type { PublicPathResolver } from "../service/PublicPathResolver.js";
|
|
3
3
|
import type { ComposeLlmsTxtRequest } from "../dto/ComposeLlmsTxtRequest.js";
|
|
4
|
-
/**
|
|
5
|
-
* Compose a `/llms.txt` body from currently-published entries.
|
|
6
|
-
*
|
|
7
|
-
* - locale: string → entries with `data.locale === locale`
|
|
8
|
-
* - locale: null → non-localized entries only. Consumers that want
|
|
9
|
-
* a cross-locale aggregate at the root URL should
|
|
10
|
-
* iterate site.locales themselves and concat.
|
|
11
|
-
*/
|
|
4
|
+
/** Compose one bounded discovery page; callers must expose nextCursor. */
|
|
12
5
|
export declare class ComposeLlmsTxtUseCase {
|
|
13
6
|
private readonly reader;
|
|
14
7
|
private readonly paths;
|
|
15
8
|
constructor(reader: EntryReader, paths: PublicPathResolver | null);
|
|
16
|
-
execute(request: ComposeLlmsTxtRequest): Promise<
|
|
9
|
+
execute(request: ComposeLlmsTxtRequest): Promise<{
|
|
10
|
+
body: string | null;
|
|
11
|
+
nextCursor?: string;
|
|
12
|
+
} | null>;
|
|
17
13
|
}
|
|
18
14
|
//# sourceMappingURL=ComposeLlmsTxtUseCase.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComposeLlmsTxtUseCase.d.ts","sourceRoot":"","sources":["../../src/usecase/ComposeLlmsTxtUseCase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAE3E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E
|
|
1
|
+
{"version":3,"file":"ComposeLlmsTxtUseCase.d.ts","sourceRoot":"","sources":["../../src/usecase/ComposeLlmsTxtUseCase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAE3E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E,0EAA0E;AAC1E,qBAAa,qBAAqB;IAE9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBADL,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAG7C,OAAO,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAmB5G"}
|
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import { serializeLlmsTxt } from "../service/MarkdownSerializer.js";
|
|
2
|
-
/**
|
|
3
|
-
* Compose a `/llms.txt` body from currently-published entries.
|
|
4
|
-
*
|
|
5
|
-
* - locale: string → entries with `data.locale === locale`
|
|
6
|
-
* - locale: null → non-localized entries only. Consumers that want
|
|
7
|
-
* a cross-locale aggregate at the root URL should
|
|
8
|
-
* iterate site.locales themselves and concat.
|
|
9
|
-
*/
|
|
2
|
+
/** Compose one bounded discovery page; callers must expose nextCursor. */
|
|
10
3
|
export class ComposeLlmsTxtUseCase {
|
|
11
4
|
reader;
|
|
12
5
|
paths;
|
|
@@ -17,20 +10,22 @@ export class ComposeLlmsTxtUseCase {
|
|
|
17
10
|
async execute(request) {
|
|
18
11
|
if (!this.paths)
|
|
19
12
|
return null;
|
|
20
|
-
const
|
|
21
|
-
locale,
|
|
13
|
+
const page = await this.reader.readPublishedPage({
|
|
14
|
+
locale: request.locale,
|
|
22
15
|
collection: request.collection,
|
|
16
|
+
includeUnlocalized: request.includeUnlocalized,
|
|
17
|
+
cursor: request.cursor,
|
|
18
|
+
limit: request.limit,
|
|
23
19
|
});
|
|
24
|
-
const
|
|
25
|
-
? (await Promise.all([query(request.locale), query(null)])).flat()
|
|
26
|
-
: await query(request.locale);
|
|
27
|
-
const grouped = groupByCollection(entries);
|
|
28
|
-
return serializeLlmsTxt({
|
|
20
|
+
const bodies = (request.locales ?? [request.locale ?? ""]).map((locale) => serializeLlmsTxt({
|
|
29
21
|
site: request.site,
|
|
30
|
-
locale
|
|
31
|
-
entriesByCollection:
|
|
32
|
-
|
|
33
|
-
|
|
22
|
+
locale,
|
|
23
|
+
entriesByCollection: groupByCollection(request.locales
|
|
24
|
+
? page.rows.filter((entry) => !entry.locale || entry.locale === locale)
|
|
25
|
+
: page.rows),
|
|
26
|
+
pathFor: (entry) => request.pathFor ? request.pathFor(entry, locale) : this.paths.forEntry(entry),
|
|
27
|
+
})).filter((body) => body !== null);
|
|
28
|
+
return { body: bodies.length ? bodies.join("\n---\n\n") : null, nextCursor: page.nextCursor };
|
|
34
29
|
}
|
|
35
30
|
}
|
|
36
31
|
function groupByCollection(entries) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComposeLlmsTxtUseCase.js","sourceRoot":"","sources":["../../src/usecase/ComposeLlmsTxtUseCase.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAGpE
|
|
1
|
+
{"version":3,"file":"ComposeLlmsTxtUseCase.js","sourceRoot":"","sources":["../../src/usecase/ComposeLlmsTxtUseCase.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAGpE,0EAA0E;AAC1E,MAAM,OAAO,qBAAqB;IAEb;IACA;IAFnB,YACmB,MAAmB,EACnB,KAAgC;QADhC,WAAM,GAAN,MAAM,CAAa;QACnB,UAAK,GAAL,KAAK,CAA2B;IAChD,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,OAA8B;QAC1C,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAC/C,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;YAC9C,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,gBAAgB,CAAC;YAC1F,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM;YACN,mBAAmB,EAAE,iBAAiB,CAAC,OAAO,CAAC,OAAO;gBACpD,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC;gBACvE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YACd,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;SACnG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACpD,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;IAChG,CAAC;CACF;AAED,SAAS,iBAAiB,CAAC,OAAyB;IAClD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAmB,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QAClC,IAAI,GAAG;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;YAChB,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type { EntryReader } from "@aotter/mantle-runtime";
|
|
2
2
|
import type { ComposeSitemapRequest } from "../dto/ComposeSitemapRequest.js";
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
* collections + locales. Result is XML text; consumer routes it as
|
|
6
|
-
* `application/xml`. See ComposeSitemapRequest for the pathFor +
|
|
7
|
-
* maxUrls knobs.
|
|
8
|
-
*/
|
|
9
|
-
export declare const SITEMAP_MAX_URLS_DEFAULT = 50000;
|
|
3
|
+
/** Entries per sitemap part; the protocol ceiling remains 50,000 URLs. */
|
|
4
|
+
export declare const SITEMAP_MAX_URLS_DEFAULT = 2000;
|
|
10
5
|
export declare class ComposeSitemapUseCase {
|
|
11
6
|
private readonly reader;
|
|
12
7
|
constructor(reader: EntryReader);
|
|
13
|
-
execute(request: ComposeSitemapRequest): Promise<
|
|
8
|
+
execute(request: ComposeSitemapRequest): Promise<{
|
|
9
|
+
body: string;
|
|
10
|
+
nextCursor?: string;
|
|
11
|
+
}>;
|
|
12
|
+
/** Walk bounded metadata pages to derive the exact part boundaries. No entry cache.
|
|
13
|
+
* ponytail: O(N) metadata reads per index MISS; persist part boundaries only if this dominates. */
|
|
14
|
+
index(request: ComposeSitemapRequest, partPath: (cursor?: string) => string): Promise<string>;
|
|
14
15
|
}
|
|
15
16
|
//# sourceMappingURL=ComposeSitemapUseCase.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComposeSitemapUseCase.d.ts","sourceRoot":"","sources":["../../src/usecase/ComposeSitemapUseCase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E
|
|
1
|
+
{"version":3,"file":"ComposeSitemapUseCase.d.ts","sourceRoot":"","sources":["../../src/usecase/ComposeSitemapUseCase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E,0EAA0E;AAC1E,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAE7C,qBAAa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,WAAW;IAE1C,OAAO,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA6B7F;uGACmG;IAC7F,KAAK,CAAC,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAiBpG"}
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { entryPublicPath } from "../service/PublicPathResolver.js";
|
|
2
|
-
import { serializeSitemap } from "../service/SitemapSerializer.js";
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
* collections + locales. Result is XML text; consumer routes it as
|
|
6
|
-
* `application/xml`. See ComposeSitemapRequest for the pathFor +
|
|
7
|
-
* maxUrls knobs.
|
|
8
|
-
*/
|
|
9
|
-
export const SITEMAP_MAX_URLS_DEFAULT = 50000;
|
|
2
|
+
import { serializeSitemap, serializeSitemapIndex } from "../service/SitemapSerializer.js";
|
|
3
|
+
/** Entries per sitemap part; the protocol ceiling remains 50,000 URLs. */
|
|
4
|
+
export const SITEMAP_MAX_URLS_DEFAULT = 2000;
|
|
10
5
|
export class ComposeSitemapUseCase {
|
|
11
6
|
reader;
|
|
12
7
|
constructor(reader) {
|
|
@@ -14,7 +9,10 @@ export class ComposeSitemapUseCase {
|
|
|
14
9
|
}
|
|
15
10
|
async execute(request) {
|
|
16
11
|
const cap = request.maxUrls ?? SITEMAP_MAX_URLS_DEFAULT;
|
|
17
|
-
const
|
|
12
|
+
const page = await this.reader.readPublishedPage({
|
|
13
|
+
limit: cap, cursor: request.cursor,
|
|
14
|
+
dataFields: request.dataFields ?? (request.pathFor ? undefined : ["slug"]),
|
|
15
|
+
});
|
|
18
16
|
const mapper = request.pathFor ?? entryPublicPath;
|
|
19
17
|
const entries = [];
|
|
20
18
|
const seen = new Set();
|
|
@@ -24,15 +22,44 @@ export class ComposeSitemapUseCase {
|
|
|
24
22
|
seen.add(path);
|
|
25
23
|
entries.push(entry ? { entry, path } : { path });
|
|
26
24
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
if (!request.cursor)
|
|
26
|
+
for (const path of request.additionalPaths ?? [])
|
|
27
|
+
push(path);
|
|
28
|
+
for (const e of page.rows) {
|
|
30
29
|
const mapped = mapper(e);
|
|
31
30
|
for (const path of mapped === null ? [] : typeof mapped === "string" ? [mapped] : mapped) {
|
|
32
31
|
push(path, e);
|
|
33
32
|
}
|
|
34
33
|
}
|
|
35
|
-
|
|
34
|
+
if (entries.length > 50_000)
|
|
35
|
+
throw new Error("sitemap part exceeds 50,000 URLs; reduce maxUrls");
|
|
36
|
+
const body = serializeSitemap({ site: request.site, entries });
|
|
37
|
+
if (new TextEncoder().encode(body).byteLength > 50 * 1024 * 1024) {
|
|
38
|
+
throw new Error("sitemap part exceeds 50 MiB; reduce maxUrls");
|
|
39
|
+
}
|
|
40
|
+
return { body, nextCursor: page.nextCursor };
|
|
41
|
+
}
|
|
42
|
+
/** Walk bounded metadata pages to derive the exact part boundaries. No entry cache.
|
|
43
|
+
* ponytail: O(N) metadata reads per index MISS; persist part boundaries only if this dominates. */
|
|
44
|
+
async index(request, partPath) {
|
|
45
|
+
const paths = [partPath()];
|
|
46
|
+
let cursor;
|
|
47
|
+
do {
|
|
48
|
+
const page = await this.reader.readPublishedPage({
|
|
49
|
+
limit: request.maxUrls ?? SITEMAP_MAX_URLS_DEFAULT,
|
|
50
|
+
dataFields: request.dataFields ?? (request.pathFor ? undefined : ["slug"]),
|
|
51
|
+
cursor,
|
|
52
|
+
});
|
|
53
|
+
cursor = page.nextCursor;
|
|
54
|
+
if (cursor)
|
|
55
|
+
paths.push(partPath(cursor));
|
|
56
|
+
if (paths.length > 50_000)
|
|
57
|
+
throw new Error("sitemap index exceeds 50,000 parts");
|
|
58
|
+
} while (cursor);
|
|
59
|
+
const body = serializeSitemapIndex(request.site, paths);
|
|
60
|
+
if (new TextEncoder().encode(body).byteLength > 50 * 1024 * 1024)
|
|
61
|
+
throw new Error("sitemap index exceeds 50 MiB");
|
|
62
|
+
return body;
|
|
36
63
|
}
|
|
37
64
|
}
|
|
38
65
|
//# sourceMappingURL=ComposeSitemapUseCase.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComposeSitemapUseCase.js","sourceRoot":"","sources":["../../src/usecase/ComposeSitemapUseCase.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"ComposeSitemapUseCase.js","sourceRoot":"","sources":["../../src/usecase/ComposeSitemapUseCase.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,9 @@ export declare class RenderListLiveUseCase {
|
|
|
20
20
|
private readonly schemas;
|
|
21
21
|
private readonly mediaAssets;
|
|
22
22
|
constructor(reader: EntryReader, templates: TemplateRegistry, schemas: ReadonlyMap<string, SchemaManifest>, mediaAssets?: MediaAssetResolver | null);
|
|
23
|
-
execute(request: RenderListLiveRequest): Promise<
|
|
23
|
+
execute(request: RenderListLiveRequest): Promise<{
|
|
24
|
+
html: string;
|
|
25
|
+
nextCursor?: string;
|
|
26
|
+
} | null>;
|
|
24
27
|
}
|
|
25
28
|
//# sourceMappingURL=RenderListLiveUseCase.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RenderListLiveUseCase.d.ts","sourceRoot":"","sources":["../../src/usecase/RenderListLiveUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,uCAAuC,CAAC;AAE/C;;;;;;;;;;GAUG;AACH,qBAAa,qBAAqB;IAE9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAHX,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,gBAAgB,EAC3B,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,EAC5C,WAAW,GAAE,kBAAkB,GAAG,IAAW;IAG1D,OAAO,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"RenderListLiveUseCase.d.ts","sourceRoot":"","sources":["../../src/usecase/RenderListLiveUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,uCAAuC,CAAC;AAE/C;;;;;;;;;;GAUG;AACH,qBAAa,qBAAqB;IAE9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAHX,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,gBAAgB,EAC3B,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,EAC5C,WAAW,GAAE,kBAAkB,GAAG,IAAW;IAG1D,OAAO,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAsBrG"}
|
|
@@ -24,15 +24,17 @@ export class RenderListLiveUseCase {
|
|
|
24
24
|
this.mediaAssets = mediaAssets;
|
|
25
25
|
}
|
|
26
26
|
async execute(request) {
|
|
27
|
-
const
|
|
27
|
+
const page = await this.reader.readPublishedPage({
|
|
28
|
+
cursor: request.cursor,
|
|
29
|
+
limit: request.limit,
|
|
28
30
|
collection: request.collection,
|
|
29
31
|
locale: request.contentLocale === undefined ? request.locale : request.contentLocale,
|
|
30
32
|
});
|
|
31
|
-
const entries = await joinParentForList(this.reader, this.schemas,
|
|
33
|
+
const entries = await joinParentForList(this.reader, this.schemas, page.rows, {
|
|
32
34
|
parentStatus: "published",
|
|
33
35
|
});
|
|
34
36
|
const mediaAssets = await resolveMediaAssetsForEntries(this.mediaAssets, entries);
|
|
35
|
-
|
|
37
|
+
const html = renderListHtml({
|
|
36
38
|
collection: request.collection,
|
|
37
39
|
locale: request.locale,
|
|
38
40
|
entries,
|
|
@@ -41,6 +43,7 @@ export class RenderListLiveUseCase {
|
|
|
41
43
|
mediaAssets,
|
|
42
44
|
seo: request.seo,
|
|
43
45
|
});
|
|
46
|
+
return html === null ? null : { html, nextCursor: page.nextCursor };
|
|
44
47
|
}
|
|
45
48
|
}
|
|
46
49
|
//# sourceMappingURL=RenderListLiveUseCase.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RenderListLiveUseCase.js","sourceRoot":"","sources":["../../src/usecase/RenderListLiveUseCase.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,wBAAwB,CAAC;AAE7E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EACL,4BAA4B,GAE7B,MAAM,uCAAuC,CAAC;AAE/C;;;;;;;;;;GAUG;AACH,MAAM,OAAO,qBAAqB;IAEb;IACA;IACA;IACA;IAJnB,YACmB,MAAmB,EACnB,SAA2B,EAC3B,OAA4C,EAC5C,cAAyC,IAAI;QAH7C,WAAM,GAAN,MAAM,CAAa;QACnB,cAAS,GAAT,SAAS,CAAkB;QAC3B,YAAO,GAAP,OAAO,CAAqC;QAC5C,gBAAW,GAAX,WAAW,CAAkC;IAC7D,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,OAA8B;QAC1C,MAAM,
|
|
1
|
+
{"version":3,"file":"RenderListLiveUseCase.js","sourceRoot":"","sources":["../../src/usecase/RenderListLiveUseCase.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,wBAAwB,CAAC;AAE7E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EACL,4BAA4B,GAE7B,MAAM,uCAAuC,CAAC;AAE/C;;;;;;;;;;GAUG;AACH,MAAM,OAAO,qBAAqB;IAEb;IACA;IACA;IACA;IAJnB,YACmB,MAAmB,EACnB,SAA2B,EAC3B,OAA4C,EAC5C,cAAyC,IAAI;QAH7C,WAAM,GAAN,MAAM,CAAa;QACnB,cAAS,GAAT,SAAS,CAAkB;QAC3B,YAAO,GAAP,OAAO,CAAqC;QAC5C,gBAAW,GAAX,WAAW,CAAkC;IAC7D,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,OAA8B;QAC1C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAC/C,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,MAAM,EAAE,OAAO,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa;SACrF,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE;YAC5E,YAAY,EAAE,WAAW;SAC1B,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,4BAA4B,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAClF,MAAM,IAAI,GAAG,cAAc,CAAC;YAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO;YACP,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,WAAW;YACX,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAC;QACH,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;IACtE,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aotter/mantle-web",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.17",
|
|
4
4
|
"description": "Optional public document composition for Mantle: HTML, Markdown, llms.txt, sitemap, SEO, and preview.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://mantle.tools/",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"README.md"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@aotter/mantle-runtime": "0.1.0-alpha.
|
|
37
|
-
"@aotter/mantle-spec": "0.1.0-alpha.
|
|
36
|
+
"@aotter/mantle-runtime": "0.1.0-alpha.17",
|
|
37
|
+
"@aotter/mantle-spec": "0.1.0-alpha.17"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^26",
|