@elytracms/next 0.0.80 → 0.0.82
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/dist/index.d.ts +260 -59
- package/dist/index.js +106 -49
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ComponentRegistry } from '@elytracms/core/component-registry';
|
|
2
2
|
export { defineComponent } from '@elytracms/core/component-registry';
|
|
3
|
-
import { basePrimitives, getImplementation,
|
|
3
|
+
import { basePrimitives, getImplementation, renderDocumentBodyItems, documentBodyItems, ImageManifest, serializeListingQuery, RenderErrorBoundary, documentBodyRichTextValues, documentBodyCompositionNodes, richTextEmbedsInValue, collectReferencedAssetIds, collectRichTextRefsInValue, collectReferencedRelations, collectReferencedListings, collectReferencedRichTextLinks, normalizeImageSource } from '@elytracms/core/runtime-renderer';
|
|
4
4
|
import { isValidElement } from 'react';
|
|
5
5
|
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
import { cacheTags, isSectionSourceId, parseCmsSourceQueryConfig, listQueryOfCmsConfig, isDocumentHistory, resolvedAsset, createContentClient, createContentContext } from '@elytracms/core/content';
|
|
7
|
-
import { documentKey,
|
|
8
|
-
export { documentSchema, fallbackHomeRoutes, localeConfigSchema, mergeRouteRecords, redirectRecordSchema, routeRecordSchema } from '@elytracms/core/cms-core';
|
|
7
|
+
import { documentKey, splitLocalePath, hierarchyMount, composePath, localeUrlPath, mergeRouteRecords, fallbackHomeRoutes, presentationBodyFields, splitPath, documentSchema, redirectRecordSchema } from '@elytracms/core/cms-core';
|
|
8
|
+
export { documentSchema, fallbackHomeRoutes, localeConfigSchema, localeUrlPath, mergeRouteRecords, redirectRecordSchema, routeRecordSchema, splitLocalePath } from '@elytracms/core/cms-core';
|
|
9
9
|
import { revalidateTag, unstable_cache } from 'next/cache';
|
|
10
10
|
import { draftMode } from 'next/headers';
|
|
11
11
|
import { redirect, notFound, permanentRedirect } from 'next/navigation';
|
|
@@ -148,11 +148,16 @@ async function CanvasRenderer(props) {
|
|
|
148
148
|
};
|
|
149
149
|
const document = result.document;
|
|
150
150
|
if (document) {
|
|
151
|
-
|
|
152
|
-
return /* @__PURE__ */ jsx(Fragment, { children: renderComposition(composition, ctx) });
|
|
151
|
+
return /* @__PURE__ */ jsx(Fragment, { children: renderDocumentBodyItems(bodyItemsOf(document, props.presentation), ctx) });
|
|
153
152
|
}
|
|
154
153
|
return /* @__PURE__ */ jsx(MissingDocumentFallback, {});
|
|
155
154
|
}
|
|
155
|
+
function bodyItemsOf(document, presentation) {
|
|
156
|
+
if (!document) return [];
|
|
157
|
+
const fields = presentation?.body ?? [];
|
|
158
|
+
if (fields.length > 0) return fields.flatMap((name) => documentBodyItems(document[name]));
|
|
159
|
+
return documentBodyItems(compositionOf(document));
|
|
160
|
+
}
|
|
156
161
|
function compositionOf(document) {
|
|
157
162
|
const body = document["body"];
|
|
158
163
|
if (Array.isArray(body) || isComponentNodeValue(body)) return body;
|
|
@@ -164,11 +169,8 @@ function compositionOf(document) {
|
|
|
164
169
|
}
|
|
165
170
|
return void 0;
|
|
166
171
|
}
|
|
167
|
-
function compositionNodesOf(document) {
|
|
168
|
-
|
|
169
|
-
const composition = compositionOf(document);
|
|
170
|
-
const candidates = Array.isArray(composition) ? composition : [composition];
|
|
171
|
-
return candidates.filter((node) => isComponentNodeValue(node));
|
|
172
|
+
function compositionNodesOf(document, presentation) {
|
|
173
|
+
return documentBodyCompositionNodes(bodyItemsOf(document, presentation));
|
|
172
174
|
}
|
|
173
175
|
function isComponentNodeValue(value) {
|
|
174
176
|
return typeof value === "object" && value !== null && typeof value.id === "string" && typeof value.componentId === "string";
|
|
@@ -219,9 +221,8 @@ function materializeSourcePayloads(input) {
|
|
|
219
221
|
}
|
|
220
222
|
return { payloads, tags };
|
|
221
223
|
}
|
|
222
|
-
var DEFAULT_LOCALES = { default: "en", locales: ["en"] };
|
|
223
224
|
function createStaticContentSource(data) {
|
|
224
|
-
const locales = data.locales
|
|
225
|
+
const locales = data.locales;
|
|
225
226
|
const routes = data.routes ?? [];
|
|
226
227
|
const redirects = data.redirects ?? [];
|
|
227
228
|
const assetUrl = data.assetUrl ?? ((asset) => `asset://unresolved/${asset.storageKey}`);
|
|
@@ -265,10 +266,15 @@ function createStaticContentSource(data) {
|
|
|
265
266
|
// dimensions. Baked into the (serializable) render outcome by the route
|
|
266
267
|
// helper, so a cached page keeps its images during a backend outage.
|
|
267
268
|
assets: () => [...assets.values()].map((record2) => resolvedAsset(record2, record2.url ?? assetUrl(record2))),
|
|
268
|
-
...data.sources ? { sources: data.sources } : {}
|
|
269
|
+
...data.sources ? { sources: data.sources } : {},
|
|
270
|
+
// EC-499: the schema the route helper reads a collection's declared
|
|
271
|
+
// `presentation` from (which field is the delivery body, which component
|
|
272
|
+
// wraps it). Already prefetched for the lookup above — exposing it costs
|
|
273
|
+
// nothing and keeps the declaration reachable without a second wiring seam.
|
|
274
|
+
...data.collections ? { collections: data.collections } : {}
|
|
269
275
|
};
|
|
270
276
|
}
|
|
271
|
-
async function createContentSnapshot(adapter, projectId, options
|
|
277
|
+
async function createContentSnapshot(adapter, projectId, options) {
|
|
272
278
|
const schema = await adapter.cms.findSchema(projectId);
|
|
273
279
|
const documentRecords = await adapter.cms.listDocuments(projectId);
|
|
274
280
|
const versionRecords = await adapter.cms.listAllDocumentVersions(projectId);
|
|
@@ -297,7 +303,7 @@ async function createContentSnapshot(adapter, projectId, options = {}) {
|
|
|
297
303
|
});
|
|
298
304
|
return createStaticContentSource({
|
|
299
305
|
projectId,
|
|
300
|
-
|
|
306
|
+
locales: options.locales,
|
|
301
307
|
...options.routes ? { routes: options.routes } : {},
|
|
302
308
|
redirects: options.redirects ? [...options.redirects] : redirects,
|
|
303
309
|
...options.sources ? { sources: options.sources } : {},
|
|
@@ -307,37 +313,57 @@ async function createContentSnapshot(adapter, projectId, options = {}) {
|
|
|
307
313
|
assetUrl: (asset) => adapter.blobs.url(asset.storageKey)
|
|
308
314
|
});
|
|
309
315
|
}
|
|
316
|
+
function canvasWrapContext(result, info) {
|
|
317
|
+
const collection = result.document?.collection;
|
|
318
|
+
return {
|
|
319
|
+
...info,
|
|
320
|
+
...collection !== void 0 ? { collection } : {},
|
|
321
|
+
document: result.document,
|
|
322
|
+
result
|
|
323
|
+
};
|
|
324
|
+
}
|
|
310
325
|
function pathFromSlug(slug) {
|
|
311
326
|
return "/" + (slug ?? []).join("/");
|
|
312
327
|
}
|
|
313
|
-
function
|
|
314
|
-
const segments = splitPath(url);
|
|
315
|
-
const first = segments[0];
|
|
316
|
-
if (first !== void 0 && first !== locales.default && locales.locales.includes(first)) {
|
|
317
|
-
return { locale: first, path: "/" + segments.slice(1).join("/") };
|
|
318
|
-
}
|
|
319
|
-
return { locale: locales.default, path: "/" + segments.join("/") };
|
|
320
|
-
}
|
|
321
|
-
function scopeAssetsToPage(allAssets, registry, result, resolveRelation) {
|
|
328
|
+
function scopeAssetsToPage(allAssets, registry, result, body, resolveRelation) {
|
|
322
329
|
if (allAssets.length === 0) return allAssets;
|
|
323
330
|
const ids = /* @__PURE__ */ new Set();
|
|
324
331
|
const seen = /* @__PURE__ */ new Set();
|
|
325
|
-
for (const node of
|
|
332
|
+
for (const node of body.nodes) {
|
|
326
333
|
collectReferencedAssetIds(node, registry, ids, resolveRelation, seen);
|
|
327
334
|
}
|
|
335
|
+
for (const value of body.richTexts) {
|
|
336
|
+
collectRichTextRefsInValue(value, { onAsset: (id) => ids.add(id) });
|
|
337
|
+
}
|
|
328
338
|
const ogImage = result.document?.["seoOgImage"];
|
|
329
339
|
const ogImageId = typeof ogImage === "string" ? ogImage : ogImage && typeof ogImage === "object" && typeof ogImage.id === "string" ? ogImage.id : null;
|
|
330
340
|
if (ogImageId) ids.add(ogImageId);
|
|
331
341
|
return ids.size === 0 ? [] : allAssets.filter((asset) => ids.has(asset.id));
|
|
332
342
|
}
|
|
333
|
-
function
|
|
334
|
-
|
|
343
|
+
function pageBodyOf(result, presentation) {
|
|
344
|
+
const items2 = bodyItemsOf(result.document, presentation);
|
|
345
|
+
const richTexts = documentBodyRichTextValues(items2);
|
|
346
|
+
return {
|
|
347
|
+
nodes: [
|
|
348
|
+
...documentBodyCompositionNodes(items2),
|
|
349
|
+
...richTexts.flatMap((value) => richTextEmbedsInValue(value))
|
|
350
|
+
],
|
|
351
|
+
richTexts
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
function presentationFor(source, result) {
|
|
355
|
+
const collectionId = result.document?.collection;
|
|
356
|
+
if (!collectionId || !source.collections) return void 0;
|
|
357
|
+
const collection = source.collections.find((candidate) => candidate.id === collectionId);
|
|
358
|
+
if (!collection?.presentation) return void 0;
|
|
359
|
+
const body = presentationBodyFields(collection);
|
|
360
|
+
return body.length > 0 ? { body: [...body] } : void 0;
|
|
335
361
|
}
|
|
336
|
-
function populatePageRelations(
|
|
362
|
+
function populatePageRelations(body, client, registry) {
|
|
337
363
|
if (!registry) return { relations: {}, docKeys: [] };
|
|
338
364
|
const refKeys = /* @__PURE__ */ new Set();
|
|
339
365
|
const relations = collectReferencedRelations(
|
|
340
|
-
|
|
366
|
+
body.nodes,
|
|
341
367
|
registry,
|
|
342
368
|
(ref) => client.resolveRelation(ref),
|
|
343
369
|
{},
|
|
@@ -345,11 +371,11 @@ function populatePageRelations(result, client, registry) {
|
|
|
345
371
|
);
|
|
346
372
|
return { relations, docKeys: [...refKeys] };
|
|
347
373
|
}
|
|
348
|
-
function populatePageListings(
|
|
374
|
+
function populatePageListings(body, client, registry) {
|
|
349
375
|
if (!registry) return { listings: {}, tags: [] };
|
|
350
376
|
const tags = [];
|
|
351
377
|
const listings = collectReferencedListings(
|
|
352
|
-
|
|
378
|
+
body.nodes,
|
|
353
379
|
registry,
|
|
354
380
|
(query) => {
|
|
355
381
|
const listed = client.listDocuments(query.collection, {
|
|
@@ -367,13 +393,20 @@ function populatePageListings(result, client, registry) {
|
|
|
367
393
|
);
|
|
368
394
|
return { listings, tags };
|
|
369
395
|
}
|
|
370
|
-
function populatePageLinks(
|
|
396
|
+
function populatePageLinks(body, client, registry) {
|
|
371
397
|
if (!registry) return { links: {}, docKeys: [] };
|
|
372
398
|
const refs = collectReferencedRichTextLinks(
|
|
373
|
-
|
|
399
|
+
body.nodes,
|
|
374
400
|
registry,
|
|
375
401
|
(ref) => client.resolveRelation(ref)
|
|
376
402
|
);
|
|
403
|
+
for (const value of body.richTexts) {
|
|
404
|
+
collectRichTextRefsInValue(value, {
|
|
405
|
+
onLink: (ref) => {
|
|
406
|
+
refs[`${ref.collection}:${ref.id}`] = ref;
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
}
|
|
377
410
|
const links = {};
|
|
378
411
|
for (const [key, ref] of Object.entries(refs)) {
|
|
379
412
|
const url = client.resolveLink(ref);
|
|
@@ -416,11 +449,14 @@ async function resolveCanvasPage(source, url, perspective, options = {}) {
|
|
|
416
449
|
});
|
|
417
450
|
payloads = { ...payloads, ...custom };
|
|
418
451
|
}
|
|
452
|
+
const presentation = presentationFor(source, result);
|
|
453
|
+
const body = pageBodyOf(result, presentation);
|
|
419
454
|
const allAssets = source.assets?.() ?? [];
|
|
420
455
|
const bakedAssets = options.registry ? scopeAssetsToPage(
|
|
421
456
|
allAssets,
|
|
422
457
|
options.registry,
|
|
423
458
|
result,
|
|
459
|
+
body,
|
|
424
460
|
(ref) => client.resolveRelation(ref)
|
|
425
461
|
) : allAssets;
|
|
426
462
|
const assetTags = cacheTags({
|
|
@@ -428,17 +464,17 @@ async function resolveCanvasPage(source, url, perspective, options = {}) {
|
|
|
428
464
|
locale: result.tags.locale
|
|
429
465
|
});
|
|
430
466
|
const { relations, docKeys: relationDocKeys } = populatePageRelations(
|
|
431
|
-
|
|
467
|
+
body,
|
|
432
468
|
client,
|
|
433
469
|
options.registry
|
|
434
470
|
);
|
|
435
471
|
const relationTags = cacheTags({ docs: relationDocKeys, locale: result.tags.locale });
|
|
436
472
|
const { listings, tags: listingTags } = populatePageListings(
|
|
437
|
-
|
|
473
|
+
body,
|
|
438
474
|
client,
|
|
439
475
|
options.registry
|
|
440
476
|
);
|
|
441
|
-
const { links, docKeys: linkDocKeys } = populatePageLinks(
|
|
477
|
+
const { links, docKeys: linkDocKeys } = populatePageLinks(body, client, options.registry);
|
|
442
478
|
const linkTags = cacheTags({ docs: linkDocKeys, locale: result.tags.locale });
|
|
443
479
|
return {
|
|
444
480
|
kind: "render",
|
|
@@ -448,6 +484,7 @@ async function resolveCanvasPage(source, url, perspective, options = {}) {
|
|
|
448
484
|
relations,
|
|
449
485
|
listings,
|
|
450
486
|
links,
|
|
487
|
+
...presentation ? { presentation } : {},
|
|
451
488
|
tags: mergeCacheTags(
|
|
452
489
|
result.tags,
|
|
453
490
|
...extraTags,
|
|
@@ -606,8 +643,8 @@ function createCanvasRoute(options) {
|
|
|
606
643
|
return outcome.permanent ? permanentRedirect(outcome.target) : redirect(outcome.target);
|
|
607
644
|
case "not-found":
|
|
608
645
|
return notFound();
|
|
609
|
-
case "render":
|
|
610
|
-
|
|
646
|
+
case "render": {
|
|
647
|
+
const rendered = /* @__PURE__ */ jsx(
|
|
611
648
|
CanvasRenderer,
|
|
612
649
|
{
|
|
613
650
|
result: outcome.result,
|
|
@@ -616,9 +653,13 @@ function createCanvasRoute(options) {
|
|
|
616
653
|
assets: outcome.assets,
|
|
617
654
|
relations: outcome.relations,
|
|
618
655
|
listings: outcome.listings,
|
|
619
|
-
links: outcome.links
|
|
656
|
+
links: outcome.links,
|
|
657
|
+
presentation: outcome.presentation
|
|
620
658
|
}
|
|
621
659
|
);
|
|
660
|
+
if (!options.wrap) return rendered;
|
|
661
|
+
return options.wrap(rendered, canvasWrapContext(outcome.result, { url, perspective }));
|
|
662
|
+
}
|
|
622
663
|
}
|
|
623
664
|
};
|
|
624
665
|
const generateMetadata = async (props) => {
|
|
@@ -653,10 +694,8 @@ function fillPattern(pattern, params) {
|
|
|
653
694
|
}
|
|
654
695
|
return "/" + segments.join("/");
|
|
655
696
|
}
|
|
656
|
-
function
|
|
657
|
-
|
|
658
|
-
if (locale === defaultLocale) return origin + path;
|
|
659
|
-
return origin + (path === "/" ? `/${locale}` : `/${locale}${path}`);
|
|
697
|
+
function originOf(baseUrl) {
|
|
698
|
+
return baseUrl.replace(/\/+$/, "");
|
|
660
699
|
}
|
|
661
700
|
function canvasSitemapEntries(source, options) {
|
|
662
701
|
const routes = options.routes ?? source.routes ?? [];
|
|
@@ -721,14 +760,32 @@ function canvasSitemapEntries(source, options) {
|
|
|
721
760
|
paths.push(path);
|
|
722
761
|
}
|
|
723
762
|
}
|
|
763
|
+
let unresolved = 0;
|
|
724
764
|
for (const path of paths) {
|
|
725
765
|
const result = client.resolvePage(path, locale);
|
|
726
|
-
if (result.status !== "ok")
|
|
766
|
+
if (result.status !== "ok") {
|
|
767
|
+
if (result.status !== "redirect") unresolved += 1;
|
|
768
|
+
continue;
|
|
769
|
+
}
|
|
727
770
|
if (result.document?.["seoNoindex"] === true) continue;
|
|
771
|
+
const { urlPath, addressable } = localeUrlPath(path, locale, locales);
|
|
772
|
+
if (!addressable) {
|
|
773
|
+
skip(
|
|
774
|
+
route,
|
|
775
|
+
`"${path}" (locale "${locale}") has no addressable URL \u2014 its first segment is read as a locale prefix`
|
|
776
|
+
);
|
|
777
|
+
continue;
|
|
778
|
+
}
|
|
728
779
|
const perLocale = byPath.get(path) ?? /* @__PURE__ */ new Map();
|
|
729
|
-
perLocale.set(locale,
|
|
780
|
+
perLocale.set(locale, originOf(options.baseUrl) + urlPath);
|
|
730
781
|
byPath.set(path, perLocale);
|
|
731
782
|
}
|
|
783
|
+
if (mount && paths.length > 0 && unresolved === paths.length) {
|
|
784
|
+
skip(
|
|
785
|
+
route,
|
|
786
|
+
`hierarchy mount over "${mount.collection}" composed ${paths.length} path(s) in locale "${locale}", none of which the resolver serves`
|
|
787
|
+
);
|
|
788
|
+
}
|
|
732
789
|
}
|
|
733
790
|
}
|
|
734
791
|
const entries = [];
|
|
@@ -810,7 +867,7 @@ function createRevalidateRoute(options) {
|
|
|
810
867
|
{ status: evaluation.status, headers: cors }
|
|
811
868
|
);
|
|
812
869
|
}
|
|
813
|
-
for (const tag of evaluation.payload.tags) revalidateTag(tag,
|
|
870
|
+
for (const tag of evaluation.payload.tags) revalidateTag(tag, { expire: 0 });
|
|
814
871
|
return Response.json({ revalidated: evaluation.payload.tags }, { headers: cors });
|
|
815
872
|
},
|
|
816
873
|
async OPTIONS() {
|
|
@@ -914,8 +971,8 @@ function elytraHostImage(options = {}) {
|
|
|
914
971
|
}
|
|
915
972
|
|
|
916
973
|
// src/full-bleed.ts
|
|
917
|
-
function firstBlockFullBleed(document, registry) {
|
|
918
|
-
const first = compositionNodesOf(document)[0];
|
|
974
|
+
function firstBlockFullBleed(document, registry, presentation) {
|
|
975
|
+
const first = compositionNodesOf(document, presentation)[0];
|
|
919
976
|
if (!first) return false;
|
|
920
977
|
return registry.getManifest(first.componentId)?.presentation?.fullBleed === true;
|
|
921
978
|
}
|
|
@@ -1299,6 +1356,6 @@ function createElytraHost(options) {
|
|
|
1299
1356
|
}
|
|
1300
1357
|
var PACKAGE = "@elytracms/next";
|
|
1301
1358
|
|
|
1302
|
-
export { CanvasRenderer, ELYTRA_HOST_ENV_KEYS, ElytraImage, PACKAGE, REVALIDATE_SIGNATURE_HEADER, assembleLiveSource, canvasPageMetadata, canvasSitemapEntries, collectBindingSourceIds, collectionCacheTag, createAssetImageLoader, createBindingResolver, createCanvasRoute, createCanvasSitemap, createContentSnapshot, createElytraHost, createPreviewDisableRoute, createPreviewRoute, createRevalidateRoute, createStaticContentSource, defaultBindingPayloads, defineHostComponents, docCacheTag, elytraHostImage, evaluatePreviewRequest, evaluateRevalidateRequest, firstBlockFullBleed, isSourcePayloadError, loadCachedEntry, loadLiveContent, materializeSourcePayloads, mergeCacheTags, nextCacheTags, nextImagePrimitive, pathFromSlug, projectSweepTag, resolveCanvasPage, resolveGlobals, resolveHostEnv, resolvePayloadToken, revalidatePayloadSchema, routeCacheTag, safeRedirectTarget, scopeCacheTag, signRevalidateBody, sourcePayloadError
|
|
1359
|
+
export { CanvasRenderer, ELYTRA_HOST_ENV_KEYS, ElytraImage, PACKAGE, REVALIDATE_SIGNATURE_HEADER, assembleLiveSource, bodyItemsOf, canvasPageMetadata, canvasSitemapEntries, collectBindingSourceIds, collectionCacheTag, createAssetImageLoader, createBindingResolver, createCanvasRoute, createCanvasSitemap, createContentSnapshot, createElytraHost, createPreviewDisableRoute, createPreviewRoute, createRevalidateRoute, createStaticContentSource, defaultBindingPayloads, defineHostComponents, docCacheTag, elytraHostImage, evaluatePreviewRequest, evaluateRevalidateRequest, firstBlockFullBleed, isSourcePayloadError, loadCachedEntry, loadLiveContent, materializeSourcePayloads, mergeCacheTags, nextCacheTags, nextImagePrimitive, pathFromSlug, projectSweepTag, resolveCanvasPage, resolveGlobals, resolveHostEnv, resolvePayloadToken, revalidatePayloadSchema, routeCacheTag, safeRedirectTarget, scopeCacheTag, signRevalidateBody, sourcePayloadError };
|
|
1303
1360
|
//# sourceMappingURL=index.js.map
|
|
1304
1361
|
//# sourceMappingURL=index.js.map
|