@payloadcms/plugin-ecommerce 3.71.0-internal.e36f916 → 3.71.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 (275) hide show
  1. package/dist/collections/addresses/createAddressesCollection.d.ts +1 -1
  2. package/dist/collections/addresses/createAddressesCollection.d.ts.map +1 -1
  3. package/dist/collections/addresses/createAddressesCollection.js +1 -1
  4. package/dist/collections/addresses/createAddressesCollection.js.map +1 -1
  5. package/dist/collections/addresses/hooks/beforeChange.d.ts +2 -3
  6. package/dist/collections/addresses/hooks/beforeChange.d.ts.map +1 -1
  7. package/dist/collections/addresses/hooks/beforeChange.js +7 -3
  8. package/dist/collections/addresses/hooks/beforeChange.js.map +1 -1
  9. package/dist/collections/carts/beforeChange.d.ts.map +1 -1
  10. package/dist/collections/carts/beforeChange.js.map +1 -1
  11. package/dist/collections/carts/createCartsCollection.d.ts +21 -0
  12. package/dist/collections/carts/createCartsCollection.d.ts.map +1 -1
  13. package/dist/collections/carts/createCartsCollection.js +27 -2
  14. package/dist/collections/carts/createCartsCollection.js.map +1 -1
  15. package/dist/collections/carts/endpoints/addItem.d.ts +19 -0
  16. package/dist/collections/carts/endpoints/addItem.d.ts.map +1 -0
  17. package/dist/collections/carts/endpoints/addItem.js +54 -0
  18. package/dist/collections/carts/endpoints/addItem.js.map +1 -0
  19. package/dist/collections/carts/endpoints/clearCart.d.ts +15 -0
  20. package/dist/collections/carts/endpoints/clearCart.d.ts.map +1 -0
  21. package/dist/collections/carts/endpoints/clearCart.js +41 -0
  22. package/dist/collections/carts/endpoints/clearCart.js.map +1 -0
  23. package/dist/collections/carts/endpoints/mergeCart.d.ts +21 -0
  24. package/dist/collections/carts/endpoints/mergeCart.d.ts.map +1 -0
  25. package/dist/collections/carts/endpoints/mergeCart.js +72 -0
  26. package/dist/collections/carts/endpoints/mergeCart.js.map +1 -0
  27. package/dist/collections/carts/endpoints/removeItem.d.ts +16 -0
  28. package/dist/collections/carts/endpoints/removeItem.d.ts.map +1 -0
  29. package/dist/collections/carts/endpoints/removeItem.js +51 -0
  30. package/dist/collections/carts/endpoints/removeItem.js.map +1 -0
  31. package/dist/collections/carts/endpoints/updateItem.d.ts +40 -0
  32. package/dist/collections/carts/endpoints/updateItem.d.ts.map +1 -0
  33. package/dist/collections/carts/endpoints/updateItem.js +95 -0
  34. package/dist/collections/carts/endpoints/updateItem.js.map +1 -0
  35. package/dist/collections/carts/hasCartSecretAccess.d.ts +2 -2
  36. package/dist/collections/carts/hasCartSecretAccess.js +3 -3
  37. package/dist/collections/carts/hasCartSecretAccess.js.map +1 -1
  38. package/dist/collections/carts/operations/addItem.d.ts +24 -0
  39. package/dist/collections/carts/operations/addItem.d.ts.map +1 -0
  40. package/dist/collections/carts/operations/addItem.js +95 -0
  41. package/dist/collections/carts/operations/addItem.js.map +1 -0
  42. package/dist/collections/carts/operations/clearCart.d.ts +20 -0
  43. package/dist/collections/carts/operations/clearCart.d.ts.map +1 -0
  44. package/dist/collections/carts/operations/clearCart.js +53 -0
  45. package/dist/collections/carts/operations/clearCart.js.map +1 -0
  46. package/dist/collections/carts/operations/createRequestWithSecret.d.ts +11 -0
  47. package/dist/collections/carts/operations/createRequestWithSecret.d.ts.map +1 -0
  48. package/dist/collections/carts/operations/createRequestWithSecret.js +21 -0
  49. package/dist/collections/carts/operations/createRequestWithSecret.js.map +1 -0
  50. package/dist/collections/carts/operations/defaultCartItemMatcher.d.ts +19 -0
  51. package/dist/collections/carts/operations/defaultCartItemMatcher.d.ts.map +1 -0
  52. package/dist/collections/carts/operations/defaultCartItemMatcher.js +25 -0
  53. package/dist/collections/carts/operations/defaultCartItemMatcher.js.map +1 -0
  54. package/dist/collections/carts/operations/defaultCartItemMatcher.spec.js +358 -0
  55. package/dist/collections/carts/operations/defaultCartItemMatcher.spec.js.map +1 -0
  56. package/dist/collections/carts/operations/mergeCart.d.ts +54 -0
  57. package/dist/collections/carts/operations/mergeCart.d.ts.map +1 -0
  58. package/dist/collections/carts/operations/mergeCart.js +144 -0
  59. package/dist/collections/carts/operations/mergeCart.js.map +1 -0
  60. package/dist/collections/carts/operations/removeItem.d.ts +21 -0
  61. package/dist/collections/carts/operations/removeItem.d.ts.map +1 -0
  62. package/dist/collections/carts/operations/removeItem.js +69 -0
  63. package/dist/collections/carts/operations/removeItem.js.map +1 -0
  64. package/dist/collections/carts/operations/types.d.ts +152 -0
  65. package/dist/collections/carts/operations/types.d.ts.map +1 -0
  66. package/dist/collections/carts/operations/types.js +7 -0
  67. package/dist/collections/carts/operations/types.js.map +1 -0
  68. package/dist/collections/carts/operations/updateItem.d.ts +41 -0
  69. package/dist/collections/carts/operations/updateItem.d.ts.map +1 -0
  70. package/dist/collections/carts/operations/updateItem.js +110 -0
  71. package/dist/collections/carts/operations/updateItem.js.map +1 -0
  72. package/dist/collections/variants/createVariantsCollection/index.d.ts +4 -0
  73. package/dist/collections/variants/createVariantsCollection/index.d.ts.map +1 -1
  74. package/dist/collections/variants/createVariantsCollection/index.js +8 -2
  75. package/dist/collections/variants/createVariantsCollection/index.js.map +1 -1
  76. package/dist/endpoints/confirmOrder.d.ts.map +1 -1
  77. package/dist/endpoints/confirmOrder.js +9 -2
  78. package/dist/endpoints/confirmOrder.js.map +1 -1
  79. package/dist/endpoints/initiatePayment.d.ts.map +1 -1
  80. package/dist/endpoints/initiatePayment.js +8 -2
  81. package/dist/endpoints/initiatePayment.js.map +1 -1
  82. package/dist/exports/client/react.d.ts +1 -1
  83. package/dist/exports/client/react.d.ts.map +1 -1
  84. package/dist/exports/client/react.js +1 -1
  85. package/dist/exports/client/react.js.map +1 -1
  86. package/dist/exports/types.d.ts +1 -1
  87. package/dist/exports/types.d.ts.map +1 -1
  88. package/dist/exports/types.js.map +1 -1
  89. package/dist/index.d.ts +7 -0
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +9 -1
  92. package/dist/index.js.map +1 -1
  93. package/dist/payments/adapters/stripe/confirmOrder.d.ts.map +1 -1
  94. package/dist/payments/adapters/stripe/confirmOrder.js +2 -2
  95. package/dist/payments/adapters/stripe/confirmOrder.js.map +1 -1
  96. package/dist/react/provider/index.d.ts +5 -4
  97. package/dist/react/provider/index.d.ts.map +1 -1
  98. package/dist/react/provider/index.js +449 -265
  99. package/dist/react/provider/index.js.map +1 -1
  100. package/dist/translations/index.d.ts +3 -4
  101. package/dist/translations/index.d.ts.map +1 -1
  102. package/dist/translations/index.js +80 -2
  103. package/dist/translations/index.js.map +1 -1
  104. package/dist/translations/languages/ar.d.ts +89 -0
  105. package/dist/translations/languages/ar.d.ts.map +1 -0
  106. package/dist/translations/languages/ar.js +92 -0
  107. package/dist/translations/languages/ar.js.map +1 -0
  108. package/dist/translations/languages/az.d.ts +89 -0
  109. package/dist/translations/languages/az.d.ts.map +1 -0
  110. package/dist/translations/languages/az.js +92 -0
  111. package/dist/translations/languages/az.js.map +1 -0
  112. package/dist/translations/languages/bg.d.ts +89 -0
  113. package/dist/translations/languages/bg.d.ts.map +1 -0
  114. package/dist/translations/languages/bg.js +92 -0
  115. package/dist/translations/languages/bg.js.map +1 -0
  116. package/dist/translations/languages/ca.d.ts +89 -0
  117. package/dist/translations/languages/ca.d.ts.map +1 -0
  118. package/dist/translations/languages/ca.js +92 -0
  119. package/dist/translations/languages/ca.js.map +1 -0
  120. package/dist/translations/languages/cs.d.ts +89 -0
  121. package/dist/translations/languages/cs.d.ts.map +1 -0
  122. package/dist/translations/languages/cs.js +92 -0
  123. package/dist/translations/languages/cs.js.map +1 -0
  124. package/dist/translations/languages/da.d.ts +89 -0
  125. package/dist/translations/languages/da.d.ts.map +1 -0
  126. package/dist/translations/languages/da.js +92 -0
  127. package/dist/translations/languages/da.js.map +1 -0
  128. package/dist/translations/languages/de.d.ts +89 -0
  129. package/dist/translations/languages/de.d.ts.map +1 -0
  130. package/dist/translations/languages/de.js +92 -0
  131. package/dist/translations/languages/de.js.map +1 -0
  132. package/dist/translations/languages/en.d.ts +89 -0
  133. package/dist/translations/languages/en.d.ts.map +1 -0
  134. package/dist/translations/languages/en.js +92 -0
  135. package/dist/translations/languages/en.js.map +1 -0
  136. package/dist/translations/languages/es.d.ts +89 -0
  137. package/dist/translations/languages/es.d.ts.map +1 -0
  138. package/dist/translations/languages/es.js +92 -0
  139. package/dist/translations/languages/es.js.map +1 -0
  140. package/dist/translations/languages/et.d.ts +89 -0
  141. package/dist/translations/languages/et.d.ts.map +1 -0
  142. package/dist/translations/languages/et.js +92 -0
  143. package/dist/translations/languages/et.js.map +1 -0
  144. package/dist/translations/languages/fa.d.ts +89 -0
  145. package/dist/translations/languages/fa.d.ts.map +1 -0
  146. package/dist/translations/languages/fa.js +92 -0
  147. package/dist/translations/languages/fa.js.map +1 -0
  148. package/dist/translations/languages/fr.d.ts +89 -0
  149. package/dist/translations/languages/fr.d.ts.map +1 -0
  150. package/dist/translations/languages/fr.js +92 -0
  151. package/dist/translations/languages/fr.js.map +1 -0
  152. package/dist/translations/languages/he.d.ts +89 -0
  153. package/dist/translations/languages/he.d.ts.map +1 -0
  154. package/dist/translations/languages/he.js +92 -0
  155. package/dist/translations/languages/he.js.map +1 -0
  156. package/dist/translations/languages/hr.d.ts +89 -0
  157. package/dist/translations/languages/hr.d.ts.map +1 -0
  158. package/dist/translations/languages/hr.js +92 -0
  159. package/dist/translations/languages/hr.js.map +1 -0
  160. package/dist/translations/languages/hu.d.ts +89 -0
  161. package/dist/translations/languages/hu.d.ts.map +1 -0
  162. package/dist/translations/languages/hu.js +92 -0
  163. package/dist/translations/languages/hu.js.map +1 -0
  164. package/dist/translations/languages/hy.d.ts +89 -0
  165. package/dist/translations/languages/hy.d.ts.map +1 -0
  166. package/dist/translations/languages/hy.js +92 -0
  167. package/dist/translations/languages/hy.js.map +1 -0
  168. package/dist/translations/languages/is.d.ts +89 -0
  169. package/dist/translations/languages/is.d.ts.map +1 -0
  170. package/dist/translations/languages/is.js +92 -0
  171. package/dist/translations/languages/is.js.map +1 -0
  172. package/dist/translations/languages/it.d.ts +89 -0
  173. package/dist/translations/languages/it.d.ts.map +1 -0
  174. package/dist/translations/languages/it.js +92 -0
  175. package/dist/translations/languages/it.js.map +1 -0
  176. package/dist/translations/languages/ja.d.ts +89 -0
  177. package/dist/translations/languages/ja.d.ts.map +1 -0
  178. package/dist/translations/languages/ja.js +92 -0
  179. package/dist/translations/languages/ja.js.map +1 -0
  180. package/dist/translations/languages/ko.d.ts +89 -0
  181. package/dist/translations/languages/ko.d.ts.map +1 -0
  182. package/dist/translations/languages/ko.js +92 -0
  183. package/dist/translations/languages/ko.js.map +1 -0
  184. package/dist/translations/languages/lt.d.ts +89 -0
  185. package/dist/translations/languages/lt.d.ts.map +1 -0
  186. package/dist/translations/languages/lt.js +92 -0
  187. package/dist/translations/languages/lt.js.map +1 -0
  188. package/dist/translations/languages/my.d.ts +89 -0
  189. package/dist/translations/languages/my.d.ts.map +1 -0
  190. package/dist/translations/languages/my.js +92 -0
  191. package/dist/translations/languages/my.js.map +1 -0
  192. package/dist/translations/languages/nb.d.ts +89 -0
  193. package/dist/translations/languages/nb.d.ts.map +1 -0
  194. package/dist/translations/languages/nb.js +92 -0
  195. package/dist/translations/languages/nb.js.map +1 -0
  196. package/dist/translations/languages/nl.d.ts +89 -0
  197. package/dist/translations/languages/nl.d.ts.map +1 -0
  198. package/dist/translations/languages/nl.js +92 -0
  199. package/dist/translations/languages/nl.js.map +1 -0
  200. package/dist/translations/languages/pl.d.ts +89 -0
  201. package/dist/translations/languages/pl.d.ts.map +1 -0
  202. package/dist/translations/languages/pl.js +92 -0
  203. package/dist/translations/languages/pl.js.map +1 -0
  204. package/dist/translations/languages/pt.d.ts +89 -0
  205. package/dist/translations/languages/pt.d.ts.map +1 -0
  206. package/dist/translations/languages/pt.js +92 -0
  207. package/dist/translations/languages/pt.js.map +1 -0
  208. package/dist/translations/languages/ro.d.ts +89 -0
  209. package/dist/translations/languages/ro.d.ts.map +1 -0
  210. package/dist/translations/languages/ro.js +92 -0
  211. package/dist/translations/languages/ro.js.map +1 -0
  212. package/dist/translations/languages/rs.d.ts +89 -0
  213. package/dist/translations/languages/rs.d.ts.map +1 -0
  214. package/dist/translations/languages/rs.js +92 -0
  215. package/dist/translations/languages/rs.js.map +1 -0
  216. package/dist/translations/languages/rsLatin.d.ts +89 -0
  217. package/dist/translations/languages/rsLatin.d.ts.map +1 -0
  218. package/dist/translations/languages/rsLatin.js +92 -0
  219. package/dist/translations/languages/rsLatin.js.map +1 -0
  220. package/dist/translations/languages/ru.d.ts +89 -0
  221. package/dist/translations/languages/ru.d.ts.map +1 -0
  222. package/dist/translations/languages/ru.js +92 -0
  223. package/dist/translations/languages/ru.js.map +1 -0
  224. package/dist/translations/languages/sk.d.ts +89 -0
  225. package/dist/translations/languages/sk.d.ts.map +1 -0
  226. package/dist/translations/languages/sk.js +92 -0
  227. package/dist/translations/languages/sk.js.map +1 -0
  228. package/dist/translations/languages/sl.d.ts +89 -0
  229. package/dist/translations/languages/sl.d.ts.map +1 -0
  230. package/dist/translations/languages/sl.js +92 -0
  231. package/dist/translations/languages/sl.js.map +1 -0
  232. package/dist/translations/languages/sv.d.ts +89 -0
  233. package/dist/translations/languages/sv.d.ts.map +1 -0
  234. package/dist/translations/languages/sv.js +92 -0
  235. package/dist/translations/languages/sv.js.map +1 -0
  236. package/dist/translations/languages/ta.d.ts +89 -0
  237. package/dist/translations/languages/ta.d.ts.map +1 -0
  238. package/dist/translations/languages/ta.js +92 -0
  239. package/dist/translations/languages/ta.js.map +1 -0
  240. package/dist/translations/languages/th.d.ts +89 -0
  241. package/dist/translations/languages/th.d.ts.map +1 -0
  242. package/dist/translations/languages/th.js +92 -0
  243. package/dist/translations/languages/th.js.map +1 -0
  244. package/dist/translations/languages/tr.d.ts +89 -0
  245. package/dist/translations/languages/tr.d.ts.map +1 -0
  246. package/dist/translations/languages/tr.js +92 -0
  247. package/dist/translations/languages/tr.js.map +1 -0
  248. package/dist/translations/languages/uk.d.ts +89 -0
  249. package/dist/translations/languages/uk.d.ts.map +1 -0
  250. package/dist/translations/languages/uk.js +92 -0
  251. package/dist/translations/languages/uk.js.map +1 -0
  252. package/dist/translations/languages/vi.d.ts +89 -0
  253. package/dist/translations/languages/vi.d.ts.map +1 -0
  254. package/dist/translations/languages/vi.js +92 -0
  255. package/dist/translations/languages/vi.js.map +1 -0
  256. package/dist/translations/languages/zh.d.ts +89 -0
  257. package/dist/translations/languages/zh.d.ts.map +1 -0
  258. package/dist/translations/languages/zh.js +92 -0
  259. package/dist/translations/languages/zh.js.map +1 -0
  260. package/dist/translations/languages/zhTw.d.ts +89 -0
  261. package/dist/translations/languages/zhTw.d.ts.map +1 -0
  262. package/dist/translations/languages/zhTw.js +92 -0
  263. package/dist/translations/languages/zhTw.js.map +1 -0
  264. package/dist/translations/translation-schema.json +313 -5
  265. package/dist/translations/types.d.ts +89 -0
  266. package/dist/translations/types.d.ts.map +1 -0
  267. package/dist/translations/types.js +3 -0
  268. package/dist/translations/types.js.map +1 -0
  269. package/dist/types/index.d.ts +154 -14
  270. package/dist/types/index.d.ts.map +1 -1
  271. package/dist/types/index.js.map +1 -1
  272. package/dist/ui/VariantOptionsSelector/index.d.ts.map +1 -1
  273. package/dist/ui/VariantOptionsSelector/index.js +6 -3
  274. package/dist/ui/VariantOptionsSelector/index.js.map +1 -1
  275. package/package.json +16 -10
@@ -1,7 +1,7 @@
1
1
  import type { CollectionConfig, Field } from 'payload';
2
2
  import type { AccessConfig, CountryType } from '../../types/index.js';
3
3
  type Props = {
4
- access: Pick<AccessConfig, 'customerOnlyFieldAccess' | 'isAdmin' | 'isAuthenticated' | 'isDocumentOwner'>;
4
+ access: Pick<AccessConfig, 'customerOnlyFieldAccess' | 'isAdmin' | 'isAuthenticated' | 'isCustomer' | 'isDocumentOwner'>;
5
5
  /**
6
6
  * Array of fields used for capturing the address data. Use this over overrides to customise the fields here as it's reused across the plugin.
7
7
  */
@@ -1 +1 @@
1
- {"version":3,"file":"createAddressesCollection.d.ts","sourceRoot":"","sources":["../../../src/collections/addresses/createAddressesCollection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAMrE,KAAK,KAAK,GAAG;IACX,MAAM,EAAE,IAAI,CACV,YAAY,EACZ,yBAAyB,GAAG,SAAS,GAAG,iBAAiB,GAAG,iBAAiB,CAC9E,CAAA;IACD;;OAEG;IACH,aAAa,EAAE,KAAK,EAAE,CAAA;IACtB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kBAAkB,CAAC,EAAE,WAAW,EAAE,CAAA;CACnC,CAAA;AAED,eAAO,MAAM,yBAAyB,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,gBAyEzD,CAAA"}
1
+ {"version":3,"file":"createAddressesCollection.d.ts","sourceRoot":"","sources":["../../../src/collections/addresses/createAddressesCollection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAMrE,KAAK,KAAK,GAAG;IACX,MAAM,EAAE,IAAI,CACV,YAAY,EACZ,yBAAyB,GAAG,SAAS,GAAG,iBAAiB,GAAG,YAAY,GAAG,iBAAiB,CAC7F,CAAA;IACD;;OAEG;IACH,aAAa,EAAE,KAAK,EAAE,CAAA;IACtB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kBAAkB,CAAC,EAAE,WAAW,EAAE,CAAA;CACnC,CAAA;AAED,eAAO,MAAM,yBAAyB,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,gBA2EzD,CAAA"}
@@ -53,7 +53,7 @@ export const createAddressesCollection = (props)=>{
53
53
  hooks: {
54
54
  beforeChange: [
55
55
  beforeChange({
56
- customerOnlyFieldAccess: access.customerOnlyFieldAccess
56
+ isCustomer: access.isCustomer ?? access.customerOnlyFieldAccess
57
57
  })
58
58
  ]
59
59
  },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/collections/addresses/createAddressesCollection.ts"],"sourcesContent":["import type { CollectionConfig, Field } from 'payload'\n\nimport type { AccessConfig, CountryType } from '../../types/index.js'\n\nimport { accessOR } from '../../utilities/accessComposition.js'\nimport { defaultCountries } from './defaultCountries.js'\nimport { beforeChange } from './hooks/beforeChange.js'\n\ntype Props = {\n access: Pick<\n AccessConfig,\n 'customerOnlyFieldAccess' | 'isAdmin' | 'isAuthenticated' | 'isDocumentOwner'\n >\n /**\n * Array of fields used for capturing the address data. Use this over overrides to customise the fields here as it's reused across the plugin.\n */\n addressFields: Field[]\n /**\n * Slug of the customers collection, defaults to 'users'.\n */\n customersSlug?: string\n supportedCountries?: CountryType[]\n}\n\nexport const createAddressesCollection: (props: Props) => CollectionConfig = (props) => {\n const { access, addressFields, customersSlug = 'users' } = props || {}\n\n const { supportedCountries: supportedCountriesFromProps } = props || {}\n const supportedCountries = supportedCountriesFromProps || defaultCountries\n const hasOnlyOneCountry = supportedCountries && supportedCountries.length === 1\n\n const fields: Field[] = [\n {\n name: 'customer',\n type: 'relationship',\n admin: {\n position: 'sidebar',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:customer'),\n relationTo: customersSlug,\n },\n ...addressFields.map((field) => {\n if ('name' in field && field.name === 'country') {\n return {\n name: 'country',\n type: 'select',\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:addressCountry'),\n options: supportedCountries || defaultCountries,\n required: true,\n ...(supportedCountries && supportedCountries?.[0] && hasOnlyOneCountry\n ? {\n defaultValue: supportedCountries?.[0].value,\n }\n : {}),\n } as Field\n }\n\n return field\n }),\n ]\n\n const baseConfig: CollectionConfig = {\n slug: 'addresses',\n access: {\n create: access.isAuthenticated,\n delete: accessOR(access.isAdmin, access.isDocumentOwner),\n read: accessOR(access.isAdmin, access.isDocumentOwner),\n update: accessOR(access.isAdmin, access.isDocumentOwner),\n },\n admin: {\n description: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:addressesCollectionDescription'),\n group: 'Ecommerce',\n hidden: true,\n useAsTitle: 'createdAt',\n },\n fields,\n hooks: {\n beforeChange: [beforeChange({ customerOnlyFieldAccess: access.customerOnlyFieldAccess })],\n },\n labels: {\n plural: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:addresses'),\n singular: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:address'),\n },\n timestamps: true,\n }\n\n return { ...baseConfig }\n}\n"],"names":["accessOR","defaultCountries","beforeChange","createAddressesCollection","props","access","addressFields","customersSlug","supportedCountries","supportedCountriesFromProps","hasOnlyOneCountry","length","fields","name","type","admin","position","label","t","relationTo","map","field","options","required","defaultValue","value","baseConfig","slug","create","isAuthenticated","delete","isAdmin","isDocumentOwner","read","update","description","group","hidden","useAsTitle","hooks","customerOnlyFieldAccess","labels","plural","singular","timestamps"],"mappings":"AAIA,SAASA,QAAQ,QAAQ,uCAAsC;AAC/D,SAASC,gBAAgB,QAAQ,wBAAuB;AACxD,SAASC,YAAY,QAAQ,0BAAyB;AAkBtD,OAAO,MAAMC,4BAAgE,CAACC;IAC5E,MAAM,EAAEC,MAAM,EAAEC,aAAa,EAAEC,gBAAgB,OAAO,EAAE,GAAGH,SAAS,CAAC;IAErE,MAAM,EAAEI,oBAAoBC,2BAA2B,EAAE,GAAGL,SAAS,CAAC;IACtE,MAAMI,qBAAqBC,+BAA+BR;IAC1D,MAAMS,oBAAoBF,sBAAsBA,mBAAmBG,MAAM,KAAK;IAE9E,MAAMC,SAAkB;QACtB;YACEC,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,UAAU;YACZ;YACAC,OAAO,CAAC,EAAEC,CAAC,EAAE,GACX,+DAA+D;gBAC/DA,EAAE;YACJC,YAAYZ;QACd;WACGD,cAAcc,GAAG,CAAC,CAACC;YACpB,IAAI,UAAUA,SAASA,MAAMR,IAAI,KAAK,WAAW;gBAC/C,OAAO;oBACLA,MAAM;oBACNC,MAAM;oBACNG,OAAO,CAAC,EAAEC,CAAC,EAAE,GACX,+DAA+D;wBAC/DA,EAAE;oBACJI,SAASd,sBAAsBP;oBAC/BsB,UAAU;oBACV,GAAIf,sBAAsBA,oBAAoB,CAAC,EAAE,IAAIE,oBACjD;wBACEc,cAAchB,oBAAoB,CAAC,EAAE,CAACiB;oBACxC,IACA,CAAC,CAAC;gBACR;YACF;YAEA,OAAOJ;QACT;KACD;IAED,MAAMK,aAA+B;QACnCC,MAAM;QACNtB,QAAQ;YACNuB,QAAQvB,OAAOwB,eAAe;YAC9BC,QAAQ9B,SAASK,OAAO0B,OAAO,EAAE1B,OAAO2B,eAAe;YACvDC,MAAMjC,SAASK,OAAO0B,OAAO,EAAE1B,OAAO2B,eAAe;YACrDE,QAAQlC,SAASK,OAAO0B,OAAO,EAAE1B,OAAO2B,eAAe;QACzD;QACAjB,OAAO;YACLoB,aAAa,CAAC,EAAEjB,CAAC,EAAE,GACjB,+DAA+D;gBAC/DA,EAAE;YACJkB,OAAO;YACPC,QAAQ;YACRC,YAAY;QACd;QACA1B;QACA2B,OAAO;YACLrC,cAAc;gBAACA,aAAa;oBAAEsC,yBAAyBnC,OAAOmC,uBAAuB;gBAAC;aAAG;QAC3F;QACAC,QAAQ;YACNC,QAAQ,CAAC,EAAExB,CAAC,EAAE,GACZ,+DAA+D;gBAC/DA,EAAE;YACJyB,UAAU,CAAC,EAAEzB,CAAC,EAAE,GACd,+DAA+D;gBAC/DA,EAAE;QACN;QACA0B,YAAY;IACd;IAEA,OAAO;QAAE,GAAGlB,UAAU;IAAC;AACzB,EAAC"}
1
+ {"version":3,"sources":["../../../src/collections/addresses/createAddressesCollection.ts"],"sourcesContent":["import type { CollectionConfig, Field } from 'payload'\n\nimport type { AccessConfig, CountryType } from '../../types/index.js'\n\nimport { accessOR } from '../../utilities/accessComposition.js'\nimport { defaultCountries } from './defaultCountries.js'\nimport { beforeChange } from './hooks/beforeChange.js'\n\ntype Props = {\n access: Pick<\n AccessConfig,\n 'customerOnlyFieldAccess' | 'isAdmin' | 'isAuthenticated' | 'isCustomer' | 'isDocumentOwner'\n >\n /**\n * Array of fields used for capturing the address data. Use this over overrides to customise the fields here as it's reused across the plugin.\n */\n addressFields: Field[]\n /**\n * Slug of the customers collection, defaults to 'users'.\n */\n customersSlug?: string\n supportedCountries?: CountryType[]\n}\n\nexport const createAddressesCollection: (props: Props) => CollectionConfig = (props) => {\n const { access, addressFields, customersSlug = 'users' } = props || {}\n\n const { supportedCountries: supportedCountriesFromProps } = props || {}\n const supportedCountries = supportedCountriesFromProps || defaultCountries\n const hasOnlyOneCountry = supportedCountries && supportedCountries.length === 1\n\n const fields: Field[] = [\n {\n name: 'customer',\n type: 'relationship',\n admin: {\n position: 'sidebar',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:customer'),\n relationTo: customersSlug,\n },\n ...addressFields.map((field) => {\n if ('name' in field && field.name === 'country') {\n return {\n name: 'country',\n type: 'select',\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:addressCountry'),\n options: supportedCountries || defaultCountries,\n required: true,\n ...(supportedCountries && supportedCountries?.[0] && hasOnlyOneCountry\n ? {\n defaultValue: supportedCountries?.[0].value,\n }\n : {}),\n } as Field\n }\n\n return field\n }),\n ]\n\n const baseConfig: CollectionConfig = {\n slug: 'addresses',\n access: {\n create: access.isAuthenticated,\n delete: accessOR(access.isAdmin, access.isDocumentOwner),\n read: accessOR(access.isAdmin, access.isDocumentOwner),\n update: accessOR(access.isAdmin, access.isDocumentOwner),\n },\n admin: {\n description: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:addressesCollectionDescription'),\n group: 'Ecommerce',\n hidden: true,\n useAsTitle: 'createdAt',\n },\n fields,\n hooks: {\n beforeChange: [\n beforeChange({ isCustomer: access.isCustomer ?? access.customerOnlyFieldAccess }),\n ],\n },\n labels: {\n plural: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:addresses'),\n singular: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:address'),\n },\n timestamps: true,\n }\n\n return { ...baseConfig }\n}\n"],"names":["accessOR","defaultCountries","beforeChange","createAddressesCollection","props","access","addressFields","customersSlug","supportedCountries","supportedCountriesFromProps","hasOnlyOneCountry","length","fields","name","type","admin","position","label","t","relationTo","map","field","options","required","defaultValue","value","baseConfig","slug","create","isAuthenticated","delete","isAdmin","isDocumentOwner","read","update","description","group","hidden","useAsTitle","hooks","isCustomer","customerOnlyFieldAccess","labels","plural","singular","timestamps"],"mappings":"AAIA,SAASA,QAAQ,QAAQ,uCAAsC;AAC/D,SAASC,gBAAgB,QAAQ,wBAAuB;AACxD,SAASC,YAAY,QAAQ,0BAAyB;AAkBtD,OAAO,MAAMC,4BAAgE,CAACC;IAC5E,MAAM,EAAEC,MAAM,EAAEC,aAAa,EAAEC,gBAAgB,OAAO,EAAE,GAAGH,SAAS,CAAC;IAErE,MAAM,EAAEI,oBAAoBC,2BAA2B,EAAE,GAAGL,SAAS,CAAC;IACtE,MAAMI,qBAAqBC,+BAA+BR;IAC1D,MAAMS,oBAAoBF,sBAAsBA,mBAAmBG,MAAM,KAAK;IAE9E,MAAMC,SAAkB;QACtB;YACEC,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,UAAU;YACZ;YACAC,OAAO,CAAC,EAAEC,CAAC,EAAE,GACX,+DAA+D;gBAC/DA,EAAE;YACJC,YAAYZ;QACd;WACGD,cAAcc,GAAG,CAAC,CAACC;YACpB,IAAI,UAAUA,SAASA,MAAMR,IAAI,KAAK,WAAW;gBAC/C,OAAO;oBACLA,MAAM;oBACNC,MAAM;oBACNG,OAAO,CAAC,EAAEC,CAAC,EAAE,GACX,+DAA+D;wBAC/DA,EAAE;oBACJI,SAASd,sBAAsBP;oBAC/BsB,UAAU;oBACV,GAAIf,sBAAsBA,oBAAoB,CAAC,EAAE,IAAIE,oBACjD;wBACEc,cAAchB,oBAAoB,CAAC,EAAE,CAACiB;oBACxC,IACA,CAAC,CAAC;gBACR;YACF;YAEA,OAAOJ;QACT;KACD;IAED,MAAMK,aAA+B;QACnCC,MAAM;QACNtB,QAAQ;YACNuB,QAAQvB,OAAOwB,eAAe;YAC9BC,QAAQ9B,SAASK,OAAO0B,OAAO,EAAE1B,OAAO2B,eAAe;YACvDC,MAAMjC,SAASK,OAAO0B,OAAO,EAAE1B,OAAO2B,eAAe;YACrDE,QAAQlC,SAASK,OAAO0B,OAAO,EAAE1B,OAAO2B,eAAe;QACzD;QACAjB,OAAO;YACLoB,aAAa,CAAC,EAAEjB,CAAC,EAAE,GACjB,+DAA+D;gBAC/DA,EAAE;YACJkB,OAAO;YACPC,QAAQ;YACRC,YAAY;QACd;QACA1B;QACA2B,OAAO;YACLrC,cAAc;gBACZA,aAAa;oBAAEsC,YAAYnC,OAAOmC,UAAU,IAAInC,OAAOoC,uBAAuB;gBAAC;aAChF;QACH;QACAC,QAAQ;YACNC,QAAQ,CAAC,EAAEzB,CAAC,EAAE,GACZ,+DAA+D;gBAC/DA,EAAE;YACJ0B,UAAU,CAAC,EAAE1B,CAAC,EAAE,GACd,+DAA+D;gBAC/DA,EAAE;QACN;QACA2B,YAAY;IACd;IAEA,OAAO;QAAE,GAAGnB,UAAU;IAAC;AACzB,EAAC"}
@@ -1,7 +1,6 @@
1
- import type { CollectionBeforeChangeHook } from 'payload';
2
- import type { AccessConfig } from '../../../types/index.js';
1
+ import type { CollectionBeforeChangeHook, FieldAccess } from 'payload';
3
2
  interface Props {
4
- customerOnlyFieldAccess: AccessConfig['customerOnlyFieldAccess'];
3
+ isCustomer?: FieldAccess;
5
4
  }
6
5
  export declare const beforeChange: (args: Props) => CollectionBeforeChangeHook;
7
6
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"beforeChange.d.ts","sourceRoot":"","sources":["../../../../src/collections/addresses/hooks/beforeChange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AAEzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAE3D,UAAU,KAAK;IACb,uBAAuB,EAAE,YAAY,CAAC,yBAAyB,CAAC,CAAA;CACjE;AAED,eAAO,MAAM,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,0BAUzC,CAAA"}
1
+ {"version":3,"file":"beforeChange.d.ts","sourceRoot":"","sources":["../../../../src/collections/addresses/hooks/beforeChange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAEtE,UAAU,KAAK;IACb,UAAU,CAAC,EAAE,WAAW,CAAA;CACzB;AAED,eAAO,MAAM,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,0BAgBzC,CAAA"}
@@ -1,12 +1,16 @@
1
- export const beforeChange = ({ customerOnlyFieldAccess })=>async ({ data, req })=>{
2
- const isCustomer = await customerOnlyFieldAccess({
1
+ export const beforeChange = ({ isCustomer })=>async ({ data, req })=>{
2
+ if (!isCustomer) {
3
+ return data;
4
+ }
5
+ const userIsCustomer = await isCustomer({
3
6
  req
4
7
  });
5
8
  // Ensure that the customer field is set to the current user's ID if the user is a customer.
6
9
  // Admins can set to any customer.
7
- if (req.user && isCustomer) {
10
+ if (req.user && userIsCustomer) {
8
11
  data.customer = req.user.id;
9
12
  }
13
+ return data;
10
14
  };
11
15
 
12
16
  //# sourceMappingURL=beforeChange.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/collections/addresses/hooks/beforeChange.ts"],"sourcesContent":["import type { CollectionBeforeChangeHook } from 'payload'\n\nimport type { AccessConfig } from '../../../types/index.js'\n\ninterface Props {\n customerOnlyFieldAccess: AccessConfig['customerOnlyFieldAccess']\n}\n\nexport const beforeChange: (args: Props) => CollectionBeforeChangeHook =\n ({ customerOnlyFieldAccess }) =>\n async ({ data, req }) => {\n const isCustomer = await customerOnlyFieldAccess({ req })\n\n // Ensure that the customer field is set to the current user's ID if the user is a customer.\n // Admins can set to any customer.\n if (req.user && isCustomer) {\n data.customer = req.user.id\n }\n }\n"],"names":["beforeChange","customerOnlyFieldAccess","data","req","isCustomer","user","customer","id"],"mappings":"AAQA,OAAO,MAAMA,eACX,CAAC,EAAEC,uBAAuB,EAAE,GAC5B,OAAO,EAAEC,IAAI,EAAEC,GAAG,EAAE;QAClB,MAAMC,aAAa,MAAMH,wBAAwB;YAAEE;QAAI;QAEvD,4FAA4F;QAC5F,kCAAkC;QAClC,IAAIA,IAAIE,IAAI,IAAID,YAAY;YAC1BF,KAAKI,QAAQ,GAAGH,IAAIE,IAAI,CAACE,EAAE;QAC7B;IACF,EAAC"}
1
+ {"version":3,"sources":["../../../../src/collections/addresses/hooks/beforeChange.ts"],"sourcesContent":["import type { CollectionBeforeChangeHook, FieldAccess } from 'payload'\n\ninterface Props {\n isCustomer?: FieldAccess\n}\n\nexport const beforeChange: (args: Props) => CollectionBeforeChangeHook =\n ({ isCustomer }) =>\n async ({ data, req }) => {\n if (!isCustomer) {\n return data\n }\n\n const userIsCustomer = await isCustomer({ req })\n\n // Ensure that the customer field is set to the current user's ID if the user is a customer.\n // Admins can set to any customer.\n if (req.user && userIsCustomer) {\n data.customer = req.user.id\n }\n\n return data\n }\n"],"names":["beforeChange","isCustomer","data","req","userIsCustomer","user","customer","id"],"mappings":"AAMA,OAAO,MAAMA,eACX,CAAC,EAAEC,UAAU,EAAE,GACf,OAAO,EAAEC,IAAI,EAAEC,GAAG,EAAE;QAClB,IAAI,CAACF,YAAY;YACf,OAAOC;QACT;QAEA,MAAME,iBAAiB,MAAMH,WAAW;YAAEE;QAAI;QAE9C,4FAA4F;QAC5F,kCAAkC;QAClC,IAAIA,IAAIE,IAAI,IAAID,gBAAgB;YAC9BF,KAAKI,QAAQ,GAAGH,IAAIE,IAAI,CAACE,EAAE;QAC7B;QAEA,OAAOL;IACT,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"beforeChange.d.ts","sourceRoot":"","sources":["../../../src/collections/carts/beforeChange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AAIzD,KAAK,KAAK,GAAG;IACX,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,0BAsD7C,CAAA"}
1
+ {"version":3,"file":"beforeChange.d.ts","sourceRoot":"","sources":["../../../src/collections/carts/beforeChange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AAIzD,KAAK,KAAK,GAAG;IACX,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,0BAwD7C,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/collections/carts/beforeChange.ts"],"sourcesContent":["import type { CollectionBeforeChangeHook } from 'payload'\n\nimport crypto from 'crypto'\n\ntype Props = {\n productsSlug: string\n variantsSlug: string\n}\n\nexport const beforeChangeCart: (args: Props) => CollectionBeforeChangeHook =\n ({ productsSlug, variantsSlug }) =>\n async ({ data, operation, req }) => {\n // Generate a secret for guest cart access on creation\n if (operation === 'create' && !data.customer && !data.secret) {\n // Generate a cryptographically secure random string\n const secret = crypto.randomBytes(20).toString('hex')\n data.secret = secret\n\n // Store in context so afterRead hook can include it in the creation response\n if (!req.context) { req.context = {} }\n req.context.newCartSecret = secret\n }\n\n // Update subtotal based on items in the cart\n if (data.items && Array.isArray(data.items)) {\n const priceField = `priceIn${data.currency}`\n\n let subtotal = 0\n\n for (const item of data.items) {\n if (item.variant) {\n const id = typeof item.variant === 'object' ? item.variant.id : item.variant\n\n const variant = await req.payload.findByID({\n id,\n collection: variantsSlug,\n depth: 0,\n select: {\n [priceField]: true,\n },\n })\n\n subtotal += variant[priceField] * item.quantity\n } else {\n const id = typeof item.product === 'object' ? item.product.id : item.product\n\n const product = await req.payload.findByID({\n id,\n collection: productsSlug,\n depth: 0,\n select: {\n [priceField]: true,\n },\n })\n\n subtotal += product[priceField] * item.quantity\n }\n }\n\n data.subtotal = subtotal\n } else {\n data.subtotal = 0\n }\n }\n"],"names":["crypto","beforeChangeCart","productsSlug","variantsSlug","data","operation","req","customer","secret","randomBytes","toString","context","newCartSecret","items","Array","isArray","priceField","currency","subtotal","item","variant","id","payload","findByID","collection","depth","select","quantity","product"],"mappings":"AAEA,OAAOA,YAAY,SAAQ;AAO3B,OAAO,MAAMC,mBACX,CAAC,EAAEC,YAAY,EAAEC,YAAY,EAAE,GAC/B,OAAO,EAAEC,IAAI,EAAEC,SAAS,EAAEC,GAAG,EAAE;QAC7B,sDAAsD;QACtD,IAAID,cAAc,YAAY,CAACD,KAAKG,QAAQ,IAAI,CAACH,KAAKI,MAAM,EAAE;YAC5D,oDAAoD;YACpD,MAAMA,SAASR,OAAOS,WAAW,CAAC,IAAIC,QAAQ,CAAC;YAC/CN,KAAKI,MAAM,GAAGA;YAEd,6EAA6E;YAC7E,IAAI,CAACF,IAAIK,OAAO,EAAE;gBAAEL,IAAIK,OAAO,GAAG,CAAC;YAAE;YACrCL,IAAIK,OAAO,CAACC,aAAa,GAAGJ;QAC9B;QAEA,6CAA6C;QAC7C,IAAIJ,KAAKS,KAAK,IAAIC,MAAMC,OAAO,CAACX,KAAKS,KAAK,GAAG;YAC3C,MAAMG,aAAa,CAAC,OAAO,EAAEZ,KAAKa,QAAQ,EAAE;YAE5C,IAAIC,WAAW;YAEf,KAAK,MAAMC,QAAQf,KAAKS,KAAK,CAAE;gBAC7B,IAAIM,KAAKC,OAAO,EAAE;oBAChB,MAAMC,KAAK,OAAOF,KAAKC,OAAO,KAAK,WAAWD,KAAKC,OAAO,CAACC,EAAE,GAAGF,KAAKC,OAAO;oBAE5E,MAAMA,UAAU,MAAMd,IAAIgB,OAAO,CAACC,QAAQ,CAAC;wBACzCF;wBACAG,YAAYrB;wBACZsB,OAAO;wBACPC,QAAQ;4BACN,CAACV,WAAW,EAAE;wBAChB;oBACF;oBAEAE,YAAYE,OAAO,CAACJ,WAAW,GAAGG,KAAKQ,QAAQ;gBACjD,OAAO;oBACL,MAAMN,KAAK,OAAOF,KAAKS,OAAO,KAAK,WAAWT,KAAKS,OAAO,CAACP,EAAE,GAAGF,KAAKS,OAAO;oBAE5E,MAAMA,UAAU,MAAMtB,IAAIgB,OAAO,CAACC,QAAQ,CAAC;wBACzCF;wBACAG,YAAYtB;wBACZuB,OAAO;wBACPC,QAAQ;4BACN,CAACV,WAAW,EAAE;wBAChB;oBACF;oBAEAE,YAAYU,OAAO,CAACZ,WAAW,GAAGG,KAAKQ,QAAQ;gBACjD;YACF;YAEAvB,KAAKc,QAAQ,GAAGA;QAClB,OAAO;YACLd,KAAKc,QAAQ,GAAG;QAClB;IACF,EAAC"}
1
+ {"version":3,"sources":["../../../src/collections/carts/beforeChange.ts"],"sourcesContent":["import type { CollectionBeforeChangeHook } from 'payload'\n\nimport crypto from 'crypto'\n\ntype Props = {\n productsSlug: string\n variantsSlug: string\n}\n\nexport const beforeChangeCart: (args: Props) => CollectionBeforeChangeHook =\n ({ productsSlug, variantsSlug }) =>\n async ({ data, operation, req }) => {\n // Generate a secret for guest cart access on creation\n if (operation === 'create' && !data.customer && !data.secret) {\n // Generate a cryptographically secure random string\n const secret = crypto.randomBytes(20).toString('hex')\n data.secret = secret\n\n // Store in context so afterRead hook can include it in the creation response\n if (!req.context) {\n req.context = {}\n }\n req.context.newCartSecret = secret\n }\n\n // Update subtotal based on items in the cart\n if (data.items && Array.isArray(data.items)) {\n const priceField = `priceIn${data.currency}`\n\n let subtotal = 0\n\n for (const item of data.items) {\n if (item.variant) {\n const id = typeof item.variant === 'object' ? item.variant.id : item.variant\n\n const variant = await req.payload.findByID({\n id,\n collection: variantsSlug,\n depth: 0,\n select: {\n [priceField]: true,\n },\n })\n\n subtotal += variant[priceField] * item.quantity\n } else {\n const id = typeof item.product === 'object' ? item.product.id : item.product\n\n const product = await req.payload.findByID({\n id,\n collection: productsSlug,\n depth: 0,\n select: {\n [priceField]: true,\n },\n })\n\n subtotal += product[priceField] * item.quantity\n }\n }\n\n data.subtotal = subtotal\n } else {\n data.subtotal = 0\n }\n }\n"],"names":["crypto","beforeChangeCart","productsSlug","variantsSlug","data","operation","req","customer","secret","randomBytes","toString","context","newCartSecret","items","Array","isArray","priceField","currency","subtotal","item","variant","id","payload","findByID","collection","depth","select","quantity","product"],"mappings":"AAEA,OAAOA,YAAY,SAAQ;AAO3B,OAAO,MAAMC,mBACX,CAAC,EAAEC,YAAY,EAAEC,YAAY,EAAE,GAC/B,OAAO,EAAEC,IAAI,EAAEC,SAAS,EAAEC,GAAG,EAAE;QAC7B,sDAAsD;QACtD,IAAID,cAAc,YAAY,CAACD,KAAKG,QAAQ,IAAI,CAACH,KAAKI,MAAM,EAAE;YAC5D,oDAAoD;YACpD,MAAMA,SAASR,OAAOS,WAAW,CAAC,IAAIC,QAAQ,CAAC;YAC/CN,KAAKI,MAAM,GAAGA;YAEd,6EAA6E;YAC7E,IAAI,CAACF,IAAIK,OAAO,EAAE;gBAChBL,IAAIK,OAAO,GAAG,CAAC;YACjB;YACAL,IAAIK,OAAO,CAACC,aAAa,GAAGJ;QAC9B;QAEA,6CAA6C;QAC7C,IAAIJ,KAAKS,KAAK,IAAIC,MAAMC,OAAO,CAACX,KAAKS,KAAK,GAAG;YAC3C,MAAMG,aAAa,CAAC,OAAO,EAAEZ,KAAKa,QAAQ,EAAE;YAE5C,IAAIC,WAAW;YAEf,KAAK,MAAMC,QAAQf,KAAKS,KAAK,CAAE;gBAC7B,IAAIM,KAAKC,OAAO,EAAE;oBAChB,MAAMC,KAAK,OAAOF,KAAKC,OAAO,KAAK,WAAWD,KAAKC,OAAO,CAACC,EAAE,GAAGF,KAAKC,OAAO;oBAE5E,MAAMA,UAAU,MAAMd,IAAIgB,OAAO,CAACC,QAAQ,CAAC;wBACzCF;wBACAG,YAAYrB;wBACZsB,OAAO;wBACPC,QAAQ;4BACN,CAACV,WAAW,EAAE;wBAChB;oBACF;oBAEAE,YAAYE,OAAO,CAACJ,WAAW,GAAGG,KAAKQ,QAAQ;gBACjD,OAAO;oBACL,MAAMN,KAAK,OAAOF,KAAKS,OAAO,KAAK,WAAWT,KAAKS,OAAO,CAACP,EAAE,GAAGF,KAAKS,OAAO;oBAE5E,MAAMA,UAAU,MAAMtB,IAAIgB,OAAO,CAACC,QAAQ,CAAC;wBACzCF;wBACAG,YAAYtB;wBACZuB,OAAO;wBACPC,QAAQ;4BACN,CAACV,WAAW,EAAE;wBAChB;oBACF;oBAEAE,YAAYU,OAAO,CAACZ,WAAW,GAAGG,KAAKQ,QAAQ;gBACjD;YACF;YAEAvB,KAAKc,QAAQ,GAAGA;QAClB,OAAO;YACLd,KAAKc,QAAQ,GAAG;QAClB;IACF,EAAC"}
@@ -1,5 +1,6 @@
1
1
  import type { CollectionConfig } from 'payload';
2
2
  import type { AccessConfig, CurrenciesConfig } from '../../types/index.js';
3
+ import type { CartItemMatcher } from './operations/types.js';
3
4
  type Props = {
4
5
  access: Pick<Required<AccessConfig>, 'isAdmin' | 'isAuthenticated' | 'isDocumentOwner'>;
5
6
  /**
@@ -7,6 +8,26 @@ type Props = {
7
8
  * Defaults to false.
8
9
  */
9
10
  allowGuestCarts?: boolean;
11
+ /**
12
+ * Custom function to determine if two cart items should be considered the same.
13
+ * When items match, their quantities are combined instead of creating separate entries.
14
+ *
15
+ * Use this to add custom uniqueness criteria beyond product and variant IDs.
16
+ *
17
+ * @default defaultCartItemMatcher (matches by product and variant ID only)
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * cartItemMatcher: ({ existingItem, newItem }) => {
22
+ * // Match by product, variant, AND custom delivery option
23
+ * const productMatch = existingItem.product === newItem.product
24
+ * const variantMatch = existingItem.variant === newItem.variant
25
+ * const deliveryMatch = existingItem.deliveryOption === newItem.deliveryOption
26
+ * return productMatch && variantMatch && deliveryMatch
27
+ * }
28
+ * ```
29
+ */
30
+ cartItemMatcher?: CartItemMatcher;
10
31
  currenciesConfig?: CurrenciesConfig;
11
32
  /**
12
33
  * Slug of the customers collection, defaults to 'users'.
@@ -1 +1 @@
1
- {"version":3,"file":"createCartsCollection.d.ts","sourceRoot":"","sources":["../../../src/collections/carts/createCartsCollection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,gBAAgB,EAAS,MAAM,SAAS,CAAA;AAE9D,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAU1E,KAAK,KAAK,GAAG;IACX,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,GAAG,iBAAiB,GAAG,iBAAiB,CAAC,CAAA;IACvF;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,eAAO,MAAM,qBAAqB,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,gBA0LrD,CAAA"}
1
+ {"version":3,"file":"createCartsCollection.d.ts","sourceRoot":"","sources":["../../../src/collections/carts/createCartsCollection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,gBAAgB,EAAS,MAAM,SAAS,CAAA;AAE9D,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAC1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAe5D,KAAK,KAAK,GAAG;IACX,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,GAAG,iBAAiB,GAAG,iBAAiB,CAAC,CAAA;IACvF;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;;;;;;;;;;;;;;OAkBG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,eAAO,MAAM,qBAAqB,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,gBAqMrD,CAAA"}
@@ -3,10 +3,16 @@ import { cartItemsField } from '../../fields/cartItemsField.js';
3
3
  import { currencyField } from '../../fields/currencyField.js';
4
4
  import { accessOR, conditional } from '../../utilities/accessComposition.js';
5
5
  import { beforeChangeCart } from './beforeChange.js';
6
+ import { addItemEndpoint } from './endpoints/addItem.js';
7
+ import { clearCartEndpoint } from './endpoints/clearCart.js';
8
+ import { mergeCartEndpoint } from './endpoints/mergeCart.js';
9
+ import { removeItemEndpoint } from './endpoints/removeItem.js';
10
+ import { updateItemEndpoint } from './endpoints/updateItem.js';
6
11
  import { hasCartSecretAccess } from './hasCartSecretAccess.js';
7
12
  import { statusBeforeRead } from './statusBeforeRead.js';
8
13
  export const createCartsCollection = (props)=>{
9
- const { access, allowGuestCarts = false, currenciesConfig, customersSlug = 'users', enableVariants = false, productsSlug = 'products', variantsSlug = 'variants' } = props || {};
14
+ const { access, allowGuestCarts = false, cartItemMatcher, currenciesConfig, customersSlug = 'users', enableVariants = false, productsSlug = 'products', variantsSlug = 'variants' } = props || {};
15
+ const cartsSlug = 'carts';
10
16
  const fields = [
11
17
  cartItemsField({
12
18
  enableVariants,
@@ -120,7 +126,7 @@ export const createCartsCollection = (props)=>{
120
126
  // Internal access function for guest users (unauthenticated)
121
127
  const isGuest = ({ req })=>!req.user;
122
128
  const baseConfig = {
123
- slug: 'carts',
129
+ slug: cartsSlug,
124
130
  access: {
125
131
  create: accessOR(access.isAdmin, access.isAuthenticated, conditional(allowGuestCarts, isGuest)),
126
132
  delete: accessOR(access.isAdmin, access.isDocumentOwner, hasCartSecretAccess(allowGuestCarts)),
@@ -133,6 +139,25 @@ export const createCartsCollection = (props)=>{
133
139
  group: 'Ecommerce',
134
140
  useAsTitle: 'createdAt'
135
141
  },
142
+ endpoints: [
143
+ addItemEndpoint({
144
+ cartItemMatcher,
145
+ cartsSlug
146
+ }),
147
+ clearCartEndpoint({
148
+ cartsSlug
149
+ }),
150
+ // mergeCartEndpoint uses its own matcher that handles CartItemData for both items
151
+ mergeCartEndpoint({
152
+ cartsSlug
153
+ }),
154
+ removeItemEndpoint({
155
+ cartsSlug
156
+ }),
157
+ updateItemEndpoint({
158
+ cartsSlug
159
+ })
160
+ ],
136
161
  fields,
137
162
  hooks: {
138
163
  afterRead: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/collections/carts/createCartsCollection.ts"],"sourcesContent":["import type { Access, CollectionConfig, Field } from 'payload'\n\nimport type { AccessConfig, CurrenciesConfig } from '../../types/index.js'\n\nimport { amountField } from '../../fields/amountField.js'\nimport { cartItemsField } from '../../fields/cartItemsField.js'\nimport { currencyField } from '../../fields/currencyField.js'\nimport { accessOR, conditional } from '../../utilities/accessComposition.js'\nimport { beforeChangeCart } from './beforeChange.js'\nimport { hasCartSecretAccess } from './hasCartSecretAccess.js'\nimport { statusBeforeRead } from './statusBeforeRead.js'\n\ntype Props = {\n access: Pick<Required<AccessConfig>, 'isAdmin' | 'isAuthenticated' | 'isDocumentOwner'>\n /**\n * Allow guest (unauthenticated) users to create carts.\n * Defaults to false.\n */\n allowGuestCarts?: boolean\n currenciesConfig?: CurrenciesConfig\n /**\n * Slug of the customers collection, defaults to 'users'.\n */\n customersSlug?: string\n /**\n * Enables support for variants in the cart.\n * Defaults to false.\n */\n enableVariants?: boolean\n /**\n * Slug of the products collection, defaults to 'products'.\n */\n productsSlug?: string\n /**\n * Slug of the variants collection, defaults to 'variants'.\n */\n variantsSlug?: string\n}\n\nexport const createCartsCollection: (props: Props) => CollectionConfig = (props) => {\n const {\n access,\n allowGuestCarts = false,\n currenciesConfig,\n customersSlug = 'users',\n enableVariants = false,\n productsSlug = 'products',\n variantsSlug = 'variants',\n } = props || {}\n\n const fields: Field[] = [\n cartItemsField({\n enableVariants,\n overrides: {\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:items'),\n labels: {\n plural: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:items'),\n singular: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:item'),\n },\n },\n productsSlug,\n variantsSlug,\n }),\n {\n name: 'secret',\n type: 'text',\n access: {\n create: () => false, // Users can't set it manually\n read: () => false, // Never readable via field access (only through afterRead hook)\n update: () => false, // Users can't update it\n },\n admin: {\n hidden: true,\n position: 'sidebar',\n readOnly: true,\n },\n index: true,\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:cartSecret'),\n },\n {\n name: 'customer',\n type: 'relationship',\n admin: {\n position: 'sidebar',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:customer'),\n relationTo: customersSlug,\n },\n {\n name: 'purchasedAt',\n type: 'date',\n admin: {\n date: { pickerAppearance: 'dayAndTime' },\n position: 'sidebar',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:purchasedAt'),\n },\n {\n name: 'status',\n type: 'select',\n admin: {\n position: 'sidebar',\n readOnly: true,\n },\n hooks: {\n afterRead: [statusBeforeRead],\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:status'),\n options: [\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:active'),\n value: 'active',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:purchased'),\n value: 'purchased',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:abandoned'),\n value: 'abandoned',\n },\n ],\n virtual: true,\n },\n ...(currenciesConfig\n ? [\n {\n type: 'row',\n admin: { position: 'sidebar' },\n fields: [\n amountField({\n currenciesConfig,\n overrides: {\n name: 'subtotal',\n\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:subtotal'),\n },\n }),\n currencyField({\n currenciesConfig,\n }),\n ],\n } as Field,\n ]\n : []),\n ]\n\n // Internal access function for guest users (unauthenticated)\n const isGuest: Access = ({ req }) => !req.user\n\n const baseConfig: CollectionConfig = {\n slug: 'carts',\n access: {\n create: accessOR(\n access.isAdmin,\n access.isAuthenticated,\n conditional(allowGuestCarts, isGuest),\n ),\n delete: accessOR(\n access.isAdmin,\n access.isDocumentOwner,\n hasCartSecretAccess(allowGuestCarts),\n ),\n read: accessOR(access.isAdmin, access.isDocumentOwner, hasCartSecretAccess(allowGuestCarts)),\n update: accessOR(\n access.isAdmin,\n access.isDocumentOwner,\n hasCartSecretAccess(allowGuestCarts),\n ),\n },\n admin: {\n description: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:cartsCollectionDescription'),\n group: 'Ecommerce',\n useAsTitle: 'createdAt',\n },\n fields,\n hooks: {\n afterRead: [\n ({ doc, req }) => {\n // Include secret only if this was just created (stored in context by beforeChange)\n if (req.context?.newCartSecret) {\n doc.secret = req.context.newCartSecret\n }\n // Secret is otherwise never exposed (field access is locked)\n return doc\n },\n ],\n beforeChange: [\n // This hook can be used to update the subtotal before saving the cart\n beforeChangeCart({ productsSlug, variantsSlug }),\n ],\n },\n labels: {\n plural: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:carts'),\n singular: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:cart'),\n },\n timestamps: true,\n }\n\n return { ...baseConfig }\n}\n"],"names":["amountField","cartItemsField","currencyField","accessOR","conditional","beforeChangeCart","hasCartSecretAccess","statusBeforeRead","createCartsCollection","props","access","allowGuestCarts","currenciesConfig","customersSlug","enableVariants","productsSlug","variantsSlug","fields","overrides","label","t","labels","plural","singular","name","type","create","read","update","admin","hidden","position","readOnly","index","relationTo","date","pickerAppearance","hooks","afterRead","options","value","virtual","isGuest","req","user","baseConfig","slug","isAdmin","isAuthenticated","delete","isDocumentOwner","description","group","useAsTitle","doc","context","newCartSecret","secret","beforeChange","timestamps"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/collections/carts/createCartsCollection.ts"],"sourcesContent":["import type { Access, CollectionConfig, Field } from 'payload'\n\nimport type { AccessConfig, CurrenciesConfig } from '../../types/index.js'\nimport type { CartItemMatcher } from './operations/types.js'\n\nimport { amountField } from '../../fields/amountField.js'\nimport { cartItemsField } from '../../fields/cartItemsField.js'\nimport { currencyField } from '../../fields/currencyField.js'\nimport { accessOR, conditional } from '../../utilities/accessComposition.js'\nimport { beforeChangeCart } from './beforeChange.js'\nimport { addItemEndpoint } from './endpoints/addItem.js'\nimport { clearCartEndpoint } from './endpoints/clearCart.js'\nimport { mergeCartEndpoint } from './endpoints/mergeCart.js'\nimport { removeItemEndpoint } from './endpoints/removeItem.js'\nimport { updateItemEndpoint } from './endpoints/updateItem.js'\nimport { hasCartSecretAccess } from './hasCartSecretAccess.js'\nimport { statusBeforeRead } from './statusBeforeRead.js'\n\ntype Props = {\n access: Pick<Required<AccessConfig>, 'isAdmin' | 'isAuthenticated' | 'isDocumentOwner'>\n /**\n * Allow guest (unauthenticated) users to create carts.\n * Defaults to false.\n */\n allowGuestCarts?: boolean\n /**\n * Custom function to determine if two cart items should be considered the same.\n * When items match, their quantities are combined instead of creating separate entries.\n *\n * Use this to add custom uniqueness criteria beyond product and variant IDs.\n *\n * @default defaultCartItemMatcher (matches by product and variant ID only)\n *\n * @example\n * ```ts\n * cartItemMatcher: ({ existingItem, newItem }) => {\n * // Match by product, variant, AND custom delivery option\n * const productMatch = existingItem.product === newItem.product\n * const variantMatch = existingItem.variant === newItem.variant\n * const deliveryMatch = existingItem.deliveryOption === newItem.deliveryOption\n * return productMatch && variantMatch && deliveryMatch\n * }\n * ```\n */\n cartItemMatcher?: CartItemMatcher\n currenciesConfig?: CurrenciesConfig\n /**\n * Slug of the customers collection, defaults to 'users'.\n */\n customersSlug?: string\n /**\n * Enables support for variants in the cart.\n * Defaults to false.\n */\n enableVariants?: boolean\n /**\n * Slug of the products collection, defaults to 'products'.\n */\n productsSlug?: string\n /**\n * Slug of the variants collection, defaults to 'variants'.\n */\n variantsSlug?: string\n}\n\nexport const createCartsCollection: (props: Props) => CollectionConfig = (props) => {\n const {\n access,\n allowGuestCarts = false,\n cartItemMatcher,\n currenciesConfig,\n customersSlug = 'users',\n enableVariants = false,\n productsSlug = 'products',\n variantsSlug = 'variants',\n } = props || {}\n\n const cartsSlug = 'carts'\n\n const fields: Field[] = [\n cartItemsField({\n enableVariants,\n overrides: {\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:items'),\n labels: {\n plural: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:items'),\n singular: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:item'),\n },\n },\n productsSlug,\n variantsSlug,\n }),\n {\n name: 'secret',\n type: 'text',\n access: {\n create: () => false, // Users can't set it manually\n read: () => false, // Never readable via field access (only through afterRead hook)\n update: () => false, // Users can't update it\n },\n admin: {\n hidden: true,\n position: 'sidebar',\n readOnly: true,\n },\n index: true,\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:cartSecret'),\n },\n {\n name: 'customer',\n type: 'relationship',\n admin: {\n position: 'sidebar',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:customer'),\n relationTo: customersSlug,\n },\n {\n name: 'purchasedAt',\n type: 'date',\n admin: {\n date: { pickerAppearance: 'dayAndTime' },\n position: 'sidebar',\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:purchasedAt'),\n },\n {\n name: 'status',\n type: 'select',\n admin: {\n position: 'sidebar',\n readOnly: true,\n },\n hooks: {\n afterRead: [statusBeforeRead],\n },\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:status'),\n options: [\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:active'),\n value: 'active',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:purchased'),\n value: 'purchased',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:abandoned'),\n value: 'abandoned',\n },\n ],\n virtual: true,\n },\n ...(currenciesConfig\n ? [\n {\n type: 'row',\n admin: { position: 'sidebar' },\n fields: [\n amountField({\n currenciesConfig,\n overrides: {\n name: 'subtotal',\n\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:subtotal'),\n },\n }),\n currencyField({\n currenciesConfig,\n }),\n ],\n } as Field,\n ]\n : []),\n ]\n\n // Internal access function for guest users (unauthenticated)\n const isGuest: Access = ({ req }) => !req.user\n\n const baseConfig: CollectionConfig = {\n slug: cartsSlug,\n access: {\n create: accessOR(\n access.isAdmin,\n access.isAuthenticated,\n conditional(allowGuestCarts, isGuest),\n ),\n delete: accessOR(\n access.isAdmin,\n access.isDocumentOwner,\n hasCartSecretAccess(allowGuestCarts),\n ),\n read: accessOR(access.isAdmin, access.isDocumentOwner, hasCartSecretAccess(allowGuestCarts)),\n update: accessOR(\n access.isAdmin,\n access.isDocumentOwner,\n hasCartSecretAccess(allowGuestCarts),\n ),\n },\n admin: {\n description: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:cartsCollectionDescription'),\n group: 'Ecommerce',\n useAsTitle: 'createdAt',\n },\n endpoints: [\n addItemEndpoint({ cartItemMatcher, cartsSlug }),\n clearCartEndpoint({ cartsSlug }),\n // mergeCartEndpoint uses its own matcher that handles CartItemData for both items\n mergeCartEndpoint({ cartsSlug }),\n removeItemEndpoint({ cartsSlug }),\n updateItemEndpoint({ cartsSlug }),\n ],\n fields,\n hooks: {\n afterRead: [\n ({ doc, req }) => {\n // Include secret only if this was just created (stored in context by beforeChange)\n if (req.context?.newCartSecret) {\n doc.secret = req.context.newCartSecret\n }\n // Secret is otherwise never exposed (field access is locked)\n return doc\n },\n ],\n beforeChange: [\n // This hook can be used to update the subtotal before saving the cart\n beforeChangeCart({ productsSlug, variantsSlug }),\n ],\n },\n labels: {\n plural: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:carts'),\n singular: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:cart'),\n },\n timestamps: true,\n }\n\n return { ...baseConfig }\n}\n"],"names":["amountField","cartItemsField","currencyField","accessOR","conditional","beforeChangeCart","addItemEndpoint","clearCartEndpoint","mergeCartEndpoint","removeItemEndpoint","updateItemEndpoint","hasCartSecretAccess","statusBeforeRead","createCartsCollection","props","access","allowGuestCarts","cartItemMatcher","currenciesConfig","customersSlug","enableVariants","productsSlug","variantsSlug","cartsSlug","fields","overrides","label","t","labels","plural","singular","name","type","create","read","update","admin","hidden","position","readOnly","index","relationTo","date","pickerAppearance","hooks","afterRead","options","value","virtual","isGuest","req","user","baseConfig","slug","isAdmin","isAuthenticated","delete","isDocumentOwner","description","group","useAsTitle","endpoints","doc","context","newCartSecret","secret","beforeChange","timestamps"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { CollectionSlug, Endpoint } from 'payload';
2
+ import type { CartItemMatcher } from '../operations/types.js';
3
+ type Args = {
4
+ cartItemMatcher?: CartItemMatcher;
5
+ cartsSlug: CollectionSlug;
6
+ };
7
+ /**
8
+ * Creates an endpoint handler for adding items to a cart.
9
+ *
10
+ * Route: POST /api/{cartsSlug}/:id/add-item
11
+ *
12
+ * Request body:
13
+ * - item: { product: string, variant?: string, ...customFields }
14
+ * - quantity?: number (defaults to 1)
15
+ * - secret?: string (for guest cart access)
16
+ */
17
+ export declare const addItemEndpoint: ({ cartItemMatcher, cartsSlug }: Args) => Endpoint;
18
+ export {};
19
+ //# sourceMappingURL=addItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addItem.d.ts","sourceRoot":"","sources":["../../../../src/collections/carts/endpoints/addItem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAIvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAI7D,KAAK,IAAI,GAAG;IACV,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,SAAS,EAAE,cAAc,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,mCAAoC,IAAI,KAAG,QAyCrE,CAAA"}
@@ -0,0 +1,54 @@
1
+ import { addDataAndFileToRequest } from 'payload';
2
+ import { addItem } from '../operations/addItem.js';
3
+ /**
4
+ * Creates an endpoint handler for adding items to a cart.
5
+ *
6
+ * Route: POST /api/{cartsSlug}/:id/add-item
7
+ *
8
+ * Request body:
9
+ * - item: { product: string, variant?: string, ...customFields }
10
+ * - quantity?: number (defaults to 1)
11
+ * - secret?: string (for guest cart access)
12
+ */ export const addItemEndpoint = ({ cartItemMatcher, cartsSlug })=>({
13
+ handler: async (req)=>{
14
+ await addDataAndFileToRequest(req);
15
+ const cartID = req.routeParams?.id;
16
+ const data = req.data;
17
+ if (!cartID) {
18
+ return Response.json({
19
+ message: 'Cart ID is required',
20
+ success: false
21
+ }, {
22
+ status: 400
23
+ });
24
+ }
25
+ if (!data?.item?.product) {
26
+ return Response.json({
27
+ message: 'Item with product ID is required',
28
+ success: false
29
+ }, {
30
+ status: 400
31
+ });
32
+ }
33
+ const result = await addItem({
34
+ cartID,
35
+ cartItemMatcher,
36
+ cartsSlug,
37
+ item: data.item,
38
+ payload: req.payload,
39
+ quantity: data.quantity,
40
+ req,
41
+ secret: data.secret
42
+ });
43
+ if (!result.success) {
44
+ return Response.json(result, {
45
+ status: 404
46
+ });
47
+ }
48
+ return Response.json(result);
49
+ },
50
+ method: 'post',
51
+ path: '/:id/add-item'
52
+ });
53
+
54
+ //# sourceMappingURL=addItem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/collections/carts/endpoints/addItem.ts"],"sourcesContent":["import type { CollectionSlug, Endpoint } from 'payload'\n\nimport { addDataAndFileToRequest } from 'payload'\n\nimport type { CartItemMatcher } from '../operations/types.js'\n\nimport { addItem } from '../operations/addItem.js'\n\ntype Args = {\n cartItemMatcher?: CartItemMatcher\n cartsSlug: CollectionSlug\n}\n\n/**\n * Creates an endpoint handler for adding items to a cart.\n *\n * Route: POST /api/{cartsSlug}/:id/add-item\n *\n * Request body:\n * - item: { product: string, variant?: string, ...customFields }\n * - quantity?: number (defaults to 1)\n * - secret?: string (for guest cart access)\n */\nexport const addItemEndpoint = ({ cartItemMatcher, cartsSlug }: Args): Endpoint => ({\n handler: async (req) => {\n await addDataAndFileToRequest(req)\n\n const cartID = req.routeParams?.id as string | undefined\n const data = req.data as {\n item?: { [key: string]: unknown; product: string; variant?: string }\n quantity?: number\n secret?: string\n }\n\n if (!cartID) {\n return Response.json({ message: 'Cart ID is required', success: false }, { status: 400 })\n }\n\n if (!data?.item?.product) {\n return Response.json(\n { message: 'Item with product ID is required', success: false },\n { status: 400 },\n )\n }\n\n const result = await addItem({\n cartID,\n cartItemMatcher,\n cartsSlug,\n item: data.item,\n payload: req.payload,\n quantity: data.quantity,\n req,\n secret: data.secret,\n })\n\n if (!result.success) {\n return Response.json(result, { status: 404 })\n }\n\n return Response.json(result)\n },\n method: 'post',\n path: '/:id/add-item',\n})\n"],"names":["addDataAndFileToRequest","addItem","addItemEndpoint","cartItemMatcher","cartsSlug","handler","req","cartID","routeParams","id","data","Response","json","message","success","status","item","product","result","payload","quantity","secret","method","path"],"mappings":"AAEA,SAASA,uBAAuB,QAAQ,UAAS;AAIjD,SAASC,OAAO,QAAQ,2BAA0B;AAOlD;;;;;;;;;CASC,GACD,OAAO,MAAMC,kBAAkB,CAAC,EAAEC,eAAe,EAAEC,SAAS,EAAQ,GAAgB,CAAA;QAClFC,SAAS,OAAOC;YACd,MAAMN,wBAAwBM;YAE9B,MAAMC,SAASD,IAAIE,WAAW,EAAEC;YAChC,MAAMC,OAAOJ,IAAII,IAAI;YAMrB,IAAI,CAACH,QAAQ;gBACX,OAAOI,SAASC,IAAI,CAAC;oBAAEC,SAAS;oBAAuBC,SAAS;gBAAM,GAAG;oBAAEC,QAAQ;gBAAI;YACzF;YAEA,IAAI,CAACL,MAAMM,MAAMC,SAAS;gBACxB,OAAON,SAASC,IAAI,CAClB;oBAAEC,SAAS;oBAAoCC,SAAS;gBAAM,GAC9D;oBAAEC,QAAQ;gBAAI;YAElB;YAEA,MAAMG,SAAS,MAAMjB,QAAQ;gBAC3BM;gBACAJ;gBACAC;gBACAY,MAAMN,KAAKM,IAAI;gBACfG,SAASb,IAAIa,OAAO;gBACpBC,UAAUV,KAAKU,QAAQ;gBACvBd;gBACAe,QAAQX,KAAKW,MAAM;YACrB;YAEA,IAAI,CAACH,OAAOJ,OAAO,EAAE;gBACnB,OAAOH,SAASC,IAAI,CAACM,QAAQ;oBAAEH,QAAQ;gBAAI;YAC7C;YAEA,OAAOJ,SAASC,IAAI,CAACM;QACvB;QACAI,QAAQ;QACRC,MAAM;IACR,CAAA,EAAE"}
@@ -0,0 +1,15 @@
1
+ import type { CollectionSlug, Endpoint } from 'payload';
2
+ type Args = {
3
+ cartsSlug: CollectionSlug;
4
+ };
5
+ /**
6
+ * Creates an endpoint handler for clearing all items from a cart.
7
+ *
8
+ * Route: POST /api/{cartsSlug}/:id/clear
9
+ *
10
+ * Request body:
11
+ * - secret?: string (for guest cart access)
12
+ */
13
+ export declare const clearCartEndpoint: ({ cartsSlug }: Args) => Endpoint;
14
+ export {};
15
+ //# sourceMappingURL=clearCart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clearCart.d.ts","sourceRoot":"","sources":["../../../../src/collections/carts/endpoints/clearCart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAMvD,KAAK,IAAI,GAAG;IACV,SAAS,EAAE,cAAc,CAAA;CAC1B,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,kBAAmB,IAAI,KAAG,QA6BtD,CAAA"}
@@ -0,0 +1,41 @@
1
+ import { addDataAndFileToRequest } from 'payload';
2
+ import { clearCart } from '../operations/clearCart.js';
3
+ /**
4
+ * Creates an endpoint handler for clearing all items from a cart.
5
+ *
6
+ * Route: POST /api/{cartsSlug}/:id/clear
7
+ *
8
+ * Request body:
9
+ * - secret?: string (for guest cart access)
10
+ */ export const clearCartEndpoint = ({ cartsSlug })=>({
11
+ handler: async (req)=>{
12
+ await addDataAndFileToRequest(req);
13
+ const cartID = req.routeParams?.id;
14
+ const data = req.data;
15
+ if (!cartID) {
16
+ return Response.json({
17
+ message: 'Cart ID is required',
18
+ success: false
19
+ }, {
20
+ status: 400
21
+ });
22
+ }
23
+ const result = await clearCart({
24
+ cartID,
25
+ cartsSlug,
26
+ payload: req.payload,
27
+ req,
28
+ secret: data?.secret
29
+ });
30
+ if (!result.success) {
31
+ return Response.json(result, {
32
+ status: 404
33
+ });
34
+ }
35
+ return Response.json(result);
36
+ },
37
+ method: 'post',
38
+ path: '/:id/clear'
39
+ });
40
+
41
+ //# sourceMappingURL=clearCart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/collections/carts/endpoints/clearCart.ts"],"sourcesContent":["import type { CollectionSlug, Endpoint } from 'payload'\n\nimport { addDataAndFileToRequest } from 'payload'\n\nimport { clearCart } from '../operations/clearCart.js'\n\ntype Args = {\n cartsSlug: CollectionSlug\n}\n\n/**\n * Creates an endpoint handler for clearing all items from a cart.\n *\n * Route: POST /api/{cartsSlug}/:id/clear\n *\n * Request body:\n * - secret?: string (for guest cart access)\n */\nexport const clearCartEndpoint = ({ cartsSlug }: Args): Endpoint => ({\n handler: async (req) => {\n await addDataAndFileToRequest(req)\n\n const cartID = req.routeParams?.id as string | undefined\n const data = req.data as {\n secret?: string\n }\n\n if (!cartID) {\n return Response.json({ message: 'Cart ID is required', success: false }, { status: 400 })\n }\n\n const result = await clearCart({\n cartID,\n cartsSlug,\n payload: req.payload,\n req,\n secret: data?.secret,\n })\n\n if (!result.success) {\n return Response.json(result, { status: 404 })\n }\n\n return Response.json(result)\n },\n method: 'post',\n path: '/:id/clear',\n})\n"],"names":["addDataAndFileToRequest","clearCart","clearCartEndpoint","cartsSlug","handler","req","cartID","routeParams","id","data","Response","json","message","success","status","result","payload","secret","method","path"],"mappings":"AAEA,SAASA,uBAAuB,QAAQ,UAAS;AAEjD,SAASC,SAAS,QAAQ,6BAA4B;AAMtD;;;;;;;CAOC,GACD,OAAO,MAAMC,oBAAoB,CAAC,EAAEC,SAAS,EAAQ,GAAgB,CAAA;QACnEC,SAAS,OAAOC;YACd,MAAML,wBAAwBK;YAE9B,MAAMC,SAASD,IAAIE,WAAW,EAAEC;YAChC,MAAMC,OAAOJ,IAAII,IAAI;YAIrB,IAAI,CAACH,QAAQ;gBACX,OAAOI,SAASC,IAAI,CAAC;oBAAEC,SAAS;oBAAuBC,SAAS;gBAAM,GAAG;oBAAEC,QAAQ;gBAAI;YACzF;YAEA,MAAMC,SAAS,MAAMd,UAAU;gBAC7BK;gBACAH;gBACAa,SAASX,IAAIW,OAAO;gBACpBX;gBACAY,QAAQR,MAAMQ;YAChB;YAEA,IAAI,CAACF,OAAOF,OAAO,EAAE;gBACnB,OAAOH,SAASC,IAAI,CAACI,QAAQ;oBAAED,QAAQ;gBAAI;YAC7C;YAEA,OAAOJ,SAASC,IAAI,CAACI;QACvB;QACAG,QAAQ;QACRC,MAAM;IACR,CAAA,EAAE"}
@@ -0,0 +1,21 @@
1
+ import type { CollectionSlug, Endpoint } from 'payload';
2
+ import type { MergeCartArgs } from '../operations/mergeCart.js';
3
+ type Args = {
4
+ cartItemMatcher?: MergeCartArgs['cartItemMatcher'];
5
+ cartsSlug: CollectionSlug;
6
+ };
7
+ /**
8
+ * Creates an endpoint handler for merging a guest cart into the authenticated user's cart.
9
+ * This is used when a guest with an existing cart logs in.
10
+ *
11
+ * Route: POST /api/{cartsSlug}/:id/merge
12
+ *
13
+ * Request body:
14
+ * - sourceCartID: string - The ID of the guest cart to merge from
15
+ * - sourceSecret: string - The secret of the guest cart for verification
16
+ *
17
+ * Requires authentication - the :id in the URL is the target cart which must belong to the user.
18
+ */
19
+ export declare const mergeCartEndpoint: ({ cartItemMatcher, cartsSlug }: Args) => Endpoint;
20
+ export {};
21
+ //# sourceMappingURL=mergeCart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeCart.d.ts","sourceRoot":"","sources":["../../../../src/collections/carts/endpoints/mergeCart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAIvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAI/D,KAAK,IAAI,GAAG;IACV,eAAe,CAAC,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAA;IAClD,SAAS,EAAE,cAAc,CAAA;CAC1B,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,mCAAoC,IAAI,KAAG,QAsDvE,CAAA"}
@@ -0,0 +1,72 @@
1
+ import { addDataAndFileToRequest } from 'payload';
2
+ import { mergeCart } from '../operations/mergeCart.js';
3
+ /**
4
+ * Creates an endpoint handler for merging a guest cart into the authenticated user's cart.
5
+ * This is used when a guest with an existing cart logs in.
6
+ *
7
+ * Route: POST /api/{cartsSlug}/:id/merge
8
+ *
9
+ * Request body:
10
+ * - sourceCartID: string - The ID of the guest cart to merge from
11
+ * - sourceSecret: string - The secret of the guest cart for verification
12
+ *
13
+ * Requires authentication - the :id in the URL is the target cart which must belong to the user.
14
+ */ export const mergeCartEndpoint = ({ cartItemMatcher, cartsSlug })=>({
15
+ handler: async (req)=>{
16
+ // This endpoint requires authentication
17
+ if (!req.user) {
18
+ return Response.json({
19
+ message: 'Authentication required',
20
+ success: false
21
+ }, {
22
+ status: 401
23
+ });
24
+ }
25
+ await addDataAndFileToRequest(req);
26
+ const targetCartID = req.routeParams?.id;
27
+ const data = req.data;
28
+ if (!targetCartID) {
29
+ return Response.json({
30
+ message: 'Target cart ID is required',
31
+ success: false
32
+ }, {
33
+ status: 400
34
+ });
35
+ }
36
+ if (!data?.sourceCartID) {
37
+ return Response.json({
38
+ message: 'Source cart ID is required',
39
+ success: false
40
+ }, {
41
+ status: 400
42
+ });
43
+ }
44
+ if (!data?.sourceSecret) {
45
+ return Response.json({
46
+ message: 'Source cart secret is required',
47
+ success: false
48
+ }, {
49
+ status: 400
50
+ });
51
+ }
52
+ const result = await mergeCart({
53
+ cartItemMatcher,
54
+ cartsSlug,
55
+ payload: req.payload,
56
+ req,
57
+ sourceCartID: data.sourceCartID,
58
+ sourceSecret: data.sourceSecret,
59
+ targetCartID
60
+ });
61
+ if (!result.success) {
62
+ return Response.json(result, {
63
+ status: 404
64
+ });
65
+ }
66
+ return Response.json(result);
67
+ },
68
+ method: 'post',
69
+ path: '/:id/merge'
70
+ });
71
+
72
+ //# sourceMappingURL=mergeCart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/collections/carts/endpoints/mergeCart.ts"],"sourcesContent":["import type { CollectionSlug, Endpoint } from 'payload'\n\nimport { addDataAndFileToRequest } from 'payload'\n\nimport type { MergeCartArgs } from '../operations/mergeCart.js'\n\nimport { mergeCart } from '../operations/mergeCart.js'\n\ntype Args = {\n cartItemMatcher?: MergeCartArgs['cartItemMatcher']\n cartsSlug: CollectionSlug\n}\n\n/**\n * Creates an endpoint handler for merging a guest cart into the authenticated user's cart.\n * This is used when a guest with an existing cart logs in.\n *\n * Route: POST /api/{cartsSlug}/:id/merge\n *\n * Request body:\n * - sourceCartID: string - The ID of the guest cart to merge from\n * - sourceSecret: string - The secret of the guest cart for verification\n *\n * Requires authentication - the :id in the URL is the target cart which must belong to the user.\n */\nexport const mergeCartEndpoint = ({ cartItemMatcher, cartsSlug }: Args): Endpoint => ({\n handler: async (req) => {\n // This endpoint requires authentication\n if (!req.user) {\n return Response.json({ message: 'Authentication required', success: false }, { status: 401 })\n }\n\n await addDataAndFileToRequest(req)\n\n const targetCartID = req.routeParams?.id as string | undefined\n const data = req.data as {\n sourceCartID?: string\n sourceSecret?: string\n }\n\n if (!targetCartID) {\n return Response.json(\n { message: 'Target cart ID is required', success: false },\n { status: 400 },\n )\n }\n\n if (!data?.sourceCartID) {\n return Response.json(\n { message: 'Source cart ID is required', success: false },\n { status: 400 },\n )\n }\n\n if (!data?.sourceSecret) {\n return Response.json(\n { message: 'Source cart secret is required', success: false },\n { status: 400 },\n )\n }\n\n const result = await mergeCart({\n cartItemMatcher,\n cartsSlug,\n payload: req.payload,\n req,\n sourceCartID: data.sourceCartID,\n sourceSecret: data.sourceSecret,\n targetCartID,\n })\n\n if (!result.success) {\n return Response.json(result, { status: 404 })\n }\n\n return Response.json(result)\n },\n method: 'post',\n path: '/:id/merge',\n})\n"],"names":["addDataAndFileToRequest","mergeCart","mergeCartEndpoint","cartItemMatcher","cartsSlug","handler","req","user","Response","json","message","success","status","targetCartID","routeParams","id","data","sourceCartID","sourceSecret","result","payload","method","path"],"mappings":"AAEA,SAASA,uBAAuB,QAAQ,UAAS;AAIjD,SAASC,SAAS,QAAQ,6BAA4B;AAOtD;;;;;;;;;;;CAWC,GACD,OAAO,MAAMC,oBAAoB,CAAC,EAAEC,eAAe,EAAEC,SAAS,EAAQ,GAAgB,CAAA;QACpFC,SAAS,OAAOC;YACd,wCAAwC;YACxC,IAAI,CAACA,IAAIC,IAAI,EAAE;gBACb,OAAOC,SAASC,IAAI,CAAC;oBAAEC,SAAS;oBAA2BC,SAAS;gBAAM,GAAG;oBAAEC,QAAQ;gBAAI;YAC7F;YAEA,MAAMZ,wBAAwBM;YAE9B,MAAMO,eAAeP,IAAIQ,WAAW,EAAEC;YACtC,MAAMC,OAAOV,IAAIU,IAAI;YAKrB,IAAI,CAACH,cAAc;gBACjB,OAAOL,SAASC,IAAI,CAClB;oBAAEC,SAAS;oBAA8BC,SAAS;gBAAM,GACxD;oBAAEC,QAAQ;gBAAI;YAElB;YAEA,IAAI,CAACI,MAAMC,cAAc;gBACvB,OAAOT,SAASC,IAAI,CAClB;oBAAEC,SAAS;oBAA8BC,SAAS;gBAAM,GACxD;oBAAEC,QAAQ;gBAAI;YAElB;YAEA,IAAI,CAACI,MAAME,cAAc;gBACvB,OAAOV,SAASC,IAAI,CAClB;oBAAEC,SAAS;oBAAkCC,SAAS;gBAAM,GAC5D;oBAAEC,QAAQ;gBAAI;YAElB;YAEA,MAAMO,SAAS,MAAMlB,UAAU;gBAC7BE;gBACAC;gBACAgB,SAASd,IAAIc,OAAO;gBACpBd;gBACAW,cAAcD,KAAKC,YAAY;gBAC/BC,cAAcF,KAAKE,YAAY;gBAC/BL;YACF;YAEA,IAAI,CAACM,OAAOR,OAAO,EAAE;gBACnB,OAAOH,SAASC,IAAI,CAACU,QAAQ;oBAAEP,QAAQ;gBAAI;YAC7C;YAEA,OAAOJ,SAASC,IAAI,CAACU;QACvB;QACAE,QAAQ;QACRC,MAAM;IACR,CAAA,EAAE"}
@@ -0,0 +1,16 @@
1
+ import type { CollectionSlug, Endpoint } from 'payload';
2
+ type Args = {
3
+ cartsSlug: CollectionSlug;
4
+ };
5
+ /**
6
+ * Creates an endpoint handler for removing items from a cart.
7
+ *
8
+ * Route: POST /api/{cartsSlug}/:id/remove-item
9
+ *
10
+ * Request body:
11
+ * - itemID: string (the cart item row ID to remove)
12
+ * - secret?: string (for guest cart access)
13
+ */
14
+ export declare const removeItemEndpoint: ({ cartsSlug }: Args) => Endpoint;
15
+ export {};
16
+ //# sourceMappingURL=removeItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"removeItem.d.ts","sourceRoot":"","sources":["../../../../src/collections/carts/endpoints/removeItem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAMvD,KAAK,IAAI,GAAG;IACV,SAAS,EAAE,cAAc,CAAA;CAC1B,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,kBAAmB,IAAI,KAAG,QAmCvD,CAAA"}