@cmssy/react 16.7.1 → 16.9.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/client.cjs CHANGED
@@ -650,6 +650,7 @@ var DEBOUNCE_MS = 300;
650
650
  function useBlockLoaderData({
651
651
  enabled,
652
652
  url = CMSSY_BLOCK_DATA_PATH,
653
+ token,
653
654
  blocks,
654
655
  locale,
655
656
  defaultLocale,
@@ -677,7 +678,10 @@ function useBlockLoaderData({
677
678
  try {
678
679
  const response = await fetch(url, {
679
680
  method: "POST",
680
- headers: { "content-type": "application/json" },
681
+ headers: {
682
+ "content-type": "application/json",
683
+ ...token ? { [core.CMSSY_EDIT_TOKEN_HEADER]: token } : {}
684
+ },
681
685
  body: request,
682
686
  signal: controller.signal
683
687
  });
@@ -705,7 +709,7 @@ function useBlockLoaderData({
705
709
  clearTimeout(timer);
706
710
  controller.abort();
707
711
  };
708
- }, [request, url, blocks.length]);
712
+ }, [request, url, token, blocks.length]);
709
713
  return data;
710
714
  }
711
715
 
@@ -984,6 +988,7 @@ function EditableBlocks({
984
988
  const liveData = useBlockLoaderData({
985
989
  enabled: loaderBlocks.length > 0,
986
990
  ...edit.blockDataUrl ? { url: edit.blockDataUrl } : {},
991
+ ...edit.blockDataToken ? { token: edit.blockDataToken } : {},
987
992
  blocks: loaderBlocks,
988
993
  locale,
989
994
  defaultLocale,
package/dist/client.d.cts CHANGED
@@ -9,6 +9,7 @@ interface EditBridgeConfig {
9
9
  blockMeta?: Record<string, BlockMeta>;
10
10
  layoutRegions?: readonly LayoutRegion[] | undefined;
11
11
  blockDataUrl?: string;
12
+ blockDataToken?: string;
12
13
  }
13
14
  type PatchMap = Partial<Record<string, Record<string, unknown>>>;
14
15
  interface InsertedBlock {
package/dist/client.d.ts CHANGED
@@ -9,6 +9,7 @@ interface EditBridgeConfig {
9
9
  blockMeta?: Record<string, BlockMeta>;
10
10
  layoutRegions?: readonly LayoutRegion[] | undefined;
11
11
  blockDataUrl?: string;
12
+ blockDataToken?: string;
12
13
  }
13
14
  type PatchMap = Partial<Record<string, Record<string, unknown>>>;
14
15
  interface InsertedBlock {
package/dist/client.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { useState, useRef, useEffect, useMemo, createElement } from 'react';
3
- import { blocksToMeta, blocksToSchemas, postToEditor, layoutRegionsToBridge, PROTOCOL_VERSION, parseEditorMessage } from '@cmssy/core';
3
+ import { blocksToMeta, blocksToSchemas, postToEditor, layoutRegionsToBridge, PROTOCOL_VERSION, parseEditorMessage, CMSSY_EDIT_TOKEN_HEADER } from '@cmssy/core';
4
4
  import { resolveInitialTarget, buildBlockContext, getBlockContentForLanguage, normalizeBlockContent, asBucket } from '@cmssy/core/internal';
5
5
  import { BlockErrorBoundary } from '@cmssy/react/block-error-boundary';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -648,6 +648,7 @@ var DEBOUNCE_MS = 300;
648
648
  function useBlockLoaderData({
649
649
  enabled,
650
650
  url = CMSSY_BLOCK_DATA_PATH,
651
+ token,
651
652
  blocks,
652
653
  locale,
653
654
  defaultLocale,
@@ -675,7 +676,10 @@ function useBlockLoaderData({
675
676
  try {
676
677
  const response = await fetch(url, {
677
678
  method: "POST",
678
- headers: { "content-type": "application/json" },
679
+ headers: {
680
+ "content-type": "application/json",
681
+ ...token ? { [CMSSY_EDIT_TOKEN_HEADER]: token } : {}
682
+ },
679
683
  body: request,
680
684
  signal: controller.signal
681
685
  });
@@ -703,7 +707,7 @@ function useBlockLoaderData({
703
707
  clearTimeout(timer);
704
708
  controller.abort();
705
709
  };
706
- }, [request, url, blocks.length]);
710
+ }, [request, url, token, blocks.length]);
707
711
  return data;
708
712
  }
709
713
 
@@ -982,6 +986,7 @@ function EditableBlocks({
982
986
  const liveData = useBlockLoaderData({
983
987
  enabled: loaderBlocks.length > 0,
984
988
  ...edit.blockDataUrl ? { url: edit.blockDataUrl } : {},
989
+ ...edit.blockDataToken ? { token: edit.blockDataToken } : {},
985
990
  blocks: loaderBlocks,
986
991
  locale,
987
992
  defaultLocale,
package/dist/index.cjs CHANGED
@@ -734,6 +734,44 @@ async function handleBlockDataRequest(body, options) {
734
734
  headers: { "cache-control": "no-store" }
735
735
  });
736
736
  }
737
+ function pageOf(body) {
738
+ if (typeof body !== "object" || body === null) return "";
739
+ const page = body.page;
740
+ if (typeof page !== "object" || page === null) return "";
741
+ const slug = page.slug;
742
+ return typeof slug === "string" ? slug : "";
743
+ }
744
+ function createBlockDataHandler(config, blocks, options = {}) {
745
+ return async function handle(request) {
746
+ if (!config.draftSecret) {
747
+ return new Response(
748
+ "cmssy: the block data route needs config.draftSecret to verify the editor",
749
+ { status: 500 }
750
+ );
751
+ }
752
+ let body;
753
+ try {
754
+ body = await request.json();
755
+ } catch {
756
+ return Response.json(
757
+ { message: "cmssy: body is not JSON" },
758
+ { status: 400 }
759
+ );
760
+ }
761
+ const authorized = await core.verifyCmssyEditToken(
762
+ request.headers.get(core.CMSSY_EDIT_TOKEN_HEADER),
763
+ config.draftSecret,
764
+ { page: pageOf(body) }
765
+ );
766
+ if (!authorized) {
767
+ return new Response(
768
+ "cmssy: block data needs the edit token the editor page was rendered with",
769
+ { status: 403 }
770
+ );
771
+ }
772
+ return handleBlockDataRequest(body, { blocks, config, ...options });
773
+ };
774
+ }
737
775
 
738
776
  Object.defineProperty(exports, "CmssyRequestError", {
739
777
  enumerable: true,
@@ -796,6 +834,7 @@ exports.CmssyServerLayout = CmssyServerLayout;
796
834
  exports.CmssyServerPage = CmssyServerPage;
797
835
  exports.UnknownBlock = UnknownBlock;
798
836
  exports.buildBlockMap = buildBlockMap;
837
+ exports.createBlockDataHandler = createBlockDataHandler;
799
838
  exports.defineBlock = defineBlock;
800
839
  exports.handleBlockDataRequest = handleBlockDataRequest;
801
840
  exports.parseBlockDataRequest = parseBlockDataRequest;
package/dist/index.d.cts CHANGED
@@ -7,7 +7,7 @@ export { FieldCondition, FieldConditionGroup, FieldConditionLogic } from '@cmssy
7
7
  export { buildBlockContext } from '@cmssy/core/internal';
8
8
  import * as react_jsx_runtime from 'react/jsx-runtime';
9
9
  import { ReactElement, ComponentType } from 'react';
10
- export { CmssyBlockDataRequest, CmssyBlockDataRequestBlock, CmssyBlockDataRequestPage, CmssyBlockDataResult, ResolveBlockDataRequestOptions, handleBlockDataRequest, parseBlockDataRequest, resolveBlockDataRequest } from './internal-server.cjs';
10
+ export { CmssyBlockDataHandlerOptions, CmssyBlockDataRequest, CmssyBlockDataRequestBlock, CmssyBlockDataRequestPage, CmssyBlockDataResult, ResolveBlockDataRequestOptions, createBlockDataHandler, handleBlockDataRequest, parseBlockDataRequest, resolveBlockDataRequest } from './internal-server.cjs';
11
11
 
12
12
  interface CmssyServerPageProps {
13
13
  page: CmssyPageData | null;
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@ export { FieldCondition, FieldConditionGroup, FieldConditionLogic } from '@cmssy
7
7
  export { buildBlockContext } from '@cmssy/core/internal';
8
8
  import * as react_jsx_runtime from 'react/jsx-runtime';
9
9
  import { ReactElement, ComponentType } from 'react';
10
- export { CmssyBlockDataRequest, CmssyBlockDataRequestBlock, CmssyBlockDataRequestPage, CmssyBlockDataResult, ResolveBlockDataRequestOptions, handleBlockDataRequest, parseBlockDataRequest, resolveBlockDataRequest } from './internal-server.js';
10
+ export { CmssyBlockDataHandlerOptions, CmssyBlockDataRequest, CmssyBlockDataRequestBlock, CmssyBlockDataRequestPage, CmssyBlockDataResult, ResolveBlockDataRequestOptions, createBlockDataHandler, handleBlockDataRequest, parseBlockDataRequest, resolveBlockDataRequest } from './internal-server.js';
11
11
 
12
12
  interface CmssyServerPageProps {
13
13
  page: CmssyPageData | null;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { blocksToSchemas, resolveEditorOrigin } from '@cmssy/core';
1
+ import { blocksToSchemas, resolveEditorOrigin, verifyCmssyEditToken, CMSSY_EDIT_TOKEN_HEADER } from '@cmssy/core';
2
2
  export { CmssyRequestError, PROTOCOL_VERSION, createCmssyClient, defineCmssyLayout, fields, graphqlRequest, isProtocolCompatible, mediaAlt, mediaUrl, mediaUrls, normalizeOrigin, parseEditorMessage, postToEditor } from '@cmssy/core';
3
3
  import { buildBlockContext, fetchLayouts, normalizeBlockContent, asBucket, resolveSiteLocales as resolveSiteLocales$1, getBlockContentForLanguage, resolveRelationContent } from '@cmssy/core/internal';
4
4
  export { buildBlockContext } from '@cmssy/core/internal';
@@ -734,5 +734,43 @@ async function handleBlockDataRequest(body, options) {
734
734
  headers: { "cache-control": "no-store" }
735
735
  });
736
736
  }
737
+ function pageOf(body) {
738
+ if (typeof body !== "object" || body === null) return "";
739
+ const page = body.page;
740
+ if (typeof page !== "object" || page === null) return "";
741
+ const slug = page.slug;
742
+ return typeof slug === "string" ? slug : "";
743
+ }
744
+ function createBlockDataHandler(config, blocks, options = {}) {
745
+ return async function handle(request) {
746
+ if (!config.draftSecret) {
747
+ return new Response(
748
+ "cmssy: the block data route needs config.draftSecret to verify the editor",
749
+ { status: 500 }
750
+ );
751
+ }
752
+ let body;
753
+ try {
754
+ body = await request.json();
755
+ } catch {
756
+ return Response.json(
757
+ { message: "cmssy: body is not JSON" },
758
+ { status: 400 }
759
+ );
760
+ }
761
+ const authorized = await verifyCmssyEditToken(
762
+ request.headers.get(CMSSY_EDIT_TOKEN_HEADER),
763
+ config.draftSecret,
764
+ { page: pageOf(body) }
765
+ );
766
+ if (!authorized) {
767
+ return new Response(
768
+ "cmssy: block data needs the edit token the editor page was rendered with",
769
+ { status: 403 }
770
+ );
771
+ }
772
+ return handleBlockDataRequest(body, { blocks, config, ...options });
773
+ };
774
+ }
737
775
 
738
- export { CmssyBlock, CmssyServerLayout, CmssyServerPage, UnknownBlock, buildBlockMap, defineBlock, handleBlockDataRequest, parseBlockDataRequest, resolveBlockDataRequest, resolveCmssyLayout, resolveCmssyLayoutSlot, resolveEditorBlockData, resolveEditorLayoutBlockData };
776
+ export { CmssyBlock, CmssyServerLayout, CmssyServerPage, UnknownBlock, buildBlockMap, createBlockDataHandler, defineBlock, handleBlockDataRequest, parseBlockDataRequest, resolveBlockDataRequest, resolveCmssyLayout, resolveCmssyLayoutSlot, resolveEditorBlockData, resolveEditorLayoutBlockData };
@@ -264,11 +264,50 @@ async function handleBlockDataRequest(body, options) {
264
264
  headers: { "cache-control": "no-store" }
265
265
  });
266
266
  }
267
+ function pageOf(body) {
268
+ if (typeof body !== "object" || body === null) return "";
269
+ const page = body.page;
270
+ if (typeof page !== "object" || page === null) return "";
271
+ const slug = page.slug;
272
+ return typeof slug === "string" ? slug : "";
273
+ }
274
+ function createBlockDataHandler(config, blocks, options = {}) {
275
+ return async function handle(request) {
276
+ if (!config.draftSecret) {
277
+ return new Response(
278
+ "cmssy: the block data route needs config.draftSecret to verify the editor",
279
+ { status: 500 }
280
+ );
281
+ }
282
+ let body;
283
+ try {
284
+ body = await request.json();
285
+ } catch {
286
+ return Response.json(
287
+ { message: "cmssy: body is not JSON" },
288
+ { status: 400 }
289
+ );
290
+ }
291
+ const authorized = await core.verifyCmssyEditToken(
292
+ request.headers.get(core.CMSSY_EDIT_TOKEN_HEADER),
293
+ config.draftSecret,
294
+ { page: pageOf(body) }
295
+ );
296
+ if (!authorized) {
297
+ return new Response(
298
+ "cmssy: block data needs the edit token the editor page was rendered with",
299
+ { status: 403 }
300
+ );
301
+ }
302
+ return handleBlockDataRequest(body, { blocks, config, ...options });
303
+ };
304
+ }
267
305
 
268
306
  Object.defineProperty(exports, "blocksToSchemas", {
269
307
  enumerable: true,
270
308
  get: function () { return core.blocksToSchemas; }
271
309
  });
310
+ exports.createBlockDataHandler = createBlockDataHandler;
272
311
  exports.handleBlockDataRequest = handleBlockDataRequest;
273
312
  exports.parseBlockDataRequest = parseBlockDataRequest;
274
313
  exports.resolveBlockData = resolveBlockData;
@@ -42,4 +42,13 @@ declare function parseBlockDataRequest(body: unknown): CmssyBlockDataRequest;
42
42
  declare function resolveBlockDataRequest(request: CmssyBlockDataRequest, options: ResolveBlockDataRequestOptions): Promise<CmssyBlockDataResult>;
43
43
  declare function handleBlockDataRequest(body: unknown, options: ResolveBlockDataRequestOptions): Promise<Response>;
44
44
 
45
- export { type CmssyBlockDataRequest, type CmssyBlockDataRequestBlock, type CmssyBlockDataRequestPage, type CmssyBlockDataResult, type ResolveBlockDataRequestOptions, handleBlockDataRequest, parseBlockDataRequest, resolveBlockDataRequest };
45
+ interface CmssyBlockDataHandlerOptions {
46
+ forms?: Record<string, CmssyFormDefinition>;
47
+ appContext?: Record<string, unknown>;
48
+ workspaceId?: string;
49
+ }
50
+ declare function createBlockDataHandler(config: CmssyClientConfig & {
51
+ draftSecret?: string;
52
+ }, blocks: BlockDefinition[], options?: CmssyBlockDataHandlerOptions): (request: Request) => Promise<Response>;
53
+
54
+ export { type CmssyBlockDataHandlerOptions, type CmssyBlockDataRequest, type CmssyBlockDataRequestBlock, type CmssyBlockDataRequestPage, type CmssyBlockDataResult, type ResolveBlockDataRequestOptions, createBlockDataHandler, handleBlockDataRequest, parseBlockDataRequest, resolveBlockDataRequest };
@@ -42,4 +42,13 @@ declare function parseBlockDataRequest(body: unknown): CmssyBlockDataRequest;
42
42
  declare function resolveBlockDataRequest(request: CmssyBlockDataRequest, options: ResolveBlockDataRequestOptions): Promise<CmssyBlockDataResult>;
43
43
  declare function handleBlockDataRequest(body: unknown, options: ResolveBlockDataRequestOptions): Promise<Response>;
44
44
 
45
- export { type CmssyBlockDataRequest, type CmssyBlockDataRequestBlock, type CmssyBlockDataRequestPage, type CmssyBlockDataResult, type ResolveBlockDataRequestOptions, handleBlockDataRequest, parseBlockDataRequest, resolveBlockDataRequest };
45
+ interface CmssyBlockDataHandlerOptions {
46
+ forms?: Record<string, CmssyFormDefinition>;
47
+ appContext?: Record<string, unknown>;
48
+ workspaceId?: string;
49
+ }
50
+ declare function createBlockDataHandler(config: CmssyClientConfig & {
51
+ draftSecret?: string;
52
+ }, blocks: BlockDefinition[], options?: CmssyBlockDataHandlerOptions): (request: Request) => Promise<Response>;
53
+
54
+ export { type CmssyBlockDataHandlerOptions, type CmssyBlockDataRequest, type CmssyBlockDataRequestBlock, type CmssyBlockDataRequestPage, type CmssyBlockDataResult, type ResolveBlockDataRequestOptions, createBlockDataHandler, handleBlockDataRequest, parseBlockDataRequest, resolveBlockDataRequest };
@@ -1,5 +1,5 @@
1
1
  import { buildBlockContext, getBlockContentForLanguage, resolveRelationContent, normalizeBlockContent } from '@cmssy/core/internal';
2
- import { blocksToSchemas } from '@cmssy/core';
2
+ import { blocksToSchemas, verifyCmssyEditToken, CMSSY_EDIT_TOKEN_HEADER } from '@cmssy/core';
3
3
  export { blocksToSchemas } from '@cmssy/core';
4
4
 
5
5
  // src/components/resolve-block-data.ts
@@ -263,5 +263,43 @@ async function handleBlockDataRequest(body, options) {
263
263
  headers: { "cache-control": "no-store" }
264
264
  });
265
265
  }
266
+ function pageOf(body) {
267
+ if (typeof body !== "object" || body === null) return "";
268
+ const page = body.page;
269
+ if (typeof page !== "object" || page === null) return "";
270
+ const slug = page.slug;
271
+ return typeof slug === "string" ? slug : "";
272
+ }
273
+ function createBlockDataHandler(config, blocks, options = {}) {
274
+ return async function handle(request) {
275
+ if (!config.draftSecret) {
276
+ return new Response(
277
+ "cmssy: the block data route needs config.draftSecret to verify the editor",
278
+ { status: 500 }
279
+ );
280
+ }
281
+ let body;
282
+ try {
283
+ body = await request.json();
284
+ } catch {
285
+ return Response.json(
286
+ { message: "cmssy: body is not JSON" },
287
+ { status: 400 }
288
+ );
289
+ }
290
+ const authorized = await verifyCmssyEditToken(
291
+ request.headers.get(CMSSY_EDIT_TOKEN_HEADER),
292
+ config.draftSecret,
293
+ { page: pageOf(body) }
294
+ );
295
+ if (!authorized) {
296
+ return new Response(
297
+ "cmssy: block data needs the edit token the editor page was rendered with",
298
+ { status: 403 }
299
+ );
300
+ }
301
+ return handleBlockDataRequest(body, { blocks, config, ...options });
302
+ };
303
+ }
266
304
 
267
- export { handleBlockDataRequest, parseBlockDataRequest, resolveBlockData, resolveBlockDataRequest, resolveEditorBlockData, resolveEditorLayoutBlockData, resolveLayoutBlockData };
305
+ export { createBlockDataHandler, handleBlockDataRequest, parseBlockDataRequest, resolveBlockData, resolveBlockDataRequest, resolveEditorBlockData, resolveEditorLayoutBlockData, resolveLayoutBlockData };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmssy/react",
3
- "version": "16.7.1",
3
+ "version": "16.9.0",
4
4
  "description": "React blocks, renderers, data client and editor bridge for cmssy headless sites",
5
5
  "keywords": [
6
6
  "cmssy",
@@ -97,7 +97,7 @@
97
97
  },
98
98
  "dependencies": {
99
99
  "@cmssy/types": "0.49.0",
100
- "@cmssy/core": "16.7.1"
100
+ "@cmssy/core": "16.9.0"
101
101
  },
102
102
  "scripts": {
103
103
  "build": "tsup",