@cmssy/next 3.0.0 → 4.0.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/dist/index.cjs +41 -3
- package/dist/index.d.cts +55 -3
- package/dist/index.d.ts +55 -3
- package/dist/index.js +38 -4
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -255,6 +255,12 @@ async function resolveEditorRequest(query, draftSecret) {
|
|
|
255
255
|
return cmssySecretsMatch(provided, draftSecret);
|
|
256
256
|
}
|
|
257
257
|
function createCmssyPage(config, blocks, options) {
|
|
258
|
+
return buildCmssyPageRenderer(config, blocks, options, false);
|
|
259
|
+
}
|
|
260
|
+
function createCmssyEditPage(config, blocks, options) {
|
|
261
|
+
return buildCmssyPageRenderer(config, blocks, options, true);
|
|
262
|
+
}
|
|
263
|
+
function buildCmssyPageRenderer(config, blocks, options, editRoute) {
|
|
258
264
|
if (!Array.isArray(blocks)) {
|
|
259
265
|
throw new Error(
|
|
260
266
|
"cmssy: createCmssyPage(config, blocks) requires a blocks array \u2014 pass your defineBlock(...) array"
|
|
@@ -274,8 +280,14 @@ function createCmssyPage(config, blocks, options) {
|
|
|
274
280
|
}) {
|
|
275
281
|
const path = fixedPath ?? (params ? (await params).path ?? void 0 : void 0);
|
|
276
282
|
const { isEnabled } = await headers.draftMode();
|
|
277
|
-
|
|
278
|
-
|
|
283
|
+
let editorActive = false;
|
|
284
|
+
if (editRoute) {
|
|
285
|
+
const query = searchParams ? await searchParams : {};
|
|
286
|
+
editorActive = await resolveEditorRequest(query, config.draftSecret);
|
|
287
|
+
if (!editorActive) {
|
|
288
|
+
navigation.notFound();
|
|
289
|
+
}
|
|
290
|
+
}
|
|
279
291
|
const editMode = isEnabled || editorActive;
|
|
280
292
|
const devAllowed = isDevelopment() && Boolean(config.devToken?.trim());
|
|
281
293
|
let locale;
|
|
@@ -386,6 +398,23 @@ function resolveBridgeOrigin(editorOrigin) {
|
|
|
386
398
|
}
|
|
387
399
|
return origins.length === 1 ? origins[0] : origins;
|
|
388
400
|
}
|
|
401
|
+
var CMSSY_EDIT_PATH_PREFIX = "/__cmssy/edit";
|
|
402
|
+
async function cmssyEditRewrite(request2, config) {
|
|
403
|
+
const { pathname, searchParams } = request2.nextUrl;
|
|
404
|
+
if (pathname.startsWith(CMSSY_EDIT_PATH_PREFIX)) return null;
|
|
405
|
+
if (!searchParams.getAll(CMSSY_EDIT_QUERY_PARAM).includes("1")) return null;
|
|
406
|
+
const provided = searchParams.get(CMSSY_SECRET_QUERY_PARAM);
|
|
407
|
+
if (!provided || !config.draftSecret) return null;
|
|
408
|
+
if (!await cmssySecretsMatch(provided, config.draftSecret)) return null;
|
|
409
|
+
const url = request2.nextUrl.clone();
|
|
410
|
+
url.pathname = `${CMSSY_EDIT_PATH_PREFIX}${pathname === "/" ? "" : pathname}`;
|
|
411
|
+
return server.NextResponse.rewrite(url);
|
|
412
|
+
}
|
|
413
|
+
function createCmssyEditMiddleware(config) {
|
|
414
|
+
return async function cmssyEditMiddleware(request2) {
|
|
415
|
+
return await cmssyEditRewrite(request2, config) ?? server.NextResponse.next();
|
|
416
|
+
};
|
|
417
|
+
}
|
|
389
418
|
function DefaultNotFound() {
|
|
390
419
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
391
420
|
"main",
|
|
@@ -698,7 +727,12 @@ async function splitCmssyLocale(config, path) {
|
|
|
698
727
|
const siteLocales = await react.resolveSiteLocales(config);
|
|
699
728
|
return react.splitLocaleFromPath(path, siteLocales);
|
|
700
729
|
}
|
|
701
|
-
async function getCmssyLocale(config) {
|
|
730
|
+
async function getCmssyLocale(config, options) {
|
|
731
|
+
if (options?.path !== void 0) {
|
|
732
|
+
const siteLocales = await react.resolveSiteLocales(config);
|
|
733
|
+
const segments = Array.isArray(options.path) ? options.path.filter(Boolean) : options.path.split("/").filter(Boolean);
|
|
734
|
+
return react.splitLocaleFromPath(segments, siteLocales).locale;
|
|
735
|
+
}
|
|
702
736
|
const { headers: headers3 } = await import('next/headers');
|
|
703
737
|
const headerList = await headers3();
|
|
704
738
|
const fromHeader = headerList.get(CMSSY_LOCALE_HEADER);
|
|
@@ -1958,6 +1992,7 @@ Object.defineProperty(exports, "resolveApiUrl", {
|
|
|
1958
1992
|
});
|
|
1959
1993
|
exports.CMSSY_CART_COOKIE = CMSSY_CART_COOKIE;
|
|
1960
1994
|
exports.CMSSY_EDIT_HEADER = CMSSY_EDIT_HEADER;
|
|
1995
|
+
exports.CMSSY_EDIT_PATH_PREFIX = CMSSY_EDIT_PATH_PREFIX;
|
|
1961
1996
|
exports.CMSSY_EDIT_QUERY_PARAM = CMSSY_EDIT_QUERY_PARAM;
|
|
1962
1997
|
exports.CMSSY_LOCALE_HEADER = CMSSY_LOCALE_HEADER;
|
|
1963
1998
|
exports.CMSSY_SECRET_QUERY_PARAM = CMSSY_SECRET_QUERY_PARAM;
|
|
@@ -1969,9 +2004,12 @@ exports.applyCmssyCsp = applyCmssyCsp;
|
|
|
1969
2004
|
exports.assertAuthConfig = assertAuthConfig;
|
|
1970
2005
|
exports.buildCmssyMetadata = buildCmssyMetadata;
|
|
1971
2006
|
exports.cmssyCspHeaders = cmssyCspHeaders;
|
|
2007
|
+
exports.cmssyEditRewrite = cmssyEditRewrite;
|
|
1972
2008
|
exports.createCmssyAuthMiddleware = createCmssyAuthMiddleware;
|
|
1973
2009
|
exports.createCmssyAuthRoute = createCmssyAuthRoute;
|
|
1974
2010
|
exports.createCmssyCartRoute = createCmssyCartRoute;
|
|
2011
|
+
exports.createCmssyEditMiddleware = createCmssyEditMiddleware;
|
|
2012
|
+
exports.createCmssyEditPage = createCmssyEditPage;
|
|
1975
2013
|
exports.createCmssyLocaleMiddleware = createCmssyLocaleMiddleware;
|
|
1976
2014
|
exports.createCmssyNotFound = createCmssyNotFound;
|
|
1977
2015
|
exports.createCmssyOrdersRoute = createCmssyOrdersRoute;
|
package/dist/index.d.cts
CHANGED
|
@@ -5,8 +5,8 @@ export { DEFAULT_CMSSY_API_URL, FieldCondition, FieldConditionGroup, FieldCondit
|
|
|
5
5
|
import { EditBridgeConfig } from '@cmssy/react/client';
|
|
6
6
|
import { CmssyAuthConfig, CmssySessionPayload, SessionCookieOptions, CmssySessionUser, FetchProductOptions, CmssyProduct, FetchProductsOptions, CmssyProductPage, FetchOrderByTokenOptions, CmssyOrder, VerifyCmssyWebhookOptions, CmssyWebhookEvent } from '@cmssy/types';
|
|
7
7
|
export { CmssyAuthConfig, CmssyProductPage, CmssySessionPayload, CmssySessionUser, CmssyStockState, CmssyWebhookEvent, CmssyWebhookOrder, FetchOrderByTokenOptions, FetchProductOptions, FetchProductsOptions, MyOrdersResult, SessionCookieOptions, VerifyCmssyWebhookOptions } from '@cmssy/types';
|
|
8
|
-
import { MetadataRoute, Metadata } from 'next';
|
|
9
8
|
import { NextRequest, NextResponse } from 'next/server';
|
|
9
|
+
import { MetadataRoute, Metadata } from 'next';
|
|
10
10
|
|
|
11
11
|
declare const DEFAULT_CMSSY_EDITOR_ORIGINS: string[];
|
|
12
12
|
declare function resolveEditorOrigin(editorOrigin: string | string[] | undefined): string | string[];
|
|
@@ -88,7 +88,51 @@ interface CatchAllProps {
|
|
|
88
88
|
params?: Promise<CatchAllParams>;
|
|
89
89
|
searchParams?: Promise<SearchParams>;
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Public catch-all page. Statically renderable: it never reads
|
|
93
|
+
* `searchParams` or `headers()` - awaiting either forces every route
|
|
94
|
+
* dynamic and kills ISR (CMS-952). Draft-mode preview (the authenticated
|
|
95
|
+
* /api/draft cookie) still works per-request via `draftMode()`, which is
|
|
96
|
+
* static-safe, and renders draft CONTENT without the editor (CMS-948).
|
|
97
|
+
* The editor-iframe flow (`?cmssyEdit=1&cmssySecret=...`) is served by
|
|
98
|
+
* the middleware rewrite (`cmssyEditRewrite`) onto the dynamic edit route
|
|
99
|
+
* mounted with `createCmssyEditPage`.
|
|
100
|
+
*/
|
|
91
101
|
declare function createCmssyPage(config: CmssyNextConfig, blocks: BlockDefinition[], options?: CreateCmssyPageOptions): ({ params, searchParams, }: CatchAllProps) => Promise<react_jsx_runtime.JSX.Element>;
|
|
102
|
+
/**
|
|
103
|
+
* Editor page for the middleware-rewritten edit route
|
|
104
|
+
* (`app/__cmssy/edit/[[...path]]/page.tsx`, `dynamic = "force-dynamic"`).
|
|
105
|
+
* Re-verifies the `cmssyEdit` + `cmssySecret` pair itself, so a direct hit
|
|
106
|
+
* on the route path (bypassing the middleware) cannot mount the editor.
|
|
107
|
+
*/
|
|
108
|
+
declare function createCmssyEditPage(config: CmssyNextConfig, blocks: BlockDefinition[], options?: CreateCmssyPageOptions): ({ params, searchParams, }: CatchAllProps) => Promise<react_jsx_runtime.JSX.Element>;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Where the middleware rewrites editor-preview traffic. Mount the matching
|
|
112
|
+
* dynamic route in the consumer app:
|
|
113
|
+
*
|
|
114
|
+
* app/__cmssy/edit/[[...path]]/page.tsx
|
|
115
|
+
* export const dynamic = "force-dynamic";
|
|
116
|
+
* export default createCmssyEditPage(cmssy, blocks, { editor: Editor });
|
|
117
|
+
*/
|
|
118
|
+
declare const CMSSY_EDIT_PATH_PREFIX = "/__cmssy/edit";
|
|
119
|
+
/**
|
|
120
|
+
* Rewrite VERIFIED editor requests (`cmssyEdit=1` + a `cmssySecret` matching
|
|
121
|
+
* the site's draft secret, CMS-948) onto the dedicated dynamic edit route, so
|
|
122
|
+
* the public catch-all can stay fully static. A static page never sees its
|
|
123
|
+
* query string - this rewrite is what makes the editor iframe work at all
|
|
124
|
+
* once ISR is on. Draft-mode preview (the authenticated /api/draft cookie) is
|
|
125
|
+
* NOT rewritten: it renders draft content on the public route via
|
|
126
|
+
* `draftMode()`, without the editor. Returns null for normal traffic so it
|
|
127
|
+
* composes with other middleware.
|
|
128
|
+
*/
|
|
129
|
+
declare function cmssyEditRewrite(request: NextRequest, config: {
|
|
130
|
+
draftSecret: string;
|
|
131
|
+
}): Promise<NextResponse | null>;
|
|
132
|
+
/** Standalone middleware when the consumer has no other middleware to compose. */
|
|
133
|
+
declare function createCmssyEditMiddleware(config: {
|
|
134
|
+
draftSecret: string;
|
|
135
|
+
}): (request: NextRequest) => Promise<NextResponse>;
|
|
92
136
|
|
|
93
137
|
interface CreateCmssyNotFoundOptions {
|
|
94
138
|
/**
|
|
@@ -220,7 +264,15 @@ declare function splitCmssyLocale(config: CmssyClientConfig, path: string[] | un
|
|
|
220
264
|
locale: string;
|
|
221
265
|
path: string[] | undefined;
|
|
222
266
|
}>;
|
|
223
|
-
|
|
267
|
+
/**
|
|
268
|
+
* Resolve the active locale. Pass `options.path` (route params) wherever
|
|
269
|
+
* possible - that path is static-safe. The no-argument form falls back to the
|
|
270
|
+
* `x-cmssy-locale` request header, which reads `headers()` and forces the
|
|
271
|
+
* calling route into dynamic rendering.
|
|
272
|
+
*/
|
|
273
|
+
declare function getCmssyLocale(config: CmssyClientConfig, options?: {
|
|
274
|
+
path?: string | string[];
|
|
275
|
+
}): Promise<string>;
|
|
224
276
|
|
|
225
277
|
/**
|
|
226
278
|
* Resolves the active locale from a pathname's leading segment. Uses the
|
|
@@ -304,4 +356,4 @@ declare class CmssyWebhookError extends Error {
|
|
|
304
356
|
*/
|
|
305
357
|
declare function verifyCmssyWebhook(options: VerifyCmssyWebhookOptions): CmssyWebhookEvent;
|
|
306
358
|
|
|
307
|
-
export { type BuildCmssyMetadataOptions, CMSSY_CART_COOKIE, CMSSY_EDIT_HEADER, CMSSY_EDIT_QUERY_PARAM, CMSSY_LOCALE_HEADER, CMSSY_SECRET_QUERY_PARAM, CMSSY_SESSION_COOKIE, type CmssyAuthMiddleware, type CmssyAuthRouteHandlers, type CmssyCartRouteHandlers, type CmssyCspOptions, type CmssyDraftRouteConfig, type CmssyEditorProps, type CmssyEnvConfig, type CmssyNextConfig, type CmssyOrdersRouteHandlers, CmssyWebhookError, type CreateCmssyNotFoundOptions, type CreateCmssyPageOptions, type CreateCmssyRobotsOptions, type CreateCmssySitemapOptions, DEFAULT_CMSSY_EDITOR_ORIGINS, SESSION_MAX_AGE_SECONDS, applyCmssyCsp, assertAuthConfig, buildCmssyMetadata, cmssyCspHeaders, createCmssyAuthMiddleware, createCmssyAuthRoute, createCmssyCartRoute, createCmssyLocaleMiddleware, createCmssyNotFound, createCmssyOrdersRoute, createCmssyPage, createCmssyRobots, createCmssySitemap, createDraftRoute, defineCmssyConfig, fetchOrderByToken, fetchProduct, fetchProducts, getCmssyAccessToken, getCmssyLocale, getCmssyUser, isAccessExpired, isCmssyEditMode, isCmssyEditRequest, localeForPathname, openSession, resolveEditorOrigin, resolveLocaleFromPathname, sealSession, sessionCookieOptions, splitCmssyLocale, verifyCmssyWebhook };
|
|
359
|
+
export { type BuildCmssyMetadataOptions, CMSSY_CART_COOKIE, CMSSY_EDIT_HEADER, CMSSY_EDIT_PATH_PREFIX, CMSSY_EDIT_QUERY_PARAM, CMSSY_LOCALE_HEADER, CMSSY_SECRET_QUERY_PARAM, CMSSY_SESSION_COOKIE, type CmssyAuthMiddleware, type CmssyAuthRouteHandlers, type CmssyCartRouteHandlers, type CmssyCspOptions, type CmssyDraftRouteConfig, type CmssyEditorProps, type CmssyEnvConfig, type CmssyNextConfig, type CmssyOrdersRouteHandlers, CmssyWebhookError, type CreateCmssyNotFoundOptions, type CreateCmssyPageOptions, type CreateCmssyRobotsOptions, type CreateCmssySitemapOptions, DEFAULT_CMSSY_EDITOR_ORIGINS, SESSION_MAX_AGE_SECONDS, applyCmssyCsp, assertAuthConfig, buildCmssyMetadata, cmssyCspHeaders, cmssyEditRewrite, createCmssyAuthMiddleware, createCmssyAuthRoute, createCmssyCartRoute, createCmssyEditMiddleware, createCmssyEditPage, createCmssyLocaleMiddleware, createCmssyNotFound, createCmssyOrdersRoute, createCmssyPage, createCmssyRobots, createCmssySitemap, createDraftRoute, defineCmssyConfig, fetchOrderByToken, fetchProduct, fetchProducts, getCmssyAccessToken, getCmssyLocale, getCmssyUser, isAccessExpired, isCmssyEditMode, isCmssyEditRequest, localeForPathname, openSession, resolveEditorOrigin, resolveLocaleFromPathname, sealSession, sessionCookieOptions, splitCmssyLocale, verifyCmssyWebhook };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ export { DEFAULT_CMSSY_API_URL, FieldCondition, FieldConditionGroup, FieldCondit
|
|
|
5
5
|
import { EditBridgeConfig } from '@cmssy/react/client';
|
|
6
6
|
import { CmssyAuthConfig, CmssySessionPayload, SessionCookieOptions, CmssySessionUser, FetchProductOptions, CmssyProduct, FetchProductsOptions, CmssyProductPage, FetchOrderByTokenOptions, CmssyOrder, VerifyCmssyWebhookOptions, CmssyWebhookEvent } from '@cmssy/types';
|
|
7
7
|
export { CmssyAuthConfig, CmssyProductPage, CmssySessionPayload, CmssySessionUser, CmssyStockState, CmssyWebhookEvent, CmssyWebhookOrder, FetchOrderByTokenOptions, FetchProductOptions, FetchProductsOptions, MyOrdersResult, SessionCookieOptions, VerifyCmssyWebhookOptions } from '@cmssy/types';
|
|
8
|
-
import { MetadataRoute, Metadata } from 'next';
|
|
9
8
|
import { NextRequest, NextResponse } from 'next/server';
|
|
9
|
+
import { MetadataRoute, Metadata } from 'next';
|
|
10
10
|
|
|
11
11
|
declare const DEFAULT_CMSSY_EDITOR_ORIGINS: string[];
|
|
12
12
|
declare function resolveEditorOrigin(editorOrigin: string | string[] | undefined): string | string[];
|
|
@@ -88,7 +88,51 @@ interface CatchAllProps {
|
|
|
88
88
|
params?: Promise<CatchAllParams>;
|
|
89
89
|
searchParams?: Promise<SearchParams>;
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Public catch-all page. Statically renderable: it never reads
|
|
93
|
+
* `searchParams` or `headers()` - awaiting either forces every route
|
|
94
|
+
* dynamic and kills ISR (CMS-952). Draft-mode preview (the authenticated
|
|
95
|
+
* /api/draft cookie) still works per-request via `draftMode()`, which is
|
|
96
|
+
* static-safe, and renders draft CONTENT without the editor (CMS-948).
|
|
97
|
+
* The editor-iframe flow (`?cmssyEdit=1&cmssySecret=...`) is served by
|
|
98
|
+
* the middleware rewrite (`cmssyEditRewrite`) onto the dynamic edit route
|
|
99
|
+
* mounted with `createCmssyEditPage`.
|
|
100
|
+
*/
|
|
91
101
|
declare function createCmssyPage(config: CmssyNextConfig, blocks: BlockDefinition[], options?: CreateCmssyPageOptions): ({ params, searchParams, }: CatchAllProps) => Promise<react_jsx_runtime.JSX.Element>;
|
|
102
|
+
/**
|
|
103
|
+
* Editor page for the middleware-rewritten edit route
|
|
104
|
+
* (`app/__cmssy/edit/[[...path]]/page.tsx`, `dynamic = "force-dynamic"`).
|
|
105
|
+
* Re-verifies the `cmssyEdit` + `cmssySecret` pair itself, so a direct hit
|
|
106
|
+
* on the route path (bypassing the middleware) cannot mount the editor.
|
|
107
|
+
*/
|
|
108
|
+
declare function createCmssyEditPage(config: CmssyNextConfig, blocks: BlockDefinition[], options?: CreateCmssyPageOptions): ({ params, searchParams, }: CatchAllProps) => Promise<react_jsx_runtime.JSX.Element>;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Where the middleware rewrites editor-preview traffic. Mount the matching
|
|
112
|
+
* dynamic route in the consumer app:
|
|
113
|
+
*
|
|
114
|
+
* app/__cmssy/edit/[[...path]]/page.tsx
|
|
115
|
+
* export const dynamic = "force-dynamic";
|
|
116
|
+
* export default createCmssyEditPage(cmssy, blocks, { editor: Editor });
|
|
117
|
+
*/
|
|
118
|
+
declare const CMSSY_EDIT_PATH_PREFIX = "/__cmssy/edit";
|
|
119
|
+
/**
|
|
120
|
+
* Rewrite VERIFIED editor requests (`cmssyEdit=1` + a `cmssySecret` matching
|
|
121
|
+
* the site's draft secret, CMS-948) onto the dedicated dynamic edit route, so
|
|
122
|
+
* the public catch-all can stay fully static. A static page never sees its
|
|
123
|
+
* query string - this rewrite is what makes the editor iframe work at all
|
|
124
|
+
* once ISR is on. Draft-mode preview (the authenticated /api/draft cookie) is
|
|
125
|
+
* NOT rewritten: it renders draft content on the public route via
|
|
126
|
+
* `draftMode()`, without the editor. Returns null for normal traffic so it
|
|
127
|
+
* composes with other middleware.
|
|
128
|
+
*/
|
|
129
|
+
declare function cmssyEditRewrite(request: NextRequest, config: {
|
|
130
|
+
draftSecret: string;
|
|
131
|
+
}): Promise<NextResponse | null>;
|
|
132
|
+
/** Standalone middleware when the consumer has no other middleware to compose. */
|
|
133
|
+
declare function createCmssyEditMiddleware(config: {
|
|
134
|
+
draftSecret: string;
|
|
135
|
+
}): (request: NextRequest) => Promise<NextResponse>;
|
|
92
136
|
|
|
93
137
|
interface CreateCmssyNotFoundOptions {
|
|
94
138
|
/**
|
|
@@ -220,7 +264,15 @@ declare function splitCmssyLocale(config: CmssyClientConfig, path: string[] | un
|
|
|
220
264
|
locale: string;
|
|
221
265
|
path: string[] | undefined;
|
|
222
266
|
}>;
|
|
223
|
-
|
|
267
|
+
/**
|
|
268
|
+
* Resolve the active locale. Pass `options.path` (route params) wherever
|
|
269
|
+
* possible - that path is static-safe. The no-argument form falls back to the
|
|
270
|
+
* `x-cmssy-locale` request header, which reads `headers()` and forces the
|
|
271
|
+
* calling route into dynamic rendering.
|
|
272
|
+
*/
|
|
273
|
+
declare function getCmssyLocale(config: CmssyClientConfig, options?: {
|
|
274
|
+
path?: string | string[];
|
|
275
|
+
}): Promise<string>;
|
|
224
276
|
|
|
225
277
|
/**
|
|
226
278
|
* Resolves the active locale from a pathname's leading segment. Uses the
|
|
@@ -304,4 +356,4 @@ declare class CmssyWebhookError extends Error {
|
|
|
304
356
|
*/
|
|
305
357
|
declare function verifyCmssyWebhook(options: VerifyCmssyWebhookOptions): CmssyWebhookEvent;
|
|
306
358
|
|
|
307
|
-
export { type BuildCmssyMetadataOptions, CMSSY_CART_COOKIE, CMSSY_EDIT_HEADER, CMSSY_EDIT_QUERY_PARAM, CMSSY_LOCALE_HEADER, CMSSY_SECRET_QUERY_PARAM, CMSSY_SESSION_COOKIE, type CmssyAuthMiddleware, type CmssyAuthRouteHandlers, type CmssyCartRouteHandlers, type CmssyCspOptions, type CmssyDraftRouteConfig, type CmssyEditorProps, type CmssyEnvConfig, type CmssyNextConfig, type CmssyOrdersRouteHandlers, CmssyWebhookError, type CreateCmssyNotFoundOptions, type CreateCmssyPageOptions, type CreateCmssyRobotsOptions, type CreateCmssySitemapOptions, DEFAULT_CMSSY_EDITOR_ORIGINS, SESSION_MAX_AGE_SECONDS, applyCmssyCsp, assertAuthConfig, buildCmssyMetadata, cmssyCspHeaders, createCmssyAuthMiddleware, createCmssyAuthRoute, createCmssyCartRoute, createCmssyLocaleMiddleware, createCmssyNotFound, createCmssyOrdersRoute, createCmssyPage, createCmssyRobots, createCmssySitemap, createDraftRoute, defineCmssyConfig, fetchOrderByToken, fetchProduct, fetchProducts, getCmssyAccessToken, getCmssyLocale, getCmssyUser, isAccessExpired, isCmssyEditMode, isCmssyEditRequest, localeForPathname, openSession, resolveEditorOrigin, resolveLocaleFromPathname, sealSession, sessionCookieOptions, splitCmssyLocale, verifyCmssyWebhook };
|
|
359
|
+
export { type BuildCmssyMetadataOptions, CMSSY_CART_COOKIE, CMSSY_EDIT_HEADER, CMSSY_EDIT_PATH_PREFIX, CMSSY_EDIT_QUERY_PARAM, CMSSY_LOCALE_HEADER, CMSSY_SECRET_QUERY_PARAM, CMSSY_SESSION_COOKIE, type CmssyAuthMiddleware, type CmssyAuthRouteHandlers, type CmssyCartRouteHandlers, type CmssyCspOptions, type CmssyDraftRouteConfig, type CmssyEditorProps, type CmssyEnvConfig, type CmssyNextConfig, type CmssyOrdersRouteHandlers, CmssyWebhookError, type CreateCmssyNotFoundOptions, type CreateCmssyPageOptions, type CreateCmssyRobotsOptions, type CreateCmssySitemapOptions, DEFAULT_CMSSY_EDITOR_ORIGINS, SESSION_MAX_AGE_SECONDS, applyCmssyCsp, assertAuthConfig, buildCmssyMetadata, cmssyCspHeaders, cmssyEditRewrite, createCmssyAuthMiddleware, createCmssyAuthRoute, createCmssyCartRoute, createCmssyEditMiddleware, createCmssyEditPage, createCmssyLocaleMiddleware, createCmssyNotFound, createCmssyOrdersRoute, createCmssyPage, createCmssyRobots, createCmssySitemap, createDraftRoute, defineCmssyConfig, fetchOrderByToken, fetchProduct, fetchProducts, getCmssyAccessToken, getCmssyLocale, getCmssyUser, isAccessExpired, isCmssyEditMode, isCmssyEditRequest, localeForPathname, openSession, resolveEditorOrigin, resolveLocaleFromPathname, sealSession, sessionCookieOptions, splitCmssyLocale, verifyCmssyWebhook };
|
package/dist/index.js
CHANGED
|
@@ -254,6 +254,12 @@ async function resolveEditorRequest(query, draftSecret) {
|
|
|
254
254
|
return cmssySecretsMatch(provided, draftSecret);
|
|
255
255
|
}
|
|
256
256
|
function createCmssyPage(config, blocks, options) {
|
|
257
|
+
return buildCmssyPageRenderer(config, blocks, options, false);
|
|
258
|
+
}
|
|
259
|
+
function createCmssyEditPage(config, blocks, options) {
|
|
260
|
+
return buildCmssyPageRenderer(config, blocks, options, true);
|
|
261
|
+
}
|
|
262
|
+
function buildCmssyPageRenderer(config, blocks, options, editRoute) {
|
|
257
263
|
if (!Array.isArray(blocks)) {
|
|
258
264
|
throw new Error(
|
|
259
265
|
"cmssy: createCmssyPage(config, blocks) requires a blocks array \u2014 pass your defineBlock(...) array"
|
|
@@ -273,8 +279,14 @@ function createCmssyPage(config, blocks, options) {
|
|
|
273
279
|
}) {
|
|
274
280
|
const path = fixedPath ?? (params ? (await params).path ?? void 0 : void 0);
|
|
275
281
|
const { isEnabled } = await draftMode();
|
|
276
|
-
|
|
277
|
-
|
|
282
|
+
let editorActive = false;
|
|
283
|
+
if (editRoute) {
|
|
284
|
+
const query = searchParams ? await searchParams : {};
|
|
285
|
+
editorActive = await resolveEditorRequest(query, config.draftSecret);
|
|
286
|
+
if (!editorActive) {
|
|
287
|
+
notFound();
|
|
288
|
+
}
|
|
289
|
+
}
|
|
278
290
|
const editMode = isEnabled || editorActive;
|
|
279
291
|
const devAllowed = isDevelopment() && Boolean(config.devToken?.trim());
|
|
280
292
|
let locale;
|
|
@@ -385,6 +397,23 @@ function resolveBridgeOrigin(editorOrigin) {
|
|
|
385
397
|
}
|
|
386
398
|
return origins.length === 1 ? origins[0] : origins;
|
|
387
399
|
}
|
|
400
|
+
var CMSSY_EDIT_PATH_PREFIX = "/__cmssy/edit";
|
|
401
|
+
async function cmssyEditRewrite(request2, config) {
|
|
402
|
+
const { pathname, searchParams } = request2.nextUrl;
|
|
403
|
+
if (pathname.startsWith(CMSSY_EDIT_PATH_PREFIX)) return null;
|
|
404
|
+
if (!searchParams.getAll(CMSSY_EDIT_QUERY_PARAM).includes("1")) return null;
|
|
405
|
+
const provided = searchParams.get(CMSSY_SECRET_QUERY_PARAM);
|
|
406
|
+
if (!provided || !config.draftSecret) return null;
|
|
407
|
+
if (!await cmssySecretsMatch(provided, config.draftSecret)) return null;
|
|
408
|
+
const url = request2.nextUrl.clone();
|
|
409
|
+
url.pathname = `${CMSSY_EDIT_PATH_PREFIX}${pathname === "/" ? "" : pathname}`;
|
|
410
|
+
return NextResponse.rewrite(url);
|
|
411
|
+
}
|
|
412
|
+
function createCmssyEditMiddleware(config) {
|
|
413
|
+
return async function cmssyEditMiddleware(request2) {
|
|
414
|
+
return await cmssyEditRewrite(request2, config) ?? NextResponse.next();
|
|
415
|
+
};
|
|
416
|
+
}
|
|
388
417
|
function DefaultNotFound() {
|
|
389
418
|
return /* @__PURE__ */ jsxs(
|
|
390
419
|
"main",
|
|
@@ -697,7 +726,12 @@ async function splitCmssyLocale(config, path) {
|
|
|
697
726
|
const siteLocales = await resolveSiteLocales(config);
|
|
698
727
|
return splitLocaleFromPath(path, siteLocales);
|
|
699
728
|
}
|
|
700
|
-
async function getCmssyLocale(config) {
|
|
729
|
+
async function getCmssyLocale(config, options) {
|
|
730
|
+
if (options?.path !== void 0) {
|
|
731
|
+
const siteLocales = await resolveSiteLocales(config);
|
|
732
|
+
const segments = Array.isArray(options.path) ? options.path.filter(Boolean) : options.path.split("/").filter(Boolean);
|
|
733
|
+
return splitLocaleFromPath(segments, siteLocales).locale;
|
|
734
|
+
}
|
|
701
735
|
const { headers: headers3 } = await import('next/headers');
|
|
702
736
|
const headerList = await headers3();
|
|
703
737
|
const fromHeader = headerList.get(CMSSY_LOCALE_HEADER);
|
|
@@ -1943,4 +1977,4 @@ function verifyCmssyWebhook(options) {
|
|
|
1943
1977
|
return parsed;
|
|
1944
1978
|
}
|
|
1945
1979
|
|
|
1946
|
-
export { CMSSY_CART_COOKIE, CMSSY_EDIT_HEADER, CMSSY_EDIT_QUERY_PARAM, CMSSY_LOCALE_HEADER, CMSSY_SECRET_QUERY_PARAM, CMSSY_SESSION_COOKIE, CmssyWebhookError, DEFAULT_CMSSY_EDITOR_ORIGINS, SESSION_MAX_AGE_SECONDS, applyCmssyCsp, assertAuthConfig, buildCmssyMetadata, cmssyCspHeaders, createCmssyAuthMiddleware, createCmssyAuthRoute, createCmssyCartRoute, createCmssyLocaleMiddleware, createCmssyNotFound, createCmssyOrdersRoute, createCmssyPage, createCmssyRobots, createCmssySitemap, createDraftRoute, defineCmssyConfig, fetchOrderByToken, fetchProduct, fetchProducts, getCmssyAccessToken, getCmssyLocale, getCmssyUser, isAccessExpired, isCmssyEditMode, isCmssyEditRequest, localeForPathname, openSession, resolveEditorOrigin, resolveLocaleFromPathname, sealSession, sessionCookieOptions, splitCmssyLocale, verifyCmssyWebhook };
|
|
1980
|
+
export { CMSSY_CART_COOKIE, CMSSY_EDIT_HEADER, CMSSY_EDIT_PATH_PREFIX, CMSSY_EDIT_QUERY_PARAM, CMSSY_LOCALE_HEADER, CMSSY_SECRET_QUERY_PARAM, CMSSY_SESSION_COOKIE, CmssyWebhookError, DEFAULT_CMSSY_EDITOR_ORIGINS, SESSION_MAX_AGE_SECONDS, applyCmssyCsp, assertAuthConfig, buildCmssyMetadata, cmssyCspHeaders, cmssyEditRewrite, createCmssyAuthMiddleware, createCmssyAuthRoute, createCmssyCartRoute, createCmssyEditMiddleware, createCmssyEditPage, createCmssyLocaleMiddleware, createCmssyNotFound, createCmssyOrdersRoute, createCmssyPage, createCmssyRobots, createCmssySitemap, createDraftRoute, defineCmssyConfig, fetchOrderByToken, fetchProduct, fetchProducts, getCmssyAccessToken, getCmssyLocale, getCmssyUser, isAccessExpired, isCmssyEditMode, isCmssyEditRequest, localeForPathname, openSession, resolveEditorOrigin, resolveLocaleFromPathname, sealSession, sessionCookieOptions, splitCmssyLocale, verifyCmssyWebhook };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmssy/next",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Next.js App Router bindings for cmssy headless sites (createCmssyPage + draft preview)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cmssy",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"dist"
|
|
42
42
|
],
|
|
43
43
|
"peerDependencies": {
|
|
44
|
-
"@cmssy/react": "^
|
|
44
|
+
"@cmssy/react": "^4.0.0",
|
|
45
45
|
"next": ">=15",
|
|
46
46
|
"react": "^18.2.0 || ^19.0.0",
|
|
47
47
|
"react-dom": "^18.2.0 || ^19.0.0"
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"tsup": "^8.3.0",
|
|
56
56
|
"typescript": "^5.6.0",
|
|
57
57
|
"vitest": "^2.1.0",
|
|
58
|
-
"@cmssy/react": "
|
|
58
|
+
"@cmssy/react": "4.0.0"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"jose": "^6.2.3",
|