payload 3.90.1 → 3.91.0-internal.07e4582
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/bin.js +3 -14
- package/dist/auth/endpoints/refresh.d.ts.map +1 -1
- package/dist/auth/endpoints/refresh.js +4 -6
- package/dist/auth/endpoints/refresh.js.map +1 -1
- package/dist/bin/index.d.ts.map +1 -1
- package/dist/bin/index.js +15 -0
- package/dist/bin/index.js.map +1 -1
- package/dist/bin/index.spec.js +54 -0
- package/dist/bin/index.spec.js.map +1 -0
- package/dist/collections/operations/findByID.d.ts.map +1 -1
- package/dist/collections/operations/findByID.js +54 -6
- package/dist/collections/operations/findByID.js.map +1 -1
- package/dist/database/createSchemaBuildContext.d.ts +12 -0
- package/dist/database/createSchemaBuildContext.d.ts.map +1 -0
- package/dist/database/createSchemaBuildContext.js +24 -0
- package/dist/database/createSchemaBuildContext.js.map +1 -0
- package/dist/database/createSchemaBuildContext.spec.js +146 -0
- package/dist/database/createSchemaBuildContext.spec.js.map +1 -0
- package/dist/exports/internal.d.ts +2 -0
- package/dist/exports/internal.d.ts.map +1 -1
- package/dist/exports/internal.js +1 -0
- package/dist/exports/internal.js.map +1 -1
- package/dist/exports/shared.d.ts +1 -1
- package/dist/exports/shared.d.ts.map +1 -1
- package/dist/exports/shared.js +1 -1
- package/dist/exports/shared.js.map +1 -1
- package/dist/fields/baseFields/slug/generateSlug.js +3 -3
- package/dist/fields/baseFields/slug/generateSlug.js.map +1 -1
- package/dist/fields/baseFields/slug/generateSlug.spec.js +22 -0
- package/dist/fields/baseFields/slug/generateSlug.spec.js.map +1 -0
- package/dist/globals/operations/findVersionByID.d.ts.map +1 -1
- package/dist/globals/operations/findVersionByID.js +4 -3
- package/dist/globals/operations/findVersionByID.js.map +1 -1
- package/dist/queues/utilities/updateJob.d.ts.map +1 -1
- package/dist/queues/utilities/updateJob.js +15 -0
- package/dist/queues/utilities/updateJob.js.map +1 -1
- package/dist/utilities/formatAdminURL.d.ts +1 -0
- package/dist/utilities/formatAdminURL.d.ts.map +1 -1
- package/dist/utilities/formatAdminURL.js +22 -4
- package/dist/utilities/formatAdminURL.js.map +1 -1
- package/dist/utilities/formatAdminURL.spec.js +98 -2
- package/dist/utilities/formatAdminURL.spec.js.map +1 -1
- package/dist/utilities/getNextJsHMRURL.d.ts.map +1 -1
- package/dist/utilities/getNextJsHMRURL.js +4 -2
- package/dist/utilities/getNextJsHMRURL.js.map +1 -1
- package/dist/utilities/getNextJsHMRURL.spec.js +11 -0
- package/dist/utilities/getNextJsHMRURL.spec.js.map +1 -1
- package/dist/utilities/handleEndpoints.d.ts.map +1 -1
- package/dist/utilities/handleEndpoints.js +5 -3
- package/dist/utilities/handleEndpoints.js.map +1 -1
- package/lexicalLoader.mjs +26 -0
- package/package.json +5 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/formatAdminURL.ts"],"sourcesContent":["import type { Config } from '../config/types.js'\n\n/**\n * This function builds correct URLs for admin panel routing.\n * Its primary responsibilities are:\n * 1. Read from your `routes.admin` config and appropriately handle `\"/\"` admin paths\n * 2. Prepend the `basePath` from your Next.js config, if specified\n * 3. Return relative or absolute URLs, as needed\n */\ntype BaseFormatURLArgs = {\n /**\n * The subpath of your application, if specified.\n * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/basePath\n * @example '/docs'\n */\n basePath?: string\n includeBasePath?: boolean\n path?: '' | `/${string}` | null\n /**\n * Return a relative URL, e.g. ignore `serverURL`.\n * Useful for route-matching, etc.\n */\n relative?: boolean\n} & Pick<Config, 'serverURL'>\n\ntype FormatURLArgs =\n | ({\n adminRoute: NonNullable<Config['routes']>['admin']\n apiRoute?: never\n } & BaseFormatURLArgs)\n | ({\n adminRoute?: never\n apiRoute: NonNullable<Config['routes']>['api']\n } & BaseFormatURLArgs)\n\nexport const formatAdminURL = (args: FormatURLArgs): string => {\n const {\n adminRoute,\n apiRoute,\n includeBasePath: includeBasePathArg,\n path = '',\n relative = false,\n serverURL,\n } = args\n const basePath = process.env.NEXT_BASE_PATH || args.basePath || ''\n const routePath = adminRoute || apiRoute\n const segments = [routePath && routePath !== '/' && routePath, path && path].filter(Boolean)\n const pathname = segments.join('') || '/'\n const pathnameWithBase = (basePath + pathname)
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/formatAdminURL.ts"],"sourcesContent":["import type { Config } from '../config/types.js'\n\n/**\n * This function builds correct URLs for admin panel routing.\n * Its primary responsibilities are:\n * 1. Read from your `routes.admin` config and appropriately handle `\"/\"` admin paths\n * 2. Prepend the `basePath` from your Next.js config, if specified\n * 3. Return relative or absolute URLs, as needed\n */\ntype BaseFormatURLArgs = {\n /**\n * The subpath of your application, if specified.\n * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/basePath\n * @example '/docs'\n */\n basePath?: string\n includeBasePath?: boolean\n path?: '' | `/${string}` | null\n /**\n * Return a relative URL, e.g. ignore `serverURL`.\n * Useful for route-matching, etc.\n */\n relative?: boolean\n} & Pick<Config, 'serverURL'>\n\ntype FormatURLArgs =\n | ({\n adminRoute: NonNullable<Config['routes']>['admin']\n apiRoute?: never\n } & BaseFormatURLArgs)\n | ({\n adminRoute?: never\n apiRoute: NonNullable<Config['routes']>['api']\n } & BaseFormatURLArgs)\n\nexport const formatAdminURL = (args: FormatURLArgs): string => {\n const {\n adminRoute,\n apiRoute,\n includeBasePath: includeBasePathArg,\n path = '',\n relative = false,\n serverURL,\n } = args\n const basePath = process.env.NEXT_BASE_PATH || args.basePath || ''\n const routePath = adminRoute || apiRoute\n const segments = [routePath && routePath !== '/' && routePath, path && path].filter(Boolean)\n const pathname = segments.join('') || '/'\n const pathnameWithBase = stripTrailingSlash(basePath + pathname) || '/'\n const includeBasePath = includeBasePathArg ?? (adminRoute ? false : true)\n\n if (relative || !serverURL) {\n if (includeBasePath && basePath) {\n return applyTrailingSlash(pathnameWithBase)\n }\n return applyTrailingSlash(pathname)\n }\n\n const serverURLObj = new URL(serverURL)\n return applyTrailingSlash(new URL(pathnameWithBase, serverURLObj.origin).toString())\n}\n\nexport const stripTrailingSlash = (path: string): string => {\n if (path.length > 1 && path.endsWith('/')) {\n return path.slice(0, -1)\n }\n\n return path\n}\n\nconst applyTrailingSlash = (url: string): string => {\n if (process.env.NEXT_TRAILING_SLASH !== 'true') {\n return url\n }\n const queryIndex = url.search(/[?#]/)\n const pathPart = queryIndex === -1 ? url : url.slice(0, queryIndex)\n const queryPart = queryIndex === -1 ? '' : url.slice(queryIndex)\n if (pathPart.endsWith('/')) {\n return url\n }\n return `${pathPart}/${queryPart}`\n}\n"],"names":["formatAdminURL","args","adminRoute","apiRoute","includeBasePath","includeBasePathArg","path","relative","serverURL","basePath","process","env","NEXT_BASE_PATH","routePath","segments","filter","Boolean","pathname","join","pathnameWithBase","stripTrailingSlash","applyTrailingSlash","serverURLObj","URL","origin","toString","length","endsWith","slice","url","NEXT_TRAILING_SLASH","queryIndex","search","pathPart","queryPart"],"mappings":"AAmCA,OAAO,MAAMA,iBAAiB,CAACC;IAC7B,MAAM,EACJC,UAAU,EACVC,QAAQ,EACRC,iBAAiBC,kBAAkB,EACnCC,OAAO,EAAE,EACTC,WAAW,KAAK,EAChBC,SAAS,EACV,GAAGP;IACJ,MAAMQ,WAAWC,QAAQC,GAAG,CAACC,cAAc,IAAIX,KAAKQ,QAAQ,IAAI;IAChE,MAAMI,YAAYX,cAAcC;IAChC,MAAMW,WAAW;QAACD,aAAaA,cAAc,OAAOA;QAAWP,QAAQA;KAAK,CAACS,MAAM,CAACC;IACpF,MAAMC,WAAWH,SAASI,IAAI,CAAC,OAAO;IACtC,MAAMC,mBAAmBC,mBAAmBX,WAAWQ,aAAa;IACpE,MAAMb,kBAAkBC,sBAAuBH,CAAAA,aAAa,QAAQ,IAAG;IAEvE,IAAIK,YAAY,CAACC,WAAW;QAC1B,IAAIJ,mBAAmBK,UAAU;YAC/B,OAAOY,mBAAmBF;QAC5B;QACA,OAAOE,mBAAmBJ;IAC5B;IAEA,MAAMK,eAAe,IAAIC,IAAIf;IAC7B,OAAOa,mBAAmB,IAAIE,IAAIJ,kBAAkBG,aAAaE,MAAM,EAAEC,QAAQ;AACnF,EAAC;AAED,OAAO,MAAML,qBAAqB,CAACd;IACjC,IAAIA,KAAKoB,MAAM,GAAG,KAAKpB,KAAKqB,QAAQ,CAAC,MAAM;QACzC,OAAOrB,KAAKsB,KAAK,CAAC,GAAG,CAAC;IACxB;IAEA,OAAOtB;AACT,EAAC;AAED,MAAMe,qBAAqB,CAACQ;IAC1B,IAAInB,QAAQC,GAAG,CAACmB,mBAAmB,KAAK,QAAQ;QAC9C,OAAOD;IACT;IACA,MAAME,aAAaF,IAAIG,MAAM,CAAC;IAC9B,MAAMC,WAAWF,eAAe,CAAC,IAAIF,MAAMA,IAAID,KAAK,CAAC,GAAGG;IACxD,MAAMG,YAAYH,eAAe,CAAC,IAAI,KAAKF,IAAID,KAAK,CAACG;IACrD,IAAIE,SAASN,QAAQ,CAAC,MAAM;QAC1B,OAAOE;IACT;IACA,OAAO,GAAGI,SAAS,CAAC,EAAEC,WAAW;AACnC"}
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { formatAdminURL } from './formatAdminURL.js';
|
|
1
|
+
import { afterEach, beforeEach, describe, it, expect } from 'vitest';
|
|
2
|
+
import { formatAdminURL, stripTrailingSlash } from './formatAdminURL.js';
|
|
3
3
|
describe('formatAdminURL', ()=>{
|
|
4
4
|
const serverURL = 'https://example.com';
|
|
5
5
|
const defaultAdminRoute = '/admin';
|
|
6
6
|
const rootAdminRoute = '/';
|
|
7
7
|
const dummyPath = '/collections/posts';
|
|
8
|
+
describe('stripTrailingSlash', ()=>{
|
|
9
|
+
it('removes a trailing slash while preserving the root path', ()=>{
|
|
10
|
+
expect(stripTrailingSlash('/admin/')).toBe('/admin');
|
|
11
|
+
expect(stripTrailingSlash('/')).toBe('/');
|
|
12
|
+
expect(stripTrailingSlash('/admin')).toBe('/admin');
|
|
13
|
+
});
|
|
14
|
+
});
|
|
8
15
|
describe('relative URLs', ()=>{
|
|
9
16
|
it('should ignore `serverURL` when relative=true', ()=>{
|
|
10
17
|
const result = formatAdminURL({
|
|
@@ -163,6 +170,95 @@ describe('formatAdminURL', ()=>{
|
|
|
163
170
|
expect(result).toBe('/');
|
|
164
171
|
});
|
|
165
172
|
});
|
|
173
|
+
describe('trailing slash handling', ()=>{
|
|
174
|
+
const originalTrailingSlash = process.env.NEXT_TRAILING_SLASH;
|
|
175
|
+
beforeEach(()=>{
|
|
176
|
+
process.env.NEXT_TRAILING_SLASH = 'true';
|
|
177
|
+
});
|
|
178
|
+
afterEach(()=>{
|
|
179
|
+
if (originalTrailingSlash === undefined) {
|
|
180
|
+
delete process.env.NEXT_TRAILING_SLASH;
|
|
181
|
+
} else {
|
|
182
|
+
process.env.NEXT_TRAILING_SLASH = originalTrailingSlash;
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
it('should append trailing slash to relative admin URL', ()=>{
|
|
186
|
+
const result = formatAdminURL({
|
|
187
|
+
adminRoute: defaultAdminRoute,
|
|
188
|
+
path: dummyPath,
|
|
189
|
+
relative: true
|
|
190
|
+
});
|
|
191
|
+
expect(result).toBe(`${defaultAdminRoute}${dummyPath}/`);
|
|
192
|
+
});
|
|
193
|
+
it('should append trailing slash to relative api URL', ()=>{
|
|
194
|
+
const result = formatAdminURL({
|
|
195
|
+
apiRoute: '/api',
|
|
196
|
+
path: '/users',
|
|
197
|
+
relative: true
|
|
198
|
+
});
|
|
199
|
+
expect(result).toBe(`${process.env.NEXT_BASE_PATH || ''}/api/users/`);
|
|
200
|
+
});
|
|
201
|
+
it('should append trailing slash to absolute URL', ()=>{
|
|
202
|
+
const result = formatAdminURL({
|
|
203
|
+
adminRoute: defaultAdminRoute,
|
|
204
|
+
path: dummyPath,
|
|
205
|
+
serverURL
|
|
206
|
+
});
|
|
207
|
+
expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}${dummyPath}/`);
|
|
208
|
+
});
|
|
209
|
+
it('should append trailing slash when basePath is set', ()=>{
|
|
210
|
+
const result = formatAdminURL({
|
|
211
|
+
apiRoute: '/api',
|
|
212
|
+
basePath: '/v1',
|
|
213
|
+
path: '/users',
|
|
214
|
+
serverURL
|
|
215
|
+
});
|
|
216
|
+
expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}/v1/api/users/`);
|
|
217
|
+
});
|
|
218
|
+
it('should not append trailing slash to root "/"', ()=>{
|
|
219
|
+
const result = formatAdminURL({
|
|
220
|
+
adminRoute: rootAdminRoute,
|
|
221
|
+
relative: true
|
|
222
|
+
});
|
|
223
|
+
expect(result).toBe('/');
|
|
224
|
+
});
|
|
225
|
+
it('should not double-slash when path already ends with /', ()=>{
|
|
226
|
+
const result = formatAdminURL({
|
|
227
|
+
adminRoute: defaultAdminRoute,
|
|
228
|
+
path: '/collections/posts',
|
|
229
|
+
relative: true
|
|
230
|
+
});
|
|
231
|
+
expect(result.endsWith('//')).toBe(false);
|
|
232
|
+
expect(result).toBe(`${defaultAdminRoute}/collections/posts/`);
|
|
233
|
+
});
|
|
234
|
+
it('should place trailing slash before query string', ()=>{
|
|
235
|
+
const path = `${dummyPath}?page=2`;
|
|
236
|
+
const result = formatAdminURL({
|
|
237
|
+
adminRoute: defaultAdminRoute,
|
|
238
|
+
path,
|
|
239
|
+
relative: true
|
|
240
|
+
});
|
|
241
|
+
expect(result).toBe(`${defaultAdminRoute}${dummyPath}/?page=2`);
|
|
242
|
+
});
|
|
243
|
+
it('should leave URLs unchanged when env var is not set', ()=>{
|
|
244
|
+
delete process.env.NEXT_TRAILING_SLASH;
|
|
245
|
+
const result = formatAdminURL({
|
|
246
|
+
adminRoute: defaultAdminRoute,
|
|
247
|
+
path: dummyPath,
|
|
248
|
+
relative: true
|
|
249
|
+
});
|
|
250
|
+
expect(result).toBe(`${defaultAdminRoute}${dummyPath}`);
|
|
251
|
+
});
|
|
252
|
+
it('should leave URLs unchanged when env var is "false"', ()=>{
|
|
253
|
+
process.env.NEXT_TRAILING_SLASH = 'false';
|
|
254
|
+
const result = formatAdminURL({
|
|
255
|
+
adminRoute: defaultAdminRoute,
|
|
256
|
+
path: dummyPath,
|
|
257
|
+
relative: true
|
|
258
|
+
});
|
|
259
|
+
expect(result).toBe(`${defaultAdminRoute}${dummyPath}`);
|
|
260
|
+
});
|
|
261
|
+
});
|
|
166
262
|
});
|
|
167
263
|
|
|
168
264
|
//# sourceMappingURL=formatAdminURL.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/formatAdminURL.spec.ts"],"sourcesContent":["import { describe, it, expect } from 'vitest'\nimport { formatAdminURL } from './formatAdminURL.js'\n\ndescribe('formatAdminURL', () => {\n const serverURL = 'https://example.com'\n\n const defaultAdminRoute = '/admin'\n const rootAdminRoute = '/'\n\n const dummyPath = '/collections/posts'\n\n describe('relative URLs', () => {\n it('should ignore `serverURL` when relative=true', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: dummyPath,\n serverURL,\n relative: true,\n })\n\n expect(result).toBe(`${defaultAdminRoute}${dummyPath}`)\n })\n\n it('should force relative URL when `serverURL` is omitted', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: dummyPath,\n relative: false,\n })\n\n expect(result).toBe(`${defaultAdminRoute}${dummyPath}`)\n })\n })\n\n describe('absolute URLs', () => {\n it('should return absolute URL with serverURL', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: dummyPath,\n serverURL,\n })\n\n expect(result).toBe(\n `${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}${dummyPath}`,\n )\n })\n\n it('should handle serverURL with trailing slash', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: '/collections/posts',\n serverURL: 'https://example.com/',\n })\n\n expect(result).toBe(\n `https://example.com${process.env.NEXT_BASE_PATH || ''}/admin/collections/posts`,\n )\n })\n\n it('should handle serverURL with subdirectory', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: '/collections/posts',\n serverURL: 'https://example.com/api/v1',\n })\n\n expect(result).toBe(\n `https://example.com${process.env.NEXT_BASE_PATH || ''}/admin/collections/posts`,\n )\n })\n })\n\n describe('admin route handling', () => {\n it('should return relative URL for adminRoute=\"/\", no path, no `serverURL`', () => {\n const result = formatAdminURL({\n adminRoute: rootAdminRoute,\n })\n\n expect(result).toBe('/')\n })\n\n it('should handle relative URL for adminRoute=\"/\", with path, no `serverURL`', () => {\n const result = formatAdminURL({\n adminRoute: rootAdminRoute,\n path: dummyPath,\n })\n\n expect(result).toBe(dummyPath)\n })\n\n it('should return absolute URL for adminRoute=\"/\", no path, with `serverURL`', () => {\n const result = formatAdminURL({\n adminRoute: rootAdminRoute,\n serverURL,\n })\n\n expect(result).toBe('https://example.com/')\n })\n\n it('should handle absolute URL for adminRoute=\"/\", with path and `serverURL`', () => {\n const result = formatAdminURL({\n adminRoute: rootAdminRoute,\n serverURL,\n path: dummyPath,\n })\n\n expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}${dummyPath}`)\n })\n })\n\n describe('base path handling', () => {\n it('should include basePath in URL', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n basePath: '/v1',\n path: dummyPath,\n serverURL,\n })\n\n expect(result).toBe(\n `${serverURL}${process.env.NEXT_BASE_PATH || ''}/v1${defaultAdminRoute}${dummyPath}`,\n )\n })\n\n it('should handle basePath with adminRoute=\"/\"', () => {\n const result = formatAdminURL({\n adminRoute: rootAdminRoute,\n basePath: '/v1',\n serverURL,\n })\n\n expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}/v1`)\n })\n\n it('should handle basePath with no adminRoute', () => {\n const result = formatAdminURL({\n adminRoute: undefined,\n basePath: '/v1',\n path: dummyPath,\n serverURL,\n })\n\n expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}/v1${dummyPath}`)\n })\n\n it('should handle empty basePath', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n basePath: '',\n path: dummyPath,\n serverURL,\n })\n\n expect(result).toBe(\n `${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}${dummyPath}`,\n )\n })\n })\n\n describe('path handling', () => {\n it('should handle empty string path', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: '',\n serverURL,\n })\n\n expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}`)\n })\n\n it('should handle null path', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: null,\n serverURL,\n })\n expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}`)\n })\n\n it('should handle undefined path', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: undefined,\n serverURL,\n })\n\n expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}`)\n })\n\n it('should handle path with query parameters', () => {\n const path = `${dummyPath}?page=2`\n\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path,\n serverURL,\n })\n\n expect(result).toBe(\n `${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}${path}`,\n )\n })\n })\n\n describe('edge cases', () => {\n it('should return \"/\" when given minimal args', () => {\n const result = formatAdminURL({\n adminRoute: undefined,\n basePath: '',\n path: '',\n relative: true,\n })\n\n expect(result).toBe('/')\n })\n })\n})\n"],"names":["describe","it","expect","formatAdminURL","serverURL","defaultAdminRoute","rootAdminRoute","dummyPath","result","adminRoute","path","relative","toBe","process","env","NEXT_BASE_PATH","basePath","undefined"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/formatAdminURL.spec.ts"],"sourcesContent":["import { afterEach, beforeEach, describe, it, expect } from 'vitest'\nimport { formatAdminURL, stripTrailingSlash } from './formatAdminURL.js'\n\ndescribe('formatAdminURL', () => {\n const serverURL = 'https://example.com'\n\n const defaultAdminRoute = '/admin'\n const rootAdminRoute = '/'\n\n const dummyPath = '/collections/posts'\n\n describe('stripTrailingSlash', () => {\n it('removes a trailing slash while preserving the root path', () => {\n expect(stripTrailingSlash('/admin/')).toBe('/admin')\n expect(stripTrailingSlash('/')).toBe('/')\n expect(stripTrailingSlash('/admin')).toBe('/admin')\n })\n })\n\n describe('relative URLs', () => {\n it('should ignore `serverURL` when relative=true', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: dummyPath,\n serverURL,\n relative: true,\n })\n\n expect(result).toBe(`${defaultAdminRoute}${dummyPath}`)\n })\n\n it('should force relative URL when `serverURL` is omitted', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: dummyPath,\n relative: false,\n })\n\n expect(result).toBe(`${defaultAdminRoute}${dummyPath}`)\n })\n })\n\n describe('absolute URLs', () => {\n it('should return absolute URL with serverURL', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: dummyPath,\n serverURL,\n })\n\n expect(result).toBe(\n `${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}${dummyPath}`,\n )\n })\n\n it('should handle serverURL with trailing slash', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: '/collections/posts',\n serverURL: 'https://example.com/',\n })\n\n expect(result).toBe(\n `https://example.com${process.env.NEXT_BASE_PATH || ''}/admin/collections/posts`,\n )\n })\n\n it('should handle serverURL with subdirectory', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: '/collections/posts',\n serverURL: 'https://example.com/api/v1',\n })\n\n expect(result).toBe(\n `https://example.com${process.env.NEXT_BASE_PATH || ''}/admin/collections/posts`,\n )\n })\n })\n\n describe('admin route handling', () => {\n it('should return relative URL for adminRoute=\"/\", no path, no `serverURL`', () => {\n const result = formatAdminURL({\n adminRoute: rootAdminRoute,\n })\n\n expect(result).toBe('/')\n })\n\n it('should handle relative URL for adminRoute=\"/\", with path, no `serverURL`', () => {\n const result = formatAdminURL({\n adminRoute: rootAdminRoute,\n path: dummyPath,\n })\n\n expect(result).toBe(dummyPath)\n })\n\n it('should return absolute URL for adminRoute=\"/\", no path, with `serverURL`', () => {\n const result = formatAdminURL({\n adminRoute: rootAdminRoute,\n serverURL,\n })\n\n expect(result).toBe('https://example.com/')\n })\n\n it('should handle absolute URL for adminRoute=\"/\", with path and `serverURL`', () => {\n const result = formatAdminURL({\n adminRoute: rootAdminRoute,\n serverURL,\n path: dummyPath,\n })\n\n expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}${dummyPath}`)\n })\n })\n\n describe('base path handling', () => {\n it('should include basePath in URL', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n basePath: '/v1',\n path: dummyPath,\n serverURL,\n })\n\n expect(result).toBe(\n `${serverURL}${process.env.NEXT_BASE_PATH || ''}/v1${defaultAdminRoute}${dummyPath}`,\n )\n })\n\n it('should handle basePath with adminRoute=\"/\"', () => {\n const result = formatAdminURL({\n adminRoute: rootAdminRoute,\n basePath: '/v1',\n serverURL,\n })\n\n expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}/v1`)\n })\n\n it('should handle basePath with no adminRoute', () => {\n const result = formatAdminURL({\n adminRoute: undefined,\n basePath: '/v1',\n path: dummyPath,\n serverURL,\n })\n\n expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}/v1${dummyPath}`)\n })\n\n it('should handle empty basePath', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n basePath: '',\n path: dummyPath,\n serverURL,\n })\n\n expect(result).toBe(\n `${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}${dummyPath}`,\n )\n })\n })\n\n describe('path handling', () => {\n it('should handle empty string path', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: '',\n serverURL,\n })\n\n expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}`)\n })\n\n it('should handle null path', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: null,\n serverURL,\n })\n expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}`)\n })\n\n it('should handle undefined path', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: undefined,\n serverURL,\n })\n\n expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}`)\n })\n\n it('should handle path with query parameters', () => {\n const path = `${dummyPath}?page=2`\n\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path,\n serverURL,\n })\n\n expect(result).toBe(\n `${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}${path}`,\n )\n })\n })\n\n describe('edge cases', () => {\n it('should return \"/\" when given minimal args', () => {\n const result = formatAdminURL({\n adminRoute: undefined,\n basePath: '',\n path: '',\n relative: true,\n })\n\n expect(result).toBe('/')\n })\n })\n\n describe('trailing slash handling', () => {\n const originalTrailingSlash = process.env.NEXT_TRAILING_SLASH\n\n beforeEach(() => {\n process.env.NEXT_TRAILING_SLASH = 'true'\n })\n\n afterEach(() => {\n if (originalTrailingSlash === undefined) {\n delete process.env.NEXT_TRAILING_SLASH\n } else {\n process.env.NEXT_TRAILING_SLASH = originalTrailingSlash\n }\n })\n\n it('should append trailing slash to relative admin URL', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: dummyPath,\n relative: true,\n })\n\n expect(result).toBe(`${defaultAdminRoute}${dummyPath}/`)\n })\n\n it('should append trailing slash to relative api URL', () => {\n const result = formatAdminURL({\n apiRoute: '/api',\n path: '/users',\n relative: true,\n })\n\n expect(result).toBe(`${process.env.NEXT_BASE_PATH || ''}/api/users/`)\n })\n\n it('should append trailing slash to absolute URL', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: dummyPath,\n serverURL,\n })\n\n expect(result).toBe(\n `${serverURL}${process.env.NEXT_BASE_PATH || ''}${defaultAdminRoute}${dummyPath}/`,\n )\n })\n\n it('should append trailing slash when basePath is set', () => {\n const result = formatAdminURL({\n apiRoute: '/api',\n basePath: '/v1',\n path: '/users',\n serverURL,\n })\n\n expect(result).toBe(`${serverURL}${process.env.NEXT_BASE_PATH || ''}/v1/api/users/`)\n })\n\n it('should not append trailing slash to root \"/\"', () => {\n const result = formatAdminURL({\n adminRoute: rootAdminRoute,\n relative: true,\n })\n\n expect(result).toBe('/')\n })\n\n it('should not double-slash when path already ends with /', () => {\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: '/collections/posts',\n relative: true,\n })\n\n expect(result.endsWith('//')).toBe(false)\n expect(result).toBe(`${defaultAdminRoute}/collections/posts/`)\n })\n\n it('should place trailing slash before query string', () => {\n const path = `${dummyPath}?page=2`\n\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path,\n relative: true,\n })\n\n expect(result).toBe(`${defaultAdminRoute}${dummyPath}/?page=2`)\n })\n\n it('should leave URLs unchanged when env var is not set', () => {\n delete process.env.NEXT_TRAILING_SLASH\n\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: dummyPath,\n relative: true,\n })\n\n expect(result).toBe(`${defaultAdminRoute}${dummyPath}`)\n })\n\n it('should leave URLs unchanged when env var is \"false\"', () => {\n process.env.NEXT_TRAILING_SLASH = 'false'\n\n const result = formatAdminURL({\n adminRoute: defaultAdminRoute,\n path: dummyPath,\n relative: true,\n })\n\n expect(result).toBe(`${defaultAdminRoute}${dummyPath}`)\n })\n })\n})\n"],"names":["afterEach","beforeEach","describe","it","expect","formatAdminURL","stripTrailingSlash","serverURL","defaultAdminRoute","rootAdminRoute","dummyPath","toBe","result","adminRoute","path","relative","process","env","NEXT_BASE_PATH","basePath","undefined","originalTrailingSlash","NEXT_TRAILING_SLASH","apiRoute","endsWith"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getNextJsHMRURL.d.ts","sourceRoot":"","sources":["../../src/utilities/getNextJsHMRURL.ts"],"names":[],"mappings":"AAWA;;;GAGG;AACH,eAAO,MAAM,eAAe,QAAO,
|
|
1
|
+
{"version":3,"file":"getNextJsHMRURL.d.ts","sourceRoot":"","sources":["../../src/utilities/getNextJsHMRURL.ts"],"names":[],"mappings":"AAWA;;;GAGG;AACH,eAAO,MAAM,eAAe,QAAO,MAelC,CAAA"}
|
|
@@ -13,8 +13,10 @@ const firstModernHMRPathVersion = '16.3.0';
|
|
|
13
13
|
const port = process.env.PORT || '3000';
|
|
14
14
|
const hasHTTPS = process.env.USE_HTTPS === 'true' || process.argv.includes('--experimental-https');
|
|
15
15
|
const protocol = hasHTTPS ? 'wss' : 'ws';
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Next.js only inlines __NEXT_ASSET_PREFIX into bundled code. In dev, withPayload keeps `payload`
|
|
18
|
+
* external, so fall back to NEXT_BASE_PATH, which withPayload sets on process.env at runtime.
|
|
19
|
+
*/ const prefix = process.env.__NEXT_ASSET_PREFIX || process.env.NEXT_BASE_PATH || '';
|
|
18
20
|
return `${protocol}://localhost:${port}${prefix}${getHMRPath()}`;
|
|
19
21
|
};
|
|
20
22
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/getNextJsHMRURL.ts"],"sourcesContent":["import { compareVersions, parseVersion } from './dependencies/versionUtils.js'\nimport { getNextVersion } from './getNextVersion.js'\n\n/** Next.js serves the dev HMR WebSocket on this path from 16.3 onwards. */\nconst modernHMRPath = '/_next/hmr'\n\n/** Next.js served the dev HMR WebSocket on this path before 16.3. */\nconst legacyHMRPath = '/_next/webpack-hmr'\n\nconst firstModernHMRPathVersion = '16.3.0'\n\n/**\n * Builds the URL of the Next.js dev HMR WebSocket, on the path served by the\n * installed Next.js version. `PAYLOAD_HMR_URL_OVERRIDE` is used verbatim.\n */\nexport const getNextJsHMRURL = (): string => {\n if (process.env.PAYLOAD_HMR_URL_OVERRIDE) {\n return process.env.PAYLOAD_HMR_URL_OVERRIDE\n }\n\n const port = process.env.PORT || '3000'\n const hasHTTPS = process.env.USE_HTTPS === 'true' || process.argv.includes('--experimental-https')\n const protocol = hasHTTPS ? 'wss' : 'ws'\n
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/getNextJsHMRURL.ts"],"sourcesContent":["import { compareVersions, parseVersion } from './dependencies/versionUtils.js'\nimport { getNextVersion } from './getNextVersion.js'\n\n/** Next.js serves the dev HMR WebSocket on this path from 16.3 onwards. */\nconst modernHMRPath = '/_next/hmr'\n\n/** Next.js served the dev HMR WebSocket on this path before 16.3. */\nconst legacyHMRPath = '/_next/webpack-hmr'\n\nconst firstModernHMRPathVersion = '16.3.0'\n\n/**\n * Builds the URL of the Next.js dev HMR WebSocket, on the path served by the\n * installed Next.js version. `PAYLOAD_HMR_URL_OVERRIDE` is used verbatim.\n */\nexport const getNextJsHMRURL = (): string => {\n if (process.env.PAYLOAD_HMR_URL_OVERRIDE) {\n return process.env.PAYLOAD_HMR_URL_OVERRIDE\n }\n\n const port = process.env.PORT || '3000'\n const hasHTTPS = process.env.USE_HTTPS === 'true' || process.argv.includes('--experimental-https')\n const protocol = hasHTTPS ? 'wss' : 'ws'\n /**\n * Next.js only inlines __NEXT_ASSET_PREFIX into bundled code. In dev, withPayload keeps `payload`\n * external, so fall back to NEXT_BASE_PATH, which withPayload sets on process.env at runtime.\n */\n const prefix = process.env.__NEXT_ASSET_PREFIX || process.env.NEXT_BASE_PATH || ''\n\n return `${protocol}://localhost:${port}${prefix}${getHMRPath()}`\n}\n\n/**\n * Pre-release identifiers are ignored, so that a `16.3.0-canary` build maps to the 16.3 path.\n * An unreadable version uses the current path, as Payload being unable to resolve Next.js\n * normally means it is not running under Next.js, where this strategy does not apply.\n */\nconst getHMRPath = (): string => {\n const nextVersion = getNextVersion()\n\n if (!nextVersion) {\n return modernHMRPath\n }\n\n const mainVersion = parseVersion(nextVersion).parts.join('.')\n\n return compareVersions(mainVersion, firstModernHMRPathVersion) === 'lower'\n ? legacyHMRPath\n : modernHMRPath\n}\n"],"names":["compareVersions","parseVersion","getNextVersion","modernHMRPath","legacyHMRPath","firstModernHMRPathVersion","getNextJsHMRURL","process","env","PAYLOAD_HMR_URL_OVERRIDE","port","PORT","hasHTTPS","USE_HTTPS","argv","includes","protocol","prefix","__NEXT_ASSET_PREFIX","NEXT_BASE_PATH","getHMRPath","nextVersion","mainVersion","parts","join"],"mappings":"AAAA,SAASA,eAAe,EAAEC,YAAY,QAAQ,iCAAgC;AAC9E,SAASC,cAAc,QAAQ,sBAAqB;AAEpD,yEAAyE,GACzE,MAAMC,gBAAgB;AAEtB,mEAAmE,GACnE,MAAMC,gBAAgB;AAEtB,MAAMC,4BAA4B;AAElC;;;CAGC,GACD,OAAO,MAAMC,kBAAkB;IAC7B,IAAIC,QAAQC,GAAG,CAACC,wBAAwB,EAAE;QACxC,OAAOF,QAAQC,GAAG,CAACC,wBAAwB;IAC7C;IAEA,MAAMC,OAAOH,QAAQC,GAAG,CAACG,IAAI,IAAI;IACjC,MAAMC,WAAWL,QAAQC,GAAG,CAACK,SAAS,KAAK,UAAUN,QAAQO,IAAI,CAACC,QAAQ,CAAC;IAC3E,MAAMC,WAAWJ,WAAW,QAAQ;IACpC;;;GAGC,GACD,MAAMK,SAASV,QAAQC,GAAG,CAACU,mBAAmB,IAAIX,QAAQC,GAAG,CAACW,cAAc,IAAI;IAEhF,OAAO,GAAGH,SAAS,aAAa,EAAEN,OAAOO,SAASG,cAAc;AAClE,EAAC;AAED;;;;CAIC,GACD,MAAMA,aAAa;IACjB,MAAMC,cAAcnB;IAEpB,IAAI,CAACmB,aAAa;QAChB,OAAOlB;IACT;IAEA,MAAMmB,cAAcrB,aAAaoB,aAAaE,KAAK,CAACC,IAAI,CAAC;IAEzD,OAAOxB,gBAAgBsB,aAAajB,+BAA+B,UAC/DD,gBACAD;AACN"}
|
|
@@ -11,6 +11,8 @@ describe('getNextJsHMRURL', ()=>{
|
|
|
11
11
|
vi.mocked(getNextVersion).mockReturnValue('16.3.0');
|
|
12
12
|
vi.stubEnv('PAYLOAD_HMR_URL_OVERRIDE', undefined);
|
|
13
13
|
vi.stubEnv('PORT', '3000');
|
|
14
|
+
vi.stubEnv('__NEXT_ASSET_PREFIX', undefined);
|
|
15
|
+
vi.stubEnv('NEXT_BASE_PATH', undefined);
|
|
14
16
|
});
|
|
15
17
|
afterEach(()=>{
|
|
16
18
|
vi.unstubAllEnvs();
|
|
@@ -55,6 +57,15 @@ describe('getNextJsHMRURL', ()=>{
|
|
|
55
57
|
vi.stubEnv('__NEXT_ASSET_PREFIX', '/base');
|
|
56
58
|
expect(getNextJsHMRURL()).toBe('ws://localhost:3000/base/_next/hmr');
|
|
57
59
|
});
|
|
60
|
+
it('should prefix the HMR path with the basePath when no assetPrefix is available', ()=>{
|
|
61
|
+
vi.stubEnv('NEXT_BASE_PATH', '/cms');
|
|
62
|
+
expect(getNextJsHMRURL()).toBe('ws://localhost:3000/cms/_next/hmr');
|
|
63
|
+
});
|
|
64
|
+
it('should prefer the assetPrefix over the basePath', ()=>{
|
|
65
|
+
vi.stubEnv('__NEXT_ASSET_PREFIX', '/assets');
|
|
66
|
+
vi.stubEnv('NEXT_BASE_PATH', '/cms');
|
|
67
|
+
expect(getNextJsHMRURL()).toBe('ws://localhost:3000/assets/_next/hmr');
|
|
68
|
+
});
|
|
58
69
|
});
|
|
59
70
|
|
|
60
71
|
//# sourceMappingURL=getNextJsHMRURL.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/getNextJsHMRURL.spec.ts"],"sourcesContent":["import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nvi.mock('./getNextVersion.js', () => ({ getNextVersion: vi.fn() }))\n\nconst { getNextVersion } = await import('./getNextVersion.js')\nconst { getNextJsHMRURL } = await import('./getNextJsHMRURL.js')\n\nconst modernURL = 'ws://localhost:3000/_next/hmr'\nconst legacyURL = 'ws://localhost:3000/_next/webpack-hmr'\n\ndescribe('getNextJsHMRURL', () => {\n beforeEach(() => {\n vi.mocked(getNextVersion).mockReturnValue('16.3.0')\n vi.stubEnv('PAYLOAD_HMR_URL_OVERRIDE', undefined)\n vi.stubEnv('PORT', '3000')\n })\n\n afterEach(() => {\n vi.unstubAllEnvs()\n })\n\n it('should use the current HMR path on Next.js 16.3', () => {\n expect(getNextJsHMRURL()).toBe(modernURL)\n })\n\n it('should use the current HMR path on Next.js versions above 16.3', () => {\n vi.mocked(getNextVersion).mockReturnValue('17.0.1')\n\n expect(getNextJsHMRURL()).toBe(modernURL)\n })\n\n it('should use the legacy HMR path on Next.js below 16.3', () => {\n vi.mocked(getNextVersion).mockReturnValue('16.2.7')\n\n expect(getNextJsHMRURL()).toBe(legacyURL)\n })\n\n it('should use the legacy HMR path on a Next.js 15 install', () => {\n vi.mocked(getNextVersion).mockReturnValue('15.5.0')\n\n expect(getNextJsHMRURL()).toBe(legacyURL)\n })\n\n it('should ignore pre-release identifiers when choosing the path', () => {\n vi.mocked(getNextVersion).mockReturnValue('16.3.0-canary.12')\n\n expect(getNextJsHMRURL()).toBe(modernURL)\n })\n\n it('should use the legacy HMR path on a pre-release below 16.3', () => {\n vi.mocked(getNextVersion).mockReturnValue('16.2.0-canary.5')\n\n expect(getNextJsHMRURL()).toBe(legacyURL)\n })\n\n it('should use the current HMR path when the Next.js version is unknown', () => {\n vi.mocked(getNextVersion).mockReturnValue(undefined)\n\n expect(getNextJsHMRURL()).toBe(modernURL)\n })\n\n it('should use PAYLOAD_HMR_URL_OVERRIDE whatever the version', () => {\n vi.mocked(getNextVersion).mockReturnValue(undefined)\n vi.stubEnv('PAYLOAD_HMR_URL_OVERRIDE', 'ws://localhost:4000/custom-hmr')\n\n expect(getNextJsHMRURL()).toBe('ws://localhost:4000/custom-hmr')\n })\n\n it('should use the wss protocol when HTTPS is enabled', () => {\n vi.stubEnv('USE_HTTPS', 'true')\n\n expect(getNextJsHMRURL()).toBe('wss://localhost:3000/_next/hmr')\n })\n\n it('should include the Next.js asset prefix', () => {\n vi.stubEnv('__NEXT_ASSET_PREFIX', '/base')\n\n expect(getNextJsHMRURL()).toBe('ws://localhost:3000/base/_next/hmr')\n })\n})\n"],"names":["afterEach","beforeEach","describe","expect","it","vi","mock","getNextVersion","fn","getNextJsHMRURL","modernURL","legacyURL","mocked","mockReturnValue","stubEnv","undefined","unstubAllEnvs","toBe"],"mappings":"AAAA,SAASA,SAAS,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAQ;AAExEA,GAAGC,IAAI,CAAC,uBAAuB,IAAO,CAAA;QAAEC,gBAAgBF,GAAGG,EAAE;IAAG,CAAA;AAEhE,MAAM,EAAED,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC;AACxC,MAAM,EAAEE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC;AAEzC,MAAMC,YAAY;AAClB,MAAMC,YAAY;AAElBT,SAAS,mBAAmB;IAC1BD,WAAW;QACTI,GAAGO,MAAM,CAACL,gBAAgBM,eAAe,CAAC;QAC1CR,GAAGS,OAAO,CAAC,4BAA4BC;QACvCV,GAAGS,OAAO,CAAC,QAAQ;
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/getNextJsHMRURL.spec.ts"],"sourcesContent":["import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nvi.mock('./getNextVersion.js', () => ({ getNextVersion: vi.fn() }))\n\nconst { getNextVersion } = await import('./getNextVersion.js')\nconst { getNextJsHMRURL } = await import('./getNextJsHMRURL.js')\n\nconst modernURL = 'ws://localhost:3000/_next/hmr'\nconst legacyURL = 'ws://localhost:3000/_next/webpack-hmr'\n\ndescribe('getNextJsHMRURL', () => {\n beforeEach(() => {\n vi.mocked(getNextVersion).mockReturnValue('16.3.0')\n vi.stubEnv('PAYLOAD_HMR_URL_OVERRIDE', undefined)\n vi.stubEnv('PORT', '3000')\n vi.stubEnv('__NEXT_ASSET_PREFIX', undefined)\n vi.stubEnv('NEXT_BASE_PATH', undefined)\n })\n\n afterEach(() => {\n vi.unstubAllEnvs()\n })\n\n it('should use the current HMR path on Next.js 16.3', () => {\n expect(getNextJsHMRURL()).toBe(modernURL)\n })\n\n it('should use the current HMR path on Next.js versions above 16.3', () => {\n vi.mocked(getNextVersion).mockReturnValue('17.0.1')\n\n expect(getNextJsHMRURL()).toBe(modernURL)\n })\n\n it('should use the legacy HMR path on Next.js below 16.3', () => {\n vi.mocked(getNextVersion).mockReturnValue('16.2.7')\n\n expect(getNextJsHMRURL()).toBe(legacyURL)\n })\n\n it('should use the legacy HMR path on a Next.js 15 install', () => {\n vi.mocked(getNextVersion).mockReturnValue('15.5.0')\n\n expect(getNextJsHMRURL()).toBe(legacyURL)\n })\n\n it('should ignore pre-release identifiers when choosing the path', () => {\n vi.mocked(getNextVersion).mockReturnValue('16.3.0-canary.12')\n\n expect(getNextJsHMRURL()).toBe(modernURL)\n })\n\n it('should use the legacy HMR path on a pre-release below 16.3', () => {\n vi.mocked(getNextVersion).mockReturnValue('16.2.0-canary.5')\n\n expect(getNextJsHMRURL()).toBe(legacyURL)\n })\n\n it('should use the current HMR path when the Next.js version is unknown', () => {\n vi.mocked(getNextVersion).mockReturnValue(undefined)\n\n expect(getNextJsHMRURL()).toBe(modernURL)\n })\n\n it('should use PAYLOAD_HMR_URL_OVERRIDE whatever the version', () => {\n vi.mocked(getNextVersion).mockReturnValue(undefined)\n vi.stubEnv('PAYLOAD_HMR_URL_OVERRIDE', 'ws://localhost:4000/custom-hmr')\n\n expect(getNextJsHMRURL()).toBe('ws://localhost:4000/custom-hmr')\n })\n\n it('should use the wss protocol when HTTPS is enabled', () => {\n vi.stubEnv('USE_HTTPS', 'true')\n\n expect(getNextJsHMRURL()).toBe('wss://localhost:3000/_next/hmr')\n })\n\n it('should include the Next.js asset prefix', () => {\n vi.stubEnv('__NEXT_ASSET_PREFIX', '/base')\n\n expect(getNextJsHMRURL()).toBe('ws://localhost:3000/base/_next/hmr')\n })\n\n it('should prefix the HMR path with the basePath when no assetPrefix is available', () => {\n vi.stubEnv('NEXT_BASE_PATH', '/cms')\n\n expect(getNextJsHMRURL()).toBe('ws://localhost:3000/cms/_next/hmr')\n })\n\n it('should prefer the assetPrefix over the basePath', () => {\n vi.stubEnv('__NEXT_ASSET_PREFIX', '/assets')\n vi.stubEnv('NEXT_BASE_PATH', '/cms')\n\n expect(getNextJsHMRURL()).toBe('ws://localhost:3000/assets/_next/hmr')\n })\n})\n"],"names":["afterEach","beforeEach","describe","expect","it","vi","mock","getNextVersion","fn","getNextJsHMRURL","modernURL","legacyURL","mocked","mockReturnValue","stubEnv","undefined","unstubAllEnvs","toBe"],"mappings":"AAAA,SAASA,SAAS,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAQ;AAExEA,GAAGC,IAAI,CAAC,uBAAuB,IAAO,CAAA;QAAEC,gBAAgBF,GAAGG,EAAE;IAAG,CAAA;AAEhE,MAAM,EAAED,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC;AACxC,MAAM,EAAEE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC;AAEzC,MAAMC,YAAY;AAClB,MAAMC,YAAY;AAElBT,SAAS,mBAAmB;IAC1BD,WAAW;QACTI,GAAGO,MAAM,CAACL,gBAAgBM,eAAe,CAAC;QAC1CR,GAAGS,OAAO,CAAC,4BAA4BC;QACvCV,GAAGS,OAAO,CAAC,QAAQ;QACnBT,GAAGS,OAAO,CAAC,uBAAuBC;QAClCV,GAAGS,OAAO,CAAC,kBAAkBC;IAC/B;IAEAf,UAAU;QACRK,GAAGW,aAAa;IAClB;IAEAZ,GAAG,mDAAmD;QACpDD,OAAOM,mBAAmBQ,IAAI,CAACP;IACjC;IAEAN,GAAG,kEAAkE;QACnEC,GAAGO,MAAM,CAACL,gBAAgBM,eAAe,CAAC;QAE1CV,OAAOM,mBAAmBQ,IAAI,CAACP;IACjC;IAEAN,GAAG,wDAAwD;QACzDC,GAAGO,MAAM,CAACL,gBAAgBM,eAAe,CAAC;QAE1CV,OAAOM,mBAAmBQ,IAAI,CAACN;IACjC;IAEAP,GAAG,0DAA0D;QAC3DC,GAAGO,MAAM,CAACL,gBAAgBM,eAAe,CAAC;QAE1CV,OAAOM,mBAAmBQ,IAAI,CAACN;IACjC;IAEAP,GAAG,gEAAgE;QACjEC,GAAGO,MAAM,CAACL,gBAAgBM,eAAe,CAAC;QAE1CV,OAAOM,mBAAmBQ,IAAI,CAACP;IACjC;IAEAN,GAAG,8DAA8D;QAC/DC,GAAGO,MAAM,CAACL,gBAAgBM,eAAe,CAAC;QAE1CV,OAAOM,mBAAmBQ,IAAI,CAACN;IACjC;IAEAP,GAAG,uEAAuE;QACxEC,GAAGO,MAAM,CAACL,gBAAgBM,eAAe,CAACE;QAE1CZ,OAAOM,mBAAmBQ,IAAI,CAACP;IACjC;IAEAN,GAAG,4DAA4D;QAC7DC,GAAGO,MAAM,CAACL,gBAAgBM,eAAe,CAACE;QAC1CV,GAAGS,OAAO,CAAC,4BAA4B;QAEvCX,OAAOM,mBAAmBQ,IAAI,CAAC;IACjC;IAEAb,GAAG,qDAAqD;QACtDC,GAAGS,OAAO,CAAC,aAAa;QAExBX,OAAOM,mBAAmBQ,IAAI,CAAC;IACjC;IAEAb,GAAG,2CAA2C;QAC5CC,GAAGS,OAAO,CAAC,uBAAuB;QAElCX,OAAOM,mBAAmBQ,IAAI,CAAC;IACjC;IAEAb,GAAG,iFAAiF;QAClFC,GAAGS,OAAO,CAAC,kBAAkB;QAE7BX,OAAOM,mBAAmBQ,IAAI,CAAC;IACjC;IAEAb,GAAG,mDAAmD;QACpDC,GAAGS,OAAO,CAAC,uBAAuB;QAClCT,GAAGS,OAAO,CAAC,kBAAkB;QAE7BX,OAAOM,mBAAmBQ,IAAI,CAAC;IACjC;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handleEndpoints.d.ts","sourceRoot":"","sources":["../../src/utilities/handleEndpoints.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAA4B,eAAe,EAAE,MAAM,oBAAoB,CAAA;AA0BnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,eAAe,kFAMzB;IACD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAAA;IAClD,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,OAAO,EAAE,OAAO,CAAA;CACjB,KAAG,OAAO,CAAC,QAAQ,
|
|
1
|
+
{"version":3,"file":"handleEndpoints.d.ts","sourceRoot":"","sources":["../../src/utilities/handleEndpoints.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAA4B,eAAe,EAAE,MAAM,oBAAoB,CAAA;AA0BnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,eAAe,kFAMzB;IACD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAAA;IAClD,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,OAAO,EAAE,OAAO,CAAA;CACjB,KAAG,OAAO,CAAC,QAAQ,CAkNnB,CAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { status as httpStatus } from 'http-status';
|
|
2
2
|
import { match } from 'path-to-regexp';
|
|
3
3
|
import { createPayloadRequest } from './createPayloadRequest.js';
|
|
4
|
-
import { formatAdminURL } from './formatAdminURL.js';
|
|
4
|
+
import { formatAdminURL, stripTrailingSlash } from './formatAdminURL.js';
|
|
5
5
|
import { headersWithCors } from './headersWithCors.js';
|
|
6
6
|
import { mergeHeaders } from './mergeHeaders.js';
|
|
7
7
|
import { routeError } from './routeError.js';
|
|
@@ -103,11 +103,13 @@ const notFoundResponse = (req, pathname)=>{
|
|
|
103
103
|
});
|
|
104
104
|
const { payload } = req;
|
|
105
105
|
const { config } = payload;
|
|
106
|
-
const
|
|
107
|
-
const
|
|
106
|
+
const rawPathname = path ?? new URL(req.url).pathname;
|
|
107
|
+
const pathname = stripTrailingSlash(rawPathname);
|
|
108
|
+
const rawBaseAPIPath = formatAdminURL({
|
|
108
109
|
apiRoute: config.routes.api,
|
|
109
110
|
path: ''
|
|
110
111
|
});
|
|
112
|
+
const baseAPIPath = stripTrailingSlash(rawBaseAPIPath);
|
|
111
113
|
if (!pathname.startsWith(baseAPIPath)) {
|
|
112
114
|
return notFoundResponse(req, pathname);
|
|
113
115
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/handleEndpoints.ts"],"sourcesContent":["import { status as httpStatus } from 'http-status'\nimport { match } from 'path-to-regexp'\n\nimport type { Collection } from '../collections/config/types.js'\nimport type { Endpoint, PayloadHandler, SanitizedConfig } from '../config/types.js'\nimport type { APIError } from '../errors/APIError.js'\nimport type { GlobalConfig } from '../globals/config/types.js'\nimport type { PayloadRequest } from '../types/index.js'\n\nimport { createPayloadRequest } from './createPayloadRequest.js'\nimport { formatAdminURL } from './formatAdminURL.js'\nimport { headersWithCors } from './headersWithCors.js'\nimport { mergeHeaders } from './mergeHeaders.js'\nimport { routeError } from './routeError.js'\n\nconst notFoundResponse = (req: PayloadRequest, pathname?: string) => {\n return Response.json(\n {\n message: `Route not found \"${pathname ?? new URL(req.url!).pathname}\"`,\n },\n {\n headers: headersWithCors({\n headers: new Headers(),\n req,\n }),\n status: httpStatus.NOT_FOUND,\n },\n )\n}\n\n/**\n * Attaches the Payload REST API to any backend framework that uses Fetch Request/Response\n * like Next.js (app router), Remix, Bun, Hono.\n *\n * ### Example: Using Hono\n * ```ts\n * import { handleEndpoints } from 'payload';\n * import { serve } from '@hono/node-server';\n * import { loadEnv } from 'payload/node';\n *\n * const port = 3001;\n * loadEnv();\n *\n * const { default: config } = await import('@payload-config');\n *\n * const server = serve({\n * fetch: async (request) => {\n * const response = await handleEndpoints({\n * config,\n * request: request.clone(),\n * });\n *\n * return response;\n * },\n * port,\n * });\n *\n * server.on('listening', () => {\n * console.log(`API server is listening on http://localhost:${port}/api`);\n * });\n * ```\n */\nexport const handleEndpoints = async ({\n basePath = '',\n config: incomingConfig,\n path,\n payloadInstanceCacheKey,\n request,\n}: {\n basePath?: string\n config: Promise<SanitizedConfig> | SanitizedConfig\n /** Override path from the request */\n path?: string\n payloadInstanceCacheKey?: string\n request: Request\n}): Promise<Response> => {\n let handler!: PayloadHandler\n let req: PayloadRequest\n let collection!: Collection\n\n // This can be used against GET request search params size limit.\n // Instead you can do POST request with a text body as search params.\n // We use this internally for relationships querying on the frontend\n // packages/ui/src/fields/Relationship/index.tsx\n if (\n request.method.toLowerCase() === 'post' &&\n (request.headers.get('X-Payload-HTTP-Method-Override') === 'GET' ||\n request.headers.get('X-HTTP-Method-Override') === 'GET')\n ) {\n let url = request.url\n let data: any = undefined\n\n if (request.headers.get('Content-Type') === 'application/x-www-form-urlencoded') {\n const search = await request.text()\n url = `${request.url}?${search}`\n } else if (request.headers.get('Content-Type') === 'application/json') {\n // May not be supported by every endpoint\n data = await request.json()\n\n // locale and fallbackLocale is read by createPayloadRequest to populate req.locale and req.fallbackLocale\n // => add to searchParams\n if (data?.locale) {\n url += `?locale=${data.locale}`\n }\n if (data?.fallbackLocale) {\n url += `&fallbackLocale=${data.depth}`\n }\n }\n\n const req = new Request(url, {\n // @ts-expect-error RequestInit does not include cache in the type\n cache: request.cache,\n credentials: request.credentials,\n headers: request.headers,\n method: 'GET',\n signal: request.signal,\n })\n\n if (data) {\n // @ts-expect-error attach data to request - less overhead than using urlencoded\n req.data = data\n }\n\n const response = await handleEndpoints({\n basePath,\n config: incomingConfig,\n path,\n payloadInstanceCacheKey,\n request: req,\n })\n\n return response\n }\n\n try {\n req = await createPayloadRequest({\n canSetHeaders: true,\n config: incomingConfig,\n payloadInstanceCacheKey,\n request,\n })\n\n const { payload } = req\n const { config } = payload\n\n const pathname = path ?? new URL(req.url!).pathname\n const baseAPIPath = formatAdminURL({\n apiRoute: config.routes.api,\n path: '',\n })\n\n if (!pathname.startsWith(baseAPIPath)) {\n return notFoundResponse(req, pathname)\n }\n\n // /api/posts/route -> /posts/route\n let adjustedPathname = pathname.replace(baseAPIPath, '')\n\n let isGlobals = false\n\n // /globals/header/route -> /header/route\n if (adjustedPathname.startsWith('/globals')) {\n isGlobals = true\n adjustedPathname = adjustedPathname.replace('/globals', '')\n }\n\n const segments = adjustedPathname.split('/')\n // remove empty string first element\n segments.shift()\n\n const firstParam = segments[0]\n\n let globalConfig!: GlobalConfig\n\n // first param can be a global slug or collection slug, find the relevant config\n if (firstParam) {\n if (isGlobals) {\n globalConfig = payload.globals.config.find((each) => each.slug === firstParam)!\n } else if (payload.collections[firstParam]) {\n collection = payload.collections[firstParam]\n }\n }\n\n let endpoints: Endpoint[] | false = config.endpoints\n\n if (collection) {\n endpoints = collection.config.endpoints\n // /posts/route -> /route\n adjustedPathname = adjustedPathname.replace(`/${collection.config.slug}`, '')\n } else if (globalConfig) {\n // /header/route -> /route\n adjustedPathname = adjustedPathname.replace(`/${globalConfig.slug}`, '')\n endpoints = globalConfig.endpoints!\n }\n\n // sanitize when endpoint.path is '/'\n if (adjustedPathname === '') {\n adjustedPathname = '/'\n }\n\n if (endpoints === false) {\n return Response.json(\n {\n message: `Cannot ${req.method?.toUpperCase()} ${req.url}`,\n },\n {\n headers: headersWithCors({\n headers: new Headers(),\n req,\n }),\n status: httpStatus.NOT_IMPLEMENTED,\n },\n )\n }\n\n // Find the relevant endpoint configuration\n const endpoint = endpoints?.find((endpoint) => {\n if (endpoint.method !== req.method?.toLowerCase()) {\n return false\n }\n\n const pathMatchFn = match(endpoint.path, { decode: decodeURIComponent })\n\n const matchResult = pathMatchFn(adjustedPathname)\n\n if (!matchResult) {\n return false\n }\n\n req.routeParams = matchResult.params as Record<string, unknown>\n\n // Inject to routeParams the slug as well so it can be used later\n if (collection) {\n req.routeParams.collection = collection.config.slug\n } else if (globalConfig) {\n req.routeParams.global = globalConfig.slug\n }\n\n return true\n })\n\n if (endpoint) {\n handler = endpoint.handler\n }\n\n if (!handler) {\n // If no custom handler found and this is an OPTIONS request,\n // return default CORS response for preflight requests\n if (req.method?.toLowerCase() === 'options') {\n return Response.json(\n {},\n {\n headers: headersWithCors({\n headers: new Headers(),\n req,\n }),\n status: 200,\n },\n )\n }\n\n return notFoundResponse(req, pathname)\n }\n\n const response = await handler(req)\n\n return new Response(response.body, {\n headers: headersWithCors({\n headers: mergeHeaders(req.responseHeaders ?? new Headers(), response.headers),\n req,\n }),\n status: response.status,\n statusText: response.statusText,\n })\n } catch (_err) {\n const err = _err as APIError\n return routeError({\n collection,\n config: incomingConfig,\n err,\n req: req!,\n })\n }\n}\n"],"names":["status","httpStatus","match","createPayloadRequest","formatAdminURL","headersWithCors","mergeHeaders","routeError","notFoundResponse","req","pathname","Response","json","message","URL","url","headers","Headers","NOT_FOUND","handleEndpoints","basePath","config","incomingConfig","path","payloadInstanceCacheKey","request","handler","collection","method","toLowerCase","get","data","undefined","search","text","locale","fallbackLocale","depth","Request","cache","credentials","signal","response","canSetHeaders","payload","baseAPIPath","apiRoute","routes","api","startsWith","adjustedPathname","replace","isGlobals","segments","split","shift","firstParam","globalConfig","globals","find","each","slug","collections","endpoints","toUpperCase","NOT_IMPLEMENTED","endpoint","pathMatchFn","decode","decodeURIComponent","matchResult","routeParams","params","global","body","responseHeaders","statusText","_err","err"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/handleEndpoints.ts"],"sourcesContent":["import { status as httpStatus } from 'http-status'\nimport { match } from 'path-to-regexp'\n\nimport type { Collection } from '../collections/config/types.js'\nimport type { Endpoint, PayloadHandler, SanitizedConfig } from '../config/types.js'\nimport type { APIError } from '../errors/APIError.js'\nimport type { GlobalConfig } from '../globals/config/types.js'\nimport type { PayloadRequest } from '../types/index.js'\n\nimport { createPayloadRequest } from './createPayloadRequest.js'\nimport { formatAdminURL, stripTrailingSlash } from './formatAdminURL.js'\nimport { headersWithCors } from './headersWithCors.js'\nimport { mergeHeaders } from './mergeHeaders.js'\nimport { routeError } from './routeError.js'\n\nconst notFoundResponse = (req: PayloadRequest, pathname?: string) => {\n return Response.json(\n {\n message: `Route not found \"${pathname ?? new URL(req.url!).pathname}\"`,\n },\n {\n headers: headersWithCors({\n headers: new Headers(),\n req,\n }),\n status: httpStatus.NOT_FOUND,\n },\n )\n}\n\n/**\n * Attaches the Payload REST API to any backend framework that uses Fetch Request/Response\n * like Next.js (app router), Remix, Bun, Hono.\n *\n * ### Example: Using Hono\n * ```ts\n * import { handleEndpoints } from 'payload';\n * import { serve } from '@hono/node-server';\n * import { loadEnv } from 'payload/node';\n *\n * const port = 3001;\n * loadEnv();\n *\n * const { default: config } = await import('@payload-config');\n *\n * const server = serve({\n * fetch: async (request) => {\n * const response = await handleEndpoints({\n * config,\n * request: request.clone(),\n * });\n *\n * return response;\n * },\n * port,\n * });\n *\n * server.on('listening', () => {\n * console.log(`API server is listening on http://localhost:${port}/api`);\n * });\n * ```\n */\nexport const handleEndpoints = async ({\n basePath = '',\n config: incomingConfig,\n path,\n payloadInstanceCacheKey,\n request,\n}: {\n basePath?: string\n config: Promise<SanitizedConfig> | SanitizedConfig\n /** Override path from the request */\n path?: string\n payloadInstanceCacheKey?: string\n request: Request\n}): Promise<Response> => {\n let handler!: PayloadHandler\n let req: PayloadRequest\n let collection!: Collection\n\n // This can be used against GET request search params size limit.\n // Instead you can do POST request with a text body as search params.\n // We use this internally for relationships querying on the frontend\n // packages/ui/src/fields/Relationship/index.tsx\n if (\n request.method.toLowerCase() === 'post' &&\n (request.headers.get('X-Payload-HTTP-Method-Override') === 'GET' ||\n request.headers.get('X-HTTP-Method-Override') === 'GET')\n ) {\n let url = request.url\n let data: any = undefined\n\n if (request.headers.get('Content-Type') === 'application/x-www-form-urlencoded') {\n const search = await request.text()\n url = `${request.url}?${search}`\n } else if (request.headers.get('Content-Type') === 'application/json') {\n // May not be supported by every endpoint\n data = await request.json()\n\n // locale and fallbackLocale is read by createPayloadRequest to populate req.locale and req.fallbackLocale\n // => add to searchParams\n if (data?.locale) {\n url += `?locale=${data.locale}`\n }\n if (data?.fallbackLocale) {\n url += `&fallbackLocale=${data.depth}`\n }\n }\n\n const req = new Request(url, {\n // @ts-expect-error RequestInit does not include cache in the type\n cache: request.cache,\n credentials: request.credentials,\n headers: request.headers,\n method: 'GET',\n signal: request.signal,\n })\n\n if (data) {\n // @ts-expect-error attach data to request - less overhead than using urlencoded\n req.data = data\n }\n\n const response = await handleEndpoints({\n basePath,\n config: incomingConfig,\n path,\n payloadInstanceCacheKey,\n request: req,\n })\n\n return response\n }\n\n try {\n req = await createPayloadRequest({\n canSetHeaders: true,\n config: incomingConfig,\n payloadInstanceCacheKey,\n request,\n })\n\n const { payload } = req\n const { config } = payload\n\n const rawPathname = path ?? new URL(req.url!).pathname\n const pathname = stripTrailingSlash(rawPathname)\n const rawBaseAPIPath = formatAdminURL({\n apiRoute: config.routes.api,\n path: '',\n })\n const baseAPIPath = stripTrailingSlash(rawBaseAPIPath)\n\n if (!pathname.startsWith(baseAPIPath)) {\n return notFoundResponse(req, pathname)\n }\n\n // /api/posts/route -> /posts/route\n let adjustedPathname = pathname.replace(baseAPIPath, '')\n\n let isGlobals = false\n\n // /globals/header/route -> /header/route\n if (adjustedPathname.startsWith('/globals')) {\n isGlobals = true\n adjustedPathname = adjustedPathname.replace('/globals', '')\n }\n\n const segments = adjustedPathname.split('/')\n // remove empty string first element\n segments.shift()\n\n const firstParam = segments[0]\n\n let globalConfig!: GlobalConfig\n\n // first param can be a global slug or collection slug, find the relevant config\n if (firstParam) {\n if (isGlobals) {\n globalConfig = payload.globals.config.find((each) => each.slug === firstParam)!\n } else if (payload.collections[firstParam]) {\n collection = payload.collections[firstParam]\n }\n }\n\n let endpoints: Endpoint[] | false = config.endpoints\n\n if (collection) {\n endpoints = collection.config.endpoints\n // /posts/route -> /route\n adjustedPathname = adjustedPathname.replace(`/${collection.config.slug}`, '')\n } else if (globalConfig) {\n // /header/route -> /route\n adjustedPathname = adjustedPathname.replace(`/${globalConfig.slug}`, '')\n endpoints = globalConfig.endpoints!\n }\n\n // sanitize when endpoint.path is '/'\n if (adjustedPathname === '') {\n adjustedPathname = '/'\n }\n\n if (endpoints === false) {\n return Response.json(\n {\n message: `Cannot ${req.method?.toUpperCase()} ${req.url}`,\n },\n {\n headers: headersWithCors({\n headers: new Headers(),\n req,\n }),\n status: httpStatus.NOT_IMPLEMENTED,\n },\n )\n }\n\n // Find the relevant endpoint configuration\n const endpoint = endpoints?.find((endpoint) => {\n if (endpoint.method !== req.method?.toLowerCase()) {\n return false\n }\n\n const pathMatchFn = match(endpoint.path, { decode: decodeURIComponent })\n\n const matchResult = pathMatchFn(adjustedPathname)\n\n if (!matchResult) {\n return false\n }\n\n req.routeParams = matchResult.params as Record<string, unknown>\n\n // Inject to routeParams the slug as well so it can be used later\n if (collection) {\n req.routeParams.collection = collection.config.slug\n } else if (globalConfig) {\n req.routeParams.global = globalConfig.slug\n }\n\n return true\n })\n\n if (endpoint) {\n handler = endpoint.handler\n }\n\n if (!handler) {\n // If no custom handler found and this is an OPTIONS request,\n // return default CORS response for preflight requests\n if (req.method?.toLowerCase() === 'options') {\n return Response.json(\n {},\n {\n headers: headersWithCors({\n headers: new Headers(),\n req,\n }),\n status: 200,\n },\n )\n }\n\n return notFoundResponse(req, pathname)\n }\n\n const response = await handler(req)\n\n return new Response(response.body, {\n headers: headersWithCors({\n headers: mergeHeaders(req.responseHeaders ?? new Headers(), response.headers),\n req,\n }),\n status: response.status,\n statusText: response.statusText,\n })\n } catch (_err) {\n const err = _err as APIError\n return routeError({\n collection,\n config: incomingConfig,\n err,\n req: req!,\n })\n }\n}\n"],"names":["status","httpStatus","match","createPayloadRequest","formatAdminURL","stripTrailingSlash","headersWithCors","mergeHeaders","routeError","notFoundResponse","req","pathname","Response","json","message","URL","url","headers","Headers","NOT_FOUND","handleEndpoints","basePath","config","incomingConfig","path","payloadInstanceCacheKey","request","handler","collection","method","toLowerCase","get","data","undefined","search","text","locale","fallbackLocale","depth","Request","cache","credentials","signal","response","canSetHeaders","payload","rawPathname","rawBaseAPIPath","apiRoute","routes","api","baseAPIPath","startsWith","adjustedPathname","replace","isGlobals","segments","split","shift","firstParam","globalConfig","globals","find","each","slug","collections","endpoints","toUpperCase","NOT_IMPLEMENTED","endpoint","pathMatchFn","decode","decodeURIComponent","matchResult","routeParams","params","global","body","responseHeaders","statusText","_err","err"],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** @type {'development' | 'production'} */
|
|
2
|
+
let environmentCondition
|
|
3
|
+
|
|
4
|
+
/** @param {'development' | 'production'} condition */
|
|
5
|
+
export function initialize(condition) {
|
|
6
|
+
environmentCondition = condition
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** @type {import('node:module').ResolveHook} */
|
|
10
|
+
export const resolve = (specifier, context, nextResolve) => {
|
|
11
|
+
if (
|
|
12
|
+
(specifier === 'lexical' ||
|
|
13
|
+
specifier.startsWith('lexical/') ||
|
|
14
|
+
specifier.startsWith('@lexical/')) &&
|
|
15
|
+
!context.conditions.includes('development') &&
|
|
16
|
+
!context.conditions.includes('production')
|
|
17
|
+
) {
|
|
18
|
+
// Preserve explicit conditions and leave every other package's resolution unchanged.
|
|
19
|
+
return nextResolve(specifier, {
|
|
20
|
+
...context,
|
|
21
|
+
conditions: [...context.conditions, environmentCondition],
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return nextResolve(specifier, context)
|
|
26
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payload",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.91.0-internal.07e4582",
|
|
4
4
|
"description": "Node, React, Headless CMS and Application Framework built on Next.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"admin panel",
|
|
@@ -82,7 +82,8 @@
|
|
|
82
82
|
},
|
|
83
83
|
"files": [
|
|
84
84
|
"dist",
|
|
85
|
-
"bin.js"
|
|
85
|
+
"bin.js",
|
|
86
|
+
"lexicalLoader.mjs"
|
|
86
87
|
],
|
|
87
88
|
"dependencies": {
|
|
88
89
|
"@next/env": "^15.1.5",
|
|
@@ -112,11 +113,11 @@
|
|
|
112
113
|
"sanitize-filename": "1.6.3",
|
|
113
114
|
"sax": "1.6.1",
|
|
114
115
|
"ts-essentials": "10.0.3",
|
|
115
|
-
"tsx": "4.
|
|
116
|
+
"tsx": "4.23.15",
|
|
116
117
|
"undici": "7.29.0",
|
|
117
118
|
"uuid": "13.0.2",
|
|
118
119
|
"ws": "^8.16.0",
|
|
119
|
-
"@payloadcms/translations": "3.
|
|
120
|
+
"@payloadcms/translations": "3.91.0-internal.07e4582"
|
|
120
121
|
},
|
|
121
122
|
"devDependencies": {
|
|
122
123
|
"@hyrious/esbuild-plugin-commonjs": "0.2.6",
|