payload 3.91.0-internal.c1569dc → 3.92.0

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 (146) hide show
  1. package/bin.js +3 -14
  2. package/dist/bin/index.d.ts.map +1 -1
  3. package/dist/bin/index.js +15 -0
  4. package/dist/bin/index.js.map +1 -1
  5. package/dist/bin/index.spec.js +54 -0
  6. package/dist/bin/index.spec.js.map +1 -0
  7. package/dist/collections/operations/findVersionByID.d.ts.map +1 -1
  8. package/dist/collections/operations/findVersionByID.js +7 -0
  9. package/dist/collections/operations/findVersionByID.js.map +1 -1
  10. package/dist/collections/operations/findVersions.d.ts.map +1 -1
  11. package/dist/collections/operations/findVersions.js +5 -0
  12. package/dist/collections/operations/findVersions.js.map +1 -1
  13. package/dist/database/createSchemaBuildContext.d.ts +12 -0
  14. package/dist/database/createSchemaBuildContext.d.ts.map +1 -0
  15. package/dist/database/createSchemaBuildContext.js +24 -0
  16. package/dist/database/createSchemaBuildContext.js.map +1 -0
  17. package/dist/database/createSchemaBuildContext.spec.js +146 -0
  18. package/dist/database/createSchemaBuildContext.spec.js.map +1 -0
  19. package/dist/database/sanitizeJoinQuery.d.ts.map +1 -1
  20. package/dist/database/sanitizeJoinQuery.js +2 -1
  21. package/dist/database/sanitizeJoinQuery.js.map +1 -1
  22. package/dist/errors/APIError.d.ts +4 -0
  23. package/dist/errors/APIError.d.ts.map +1 -1
  24. package/dist/errors/APIError.js +5 -1
  25. package/dist/errors/APIError.js.map +1 -1
  26. package/dist/errors/AuthenticationError.d.ts.map +1 -1
  27. package/dist/errors/AuthenticationError.js +1 -0
  28. package/dist/errors/AuthenticationError.js.map +1 -1
  29. package/dist/errors/DuplicateCollection.d.ts.map +1 -1
  30. package/dist/errors/DuplicateCollection.js +1 -0
  31. package/dist/errors/DuplicateCollection.js.map +1 -1
  32. package/dist/errors/DuplicateFieldName.d.ts.map +1 -1
  33. package/dist/errors/DuplicateFieldName.js +1 -0
  34. package/dist/errors/DuplicateFieldName.js.map +1 -1
  35. package/dist/errors/DuplicateGlobal.d.ts.map +1 -1
  36. package/dist/errors/DuplicateGlobal.js +1 -0
  37. package/dist/errors/DuplicateGlobal.js.map +1 -1
  38. package/dist/errors/ErrorDeletingFile.d.ts.map +1 -1
  39. package/dist/errors/ErrorDeletingFile.js +1 -0
  40. package/dist/errors/ErrorDeletingFile.js.map +1 -1
  41. package/dist/errors/FileRetrievalError.d.ts.map +1 -1
  42. package/dist/errors/FileRetrievalError.js +1 -0
  43. package/dist/errors/FileRetrievalError.js.map +1 -1
  44. package/dist/errors/FileUploadError.d.ts.map +1 -1
  45. package/dist/errors/FileUploadError.js +1 -0
  46. package/dist/errors/FileUploadError.js.map +1 -1
  47. package/dist/errors/Forbidden.d.ts.map +1 -1
  48. package/dist/errors/Forbidden.js +1 -0
  49. package/dist/errors/Forbidden.js.map +1 -1
  50. package/dist/errors/InvalidConfiguration.d.ts.map +1 -1
  51. package/dist/errors/InvalidConfiguration.js +1 -0
  52. package/dist/errors/InvalidConfiguration.js.map +1 -1
  53. package/dist/errors/InvalidFieldJoin.d.ts.map +1 -1
  54. package/dist/errors/InvalidFieldJoin.js +1 -0
  55. package/dist/errors/InvalidFieldJoin.js.map +1 -1
  56. package/dist/errors/InvalidFieldName.d.ts.map +1 -1
  57. package/dist/errors/InvalidFieldName.js +1 -0
  58. package/dist/errors/InvalidFieldName.js.map +1 -1
  59. package/dist/errors/InvalidFieldRelationship.d.ts.map +1 -1
  60. package/dist/errors/InvalidFieldRelationship.js +1 -0
  61. package/dist/errors/InvalidFieldRelationship.js.map +1 -1
  62. package/dist/errors/InvalidSchema.d.ts.map +1 -1
  63. package/dist/errors/InvalidSchema.js +1 -0
  64. package/dist/errors/InvalidSchema.js.map +1 -1
  65. package/dist/errors/Locked.d.ts.map +1 -1
  66. package/dist/errors/Locked.js +1 -0
  67. package/dist/errors/Locked.js.map +1 -1
  68. package/dist/errors/LockedAuth.d.ts.map +1 -1
  69. package/dist/errors/LockedAuth.js +1 -0
  70. package/dist/errors/LockedAuth.js.map +1 -1
  71. package/dist/errors/MissingCollectionLabel.d.ts.map +1 -1
  72. package/dist/errors/MissingCollectionLabel.js +1 -0
  73. package/dist/errors/MissingCollectionLabel.js.map +1 -1
  74. package/dist/errors/MissingEditorProp.d.ts.map +1 -1
  75. package/dist/errors/MissingEditorProp.js +1 -0
  76. package/dist/errors/MissingEditorProp.js.map +1 -1
  77. package/dist/errors/MissingFieldInputOptions.d.ts.map +1 -1
  78. package/dist/errors/MissingFieldInputOptions.js +1 -0
  79. package/dist/errors/MissingFieldInputOptions.js.map +1 -1
  80. package/dist/errors/MissingFieldType.d.ts.map +1 -1
  81. package/dist/errors/MissingFieldType.js +1 -0
  82. package/dist/errors/MissingFieldType.js.map +1 -1
  83. package/dist/errors/MissingFile.d.ts.map +1 -1
  84. package/dist/errors/MissingFile.js +1 -0
  85. package/dist/errors/MissingFile.js.map +1 -1
  86. package/dist/errors/NotFound.d.ts.map +1 -1
  87. package/dist/errors/NotFound.js +1 -0
  88. package/dist/errors/NotFound.js.map +1 -1
  89. package/dist/errors/QueryError.d.ts.map +1 -1
  90. package/dist/errors/QueryError.js +1 -0
  91. package/dist/errors/QueryError.js.map +1 -1
  92. package/dist/errors/ReservedFieldName.d.ts.map +1 -1
  93. package/dist/errors/ReservedFieldName.js +1 -0
  94. package/dist/errors/ReservedFieldName.js.map +1 -1
  95. package/dist/errors/TimestampsRequired.d.ts.map +1 -1
  96. package/dist/errors/TimestampsRequired.js +1 -0
  97. package/dist/errors/TimestampsRequired.js.map +1 -1
  98. package/dist/errors/UnauthorizedError.d.ts.map +1 -1
  99. package/dist/errors/UnauthorizedError.js +1 -0
  100. package/dist/errors/UnauthorizedError.js.map +1 -1
  101. package/dist/errors/UnverifiedEmail.d.ts.map +1 -1
  102. package/dist/errors/UnverifiedEmail.js +1 -0
  103. package/dist/errors/UnverifiedEmail.js.map +1 -1
  104. package/dist/errors/ValidationError.d.ts.map +1 -1
  105. package/dist/errors/ValidationError.js +1 -0
  106. package/dist/errors/ValidationError.js.map +1 -1
  107. package/dist/exports/internal.d.ts +2 -0
  108. package/dist/exports/internal.d.ts.map +1 -1
  109. package/dist/exports/internal.js +1 -0
  110. package/dist/exports/internal.js.map +1 -1
  111. package/dist/fields/hooks/beforeChange/flattenValidationData.d.ts +14 -0
  112. package/dist/fields/hooks/beforeChange/flattenValidationData.d.ts.map +1 -0
  113. package/dist/fields/hooks/beforeChange/flattenValidationData.js +36 -0
  114. package/dist/fields/hooks/beforeChange/flattenValidationData.js.map +1 -0
  115. package/dist/fields/hooks/beforeChange/promise.d.ts +2 -1
  116. package/dist/fields/hooks/beforeChange/promise.d.ts.map +1 -1
  117. package/dist/fields/hooks/beforeChange/promise.js +96 -22
  118. package/dist/fields/hooks/beforeChange/promise.js.map +1 -1
  119. package/dist/fields/hooks/beforeChange/traverseFields.d.ts +2 -1
  120. package/dist/fields/hooks/beforeChange/traverseFields.d.ts.map +1 -1
  121. package/dist/fields/hooks/beforeChange/traverseFields.js +2 -1
  122. package/dist/fields/hooks/beforeChange/traverseFields.js.map +1 -1
  123. package/dist/globals/operations/findVersionByID.d.ts.map +1 -1
  124. package/dist/globals/operations/findVersionByID.js +7 -0
  125. package/dist/globals/operations/findVersionByID.js.map +1 -1
  126. package/dist/globals/operations/findVersions.d.ts.map +1 -1
  127. package/dist/globals/operations/findVersions.js +5 -0
  128. package/dist/globals/operations/findVersions.js.map +1 -1
  129. package/dist/index.bundled.d.ts +6 -1
  130. package/dist/queues/utilities/updateJob.d.ts.map +1 -1
  131. package/dist/queues/utilities/updateJob.js +15 -0
  132. package/dist/queues/utilities/updateJob.js.map +1 -1
  133. package/dist/utilities/getEntityPermissions/getEntityPermissions.d.ts.map +1 -1
  134. package/dist/utilities/getEntityPermissions/getEntityPermissions.js +1 -0
  135. package/dist/utilities/getEntityPermissions/getEntityPermissions.js.map +1 -1
  136. package/dist/utilities/getNextJsHMRURL.d.ts.map +1 -1
  137. package/dist/utilities/getNextJsHMRURL.js +4 -2
  138. package/dist/utilities/getNextJsHMRURL.js.map +1 -1
  139. package/dist/utilities/getNextJsHMRURL.spec.js +11 -0
  140. package/dist/utilities/getNextJsHMRURL.spec.js.map +1 -1
  141. package/dist/utilities/getVersionsConfig.d.ts +4 -0
  142. package/dist/utilities/getVersionsConfig.d.ts.map +1 -1
  143. package/dist/utilities/getVersionsConfig.js +5 -0
  144. package/dist/utilities/getVersionsConfig.js.map +1 -1
  145. package/lexicalLoader.mjs +26 -0
  146. package/package.json +10 -9
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utilities/getEntityPermissions/getEntityPermissions.ts"],"sourcesContent":["import { isDeepStrictEqual } from 'util'\n\nimport type {\n BlockPermissions,\n CollectionPermission,\n FieldsPermissions,\n GlobalPermission,\n Permission,\n} from '../../auth/types.js'\nimport type { SanitizedCollectionConfig, TypeWithID } from '../../collections/config/types.js'\nimport type { SanitizedGlobalConfig } from '../../globals/config/types.js'\nimport type { BlockSlug, DefaultDocumentIDType } from '../../index.js'\nimport type { AllOperations, JsonObject, PayloadRequest, Where } from '../../types/index.js'\n\nimport { entityDocExists } from './entityDocExists.js'\nimport { populateFieldPermissions } from './populateFieldPermissions.js'\n\ntype WhereQueryCache = { result: Promise<boolean>; where: Where }[]\n\nexport type BlockReferencesPermissions = Record<\n BlockSlug,\n BlockPermissions | Promise<BlockPermissions>\n>\n\nexport type EntityDoc = JsonObject | TypeWithID\n\ntype ReturnType<TEntityType extends 'collection' | 'global'> = TEntityType extends 'global'\n ? GlobalPermission\n : CollectionPermission\n\ntype Args<TEntityType extends 'collection' | 'global'> = {\n blockReferencesPermissions: BlockReferencesPermissions\n /**\n * If the document data is passed, it will be used to check access instead of fetching the document from the database.\n */\n data?: JsonObject\n entity: TEntityType extends 'collection' ? SanitizedCollectionConfig : SanitizedGlobalConfig\n entityType: TEntityType\n /**\n * Operations to check access for\n */\n operations: AllOperations[]\n req: PayloadRequest\n} & (\n | {\n fetchData: false\n id?: never\n }\n | {\n fetchData: true\n id: TEntityType extends 'collection' ? DefaultDocumentIDType : undefined\n }\n)\n\nconst topLevelCollectionPermissions = [\n 'create',\n 'delete',\n 'read',\n 'readVersions',\n 'update',\n 'unlock',\n]\nconst topLevelGlobalPermissions = ['read', 'readVersions', 'update']\n\n/**\n * Build up permissions object for an entity (collection or global).\n * This is not run during any update and reflects the current state of the entity data => doc and data is the same.\n *\n * When `fetchData` is false:\n * - returned `Where` are not run and evaluated as \"does not have permission\".\n * - If req.data is passed: `data` and `doc` is passed to access functions.\n * - If req.data is not passed: `data` and `doc` is not passed to access functions.\n *\n * When `fetchData` is true:\n * - `Where` are run and evaluated as \"has permission\" or \"does not have permission\".\n * - `data` and `doc` are always passed to access functions.\n * - Error is thrown if `entityType` is 'collection' and `id` is not passed.\n *\n * In both cases:\n * We cannot include siblingData or blockData here, as we do not have siblingData available once we reach block or array\n * rows, as we're calculating schema permissions, which do not include individual rows.\n * For consistency, it's thus better to never include the siblingData and blockData\n *\n * @internal\n */\nexport async function getEntityPermissions<TEntityType extends 'collection' | 'global'>(\n args: Args<TEntityType>,\n): Promise<ReturnType<TEntityType>> {\n const {\n id,\n blockReferencesPermissions,\n data: _data,\n entity,\n entityType,\n fetchData,\n operations,\n req,\n } = args\n const { locale: _locale, user } = req\n\n const locale = _locale ? _locale : undefined\n\n if (fetchData && entityType === 'collection' && !id) {\n throw new Error('ID is required when fetching data for a collection')\n }\n\n const hasData = _data && Object.keys(_data).length > 0\n const data: JsonObject | undefined = hasData\n ? _data\n : fetchData\n ? await (async () => {\n if (entityType === 'global') {\n return req.payload.findGlobal({\n slug: entity.slug,\n depth: 0,\n fallbackLocale: null,\n locale,\n overrideAccess: true,\n req,\n })\n }\n\n if (entityType === 'collection') {\n return req.payload.findByID({\n id: id!,\n collection: entity.slug,\n depth: 0,\n fallbackLocale: null,\n locale,\n overrideAccess: true,\n req,\n trash: true,\n })\n }\n })()\n : undefined\n\n const isLoggedIn = !!user\n const collectionConfig =\n entityType === 'collection' ? (entity as SanitizedCollectionConfig) : undefined\n\n const fieldsPermissions: FieldsPermissions = {}\n\n const entityPermissions: ReturnType<TEntityType> = {\n fields: fieldsPermissions,\n } as ReturnType<TEntityType>\n\n const promises: Promise<void>[] = []\n\n // Phase 1: Resolve all access functions to get where queries\n const accessResults: {\n operation: keyof typeof entity.access\n result: Promise<boolean | Where>\n }[] = []\n\n for (const _operation of operations) {\n const operation = _operation as keyof typeof entity.access\n const accessFunction = entity.access[operation]\n\n if (\n (entityType === 'collection' && topLevelCollectionPermissions.includes(operation)) ||\n (entityType === 'global' && topLevelGlobalPermissions.includes(operation))\n ) {\n if (typeof accessFunction === 'function') {\n accessResults.push({\n operation,\n result: Promise.resolve(\n accessFunction({\n id,\n collectionConfig,\n data,\n req,\n }),\n ) as Promise<boolean | Where>,\n })\n } else {\n entityPermissions[operation] = {\n permission: isLoggedIn,\n }\n }\n }\n }\n\n // Await all access functions in parallel\n const resolvedAccessResults = await Promise.all(\n accessResults.map(async (item) => ({\n operation: item.operation,\n result: await item.result,\n })),\n )\n\n // Phase 2: Process where queries with cache and resolve in parallel\n const whereQueryCache: WhereQueryCache = []\n const wherePromises: Promise<void>[] = []\n\n for (const { operation, result: accessResult } of resolvedAccessResults) {\n if (typeof accessResult === 'object') {\n processWhereQuery({\n id,\n slug: entity.slug,\n accessResult,\n entityPermissions,\n entityType,\n fetchData,\n locale,\n operation,\n req,\n wherePromises,\n whereQueryCache,\n })\n } else if (entityPermissions[operation]?.permission !== false) {\n entityPermissions[operation] = { permission: !!accessResult }\n }\n }\n\n // Await all where query DB calls in parallel\n await Promise.all(wherePromises)\n\n populateFieldPermissions({\n blockReferencesPermissions,\n data,\n fields: entity.fields,\n operations,\n parentPermissionsObject: entityPermissions,\n permissionsObject: fieldsPermissions,\n promises,\n req,\n })\n\n /**\n * Await all promises in parallel.\n * A promise can add more promises to the promises array (group of fields calls populateFieldPermissions again in their own promise), which will not be\n * awaited in the first run.\n * This is why we need to loop again to process the new promises, until there are no more promises left.\n */\n let iterations = 0\n while (promises.length > 0) {\n const currentPromises = promises.splice(0, promises.length)\n\n await Promise.all(currentPromises)\n\n iterations++\n if (iterations >= 100) {\n throw new Error('Infinite getEntityPermissions promise loop detected.')\n }\n }\n\n return entityPermissions\n}\n\nconst processWhereQuery = ({\n id,\n slug,\n accessResult,\n entityPermissions,\n entityType,\n fetchData,\n locale,\n operation,\n req,\n wherePromises,\n whereQueryCache,\n}: {\n accessResult: Where\n entityPermissions: CollectionPermission | GlobalPermission\n entityType: 'collection' | 'global'\n fetchData: boolean\n id?: DefaultDocumentIDType\n locale?: string\n operation: Extract<keyof (CollectionPermission | GlobalPermission), AllOperations>\n req: PayloadRequest\n slug: string\n wherePromises: Promise<void>[]\n whereQueryCache: WhereQueryCache\n}): void => {\n if (fetchData) {\n // Check cache for identical where query using deep comparison\n let cached = whereQueryCache.find((entry) => isDeepStrictEqual(entry.where, accessResult))\n\n if (!cached) {\n // Cache miss - start DB query (don't await)\n cached = {\n result: entityDocExists({\n id,\n slug,\n entityType,\n locale,\n operation,\n req,\n where: accessResult,\n }),\n where: accessResult,\n }\n whereQueryCache.push(cached)\n }\n\n // Defer resolution to Promise.all (cache hits reuse same promise)\n wherePromises.push(\n cached.result.then((hasPermission) => {\n entityPermissions[operation] = {\n permission: hasPermission,\n where: accessResult,\n } as Permission\n }),\n )\n } else {\n // TODO: 4.0: Investigate defaulting to `false` here, if where query is returned but ignored as we don't\n // have the document data available. This seems more secure.\n // Alternatively, we could set permission to a third state, like 'unknown'.\n // Even after calling sanitizePermissions, the permissions will still be true if the where query is returned but ignored as we don't have the document data available.\n entityPermissions[operation] = { permission: true, where: accessResult } as Permission\n }\n}\n"],"names":["isDeepStrictEqual","entityDocExists","populateFieldPermissions","topLevelCollectionPermissions","topLevelGlobalPermissions","getEntityPermissions","args","id","blockReferencesPermissions","data","_data","entity","entityType","fetchData","operations","req","locale","_locale","user","undefined","Error","hasData","Object","keys","length","payload","findGlobal","slug","depth","fallbackLocale","overrideAccess","findByID","collection","trash","isLoggedIn","collectionConfig","fieldsPermissions","entityPermissions","fields","promises","accessResults","_operation","operation","accessFunction","access","includes","push","result","Promise","resolve","permission","resolvedAccessResults","all","map","item","whereQueryCache","wherePromises","accessResult","processWhereQuery","parentPermissionsObject","permissionsObject","iterations","currentPromises","splice","cached","find","entry","where","then","hasPermission"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,OAAM;AAcxC,SAASC,eAAe,QAAQ,uBAAsB;AACtD,SAASC,wBAAwB,QAAQ,gCAA+B;AAuCxE,MAAMC,gCAAgC;IACpC;IACA;IACA;IACA;IACA;IACA;CACD;AACD,MAAMC,4BAA4B;IAAC;IAAQ;IAAgB;CAAS;AAEpE;;;;;;;;;;;;;;;;;;;;CAoBC,GACD,OAAO,eAAeC,qBACpBC,IAAuB;IAEvB,MAAM,EACJC,EAAE,EACFC,0BAA0B,EAC1BC,MAAMC,KAAK,EACXC,MAAM,EACNC,UAAU,EACVC,SAAS,EACTC,UAAU,EACVC,GAAG,EACJ,GAAGT;IACJ,MAAM,EAAEU,QAAQC,OAAO,EAAEC,IAAI,EAAE,GAAGH;IAElC,MAAMC,SAASC,UAAUA,UAAUE;IAEnC,IAAIN,aAAaD,eAAe,gBAAgB,CAACL,IAAI;QACnD,MAAM,IAAIa,MAAM;IAClB;IAEA,MAAMC,UAAUX,SAASY,OAAOC,IAAI,CAACb,OAAOc,MAAM,GAAG;IACrD,MAAMf,OAA+BY,UACjCX,QACAG,YACE,MAAM,AAAC,CAAA;QACL,IAAID,eAAe,UAAU;YAC3B,OAAOG,IAAIU,OAAO,CAACC,UAAU,CAAC;gBAC5BC,MAAMhB,OAAOgB,IAAI;gBACjBC,OAAO;gBACPC,gBAAgB;gBAChBb;gBACAc,gBAAgB;gBAChBf;YACF;QACF;QAEA,IAAIH,eAAe,cAAc;YAC/B,OAAOG,IAAIU,OAAO,CAACM,QAAQ,CAAC;gBAC1BxB,IAAIA;gBACJyB,YAAYrB,OAAOgB,IAAI;gBACvBC,OAAO;gBACPC,gBAAgB;gBAChBb;gBACAc,gBAAgB;gBAChBf;gBACAkB,OAAO;YACT;QACF;IACF,CAAA,MACAd;IAEN,MAAMe,aAAa,CAAC,CAAChB;IACrB,MAAMiB,mBACJvB,eAAe,eAAgBD,SAAuCQ;IAExE,MAAMiB,oBAAuC,CAAC;IAE9C,MAAMC,oBAA6C;QACjDC,QAAQF;IACV;IAEA,MAAMG,WAA4B,EAAE;IAEpC,6DAA6D;IAC7D,MAAMC,gBAGA,EAAE;IAER,KAAK,MAAMC,cAAc3B,WAAY;QACnC,MAAM4B,YAAYD;QAClB,MAAME,iBAAiBhC,OAAOiC,MAAM,CAACF,UAAU;QAE/C,IACE,AAAC9B,eAAe,gBAAgBT,8BAA8B0C,QAAQ,CAACH,cACtE9B,eAAe,YAAYR,0BAA0ByC,QAAQ,CAACH,YAC/D;YACA,IAAI,OAAOC,mBAAmB,YAAY;gBACxCH,cAAcM,IAAI,CAAC;oBACjBJ;oBACAK,QAAQC,QAAQC,OAAO,CACrBN,eAAe;wBACbpC;wBACA4B;wBACA1B;wBACAM;oBACF;gBAEJ;YACF,OAAO;gBACLsB,iBAAiB,CAACK,UAAU,GAAG;oBAC7BQ,YAAYhB;gBACd;YACF;QACF;IACF;IAEA,yCAAyC;IACzC,MAAMiB,wBAAwB,MAAMH,QAAQI,GAAG,CAC7CZ,cAAca,GAAG,CAAC,OAAOC,OAAU,CAAA;YACjCZ,WAAWY,KAAKZ,SAAS;YACzBK,QAAQ,MAAMO,KAAKP,MAAM;QAC3B,CAAA;IAGF,oEAAoE;IACpE,MAAMQ,kBAAmC,EAAE;IAC3C,MAAMC,gBAAiC,EAAE;IAEzC,KAAK,MAAM,EAAEd,SAAS,EAAEK,QAAQU,YAAY,EAAE,IAAIN,sBAAuB;QACvE,IAAI,OAAOM,iBAAiB,UAAU;YACpCC,kBAAkB;gBAChBnD;gBACAoB,MAAMhB,OAAOgB,IAAI;gBACjB8B;gBACApB;gBACAzB;gBACAC;gBACAG;gBACA0B;gBACA3B;gBACAyC;gBACAD;YACF;QACF,OAAO,IAAIlB,iBAAiB,CAACK,UAAU,EAAEQ,eAAe,OAAO;YAC7Db,iBAAiB,CAACK,UAAU,GAAG;gBAAEQ,YAAY,CAAC,CAACO;YAAa;QAC9D;IACF;IAEA,6CAA6C;IAC7C,MAAMT,QAAQI,GAAG,CAACI;IAElBtD,yBAAyB;QACvBM;QACAC;QACA6B,QAAQ3B,OAAO2B,MAAM;QACrBxB;QACA6C,yBAAyBtB;QACzBuB,mBAAmBxB;QACnBG;QACAxB;IACF;IAEA;;;;;GAKC,GACD,IAAI8C,aAAa;IACjB,MAAOtB,SAASf,MAAM,GAAG,EAAG;QAC1B,MAAMsC,kBAAkBvB,SAASwB,MAAM,CAAC,GAAGxB,SAASf,MAAM;QAE1D,MAAMwB,QAAQI,GAAG,CAACU;QAElBD;QACA,IAAIA,cAAc,KAAK;YACrB,MAAM,IAAIzC,MAAM;QAClB;IACF;IAEA,OAAOiB;AACT;AAEA,MAAMqB,oBAAoB,CAAC,EACzBnD,EAAE,EACFoB,IAAI,EACJ8B,YAAY,EACZpB,iBAAiB,EACjBzB,UAAU,EACVC,SAAS,EACTG,MAAM,EACN0B,SAAS,EACT3B,GAAG,EACHyC,aAAa,EACbD,eAAe,EAahB;IACC,IAAI1C,WAAW;QACb,8DAA8D;QAC9D,IAAImD,SAAST,gBAAgBU,IAAI,CAAC,CAACC,QAAUlE,kBAAkBkE,MAAMC,KAAK,EAAEV;QAE5E,IAAI,CAACO,QAAQ;YACX,4CAA4C;YAC5CA,SAAS;gBACPjB,QAAQ9C,gBAAgB;oBACtBM;oBACAoB;oBACAf;oBACAI;oBACA0B;oBACA3B;oBACAoD,OAAOV;gBACT;gBACAU,OAAOV;YACT;YACAF,gBAAgBT,IAAI,CAACkB;QACvB;QAEA,kEAAkE;QAClER,cAAcV,IAAI,CAChBkB,OAAOjB,MAAM,CAACqB,IAAI,CAAC,CAACC;YAClBhC,iBAAiB,CAACK,UAAU,GAAG;gBAC7BQ,YAAYmB;gBACZF,OAAOV;YACT;QACF;IAEJ,OAAO;QACL,wGAAwG;QACxG,4DAA4D;QAC5D,2EAA2E;QAC3E,sKAAsK;QACtKpB,iBAAiB,CAACK,UAAU,GAAG;YAAEQ,YAAY;YAAMiB,OAAOV;QAAa;IACzE;AACF"}
1
+ {"version":3,"sources":["../../../src/utilities/getEntityPermissions/getEntityPermissions.ts"],"sourcesContent":["import { isDeepStrictEqual } from 'util'\n\nimport type {\n BlockPermissions,\n CollectionPermission,\n FieldsPermissions,\n GlobalPermission,\n Permission,\n} from '../../auth/types.js'\nimport type { SanitizedCollectionConfig, TypeWithID } from '../../collections/config/types.js'\nimport type { SanitizedGlobalConfig } from '../../globals/config/types.js'\nimport type { BlockSlug, DefaultDocumentIDType } from '../../index.js'\nimport type { AllOperations, JsonObject, PayloadRequest, Where } from '../../types/index.js'\n\nimport { entityDocExists } from './entityDocExists.js'\nimport { populateFieldPermissions } from './populateFieldPermissions.js'\n\ntype WhereQueryCache = { result: Promise<boolean>; where: Where }[]\n\nexport type BlockReferencesPermissions = Record<\n BlockSlug,\n BlockPermissions | Promise<BlockPermissions>\n>\n\nexport type EntityDoc = JsonObject | TypeWithID\n\ntype ReturnType<TEntityType extends 'collection' | 'global'> = TEntityType extends 'global'\n ? GlobalPermission\n : CollectionPermission\n\ntype Args<TEntityType extends 'collection' | 'global'> = {\n blockReferencesPermissions: BlockReferencesPermissions\n /**\n * If the document data is passed, it will be used to check access instead of fetching the document from the database.\n */\n data?: JsonObject\n entity: TEntityType extends 'collection' ? SanitizedCollectionConfig : SanitizedGlobalConfig\n entityType: TEntityType\n /**\n * Operations to check access for\n */\n operations: AllOperations[]\n req: PayloadRequest\n} & (\n | {\n fetchData: false\n id?: never\n }\n | {\n fetchData: true\n id: TEntityType extends 'collection' ? DefaultDocumentIDType : undefined\n }\n)\n\nconst topLevelCollectionPermissions = [\n 'create',\n 'delete',\n 'read',\n 'readVersions',\n 'update',\n 'unlock',\n]\nconst topLevelGlobalPermissions = ['read', 'readVersions', 'update']\n\n/**\n * Build up permissions object for an entity (collection or global).\n * This is not run during any update and reflects the current state of the entity data => doc and data is the same.\n *\n * When `fetchData` is false:\n * - returned `Where` are not run and evaluated as \"does not have permission\".\n * - If req.data is passed: `data` and `doc` is passed to access functions.\n * - If req.data is not passed: `data` and `doc` is not passed to access functions.\n *\n * When `fetchData` is true:\n * - `Where` are run and evaluated as \"has permission\" or \"does not have permission\".\n * - `data` and `doc` are always passed to access functions.\n * - Error is thrown if `entityType` is 'collection' and `id` is not passed.\n *\n * In both cases:\n * We cannot include siblingData or blockData here, as we do not have siblingData available once we reach block or array\n * rows, as we're calculating schema permissions, which do not include individual rows.\n * For consistency, it's thus better to never include the siblingData and blockData\n *\n * @internal\n */\nexport async function getEntityPermissions<TEntityType extends 'collection' | 'global'>(\n args: Args<TEntityType>,\n): Promise<ReturnType<TEntityType>> {\n const {\n id,\n blockReferencesPermissions,\n data: _data,\n entity,\n entityType,\n fetchData,\n operations,\n req,\n } = args\n const { locale: _locale, user } = req\n\n const locale = _locale ? _locale : undefined\n\n if (fetchData && entityType === 'collection' && !id) {\n throw new Error('ID is required when fetching data for a collection')\n }\n\n const hasData = _data && Object.keys(_data).length > 0\n const data: JsonObject | undefined = hasData\n ? _data\n : fetchData\n ? await (async () => {\n if (entityType === 'global') {\n return req.payload.findGlobal({\n slug: entity.slug,\n depth: 0,\n fallbackLocale: null,\n locale,\n overrideAccess: true,\n req,\n })\n }\n\n if (entityType === 'collection') {\n return req.payload.findByID({\n id: id!,\n collection: entity.slug,\n depth: 0,\n fallbackLocale: null,\n locale,\n overrideAccess: true,\n req,\n trash: true,\n })\n }\n })()\n : undefined\n\n const isLoggedIn = !!user\n const collectionConfig =\n entityType === 'collection' ? (entity as SanitizedCollectionConfig) : undefined\n\n const fieldsPermissions: FieldsPermissions = {}\n\n const entityPermissions: ReturnType<TEntityType> = {\n fields: fieldsPermissions,\n } as ReturnType<TEntityType>\n\n const promises: Promise<void>[] = []\n\n // Phase 1: Resolve all access functions to get where queries\n const accessResults: {\n operation: keyof typeof entity.access\n result: Promise<boolean | Where>\n }[] = []\n\n for (const _operation of operations) {\n const operation = _operation as keyof typeof entity.access\n const accessFunction = entity.access[operation]\n\n if (\n (entityType === 'collection' && topLevelCollectionPermissions.includes(operation)) ||\n (entityType === 'global' && topLevelGlobalPermissions.includes(operation))\n ) {\n if (typeof accessFunction === 'function') {\n accessResults.push({\n operation,\n result: Promise.resolve(\n accessFunction({\n id,\n collectionConfig,\n data,\n req,\n }),\n ) as Promise<boolean | Where>,\n })\n } else {\n entityPermissions[operation] = {\n permission: isLoggedIn,\n }\n }\n }\n }\n\n // Await all access functions in parallel\n const resolvedAccessResults = await Promise.all(\n accessResults.map(async (item) => ({\n operation: item.operation,\n result: await item.result,\n })),\n )\n\n // Phase 2: Process where queries with cache and resolve in parallel\n const whereQueryCache: WhereQueryCache = []\n const wherePromises: Promise<void>[] = []\n\n for (const { operation, result: accessResult } of resolvedAccessResults) {\n if (typeof accessResult === 'object') {\n processWhereQuery({\n id,\n slug: entity.slug,\n accessResult,\n entityPermissions,\n entityType,\n fetchData,\n locale,\n operation,\n req,\n wherePromises,\n whereQueryCache,\n })\n } else if (entityPermissions[operation]?.permission !== false) {\n entityPermissions[operation] = { permission: !!accessResult }\n }\n }\n\n // Await all where query DB calls in parallel\n await Promise.all(wherePromises)\n\n populateFieldPermissions({\n id,\n blockReferencesPermissions,\n data,\n fields: entity.fields,\n operations,\n parentPermissionsObject: entityPermissions,\n permissionsObject: fieldsPermissions,\n promises,\n req,\n })\n\n /**\n * Await all promises in parallel.\n * A promise can add more promises to the promises array (group of fields calls populateFieldPermissions again in their own promise), which will not be\n * awaited in the first run.\n * This is why we need to loop again to process the new promises, until there are no more promises left.\n */\n let iterations = 0\n while (promises.length > 0) {\n const currentPromises = promises.splice(0, promises.length)\n\n await Promise.all(currentPromises)\n\n iterations++\n if (iterations >= 100) {\n throw new Error('Infinite getEntityPermissions promise loop detected.')\n }\n }\n\n return entityPermissions\n}\n\nconst processWhereQuery = ({\n id,\n slug,\n accessResult,\n entityPermissions,\n entityType,\n fetchData,\n locale,\n operation,\n req,\n wherePromises,\n whereQueryCache,\n}: {\n accessResult: Where\n entityPermissions: CollectionPermission | GlobalPermission\n entityType: 'collection' | 'global'\n fetchData: boolean\n id?: DefaultDocumentIDType\n locale?: string\n operation: Extract<keyof (CollectionPermission | GlobalPermission), AllOperations>\n req: PayloadRequest\n slug: string\n wherePromises: Promise<void>[]\n whereQueryCache: WhereQueryCache\n}): void => {\n if (fetchData) {\n // Check cache for identical where query using deep comparison\n let cached = whereQueryCache.find((entry) => isDeepStrictEqual(entry.where, accessResult))\n\n if (!cached) {\n // Cache miss - start DB query (don't await)\n cached = {\n result: entityDocExists({\n id,\n slug,\n entityType,\n locale,\n operation,\n req,\n where: accessResult,\n }),\n where: accessResult,\n }\n whereQueryCache.push(cached)\n }\n\n // Defer resolution to Promise.all (cache hits reuse same promise)\n wherePromises.push(\n cached.result.then((hasPermission) => {\n entityPermissions[operation] = {\n permission: hasPermission,\n where: accessResult,\n } as Permission\n }),\n )\n } else {\n // TODO: 4.0: Investigate defaulting to `false` here, if where query is returned but ignored as we don't\n // have the document data available. This seems more secure.\n // Alternatively, we could set permission to a third state, like 'unknown'.\n // Even after calling sanitizePermissions, the permissions will still be true if the where query is returned but ignored as we don't have the document data available.\n entityPermissions[operation] = { permission: true, where: accessResult } as Permission\n }\n}\n"],"names":["isDeepStrictEqual","entityDocExists","populateFieldPermissions","topLevelCollectionPermissions","topLevelGlobalPermissions","getEntityPermissions","args","id","blockReferencesPermissions","data","_data","entity","entityType","fetchData","operations","req","locale","_locale","user","undefined","Error","hasData","Object","keys","length","payload","findGlobal","slug","depth","fallbackLocale","overrideAccess","findByID","collection","trash","isLoggedIn","collectionConfig","fieldsPermissions","entityPermissions","fields","promises","accessResults","_operation","operation","accessFunction","access","includes","push","result","Promise","resolve","permission","resolvedAccessResults","all","map","item","whereQueryCache","wherePromises","accessResult","processWhereQuery","parentPermissionsObject","permissionsObject","iterations","currentPromises","splice","cached","find","entry","where","then","hasPermission"],"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,MAYlC,CAAA"}
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
- // The __NEXT_ASSET_PREFIX env variable is set for both assetPrefix and basePath (tested in Next.js 15.1.6)
17
- const prefix = process.env.__NEXT_ASSET_PREFIX ?? '';
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 // The __NEXT_ASSET_PREFIX env variable is set for both assetPrefix and basePath (tested in Next.js 15.1.6)\n const prefix = process.env.__NEXT_ASSET_PREFIX ?? ''\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","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,2GAA2G;IAC3G,MAAMK,SAASV,QAAQC,GAAG,CAACU,mBAAmB,IAAI;IAElD,OAAO,GAAGF,SAAS,aAAa,EAAEN,OAAOO,SAASE,cAAc;AAClE,EAAC;AAED;;;;CAIC,GACD,MAAMA,aAAa;IACjB,MAAMC,cAAclB;IAEpB,IAAI,CAACkB,aAAa;QAChB,OAAOjB;IACT;IAEA,MAAMkB,cAAcpB,aAAamB,aAAaE,KAAK,CAACC,IAAI,CAAC;IAEzD,OAAOvB,gBAAgBqB,aAAahB,+BAA+B,UAC/DD,gBACAD;AACN"}
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;IACrB;IAEAd,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;AACF"}
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"}
@@ -2,6 +2,10 @@ import type { CollectionConfig } from '../collections/config/types.js';
2
2
  import type { GlobalConfig } from '../globals/config/types.js';
3
3
  import type { Autosave, SanitizedDrafts } from '../versions/types.js';
4
4
  type EntityConfig = Pick<CollectionConfig | GlobalConfig, 'versions'>;
5
+ /**
6
+ * Check if an entity has versions enabled at all
7
+ */
8
+ export declare const hasVersionsEnabled: (config: EntityConfig) => boolean;
5
9
  /**
6
10
  * Check if an entity has drafts enabled
7
11
  */
@@ -1 +1 @@
1
- {"version":3,"file":"getVersionsConfig.d.ts","sourceRoot":"","sources":["../../src/utilities/getVersionsConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAIrE,KAAK,YAAY,GAAG,IAAI,CAAC,gBAAgB,GAAG,YAAY,EAAE,UAAU,CAAC,CAAA;AAErE;;GAEG;AACH,eAAO,MAAM,gBAAgB,WAAY,YAAY,KAAG,OAEvD,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,wBAAwB,WAAY,YAAY,KAAG,OAQ/D,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,WACrB,YAAY,KACnB,MAAM,IAAI;IACX,QAAQ,EAAE;QACR,MAAM,EAAE;YAAE,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAA;SAAE,CAAA;KACvC,CAAA;CACF,GAAG,YAQH,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,yBAAyB,WAAY,YAAY,KAAG,OAQhE,CAAA;AAED,eAAO,MAAM,0BAA0B,WAC7B,YAAY,KACnB,MAAM,IAAI;IACX,QAAQ,EAAE;QACR,MAAM,EAAE;YAAE,eAAe,EAAE,eAAe,CAAC,iBAAiB,CAAC,CAAA;SAAE,CAAA;KAChE,CAAA;CACF,GAAG,YAQH,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,WAAY,YAAY,KAAG,MAYrD,CAAA;AAED,eAAO,MAAM,mBAAmB,WAAY,YAAY,KAAG,MAa1D,CAAA"}
1
+ {"version":3,"file":"getVersionsConfig.d.ts","sourceRoot":"","sources":["../../src/utilities/getVersionsConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAIrE,KAAK,YAAY,GAAG,IAAI,CAAC,gBAAgB,GAAG,YAAY,EAAE,UAAU,CAAC,CAAA;AAErE;;GAEG;AACH,eAAO,MAAM,kBAAkB,WAAY,YAAY,KAAG,OAEzD,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,WAAY,YAAY,KAAG,OAEvD,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,wBAAwB,WAAY,YAAY,KAAG,OAQ/D,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,WACrB,YAAY,KACnB,MAAM,IAAI;IACX,QAAQ,EAAE;QACR,MAAM,EAAE;YAAE,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAA;SAAE,CAAA;KACvC,CAAA;CACF,GAAG,YAQH,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,yBAAyB,WAAY,YAAY,KAAG,OAQhE,CAAA;AAED,eAAO,MAAM,0BAA0B,WAC7B,YAAY,KACnB,MAAM,IAAI;IACX,QAAQ,EAAE;QACR,MAAM,EAAE;YAAE,eAAe,EAAE,eAAe,CAAC,iBAAiB,CAAC,CAAA;SAAE,CAAA;KAChE,CAAA;CACF,GAAG,YAQH,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,WAAY,YAAY,KAAG,MAYrD,CAAA;AAED,eAAO,MAAM,mBAAmB,WAAY,YAAY,KAAG,MAa1D,CAAA"}
@@ -1,4 +1,9 @@
1
1
  import { versionDefaults } from '../versions/defaults.js';
2
+ /**
3
+ * Check if an entity has versions enabled at all
4
+ */ export const hasVersionsEnabled = (config)=>{
5
+ return Boolean(config?.versions);
6
+ };
2
7
  /**
3
8
  * Check if an entity has drafts enabled
4
9
  */ export const hasDraftsEnabled = (config)=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/getVersionsConfig.ts"],"sourcesContent":["import type { CollectionConfig } from '../collections/config/types.js'\nimport type { GlobalConfig } from '../globals/config/types.js'\nimport type { Autosave, SanitizedDrafts } from '../versions/types.js'\n\nimport { versionDefaults } from '../versions/defaults.js'\n\ntype EntityConfig = Pick<CollectionConfig | GlobalConfig, 'versions'>\n\n/**\n * Check if an entity has drafts enabled\n */\nexport const hasDraftsEnabled = (config: EntityConfig): boolean => {\n return Boolean(config?.versions && typeof config.versions === 'object' && config.versions.drafts)\n}\n\n/**\n * Check if an entity has localized status enabled\n */\nexport const hasLocalizeStatusEnabled = (config: EntityConfig): boolean => {\n return Boolean(\n config?.versions &&\n typeof config.versions === 'object' &&\n config.versions.drafts &&\n typeof config.versions.drafts === 'object' &&\n config.versions.drafts.localizeStatus,\n )\n}\n\n/**\n * Check if an entity has autosave enabled\n */\nexport const hasAutosaveEnabled = (\n config: EntityConfig,\n): config is {\n versions: {\n drafts: { autosave: Autosave | false }\n }\n} & EntityConfig => {\n return Boolean(\n config?.versions &&\n typeof config.versions === 'object' &&\n config.versions.drafts &&\n typeof config.versions.drafts === 'object' &&\n config.versions.drafts.autosave,\n )\n}\n\n/**\n * Check if an entity has validate drafts enabled\n */\nexport const hasDraftValidationEnabled = (config: EntityConfig): boolean => {\n return Boolean(\n config?.versions &&\n typeof config.versions === 'object' &&\n config.versions.drafts &&\n typeof config.versions.drafts === 'object' &&\n config.versions.drafts.validate,\n )\n}\n\nexport const hasScheduledPublishEnabled = (\n config: EntityConfig,\n): config is {\n versions: {\n drafts: { schedulePublish: SanitizedDrafts['schedulePublish'] }\n }\n} & EntityConfig => {\n return Boolean(\n config?.versions &&\n typeof config.versions === 'object' &&\n config.versions.drafts &&\n typeof config.versions.drafts === 'object' &&\n config.versions.drafts.schedulePublish,\n )\n}\n\n/**\n * Get the maximum number of versions to keep for an entity\n * Returns maxPerDoc for collections or max for globals\n */\nexport const getVersionsMax = (config: EntityConfig): number => {\n if (!config?.versions || typeof config.versions !== 'object') {\n return 0\n }\n // Collections have maxPerDoc, globals have max\n if ('maxPerDoc' in config.versions) {\n return config.versions.maxPerDoc ?? 100\n }\n if ('max' in config.versions) {\n return config.versions.max ?? 100\n }\n return 0\n}\n\nexport const getAutosaveInterval = (config: EntityConfig): number => {\n let interval = versionDefaults.autosaveInterval\n if (\n config?.versions &&\n typeof config.versions === 'object' &&\n config.versions.drafts &&\n typeof config.versions.drafts === 'object' &&\n config.versions.drafts.autosave &&\n typeof config.versions.drafts.autosave === 'object'\n ) {\n interval = config.versions.drafts.autosave.interval ?? versionDefaults.autosaveInterval\n }\n return interval\n}\n"],"names":["versionDefaults","hasDraftsEnabled","config","Boolean","versions","drafts","hasLocalizeStatusEnabled","localizeStatus","hasAutosaveEnabled","autosave","hasDraftValidationEnabled","validate","hasScheduledPublishEnabled","schedulePublish","getVersionsMax","maxPerDoc","max","getAutosaveInterval","interval","autosaveInterval"],"mappings":"AAIA,SAASA,eAAe,QAAQ,0BAAyB;AAIzD;;CAEC,GACD,OAAO,MAAMC,mBAAmB,CAACC;IAC/B,OAAOC,QAAQD,QAAQE,YAAY,OAAOF,OAAOE,QAAQ,KAAK,YAAYF,OAAOE,QAAQ,CAACC,MAAM;AAClG,EAAC;AAED;;CAEC,GACD,OAAO,MAAMC,2BAA2B,CAACJ;IACvC,OAAOC,QACLD,QAAQE,YACN,OAAOF,OAAOE,QAAQ,KAAK,YAC3BF,OAAOE,QAAQ,CAACC,MAAM,IACtB,OAAOH,OAAOE,QAAQ,CAACC,MAAM,KAAK,YAClCH,OAAOE,QAAQ,CAACC,MAAM,CAACE,cAAc;AAE3C,EAAC;AAED;;CAEC,GACD,OAAO,MAAMC,qBAAqB,CAChCN;IAMA,OAAOC,QACLD,QAAQE,YACN,OAAOF,OAAOE,QAAQ,KAAK,YAC3BF,OAAOE,QAAQ,CAACC,MAAM,IACtB,OAAOH,OAAOE,QAAQ,CAACC,MAAM,KAAK,YAClCH,OAAOE,QAAQ,CAACC,MAAM,CAACI,QAAQ;AAErC,EAAC;AAED;;CAEC,GACD,OAAO,MAAMC,4BAA4B,CAACR;IACxC,OAAOC,QACLD,QAAQE,YACN,OAAOF,OAAOE,QAAQ,KAAK,YAC3BF,OAAOE,QAAQ,CAACC,MAAM,IACtB,OAAOH,OAAOE,QAAQ,CAACC,MAAM,KAAK,YAClCH,OAAOE,QAAQ,CAACC,MAAM,CAACM,QAAQ;AAErC,EAAC;AAED,OAAO,MAAMC,6BAA6B,CACxCV;IAMA,OAAOC,QACLD,QAAQE,YACN,OAAOF,OAAOE,QAAQ,KAAK,YAC3BF,OAAOE,QAAQ,CAACC,MAAM,IACtB,OAAOH,OAAOE,QAAQ,CAACC,MAAM,KAAK,YAClCH,OAAOE,QAAQ,CAACC,MAAM,CAACQ,eAAe;AAE5C,EAAC;AAED;;;CAGC,GACD,OAAO,MAAMC,iBAAiB,CAACZ;IAC7B,IAAI,CAACA,QAAQE,YAAY,OAAOF,OAAOE,QAAQ,KAAK,UAAU;QAC5D,OAAO;IACT;IACA,+CAA+C;IAC/C,IAAI,eAAeF,OAAOE,QAAQ,EAAE;QAClC,OAAOF,OAAOE,QAAQ,CAACW,SAAS,IAAI;IACtC;IACA,IAAI,SAASb,OAAOE,QAAQ,EAAE;QAC5B,OAAOF,OAAOE,QAAQ,CAACY,GAAG,IAAI;IAChC;IACA,OAAO;AACT,EAAC;AAED,OAAO,MAAMC,sBAAsB,CAACf;IAClC,IAAIgB,WAAWlB,gBAAgBmB,gBAAgB;IAC/C,IACEjB,QAAQE,YACR,OAAOF,OAAOE,QAAQ,KAAK,YAC3BF,OAAOE,QAAQ,CAACC,MAAM,IACtB,OAAOH,OAAOE,QAAQ,CAACC,MAAM,KAAK,YAClCH,OAAOE,QAAQ,CAACC,MAAM,CAACI,QAAQ,IAC/B,OAAOP,OAAOE,QAAQ,CAACC,MAAM,CAACI,QAAQ,KAAK,UAC3C;QACAS,WAAWhB,OAAOE,QAAQ,CAACC,MAAM,CAACI,QAAQ,CAACS,QAAQ,IAAIlB,gBAAgBmB,gBAAgB;IACzF;IACA,OAAOD;AACT,EAAC"}
1
+ {"version":3,"sources":["../../src/utilities/getVersionsConfig.ts"],"sourcesContent":["import type { CollectionConfig } from '../collections/config/types.js'\nimport type { GlobalConfig } from '../globals/config/types.js'\nimport type { Autosave, SanitizedDrafts } from '../versions/types.js'\n\nimport { versionDefaults } from '../versions/defaults.js'\n\ntype EntityConfig = Pick<CollectionConfig | GlobalConfig, 'versions'>\n\n/**\n * Check if an entity has versions enabled at all\n */\nexport const hasVersionsEnabled = (config: EntityConfig): boolean => {\n return Boolean(config?.versions)\n}\n\n/**\n * Check if an entity has drafts enabled\n */\nexport const hasDraftsEnabled = (config: EntityConfig): boolean => {\n return Boolean(config?.versions && typeof config.versions === 'object' && config.versions.drafts)\n}\n\n/**\n * Check if an entity has localized status enabled\n */\nexport const hasLocalizeStatusEnabled = (config: EntityConfig): boolean => {\n return Boolean(\n config?.versions &&\n typeof config.versions === 'object' &&\n config.versions.drafts &&\n typeof config.versions.drafts === 'object' &&\n config.versions.drafts.localizeStatus,\n )\n}\n\n/**\n * Check if an entity has autosave enabled\n */\nexport const hasAutosaveEnabled = (\n config: EntityConfig,\n): config is {\n versions: {\n drafts: { autosave: Autosave | false }\n }\n} & EntityConfig => {\n return Boolean(\n config?.versions &&\n typeof config.versions === 'object' &&\n config.versions.drafts &&\n typeof config.versions.drafts === 'object' &&\n config.versions.drafts.autosave,\n )\n}\n\n/**\n * Check if an entity has validate drafts enabled\n */\nexport const hasDraftValidationEnabled = (config: EntityConfig): boolean => {\n return Boolean(\n config?.versions &&\n typeof config.versions === 'object' &&\n config.versions.drafts &&\n typeof config.versions.drafts === 'object' &&\n config.versions.drafts.validate,\n )\n}\n\nexport const hasScheduledPublishEnabled = (\n config: EntityConfig,\n): config is {\n versions: {\n drafts: { schedulePublish: SanitizedDrafts['schedulePublish'] }\n }\n} & EntityConfig => {\n return Boolean(\n config?.versions &&\n typeof config.versions === 'object' &&\n config.versions.drafts &&\n typeof config.versions.drafts === 'object' &&\n config.versions.drafts.schedulePublish,\n )\n}\n\n/**\n * Get the maximum number of versions to keep for an entity\n * Returns maxPerDoc for collections or max for globals\n */\nexport const getVersionsMax = (config: EntityConfig): number => {\n if (!config?.versions || typeof config.versions !== 'object') {\n return 0\n }\n // Collections have maxPerDoc, globals have max\n if ('maxPerDoc' in config.versions) {\n return config.versions.maxPerDoc ?? 100\n }\n if ('max' in config.versions) {\n return config.versions.max ?? 100\n }\n return 0\n}\n\nexport const getAutosaveInterval = (config: EntityConfig): number => {\n let interval = versionDefaults.autosaveInterval\n if (\n config?.versions &&\n typeof config.versions === 'object' &&\n config.versions.drafts &&\n typeof config.versions.drafts === 'object' &&\n config.versions.drafts.autosave &&\n typeof config.versions.drafts.autosave === 'object'\n ) {\n interval = config.versions.drafts.autosave.interval ?? versionDefaults.autosaveInterval\n }\n return interval\n}\n"],"names":["versionDefaults","hasVersionsEnabled","config","Boolean","versions","hasDraftsEnabled","drafts","hasLocalizeStatusEnabled","localizeStatus","hasAutosaveEnabled","autosave","hasDraftValidationEnabled","validate","hasScheduledPublishEnabled","schedulePublish","getVersionsMax","maxPerDoc","max","getAutosaveInterval","interval","autosaveInterval"],"mappings":"AAIA,SAASA,eAAe,QAAQ,0BAAyB;AAIzD;;CAEC,GACD,OAAO,MAAMC,qBAAqB,CAACC;IACjC,OAAOC,QAAQD,QAAQE;AACzB,EAAC;AAED;;CAEC,GACD,OAAO,MAAMC,mBAAmB,CAACH;IAC/B,OAAOC,QAAQD,QAAQE,YAAY,OAAOF,OAAOE,QAAQ,KAAK,YAAYF,OAAOE,QAAQ,CAACE,MAAM;AAClG,EAAC;AAED;;CAEC,GACD,OAAO,MAAMC,2BAA2B,CAACL;IACvC,OAAOC,QACLD,QAAQE,YACN,OAAOF,OAAOE,QAAQ,KAAK,YAC3BF,OAAOE,QAAQ,CAACE,MAAM,IACtB,OAAOJ,OAAOE,QAAQ,CAACE,MAAM,KAAK,YAClCJ,OAAOE,QAAQ,CAACE,MAAM,CAACE,cAAc;AAE3C,EAAC;AAED;;CAEC,GACD,OAAO,MAAMC,qBAAqB,CAChCP;IAMA,OAAOC,QACLD,QAAQE,YACN,OAAOF,OAAOE,QAAQ,KAAK,YAC3BF,OAAOE,QAAQ,CAACE,MAAM,IACtB,OAAOJ,OAAOE,QAAQ,CAACE,MAAM,KAAK,YAClCJ,OAAOE,QAAQ,CAACE,MAAM,CAACI,QAAQ;AAErC,EAAC;AAED;;CAEC,GACD,OAAO,MAAMC,4BAA4B,CAACT;IACxC,OAAOC,QACLD,QAAQE,YACN,OAAOF,OAAOE,QAAQ,KAAK,YAC3BF,OAAOE,QAAQ,CAACE,MAAM,IACtB,OAAOJ,OAAOE,QAAQ,CAACE,MAAM,KAAK,YAClCJ,OAAOE,QAAQ,CAACE,MAAM,CAACM,QAAQ;AAErC,EAAC;AAED,OAAO,MAAMC,6BAA6B,CACxCX;IAMA,OAAOC,QACLD,QAAQE,YACN,OAAOF,OAAOE,QAAQ,KAAK,YAC3BF,OAAOE,QAAQ,CAACE,MAAM,IACtB,OAAOJ,OAAOE,QAAQ,CAACE,MAAM,KAAK,YAClCJ,OAAOE,QAAQ,CAACE,MAAM,CAACQ,eAAe;AAE5C,EAAC;AAED;;;CAGC,GACD,OAAO,MAAMC,iBAAiB,CAACb;IAC7B,IAAI,CAACA,QAAQE,YAAY,OAAOF,OAAOE,QAAQ,KAAK,UAAU;QAC5D,OAAO;IACT;IACA,+CAA+C;IAC/C,IAAI,eAAeF,OAAOE,QAAQ,EAAE;QAClC,OAAOF,OAAOE,QAAQ,CAACY,SAAS,IAAI;IACtC;IACA,IAAI,SAASd,OAAOE,QAAQ,EAAE;QAC5B,OAAOF,OAAOE,QAAQ,CAACa,GAAG,IAAI;IAChC;IACA,OAAO;AACT,EAAC;AAED,OAAO,MAAMC,sBAAsB,CAAChB;IAClC,IAAIiB,WAAWnB,gBAAgBoB,gBAAgB;IAC/C,IACElB,QAAQE,YACR,OAAOF,OAAOE,QAAQ,KAAK,YAC3BF,OAAOE,QAAQ,CAACE,MAAM,IACtB,OAAOJ,OAAOE,QAAQ,CAACE,MAAM,KAAK,YAClCJ,OAAOE,QAAQ,CAACE,MAAM,CAACI,QAAQ,IAC/B,OAAOR,OAAOE,QAAQ,CAACE,MAAM,CAACI,QAAQ,KAAK,UAC3C;QACAS,WAAWjB,OAAOE,QAAQ,CAACE,MAAM,CAACI,QAAQ,CAACS,QAAQ,IAAInB,gBAAgBoB,gBAAgB;IACzF;IACA,OAAOD;AACT,EAAC"}
@@ -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.91.0-internal.c1569dc",
3
+ "version": "3.92.0",
4
4
  "description": "Node, React, Headless CMS and Application Framework built on Next.js",
5
5
  "keywords": [
6
6
  "admin panel",
@@ -82,10 +82,12 @@
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",
90
+ "@payloadcms/translations": "3.92.0",
89
91
  "@types/busboy": "1.5.4",
90
92
  "ajv": "8.18.0",
91
93
  "bson-objectid": "2.0.4",
@@ -112,15 +114,15 @@
112
114
  "sanitize-filename": "1.6.3",
113
115
  "sax": "1.6.1",
114
116
  "ts-essentials": "10.0.3",
115
- "tsx": "4.22.4",
116
- "undici": "7.29.0",
117
+ "tsx": "4.23.15",
118
+ "undici": "7.30.1",
117
119
  "uuid": "13.0.2",
118
- "ws": "^8.16.0",
119
- "@payloadcms/translations": "3.91.0-internal.c1569dc"
120
+ "ws": "^8.16.0"
120
121
  },
121
122
  "devDependencies": {
122
123
  "@hyrious/esbuild-plugin-commonjs": "0.2.6",
123
124
  "@monaco-editor/react": "4.7.0",
125
+ "@payloadcms/eslint-config": "3.28.0",
124
126
  "@types/json-schema": "7.0.15",
125
127
  "@types/minimist": "1.2.2",
126
128
  "@types/nodemailer": "^8.0.0",
@@ -136,14 +138,13 @@
136
138
  "rimraf": "6.0.1",
137
139
  "rollup": "4.59.0",
138
140
  "rollup-plugin-dts": "6.2.3",
139
- "sharp": "0.32.6",
140
- "@payloadcms/eslint-config": "3.28.0"
141
+ "sharp": "0.32.6"
141
142
  },
142
143
  "peerDependencies": {
143
144
  "graphql": "^16.8.1"
144
145
  },
145
146
  "engines": {
146
- "node": "^18.20.2 || >=20.9.0"
147
+ "node": "^22.23.4 || >=24.22.1"
147
148
  },
148
149
  "publishConfig": {
149
150
  "registry": "https://registry.npmjs.org/"