@nitrogenbuilder/connector-payload 1.2.0 → 1.2.2

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.
@@ -1,10 +1,31 @@
1
+ import { existsSync } from "node:fs";
1
2
  import fs from "node:fs/promises";
3
+ import { createRequire } from "node:module";
2
4
  import path from "node:path";
3
5
  import { fileURLToPath } from "node:url";
4
6
  import { NextResponse } from "next/server";
5
7
  const __filename = fileURLToPath(import.meta.url);
6
8
  const __dirname = path.dirname(__filename);
7
- const ASSETS_DIR = path.resolve(__dirname, "..", "editor-assets");
9
+ // Next bundles npm packages into server chunks, so in a production build
10
+ // __dirname points into .next/server and the relative lookup fails. Resolve
11
+ // the installed package on disk through Node's resolver instead (works from
12
+ // inside a bundle because createRequire resolves against the host app's real
13
+ // node_modules), and keep the relative path as a fallback for unbundled /
14
+ // linked-dev execution where the package specifier may not resolve.
15
+ function resolveAssetsDir() {
16
+ try {
17
+ const nodeRequire = createRequire(import.meta.url);
18
+ const pkgRoot = path.dirname(nodeRequire.resolve("@nitrogenbuilder/connector-payload/package.json"));
19
+ const dir = path.join(pkgRoot, "dist", "editor-assets");
20
+ if (existsSync(dir))
21
+ return dir;
22
+ }
23
+ catch {
24
+ // fall through to the relative fallback
25
+ }
26
+ return path.resolve(__dirname, "..", "editor-assets");
27
+ }
28
+ const ASSETS_DIR = resolveAssetsDir();
8
29
  function getContentType(filePath) {
9
30
  switch (path.extname(filePath).toLowerCase()) {
10
31
  case ".css":
@@ -106,6 +106,35 @@ function resolveMediaUrl(url, settings) {
106
106
  const relativeUrl = url.startsWith('/') ? url : `/${url}`;
107
107
  return baseUrl ? `${baseUrl}${relativeUrl}` : relativeUrl;
108
108
  }
109
+ const MEDIA_PATH_MARKER = 'api/media/file/';
110
+ // The editor's wysiwyg (TinyMCE) rewrites same-origin media URLs to relative
111
+ // paths on save (e.g. `../../api/media/file/x.pdf`), which 404 on the frontend
112
+ // host. Re-anchor anything that is only `./`/`../` hops away from the media
113
+ // path back to the Payload origin; other relative URLs are left untouched.
114
+ function resolveInlineMediaUrl(url, settings) {
115
+ if (/^https?:\/\//i.test(url))
116
+ return url;
117
+ const index = url.indexOf(MEDIA_PATH_MARKER);
118
+ if (index === -1)
119
+ return url;
120
+ const prefix = url.slice(0, index);
121
+ if (!/^[./]*$/.test(prefix))
122
+ return url;
123
+ return resolveMediaUrl(`/${url.slice(index)}`, settings);
124
+ }
125
+ function resolveInlineMediaUrls(value, settings) {
126
+ if (!value.includes(MEDIA_PATH_MARKER))
127
+ return value;
128
+ if (!value.includes('<')) {
129
+ const trimmed = value.trim();
130
+ const resolved = resolveInlineMediaUrl(trimmed, settings);
131
+ return resolved === trimmed ? value : resolved;
132
+ }
133
+ return value.replace(/((?:href|src)=)(["'])([^"']*)\2/gi, (match, attr, quote, url) => {
134
+ const resolved = resolveInlineMediaUrl(url, settings);
135
+ return resolved === url ? match : `${attr}${quote}${resolved}${quote}`;
136
+ });
137
+ }
109
138
  async function findInternalTarget(context, link, internalRef) {
110
139
  const entryId = getId(internalRef.entryId);
111
140
  if (entryId === null)
@@ -205,13 +234,25 @@ async function resolveLinkRecord(context, link) {
205
234
  }
206
235
  async function walk(context, value) {
207
236
  if (Array.isArray(value)) {
208
- await Promise.all(value.map((item) => walk(context, item)));
237
+ await Promise.all(value.map(async (item, index) => {
238
+ if (typeof item === 'string') {
239
+ value[index] = resolveInlineMediaUrls(item, context.settings);
240
+ return;
241
+ }
242
+ await walk(context, item);
243
+ }));
209
244
  return;
210
245
  }
211
246
  if (!isRecord(value))
212
247
  return;
213
248
  await resolveLinkRecord(context, value);
214
- await Promise.all(Object.values(value).map((item) => walk(context, item)));
249
+ await Promise.all(Object.entries(value).map(async ([key, item]) => {
250
+ if (typeof item === 'string') {
251
+ value[key] = resolveInlineMediaUrls(item, context.settings);
252
+ return;
253
+ }
254
+ await walk(context, item);
255
+ }));
215
256
  }
216
257
  export async function resolveCtrlLinksInNitrogenData(payload, value, settings) {
217
258
  if (!value)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitrogenbuilder/connector-payload",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
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",
@@ -23,7 +23,8 @@
23
23
  "types": "./dist/editor/NitrogenEditorAssetsRoute.d.ts",
24
24
  "default": "./dist/editor/NitrogenEditorAssetsRoute.js"
25
25
  },
26
- "./components/*": "./dist/components/*"
26
+ "./components/*": "./dist/components/*",
27
+ "./package.json": "./package.json"
27
28
  },
28
29
  "files": [
29
30
  "dist"