@payloadcms/ui 4.0.0-canary.33 → 4.0.0-canary.35

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 (160) hide show
  1. package/dist/elements/APIKeyInput/index.d.ts +2 -0
  2. package/dist/elements/APIKeyInput/index.d.ts.map +1 -1
  3. package/dist/elements/APIKeyInput/index.js +27 -29
  4. package/dist/elements/APIKeyInput/index.js.map +1 -1
  5. package/dist/elements/BulkUpload/FormsManager/createFormData.d.ts +1 -1
  6. package/dist/elements/BulkUpload/FormsManager/createFormData.d.ts.map +1 -1
  7. package/dist/elements/BulkUpload/FormsManager/createFormData.js +7 -3
  8. package/dist/elements/BulkUpload/FormsManager/createFormData.js.map +1 -1
  9. package/dist/elements/BulkUpload/FormsManager/index.d.ts.map +1 -1
  10. package/dist/elements/BulkUpload/FormsManager/index.js +4 -2
  11. package/dist/elements/BulkUpload/FormsManager/index.js.map +1 -1
  12. package/dist/elements/DocumentHeader/Tabs/Tab/index.d.ts +1 -0
  13. package/dist/elements/DocumentHeader/Tabs/Tab/index.d.ts.map +1 -1
  14. package/dist/elements/DocumentHeader/Tabs/Tab/index.js +3 -2
  15. package/dist/elements/DocumentHeader/Tabs/Tab/index.js.map +1 -1
  16. package/dist/elements/DocumentHeader/Tabs/index.d.ts +1 -0
  17. package/dist/elements/DocumentHeader/Tabs/index.d.ts.map +1 -1
  18. package/dist/elements/DocumentHeader/Tabs/index.js +5 -3
  19. package/dist/elements/DocumentHeader/Tabs/index.js.map +1 -1
  20. package/dist/elements/DocumentHeader/index.d.ts +1 -0
  21. package/dist/elements/DocumentHeader/index.d.ts.map +1 -1
  22. package/dist/elements/DocumentHeader/index.js +4 -2
  23. package/dist/elements/DocumentHeader/index.js.map +1 -1
  24. package/dist/elements/Nav/SidebarTabs/renderTabServerFn.js +3 -2
  25. package/dist/elements/Nav/SidebarTabs/renderTabServerFn.js.map +1 -1
  26. package/dist/elements/QueryPresets/QueryPresetBar/index.d.ts.map +1 -1
  27. package/dist/elements/QueryPresets/QueryPresetBar/index.js +14 -1
  28. package/dist/elements/QueryPresets/QueryPresetBar/index.js.map +1 -1
  29. package/dist/forms/Form/context.d.ts +3 -1
  30. package/dist/forms/Form/context.d.ts.map +1 -1
  31. package/dist/forms/Form/context.js +3 -1
  32. package/dist/forms/Form/context.js.map +1 -1
  33. package/dist/forms/Form/index.d.ts.map +1 -1
  34. package/dist/forms/Form/index.js +13 -4
  35. package/dist/forms/Form/index.js.map +1 -1
  36. package/dist/forms/fieldSchemasToFormState/renderField.d.ts.map +1 -1
  37. package/dist/forms/fieldSchemasToFormState/renderField.js +3 -2
  38. package/dist/forms/fieldSchemasToFormState/renderField.js.map +1 -1
  39. package/dist/forms/fieldSchemasToFormState/serverFunctions/mergeAllowedFieldOverrides.d.ts +12 -0
  40. package/dist/forms/fieldSchemasToFormState/serverFunctions/mergeAllowedFieldOverrides.d.ts.map +1 -0
  41. package/dist/forms/fieldSchemasToFormState/serverFunctions/mergeAllowedFieldOverrides.js +42 -0
  42. package/dist/forms/fieldSchemasToFormState/serverFunctions/mergeAllowedFieldOverrides.js.map +1 -0
  43. package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.d.ts +8 -6
  44. package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.d.ts.map +1 -1
  45. package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.js +22 -9
  46. package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.js.map +1 -1
  47. package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.spec.js +150 -0
  48. package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.spec.js.map +1 -0
  49. package/dist/forms/fieldSchemasToFormState/types.d.ts +1 -0
  50. package/dist/forms/fieldSchemasToFormState/types.d.ts.map +1 -1
  51. package/dist/forms/fieldSchemasToFormState/types.js.map +1 -1
  52. package/dist/layouts/Root/index.js +6 -5
  53. package/dist/layouts/Root/index.js.map +1 -1
  54. package/dist/providers/LivePreview/index.d.ts.map +1 -1
  55. package/dist/providers/LivePreview/index.js +13 -6
  56. package/dist/providers/LivePreview/index.js.map +1 -1
  57. package/dist/styles.css +1 -1
  58. package/dist/utilities/buildFormState.d.ts.map +1 -1
  59. package/dist/utilities/buildFormState.js +6 -2
  60. package/dist/utilities/buildFormState.js.map +1 -1
  61. package/dist/utilities/formatAbsoluteURL.d.ts +1 -1
  62. package/dist/utilities/formatAbsoluteURL.d.ts.map +1 -1
  63. package/dist/utilities/formatAbsoluteURL.js +18 -8
  64. package/dist/utilities/formatAbsoluteURL.js.map +1 -1
  65. package/dist/utilities/formatAbsoluteURL.spec.js +27 -0
  66. package/dist/utilities/formatAbsoluteURL.spec.js.map +1 -0
  67. package/dist/utilities/handleServerFunctions.d.ts.map +1 -1
  68. package/dist/utilities/handleServerFunctions.js +4 -2
  69. package/dist/utilities/handleServerFunctions.js.map +1 -1
  70. package/dist/utilities/initReq.d.ts.map +1 -1
  71. package/dist/utilities/initReq.js +40 -5
  72. package/dist/utilities/initReq.js.map +1 -1
  73. package/dist/utilities/initReq.spec.js +226 -0
  74. package/dist/utilities/initReq.spec.js.map +1 -0
  75. package/dist/utilities/isAbsoluteURL.d.ts +3 -0
  76. package/dist/utilities/isAbsoluteURL.d.ts.map +1 -0
  77. package/dist/utilities/isAbsoluteURL.js +15 -0
  78. package/dist/utilities/isAbsoluteURL.js.map +1 -0
  79. package/dist/utilities/isAbsoluteURL.spec.js +11 -0
  80. package/dist/utilities/isAbsoluteURL.spec.js.map +1 -0
  81. package/dist/utilities/isHttpURL.d.ts +3 -0
  82. package/dist/utilities/isHttpURL.d.ts.map +1 -0
  83. package/dist/utilities/isHttpURL.js +12 -0
  84. package/dist/utilities/isHttpURL.js.map +1 -0
  85. package/dist/utilities/isHttpURL.spec.js +25 -0
  86. package/dist/utilities/isHttpURL.spec.js.map +1 -0
  87. package/dist/utilities/isPublicAdminRoute.d.ts.map +1 -1
  88. package/dist/utilities/isPublicAdminRoute.js +9 -6
  89. package/dist/utilities/isPublicAdminRoute.js.map +1 -1
  90. package/dist/utilities/isPublicAdminRoute.spec.js +34 -0
  91. package/dist/utilities/isPublicAdminRoute.spec.js.map +1 -0
  92. package/dist/utilities/schedulePublishHandler.d.ts.map +1 -1
  93. package/dist/utilities/schedulePublishHandler.js +4 -1
  94. package/dist/utilities/schedulePublishHandler.js.map +1 -1
  95. package/dist/views/Account/index.d.ts +1 -1
  96. package/dist/views/Account/index.d.ts.map +1 -1
  97. package/dist/views/Account/index.js +8 -5
  98. package/dist/views/Account/index.js.map +1 -1
  99. package/dist/views/Dashboard/Default/ModularDashboard/index.d.ts.map +1 -1
  100. package/dist/views/Dashboard/Default/ModularDashboard/index.js +1 -0
  101. package/dist/views/Dashboard/Default/ModularDashboard/index.js.map +1 -1
  102. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/getDefaultLayoutServerFn.d.ts.map +1 -1
  103. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/getDefaultLayoutServerFn.js +3 -1
  104. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/getDefaultLayoutServerFn.js.map +1 -1
  105. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/renderWidgetServerFn.d.ts.map +1 -1
  106. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/renderWidgetServerFn.js +2 -0
  107. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/renderWidgetServerFn.js.map +1 -1
  108. package/dist/views/Dashboard/index.d.ts.map +1 -1
  109. package/dist/views/Dashboard/index.js +2 -3
  110. package/dist/views/Dashboard/index.js.map +1 -1
  111. package/dist/views/Document/handleServerFunction.d.ts.map +1 -1
  112. package/dist/views/Document/handleServerFunction.js +2 -0
  113. package/dist/views/Document/handleServerFunction.js.map +1 -1
  114. package/dist/views/Document/index.d.ts +1 -1
  115. package/dist/views/Document/index.d.ts.map +1 -1
  116. package/dist/views/Document/index.js +9 -4
  117. package/dist/views/Document/index.js.map +1 -1
  118. package/dist/views/Document/renderDocumentSlots.d.ts +1 -0
  119. package/dist/views/Document/renderDocumentSlots.d.ts.map +1 -1
  120. package/dist/views/Document/renderDocumentSlots.js +7 -4
  121. package/dist/views/Document/renderDocumentSlots.js.map +1 -1
  122. package/dist/views/Edit/Auth/APIKey.d.ts +1 -1
  123. package/dist/views/Edit/Auth/APIKey.d.ts.map +1 -1
  124. package/dist/views/Edit/Auth/APIKey.js +233 -59
  125. package/dist/views/Edit/Auth/APIKey.js.map +1 -1
  126. package/dist/views/Edit/Auth/APIKeyGenerationModal.d.ts +12 -0
  127. package/dist/views/Edit/Auth/APIKeyGenerationModal.d.ts.map +1 -0
  128. package/dist/views/Edit/Auth/APIKeyGenerationModal.js +117 -0
  129. package/dist/views/Edit/Auth/APIKeyGenerationModal.js.map +1 -0
  130. package/dist/views/Edit/Auth/index.css +91 -0
  131. package/dist/views/Edit/Auth/index.d.ts.map +1 -1
  132. package/dist/views/Edit/Auth/index.js +10 -28
  133. package/dist/views/Edit/Auth/index.js.map +1 -1
  134. package/dist/views/Edit/Auth/types.d.ts +3 -1
  135. package/dist/views/Edit/Auth/types.d.ts.map +1 -1
  136. package/dist/views/Edit/Auth/types.js.map +1 -1
  137. package/dist/views/ForgotPassword/ForgotPasswordForm/index.css +14 -0
  138. package/dist/views/ForgotPassword/ForgotPasswordForm/index.d.ts.map +1 -1
  139. package/dist/views/ForgotPassword/ForgotPasswordForm/index.js +209 -161
  140. package/dist/views/ForgotPassword/ForgotPasswordForm/index.js.map +1 -1
  141. package/dist/views/ForgotPassword/index.d.ts.map +1 -1
  142. package/dist/views/ForgotPassword/index.js +2 -11
  143. package/dist/views/ForgotPassword/index.js.map +1 -1
  144. package/dist/views/List/handleServerFunction.d.ts.map +1 -1
  145. package/dist/views/List/handleServerFunction.js +3 -1
  146. package/dist/views/List/handleServerFunction.js.map +1 -1
  147. package/dist/views/List/index.d.ts.map +1 -1
  148. package/dist/views/List/index.js +2 -1
  149. package/dist/views/List/index.js.map +1 -1
  150. package/dist/views/NotFound/page.d.ts.map +1 -1
  151. package/dist/views/NotFound/page.js +4 -3
  152. package/dist/views/NotFound/page.js.map +1 -1
  153. package/dist/views/Root/index.d.ts.map +1 -1
  154. package/dist/views/Root/index.js +5 -3
  155. package/dist/views/Root/index.js.map +1 -1
  156. package/dist/views/Verify/index.d.ts +1 -1
  157. package/dist/views/Verify/index.d.ts.map +1 -1
  158. package/dist/views/Verify/index.js +4 -4
  159. package/dist/views/Verify/index.js.map +1 -1
  160. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"buildFormState.d.ts","sourceRoot":"","sources":["../../src/utilities/buildFormState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,SAAS,EACT,cAAc,EACd,IAAI,EACL,MAAM,SAAS,CAAA;AAehB,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,gBAAgB,EAAE,MAAM,CAAA;IACxB,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,KAAK,2BAA2B,GAAG;IACjC,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,MAAM,CAAC,EAAE,KAAK,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,KAAK,yBAAyB,GAAG;IAC/B,cAAc,CAAC,EAAE,KAAK,CAAA;IACtB,WAAW,CAAC,EAAE,KAAK,CAAA;IACnB,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,cAAc,CAAC,EAAE,KAAK,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,GAAG,CACA;IACE,OAAO,EAAE,MAAM,CAAA;CAChB,GACD,WAAW,CACd,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,yBAAyB,GAAG,2BAA2B,CAAA;AAE1F,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAChD,kBAAkB,EAClB,OAAO,CAAC,oBAAoB,CAAC,CAwB9B,CAAA;AAED,eAAO,MAAM,cAAc,SACnB,kBAAkB,KACvB,OAAO,CAAC,2BAA2B,CAuNrC,CAAA"}
1
+ {"version":3,"file":"buildFormState.d.ts","sourceRoot":"","sources":["../../src/utilities/buildFormState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,SAAS,EACT,cAAc,EACd,IAAI,EACL,MAAM,SAAS,CAAA;AAehB,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,gBAAgB,EAAE,MAAM,CAAA;IACxB,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,KAAK,2BAA2B,GAAG;IACjC,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,MAAM,CAAC,EAAE,KAAK,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,KAAK,yBAAyB,GAAG;IAC/B,cAAc,CAAC,EAAE,KAAK,CAAA;IACtB,WAAW,CAAC,EAAE,KAAK,CAAA;IACnB,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,cAAc,CAAC,EAAE,KAAK,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,GAAG,CACA;IACE,OAAO,EAAE,MAAM,CAAA;CAChB,GACD,WAAW,CACd,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,yBAAyB,GAAG,2BAA2B,CAAA;AAE1F,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAChD,kBAAkB,EAClB,OAAO,CAAC,oBAAoB,CAAC,CAwB9B,CAAA;AAED,eAAO,MAAM,cAAc,SACnB,kBAAkB,KACvB,OAAO,CAAC,2BAA2B,CAwNrC,CAAA"}
@@ -69,7 +69,8 @@ export const buildFormState = async args => {
69
69
  select,
70
70
  skipClientConfigAuth,
71
71
  skipValidation,
72
- updateLastEdited
72
+ updateLastEdited,
73
+ user
73
74
  } = args;
74
75
  const selectMode = select ? getSelectMode(select) : undefined;
75
76
  if (!collectionSlug && !globalSlug && !widgetSlug) {
@@ -149,7 +150,10 @@ export const buildFormState = async args => {
149
150
  previousFormState: formState,
150
151
  readOnly,
151
152
  renderAllFields,
152
- renderFieldFn: renderField,
153
+ renderFieldFn: args => renderField({
154
+ ...args,
155
+ user
156
+ }),
153
157
  req,
154
158
  schemaPath,
155
159
  select,
@@ -1 +1 @@
1
- {"version":3,"file":"buildFormState.js","names":["canAccessAdmin","formatErrors","UnauthorizedError","getSelectMode","reduceFieldsToValues","fieldSchemasToFormState","renderField","getClientConfig","getClientSchemaMap","getSchemaMap","handleFormStateLocking","handleLivePreview","handlePreview","handleStaleDataCheck","buildFormStateHandler","args","req","res","buildFormState","err","payload","logger","error","msg","message","id","idFromArgs","checkForStaleData","collectionSlug","data","incomingData","docPermissions","docPreferences","documentFormState","formState","globalSlug","initialBlockData","initialBlockFormState","mockRSCs","operation","originalUpdatedAt","readOnly","renderAllFields","i18n","config","returnLivePreviewURL","returnLockStatus","returnPreviewURL","widgetSlug","schemaPath","select","skipClientConfigAuth","skipValidation","updateLastEdited","selectMode","undefined","Error","schemaMap","clientSchemaMap","importMap","user","fieldOrEntityConfig","get","fields","length","type","documentData","blockData","Array","isArray","formStateResult","clientFieldSchemaMap","fieldSchemaMap","permissions","preferences","previousFormState","renderFieldFn","collections","upload","file","lockedStateResult","staleDataStateResult","lockedState","staleDataState","state","livePreviewURL","previewURL"],"sources":["../../src/utilities/buildFormState.ts"],"sourcesContent":["import type {\n BuildFormStateArgs,\n ClientConfig,\n ErrorResult,\n FormState,\n ServerFunction,\n User,\n} from 'payload'\n\nimport { canAccessAdmin, formatErrors, UnauthorizedError } from 'payload'\nimport { getSelectMode, reduceFieldsToValues } from 'payload/shared'\n\nimport { fieldSchemasToFormState } from '../forms/fieldSchemasToFormState/index.js'\nimport { renderField } from '../forms/fieldSchemasToFormState/renderField.js'\nimport { getClientConfig } from './getClientConfig.js'\nimport { getClientSchemaMap } from './getClientSchemaMap.js'\nimport { getSchemaMap } from './getSchemaMap.js'\nimport { handleFormStateLocking } from './handleFormStateLocking.js'\nimport { handleLivePreview } from './handleLivePreview.js'\nimport { handlePreview } from './handlePreview.js'\nimport { handleStaleDataCheck } from './handleStaleDataCheck.js'\n\nexport type LockedState = {\n isLocked: boolean\n lastEditedAt: string\n user?: number | string | User\n}\n\nexport type StaleDataState = {\n currentUpdatedAt: string\n isStale: boolean\n}\n\ntype BuildFormStateSuccessResult = {\n clientConfig?: ClientConfig\n errors?: never\n indexPath?: string\n livePreviewURL?: string\n lockedState?: LockedState\n previewURL?: string\n staleDataState?: StaleDataState\n state: FormState\n}\n\ntype BuildFormStateErrorResult = {\n livePreviewURL?: never\n lockedState?: never\n previewURL?: never\n staleDataState?: never\n state?: never\n} & (\n | {\n message: string\n }\n | ErrorResult\n)\n\nexport type BuildFormStateResult = BuildFormStateErrorResult | BuildFormStateSuccessResult\n\nexport const buildFormStateHandler: ServerFunction<\n BuildFormStateArgs,\n Promise<BuildFormStateResult>\n> = async (args) => {\n const { req } = args\n\n try {\n await canAccessAdmin({ req })\n const res = await buildFormState(args)\n\n return res\n } catch (err) {\n req.payload.logger.error({ err, msg: `There was an error building form state` })\n\n if (err.message === 'Could not find field schema for given path') {\n return {\n message: err.message,\n }\n }\n\n if (err.message === 'Unauthorized') {\n throw new UnauthorizedError()\n }\n\n return formatErrors(err)\n }\n}\n\nexport const buildFormState = async (\n args: BuildFormStateArgs,\n): Promise<BuildFormStateSuccessResult> => {\n const {\n id: idFromArgs,\n checkForStaleData,\n collectionSlug,\n data: incomingData,\n docPermissions,\n docPreferences,\n documentFormState,\n formState,\n globalSlug,\n initialBlockData,\n initialBlockFormState,\n mockRSCs,\n operation,\n originalUpdatedAt,\n readOnly,\n renderAllFields,\n req,\n req: {\n i18n,\n payload,\n payload: { config },\n },\n returnLivePreviewURL,\n returnLockStatus,\n returnPreviewURL,\n widgetSlug,\n schemaPath = collectionSlug || globalSlug || widgetSlug,\n select,\n skipClientConfigAuth,\n skipValidation,\n updateLastEdited,\n } = args\n\n const selectMode = select ? getSelectMode(select) : undefined\n\n if (!collectionSlug && !globalSlug && !widgetSlug) {\n throw new Error('Either collectionSlug, globalSlug, or widgetSlug must be provided')\n }\n\n const schemaMap = getSchemaMap({\n collectionSlug,\n config,\n globalSlug,\n i18n,\n widgetSlug,\n })\n\n const clientSchemaMap = getClientSchemaMap({\n collectionSlug,\n config: getClientConfig({\n config,\n i18n,\n importMap: req.payload.importMap,\n user: skipClientConfigAuth ? true : req.user,\n }),\n globalSlug,\n i18n,\n payload,\n schemaMap,\n widgetSlug,\n })\n\n const id = collectionSlug ? idFromArgs : undefined\n const fieldOrEntityConfig = schemaMap.get(schemaPath)\n\n if (!fieldOrEntityConfig) {\n throw new Error(`Could not find \"${schemaPath}\" in the fieldSchemaMap`)\n }\n\n if (\n (!('fields' in fieldOrEntityConfig) ||\n !fieldOrEntityConfig.fields ||\n !fieldOrEntityConfig.fields.length) &&\n 'type' in fieldOrEntityConfig &&\n fieldOrEntityConfig.type !== 'blocks'\n ) {\n throw new Error(\n `The field found in fieldSchemaMap for \"${schemaPath}\" does not contain any subfields.`,\n )\n }\n\n // If there is form state but no data, deduce data from that form state, e.g. on initial load\n // Otherwise, use the incoming data as the source of truth, e.g. on subsequent saves\n const data = incomingData || reduceFieldsToValues(formState, true)\n\n let documentData = undefined\n\n if (documentFormState) {\n documentData = reduceFieldsToValues(documentFormState, true)\n }\n\n let blockData = initialBlockData\n\n if (initialBlockFormState) {\n blockData = reduceFieldsToValues(initialBlockFormState, true)\n }\n\n /**\n * When building state for sub schemas we need to adjust:\n * - `fields`\n * - `parentSchemaPath`\n * - `parentPath`\n *\n * Type assertion is fine because we wrap sub schemas in an array\n * so we can safely map over them within `fieldSchemasToFormState`\n */\n const fields = Array.isArray(fieldOrEntityConfig)\n ? fieldOrEntityConfig\n : 'fields' in fieldOrEntityConfig\n ? fieldOrEntityConfig.fields\n : [fieldOrEntityConfig]\n\n // Ensure data.id is present during form state requests, where the data\n // is passed from the client as an argument, without the ID\n if (!data.id && id) {\n data.id = id\n }\n\n const formStateResult = await fieldSchemasToFormState({\n id,\n clientFieldSchemaMap: clientSchemaMap,\n collectionSlug,\n data,\n documentData,\n fields,\n fieldSchemaMap: schemaMap,\n globalSlug,\n initialBlockData: blockData,\n mockRSCs,\n operation,\n permissions: docPermissions?.fields || {},\n preferences: docPreferences || { fields: {} },\n previousFormState: formState,\n readOnly,\n renderAllFields,\n renderFieldFn: renderField,\n req,\n schemaPath,\n select,\n selectMode,\n skipValidation,\n })\n\n // Maintain form state of auth / upload fields\n if (collectionSlug && formState) {\n if (payload.collections[collectionSlug]?.config?.upload && formState.file) {\n formStateResult.file = formState.file\n }\n }\n\n let lockedStateResult: LockedState | undefined\n\n if (returnLockStatus) {\n lockedStateResult = await handleFormStateLocking({\n id,\n collectionSlug,\n globalSlug,\n req,\n updateLastEdited,\n })\n }\n\n let staleDataStateResult: StaleDataState | undefined\n\n if (checkForStaleData && originalUpdatedAt && ((collectionSlug && id) || globalSlug)) {\n staleDataStateResult = await handleStaleDataCheck({\n id,\n collectionSlug,\n globalSlug,\n originalUpdatedAt,\n req,\n })\n }\n\n const res: BuildFormStateSuccessResult = {\n lockedState: lockedStateResult,\n staleDataState: staleDataStateResult,\n state: formStateResult,\n }\n\n if (returnLivePreviewURL) {\n const { livePreviewURL } = await handleLivePreview({\n collectionSlug,\n config,\n data,\n globalSlug,\n req,\n })\n\n // Important: only set this when not undefined,\n // Otherwise it will travel through the network as `$undefined`\n if (livePreviewURL) {\n res.livePreviewURL = livePreviewURL\n }\n }\n\n if (returnPreviewURL) {\n const { previewURL } = await handlePreview({\n collectionSlug,\n config,\n data,\n globalSlug,\n req,\n })\n\n // Important: only set this when not undefined,\n // Otherwise it will travel through the network as `$undefined`\n if (previewURL) {\n res.previewURL = previewURL\n }\n }\n\n return res\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"buildFormState.js","names":["canAccessAdmin","formatErrors","UnauthorizedError","getSelectMode","reduceFieldsToValues","fieldSchemasToFormState","renderField","getClientConfig","getClientSchemaMap","getSchemaMap","handleFormStateLocking","handleLivePreview","handlePreview","handleStaleDataCheck","buildFormStateHandler","args","req","res","buildFormState","err","payload","logger","error","msg","message","id","idFromArgs","checkForStaleData","collectionSlug","data","incomingData","docPermissions","docPreferences","documentFormState","formState","globalSlug","initialBlockData","initialBlockFormState","mockRSCs","operation","originalUpdatedAt","readOnly","renderAllFields","i18n","config","returnLivePreviewURL","returnLockStatus","returnPreviewURL","widgetSlug","schemaPath","select","skipClientConfigAuth","skipValidation","updateLastEdited","user","selectMode","undefined","Error","schemaMap","clientSchemaMap","importMap","fieldOrEntityConfig","get","fields","length","type","documentData","blockData","Array","isArray","formStateResult","clientFieldSchemaMap","fieldSchemaMap","permissions","preferences","previousFormState","renderFieldFn","collections","upload","file","lockedStateResult","staleDataStateResult","lockedState","staleDataState","state","livePreviewURL","previewURL"],"sources":["../../src/utilities/buildFormState.ts"],"sourcesContent":["import type {\n BuildFormStateArgs,\n ClientConfig,\n ErrorResult,\n FormState,\n ServerFunction,\n User,\n} from 'payload'\n\nimport { canAccessAdmin, formatErrors, UnauthorizedError } from 'payload'\nimport { getSelectMode, reduceFieldsToValues } from 'payload/shared'\n\nimport { fieldSchemasToFormState } from '../forms/fieldSchemasToFormState/index.js'\nimport { renderField } from '../forms/fieldSchemasToFormState/renderField.js'\nimport { getClientConfig } from './getClientConfig.js'\nimport { getClientSchemaMap } from './getClientSchemaMap.js'\nimport { getSchemaMap } from './getSchemaMap.js'\nimport { handleFormStateLocking } from './handleFormStateLocking.js'\nimport { handleLivePreview } from './handleLivePreview.js'\nimport { handlePreview } from './handlePreview.js'\nimport { handleStaleDataCheck } from './handleStaleDataCheck.js'\n\nexport type LockedState = {\n isLocked: boolean\n lastEditedAt: string\n user?: number | string | User\n}\n\nexport type StaleDataState = {\n currentUpdatedAt: string\n isStale: boolean\n}\n\ntype BuildFormStateSuccessResult = {\n clientConfig?: ClientConfig\n errors?: never\n indexPath?: string\n livePreviewURL?: string\n lockedState?: LockedState\n previewURL?: string\n staleDataState?: StaleDataState\n state: FormState\n}\n\ntype BuildFormStateErrorResult = {\n livePreviewURL?: never\n lockedState?: never\n previewURL?: never\n staleDataState?: never\n state?: never\n} & (\n | {\n message: string\n }\n | ErrorResult\n)\n\nexport type BuildFormStateResult = BuildFormStateErrorResult | BuildFormStateSuccessResult\n\nexport const buildFormStateHandler: ServerFunction<\n BuildFormStateArgs,\n Promise<BuildFormStateResult>\n> = async (args) => {\n const { req } = args\n\n try {\n await canAccessAdmin({ req })\n const res = await buildFormState(args)\n\n return res\n } catch (err) {\n req.payload.logger.error({ err, msg: `There was an error building form state` })\n\n if (err.message === 'Could not find field schema for given path') {\n return {\n message: err.message,\n }\n }\n\n if (err.message === 'Unauthorized') {\n throw new UnauthorizedError()\n }\n\n return formatErrors(err)\n }\n}\n\nexport const buildFormState = async (\n args: BuildFormStateArgs,\n): Promise<BuildFormStateSuccessResult> => {\n const {\n id: idFromArgs,\n checkForStaleData,\n collectionSlug,\n data: incomingData,\n docPermissions,\n docPreferences,\n documentFormState,\n formState,\n globalSlug,\n initialBlockData,\n initialBlockFormState,\n mockRSCs,\n operation,\n originalUpdatedAt,\n readOnly,\n renderAllFields,\n req,\n req: {\n i18n,\n payload,\n payload: { config },\n },\n returnLivePreviewURL,\n returnLockStatus,\n returnPreviewURL,\n widgetSlug,\n schemaPath = collectionSlug || globalSlug || widgetSlug,\n select,\n skipClientConfigAuth,\n skipValidation,\n updateLastEdited,\n user,\n } = args\n\n const selectMode = select ? getSelectMode(select) : undefined\n\n if (!collectionSlug && !globalSlug && !widgetSlug) {\n throw new Error('Either collectionSlug, globalSlug, or widgetSlug must be provided')\n }\n\n const schemaMap = getSchemaMap({\n collectionSlug,\n config,\n globalSlug,\n i18n,\n widgetSlug,\n })\n\n const clientSchemaMap = getClientSchemaMap({\n collectionSlug,\n config: getClientConfig({\n config,\n i18n,\n importMap: req.payload.importMap,\n user: skipClientConfigAuth ? true : req.user,\n }),\n globalSlug,\n i18n,\n payload,\n schemaMap,\n widgetSlug,\n })\n\n const id = collectionSlug ? idFromArgs : undefined\n const fieldOrEntityConfig = schemaMap.get(schemaPath)\n\n if (!fieldOrEntityConfig) {\n throw new Error(`Could not find \"${schemaPath}\" in the fieldSchemaMap`)\n }\n\n if (\n (!('fields' in fieldOrEntityConfig) ||\n !fieldOrEntityConfig.fields ||\n !fieldOrEntityConfig.fields.length) &&\n 'type' in fieldOrEntityConfig &&\n fieldOrEntityConfig.type !== 'blocks'\n ) {\n throw new Error(\n `The field found in fieldSchemaMap for \"${schemaPath}\" does not contain any subfields.`,\n )\n }\n\n // If there is form state but no data, deduce data from that form state, e.g. on initial load\n // Otherwise, use the incoming data as the source of truth, e.g. on subsequent saves\n const data = incomingData || reduceFieldsToValues(formState, true)\n\n let documentData = undefined\n\n if (documentFormState) {\n documentData = reduceFieldsToValues(documentFormState, true)\n }\n\n let blockData = initialBlockData\n\n if (initialBlockFormState) {\n blockData = reduceFieldsToValues(initialBlockFormState, true)\n }\n\n /**\n * When building state for sub schemas we need to adjust:\n * - `fields`\n * - `parentSchemaPath`\n * - `parentPath`\n *\n * Type assertion is fine because we wrap sub schemas in an array\n * so we can safely map over them within `fieldSchemasToFormState`\n */\n const fields = Array.isArray(fieldOrEntityConfig)\n ? fieldOrEntityConfig\n : 'fields' in fieldOrEntityConfig\n ? fieldOrEntityConfig.fields\n : [fieldOrEntityConfig]\n\n // Ensure data.id is present during form state requests, where the data\n // is passed from the client as an argument, without the ID\n if (!data.id && id) {\n data.id = id\n }\n\n const formStateResult = await fieldSchemasToFormState({\n id,\n clientFieldSchemaMap: clientSchemaMap,\n collectionSlug,\n data,\n documentData,\n fields,\n fieldSchemaMap: schemaMap,\n globalSlug,\n initialBlockData: blockData,\n mockRSCs,\n operation,\n permissions: docPermissions?.fields || {},\n preferences: docPreferences || { fields: {} },\n previousFormState: formState,\n readOnly,\n renderAllFields,\n renderFieldFn: (args) => renderField({ ...args, user }),\n req,\n schemaPath,\n select,\n selectMode,\n skipValidation,\n })\n\n // Maintain form state of auth / upload fields\n if (collectionSlug && formState) {\n if (payload.collections[collectionSlug]?.config?.upload && formState.file) {\n formStateResult.file = formState.file\n }\n }\n\n let lockedStateResult: LockedState | undefined\n\n if (returnLockStatus) {\n lockedStateResult = await handleFormStateLocking({\n id,\n collectionSlug,\n globalSlug,\n req,\n updateLastEdited,\n })\n }\n\n let staleDataStateResult: StaleDataState | undefined\n\n if (checkForStaleData && originalUpdatedAt && ((collectionSlug && id) || globalSlug)) {\n staleDataStateResult = await handleStaleDataCheck({\n id,\n collectionSlug,\n globalSlug,\n originalUpdatedAt,\n req,\n })\n }\n\n const res: BuildFormStateSuccessResult = {\n lockedState: lockedStateResult,\n staleDataState: staleDataStateResult,\n state: formStateResult,\n }\n\n if (returnLivePreviewURL) {\n const { livePreviewURL } = await handleLivePreview({\n collectionSlug,\n config,\n data,\n globalSlug,\n req,\n })\n\n // Important: only set this when not undefined,\n // Otherwise it will travel through the network as `$undefined`\n if (livePreviewURL) {\n res.livePreviewURL = livePreviewURL\n }\n }\n\n if (returnPreviewURL) {\n const { previewURL } = await handlePreview({\n collectionSlug,\n config,\n data,\n globalSlug,\n req,\n })\n\n // Important: only set this when not undefined,\n // Otherwise it will travel through the network as `$undefined`\n if (previewURL) {\n res.previewURL = previewURL\n }\n }\n\n return res\n}\n"],"mappings":"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","ignoreList":[]}
@@ -4,5 +4,5 @@
4
4
  * Note: This MUST be called within the client environment as it relies on the `window` object
5
5
  * to determine the absolute URL.
6
6
  */
7
- export declare const formatAbsoluteURL: (incomingURL: string) => any;
7
+ export declare const formatAbsoluteURL: (incomingURL: string) => string | undefined;
8
8
  //# sourceMappingURL=formatAbsoluteURL.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"formatAbsoluteURL.d.ts","sourceRoot":"","sources":["../../src/utilities/formatAbsoluteURL.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,gBAAiB,MAAM,QAGpB,CAAA"}
1
+ {"version":3,"file":"formatAbsoluteURL.d.ts","sourceRoot":"","sources":["../../src/utilities/formatAbsoluteURL.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,gBAAiB,MAAM,KAAG,MAAM,GAAG,SAmBhE,CAAA"}
@@ -1,15 +1,25 @@
1
- const getAbsoluteUrl = url => {
2
- try {
3
- return new URL(url, window.location.origin).href;
4
- } catch {
5
- return url;
6
- }
7
- };
1
+ import { isHttpURL } from './isHttpURL.js';
8
2
  /**
9
3
  * Ensures the provided URL is absolute. If not, it converts it to an absolute URL based
10
4
  * on the current window location.
11
5
  * Note: This MUST be called within the client environment as it relies on the `window` object
12
6
  * to determine the absolute URL.
13
7
  */
14
- export const formatAbsoluteURL = incomingURL => incomingURL?.startsWith('http://') || incomingURL?.startsWith('https://') ? incomingURL : getAbsoluteUrl(incomingURL);
8
+ export const formatAbsoluteURL = incomingURL => {
9
+ try {
10
+ // This throws for malformed URLs, e.g. `https://[wrong`.
11
+ // Preformed absolute URLs ignore `window.location.origin` when parsed.
12
+ const parsedURL = new URL(incomingURL, window.location.origin);
13
+ // If the given URL is already absolute, preserve its original format exactly, i.e. `new URL()` may have added a trailing slash
14
+ if (incomingURL.startsWith('http://') || incomingURL.startsWith('https://')) {
15
+ return incomingURL;
16
+ }
17
+ if (isHttpURL(parsedURL)) {
18
+ return parsedURL.href;
19
+ }
20
+ return undefined;
21
+ } catch {
22
+ return undefined;
23
+ }
24
+ };
15
25
  //# sourceMappingURL=formatAbsoluteURL.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"formatAbsoluteURL.js","names":["getAbsoluteUrl","url","URL","window","location","origin","href","formatAbsoluteURL","incomingURL","startsWith"],"sources":["../../src/utilities/formatAbsoluteURL.ts"],"sourcesContent":["const getAbsoluteUrl = (url) => {\n try {\n return new URL(url, window.location.origin).href\n } catch {\n return url\n }\n}\n\n/**\n * Ensures the provided URL is absolute. If not, it converts it to an absolute URL based\n * on the current window location.\n * Note: This MUST be called within the client environment as it relies on the `window` object\n * to determine the absolute URL.\n */\nexport const formatAbsoluteURL = (incomingURL: string) =>\n incomingURL?.startsWith('http://') || incomingURL?.startsWith('https://')\n ? incomingURL\n : getAbsoluteUrl(incomingURL)\n"],"mappings":"AAAA,MAAMA,cAAA,GAAkBC,GAAA;EACtB,IAAI;IACF,OAAO,IAAIC,GAAA,CAAID,GAAA,EAAKE,MAAA,CAAOC,QAAQ,CAACC,MAAM,EAAEC,IAAI;EAClD,EAAE,MAAM;IACN,OAAOL,GAAA;EACT;AACF;AAEA;;;;;;AAMA,OAAO,MAAMM,iBAAA,GAAqBC,WAAA,IAChCA,WAAA,EAAaC,UAAA,CAAW,cAAcD,WAAA,EAAaC,UAAA,CAAW,cAC1DD,WAAA,GACAR,cAAA,CAAeQ,WAAA","ignoreList":[]}
1
+ {"version":3,"file":"formatAbsoluteURL.js","names":["isHttpURL","formatAbsoluteURL","incomingURL","parsedURL","URL","window","location","origin","startsWith","href","undefined"],"sources":["../../src/utilities/formatAbsoluteURL.ts"],"sourcesContent":["import { isHttpURL } from './isHttpURL.js'\n\n/**\n * Ensures the provided URL is absolute. If not, it converts it to an absolute URL based\n * on the current window location.\n * Note: This MUST be called within the client environment as it relies on the `window` object\n * to determine the absolute URL.\n */\nexport const formatAbsoluteURL = (incomingURL: string): string | undefined => {\n try {\n // This throws for malformed URLs, e.g. `https://[wrong`.\n // Preformed absolute URLs ignore `window.location.origin` when parsed.\n const parsedURL = new URL(incomingURL, window.location.origin)\n\n // If the given URL is already absolute, preserve its original format exactly, i.e. `new URL()` may have added a trailing slash\n if (incomingURL.startsWith('http://') || incomingURL.startsWith('https://')) {\n return incomingURL\n }\n\n if (isHttpURL(parsedURL)) {\n return parsedURL.href\n }\n\n return undefined\n } catch {\n return undefined\n }\n}\n"],"mappings":"AAAA,SAASA,SAAS,QAAQ;AAE1B;;;;;;AAMA,OAAO,MAAMC,iBAAA,GAAqBC,WAAA;EAChC,IAAI;IACF;IACA;IACA,MAAMC,SAAA,GAAY,IAAIC,GAAA,CAAIF,WAAA,EAAaG,MAAA,CAAOC,QAAQ,CAACC,MAAM;IAE7D;IACA,IAAIL,WAAA,CAAYM,UAAU,CAAC,cAAcN,WAAA,CAAYM,UAAU,CAAC,aAAa;MAC3E,OAAON,WAAA;IACT;IAEA,IAAIF,SAAA,CAAUG,SAAA,GAAY;MACxB,OAAOA,SAAA,CAAUM,IAAI;IACvB;IAEA,OAAOC,SAAA;EACT,EAAE,MAAM;IACN,OAAOA,SAAA;EACT;AACF","ignoreList":[]}
@@ -0,0 +1,27 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { formatAbsoluteURL } from './formatAbsoluteURL.js';
3
+ describe('formatAbsoluteURL', () => {
4
+ beforeEach(() => {
5
+ vi.stubGlobal('window', {
6
+ location: {
7
+ origin: 'https://admin.example.com'
8
+ }
9
+ });
10
+ });
11
+ afterEach(() => {
12
+ vi.unstubAllGlobals();
13
+ });
14
+ it.each([['/preview', 'https://admin.example.com/preview'], ['preview?draft=true', 'https://admin.example.com/preview?draft=true'], ['../preview', 'https://admin.example.com/preview'], ['?draft=true', 'https://admin.example.com/?draft=true'], ['#preview', 'https://admin.example.com/#preview'], ['//preview.example.com/page', 'https://preview.example.com/page'], ['', 'https://admin.example.com/']])('should resolve relative URL %s against the admin origin', (input, expected) => {
15
+ expect(formatAbsoluteURL(input)).toBe(expected);
16
+ });
17
+ it.each(['http://preview.example.com', 'https://preview.example.com', 'https://preview.example.com:443/one/../two?draft=true#preview'])('should preserve absolute HTTP(S) URL %s', input => {
18
+ expect(formatAbsoluteURL(input)).toBe(input);
19
+ });
20
+ it.each(['mailto:editor@example.com', 'file:///preview.html'])('should return undefined for unsupported URL %s', input => {
21
+ expect(formatAbsoluteURL(input)).toBeUndefined();
22
+ });
23
+ it.each(['http://', 'https://', 'https://[invalid'])('should return undefined for invalid URL %s', input => {
24
+ expect(formatAbsoluteURL(input)).toBeUndefined();
25
+ });
26
+ });
27
+ //# sourceMappingURL=formatAbsoluteURL.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatAbsoluteURL.spec.js","names":["afterEach","beforeEach","describe","expect","it","vi","formatAbsoluteURL","stubGlobal","location","origin","unstubAllGlobals","each","input","expected","toBe","toBeUndefined"],"sources":["../../src/utilities/formatAbsoluteURL.spec.ts"],"sourcesContent":["import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport { formatAbsoluteURL } from './formatAbsoluteURL.js'\n\ndescribe('formatAbsoluteURL', () => {\n beforeEach(() => {\n vi.stubGlobal('window', {\n location: { origin: 'https://admin.example.com' },\n })\n })\n\n afterEach(() => {\n vi.unstubAllGlobals()\n })\n\n it.each([\n ['/preview', 'https://admin.example.com/preview'],\n ['preview?draft=true', 'https://admin.example.com/preview?draft=true'],\n ['../preview', 'https://admin.example.com/preview'],\n ['?draft=true', 'https://admin.example.com/?draft=true'],\n ['#preview', 'https://admin.example.com/#preview'],\n ['//preview.example.com/page', 'https://preview.example.com/page'],\n ['', 'https://admin.example.com/'],\n ])('should resolve relative URL %s against the admin origin', (input, expected) => {\n expect(formatAbsoluteURL(input)).toBe(expected)\n })\n\n it.each([\n 'http://preview.example.com',\n 'https://preview.example.com',\n 'https://preview.example.com:443/one/../two?draft=true#preview',\n ])('should preserve absolute HTTP(S) URL %s', (input) => {\n expect(formatAbsoluteURL(input)).toBe(input)\n })\n\n it.each(['mailto:editor@example.com', 'file:///preview.html'])(\n 'should return undefined for unsupported URL %s',\n (input) => {\n expect(formatAbsoluteURL(input)).toBeUndefined()\n },\n )\n\n it.each(['http://', 'https://', 'https://[invalid'])(\n 'should return undefined for invalid URL %s',\n (input) => {\n expect(formatAbsoluteURL(input)).toBeUndefined()\n },\n )\n})\n"],"mappings":"AAAA,SAASA,SAAS,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ;AAEhE,SAASC,iBAAiB,QAAQ;AAElCJ,QAAA,CAAS,qBAAqB;EAC5BD,UAAA,CAAW;IACTI,EAAA,CAAGE,UAAU,CAAC,UAAU;MACtBC,QAAA,EAAU;QAAEC,MAAA,EAAQ;MAA4B;IAClD;EACF;EAEAT,SAAA,CAAU;IACRK,EAAA,CAAGK,gBAAgB;EACrB;EAEAN,EAAA,CAAGO,IAAI,CAAC,CACN,CAAC,YAAY,oCAAoC,EACjD,CAAC,sBAAsB,+CAA+C,EACtE,CAAC,cAAc,oCAAoC,EACnD,CAAC,eAAe,wCAAwC,EACxD,CAAC,YAAY,qCAAqC,EAClD,CAAC,8BAA8B,mCAAmC,EAClE,CAAC,IAAI,6BAA6B,CACnC,EAAE,2DAA2D,CAACC,KAAA,EAAOC,QAAA;IACpEV,MAAA,CAAOG,iBAAA,CAAkBM,KAAA,GAAQE,IAAI,CAACD,QAAA;EACxC;EAEAT,EAAA,CAAGO,IAAI,CAAC,CACN,8BACA,+BACA,gEACD,EAAE,2CAA4CC,KAAA;IAC7CT,MAAA,CAAOG,iBAAA,CAAkBM,KAAA,GAAQE,IAAI,CAACF,KAAA;EACxC;EAEAR,EAAA,CAAGO,IAAI,CAAC,CAAC,6BAA6B,uBAAuB,EAC3D,kDACCC,KAAA;IACCT,MAAA,CAAOG,iBAAA,CAAkBM,KAAA,GAAQG,aAAa;EAChD;EAGFX,EAAA,CAAGO,IAAI,CAAC,CAAC,WAAW,YAAY,mBAAmB,EACjD,8CACCC,KAAA;IACCT,MAAA,CAAOG,iBAAA,CAAkBM,KAAA,GAAQG,aAAa;EAChD;AAEJ","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"handleServerFunctions.d.ts","sourceRoot":"","sources":["../../src/utilities/handleServerFunctions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EACT,aAAa,EACb,eAAe,EACf,cAAc,EACd,qBAAqB,EACtB,MAAM,SAAS,CAAA;AAIhB,KAAK,OAAO,GAAG,CAAC,IAAI,EAAE;IACpB,aAAa,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAAA;IACzD,SAAS,EAAE,SAAS,CAAA;CACrB,KAAK,OAAO,CAAC,aAAa,CAAC,CAAA;AAE5B,KAAK,+BAA+B,GAAG;IACrC;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;IAC1D;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;CAClE,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,mDAIrC,+BAA+B,KAAG,qBAmCpC,CAAA"}
1
+ {"version":3,"file":"handleServerFunctions.d.ts","sourceRoot":"","sources":["../../src/utilities/handleServerFunctions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EACT,aAAa,EACb,eAAe,EACf,cAAc,EACd,qBAAqB,EACtB,MAAM,SAAS,CAAA;AAIhB,KAAK,OAAO,GAAG,CAAC,IAAI,EAAE;IACpB,aAAa,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAAA;IACzD,SAAS,EAAE,SAAS,CAAA;CACrB,KAAK,OAAO,CAAC,aAAa,CAAC,CAAA;AAE5B,KAAK,+BAA+B,GAAG;IACrC;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;IAC1D;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;CAClE,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,mDAIrC,+BAA+B,KAAG,qBAoCpC,CAAA"}
@@ -28,7 +28,8 @@ export const createServerFunctionHandler = ({
28
28
  cookies,
29
29
  locale,
30
30
  permissions,
31
- req
31
+ req,
32
+ user
32
33
  } = await initReq({
33
34
  configPromise,
34
35
  importMap
@@ -39,7 +40,8 @@ export const createServerFunctionHandler = ({
39
40
  importMap,
40
41
  locale,
41
42
  permissions,
42
- req
43
+ req,
44
+ user
43
45
  };
44
46
  const fn = extraServerFunctions?.[fnKey] || baseServerFunctions[fnKey];
45
47
  if (!fn) {
@@ -1 +1 @@
1
- {"version":3,"file":"handleServerFunctions.js","names":["sharedServerFunctions","createServerFunctionHandler","initReq","serverFunctions","transformResult","baseServerFunctions","args","name","fnKey","fnArgs","config","configPromise","importMap","extraServerFunctions","cookies","locale","permissions","req","augmentedArgs","fn","Error","result"],"sources":["../../src/utilities/handleServerFunctions.ts"],"sourcesContent":["import type {\n DefaultServerFunctionArgs,\n ImportMap,\n InitReqResult,\n SanitizedConfig,\n ServerFunction,\n ServerFunctionHandler,\n} from 'payload'\n\nimport { sharedServerFunctions } from './serverFunctionRegistry.js'\n\ntype InitReq = (args: {\n configPromise: Promise<SanitizedConfig> | SanitizedConfig\n importMap: ImportMap\n}) => Promise<InitReqResult>\n\ntype CreateServerFunctionHandlerArgs = {\n /**\n * Framework-specific request initialization. The adapter closes over its own\n * `ServerAdapter` / request source (Next.js: `initReq` + `nextServerAdapter`;\n * TanStack Start: its `getRequest()`-based `initReq`).\n */\n initReq: InitReq\n /**\n * Additional handlers registered alongside `sharedServerFunctions`. Reserved\n * for adapter-specific functions; today both adapters run the shared set only.\n */\n serverFunctions?: Record<string, ServerFunction<any, any>>\n /**\n * Post-processes each handler's return value before it goes over the wire.\n * The TanStack Start adapter passes `serializeForRsc` to convert React\n * elements into RSC handles; Next.js ships them natively and omits this.\n */\n transformResult?: (result: unknown) => Promise<unknown> | unknown\n}\n\n/**\n * Factory for the framework-agnostic `handleServerFunctions` entry point.\n *\n * All adapters dispatch from the shared registry (`sharedServerFunctions`) and\n * differ only in the two injected hooks below — `initReq` and `transformResult`\n * — so there is a single dispatch implementation and the handler sets cannot\n * drift between frameworks.\n */\nexport const createServerFunctionHandler = ({\n initReq,\n serverFunctions,\n transformResult,\n}: CreateServerFunctionHandlerArgs): ServerFunctionHandler => {\n const baseServerFunctions: Record<string, ServerFunction<any, any>> = serverFunctions\n ? { ...sharedServerFunctions, ...serverFunctions }\n : sharedServerFunctions\n\n return async (args) => {\n const {\n name: fnKey,\n args: fnArgs,\n config: configPromise,\n importMap,\n serverFunctions: extraServerFunctions,\n } = args\n\n const { cookies, locale, permissions, req } = await initReq({ configPromise, importMap })\n\n const augmentedArgs: DefaultServerFunctionArgs = {\n ...fnArgs,\n cookies,\n importMap,\n locale,\n permissions,\n req,\n }\n\n const fn = extraServerFunctions?.[fnKey] || baseServerFunctions[fnKey]\n\n if (!fn) {\n throw new Error(`Unknown Server Function: ${fnKey}`)\n }\n\n const result = await fn(augmentedArgs)\n\n return transformResult ? await transformResult(result) : result\n }\n}\n"],"mappings":"AASA,SAASA,qBAAqB,QAAQ;AA2BtC;;;;;;;;AAQA,OAAO,MAAMC,2BAAA,GAA8BA,CAAC;EAC1CC,OAAO;EACPC,eAAe;EACfC;AAAe,CACiB;EAChC,MAAMC,mBAAA,GAAgEF,eAAA,GAClE;IAAE,GAAGH,qBAAqB;IAAE,GAAGG;EAAgB,IAC/CH,qBAAA;EAEJ,OAAO,MAAOM,IAAA;IACZ,MAAM;MACJC,IAAA,EAAMC,KAAK;MACXF,IAAA,EAAMG,MAAM;MACZC,MAAA,EAAQC,aAAa;MACrBC,SAAS;MACTT,eAAA,EAAiBU;IAAoB,CACtC,GAAGP,IAAA;IAEJ,MAAM;MAAEQ,OAAO;MAAEC,MAAM;MAAEC,WAAW;MAAEC;IAAG,CAAE,GAAG,MAAMf,OAAA,CAAQ;MAAES,aAAA;MAAeC;IAAU;IAEvF,MAAMM,aAAA,GAA2C;MAC/C,GAAGT,MAAM;MACTK,OAAA;MACAF,SAAA;MACAG,MAAA;MACAC,WAAA;MACAC;IACF;IAEA,MAAME,EAAA,GAAKN,oBAAA,GAAuBL,KAAA,CAAM,IAAIH,mBAAmB,CAACG,KAAA,CAAM;IAEtE,IAAI,CAACW,EAAA,EAAI;MACP,MAAM,IAAIC,KAAA,CAAM,4BAA4BZ,KAAA,EAAO;IACrD;IAEA,MAAMa,MAAA,GAAS,MAAMF,EAAA,CAAGD,aAAA;IAExB,OAAOd,eAAA,GAAkB,MAAMA,eAAA,CAAgBiB,MAAA,IAAUA,MAAA;EAC3D;AACF","ignoreList":[]}
1
+ {"version":3,"file":"handleServerFunctions.js","names":["sharedServerFunctions","createServerFunctionHandler","initReq","serverFunctions","transformResult","baseServerFunctions","args","name","fnKey","fnArgs","config","configPromise","importMap","extraServerFunctions","cookies","locale","permissions","req","user","augmentedArgs","fn","Error","result"],"sources":["../../src/utilities/handleServerFunctions.ts"],"sourcesContent":["import type {\n DefaultServerFunctionArgs,\n ImportMap,\n InitReqResult,\n SanitizedConfig,\n ServerFunction,\n ServerFunctionHandler,\n} from 'payload'\n\nimport { sharedServerFunctions } from './serverFunctionRegistry.js'\n\ntype InitReq = (args: {\n configPromise: Promise<SanitizedConfig> | SanitizedConfig\n importMap: ImportMap\n}) => Promise<InitReqResult>\n\ntype CreateServerFunctionHandlerArgs = {\n /**\n * Framework-specific request initialization. The adapter closes over its own\n * `ServerAdapter` / request source (Next.js: `initReq` + `nextServerAdapter`;\n * TanStack Start: its `getRequest()`-based `initReq`).\n */\n initReq: InitReq\n /**\n * Additional handlers registered alongside `sharedServerFunctions`. Reserved\n * for adapter-specific functions; today both adapters run the shared set only.\n */\n serverFunctions?: Record<string, ServerFunction<any, any>>\n /**\n * Post-processes each handler's return value before it goes over the wire.\n * The TanStack Start adapter passes `serializeForRsc` to convert React\n * elements into RSC handles; Next.js ships them natively and omits this.\n */\n transformResult?: (result: unknown) => Promise<unknown> | unknown\n}\n\n/**\n * Factory for the framework-agnostic `handleServerFunctions` entry point.\n *\n * All adapters dispatch from the shared registry (`sharedServerFunctions`) and\n * differ only in the two injected hooks below — `initReq` and `transformResult`\n * — so there is a single dispatch implementation and the handler sets cannot\n * drift between frameworks.\n */\nexport const createServerFunctionHandler = ({\n initReq,\n serverFunctions,\n transformResult,\n}: CreateServerFunctionHandlerArgs): ServerFunctionHandler => {\n const baseServerFunctions: Record<string, ServerFunction<any, any>> = serverFunctions\n ? { ...sharedServerFunctions, ...serverFunctions }\n : sharedServerFunctions\n\n return async (args) => {\n const {\n name: fnKey,\n args: fnArgs,\n config: configPromise,\n importMap,\n serverFunctions: extraServerFunctions,\n } = args\n\n const { cookies, locale, permissions, req, user } = await initReq({ configPromise, importMap })\n\n const augmentedArgs: DefaultServerFunctionArgs = {\n ...fnArgs,\n cookies,\n importMap,\n locale,\n permissions,\n req,\n user,\n }\n\n const fn = extraServerFunctions?.[fnKey] || baseServerFunctions[fnKey]\n\n if (!fn) {\n throw new Error(`Unknown Server Function: ${fnKey}`)\n }\n\n const result = await fn(augmentedArgs)\n\n return transformResult ? await transformResult(result) : result\n }\n}\n"],"mappings":"AASA,SAASA,qBAAqB,QAAQ;AA2BtC;;;;;;;;AAQA,OAAO,MAAMC,2BAAA,GAA8BA,CAAC;EAC1CC,OAAO;EACPC,eAAe;EACfC;AAAe,CACiB;EAChC,MAAMC,mBAAA,GAAgEF,eAAA,GAClE;IAAE,GAAGH,qBAAqB;IAAE,GAAGG;EAAgB,IAC/CH,qBAAA;EAEJ,OAAO,MAAOM,IAAA;IACZ,MAAM;MACJC,IAAA,EAAMC,KAAK;MACXF,IAAA,EAAMG,MAAM;MACZC,MAAA,EAAQC,aAAa;MACrBC,SAAS;MACTT,eAAA,EAAiBU;IAAoB,CACtC,GAAGP,IAAA;IAEJ,MAAM;MAAEQ,OAAO;MAAEC,MAAM;MAAEC,WAAW;MAAEC,GAAG;MAAEC;IAAI,CAAE,GAAG,MAAMhB,OAAA,CAAQ;MAAES,aAAA;MAAeC;IAAU;IAE7F,MAAMO,aAAA,GAA2C;MAC/C,GAAGV,MAAM;MACTK,OAAA;MACAF,SAAA;MACAG,MAAA;MACAC,WAAA;MACAC,GAAA;MACAC;IACF;IAEA,MAAME,EAAA,GAAKP,oBAAA,GAAuBL,KAAA,CAAM,IAAIH,mBAAmB,CAACG,KAAA,CAAM;IAEtE,IAAI,CAACY,EAAA,EAAI;MACP,MAAM,IAAIC,KAAA,CAAM,4BAA4Bb,KAAA,EAAO;IACrD;IAEA,MAAMc,MAAA,GAAS,MAAMF,EAAA,CAAGD,aAAA;IAExB,OAAOf,eAAA,GAAkB,MAAMA,eAAA,CAAgBkB,MAAA,IAAUA,MAAA;EAC3D;AACF","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"initReq.d.ts","sourceRoot":"","sources":["../../src/utilities/initReq.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EAEb,eAAe,EACf,aAAa,EACd,MAAM,SAAS,CAAA;AAGhB,OAAO,EACL,cAAc,EAMf,MAAM,SAAS,CAAA;AAahB;;;;GAIG;AACH,eAAO,MAAM,OAAO,gFAOjB;IACD,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,aAAa,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAAA;IACzD,SAAS,EAAE,SAAS,CAAA;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;IAChD,aAAa,EAAE,aAAa,CAAA;CAC7B,KAAG,OAAO,CAAC,aAAa,CA2FxB,CAAA"}
1
+ {"version":3,"file":"initReq.d.ts","sourceRoot":"","sources":["../../src/utilities/initReq.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EAEb,eAAe,EACf,aAAa,EACd,MAAM,SAAS,CAAA;AAGhB,OAAO,EACL,cAAc,EAMf,MAAM,SAAS,CAAA;AAchB;;;;GAIG;AACH,eAAO,MAAM,OAAO,gFAOjB;IACD,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,aAAa,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAAA;IACzD,SAAS,EAAE,SAAS,CAAA;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;IAChD,aAAa,EAAE,aAAa,CAAA;CAC7B,KAAG,OAAO,CAAC,aAAa,CA2HxB,CAAA"}
@@ -1,5 +1,6 @@
1
1
  import { initI18n } from '@payloadcms/translations';
2
2
  import { createLocalReq, executeAuthStrategies, getAccessResults, getPayload, getRequestLanguage, parseCookies } from 'payload';
3
+ import { applyUserReadAccess } from 'payload/internal';
3
4
  import { getRequestLocale } from './getRequestLocale.js';
4
5
  import { selectiveCache } from './selectiveCache.js';
5
6
  const partialReqCache = selectiveCache('partialReq');
@@ -19,7 +20,7 @@ export const initReq = async function ({
19
20
  }) {
20
21
  const headers = await serverAdapter.getHeaders();
21
22
  const cookies = parseCookies(headers);
22
- const partialResult = await partialReqCache.get(async () => {
23
+ const getPartialResult = async () => {
23
24
  const config = await configPromise;
24
25
  const payload = await getPayload({
25
26
  config,
@@ -51,8 +52,9 @@ export const initReq = async function ({
51
52
  responseHeaders,
52
53
  user
53
54
  };
54
- }, 'global');
55
- return reqCache.get(async () => {
55
+ };
56
+ const partialResult = await partialReqCache.get(getPartialResult, 'global');
57
+ const getResult = async () => {
56
58
  const {
57
59
  i18n,
58
60
  languageCode,
@@ -64,6 +66,10 @@ export const initReq = async function ({
64
66
  req: reqOverrides,
65
67
  ...optionsOverrides
66
68
  } = overrides || {};
69
+ const hasOptionsUserOverride = Object.hasOwn(optionsOverrides, 'user');
70
+ const hasReqUserOverride = Object.hasOwn(reqOverrides ?? {}, 'user');
71
+ const hasUserOverride = hasOptionsUserOverride || hasReqUserOverride;
72
+ const userOverride = hasOptionsUserOverride ? optionsOverrides.user : reqOverrides?.user;
67
73
  const req = await createLocalReq({
68
74
  req: {
69
75
  headers,
@@ -76,10 +82,37 @@ export const initReq = async function ({
76
82
  },
77
83
  ...(optionsOverrides || {})
78
84
  }, payload);
85
+ if (hasUserOverride && userOverride == null) {
86
+ req.user = null;
87
+ }
88
+ let userWithReadAccess = req.user;
79
89
  const locale = await getRequestLocale({
80
90
  req
81
91
  });
82
92
  req.locale = locale?.code;
93
+ if (!hasUserOverride && req.user) {
94
+ try {
95
+ const collectionSlug = req.user.collection ?? payload.config.admin.user;
96
+ const collection = payload.collections[collectionSlug]?.config;
97
+ if (!collection?.auth) {
98
+ throw new Error('Authenticated user collection not found');
99
+ }
100
+ userWithReadAccess = await applyUserReadAccess({
101
+ collection,
102
+ depth: collection.auth.depth,
103
+ overrideAccess: false,
104
+ req,
105
+ showHiddenFields: false,
106
+ user: req.user
107
+ });
108
+ } catch (error) {
109
+ payload.logger.error({
110
+ err: error
111
+ });
112
+ req.user = null;
113
+ userWithReadAccess = null;
114
+ }
115
+ }
83
116
  const permissions = await getAccessResults({
84
117
  req
85
118
  });
@@ -89,9 +122,11 @@ export const initReq = async function ({
89
122
  languageCode,
90
123
  locale,
91
124
  permissions,
92
- req
125
+ req,
126
+ user: userWithReadAccess
93
127
  };
94
- }, key).then(result => {
128
+ };
129
+ return reqCache.get(getResult, key, overrides).then(result => {
95
130
  // Shallow-copy req before returning to prevent
96
131
  // mutations from propagating to the cached req object.
97
132
  // This ensures parallel operations using the same cache key don't affect each other.
@@ -1 +1 @@
1
- {"version":3,"file":"initReq.js","names":["initI18n","createLocalReq","executeAuthStrategies","getAccessResults","getPayload","getRequestLanguage","parseCookies","getRequestLocale","selectiveCache","partialReqCache","reqCache","initReq","canSetHeaders","configPromise","importMap","key","overrides","serverAdapter","headers","getHeaders","cookies","partialResult","get","config","payload","cron","languageCode","i18n","context","language","responseHeaders","user","req","reqOverrides","optionsOverrides","host","server","locale","code","permissions","then","result"],"sources":["../../src/utilities/initReq.ts"],"sourcesContent":["import type { I18n, I18nClient } from '@payloadcms/translations'\nimport type {\n ImportMap,\n InitReqResult,\n PayloadRequest,\n SanitizedConfig,\n ServerAdapter,\n} from 'payload'\n\nimport { initI18n } from '@payloadcms/translations'\nimport {\n createLocalReq,\n executeAuthStrategies,\n getAccessResults,\n getPayload,\n getRequestLanguage,\n parseCookies,\n} from 'payload'\n\nimport { getRequestLocale } from './getRequestLocale.js'\nimport { selectiveCache } from './selectiveCache.js'\n\ntype PartialResult = {\n i18n: I18nClient\n} & Pick<InitReqResult, 'languageCode'> &\n Pick<PayloadRequest, 'payload' | 'responseHeaders' | 'user'>\n\nconst partialReqCache = selectiveCache<PartialResult>('partialReq')\nconst reqCache = selectiveCache<InitReqResult>('req')\n\n/**\n * Initializes a full request object, including the `req` object and access control.\n * Reads headers/cookies through the supplied `serverAdapter` so the function is\n * framework-agnostic; the consuming framework wires its own adapter.\n */\nexport const initReq = async function ({\n canSetHeaders,\n configPromise,\n importMap,\n key,\n overrides,\n serverAdapter,\n}: {\n canSetHeaders?: boolean\n configPromise: Promise<SanitizedConfig> | SanitizedConfig\n importMap: ImportMap\n key: string\n overrides?: Parameters<typeof createLocalReq>[0]\n serverAdapter: ServerAdapter\n}): Promise<InitReqResult> {\n const headers = await serverAdapter.getHeaders()\n const cookies = parseCookies(headers)\n\n const partialResult = await partialReqCache.get(async () => {\n const config = await configPromise\n const payload = await getPayload({ config, cron: true, importMap })\n const languageCode = getRequestLanguage({\n config,\n cookies,\n headers,\n })\n\n const i18n: I18nClient = await initI18n({\n config: config.i18n,\n context: 'client',\n language: languageCode,\n })\n\n const { responseHeaders, user } = await executeAuthStrategies({\n canSetHeaders,\n headers,\n payload,\n })\n\n return {\n i18n,\n languageCode,\n payload,\n responseHeaders,\n user,\n }\n }, 'global')\n\n return reqCache\n .get(async () => {\n const { i18n, languageCode, payload, responseHeaders, user } = partialResult\n\n const { req: reqOverrides, ...optionsOverrides } = overrides || {}\n\n const req = await createLocalReq(\n {\n req: {\n headers,\n host: headers.get('host'),\n i18n: i18n as I18n,\n responseHeaders,\n server: serverAdapter,\n user,\n ...(reqOverrides || {}),\n },\n ...(optionsOverrides || {}),\n },\n payload,\n )\n\n const locale = await getRequestLocale({\n req,\n })\n\n req.locale = locale?.code\n\n const permissions = await getAccessResults({\n req,\n })\n\n return {\n cookies,\n headers,\n languageCode,\n locale,\n permissions,\n req,\n }\n }, key)\n .then((result) => {\n // Shallow-copy req before returning to prevent\n // mutations from propagating to the cached req object.\n // This ensures parallel operations using the same cache key don't affect each other.\n return {\n ...result,\n req: {\n ...result.req,\n ...(result.req?.context\n ? {\n context: { ...result.req.context },\n }\n : {}),\n },\n }\n })\n}\n"],"mappings":"AASA,SAASA,QAAQ,QAAQ;AACzB,SACEC,cAAc,EACdC,qBAAqB,EACrBC,gBAAgB,EAChBC,UAAU,EACVC,kBAAkB,EAClBC,YAAY,QACP;AAEP,SAASC,gBAAgB,QAAQ;AACjC,SAASC,cAAc,QAAQ;AAO/B,MAAMC,eAAA,GAAkBD,cAAA,CAA8B;AACtD,MAAME,QAAA,GAAWF,cAAA,CAA8B;AAE/C;;;;;AAKA,OAAO,MAAMG,OAAA,GAAU,eAAAA,CAAgB;EACrCC,aAAa;EACbC,aAAa;EACbC,SAAS;EACTC,GAAG;EACHC,SAAS;EACTC;AAAa,CAQd;EACC,MAAMC,OAAA,GAAU,MAAMD,aAAA,CAAcE,UAAU;EAC9C,MAAMC,OAAA,GAAUd,YAAA,CAAaY,OAAA;EAE7B,MAAMG,aAAA,GAAgB,MAAMZ,eAAA,CAAgBa,GAAG,CAAC;IAC9C,MAAMC,MAAA,GAAS,MAAMV,aAAA;IACrB,MAAMW,OAAA,GAAU,MAAMpB,UAAA,CAAW;MAAEmB,MAAA;MAAQE,IAAA,EAAM;MAAMX;IAAU;IACjE,MAAMY,YAAA,GAAerB,kBAAA,CAAmB;MACtCkB,MAAA;MACAH,OAAA;MACAF;IACF;IAEA,MAAMS,IAAA,GAAmB,MAAM3B,QAAA,CAAS;MACtCuB,MAAA,EAAQA,MAAA,CAAOI,IAAI;MACnBC,OAAA,EAAS;MACTC,QAAA,EAAUH;IACZ;IAEA,MAAM;MAAEI,eAAe;MAAEC;IAAI,CAAE,GAAG,MAAM7B,qBAAA,CAAsB;MAC5DU,aAAA;MACAM,OAAA;MACAM;IACF;IAEA,OAAO;MACLG,IAAA;MACAD,YAAA;MACAF,OAAA;MACAM,eAAA;MACAC;IACF;EACF,GAAG;EAEH,OAAOrB,QAAA,CACJY,GAAG,CAAC;IACH,MAAM;MAAEK,IAAI;MAAED,YAAY;MAAEF,OAAO;MAAEM,eAAe;MAAEC;IAAI,CAAE,GAAGV,aAAA;IAE/D,MAAM;MAAEW,GAAA,EAAKC,YAAY;MAAE,GAAGC;IAAA,CAAkB,GAAGlB,SAAA,IAAa,CAAC;IAEjE,MAAMgB,GAAA,GAAM,MAAM/B,cAAA,CAChB;MACE+B,GAAA,EAAK;QACHd,OAAA;QACAiB,IAAA,EAAMjB,OAAA,CAAQI,GAAG,CAAC;QAClBK,IAAA,EAAMA,IAAA;QACNG,eAAA;QACAM,MAAA,EAAQnB,aAAA;QACRc,IAAA;QACA,IAAIE,YAAA,IAAgB,CAAC,CAAC;MACxB;MACA,IAAIC,gBAAA,IAAoB,CAAC,CAAC;IAC5B,GACAV,OAAA;IAGF,MAAMa,MAAA,GAAS,MAAM9B,gBAAA,CAAiB;MACpCyB;IACF;IAEAA,GAAA,CAAIK,MAAM,GAAGA,MAAA,EAAQC,IAAA;IAErB,MAAMC,WAAA,GAAc,MAAMpC,gBAAA,CAAiB;MACzC6B;IACF;IAEA,OAAO;MACLZ,OAAA;MACAF,OAAA;MACAQ,YAAA;MACAW,MAAA;MACAE,WAAA;MACAP;IACF;EACF,GAAGjB,GAAA,EACFyB,IAAI,CAAEC,MAAA;IACL;IACA;IACA;IACA,OAAO;MACL,GAAGA,MAAM;MACTT,GAAA,EAAK;QACH,GAAGS,MAAA,CAAOT,GAAG;QACb,IAAIS,MAAA,CAAOT,GAAG,EAAEJ,OAAA,GACZ;UACEA,OAAA,EAAS;YAAE,GAAGa,MAAA,CAAOT,GAAG,CAACJ;UAAQ;QACnC,IACA,CAAC,CAAC;MACR;IACF;EACF;AACJ","ignoreList":[]}
1
+ {"version":3,"file":"initReq.js","names":["initI18n","createLocalReq","executeAuthStrategies","getAccessResults","getPayload","getRequestLanguage","parseCookies","applyUserReadAccess","getRequestLocale","selectiveCache","partialReqCache","reqCache","initReq","canSetHeaders","configPromise","importMap","key","overrides","serverAdapter","headers","getHeaders","cookies","getPartialResult","config","payload","cron","languageCode","i18n","context","language","responseHeaders","user","partialResult","get","getResult","req","reqOverrides","optionsOverrides","hasOptionsUserOverride","Object","hasOwn","hasReqUserOverride","hasUserOverride","userOverride","host","server","userWithReadAccess","locale","code","collectionSlug","collection","admin","collections","auth","Error","depth","overrideAccess","showHiddenFields","error","logger","err","permissions","then","result"],"sources":["../../src/utilities/initReq.ts"],"sourcesContent":["import type { I18n, I18nClient } from '@payloadcms/translations'\nimport type {\n ImportMap,\n InitReqResult,\n PayloadRequest,\n SanitizedConfig,\n ServerAdapter,\n} from 'payload'\n\nimport { initI18n } from '@payloadcms/translations'\nimport {\n createLocalReq,\n executeAuthStrategies,\n getAccessResults,\n getPayload,\n getRequestLanguage,\n parseCookies,\n} from 'payload'\nimport { applyUserReadAccess } from 'payload/internal'\n\nimport { getRequestLocale } from './getRequestLocale.js'\nimport { selectiveCache } from './selectiveCache.js'\n\ntype PartialResult = {\n i18n: I18nClient\n} & Pick<InitReqResult, 'languageCode'> &\n Pick<PayloadRequest, 'payload' | 'responseHeaders' | 'user'>\n\nconst partialReqCache = selectiveCache<PartialResult>('partialReq')\nconst reqCache = selectiveCache<InitReqResult>('req')\n\n/**\n * Initializes a full request object, including the `req` object and access control.\n * Reads headers/cookies through the supplied `serverAdapter` so the function is\n * framework-agnostic; the consuming framework wires its own adapter.\n */\nexport const initReq = async function ({\n canSetHeaders,\n configPromise,\n importMap,\n key,\n overrides,\n serverAdapter,\n}: {\n canSetHeaders?: boolean\n configPromise: Promise<SanitizedConfig> | SanitizedConfig\n importMap: ImportMap\n key: string\n overrides?: Parameters<typeof createLocalReq>[0]\n serverAdapter: ServerAdapter\n}): Promise<InitReqResult> {\n const headers = await serverAdapter.getHeaders()\n const cookies = parseCookies(headers)\n\n const getPartialResult = async () => {\n const config = await configPromise\n const payload = await getPayload({ config, cron: true, importMap })\n const languageCode = getRequestLanguage({\n config,\n cookies,\n headers,\n })\n\n const i18n: I18nClient = await initI18n({\n config: config.i18n,\n context: 'client',\n language: languageCode,\n })\n\n const { responseHeaders, user } = await executeAuthStrategies({\n canSetHeaders,\n headers,\n payload,\n })\n\n return {\n i18n,\n languageCode,\n payload,\n responseHeaders,\n user,\n }\n }\n\n const partialResult = await partialReqCache.get(getPartialResult, 'global')\n\n const getResult = async () => {\n const { i18n, languageCode, payload, responseHeaders, user } = partialResult\n\n const { req: reqOverrides, ...optionsOverrides } = overrides || {}\n const hasOptionsUserOverride = Object.hasOwn(optionsOverrides, 'user')\n const hasReqUserOverride = Object.hasOwn(reqOverrides ?? {}, 'user')\n const hasUserOverride = hasOptionsUserOverride || hasReqUserOverride\n const userOverride = hasOptionsUserOverride ? optionsOverrides.user : reqOverrides?.user\n\n const req = await createLocalReq(\n {\n req: {\n headers,\n host: headers.get('host'),\n i18n: i18n as I18n,\n responseHeaders,\n server: serverAdapter,\n user,\n ...(reqOverrides || {}),\n },\n ...(optionsOverrides || {}),\n },\n payload,\n )\n\n if (hasUserOverride && userOverride == null) {\n req.user = null\n }\n\n let userWithReadAccess = req.user\n\n const locale = await getRequestLocale({ req })\n req.locale = locale?.code\n\n if (!hasUserOverride && req.user) {\n try {\n const collectionSlug = req.user.collection ?? payload.config.admin.user\n const collection = payload.collections[collectionSlug]?.config\n\n if (!collection?.auth) {\n throw new Error('Authenticated user collection not found')\n }\n\n userWithReadAccess = await applyUserReadAccess({\n collection,\n depth: collection.auth.depth,\n overrideAccess: false,\n req,\n showHiddenFields: false,\n user: req.user,\n })\n } catch (error) {\n payload.logger.error({ err: error })\n req.user = null\n userWithReadAccess = null\n }\n }\n\n const permissions = await getAccessResults({ req })\n\n return {\n cookies,\n headers,\n languageCode,\n locale,\n permissions,\n req,\n user: userWithReadAccess,\n }\n }\n\n return reqCache.get(getResult, key, overrides).then((result) => {\n // Shallow-copy req before returning to prevent\n // mutations from propagating to the cached req object.\n // This ensures parallel operations using the same cache key don't affect each other.\n return {\n ...result,\n req: {\n ...result.req,\n ...(result.req?.context\n ? {\n context: { ...result.req.context },\n }\n : {}),\n },\n }\n })\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,226 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ const mocks = vi.hoisted(() => ({
3
+ accessContexts: [],
4
+ accessUser: null,
5
+ applyUserReadAccess: vi.fn(),
6
+ cacheStores: new Map(),
7
+ executeAuthStrategies: vi.fn(),
8
+ user: {
9
+ collection: 'users',
10
+ id: 'user-id',
11
+ role: 'admin'
12
+ }
13
+ }));
14
+ vi.mock('@payloadcms/translations', () => ({
15
+ initI18n: vi.fn(async () => ({
16
+ fallbackLanguage: 'en',
17
+ language: 'en',
18
+ t: key => key,
19
+ translations: {}
20
+ }))
21
+ }));
22
+ vi.mock('payload', () => ({
23
+ createLocalReq: vi.fn(async (options, payload) => {
24
+ const request = options.req ?? {};
25
+ const user = options.user ?? request.user ?? null;
26
+ return {
27
+ ...request,
28
+ context: options.context ?? request.context ?? {},
29
+ headers: request.headers ?? new Headers(),
30
+ locale: options.locale ?? request.locale ?? 'en',
31
+ pathname: options.urlSuffix,
32
+ payload,
33
+ query: request.query ?? {},
34
+ responseHeaders: request.responseHeaders ?? new Headers(),
35
+ user: user && !user.collection ? {
36
+ ...user,
37
+ collection: payload.config.admin.user
38
+ } : user
39
+ };
40
+ }),
41
+ executeAuthStrategies: mocks.executeAuthStrategies,
42
+ getAccessResults: vi.fn(async ({
43
+ req
44
+ }) => {
45
+ mocks.accessContexts.push(req.context.name);
46
+ mocks.accessUser = req.user;
47
+ return {};
48
+ }),
49
+ getPayload: vi.fn(async () => ({
50
+ collections: {
51
+ users: {
52
+ config: {
53
+ auth: {
54
+ depth: 1
55
+ },
56
+ slug: 'users'
57
+ }
58
+ }
59
+ },
60
+ config: {
61
+ admin: {
62
+ user: 'users'
63
+ },
64
+ i18n: {
65
+ fallbackLanguage: 'en',
66
+ supportedLanguages: {
67
+ en: {}
68
+ },
69
+ translations: {}
70
+ }
71
+ },
72
+ logger: {
73
+ error: vi.fn()
74
+ }
75
+ })),
76
+ getRequestLanguage: vi.fn(() => 'en'),
77
+ parseCookies: vi.fn(() => new Map())
78
+ }));
79
+ vi.mock('payload/internal', () => ({
80
+ applyUserReadAccess: mocks.applyUserReadAccess
81
+ }));
82
+ vi.mock('./getRequestLocale.js', () => ({
83
+ getRequestLocale: vi.fn(async ({
84
+ req
85
+ }) => ({
86
+ code: req.locale
87
+ }))
88
+ }));
89
+ vi.mock('./selectiveCache.js', () => ({
90
+ selectiveCache: namespace => ({
91
+ get: async (factory, ...args) => {
92
+ let entries = mocks.cacheStores.get(namespace);
93
+ if (!entries) {
94
+ entries = [];
95
+ mocks.cacheStores.set(namespace, entries);
96
+ }
97
+ const cached = entries.find(entry => entry.args.length === args.length && entry.args.every((arg, i) => arg === args[i]));
98
+ if (cached) {
99
+ return cached.value;
100
+ }
101
+ const value = await factory();
102
+ entries.push({
103
+ args,
104
+ value
105
+ });
106
+ return value;
107
+ }
108
+ })
109
+ }));
110
+ import { initReq } from './initReq.js';
111
+ describe('initReq', () => {
112
+ beforeEach(() => {
113
+ mocks.accessContexts = [];
114
+ mocks.accessUser = null;
115
+ mocks.applyUserReadAccess.mockReset();
116
+ mocks.applyUserReadAccess.mockImplementation(async ({
117
+ req,
118
+ user
119
+ }) => ({
120
+ collection: user.collection,
121
+ id: user.id,
122
+ name: req.context.name
123
+ }));
124
+ mocks.cacheStores.clear();
125
+ mocks.executeAuthStrategies.mockReset();
126
+ mocks.executeAuthStrategies.mockResolvedValue({
127
+ user: mocks.user
128
+ });
129
+ });
130
+ it('should keep the complete req.user and filter the user for each response', async () => {
131
+ const first = await initReq({
132
+ configPromise: {},
133
+ importMap: {},
134
+ key: 'response',
135
+ overrides: {
136
+ context: {
137
+ name: 'First'
138
+ }
139
+ },
140
+ serverAdapter: {
141
+ getHeaders: async () => new Headers()
142
+ }
143
+ });
144
+ const second = await initReq({
145
+ configPromise: {},
146
+ importMap: {},
147
+ key: 'response',
148
+ overrides: {
149
+ context: {
150
+ name: 'Second'
151
+ }
152
+ },
153
+ serverAdapter: {
154
+ getHeaders: async () => new Headers()
155
+ }
156
+ });
157
+ expect(mocks.executeAuthStrategies).toHaveBeenCalledOnce();
158
+ expect(mocks.applyUserReadAccess).toHaveBeenCalledTimes(2);
159
+ expect(first.req.user).toHaveProperty('role', 'admin');
160
+ expect(second.req.user).toHaveProperty('role', 'admin');
161
+ expect(first.user).toMatchObject({
162
+ name: 'First'
163
+ });
164
+ expect(second.user).toMatchObject({
165
+ name: 'Second'
166
+ });
167
+ expect(first.user).not.toHaveProperty('role');
168
+ expect(mocks.accessUser).toHaveProperty('role', 'admin');
169
+ expect(mocks.accessContexts).toEqual(['First', 'Second']);
170
+ });
171
+ it('should use anonymous access when user read access fails', async () => {
172
+ mocks.applyUserReadAccess.mockRejectedValue(new Error('read access failed'));
173
+ const result = await initReq({
174
+ configPromise: {},
175
+ importMap: {},
176
+ key: 'failure',
177
+ serverAdapter: {
178
+ getHeaders: async () => new Headers()
179
+ }
180
+ });
181
+ expect(result.req.user).toBeNull();
182
+ expect(result.user).toBeNull();
183
+ expect(mocks.accessUser).toBeNull();
184
+ });
185
+ it('should preserve an explicit req.user override', async () => {
186
+ const user = {
187
+ id: 'override-user'
188
+ };
189
+ const result = await initReq({
190
+ configPromise: {},
191
+ importMap: {},
192
+ key: 'override',
193
+ overrides: {
194
+ req: {
195
+ user
196
+ }
197
+ },
198
+ serverAdapter: {
199
+ getHeaders: async () => new Headers()
200
+ }
201
+ });
202
+ expect(result.req.user).toMatchObject({
203
+ collection: 'users',
204
+ id: 'override-user'
205
+ });
206
+ expect(result.user).toBe(result.req.user);
207
+ expect(mocks.applyUserReadAccess).not.toHaveBeenCalled();
208
+ });
209
+ it('should preserve an explicit null user override', async () => {
210
+ const result = await initReq({
211
+ configPromise: {},
212
+ importMap: {},
213
+ key: 'anonymous',
214
+ overrides: {
215
+ user: null
216
+ },
217
+ serverAdapter: {
218
+ getHeaders: async () => new Headers()
219
+ }
220
+ });
221
+ expect(result.req.user).toBeNull();
222
+ expect(result.user).toBeNull();
223
+ expect(mocks.applyUserReadAccess).not.toHaveBeenCalled();
224
+ });
225
+ });
226
+ //# sourceMappingURL=initReq.spec.js.map