@cmssy/astro 10.10.0 → 11.1.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 CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  var core = require('@cmssy/core');
4
4
  var internal = require('@cmssy/core/internal');
5
+ var react = require('@cmssy/react');
5
6
 
6
7
  // src/middleware.ts
7
8
  var CMSSY_EDIT_PATH_PREFIX = "/cmssy-edit";
@@ -47,25 +48,57 @@ function cmssyMiddleware(config, options = {}) {
47
48
  return next();
48
49
  };
49
50
  }
50
- async function loadCmssyPage(config, request, url) {
51
+ async function loadCmssyPage(config, request, url, options = {}) {
51
52
  const isEdit = request.headers.get(core.CMSSY_EDIT_HEADER) === "1";
52
- const siteLocales = await internal.resolveSiteLocales(config);
53
53
  const segments = url.pathname.replace(/^\/cmssy-edit/, "").split("/").filter(Boolean);
54
- const fromPath = internal.splitLocaleFromPath(segments, siteLocales);
55
- const locale = request.headers.get(internal.CMSSY_LOCALE_HEADER) ?? fromPath.locale;
56
- const path = fromPath.path;
57
- const previewSecret = isEdit ? config.draftSecret : void 0;
58
- const [page, layouts] = await Promise.all([
59
- internal.fetchPage(config, path, { previewSecret }),
60
- internal.fetchLayouts(config, path, { previewSecret })
61
- ]);
54
+ const positions = options.positions ?? ["header", "footer"];
55
+ const blocks = options.blocks ?? [];
56
+ const headerLocale = request.headers.get(internal.CMSSY_LOCALE_HEADER) ?? void 0;
57
+ const slot = await react.resolveCmssyLayoutSlot(config, {
58
+ position: positions[0] ?? "header",
59
+ blocks,
60
+ editMode: isEdit,
61
+ path: segments,
62
+ locale: headerLocale,
63
+ appContext: options.appContext
64
+ });
65
+ const page = await internal.fetchPage(config, slot.path, {
66
+ previewSecret: isEdit ? config.draftSecret : void 0
67
+ });
68
+ let editorData;
69
+ if (isEdit && slot.data && slot.resolvedContent) {
70
+ editorData = {
71
+ [positions[0] ?? "header"]: {
72
+ data: slot.data,
73
+ resolvedContent: slot.resolvedContent
74
+ }
75
+ };
76
+ for (const position of positions.slice(1)) {
77
+ const extra = await react.resolveCmssyLayoutSlot(config, {
78
+ position,
79
+ blocks,
80
+ editMode: true,
81
+ path: segments,
82
+ locale: headerLocale,
83
+ appContext: options.appContext
84
+ });
85
+ if (extra.data && extra.resolvedContent) {
86
+ editorData[position] = {
87
+ data: extra.data,
88
+ resolvedContent: extra.resolvedContent
89
+ };
90
+ }
91
+ }
92
+ }
62
93
  return {
63
94
  page,
64
- layouts,
65
- locale,
66
- defaultLocale: siteLocales.defaultLocale,
67
- enabledLocales: siteLocales.locales,
68
- isEdit
95
+ layouts: slot.groups,
96
+ locale: slot.locale,
97
+ defaultLocale: slot.defaultLocale,
98
+ enabledLocales: slot.enabledLocales,
99
+ isEdit,
100
+ editorData,
101
+ editorOrigin: slot.editorOrigin
69
102
  };
70
103
  }
71
104
 
package/dist/index.d.cts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { CmssyConfig, CmssyPageData, CmssyLayoutGroup } from '@cmssy/core';
2
2
  export { CMSSY_EDIT_HEADER, CMSSY_LOCALE_HEADER, CmssyBlockContext, CmssyConfig, CmssyEnvConfig, CmssyLayoutGroup, CmssyPageData, createCmssyClient, defineCmssyConfig, localizeHref } from '@cmssy/core';
3
+ import { BlockDefinition } from '@cmssy/react';
3
4
 
4
5
  declare const CMSSY_EDIT_PATH_PREFIX = "/cmssy-edit";
5
6
  interface CmssyMiddlewareOptions {
@@ -40,14 +41,40 @@ interface CmssyPageResult {
40
41
  enabledLocales: string[];
41
42
  /** True for a verified editor request. The edit route renders the bridge. */
42
43
  isEdit: boolean;
44
+ /**
45
+ * Edit mode only, and only when `blocks` was passed: what the canvas needs,
46
+ * **keyed by position**. The header and the footer hold different blocks, so
47
+ * they resolve to different data - handing the footer the header's is the
48
+ * quiet version of this bug.
49
+ *
50
+ * Without `resolvedContent` a relation field shows the raw ids it stores,
51
+ * which is what this adapter did until now.
52
+ */
53
+ editorData?: Record<string, CmssyLayoutEditorData>;
54
+ editorOrigin?: string | string[];
55
+ }
56
+ interface CmssyLayoutEditorData {
57
+ data: Record<string, unknown>;
58
+ resolvedContent: Record<string, Record<string, unknown>>;
59
+ }
60
+ interface LoadCmssyPageOptions {
61
+ /**
62
+ * The block registry. Required to resolve the editor's layout data; omit it
63
+ * and the layouts still render, but the editor cannot fill them.
64
+ */
65
+ blocks?: BlockDefinition[];
66
+ /** Which positions the editor renders. Defaults to the header and footer. */
67
+ positions?: string[];
68
+ appContext?: Record<string, unknown>;
43
69
  }
44
70
  /**
45
- * Everything a cmssy page needs, from a plain Request. No framework globals: the
46
- * locale comes from the header the middleware set (falling back to the path, so
47
- * a prerendered page still knows its language), and the editor flag comes from
48
- * the same signal the Next adapter uses - because it is the same protocol, not
49
- * a Next protocol.
71
+ * Everything a cmssy page needs, from a plain Request. No framework globals.
72
+ *
73
+ * The layout half is `resolveCmssyLayoutSlot` from `@cmssy/react` - the same
74
+ * function the Next adapter uses, so the preview secret, the language and the
75
+ * editor data are decided in one place for all three frameworks rather than
76
+ * three times with two of them wrong.
50
77
  */
51
- declare function loadCmssyPage(config: CmssyConfig, request: Request, url: URL): Promise<CmssyPageResult>;
78
+ declare function loadCmssyPage(config: CmssyConfig, request: Request, url: URL, options?: LoadCmssyPageOptions): Promise<CmssyPageResult>;
52
79
 
53
80
  export { CMSSY_EDIT_PATH_PREFIX, type CmssyMiddlewareOptions, type CmssyPageResult, cmssyMiddleware, loadCmssyPage };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { CmssyConfig, CmssyPageData, CmssyLayoutGroup } from '@cmssy/core';
2
2
  export { CMSSY_EDIT_HEADER, CMSSY_LOCALE_HEADER, CmssyBlockContext, CmssyConfig, CmssyEnvConfig, CmssyLayoutGroup, CmssyPageData, createCmssyClient, defineCmssyConfig, localizeHref } from '@cmssy/core';
3
+ import { BlockDefinition } from '@cmssy/react';
3
4
 
4
5
  declare const CMSSY_EDIT_PATH_PREFIX = "/cmssy-edit";
5
6
  interface CmssyMiddlewareOptions {
@@ -40,14 +41,40 @@ interface CmssyPageResult {
40
41
  enabledLocales: string[];
41
42
  /** True for a verified editor request. The edit route renders the bridge. */
42
43
  isEdit: boolean;
44
+ /**
45
+ * Edit mode only, and only when `blocks` was passed: what the canvas needs,
46
+ * **keyed by position**. The header and the footer hold different blocks, so
47
+ * they resolve to different data - handing the footer the header's is the
48
+ * quiet version of this bug.
49
+ *
50
+ * Without `resolvedContent` a relation field shows the raw ids it stores,
51
+ * which is what this adapter did until now.
52
+ */
53
+ editorData?: Record<string, CmssyLayoutEditorData>;
54
+ editorOrigin?: string | string[];
55
+ }
56
+ interface CmssyLayoutEditorData {
57
+ data: Record<string, unknown>;
58
+ resolvedContent: Record<string, Record<string, unknown>>;
59
+ }
60
+ interface LoadCmssyPageOptions {
61
+ /**
62
+ * The block registry. Required to resolve the editor's layout data; omit it
63
+ * and the layouts still render, but the editor cannot fill them.
64
+ */
65
+ blocks?: BlockDefinition[];
66
+ /** Which positions the editor renders. Defaults to the header and footer. */
67
+ positions?: string[];
68
+ appContext?: Record<string, unknown>;
43
69
  }
44
70
  /**
45
- * Everything a cmssy page needs, from a plain Request. No framework globals: the
46
- * locale comes from the header the middleware set (falling back to the path, so
47
- * a prerendered page still knows its language), and the editor flag comes from
48
- * the same signal the Next adapter uses - because it is the same protocol, not
49
- * a Next protocol.
71
+ * Everything a cmssy page needs, from a plain Request. No framework globals.
72
+ *
73
+ * The layout half is `resolveCmssyLayoutSlot` from `@cmssy/react` - the same
74
+ * function the Next adapter uses, so the preview secret, the language and the
75
+ * editor data are decided in one place for all three frameworks rather than
76
+ * three times with two of them wrong.
50
77
  */
51
- declare function loadCmssyPage(config: CmssyConfig, request: Request, url: URL): Promise<CmssyPageResult>;
78
+ declare function loadCmssyPage(config: CmssyConfig, request: Request, url: URL, options?: LoadCmssyPageOptions): Promise<CmssyPageResult>;
52
79
 
53
80
  export { CMSSY_EDIT_PATH_PREFIX, type CmssyMiddlewareOptions, type CmssyPageResult, cmssyMiddleware, loadCmssyPage };
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { CMSSY_EDIT_HEADER, CMSSY_EDIT_QUERY_PARAM, isVerifiedEditUrl, applyCmssyCsp, CMSSY_SECRET_QUERY_PARAM } from '@cmssy/core';
2
2
  export { CMSSY_EDIT_HEADER, CMSSY_LOCALE_HEADER, createCmssyClient, defineCmssyConfig, localizeHref } from '@cmssy/core';
3
- import { CMSSY_LOCALE_HEADER, localeForPathname, isDevelopment, resolveSiteLocales, splitLocaleFromPath, fetchPage, fetchLayouts } from '@cmssy/core/internal';
3
+ import { CMSSY_LOCALE_HEADER, localeForPathname, isDevelopment, resolveSiteLocales, fetchPage } from '@cmssy/core/internal';
4
+ import { resolveCmssyLayoutSlot } from '@cmssy/react';
4
5
 
5
6
  // src/middleware.ts
6
7
  var CMSSY_EDIT_PATH_PREFIX = "/cmssy-edit";
@@ -46,25 +47,57 @@ function cmssyMiddleware(config, options = {}) {
46
47
  return next();
47
48
  };
48
49
  }
49
- async function loadCmssyPage(config, request, url) {
50
+ async function loadCmssyPage(config, request, url, options = {}) {
50
51
  const isEdit = request.headers.get(CMSSY_EDIT_HEADER) === "1";
51
- const siteLocales = await resolveSiteLocales(config);
52
52
  const segments = url.pathname.replace(/^\/cmssy-edit/, "").split("/").filter(Boolean);
53
- const fromPath = splitLocaleFromPath(segments, siteLocales);
54
- const locale = request.headers.get(CMSSY_LOCALE_HEADER) ?? fromPath.locale;
55
- const path = fromPath.path;
56
- const previewSecret = isEdit ? config.draftSecret : void 0;
57
- const [page, layouts] = await Promise.all([
58
- fetchPage(config, path, { previewSecret }),
59
- fetchLayouts(config, path, { previewSecret })
60
- ]);
53
+ const positions = options.positions ?? ["header", "footer"];
54
+ const blocks = options.blocks ?? [];
55
+ const headerLocale = request.headers.get(CMSSY_LOCALE_HEADER) ?? void 0;
56
+ const slot = await resolveCmssyLayoutSlot(config, {
57
+ position: positions[0] ?? "header",
58
+ blocks,
59
+ editMode: isEdit,
60
+ path: segments,
61
+ locale: headerLocale,
62
+ appContext: options.appContext
63
+ });
64
+ const page = await fetchPage(config, slot.path, {
65
+ previewSecret: isEdit ? config.draftSecret : void 0
66
+ });
67
+ let editorData;
68
+ if (isEdit && slot.data && slot.resolvedContent) {
69
+ editorData = {
70
+ [positions[0] ?? "header"]: {
71
+ data: slot.data,
72
+ resolvedContent: slot.resolvedContent
73
+ }
74
+ };
75
+ for (const position of positions.slice(1)) {
76
+ const extra = await resolveCmssyLayoutSlot(config, {
77
+ position,
78
+ blocks,
79
+ editMode: true,
80
+ path: segments,
81
+ locale: headerLocale,
82
+ appContext: options.appContext
83
+ });
84
+ if (extra.data && extra.resolvedContent) {
85
+ editorData[position] = {
86
+ data: extra.data,
87
+ resolvedContent: extra.resolvedContent
88
+ };
89
+ }
90
+ }
91
+ }
61
92
  return {
62
93
  page,
63
- layouts,
64
- locale,
65
- defaultLocale: siteLocales.defaultLocale,
66
- enabledLocales: siteLocales.locales,
67
- isEdit
94
+ layouts: slot.groups,
95
+ locale: slot.locale,
96
+ defaultLocale: slot.defaultLocale,
97
+ enabledLocales: slot.enabledLocales,
98
+ isEdit,
99
+ editorData,
100
+ editorOrigin: slot.editorOrigin
68
101
  };
69
102
  }
70
103
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmssy/astro",
3
- "version": "10.10.0",
3
+ "version": "11.1.0",
4
4
  "description": "Astro bindings for cmssy headless sites: middleware, page loader, sitemap and robots.",
5
5
  "keywords": [
6
6
  "cmssy",
@@ -39,16 +39,18 @@
39
39
  "dist"
40
40
  ],
41
41
  "peerDependencies": {
42
- "astro": ">=4"
42
+ "astro": ">=4",
43
+ "@cmssy/react": "^11.1.0"
43
44
  },
44
45
  "devDependencies": {
45
46
  "@types/node": "^20.0.0",
46
47
  "tsup": "^8.3.0",
47
48
  "typescript": "^5.6.0",
48
- "vitest": "^2.1.0"
49
+ "vitest": "^2.1.0",
50
+ "@cmssy/react": "11.1.0"
49
51
  },
50
52
  "dependencies": {
51
- "@cmssy/core": "10.10.0"
53
+ "@cmssy/core": "11.1.0"
52
54
  },
53
55
  "scripts": {
54
56
  "build": "tsup",