@cmssy/react 0.17.0 → 0.17.1

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
@@ -44,22 +44,37 @@ var PROTOCOL_VERSION = 2;
44
44
 
45
45
  // src/bridge/messages.ts
46
46
  function normalizeOrigin(origin) {
47
- if (origin === "*") return "*";
47
+ const trimmed = origin.trim();
48
+ if (trimmed === "*") return "*";
48
49
  try {
49
- return new URL(origin).origin;
50
+ return new URL(trimmed).origin;
50
51
  } catch {
51
- return origin;
52
+ return trimmed;
52
53
  }
53
54
  }
54
55
  function postToEditor(target, editorOrigin, message) {
55
56
  target.postMessage(message, normalizeOrigin(editorOrigin));
56
57
  }
58
+ function isOriginAllowed(origin, allowed) {
59
+ const list = Array.isArray(allowed) ? allowed : [allowed];
60
+ const actual = normalizeOrigin(origin);
61
+ return list.some((candidate) => {
62
+ const expected = normalizeOrigin(candidate);
63
+ return expected === "*" || expected === actual;
64
+ });
65
+ }
66
+ function resolveInitialTarget(editorOrigin) {
67
+ const list = (Array.isArray(editorOrigin) ? editorOrigin : [editorOrigin]).map((origin) => normalizeOrigin(origin));
68
+ if (list.includes("*")) return "*";
69
+ if (list.length === 1) return list[0];
70
+ const referrerOrigin = typeof document !== "undefined" && document.referrer ? normalizeOrigin(document.referrer) : "";
71
+ return list.find((origin) => origin === referrerOrigin) ?? list[0];
72
+ }
57
73
  function isObject(value) {
58
74
  return typeof value === "object" && value !== null && !Array.isArray(value);
59
75
  }
60
76
  function parseEditorMessage(data, origin, expectedOrigin) {
61
- const expected = normalizeOrigin(expectedOrigin);
62
- if (expected !== "*" && origin !== expected) return null;
77
+ if (!isOriginAllowed(origin, expectedOrigin)) return null;
63
78
  if (!isObject(data)) return null;
64
79
  switch (data.type) {
65
80
  case "cmssy:select":
@@ -174,7 +189,9 @@ function useEditBridge(page, config) {
174
189
  react.useEffect(() => {
175
190
  if (typeof window === "undefined" || window.parent === window) return;
176
191
  const { editorOrigin } = config;
177
- if (editorOrigin === "*" && typeof console !== "undefined") {
192
+ let postTarget = resolveInitialTarget(editorOrigin);
193
+ const isWildcard = Array.isArray(editorOrigin) ? editorOrigin.includes("*") : editorOrigin === "*";
194
+ if (isWildcard && typeof console !== "undefined") {
178
195
  console.warn(
179
196
  "[cmssy] editorOrigin '*' disables origin checks - dev only, do not use in production"
180
197
  );
@@ -183,7 +200,7 @@ function useEditBridge(page, config) {
183
200
  try {
184
201
  const rects = collectRects();
185
202
  const pageIds = new Set(blocks.map((b) => b.id));
186
- postToEditor(window.parent, editorOrigin, {
203
+ postToEditor(window.parent, postTarget, {
187
204
  type: "cmssy:ready",
188
205
  protocolVersion: PROTOCOL_VERSION,
189
206
  blocks: [
@@ -211,6 +228,7 @@ function useEditBridge(page, config) {
211
228
  editorOrigin
212
229
  );
213
230
  if (!message) return;
231
+ postTarget = event.origin;
214
232
  if (message.type === "cmssy:patch") {
215
233
  if (message.layoutPosition !== void 0) return;
216
234
  setPatches((prev) => ({
@@ -268,7 +286,7 @@ function useEditBridge(page, config) {
268
286
  const r = el.getBoundingClientRect();
269
287
  const layoutPosition = el.getAttribute("data-layout-position");
270
288
  try {
271
- postToEditor(window.parent, editorOrigin, {
289
+ postToEditor(window.parent, postTarget, {
272
290
  type: "cmssy:click",
273
291
  blockId: id,
274
292
  rect: { x: r.x, y: r.y, width: r.width, height: r.height },
@@ -293,7 +311,7 @@ function useEditBridge(page, config) {
293
311
  if (!el) return;
294
312
  const r = el.getBoundingClientRect();
295
313
  try {
296
- postToEditor(window.parent, editorOrigin, {
314
+ postToEditor(window.parent, postTarget, {
297
315
  type: "cmssy:bounds",
298
316
  blockId: id,
299
317
  rect: { x: r.x, y: r.y, width: r.width, height: r.height }
@@ -383,7 +401,9 @@ function useDragAgent(config) {
383
401
  react.useEffect(() => {
384
402
  if (typeof window === "undefined" || window.parent === window) return;
385
403
  const { editorOrigin } = config;
386
- if (editorOrigin === "*" && typeof console !== "undefined") {
404
+ let postTarget = resolveInitialTarget(editorOrigin);
405
+ const isWildcard = Array.isArray(editorOrigin) ? editorOrigin.includes("*") : editorOrigin === "*";
406
+ if (isWildcard && typeof console !== "undefined") {
387
407
  console.warn(
388
408
  "[cmssy] editorOrigin '*' disables origin checks - dev only, do not use in production"
389
409
  );
@@ -419,7 +439,7 @@ function useDragAgent(config) {
419
439
  updateDropY(null);
420
440
  resolver.invalidate();
421
441
  try {
422
- postToEditor(window.parent, editorOrigin, {
442
+ postToEditor(window.parent, postTarget, {
423
443
  type: "cmssy:move",
424
444
  protocolVersion: PROTOCOL_VERSION,
425
445
  blockId,
@@ -441,6 +461,7 @@ function useDragAgent(config) {
441
461
  editorOrigin
442
462
  );
443
463
  if (!message) return;
464
+ postTarget = event.origin;
444
465
  if (message.type === "cmssy:drag-over") {
445
466
  const edge = 64;
446
467
  const step = 20;
@@ -452,7 +473,7 @@ function useDragAgent(config) {
452
473
  const { index, y } = resolver.resolve(message.y);
453
474
  updateDropY(y);
454
475
  try {
455
- postToEditor(window.parent, editorOrigin, {
476
+ postToEditor(window.parent, postTarget, {
456
477
  type: "cmssy:drag-index",
457
478
  protocolVersion: PROTOCOL_VERSION,
458
479
  index
package/dist/client.d.cts CHANGED
@@ -5,7 +5,7 @@ import { ReactNode } from 'react';
5
5
  import '@cmssy/types';
6
6
 
7
7
  interface EditBridgeConfig {
8
- editorOrigin: string;
8
+ editorOrigin: string | string[];
9
9
  schemas?: Record<string, BlockSchema>;
10
10
  blockMeta?: Record<string, BlockMeta>;
11
11
  }
package/dist/client.d.ts CHANGED
@@ -5,7 +5,7 @@ import { ReactNode } from 'react';
5
5
  import '@cmssy/types';
6
6
 
7
7
  interface EditBridgeConfig {
8
- editorOrigin: string;
8
+ editorOrigin: string | string[];
9
9
  schemas?: Record<string, BlockSchema>;
10
10
  blockMeta?: Record<string, BlockMeta>;
11
11
  }
package/dist/client.js CHANGED
@@ -42,22 +42,37 @@ var PROTOCOL_VERSION = 2;
42
42
 
43
43
  // src/bridge/messages.ts
44
44
  function normalizeOrigin(origin) {
45
- if (origin === "*") return "*";
45
+ const trimmed = origin.trim();
46
+ if (trimmed === "*") return "*";
46
47
  try {
47
- return new URL(origin).origin;
48
+ return new URL(trimmed).origin;
48
49
  } catch {
49
- return origin;
50
+ return trimmed;
50
51
  }
51
52
  }
52
53
  function postToEditor(target, editorOrigin, message) {
53
54
  target.postMessage(message, normalizeOrigin(editorOrigin));
54
55
  }
56
+ function isOriginAllowed(origin, allowed) {
57
+ const list = Array.isArray(allowed) ? allowed : [allowed];
58
+ const actual = normalizeOrigin(origin);
59
+ return list.some((candidate) => {
60
+ const expected = normalizeOrigin(candidate);
61
+ return expected === "*" || expected === actual;
62
+ });
63
+ }
64
+ function resolveInitialTarget(editorOrigin) {
65
+ const list = (Array.isArray(editorOrigin) ? editorOrigin : [editorOrigin]).map((origin) => normalizeOrigin(origin));
66
+ if (list.includes("*")) return "*";
67
+ if (list.length === 1) return list[0];
68
+ const referrerOrigin = typeof document !== "undefined" && document.referrer ? normalizeOrigin(document.referrer) : "";
69
+ return list.find((origin) => origin === referrerOrigin) ?? list[0];
70
+ }
55
71
  function isObject(value) {
56
72
  return typeof value === "object" && value !== null && !Array.isArray(value);
57
73
  }
58
74
  function parseEditorMessage(data, origin, expectedOrigin) {
59
- const expected = normalizeOrigin(expectedOrigin);
60
- if (expected !== "*" && origin !== expected) return null;
75
+ if (!isOriginAllowed(origin, expectedOrigin)) return null;
61
76
  if (!isObject(data)) return null;
62
77
  switch (data.type) {
63
78
  case "cmssy:select":
@@ -172,7 +187,9 @@ function useEditBridge(page, config) {
172
187
  useEffect(() => {
173
188
  if (typeof window === "undefined" || window.parent === window) return;
174
189
  const { editorOrigin } = config;
175
- if (editorOrigin === "*" && typeof console !== "undefined") {
190
+ let postTarget = resolveInitialTarget(editorOrigin);
191
+ const isWildcard = Array.isArray(editorOrigin) ? editorOrigin.includes("*") : editorOrigin === "*";
192
+ if (isWildcard && typeof console !== "undefined") {
176
193
  console.warn(
177
194
  "[cmssy] editorOrigin '*' disables origin checks - dev only, do not use in production"
178
195
  );
@@ -181,7 +198,7 @@ function useEditBridge(page, config) {
181
198
  try {
182
199
  const rects = collectRects();
183
200
  const pageIds = new Set(blocks.map((b) => b.id));
184
- postToEditor(window.parent, editorOrigin, {
201
+ postToEditor(window.parent, postTarget, {
185
202
  type: "cmssy:ready",
186
203
  protocolVersion: PROTOCOL_VERSION,
187
204
  blocks: [
@@ -209,6 +226,7 @@ function useEditBridge(page, config) {
209
226
  editorOrigin
210
227
  );
211
228
  if (!message) return;
229
+ postTarget = event.origin;
212
230
  if (message.type === "cmssy:patch") {
213
231
  if (message.layoutPosition !== void 0) return;
214
232
  setPatches((prev) => ({
@@ -266,7 +284,7 @@ function useEditBridge(page, config) {
266
284
  const r = el.getBoundingClientRect();
267
285
  const layoutPosition = el.getAttribute("data-layout-position");
268
286
  try {
269
- postToEditor(window.parent, editorOrigin, {
287
+ postToEditor(window.parent, postTarget, {
270
288
  type: "cmssy:click",
271
289
  blockId: id,
272
290
  rect: { x: r.x, y: r.y, width: r.width, height: r.height },
@@ -291,7 +309,7 @@ function useEditBridge(page, config) {
291
309
  if (!el) return;
292
310
  const r = el.getBoundingClientRect();
293
311
  try {
294
- postToEditor(window.parent, editorOrigin, {
312
+ postToEditor(window.parent, postTarget, {
295
313
  type: "cmssy:bounds",
296
314
  blockId: id,
297
315
  rect: { x: r.x, y: r.y, width: r.width, height: r.height }
@@ -381,7 +399,9 @@ function useDragAgent(config) {
381
399
  useEffect(() => {
382
400
  if (typeof window === "undefined" || window.parent === window) return;
383
401
  const { editorOrigin } = config;
384
- if (editorOrigin === "*" && typeof console !== "undefined") {
402
+ let postTarget = resolveInitialTarget(editorOrigin);
403
+ const isWildcard = Array.isArray(editorOrigin) ? editorOrigin.includes("*") : editorOrigin === "*";
404
+ if (isWildcard && typeof console !== "undefined") {
385
405
  console.warn(
386
406
  "[cmssy] editorOrigin '*' disables origin checks - dev only, do not use in production"
387
407
  );
@@ -417,7 +437,7 @@ function useDragAgent(config) {
417
437
  updateDropY(null);
418
438
  resolver.invalidate();
419
439
  try {
420
- postToEditor(window.parent, editorOrigin, {
440
+ postToEditor(window.parent, postTarget, {
421
441
  type: "cmssy:move",
422
442
  protocolVersion: PROTOCOL_VERSION,
423
443
  blockId,
@@ -439,6 +459,7 @@ function useDragAgent(config) {
439
459
  editorOrigin
440
460
  );
441
461
  if (!message) return;
462
+ postTarget = event.origin;
442
463
  if (message.type === "cmssy:drag-over") {
443
464
  const edge = 64;
444
465
  const step = 20;
@@ -450,7 +471,7 @@ function useDragAgent(config) {
450
471
  const { index, y } = resolver.resolve(message.y);
451
472
  updateDropY(y);
452
473
  try {
453
- postToEditor(window.parent, editorOrigin, {
474
+ postToEditor(window.parent, postTarget, {
454
475
  type: "cmssy:drag-index",
455
476
  protocolVersion: PROTOCOL_VERSION,
456
477
  index
package/dist/index.cjs CHANGED
@@ -239,22 +239,30 @@ function isProtocolCompatible(version) {
239
239
 
240
240
  // src/bridge/messages.ts
241
241
  function normalizeOrigin(origin) {
242
- if (origin === "*") return "*";
242
+ const trimmed = origin.trim();
243
+ if (trimmed === "*") return "*";
243
244
  try {
244
- return new URL(origin).origin;
245
+ return new URL(trimmed).origin;
245
246
  } catch {
246
- return origin;
247
+ return trimmed;
247
248
  }
248
249
  }
249
250
  function postToEditor(target, editorOrigin, message) {
250
251
  target.postMessage(message, normalizeOrigin(editorOrigin));
251
252
  }
253
+ function isOriginAllowed(origin, allowed) {
254
+ const list = Array.isArray(allowed) ? allowed : [allowed];
255
+ const actual = normalizeOrigin(origin);
256
+ return list.some((candidate) => {
257
+ const expected = normalizeOrigin(candidate);
258
+ return expected === "*" || expected === actual;
259
+ });
260
+ }
252
261
  function isObject(value) {
253
262
  return typeof value === "object" && value !== null && !Array.isArray(value);
254
263
  }
255
264
  function parseEditorMessage(data, origin, expectedOrigin) {
256
- const expected = normalizeOrigin(expectedOrigin);
257
- if (expected !== "*" && origin !== expected) return null;
265
+ if (!isOriginAllowed(origin, expectedOrigin)) return null;
258
266
  if (!isObject(data)) return null;
259
267
  switch (data.type) {
260
268
  case "cmssy:select":
@@ -749,23 +757,23 @@ function createCmssyClient(input) {
749
757
  return {
750
758
  config,
751
759
  resolveWorkspaceId: resolveWorkspaceId2,
752
- query(document, variables = {}, options) {
760
+ query(document2, variables = {}, options) {
753
761
  return graphqlRequest(
754
762
  config,
755
- document,
763
+ document2,
756
764
  variables,
757
765
  options,
758
766
  "graphql operation"
759
767
  );
760
768
  },
761
- async queryScoped(document, variables = {}, options = {}) {
769
+ async queryScoped(document2, variables = {}, options = {}) {
762
770
  const { workspaceId: provided, headers, ...rest } = options;
763
771
  const workspaceId = provided ?? await resolveWorkspaceId2({ ...rest, headers });
764
772
  const hasWorkspaceId = variables.workspaceId !== void 0 && variables.workspaceId !== null;
765
- const scopedVariables = /\$workspaceId\b/.test(document) && !hasWorkspaceId ? { ...variables, workspaceId } : variables;
773
+ const scopedVariables = /\$workspaceId\b/.test(document2) && !hasWorkspaceId ? { ...variables, workspaceId } : variables;
766
774
  return graphqlRequest(
767
775
  config,
768
- document,
776
+ document2,
769
777
  scopedVariables,
770
778
  { ...rest, headers: { ...headers, "x-workspace-id": workspaceId } },
771
779
  "graphql operation"
package/dist/index.d.cts CHANGED
@@ -68,7 +68,7 @@ interface PostTarget {
68
68
  }
69
69
  declare function normalizeOrigin(origin: string): string;
70
70
  declare function postToEditor(target: PostTarget, editorOrigin: string, message: AppToEditorMessage): void;
71
- declare function parseEditorMessage(data: unknown, origin: string, expectedOrigin: string): EditorToAppMessage | null;
71
+ declare function parseEditorMessage(data: unknown, origin: string, expectedOrigin: string | string[]): EditorToAppMessage | null;
72
72
 
73
73
  declare function getBlockContentForLanguage(content: unknown, locale: string, defaultLocale?: string, availableLocales?: string[]): Record<string, unknown>;
74
74
 
package/dist/index.d.ts CHANGED
@@ -68,7 +68,7 @@ interface PostTarget {
68
68
  }
69
69
  declare function normalizeOrigin(origin: string): string;
70
70
  declare function postToEditor(target: PostTarget, editorOrigin: string, message: AppToEditorMessage): void;
71
- declare function parseEditorMessage(data: unknown, origin: string, expectedOrigin: string): EditorToAppMessage | null;
71
+ declare function parseEditorMessage(data: unknown, origin: string, expectedOrigin: string | string[]): EditorToAppMessage | null;
72
72
 
73
73
  declare function getBlockContentForLanguage(content: unknown, locale: string, defaultLocale?: string, availableLocales?: string[]): Record<string, unknown>;
74
74
 
package/dist/index.js CHANGED
@@ -237,22 +237,30 @@ function isProtocolCompatible(version) {
237
237
 
238
238
  // src/bridge/messages.ts
239
239
  function normalizeOrigin(origin) {
240
- if (origin === "*") return "*";
240
+ const trimmed = origin.trim();
241
+ if (trimmed === "*") return "*";
241
242
  try {
242
- return new URL(origin).origin;
243
+ return new URL(trimmed).origin;
243
244
  } catch {
244
- return origin;
245
+ return trimmed;
245
246
  }
246
247
  }
247
248
  function postToEditor(target, editorOrigin, message) {
248
249
  target.postMessage(message, normalizeOrigin(editorOrigin));
249
250
  }
251
+ function isOriginAllowed(origin, allowed) {
252
+ const list = Array.isArray(allowed) ? allowed : [allowed];
253
+ const actual = normalizeOrigin(origin);
254
+ return list.some((candidate) => {
255
+ const expected = normalizeOrigin(candidate);
256
+ return expected === "*" || expected === actual;
257
+ });
258
+ }
250
259
  function isObject(value) {
251
260
  return typeof value === "object" && value !== null && !Array.isArray(value);
252
261
  }
253
262
  function parseEditorMessage(data, origin, expectedOrigin) {
254
- const expected = normalizeOrigin(expectedOrigin);
255
- if (expected !== "*" && origin !== expected) return null;
263
+ if (!isOriginAllowed(origin, expectedOrigin)) return null;
256
264
  if (!isObject(data)) return null;
257
265
  switch (data.type) {
258
266
  case "cmssy:select":
@@ -747,23 +755,23 @@ function createCmssyClient(input) {
747
755
  return {
748
756
  config,
749
757
  resolveWorkspaceId: resolveWorkspaceId2,
750
- query(document, variables = {}, options) {
758
+ query(document2, variables = {}, options) {
751
759
  return graphqlRequest(
752
760
  config,
753
- document,
761
+ document2,
754
762
  variables,
755
763
  options,
756
764
  "graphql operation"
757
765
  );
758
766
  },
759
- async queryScoped(document, variables = {}, options = {}) {
767
+ async queryScoped(document2, variables = {}, options = {}) {
760
768
  const { workspaceId: provided, headers, ...rest } = options;
761
769
  const workspaceId = provided ?? await resolveWorkspaceId2({ ...rest, headers });
762
770
  const hasWorkspaceId = variables.workspaceId !== void 0 && variables.workspaceId !== null;
763
- const scopedVariables = /\$workspaceId\b/.test(document) && !hasWorkspaceId ? { ...variables, workspaceId } : variables;
771
+ const scopedVariables = /\$workspaceId\b/.test(document2) && !hasWorkspaceId ? { ...variables, workspaceId } : variables;
764
772
  return graphqlRequest(
765
773
  config,
766
- document,
774
+ document2,
767
775
  scopedVariables,
768
776
  { ...rest, headers: { ...headers, "x-workspace-id": workspaceId } },
769
777
  "graphql operation"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmssy/react",
3
- "version": "0.17.0",
3
+ "version": "0.17.1",
4
4
  "description": "React blocks, renderers, data client and editor bridge for cmssy headless sites",
5
5
  "keywords": [
6
6
  "cmssy",