@nitrogenbuilder/connector-payload 0.1.29 → 0.1.31

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.
@@ -81,6 +81,16 @@ export const NitrogenTemplates = {
81
81
  },
82
82
  },
83
83
  },
84
+ {
85
+ name: 'templateConditions',
86
+ type: 'json',
87
+ admin: {
88
+ description: 'Template conditions used by the Nitrogen editor',
89
+ components: {
90
+ Field: '@nitrogenbuilder/connector-payload/components/NitrogenDataViewer',
91
+ },
92
+ },
93
+ },
84
94
  ],
85
95
  },
86
96
  ],
@@ -71,9 +71,7 @@ export const NitrogenEditButtonRuntime = ({ collection }) => {
71
71
  const editorBase = instanceUrl ?? '';
72
72
  const isDevelopmentMode = isLocalAdminHost();
73
73
  const encodedAuthorId = encodeURIComponent(authorId);
74
- const developmentFlags = isDevelopmentMode
75
- ? '&development=true&editorDevelopment=true'
76
- : '';
74
+ const developmentFlags = isDevelopmentMode ? '&development=true' : '';
77
75
  const editHref = `${editorBase}/nitrogen-editor?token=${encodeURIComponent(token)}&collection=${encodeURIComponent(collection)}&pageId=${id}&authorId=${encodedAuthorId}&author=${encodedAuthorId}${developmentFlags}`;
78
76
  const viewHref = collection === 'nitrogen-templates'
79
77
  ? `${frontendUrl}/nitrogen-templates/${slug}`
@@ -95,10 +95,18 @@ export function createNitrogenEditorPage(config) {
95
95
  cssInjection: nitrogenConfig.cssInjection || "",
96
96
  };
97
97
  const editId = params.pageId;
98
- // Keep editor HMR opt-in separate from preview-target selection so a
99
- // deployed Payload instance can still preview against a local frontend.
98
+ // Preserve the old localhost flow: `development=true` should still imply
99
+ // local editor HMR when the editor page itself is served from localhost.
100
+ // Deployed hosts stay on the built editor unless explicitly opted in.
101
+ const requestHost = headersList.get("host") || "";
102
+ const requestHostname = requestHost.split(":")[0];
103
+ const isLocalRequestHost = requestHostname === "localhost" ||
104
+ requestHostname === "127.0.0.1" ||
105
+ requestHostname === "[::1]";
100
106
  const isEditorDevelopment = params.editorDevelopment === "true";
101
- const isEditorDev = isEditorDevelopment && !!settings.instanceUrl;
107
+ const isEditorDev = !!settings.instanceUrl &&
108
+ (isEditorDevelopment ||
109
+ (isPreviewDevelopment && isLocalRequestHost));
102
110
  const editorOrigin = settings.instanceUrl?.replace(/\/$/, "") || "";
103
111
  const editorAssetsBase = isEditorDev
104
112
  ? editorOrigin
@@ -1,4 +1,22 @@
1
1
  import { getNitrogenSettings, buildDynamicData, buildPageResponse, buildListItemResponse, getTemplateForType, requireAuth, } from './helpers';
2
+ import { buildPermalink, buildRelativePermalink } from '../collection-registry';
3
+ function isContentTemplateCollection(collection) {
4
+ return !!collection && collection !== 'header' && collection !== 'footer';
5
+ }
6
+ function getTemplateConditions(doc) {
7
+ return doc.templateConditions ?? { conditionGroups: [] };
8
+ }
9
+ function getTemplatePreviewTarget(doc, settings, associatedCollection, associatedDoc) {
10
+ const previewCollection = associatedDoc && isContentTemplateCollection(associatedCollection)
11
+ ? associatedCollection
12
+ : 'nitrogen-templates';
13
+ const previewSlug = String(associatedDoc?.slug || doc.slug || '');
14
+ return {
15
+ slug: previewSlug,
16
+ permalink: buildPermalink(previewCollection, previewSlug, settings.frontendUrl),
17
+ relative_permalink: buildRelativePermalink(previewCollection, previewSlug),
18
+ };
19
+ }
2
20
  export const templatesEndpoints = [
3
21
  // GET /api/nitrogen/v1/nitrogen-templates/slug/:slug — Get a single template by slug
4
22
  {
@@ -24,10 +42,9 @@ export const templatesEndpoints = [
24
42
  }
25
43
  const settings = await getNitrogenSettings(payload);
26
44
  let dynamicData = buildDynamicData(doc, settings);
45
+ let associatedDoc;
27
46
  const associatedCollection = doc.associatedCollection;
28
- if (associatedCollection &&
29
- associatedCollection !== 'header' &&
30
- associatedCollection !== 'footer') {
47
+ if (isContentTemplateCollection(associatedCollection)) {
31
48
  try {
32
49
  const associated = await payload.find({
33
50
  collection: associatedCollection,
@@ -35,7 +52,8 @@ export const templatesEndpoints = [
35
52
  depth: 1,
36
53
  });
37
54
  if (associated.docs.length) {
38
- dynamicData = buildDynamicData(associated.docs[0], settings);
55
+ associatedDoc = associated.docs[0];
56
+ dynamicData = buildDynamicData(associatedDoc, settings);
39
57
  }
40
58
  }
41
59
  catch {
@@ -43,19 +61,16 @@ export const templatesEndpoints = [
43
61
  }
44
62
  }
45
63
  const response = buildPageResponse(doc, settings, dynamicData);
46
- const relativePermalink = `/nitrogen-templates/${doc.slug}`;
47
- const frontendBase = (settings.frontendUrl || '').replace(/\/$/, '');
64
+ const previewTarget = getTemplatePreviewTarget(doc, settings, associatedCollection, associatedDoc);
48
65
  return Response.json({
49
66
  ...response,
50
- permalink: frontendBase ? `${frontendBase}${relativePermalink}` : relativePermalink,
51
- relative_permalink: relativePermalink,
67
+ slug: previewTarget.slug,
68
+ permalink: previewTarget.permalink,
69
+ relative_permalink: previewTarget.relative_permalink,
52
70
  postType: associatedCollection || '',
53
- headerTemplate: associatedCollection !== 'header' && associatedCollection !== 'footer'
54
- ? headerTemplate
55
- : null,
56
- footerTemplate: associatedCollection !== 'header' && associatedCollection !== 'footer'
57
- ? footerTemplate
58
- : null,
71
+ templateConditions: getTemplateConditions(doc),
72
+ headerTemplate: isContentTemplateCollection(associatedCollection) ? headerTemplate : null,
73
+ footerTemplate: isContentTemplateCollection(associatedCollection) ? footerTemplate : null,
59
74
  });
60
75
  }
61
76
  catch {
@@ -114,10 +129,9 @@ export const templatesEndpoints = [
114
129
  // Build dynamic data from the first document of the associated collection
115
130
  // so the template preview has real data to bind to
116
131
  let dynamicData = buildDynamicData(doc, settings);
132
+ let associatedDoc;
117
133
  const associatedCollection = doc.associatedCollection;
118
- if (associatedCollection &&
119
- associatedCollection !== 'header' &&
120
- associatedCollection !== 'footer') {
134
+ if (isContentTemplateCollection(associatedCollection)) {
121
135
  try {
122
136
  const associated = await payload.find({
123
137
  collection: associatedCollection,
@@ -125,7 +139,8 @@ export const templatesEndpoints = [
125
139
  depth: 1,
126
140
  });
127
141
  if (associated.docs.length) {
128
- dynamicData = buildDynamicData(associated.docs[0], settings);
142
+ associatedDoc = associated.docs[0];
143
+ dynamicData = buildDynamicData(associatedDoc, settings);
129
144
  }
130
145
  }
131
146
  catch {
@@ -133,19 +148,16 @@ export const templatesEndpoints = [
133
148
  }
134
149
  }
135
150
  const response = buildPageResponse(doc, settings, dynamicData);
136
- const relativePermalink = `/nitrogen-templates/${doc.slug}`;
137
- const frontendBase = (settings.frontendUrl || '').replace(/\/$/, '');
151
+ const previewTarget = getTemplatePreviewTarget(doc, settings, associatedCollection, associatedDoc);
138
152
  return Response.json({
139
153
  ...response,
140
- permalink: frontendBase ? `${frontendBase}${relativePermalink}` : relativePermalink,
141
- relative_permalink: relativePermalink,
154
+ slug: previewTarget.slug,
155
+ permalink: previewTarget.permalink,
156
+ relative_permalink: previewTarget.relative_permalink,
142
157
  postType: associatedCollection || '',
143
- headerTemplate: associatedCollection !== 'header' && associatedCollection !== 'footer'
144
- ? headerTemplate
145
- : null,
146
- footerTemplate: associatedCollection !== 'header' && associatedCollection !== 'footer'
147
- ? footerTemplate
148
- : null,
158
+ templateConditions: getTemplateConditions(doc),
159
+ headerTemplate: isContentTemplateCollection(associatedCollection) ? headerTemplate : null,
160
+ footerTemplate: isContentTemplateCollection(associatedCollection) ? footerTemplate : null,
149
161
  });
150
162
  }
151
163
  catch {
@@ -165,10 +177,13 @@ export const templatesEndpoints = [
165
177
  const id = routeParams?.id;
166
178
  const body = (await req.json?.());
167
179
  const data = (body?.data && typeof body.data === 'object') ? body.data : body;
168
- if (!data?.title) {
169
- return Response.json({ error: 'Title is required' }, { status: 400 });
180
+ if (!data) {
181
+ return Response.json({ error: 'No update data provided' }, { status: 400 });
182
+ }
183
+ const updateData = {};
184
+ if (data.title !== undefined) {
185
+ updateData.title = data.title;
170
186
  }
171
- const updateData = { title: data.title };
172
187
  if (data.author) {
173
188
  updateData.author = data.author;
174
189
  }
@@ -182,6 +197,12 @@ export const templatesEndpoints = [
182
197
  if (data.settings !== undefined) {
183
198
  updateData.templateSettings = data.settings;
184
199
  }
200
+ if (data.conditions !== undefined) {
201
+ updateData.templateConditions = data.conditions;
202
+ }
203
+ if (Object.keys(updateData).length === 0) {
204
+ return Response.json({ error: 'No update data provided' }, { status: 400 });
205
+ }
185
206
  await payload.update({
186
207
  collection: 'nitrogen-templates',
187
208
  id,
package/dist/index.js CHANGED
@@ -55,6 +55,11 @@ export const nitrogenConnectorPlugin = (options = {}) => (incomingConfig) => {
55
55
  // Register templates collection
56
56
  registerCollection("nitrogen-templates", "nitrogen-templates", "/nitrogen-templates/[slug]");
57
57
  registerCollection("nitrogen_template", "nitrogen-templates", "/nitrogen-templates/[slug]");
58
+ // Register route patterns for non-editable collections too so templates can
59
+ // preview against real frontend URLs for their associated collections.
60
+ for (const [slug, routePattern] of Object.entries(options.collectionRoutes || {})) {
61
+ registerCollection(slug, slug, routePattern);
62
+ }
58
63
  // Process collections
59
64
  const additionalCollections = options.collections || [];
60
65
  for (const slug of additionalCollections) {
package/dist/types.d.ts CHANGED
@@ -28,6 +28,7 @@ export interface NitrogenTemplateDoc extends NitrogenDocBase {
28
28
  templateType?: string;
29
29
  associatedCollection?: string;
30
30
  templateSettings?: JsonObject;
31
+ templateConditions?: JsonObject;
31
32
  }
32
33
  export interface NitrogenSettingsGlobal {
33
34
  licenseKey?: string;
@@ -99,6 +100,7 @@ export interface TemplateUpdateRequestBody {
99
100
  data_content?: string | JsonObject[];
100
101
  templateType?: string;
101
102
  settings?: JsonObject;
103
+ conditions?: JsonObject;
102
104
  }
103
105
  interface TemplateUpdateData {
104
106
  title?: string;
@@ -106,6 +108,7 @@ interface TemplateUpdateData {
106
108
  data?: string | JsonObject[];
107
109
  templateType?: string;
108
110
  settings?: JsonObject;
111
+ conditions?: JsonObject;
109
112
  }
110
113
  export interface SlugLookupRequestBody {
111
114
  slug?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitrogenbuilder/connector-payload",
3
- "version": "0.1.29",
3
+ "version": "0.1.31",
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",