@elytracms/next 0.0.82 → 0.0.83
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 +47 -2
- package/dist/index.js +24 -12
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { z } from 'zod';
|
|
|
16
16
|
export { z } from 'zod';
|
|
17
17
|
import { ImageLoader } from 'next/image';
|
|
18
18
|
import { HostImageRenderer } from './host-image.js';
|
|
19
|
+
import { HostComponentEntry } from '@elytracms/core/studio-core';
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* One host-repo component: the manifest the builder edits against plus the
|
|
@@ -1491,8 +1492,26 @@ interface ElytraHostOptions {
|
|
|
1491
1492
|
* SAME modules the studio composes with). Base primitives are always
|
|
1492
1493
|
* included; `base.Image` is swapped for `next/image` delivery by default
|
|
1493
1494
|
* (see `image`).
|
|
1495
|
+
*
|
|
1496
|
+
* Typed as the CONFIG's `HostComponentEntry` (`implementation: unknown`), not
|
|
1497
|
+
* the stricter {@link HostComponent}, so that `createElytraHost({ ...site })`
|
|
1498
|
+
* — the shape EC-532 makes the contract — compiles however the consumer typed
|
|
1499
|
+
* their project entry. It previously demanded `ComponentType`, which meant the
|
|
1500
|
+
* recommended spread worked only when the entry's implementation types
|
|
1501
|
+
* survived inference: `apps/demo/elytra.config.ts` gets away with it via
|
|
1502
|
+
* `satisfies`, and anyone using the engine's own published `HostComponentEntry`
|
|
1503
|
+
* / `WorkspaceProjectEntry` annotation did not. Both production consumers hit
|
|
1504
|
+
* exactly that and each carried one hand-restated `components` line (EC-539).
|
|
1505
|
+
*
|
|
1506
|
+
* What this costs, stated plainly rather than glossed: a list passed HERE no
|
|
1507
|
+
* longer gets a compile-time check that each `implementation` is really a
|
|
1508
|
+
* component, and nothing yet checks it at runtime either — a garbage value
|
|
1509
|
+
* would reach the renderer. `defineHostComponents` keeps the strict
|
|
1510
|
+
* {@link HostComponent} signature, so a hand-built list passed there directly
|
|
1511
|
+
* is still checked. Closing the gap properly needs a registration issue code
|
|
1512
|
+
* in the core registry; booked as EC-541 rather than smuggled in here.
|
|
1494
1513
|
*/
|
|
1495
|
-
components?: readonly
|
|
1514
|
+
components?: readonly HostComponentEntry[];
|
|
1496
1515
|
/**
|
|
1497
1516
|
* `base.Image` delivery options (loader/sizes/quality — the non-Vercel CDN
|
|
1498
1517
|
* seam), or `false` to keep the plain-`<img>` primitive. Default: Next's own
|
|
@@ -1548,6 +1567,25 @@ interface LoadGlobalsOptions {
|
|
|
1548
1567
|
/** Perspective of the chrome read. Default `'published'` (live is published-only). */
|
|
1549
1568
|
perspective?: Perspective;
|
|
1550
1569
|
}
|
|
1570
|
+
/**
|
|
1571
|
+
* Which world {@link ElytraHost.loadContent} reads from.
|
|
1572
|
+
*
|
|
1573
|
+
* - `live` — the configured Convex deployment (published; token-gated draft).
|
|
1574
|
+
* - `fallback` — the host's own `fallbackContent` world (the scaffold's seeded
|
|
1575
|
+
* starter, the demo's in-memory fixture). A legitimate, supported mode.
|
|
1576
|
+
* - `empty` — no backend and no fallback: this project's structure with no
|
|
1577
|
+
* content, so every URL is a clean 404. Correct for a CI build; almost never
|
|
1578
|
+
* what a deployed site intends.
|
|
1579
|
+
*
|
|
1580
|
+
* The mode was decided from env long before EC-527 and readable by **nobody**,
|
|
1581
|
+
* so a site serving the fallback looked identical from the outside to one
|
|
1582
|
+
* reading the real deployment. Measured on the demo: `/` returned `200` while
|
|
1583
|
+
* all four of EC-512's published fixtures 404'd — an agent following AGENTS.md
|
|
1584
|
+
* §5 gets no signal that the thing under test was never exercised. Declared
|
|
1585
|
+
* once, read here, so a host can *say* which world it is in instead of
|
|
1586
|
+
* re-deriving it from `env` and drifting.
|
|
1587
|
+
*/
|
|
1588
|
+
type ElytraContentMode = 'live' | 'fallback' | 'empty';
|
|
1551
1589
|
/** The delivery host handle {@link createElytraHost} yields. */
|
|
1552
1590
|
interface ElytraHost {
|
|
1553
1591
|
/**
|
|
@@ -1555,6 +1593,13 @@ interface ElytraHost {
|
|
|
1555
1593
|
* studio's webhook tags), else the config slug.
|
|
1556
1594
|
*/
|
|
1557
1595
|
contentScope: string;
|
|
1596
|
+
/**
|
|
1597
|
+
* Which world {@link loadContent} reads from — see {@link ElytraContentMode}.
|
|
1598
|
+
* Read it to announce the mode (a boot line, a dev-only banner) rather than
|
|
1599
|
+
* re-deriving it from {@link env}, which is the drift this field exists to
|
|
1600
|
+
* prevent.
|
|
1601
|
+
*/
|
|
1602
|
+
contentMode: ElytraContentMode;
|
|
1558
1603
|
/** The resolved env bag (documented names, trimmed, empty = unset). */
|
|
1559
1604
|
env: ElytraHostEnv;
|
|
1560
1605
|
/** Materialized route records (a derive is run once, at factory time). */
|
|
@@ -1742,4 +1787,4 @@ declare function evaluatePreviewRequest(requestUrl: string | URL, expectedToken:
|
|
|
1742
1787
|
*/
|
|
1743
1788
|
declare const PACKAGE = "@elytracms/next";
|
|
1744
1789
|
|
|
1745
|
-
export { type AssetImageLoaderOptions, type BindingPayloads, type CacheWrapper, type CacheWrapperOptions, type CachedEntry, type CanvasCacheOptions, type CanvasContentRequest, type CanvasDataSource, type CanvasPageOutcome, type CanvasPayloadContext, type CanvasPayloadsFactory, CanvasRenderer, type CanvasRendererProps, type CanvasRequestInfo, type CanvasRoute, type CanvasRouteOptions, type CanvasRouteProps, type CanvasSitemapOptions, type CanvasSitemapResult, type CanvasWrapContext, type ContentSnapshot, type ContentSnapshotOptions, type ContentSource, type CreateCanvasSitemapOptions, type DefineHostComponentsOptions, type DeliveryPresentation, ELYTRA_HOST_ENV_KEYS, type ElytraHost, type ElytraHostEnv, type ElytraHostImageOptions, type ElytraHostOptions, ElytraImage, type ElytraImageAsset, type ElytraImageProps, type GlobalsConventions, type HostCanvasRouteOptions, type HostComponent, type HostComponents, type LiveContentOptions, type LoadGlobalsOptions, type MaterializeSourcePayloadsInput, type MaterializedSourcePayloads, type NextImagePrimitiveOptions, PACKAGE, type PreviewEvaluation, type PreviewRouteHandlers, type PreviewRouteOptions, REVALIDATE_SIGNATURE_HEADER, type ResolveCanvasPageOptions, type ResolveGlobalsOptions, type ResolvedLink, type ResolvedNavEntry, type ResolvedNavLink, type RevalidateEvaluation, type RevalidatePayload, type RevalidateRouteHandlers, type RevalidateRouteOptions, type SiteGlobals, type SitemapParamsProvider, type SitemapRouteContext, type SitemapSkippedRoute, type SourcePayloadError, type StaticContentData, 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 };
|
|
1790
|
+
export { type AssetImageLoaderOptions, type BindingPayloads, type CacheWrapper, type CacheWrapperOptions, type CachedEntry, type CanvasCacheOptions, type CanvasContentRequest, type CanvasDataSource, type CanvasPageOutcome, type CanvasPayloadContext, type CanvasPayloadsFactory, CanvasRenderer, type CanvasRendererProps, type CanvasRequestInfo, type CanvasRoute, type CanvasRouteOptions, type CanvasRouteProps, type CanvasSitemapOptions, type CanvasSitemapResult, type CanvasWrapContext, type ContentSnapshot, type ContentSnapshotOptions, type ContentSource, type CreateCanvasSitemapOptions, type DefineHostComponentsOptions, type DeliveryPresentation, ELYTRA_HOST_ENV_KEYS, type ElytraContentMode, type ElytraHost, type ElytraHostEnv, type ElytraHostImageOptions, type ElytraHostOptions, ElytraImage, type ElytraImageAsset, type ElytraImageProps, type GlobalsConventions, type HostCanvasRouteOptions, type HostComponent, type HostComponents, type LiveContentOptions, type LoadGlobalsOptions, type MaterializeSourcePayloadsInput, type MaterializedSourcePayloads, type NextImagePrimitiveOptions, PACKAGE, type PreviewEvaluation, type PreviewRouteHandlers, type PreviewRouteOptions, REVALIDATE_SIGNATURE_HEADER, type ResolveCanvasPageOptions, type ResolveGlobalsOptions, type ResolvedLink, type ResolvedNavEntry, type ResolvedNavLink, type RevalidateEvaluation, type RevalidatePayload, type RevalidateRouteHandlers, type RevalidateRouteOptions, type SiteGlobals, type SitemapParamsProvider, type SitemapRouteContext, type SitemapSkippedRoute, type SourcePayloadError, type StaticContentData, 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 };
|
package/dist/index.js
CHANGED
|
@@ -715,7 +715,8 @@ function canvasSitemapEntries(source, options) {
|
|
|
715
715
|
}
|
|
716
716
|
return client;
|
|
717
717
|
};
|
|
718
|
-
const
|
|
718
|
+
const byUrl = /* @__PURE__ */ new Map();
|
|
719
|
+
const byGroup = /* @__PURE__ */ new Map();
|
|
719
720
|
for (const route of routes) {
|
|
720
721
|
const paramNames = paramNamesOf(route.pattern);
|
|
721
722
|
const mount = hierarchyMount(route);
|
|
@@ -776,9 +777,12 @@ function canvasSitemapEntries(source, options) {
|
|
|
776
777
|
);
|
|
777
778
|
continue;
|
|
778
779
|
}
|
|
779
|
-
const
|
|
780
|
-
|
|
781
|
-
|
|
780
|
+
const absolute = originOf(options.baseUrl) + urlPath;
|
|
781
|
+
const group = result.document ? `${route.id}\0doc\0${result.document.collection}\0${result.document.id}` : `${route.id}\0path\0${path}`;
|
|
782
|
+
if (!byUrl.has(absolute)) byUrl.set(absolute, { group, locale });
|
|
783
|
+
const perLocale = byGroup.get(group) ?? /* @__PURE__ */ new Map();
|
|
784
|
+
if (!perLocale.has(locale)) perLocale.set(locale, absolute);
|
|
785
|
+
byGroup.set(group, perLocale);
|
|
782
786
|
}
|
|
783
787
|
if (mount && paths.length > 0 && unresolved === paths.length) {
|
|
784
788
|
skip(
|
|
@@ -789,14 +793,10 @@ function canvasSitemapEntries(source, options) {
|
|
|
789
793
|
}
|
|
790
794
|
}
|
|
791
795
|
const entries = [];
|
|
792
|
-
for (const
|
|
793
|
-
const
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
url,
|
|
797
|
-
...perLocale.size > 1 ? { alternates: { languages } } : {}
|
|
798
|
-
});
|
|
799
|
-
}
|
|
796
|
+
for (const [url, { group }] of byUrl) {
|
|
797
|
+
const perLocale = byGroup.get(group);
|
|
798
|
+
const languages = perLocale && perLocale.size > 1 ? Object.fromEntries(perLocale) : void 0;
|
|
799
|
+
entries.push({ url, ...languages ? { alternates: { languages } } : {} });
|
|
800
800
|
}
|
|
801
801
|
entries.sort((a, b) => a.url < b.url ? -1 : a.url > b.url ? 1 : 0);
|
|
802
802
|
return { entries, skipped };
|
|
@@ -1266,12 +1266,23 @@ function createElytraHost(options) {
|
|
|
1266
1266
|
const env = resolveHostEnv(options.env ?? process.env);
|
|
1267
1267
|
const routes = materializeRoutes(options.routes, options.collections);
|
|
1268
1268
|
const live = env.convexUrl !== void 0 && env.projectId !== void 0;
|
|
1269
|
+
if (!live && (env.convexUrl !== void 0 || env.projectId !== void 0)) {
|
|
1270
|
+
const [present, missing] = env.convexUrl !== void 0 ? [ELYTRA_HOST_ENV_KEYS.convexUrl, ELYTRA_HOST_ENV_KEYS.projectId] : [ELYTRA_HOST_ENV_KEYS.projectId, ELYTRA_HOST_ENV_KEYS.convexUrl];
|
|
1271
|
+
throw new Error(
|
|
1272
|
+
`Elytra delivery host: ${present} is set but ${missing} is not \u2014 live content needs both. Left as it is, this site would serve fallback content and look healthy. Set ${missing} to go live, or unset ${present} to run the no-backend fallback on purpose.`
|
|
1273
|
+
);
|
|
1274
|
+
}
|
|
1275
|
+
const contentMode = live ? "live" : options.fallbackContent ? "fallback" : "empty";
|
|
1269
1276
|
const contentScope = live ? env.projectId : options.slug;
|
|
1270
1277
|
const components = defineHostComponents([
|
|
1271
1278
|
// Batteries included (EC-368 image defaults): graph `base.Image` nodes render
|
|
1272
1279
|
// through next/image — resized variants via the host's own optimizer. The
|
|
1273
1280
|
// canonical manifest stays (first registration wins in defineHostComponents).
|
|
1274
1281
|
...options.image === false ? [] : [nextImagePrimitive(options.image ?? {})],
|
|
1282
|
+
// EC-539: the option is the CONFIG's entry shape (`implementation: unknown`)
|
|
1283
|
+
// so the recommended `{ ...site }` spread compiles. Narrowing here is the
|
|
1284
|
+
// one place that widening is paid for; see the option's doc comment and
|
|
1285
|
+
// EC-541 for the runtime check that should back it.
|
|
1275
1286
|
...options.components ?? []
|
|
1276
1287
|
]);
|
|
1277
1288
|
const emptySource = createStaticContentSource({
|
|
@@ -1341,6 +1352,7 @@ function createElytraHost(options) {
|
|
|
1341
1352
|
};
|
|
1342
1353
|
return {
|
|
1343
1354
|
contentScope,
|
|
1355
|
+
contentMode,
|
|
1344
1356
|
env,
|
|
1345
1357
|
routes,
|
|
1346
1358
|
components,
|