@nitrogenbuilder/connector-payload 0.1.25 → 0.1.27

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.
@@ -47,13 +47,6 @@ export const NitrogenTemplates = {
47
47
  position: 'sidebar',
48
48
  },
49
49
  },
50
- {
51
- name: 'templateType',
52
- type: 'text',
53
- admin: {
54
- description: 'Template type identifier for filtering',
55
- },
56
- },
57
50
  {
58
51
  name: 'associatedCollection',
59
52
  type: 'text',
@@ -62,18 +55,33 @@ export const NitrogenTemplates = {
62
55
  },
63
56
  },
64
57
  {
65
- name: 'nitrogenData',
66
- type: 'json',
67
- admin: {
68
- description: 'Nitrogen page builder JSON module tree',
69
- },
70
- },
71
- {
72
- name: 'templateSettings',
73
- type: 'json',
58
+ label: 'Nitrogen',
59
+ type: 'group',
74
60
  admin: {
75
- description: 'Template-level Nitrogen settings',
61
+ hideGutter: true,
76
62
  },
63
+ fields: [
64
+ {
65
+ name: 'nitrogenData',
66
+ type: 'json',
67
+ admin: {
68
+ description: 'Nitrogen page builder JSON module tree',
69
+ components: {
70
+ Field: '@nitrogenbuilder/connector-payload/components/NitrogenDataViewer',
71
+ },
72
+ },
73
+ },
74
+ {
75
+ name: 'templateSettings',
76
+ type: 'json',
77
+ admin: {
78
+ description: 'Template-level Nitrogen settings',
79
+ components: {
80
+ Field: '@nitrogenbuilder/connector-payload/components/NitrogenDataViewer',
81
+ },
82
+ },
83
+ },
84
+ ],
77
85
  },
78
86
  ],
79
87
  };
@@ -68,16 +68,18 @@ export const NitrogenEditButtonRuntime = ({ collection }) => {
68
68
  }, [collection]);
69
69
  if (!id || !token || !authorId)
70
70
  return null;
71
- const param = collection === 'nitrogen-templates' ? 'templateId' : 'pageId';
72
71
  const editorBase = instanceUrl ?? '';
73
72
  const isDevelopmentMode = isLocalAdminHost();
74
- const editHref = `${editorBase}/nitrogen-editor?token=${encodeURIComponent(token)}&collection=${encodeURIComponent(collection)}&${param}=${id}&authorId=${encodeURIComponent(authorId)}${isDevelopmentMode ? '&development=true' : ''}`;
73
+ const editHref = `${editorBase}/nitrogen-editor?token=${encodeURIComponent(token)}&collection=${encodeURIComponent(collection)}&pageId=${id}&authorId=${encodeURIComponent(authorId)}${isDevelopmentMode ? '&development=true' : ''}`;
74
+ const viewHref = collection === 'nitrogen-templates'
75
+ ? `${frontendUrl}/nitrogen-templates/${slug}`
76
+ : `${frontendUrl}/${slug}`;
75
77
  const editButtonVars = isDevelopmentMode
76
78
  ? nitrogenEditDevButtonVars
77
79
  : nitrogenEditLiveButtonVars;
78
- return (_jsxs("div", { style: nitrogenButtonGroupStyle, children: [slug && frontendUrl && (_jsx(Button, { buttonStyle: "primary", el: "anchor", margin: false, newTab: true, url: `${frontendUrl}/${slug}`, extraButtonProps: {
80
+ return (_jsxs("div", { style: nitrogenButtonGroupStyle, children: [slug && frontendUrl && (_jsx(Button, { buttonStyle: "primary", el: "anchor", margin: false, newTab: true, url: viewHref, extraButtonProps: {
79
81
  style: nitrogenViewButtonVars,
80
- }, children: "View Page" })), _jsx(Button, { buttonStyle: "primary", el: "anchor", margin: false, newTab: true, url: editHref, extraButtonProps: {
82
+ }, children: collection === 'nitrogen-templates' ? 'View Template' : 'View Page' })), _jsx(Button, { buttonStyle: "primary", el: "anchor", margin: false, newTab: true, url: editHref, extraButtonProps: {
81
83
  style: editButtonVars,
82
84
  }, children: "Edit with Nitrogen" })] }));
83
85
  };
@@ -24,22 +24,22 @@ export const nitrogenButtonGroupStyle = {
24
24
  alignItems: "center",
25
25
  };
26
26
  export const nitrogenViewButtonVars = createFilledButtonVars({
27
- background: monogenPalette.hasVal,
28
- hoverBackground: "#5F97CF",
27
+ background: monogenPalette.inheritVal,
28
+ hoverBackground: "#CC7B2B",
29
29
  text: monogenPalette.gray900,
30
30
  border: "rgba(22, 25, 29, 0.12)",
31
31
  });
32
32
  export const nitrogenEditLiveButtonVars = createFilledButtonVars({
33
- background: monogenPalette.inheritVal,
34
- hoverBackground: "#CC7B2B",
33
+ background: monogenPalette.hasVal,
34
+ hoverBackground: "#5F97CF",
35
35
  text: monogenPalette.gray900,
36
36
  border: "rgba(22, 25, 29, 0.12)",
37
37
  });
38
38
  export const nitrogenEditDevButtonVars = createFilledButtonVars({
39
- background: monogenPalette.gray700,
40
- hoverBackground: monogenPalette.gray600,
41
- text: monogenPalette.gray200,
42
- border: "rgba(226, 229, 233, 0.08)",
39
+ background: monogenPalette.hasVal,
40
+ hoverBackground: "#5F97CF",
41
+ text: monogenPalette.gray900,
42
+ border: "rgba(22, 25, 29, 0.12)",
43
43
  });
44
44
  export const nitrogenSecondaryButtonVars = {
45
45
  "--color": monogenPalette.gray400,
@@ -1,7 +1,6 @@
1
1
  import type { SanitizedConfig } from "payload";
2
2
  interface NitrogenEditorSearchParams {
3
3
  pageId?: string;
4
- templateId?: string;
5
4
  collection?: string;
6
5
  development?: string;
7
6
  }
@@ -14,7 +13,7 @@ interface NitrogenEditorSearchParams {
14
13
  * import configPromise from '@payload-config'
15
14
  * export default createNitrogenEditorPage(configPromise)
16
15
  *
17
- * Accessible at `/nitrogen-editor?pageId=xxx` or `/nitrogen-editor?templateId=xxx`.
16
+ * Accessible at `/nitrogen-editor?pageId=xxx`.
18
17
  */
19
18
  export declare function createNitrogenEditorPage(config: Promise<SanitizedConfig>): ({ searchParams, }: {
20
19
  searchParams: Promise<NitrogenEditorSearchParams>;
@@ -26,6 +26,26 @@ function getSiteUrl(settings, isDevelopment) {
26
26
  const fallbackUrl = isDevelopment
27
27
  ? settings.frontendUrl
28
28
  : settings.developmentUrl;
29
+ const normalizeOrigin = (value) => {
30
+ if (!value)
31
+ return "";
32
+ try {
33
+ return new URL(value).origin;
34
+ }
35
+ catch {
36
+ return "";
37
+ }
38
+ };
39
+ const preferredOrigin = normalizeOrigin(preferredUrl);
40
+ const fallbackOrigin = normalizeOrigin(fallbackUrl);
41
+ const instanceOrigin = normalizeOrigin(settings.instanceUrl);
42
+ if (preferredUrl &&
43
+ instanceOrigin &&
44
+ preferredOrigin === instanceOrigin &&
45
+ fallbackUrl &&
46
+ fallbackOrigin !== instanceOrigin) {
47
+ return fallbackUrl;
48
+ }
29
49
  return preferredUrl || fallbackUrl || "";
30
50
  }
31
51
  /**
@@ -37,7 +57,7 @@ function getSiteUrl(settings, isDevelopment) {
37
57
  * import configPromise from '@payload-config'
38
58
  * export default createNitrogenEditorPage(configPromise)
39
59
  *
40
- * Accessible at `/nitrogen-editor?pageId=xxx` or `/nitrogen-editor?templateId=xxx`.
60
+ * Accessible at `/nitrogen-editor?pageId=xxx`.
41
61
  */
42
62
  export function createNitrogenEditorPage(config) {
43
63
  return async function NitrogenEditorPage({ searchParams, }) {
@@ -56,15 +76,7 @@ export function createNitrogenEditorPage(config) {
56
76
  const isDevelopment = params.development === "true";
57
77
  const siteUrl = getSiteUrl(settings, isDevelopment);
58
78
  const nitrogenConfig = settings.nitrogenConfig || {};
59
- // Determine the postType for the editor's API calls
60
- let postType;
61
- if (params.collection) {
62
- postType = params.collection;
63
- }
64
- else if (params.templateId) {
65
- postType = "nitrogen-templates";
66
- }
67
- else {
79
+ if (!params.pageId || !params.collection) {
68
80
  return redirect("/admin");
69
81
  }
70
82
  // Build the config object the builder reads from window.nitrogenConfig
@@ -73,14 +85,14 @@ export function createNitrogenEditorPage(config) {
73
85
  provider: {
74
86
  type: "payload",
75
87
  apiUrl: getNitrogenApiUrl(isDevelopment),
76
- collection: postType,
88
+ collection: params.collection,
77
89
  },
78
90
  siteUrl: siteUrl || "",
79
91
  urlMaps: nitrogenConfig.urlMaps || [],
80
92
  wysiwygColors: nitrogenConfig.wysiwygColors || {},
81
93
  cssInjection: nitrogenConfig.cssInjection || "",
82
94
  };
83
- const editId = params.templateId || params.pageId || "";
95
+ const editId = params.pageId;
84
96
  const isEditorDev = isDevelopment && !!settings.instanceUrl;
85
97
  const editorOrigin = settings.instanceUrl?.replace(/\/$/, "") || "";
86
98
  const editorAssetsBase = isEditorDev
@@ -4,11 +4,22 @@ export function formatDate(date) {
4
4
  return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}`;
5
5
  }
6
6
  export function buildDynamicData(doc, globalSettings) {
7
+ const rawDoc = doc;
8
+ const docData = Object.fromEntries(Object.entries(rawDoc).filter(([key]) => key !== 'nitrogenData' &&
9
+ key !== 'pageSettings' &&
10
+ key !== 'templateSettings'));
11
+ const rawContent = typeof rawDoc.content === 'string'
12
+ ? rawDoc.content
13
+ : '';
14
+ const rawExcerpt = typeof rawDoc.excerpt === 'string'
15
+ ? rawDoc.excerpt
16
+ : '';
7
17
  const dynamicData = {
8
18
  Post: {
19
+ ...docData,
9
20
  post_title: doc.title || '',
10
- post_content: '',
11
- post_excerpt: '',
21
+ post_content: rawContent,
22
+ post_excerpt: rawExcerpt,
12
23
  post_date: formatDate(doc.createdAt),
13
24
  post_date_gmt: formatDate(doc.createdAt),
14
25
  post_modified: formatDate(doc.updatedAt),
@@ -112,9 +123,13 @@ export async function getTemplateForType(payload, type) {
112
123
  try {
113
124
  const result = await payload.find({
114
125
  collection: 'nitrogen-templates',
115
- where: { associatedCollection: { equals: type } },
126
+ where: {
127
+ associatedCollection: { equals: type },
128
+ status: { equals: 'published' },
129
+ },
116
130
  limit: 1,
117
131
  depth: 0,
132
+ sort: '-updatedAt',
118
133
  });
119
134
  const doc = result.docs[0];
120
135
  if (!doc)
@@ -1,5 +1,58 @@
1
1
  import { getNitrogenSettings, buildDynamicData, buildPageResponse, buildListItemResponse, requireAuth, } from './helpers';
2
2
  export const templatesEndpoints = [
3
+ // GET /api/nitrogen/v1/nitrogen-templates/slug/:slug — Get a single template by slug
4
+ {
5
+ path: '/nitrogen/v1/nitrogen-templates/slug/:slug',
6
+ method: 'get',
7
+ handler: async (req) => {
8
+ const { payload, routeParams } = req;
9
+ const slug = routeParams?.slug;
10
+ try {
11
+ const result = await payload.find({
12
+ collection: 'nitrogen-templates',
13
+ where: { slug: { equals: slug } },
14
+ limit: 1,
15
+ depth: 1,
16
+ });
17
+ const doc = result.docs[0];
18
+ if (!doc) {
19
+ return Response.json({ error: 'Not found' }, { status: 404 });
20
+ }
21
+ const settings = await getNitrogenSettings(payload);
22
+ let dynamicData = buildDynamicData(doc, settings);
23
+ const associatedCollection = doc.associatedCollection;
24
+ if (associatedCollection &&
25
+ associatedCollection !== 'header' &&
26
+ associatedCollection !== 'footer') {
27
+ try {
28
+ const associated = await payload.find({
29
+ collection: associatedCollection,
30
+ limit: 1,
31
+ depth: 1,
32
+ });
33
+ if (associated.docs.length) {
34
+ dynamicData = buildDynamicData(associated.docs[0], settings);
35
+ }
36
+ }
37
+ catch {
38
+ // Collection may not exist — use template's own data
39
+ }
40
+ }
41
+ const response = buildPageResponse(doc, settings, dynamicData);
42
+ const relativePermalink = `/nitrogen-templates/${doc.slug}`;
43
+ const frontendBase = (settings.frontendUrl || '').replace(/\/$/, '');
44
+ return Response.json({
45
+ ...response,
46
+ permalink: frontendBase ? `${frontendBase}${relativePermalink}` : relativePermalink,
47
+ relative_permalink: relativePermalink,
48
+ postType: associatedCollection || '',
49
+ });
50
+ }
51
+ catch {
52
+ return Response.json({ error: 'Not found' }, { status: 404 });
53
+ }
54
+ },
55
+ },
3
56
  // GET /api/nitrogen/v1/templates — List templates
4
57
  {
5
58
  path: '/nitrogen/v1/nitrogen-templates',
@@ -23,6 +76,8 @@ export const templatesEndpoints = [
23
76
  });
24
77
  const items = result.docs.map((doc) => ({
25
78
  ...buildListItemResponse(doc, settings),
79
+ permalink: `${(settings.frontendUrl || '').replace(/\/$/, '')}/nitrogen-templates/${doc.slug}`,
80
+ relative_permalink: `/nitrogen-templates/${doc.slug}`,
26
81
  postType: doc.associatedCollection || '',
27
82
  }));
28
83
  return Response.json(items);
@@ -64,8 +119,12 @@ export const templatesEndpoints = [
64
119
  }
65
120
  }
66
121
  const response = buildPageResponse(doc, settings, dynamicData);
122
+ const relativePermalink = `/nitrogen-templates/${doc.slug}`;
123
+ const frontendBase = (settings.frontendUrl || '').replace(/\/$/, '');
67
124
  return Response.json({
68
125
  ...response,
126
+ permalink: frontendBase ? `${frontendBase}${relativePermalink}` : relativePermalink,
127
+ relative_permalink: relativePermalink,
69
128
  postType: associatedCollection || '',
70
129
  });
71
130
  }
@@ -85,7 +144,7 @@ export const templatesEndpoints = [
85
144
  const { payload, routeParams } = req;
86
145
  const id = routeParams?.id;
87
146
  const body = (await req.json?.());
88
- const data = body?.data || body;
147
+ const data = (body?.data && typeof body.data === 'object') ? body.data : body;
89
148
  if (!data?.title) {
90
149
  return Response.json({ error: 'Title is required' }, { status: 400 });
91
150
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitrogenbuilder/connector-payload",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "description": "Nitrogen page builder connector plugin for Payload CMS 3.x",
5
5
  "author": "Leonardo Dentzien <leo@torchmedia.ca>",
6
6
  "type": "module",