@nitrogenbuilder/connector-payload 0.1.39 → 0.1.41

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.
Files changed (33) hide show
  1. package/dist/components/LockedJsonField.js +1 -1
  2. package/dist/components/NitrogenComponentInventoryClient.d.ts +3 -2
  3. package/dist/components/NitrogenComponentInventoryClient.js +370 -63
  4. package/dist/components/NitrogenComponentInventoryField.js +15 -5
  5. package/dist/components/NitrogenComponentInventoryView.js +15 -5
  6. package/dist/components/NitrogenDataViewer.js +1 -1
  7. package/dist/components/NitrogenEditButton.js +2 -2
  8. package/dist/components/NitrogenEditButtonRuntime.js +21 -5
  9. package/dist/components/NitrogenViewButton.js +2 -2
  10. package/dist/components/NitrogenViewButtonRuntime.js +7 -3
  11. package/dist/editor/NitrogenEditorPage.js +12 -29
  12. package/dist/editor/index.d.ts +3 -3
  13. package/dist/editor/index.js +3 -3
  14. package/dist/endpoints/all.js +2 -2
  15. package/dist/endpoints/batch.js +2 -2
  16. package/dist/endpoints/collection-endpoints.js +1 -1
  17. package/dist/endpoints/component-inventory.d.ts +1 -1
  18. package/dist/endpoints/component-inventory.js +275 -2
  19. package/dist/endpoints/helpers.d.ts +5 -5
  20. package/dist/endpoints/helpers.js +1 -1
  21. package/dist/endpoints/media.js +1 -1
  22. package/dist/endpoints/nitrogen-settings.js +1 -1
  23. package/dist/endpoints/templates.js +2 -2
  24. package/dist/frontend/NitrogenWrapper.js +2 -2
  25. package/dist/frontend/index.d.ts +5 -5
  26. package/dist/frontend/index.js +3 -3
  27. package/dist/globals/NitrogenSettings.js +46 -11
  28. package/dist/index.d.ts +7 -7
  29. package/dist/index.js +22 -22
  30. package/dist/inventory/indexing.d.ts +2 -2
  31. package/dist/inventory/indexing.js +1 -1
  32. package/dist/types.d.ts +6 -1
  33. package/package.json +1 -1
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useEffect } from 'react';
4
4
  import { Button } from '@payloadcms/ui';
5
- import { nitrogenButtonGroupStyle, nitrogenEditDevButtonVars, nitrogenEditLiveButtonVars, nitrogenViewButtonVars, } from './nitrogenAdminButtonStyles';
5
+ import { nitrogenButtonGroupStyle, nitrogenEditDevButtonVars, nitrogenEditLiveButtonVars, nitrogenViewButtonVars, } from './nitrogenAdminButtonStyles.js';
6
6
  function isLocalAdminHost() {
7
7
  const hostname = window.location.hostname;
8
8
  return (hostname === 'localhost' ||
@@ -11,8 +11,23 @@ function isLocalAdminHost() {
11
11
  }
12
12
  function getPreferredSiteUrl(data) {
13
13
  const isLocalAdmin = isLocalAdminHost();
14
- const preferredUrl = isLocalAdmin ? data.developmentUrl : data.frontendUrl;
15
- const fallbackUrl = isLocalAdmin ? data.frontendUrl : data.developmentUrl;
14
+ const preferredUrl = isLocalAdmin
15
+ ? data.frontendDevUrl || data.developmentUrl
16
+ : data.frontendUrl;
17
+ const fallbackUrl = isLocalAdmin
18
+ ? data.frontendUrl
19
+ : data.frontendDevUrl || data.developmentUrl;
20
+ return preferredUrl || fallbackUrl || '';
21
+ }
22
+ function getPreferredEditorUrl(data) {
23
+ const isLocalAdmin = isLocalAdminHost();
24
+ const legacyEditorDevUrl = data.instanceUrl;
25
+ const preferredUrl = isLocalAdmin
26
+ ? data.nitrogenEditorDevUrl || legacyEditorDevUrl
27
+ : data.nitrogenEditorUrl;
28
+ const fallbackUrl = isLocalAdmin
29
+ ? data.nitrogenEditorUrl
30
+ : data.nitrogenEditorDevUrl || legacyEditorDevUrl;
16
31
  return preferredUrl || fallbackUrl || '';
17
32
  }
18
33
  function normalizeRoutePattern(routePattern) {
@@ -105,8 +120,9 @@ export const NitrogenEditButtonRuntime = ({ collection, routePattern }) => {
105
120
  if (data.connectorToken) {
106
121
  setToken(data.connectorToken);
107
122
  }
108
- if (data.instanceUrl) {
109
- setInstanceUrl(data.instanceUrl.replace(/\/$/, ''));
123
+ const editorUrl = getPreferredEditorUrl(data);
124
+ if (editorUrl) {
125
+ setInstanceUrl(editorUrl.replace(/\/$/, ''));
110
126
  }
111
127
  const url = getPreferredSiteUrl(data);
112
128
  if (url) {
@@ -1,6 +1,6 @@
1
1
  'use client';
2
- import dynamic from 'next/dynamic';
3
- export const NitrogenViewButton = dynamic(() => import('./NitrogenViewButtonRuntime').then((module) => module.NitrogenViewButtonRuntime), {
2
+ import dynamic from 'next/dynamic.js';
3
+ export const NitrogenViewButton = dynamic(() => import('./NitrogenViewButtonRuntime.js').then((module) => module.NitrogenViewButtonRuntime), {
4
4
  loading: () => null,
5
5
  ssr: false,
6
6
  });
@@ -2,14 +2,18 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useState, useEffect } from 'react';
4
4
  import { Button } from '@payloadcms/ui';
5
- import { nitrogenViewButtonVars } from './nitrogenAdminButtonStyles';
5
+ import { nitrogenViewButtonVars } from './nitrogenAdminButtonStyles.js';
6
6
  function getPreferredSiteUrl(data) {
7
7
  const hostname = window.location.hostname;
8
8
  const isLocalAdmin = hostname === 'localhost' ||
9
9
  hostname === '127.0.0.1' ||
10
10
  hostname === '[::1]';
11
- const preferredUrl = isLocalAdmin ? data.developmentUrl : data.frontendUrl;
12
- const fallbackUrl = isLocalAdmin ? data.frontendUrl : data.developmentUrl;
11
+ const preferredUrl = isLocalAdmin
12
+ ? data.frontendDevUrl || data.developmentUrl
13
+ : data.frontendUrl;
14
+ const fallbackUrl = isLocalAdmin
15
+ ? data.frontendUrl
16
+ : data.frontendDevUrl || data.developmentUrl;
13
17
  return preferredUrl || fallbackUrl || '';
14
18
  }
15
19
  function normalizeRoutePattern(routePattern) {
@@ -21,33 +21,16 @@ function getNitrogenApiUrl(isDevelopment) {
21
21
  }
22
22
  function getSiteUrl(settings, isDevelopment) {
23
23
  const preferredUrl = isDevelopment
24
- ? settings.developmentUrl
24
+ ? settings.frontendDevUrl || settings.developmentUrl
25
25
  : settings.frontendUrl;
26
26
  const fallbackUrl = isDevelopment
27
27
  ? settings.frontendUrl
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
- }
28
+ : settings.frontendDevUrl || settings.developmentUrl;
49
29
  return preferredUrl || fallbackUrl || "";
50
30
  }
31
+ function getNitrogenEditorDevUrl(settings) {
32
+ return settings.nitrogenEditorDevUrl || settings.instanceUrl || "";
33
+ }
51
34
  /**
52
35
  * Creates a standalone editor page that loads the Nitrogen builder.
53
36
  *
@@ -73,7 +56,7 @@ export function createNitrogenEditorPage(config) {
73
56
  const settings = (await payload.findGlobal({
74
57
  slug: "nitrogen-settings",
75
58
  }));
76
- // `development=true` selects the preview target (`developmentUrl`) without
59
+ // `development=true` selects the preview target (`frontendDevUrl`) without
77
60
  // requiring the editor shell itself to come from a local Vite server.
78
61
  const isPreviewDevelopment = params.development === "true";
79
62
  const siteUrl = getSiteUrl(settings, isPreviewDevelopment);
@@ -104,19 +87,19 @@ export function createNitrogenEditorPage(config) {
104
87
  requestHostname === "127.0.0.1" ||
105
88
  requestHostname === "[::1]";
106
89
  const isEditorDevelopment = params.editorDevelopment === "true";
107
- const isEditorDev = !!settings.instanceUrl &&
90
+ const editorDevOrigin = getNitrogenEditorDevUrl(settings).replace(/\/$/, "");
91
+ const isEditorDev = !!editorDevOrigin &&
108
92
  (isEditorDevelopment ||
109
93
  (isPreviewDevelopment && isLocalRequestHost));
110
- const editorOrigin = settings.instanceUrl?.replace(/\/$/, "") || "";
111
94
  const editorAssetsBase = isEditorDev
112
- ? editorOrigin
95
+ ? editorDevOrigin
113
96
  : "/nitrogen-editor/assets";
114
97
  const editorCdnVersion = typeof settings.editorCdnVersion === "string" &&
115
98
  settings.editorCdnVersion.trim()
116
99
  ? settings.editorCdnVersion.trim()
117
100
  : DEFAULT_EDITOR_CDN_VERSION;
118
101
  const cdnBase = `https://cdn.jsdelivr.net/npm/@nitrogenbuilder/editor@${editorCdnVersion}`;
119
- return (_jsxs(_Fragment, { children: [!isEditorDev && (_jsxs(_Fragment, { children: [_jsx("link", { rel: "preconnect", href: "https://cdn.jsdelivr.net" }), _jsx("link", { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "" })] })), isEditorDev ? (_jsxs(_Fragment, { children: [_jsx("link", { rel: "stylesheet", crossOrigin: "", href: `${editorAssetsBase}/fa620pro/css/all.css` }), _jsx("link", { rel: "stylesheet", crossOrigin: "", href: `${editorAssetsBase}/fa620pro/css/sharp-solid.css` }), _jsx("link", { rel: "stylesheet", crossOrigin: "", href: `${editorOrigin}/src/index.scss` })] })) : (_jsxs(_Fragment, { children: [_jsx("link", { rel: "stylesheet", crossOrigin: "", href: `${editorAssetsBase}/fa620pro/css/all.css` }), _jsx("link", { rel: "stylesheet", crossOrigin: "", href: `${editorAssetsBase}/fa620pro/css/sharp-solid.css` }), _jsx("link", { rel: "stylesheet", crossOrigin: "", href: `${cdnBase}/index.css` })] })), _jsx("script", { dangerouslySetInnerHTML: {
102
+ return (_jsxs(_Fragment, { children: [!isEditorDev && (_jsxs(_Fragment, { children: [_jsx("link", { rel: "preconnect", href: "https://cdn.jsdelivr.net" }), _jsx("link", { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "" })] })), isEditorDev ? (_jsxs(_Fragment, { children: [_jsx("link", { rel: "stylesheet", crossOrigin: "", href: `${editorAssetsBase}/fa620pro/css/all.css` }), _jsx("link", { rel: "stylesheet", crossOrigin: "", href: `${editorAssetsBase}/fa620pro/css/sharp-solid.css` }), _jsx("link", { rel: "stylesheet", crossOrigin: "", href: `${editorDevOrigin}/src/index.scss` })] })) : (_jsxs(_Fragment, { children: [_jsx("link", { rel: "stylesheet", crossOrigin: "", href: `${editorAssetsBase}/fa620pro/css/all.css` }), _jsx("link", { rel: "stylesheet", crossOrigin: "", href: `${editorAssetsBase}/fa620pro/css/sharp-solid.css` }), _jsx("link", { rel: "stylesheet", crossOrigin: "", href: `${cdnBase}/index.css` })] })), _jsx("script", { dangerouslySetInnerHTML: {
120
103
  __html: [
121
104
  `window.nitrogenConfig = ${JSON.stringify(builderConfig)};`,
122
105
  `window.nitrogenEditId = "${editId}";`,
@@ -142,7 +125,7 @@ export function createNitrogenEditorPage(config) {
142
125
  } })) }), _jsx("style", { dangerouslySetInnerHTML: {
143
126
  __html: `@keyframes nitrogen-loader-pulse{0%{transform:scale(1);opacity:0}50%{opacity:1}100%{transform:scale(1.05);opacity:0}}`,
144
127
  } })] }), isEditorDev ? (_jsxs(_Fragment, { children: [_jsx("script", { type: "module", dangerouslySetInnerHTML: {
145
- __html: `import RefreshRuntime from "${editorOrigin}/@react-refresh";RefreshRuntime.injectIntoGlobalHook(window);window.$RefreshReg$ = () => {};window.$RefreshSig$ = () => (type) => type;window.__vite_plugin_react_preamble_installed__ = true;`,
146
- } }), _jsx("script", { type: "module", src: `${editorOrigin}/@vite/client` }), _jsx("script", { type: "module", crossOrigin: "", src: `${editorOrigin}/src/main.tsx` })] })) : (_jsx("script", { type: "module", crossOrigin: "", src: `${cdnBase}/index.js` }))] }));
128
+ __html: `import RefreshRuntime from "${editorDevOrigin}/@react-refresh";RefreshRuntime.injectIntoGlobalHook(window);window.$RefreshReg$ = () => {};window.$RefreshSig$ = () => (type) => type;window.__vite_plugin_react_preamble_installed__ = true;`,
129
+ } }), _jsx("script", { type: "module", src: `${editorDevOrigin}/@vite/client` }), _jsx("script", { type: "module", crossOrigin: "", src: `${editorDevOrigin}/src/main.tsx` })] })) : (_jsx("script", { type: "module", crossOrigin: "", src: `${cdnBase}/index.js` }))] }));
147
130
  };
148
131
  }
@@ -1,3 +1,3 @@
1
- export { createNitrogenEditorPage } from './NitrogenEditorPage';
2
- export { default as NitrogenEditorLayout } from './NitrogenEditorLayout';
3
- export { GET as nitrogenEditorAssetsRoute } from './NitrogenEditorAssetsRoute';
1
+ export { createNitrogenEditorPage } from './NitrogenEditorPage.js';
2
+ export { default as NitrogenEditorLayout } from './NitrogenEditorLayout.js';
3
+ export { GET as nitrogenEditorAssetsRoute } from './NitrogenEditorAssetsRoute.js';
@@ -1,3 +1,3 @@
1
- export { createNitrogenEditorPage } from './NitrogenEditorPage';
2
- export { default as NitrogenEditorLayout } from './NitrogenEditorLayout';
3
- export { GET as nitrogenEditorAssetsRoute } from './NitrogenEditorAssetsRoute';
1
+ export { createNitrogenEditorPage } from './NitrogenEditorPage.js';
2
+ export { default as NitrogenEditorLayout } from './NitrogenEditorLayout.js';
3
+ export { GET as nitrogenEditorAssetsRoute } from './NitrogenEditorAssetsRoute.js';
@@ -1,5 +1,5 @@
1
- import { getNitrogenSettings } from './helpers';
2
- import { buildPermalink, buildRelativePermalink, resolveCollection, } from '../collection-registry';
1
+ import { getNitrogenSettings } from './helpers.js';
2
+ import { buildPermalink, buildRelativePermalink, resolveCollection, } from '../collection-registry.js';
3
3
  export const allEndpoints = [
4
4
  // GET /api/nitrogen/v1/all — List all items with filtering
5
5
  {
@@ -1,5 +1,5 @@
1
- import { buildPermalink, buildRelativePermalink, resolveCollection, } from "../collection-registry";
2
- import { getNitrogenSettings, buildDynamicData, buildPageResponse, } from "./helpers";
1
+ import { buildPermalink, buildRelativePermalink, resolveCollection, } from "../collection-registry.js";
2
+ import { getNitrogenSettings, buildDynamicData, buildPageResponse, } from "./helpers.js";
3
3
  function toArray(value) {
4
4
  if (Array.isArray(value)) {
5
5
  return value.map((item) => String(item).trim()).filter(Boolean);
@@ -1,4 +1,4 @@
1
- import { getNitrogenSettings, buildDynamicData, buildPageResponse, buildListItemResponse, getTemplateForType, requireAuth, } from './helpers';
1
+ import { getNitrogenSettings, buildDynamicData, buildPageResponse, buildListItemResponse, getTemplateForType, requireAuth, } from './helpers.js';
2
2
  /**
3
3
  * Creates a complete set of CRUD endpoints for a given Payload collection.
4
4
  *
@@ -1,5 +1,5 @@
1
1
  import type { Endpoint } from 'payload';
2
- import type { NitrogenComponentManifestInput } from '../inventory/manifest';
2
+ import type { NitrogenComponentManifestInput } from '../inventory/manifest.js';
3
3
  export declare function createComponentInventoryEndpoints(args: {
4
4
  collections: string[];
5
5
  componentManifest?: NitrogenComponentManifestInput;
@@ -1,5 +1,199 @@
1
- import { requireAuth } from './helpers';
2
- import { reindexAllComponentInventory } from '../inventory/indexing';
1
+ import { requireAuth } from './helpers.js';
2
+ import { findAllDocs, NITROGEN_COMPONENT_CATALOG_COLLECTION, NITROGEN_COMPONENT_USAGE_COLLECTION, reindexAllComponentInventory, } from '../inventory/indexing.js';
3
+ function moduleNameFromNode(node) {
4
+ const value = node.module;
5
+ if (typeof value === 'string')
6
+ return value;
7
+ if (value && typeof value === 'object' && typeof value.name === 'string') {
8
+ return String(value.name);
9
+ }
10
+ return null;
11
+ }
12
+ function cloneJson(value) {
13
+ return value === undefined ? value : JSON.parse(JSON.stringify(value));
14
+ }
15
+ function isSourceFilterMatch(usage, sourceFilters) {
16
+ if (!sourceFilters.length) {
17
+ return true;
18
+ }
19
+ return (sourceFilters.includes(`collection:${usage.sourceCollection}`) ||
20
+ sourceFilters.includes(`document:${usage.sourceCollection}:${usage.sourceDocumentId}`));
21
+ }
22
+ async function findUsageDocsForComponent(payload, componentName, sourceFilters) {
23
+ const usageDocs = await findAllDocs(payload, NITROGEN_COMPONENT_USAGE_COLLECTION, {
24
+ limit: 200,
25
+ where: {
26
+ componentName: {
27
+ equals: componentName,
28
+ },
29
+ },
30
+ });
31
+ return usageDocs.filter((usage) => isSourceFilterMatch(usage, sourceFilters));
32
+ }
33
+ function findModuleInTree(modules, componentName, moduleId) {
34
+ if (!Array.isArray(modules)) {
35
+ return null;
36
+ }
37
+ for (const maybeNode of modules) {
38
+ if (!maybeNode || typeof maybeNode !== 'object') {
39
+ continue;
40
+ }
41
+ const node = maybeNode;
42
+ const nodeModuleId = typeof node.id === 'string' || typeof node.id === 'number' ? String(node.id) : undefined;
43
+ const nodeComponentName = moduleNameFromNode(node);
44
+ if (nodeComponentName === componentName &&
45
+ (!moduleId || !nodeModuleId || nodeModuleId === moduleId)) {
46
+ return node;
47
+ }
48
+ const props = node.props;
49
+ if (props && typeof props === 'object') {
50
+ const children = props.children;
51
+ if (Array.isArray(children)) {
52
+ const found = findModuleInTree(children, componentName, moduleId);
53
+ if (found)
54
+ return found;
55
+ }
56
+ else if (children && typeof children === 'object') {
57
+ for (const slotChildren of Object.values(children)) {
58
+ const found = findModuleInTree(slotChildren, componentName, moduleId);
59
+ if (found)
60
+ return found;
61
+ }
62
+ }
63
+ }
64
+ if (Array.isArray(node.children)) {
65
+ const found = findModuleInTree(node.children, componentName, moduleId);
66
+ if (found)
67
+ return found;
68
+ }
69
+ }
70
+ return null;
71
+ }
72
+ function setValueAtPath(target, path, value) {
73
+ const parts = path.split('.').filter(Boolean);
74
+ let cursor = target;
75
+ parts.forEach((part, index) => {
76
+ if (index === parts.length - 1) {
77
+ cursor[part] = value;
78
+ return;
79
+ }
80
+ const next = cursor[part];
81
+ if (!next || typeof next !== 'object' || Array.isArray(next)) {
82
+ cursor[part] = {};
83
+ }
84
+ cursor = cursor[part];
85
+ });
86
+ }
87
+ function updateModulesForComponent(modules, componentName, propPath, value, options) {
88
+ if (!Array.isArray(modules)) {
89
+ return 0;
90
+ }
91
+ let occurrenceCount = 0;
92
+ modules.forEach((maybeNode) => {
93
+ if (!maybeNode || typeof maybeNode !== 'object') {
94
+ return;
95
+ }
96
+ const node = maybeNode;
97
+ if (moduleNameFromNode(node) === componentName) {
98
+ occurrenceCount += 1;
99
+ if (options.apply) {
100
+ if (!node.props || typeof node.props !== 'object' || Array.isArray(node.props)) {
101
+ node.props = {};
102
+ }
103
+ setValueAtPath(node.props, propPath, value);
104
+ }
105
+ }
106
+ const props = node.props;
107
+ if (props && typeof props === 'object') {
108
+ const children = props.children;
109
+ if (Array.isArray(children)) {
110
+ occurrenceCount += updateModulesForComponent(children, componentName, propPath, value, options);
111
+ }
112
+ else if (children && typeof children === 'object') {
113
+ Object.values(children).forEach((slotChildren) => {
114
+ occurrenceCount += updateModulesForComponent(slotChildren, componentName, propPath, value, options);
115
+ });
116
+ }
117
+ }
118
+ if (Array.isArray(node.children)) {
119
+ occurrenceCount += updateModulesForComponent(node.children, componentName, propPath, value, options);
120
+ }
121
+ });
122
+ return occurrenceCount;
123
+ }
124
+ async function getComponentCatalogDoc(payload, componentName) {
125
+ const docs = await findAllDocs(payload, NITROGEN_COMPONENT_CATALOG_COLLECTION, {
126
+ limit: 1,
127
+ where: {
128
+ componentName: {
129
+ equals: componentName,
130
+ },
131
+ },
132
+ });
133
+ return docs[0];
134
+ }
135
+ async function runComponentPropUpdate(payload, body, mode) {
136
+ const componentName = typeof body.componentName === 'string' ? body.componentName.trim() : '';
137
+ const propPath = typeof body.propPath === 'string' ? body.propPath.trim() : '';
138
+ const sourceFilters = Array.isArray(body.sourceFilters)
139
+ ? body.sourceFilters.filter((value) => typeof value === 'string')
140
+ : [];
141
+ if (!componentName || !propPath) {
142
+ return Response.json({ error: 'componentName and propPath are required.' }, { status: 400 });
143
+ }
144
+ const usageDocs = await findUsageDocsForComponent(payload, componentName, sourceFilters);
145
+ const sourceKeys = Array.from(new Set(usageDocs.map((usage) => `${usage.sourceCollection}:${usage.sourceDocumentId}`)));
146
+ const documents = [];
147
+ let occurrenceCount = 0;
148
+ for (const sourceKey of sourceKeys) {
149
+ const [collection, ...idParts] = sourceKey.split(':');
150
+ const documentId = idParts.join(':');
151
+ try {
152
+ const doc = (await payload.findByID({
153
+ collection: collection,
154
+ id: documentId,
155
+ depth: 0,
156
+ overrideAccess: true,
157
+ }));
158
+ const nextNitrogenData = cloneJson(doc.nitrogenData ?? []);
159
+ const docOccurrenceCount = updateModulesForComponent(nextNitrogenData, componentName, propPath, body.value, { apply: mode === 'apply' });
160
+ if (docOccurrenceCount === 0) {
161
+ continue;
162
+ }
163
+ occurrenceCount += docOccurrenceCount;
164
+ documents.push({
165
+ collection,
166
+ documentId,
167
+ occurrenceCount: docOccurrenceCount,
168
+ title: doc.title || doc.slug || undefined,
169
+ });
170
+ if (mode === 'apply') {
171
+ await payload.update({
172
+ collection: collection,
173
+ id: documentId,
174
+ data: {
175
+ nitrogenData: nextNitrogenData,
176
+ },
177
+ depth: 0,
178
+ overrideAccess: true,
179
+ });
180
+ }
181
+ }
182
+ catch (error) {
183
+ payload.logger.warn(`[@nitrogenbuilder/connector-payload] Could not update "${componentName}" in ${sourceKey}: ${error instanceof Error ? error.message : String(error)}`);
184
+ }
185
+ }
186
+ return {
187
+ componentName,
188
+ documentCount: documents.length,
189
+ documents,
190
+ mode,
191
+ occurrenceCount,
192
+ propPath,
193
+ success: true,
194
+ value: body.value,
195
+ };
196
+ }
3
197
  export function createComponentInventoryEndpoints(args) {
4
198
  return [
5
199
  {
@@ -16,5 +210,84 @@ export function createComponentInventoryEndpoints(args) {
16
210
  });
17
211
  },
18
212
  },
213
+ {
214
+ path: '/nitrogen/v1/component-inventory/preview-data',
215
+ method: 'get',
216
+ handler: async (req) => {
217
+ const authError = requireAuth(req);
218
+ if (authError)
219
+ return authError;
220
+ const url = new URL(req.url || '', 'http://localhost');
221
+ const componentName = url.searchParams.get('componentName')?.trim() || '';
222
+ const sourceCollection = url.searchParams.get('sourceCollection')?.trim() || '';
223
+ const sourceDocumentId = url.searchParams.get('sourceDocumentId')?.trim() || '';
224
+ const moduleId = url.searchParams.get('moduleId')?.trim() || undefined;
225
+ if (!componentName) {
226
+ return Response.json({ error: 'componentName is required.' }, { status: 400 });
227
+ }
228
+ if (sourceCollection && sourceDocumentId) {
229
+ try {
230
+ const doc = (await req.payload.findByID({
231
+ collection: sourceCollection,
232
+ id: sourceDocumentId,
233
+ depth: 0,
234
+ overrideAccess: true,
235
+ }));
236
+ const module = findModuleInTree(doc.nitrogenData, componentName, moduleId);
237
+ if (module) {
238
+ return Response.json({
239
+ componentName,
240
+ module: cloneJson(module),
241
+ source: {
242
+ collection: sourceCollection,
243
+ documentId: sourceDocumentId,
244
+ title: doc.title || doc.slug || '',
245
+ },
246
+ success: true,
247
+ });
248
+ }
249
+ }
250
+ catch {
251
+ // Fall back to a default module below.
252
+ }
253
+ }
254
+ const catalogDoc = await getComponentCatalogDoc(req.payload, componentName);
255
+ return Response.json({
256
+ componentName,
257
+ definition: catalogDoc?.definition || null,
258
+ module: {
259
+ id: `nitrogen-component-preview-${componentName}`,
260
+ module: componentName,
261
+ props: {},
262
+ },
263
+ source: null,
264
+ success: true,
265
+ });
266
+ },
267
+ },
268
+ {
269
+ path: '/nitrogen/v1/component-inventory/prop-update/preview',
270
+ method: 'post',
271
+ handler: async (req) => {
272
+ const authError = requireAuth(req);
273
+ if (authError)
274
+ return authError;
275
+ const body = (await req.json?.());
276
+ const result = await runComponentPropUpdate(req.payload, body || {}, 'preview');
277
+ return result instanceof Response ? result : Response.json(result);
278
+ },
279
+ },
280
+ {
281
+ path: '/nitrogen/v1/component-inventory/prop-update/apply',
282
+ method: 'post',
283
+ handler: async (req) => {
284
+ const authError = requireAuth(req);
285
+ if (authError)
286
+ return authError;
287
+ const body = (await req.json?.());
288
+ const result = await runComponentPropUpdate(req.payload, body || {}, 'apply');
289
+ return result instanceof Response ? result : Response.json(result);
290
+ },
291
+ },
19
292
  ];
20
293
  }
@@ -1,5 +1,5 @@
1
1
  import type { Payload, PayloadRequest } from 'payload';
2
- import type { JsonObject, NitrogenPageDoc, NitrogenTemplateDoc, NitrogenSettingsGlobal, MediaDoc } from '../types';
2
+ import type { JsonObject, NitrogenPageDoc, NitrogenTemplateDoc, NitrogenSettingsGlobal, MediaDoc } from '../types.js';
3
3
  export interface TemplateRef {
4
4
  ID: string | number;
5
5
  content: string;
@@ -60,10 +60,10 @@ export declare function buildMediaItemResponse(doc: MediaDoc): {
60
60
  height: number;
61
61
  createdAt: string;
62
62
  sizes: {
63
- [key: string]: import("../types").MediaSize | undefined;
64
- thumbnail?: import("../types").MediaSize;
65
- medium?: import("../types").MediaSize;
66
- large?: import("../types").MediaSize;
63
+ [key: string]: import("../types.js").MediaSize | undefined;
64
+ thumbnail?: import("../types.js").MediaSize;
65
+ medium?: import("../types.js").MediaSize;
66
+ large?: import("../types.js").MediaSize;
67
67
  };
68
68
  thumbnailURL: string;
69
69
  name: string;
@@ -1,4 +1,4 @@
1
- import { buildPermalink, buildRelativePermalink } from '../collection-registry';
1
+ import { buildPermalink, buildRelativePermalink } from '../collection-registry.js';
2
2
  export function formatDate(date) {
3
3
  const d = new Date(date);
4
4
  const pad = (n) => String(n).padStart(2, '0');
@@ -1,4 +1,4 @@
1
- import { buildMediaItemResponse, requireAuth } from './helpers';
1
+ import { buildMediaItemResponse, requireAuth } from './helpers.js';
2
2
  const MIME_TYPES_BY_EXTENSION = {
3
3
  '.jpg': ['image/jpeg'],
4
4
  '.jpeg': ['image/jpeg'],
@@ -1,4 +1,4 @@
1
- import { requireAuth } from './helpers';
1
+ import { requireAuth } from './helpers.js';
2
2
  export const nitrogenSettingsEndpoints = [
3
3
  // PUT /api/nitrogen/v1/nitrogen-settings — Save Nitrogen settings
4
4
  {
@@ -1,5 +1,5 @@
1
- import { getNitrogenSettings, buildDynamicData, buildPageResponse, buildListItemResponse, getTemplateForType, requireAuth, } from './helpers';
2
- import { buildPermalink, buildRelativePermalink } from '../collection-registry';
1
+ import { getNitrogenSettings, buildDynamicData, buildPageResponse, buildListItemResponse, getTemplateForType, requireAuth, } from './helpers.js';
2
+ import { buildPermalink, buildRelativePermalink } from '../collection-registry.js';
3
3
  function isContentTemplateCollection(collection) {
4
4
  return !!collection && collection !== 'header' && collection !== 'footer';
5
5
  }
@@ -1,7 +1,7 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { getPayload } from 'payload';
3
- import { NitrogenPageClient } from './NitrogenPageClient';
4
- import { buildDynamicData, getNitrogenSettings } from '../endpoints/helpers';
3
+ import { NitrogenPageClient } from './NitrogenPageClient.js';
4
+ import { buildDynamicData, getNitrogenSettings } from '../endpoints/helpers.js';
5
5
  /**
6
6
  * Server component that wraps your page content and automatically handles
7
7
  * Nitrogen builder mode and Nitrogen-rendered pages.
@@ -1,7 +1,7 @@
1
- export { NitrogenWrapper } from "./NitrogenWrapper";
2
- export type { NitrogenWrapperProps } from "./NitrogenWrapper";
3
- export { NitrogenPageClient } from "./NitrogenPageClient";
4
- export type { NitrogenPageClientProps } from "./NitrogenPageClient";
5
- export { buildDynamicData, getNitrogenSettings } from "../endpoints/helpers";
1
+ export { NitrogenWrapper } from "./NitrogenWrapper.js";
2
+ export type { NitrogenWrapperProps } from "./NitrogenWrapper.js";
3
+ export { NitrogenPageClient } from "./NitrogenPageClient.js";
4
+ export type { NitrogenPageClientProps } from "./NitrogenPageClient.js";
5
+ export { buildDynamicData, getNitrogenSettings } from "../endpoints/helpers.js";
6
6
  export { nitrogen } from "@nitrogenbuilder/client-core";
7
7
  export type { ComponentSettings, ComponentSettingsToProps, } from "@nitrogenbuilder/types";
@@ -1,8 +1,8 @@
1
1
  // Main export - use NitrogenWrapper for simplest integration
2
- export { NitrogenWrapper } from "./NitrogenWrapper";
2
+ export { NitrogenWrapper } from "./NitrogenWrapper.js";
3
3
  // Lower-level exports for custom implementations
4
- export { NitrogenPageClient } from "./NitrogenPageClient";
4
+ export { NitrogenPageClient } from "./NitrogenPageClient.js";
5
5
  // Helper exports for data fetching (server-safe)
6
- export { buildDynamicData, getNitrogenSettings } from "../endpoints/helpers";
6
+ export { buildDynamicData, getNitrogenSettings } from "../endpoints/helpers.js";
7
7
  // Re-export nitrogen singleton for registering custom components
8
8
  export { nitrogen } from "@nitrogenbuilder/client-core";