@nexo-labs/payload-stripe-inventory 1.6.11 → 1.6.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,7 @@
1
1
  import { S as generateUserInventory, _ as PricingType, a as getPermissionsSlugs, b as permissionSlugs, d as COLLECTION_SLUG_PRICES, f as COLLECTION_SLUG_PRODUCTS, g as PricingPlanInterval, m as MAX_UNLOCKS_PER_WEEK, n as countWeeklyUnlocksQuery, p as COLLECTION_SLUG_USER, r as checkIfUserCanUnlockQuery, u as COLLECTION_SLUG_CUSTOMERS, x as generateCustomerInventory, y as formatOptions } from "../src-BmlQoR4x.mjs";
2
+ import { stripePlugin } from "@payloadcms/plugin-stripe";
2
3
  import Stripe from "stripe";
3
- import { headers } from "next/headers.js";
4
- import { NextResponse } from "next/server.js";
5
4
  import { COLLECTION_SLUG_TAXONOMY, buildTaxonomyRelationship } from "@nexo-labs/payload-taxonomies";
6
- import { stripePlugin } from "@payloadcms/plugin-stripe";
7
5
 
8
6
  //#region src/server/utils/payload/upsert.ts
9
7
  const payloadUpsert = async ({ payload, collection, data, where }) => {
@@ -42,7 +40,7 @@ const updatePrices = async (payload) => {
42
40
  limit: 100,
43
41
  active: true
44
42
  })).data.map((price) => priceUpsert(price, payload));
45
- const pricesByProductId = (await Promise.all(promises)).mapNotNull((t) => t).reduce((acc, { productId, priceId }) => {
43
+ const pricesByProductId = (await Promise.all(promises)).filter((p) => p !== null).reduce((acc, { productId, priceId }) => {
46
44
  if (!acc[productId]) acc[productId] = [];
47
45
  acc[productId].push(priceId);
48
46
  return acc;
@@ -468,13 +466,6 @@ const customerDeleted = async (customer, payload) => {
468
466
  }
469
467
  };
470
468
 
471
- //#endregion
472
- //#region src/server/access/get-current-user-query.ts
473
- async function getCurrentUserQuery(payload) {
474
- const headers$1 = await headers();
475
- return (await payload.auth({ headers: headers$1 })).user;
476
- }
477
-
478
469
  //#endregion
479
470
  //#region src/server/actions/unlock-item-for-user-action.ts
480
471
  const addUniqueUnlock = (unlocks, collection, contentId) => {
@@ -485,9 +476,16 @@ const addUniqueUnlock = (unlocks, collection, contentId) => {
485
476
  dateUnlocked: /* @__PURE__ */ new Date()
486
477
  }];
487
478
  };
488
- const unlockItemForUser = async (getPayload, collection, contentId) => {
489
- const payload = await getPayload();
490
- const user = await getCurrentUserQuery(payload);
479
+ /**
480
+ * Unlocks an item for a user, adding it to their inventory.
481
+ *
482
+ * @param payload - The Payload instance
483
+ * @param user - The authenticated user
484
+ * @param collection - The collection slug of the item to unlock
485
+ * @param contentId - The ID of the item to unlock
486
+ * @returns Result indicating success or error message
487
+ */
488
+ const unlockItemForUser = async (payload, user, collection, contentId) => {
491
489
  if (!user || !user.id) return { error: "Usuario no válido" };
492
490
  const item = await payload.findByID({
493
491
  collection,
@@ -549,148 +547,336 @@ async function getCustomerFromStripeOrCreate(email, name) {
549
547
  }
550
548
 
551
549
  //#endregion
552
- //#region src/server/api/handle-donation.ts
553
- async function handleDonation(request, getPayload, getRoutes) {
554
- const payload = await getPayload();
555
- const payloadUser = await getCurrentUserQuery(payload);
556
- if (!payloadUser || !payloadUser.email) throw new Error("You must be logged in to make a donation");
557
- const amountParam = new URL(request.url).searchParams.get("amount");
558
- if (!amountParam) throw new Error("Amount is required");
559
- const amount = parseInt(amountParam);
560
- if (amount < 100) throw new Error("Minimum donation amount is €1");
561
- const stripe = stripeBuilder();
562
- const customerId = await getCustomerFromStripeOrCreate(payloadUser.email, payloadUser.name);
563
- await upsertCustomerInventoryAndSyncWithUser(payload, payloadUser.customer?.inventory, payloadUser.email, customerId);
564
- const metadata = { type: "donation" };
565
- const session = await stripe.checkout.sessions.create({
566
- customer: customerId,
567
- payment_method_types: ["card"],
568
- line_items: [{
569
- price_data: {
570
- currency: "eur",
571
- product_data: {
572
- name: "Donación - Portal Escohotado",
573
- description: "Apoyo al mantenimiento del legado digital de Antonio Escohotado"
550
+ //#region src/server/endpoints/validators/request-validator.ts
551
+ /**
552
+ * Creates a JSON response using Web API Response
553
+ */
554
+ function jsonResponse(data, options) {
555
+ return new Response(JSON.stringify(data), {
556
+ headers: { "Content-Type": "application/json" },
557
+ ...options
558
+ });
559
+ }
560
+ /**
561
+ * Creates a redirect response using Web API Response
562
+ * @param url - The URL to redirect to
563
+ * @param status - HTTP status code (default: 303 See Other)
564
+ */
565
+ function redirectResponse(url, status = 303) {
566
+ return new Response(null, {
567
+ status,
568
+ headers: { Location: url }
569
+ });
570
+ }
571
+ /**
572
+ * Creates an error response
573
+ */
574
+ function errorResponse(message, status = 400) {
575
+ return jsonResponse({ error: message }, { status });
576
+ }
577
+ /**
578
+ * Validates that the request has an authenticated user
579
+ * Uses the config's resolveUser if provided, otherwise uses request.user
580
+ */
581
+ async function validateAuthenticatedRequest(request, config) {
582
+ if (config.checkPermissions) {
583
+ if (!await config.checkPermissions(request)) return {
584
+ success: false,
585
+ error: errorResponse("Permission denied", 403)
586
+ };
587
+ }
588
+ let user = null;
589
+ if (config.resolveUser) user = await config.resolveUser(request);
590
+ else user = request.user;
591
+ if (!user) return {
592
+ success: false,
593
+ error: errorResponse("You must be logged in to access this endpoint", 401)
594
+ };
595
+ if (!user.email) return {
596
+ success: false,
597
+ error: errorResponse("User email is required", 400)
598
+ };
599
+ return {
600
+ success: true,
601
+ user,
602
+ payload: request.payload
603
+ };
604
+ }
605
+
606
+ //#endregion
607
+ //#region src/server/endpoints/handlers/checkout-handler.ts
608
+ /**
609
+ * Creates a handler for Stripe checkout sessions (subscriptions)
610
+ *
611
+ * @param config - Endpoint configuration
612
+ * @returns PayloadHandler for checkout endpoint
613
+ */
614
+ function createCheckoutHandler(config) {
615
+ return async (request) => {
616
+ try {
617
+ const validated = await validateAuthenticatedRequest(request, config);
618
+ if (!validated.success) return validated.error;
619
+ const { user, payload } = validated;
620
+ const priceId = new URL(request.url || "").searchParams.get("priceId");
621
+ if (!priceId) return errorResponse("priceId is required", 400);
622
+ const stripe = stripeBuilder();
623
+ const customerId = await getCustomerFromStripeOrCreate(user.email, user.name);
624
+ await upsertCustomerInventoryAndSyncWithUser(payload, user.customer?.inventory, user.email, customerId);
625
+ const metadata = { type: "subscription" };
626
+ const checkoutResult = await stripe.checkout.sessions.create({
627
+ success_url: `${process.env.DOMAIN}${config.routes.subscriptionPageHref}?success=${Date.now()}`,
628
+ cancel_url: `${process.env.DOMAIN}${config.routes.subscriptionPageHref}?error=${Date.now()}`,
629
+ mode: "subscription",
630
+ customer: customerId,
631
+ client_reference_id: String(user.id),
632
+ line_items: [{
633
+ price: priceId,
634
+ quantity: 1
635
+ }],
636
+ metadata,
637
+ tax_id_collection: { enabled: true },
638
+ customer_update: {
639
+ name: "auto",
640
+ address: "auto",
641
+ shipping: "auto"
574
642
  },
575
- unit_amount: amount
576
- },
577
- quantity: 1
578
- }],
579
- mode: "payment",
580
- success_url: `${process.env.DOMAIN}${getRoutes().nextJS.subscriptionPageHref}?success=donation`,
581
- cancel_url: `${process.env.DOMAIN}${getRoutes().nextJS.subscriptionPageHref}?error=donation_cancelled`,
582
- metadata,
583
- payment_intent_data: { metadata },
584
- invoice_creation: {
585
- enabled: true,
586
- invoice_data: { metadata }
643
+ subscription_data: { metadata }
644
+ });
645
+ if (checkoutResult.url) return redirectResponse(checkoutResult.url, 303);
646
+ return errorResponse("Failed to create checkout URL", 406);
647
+ } catch (error) {
648
+ console.error("[Stripe Checkout Error]", error);
649
+ return errorResponse(error instanceof Error ? error.message : "Unknown error occurred", 500);
587
650
  }
588
- });
589
- return NextResponse.json({ url: session.url });
651
+ };
590
652
  }
591
653
 
592
654
  //#endregion
593
- //#region src/server/api/handle-update.ts
594
- async function handleUpdate(request, getPayload, getRoutes) {
595
- const payload = await getPayload();
596
- const payloadUser = await getCurrentUserQuery(payload);
597
- if (!payloadUser) throw new Error("You must be logged in to access this page");
598
- const { searchParams } = new URL(request.url);
599
- const subscriptionId = searchParams.get("subscriptionId");
600
- const cancelAtPeriodEnd = searchParams.get("cancelAtPeriodEnd") === "true";
601
- if (!subscriptionId) throw Error("SubscriptionId could not be found.");
602
- await stripeBuilder().subscriptions.update(subscriptionId, { cancel_at_period_end: cancelAtPeriodEnd });
603
- const customer = payloadUser.customer;
604
- console.error("UPDATE: customer", customer);
605
- const inventory = customer.inventory;
606
- if (inventory && inventory.subscriptions && inventory.subscriptions[subscriptionId]) inventory.subscriptions[subscriptionId].cancel_at_period_end = cancelAtPeriodEnd;
607
- await upsertCustomerInventoryAndSyncWithUser(payload, inventory, customer.email);
608
- const routes = getRoutes();
609
- return NextResponse.redirect(`${process.env.DOMAIN}${routes.nextJS.subscriptionPageHref}?refresh=${Date.now()}`, 303);
655
+ //#region src/server/endpoints/handlers/donation-handler.ts
656
+ /**
657
+ * Creates a handler for one-time donation payments
658
+ *
659
+ * @param config - Endpoint configuration
660
+ * @returns PayloadHandler for donation endpoint
661
+ */
662
+ function createDonationHandler(config) {
663
+ return async (request) => {
664
+ try {
665
+ const validated = await validateAuthenticatedRequest(request, config);
666
+ if (!validated.success) return validated.error;
667
+ const { user, payload } = validated;
668
+ const amountParam = new URL(request.url || "").searchParams.get("amount");
669
+ if (!amountParam) return errorResponse("amount is required", 400);
670
+ const amount = parseInt(amountParam, 10);
671
+ if (isNaN(amount) || amount < 100) return errorResponse("Minimum donation amount is 1 EUR (100 cents)", 400);
672
+ const stripe = stripeBuilder();
673
+ const customerId = await getCustomerFromStripeOrCreate(user.email, user.name);
674
+ await upsertCustomerInventoryAndSyncWithUser(payload, user.customer?.inventory, user.email, customerId);
675
+ const donationPageHref = config.routes.donationPageHref || config.routes.subscriptionPageHref;
676
+ const metadata = { type: "donation" };
677
+ return jsonResponse({ url: (await stripe.checkout.sessions.create({
678
+ customer: customerId,
679
+ payment_method_types: ["card"],
680
+ line_items: [{
681
+ price_data: {
682
+ currency: "eur",
683
+ product_data: {
684
+ name: "Donation",
685
+ description: "One-time donation"
686
+ },
687
+ unit_amount: amount
688
+ },
689
+ quantity: 1
690
+ }],
691
+ mode: "payment",
692
+ success_url: `${process.env.DOMAIN}${donationPageHref}?success=donation`,
693
+ cancel_url: `${process.env.DOMAIN}${donationPageHref}?error=donation_cancelled`,
694
+ metadata,
695
+ payment_intent_data: { metadata },
696
+ invoice_creation: {
697
+ enabled: true,
698
+ invoice_data: { metadata }
699
+ }
700
+ })).url });
701
+ } catch (error) {
702
+ console.error("[Stripe Donation Error]", error);
703
+ return errorResponse(error instanceof Error ? error.message : "Unknown error occurred", 500);
704
+ }
705
+ };
610
706
  }
611
707
 
612
708
  //#endregion
613
- //#region src/server/api/handle-portal.ts
614
- async function handlePortal(request, getPayload, getRoutes) {
615
- const payload = await getPayload();
616
- const payloadUser = await getCurrentUserQuery(payload);
617
- if (!payloadUser || !payloadUser.email) throw new Error("You must be logged in to access this page");
618
- const url = new URL(request.url);
619
- const cancelSubscriptionId = url.searchParams.get("cancelSubscriptionId");
620
- const updateSubscriptionId = url.searchParams.get("updateSubscriptionId");
621
- let flowData;
622
- if (cancelSubscriptionId) flowData = {
623
- type: "subscription_cancel",
624
- subscription_cancel: { subscription: cancelSubscriptionId }
709
+ //#region src/server/endpoints/handlers/portal-handler.ts
710
+ /**
711
+ * Creates a handler for Stripe Billing Portal access
712
+ *
713
+ * @param config - Endpoint configuration
714
+ * @returns PayloadHandler for portal endpoint
715
+ */
716
+ function createPortalHandler(config) {
717
+ return async (request) => {
718
+ try {
719
+ const validated = await validateAuthenticatedRequest(request, config);
720
+ if (!validated.success) return validated.error;
721
+ const { user, payload } = validated;
722
+ const url = new URL(request.url || "");
723
+ const cancelSubscriptionId = url.searchParams.get("cancelSubscriptionId");
724
+ const updateSubscriptionId = url.searchParams.get("updateSubscriptionId");
725
+ let flowData;
726
+ if (cancelSubscriptionId) flowData = {
727
+ type: "subscription_cancel",
728
+ subscription_cancel: { subscription: cancelSubscriptionId }
729
+ };
730
+ else if (updateSubscriptionId) flowData = {
731
+ type: "subscription_update",
732
+ subscription_update: { subscription: updateSubscriptionId }
733
+ };
734
+ const stripe = stripeBuilder();
735
+ const customerId = await getCustomerFromStripeOrCreate(user.email, user.name);
736
+ await upsertCustomerInventoryAndSyncWithUser(payload, user.customer?.inventory, user.email, customerId);
737
+ return redirectResponse((await stripe.billingPortal.sessions.create({
738
+ flow_data: flowData,
739
+ customer: customerId,
740
+ return_url: `${process.env.DOMAIN}${config.routes.subscriptionPageHref}`
741
+ })).url, 303);
742
+ } catch (error) {
743
+ console.error("[Stripe Portal Error]", error);
744
+ return errorResponse(error instanceof Error ? error.message : "Unknown error occurred", 500);
745
+ }
625
746
  };
626
- else if (updateSubscriptionId) flowData = {
627
- type: "subscription_update",
628
- subscription_update: { subscription: updateSubscriptionId }
747
+ }
748
+
749
+ //#endregion
750
+ //#region src/server/endpoints/handlers/update-handler.ts
751
+ /**
752
+ * Creates a handler for updating Stripe subscriptions (cancel at period end)
753
+ *
754
+ * @param config - Endpoint configuration
755
+ * @returns PayloadHandler for update endpoint
756
+ */
757
+ function createUpdateHandler(config) {
758
+ return async (request) => {
759
+ try {
760
+ const validated = await validateAuthenticatedRequest(request, config);
761
+ if (!validated.success) return validated.error;
762
+ const { user, payload } = validated;
763
+ const url = new URL(request.url || "");
764
+ const subscriptionId = url.searchParams.get("subscriptionId");
765
+ const cancelAtPeriodEnd = url.searchParams.get("cancelAtPeriodEnd") === "true";
766
+ if (!subscriptionId) return errorResponse("subscriptionId is required", 400);
767
+ await stripeBuilder().subscriptions.update(subscriptionId, { cancel_at_period_end: cancelAtPeriodEnd });
768
+ const customer = user.customer;
769
+ const inventory = customer?.inventory;
770
+ if (inventory?.subscriptions?.[subscriptionId]) inventory.subscriptions[subscriptionId].cancel_at_period_end = cancelAtPeriodEnd;
771
+ if (customer?.email) await upsertCustomerInventoryAndSyncWithUser(payload, inventory, customer.email);
772
+ return redirectResponse(`${process.env.DOMAIN}${config.routes.subscriptionPageHref}?refresh=${Date.now()}`, 303);
773
+ } catch (error) {
774
+ console.error("[Stripe Update Error]", error);
775
+ return errorResponse(error instanceof Error ? error.message : "Unknown error occurred", 500);
776
+ }
629
777
  };
630
- const stripe = stripeBuilder();
631
- const routes = getRoutes();
632
- const customerId = await getCustomerFromStripeOrCreate(payloadUser.email, payloadUser.name);
633
- await upsertCustomerInventoryAndSyncWithUser(payload, payloadUser.customer?.inventory, payloadUser.email, customerId);
634
- const session = await stripe.billingPortal.sessions.create({
635
- flow_data: flowData,
636
- customer: customerId,
637
- return_url: `${process.env.DOMAIN}${routes.nextJS.subscriptionPageHref}`
638
- });
639
- return NextResponse.redirect(session.url, 303);
640
778
  }
641
779
 
642
780
  //#endregion
643
- //#region src/server/api/handle-checkout.ts
644
- async function handleCheckout(request, getPayload, getRoutes) {
645
- const payload = await getPayload();
646
- const payloadUser = await getCurrentUserQuery(payload);
647
- const priceId = new URL(request.url).searchParams.get("priceId");
648
- if (!priceId || !payloadUser || !payloadUser.email) throw new Error("Invalid request");
649
- const stripe = stripeBuilder();
650
- const routes = getRoutes();
651
- const customerId = await getCustomerFromStripeOrCreate(payloadUser.email, payloadUser.name);
652
- await upsertCustomerInventoryAndSyncWithUser(payload, payloadUser.customer?.inventory, payloadUser.email, customerId);
653
- const metadata = { type: "subscription" };
654
- const checkoutResult = await stripe.checkout.sessions.create({
655
- success_url: `${process.env.DOMAIN}${routes.nextJS.subscriptionPageHref}?success=${Date.now()}`,
656
- cancel_url: `${process.env.DOMAIN}${routes.nextJS.subscriptionPageHref}?error=${Date.now()}`,
657
- mode: "subscription",
658
- customer: customerId,
659
- client_reference_id: String(payloadUser.id),
660
- line_items: [{
661
- price: priceId,
662
- quantity: 1
663
- }],
664
- metadata,
665
- tax_id_collection: { enabled: true },
666
- customer_update: {
667
- name: "auto",
668
- address: "auto",
669
- shipping: "auto"
781
+ //#region src/server/endpoints/index.ts
782
+ /**
783
+ * Creates all Stripe inventory endpoints
784
+ *
785
+ * @param config - Endpoint configuration
786
+ * @param basePath - Base path for endpoints (default: '/stripe')
787
+ * @returns Array of Payload endpoints
788
+ *
789
+ * @example
790
+ * ```typescript
791
+ * const endpoints = createStripeEndpoints({
792
+ * routes: { subscriptionPageHref: '/account/subscription' },
793
+ * });
794
+ * // Endpoints:
795
+ * // GET /api/stripe/checkout?priceId={id}
796
+ * // GET /api/stripe/portal
797
+ * // GET /api/stripe/update?subscriptionId={id}&cancelAtPeriodEnd={bool}
798
+ * // GET /api/stripe/donation?amount={cents}
799
+ * ```
800
+ */
801
+ function createStripeEndpoints(config, basePath = "/stripe") {
802
+ return [
803
+ {
804
+ path: `${basePath}/checkout`,
805
+ method: "get",
806
+ handler: createCheckoutHandler(config)
670
807
  },
671
- subscription_data: { metadata }
672
- });
673
- if (checkoutResult.url) return NextResponse.redirect(checkoutResult.url, 303);
674
- else return NextResponse.json("Create checkout url failed", { status: 406 });
808
+ {
809
+ path: `${basePath}/portal`,
810
+ method: "get",
811
+ handler: createPortalHandler(config)
812
+ },
813
+ {
814
+ path: `${basePath}/update`,
815
+ method: "get",
816
+ handler: createUpdateHandler(config)
817
+ },
818
+ {
819
+ path: `${basePath}/donation`,
820
+ method: "get",
821
+ handler: createDonationHandler(config)
822
+ }
823
+ ];
675
824
  }
676
825
 
677
826
  //#endregion
678
- //#region src/server/api/index.ts
679
- function createStripeInventoryHandlers(getPayload, getRoutes) {
680
- return {
681
- checkout: { GET: (request) => handleCheckout(request, getPayload, getRoutes) },
682
- portal: { GET: (request) => handlePortal(request, getPayload, getRoutes) },
683
- update: { GET: (request) => handleUpdate(request, getPayload, getRoutes) },
684
- donation: { GET: (request) => handleDonation(request, getPayload, getRoutes) }
827
+ //#region src/server/plugin/create-stripe-inventory-plugin.ts
828
+ /**
829
+ * Creates the Stripe Inventory plugin for Payload CMS
830
+ *
831
+ * This plugin:
832
+ * - Registers REST endpoints for checkout, portal, update, and donation
833
+ * - Sets up Stripe webhook handlers for subscription and payment events
834
+ * - Syncs customer data between Stripe and Payload
835
+ *
836
+ * @param config - Plugin configuration
837
+ * @returns A Payload plugin function
838
+ *
839
+ * Endpoints registered:
840
+ * - GET /api{basePath}/checkout?priceId={id} - Redirect to Stripe Checkout
841
+ * - GET /api{basePath}/portal - Redirect to Stripe Billing Portal
842
+ * - GET /api{basePath}/update?subscriptionId={id}&cancelAtPeriodEnd={bool} - Update subscription
843
+ * - GET /api{basePath}/donation?amount={cents} - Returns JSON with checkout URL
844
+ */
845
+ function createStripeInventoryPlugin(config) {
846
+ const basePath = config.basePath || "/stripe";
847
+ const endpointConfig = {
848
+ routes: config.routes,
849
+ checkPermissions: config.checkPermissions,
850
+ resolveUser: config.resolveUser
851
+ };
852
+ const onSubscriptionUpdate = config.onSubscriptionUpdate || (async () => {});
853
+ return (incomingConfig) => {
854
+ const stripeEndpoints = createStripeEndpoints(endpointConfig, basePath);
855
+ const configWithEndpoints = {
856
+ ...incomingConfig,
857
+ endpoints: [...incomingConfig.endpoints || [], ...stripeEndpoints]
858
+ };
859
+ return stripePlugin({
860
+ isTestKey: process.env.STRIPE_SECRET_KEY?.includes("sk_test"),
861
+ stripeSecretKey: process.env.STRIPE_SECRET_KEY || "",
862
+ stripeWebhooksEndpointSecret: process.env.STRIPE_WEBHOOK_SECRET,
863
+ webhooks: {
864
+ "price.deleted": async ({ event, payload }) => await priceDeleted(event.data.object, payload),
865
+ "customer.subscription.created": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate),
866
+ "customer.subscription.paused": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate),
867
+ "customer.subscription.updated": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate),
868
+ "customer.subscription.deleted": async ({ event, payload }) => await subscriptionDeleted(event.data.object, payload, onSubscriptionUpdate),
869
+ "customer.deleted": async ({ event, payload }) => await customerDeleted(event.data.object, payload),
870
+ "product.deleted": async ({ event, payload }) => await productDeleted(event.data.object, payload),
871
+ "payment_intent.succeeded": async ({ event, payload }) => {
872
+ await paymentSucceeded(event.data.object, payload);
873
+ },
874
+ "invoice.paid": async ({ event, payload }) => {
875
+ await invoiceSucceeded(event.data.object, payload);
876
+ }
877
+ }
878
+ })(configWithEndpoints);
685
879
  };
686
- }
687
- function createRouteHandlers(getPayload, getRoutes) {
688
- return { GET: async (request, { params }) => {
689
- const path = (await params).stripe[0];
690
- const handlers = createStripeInventoryHandlers(getPayload, getRoutes);
691
- if (path === "checkout" || path === "portal" || path === "update" || path === "donation") return handlers[path].GET(request);
692
- return NextResponse.json({ error: "Route not found" }, { status: 404 });
693
- } };
694
880
  }
695
881
 
696
882
  //#endregion
@@ -723,6 +909,19 @@ const loggedInOrPublished = ({ req: { user } }) => {
723
909
  return { _status: { equals: "published" } };
724
910
  };
725
911
 
912
+ //#endregion
913
+ //#region src/server/access/get-user-from-request.ts
914
+ /**
915
+ * Gets the current user from a PayloadRequest without depending on next/headers.
916
+ * This is the recommended way to get the user in Payload endpoint handlers.
917
+ *
918
+ * @param request - The PayloadRequest object
919
+ * @returns The user object or null if not authenticated
920
+ */
921
+ function getUserFromRequest(request) {
922
+ return request.user;
923
+ }
924
+
726
925
  //#endregion
727
926
  //#region src/server/collections/customers.ts
728
927
  const customers = {
@@ -1002,30 +1201,5 @@ const products = {
1002
1201
  };
1003
1202
 
1004
1203
  //#endregion
1005
- //#region src/server/plugin.ts
1006
- const plugin = (onSubscriptionUpdate) => {
1007
- return stripePlugin({
1008
- isTestKey: process.env.STRIPE_SECRET_KEY?.includes("sk_test"),
1009
- stripeSecretKey: process.env.STRIPE_SECRET_KEY || "",
1010
- stripeWebhooksEndpointSecret: process.env.STRIPE_WEBHOOK_SECRET,
1011
- webhooks: {
1012
- "price.deleted": async ({ event, payload }) => await priceDeleted(event.data.object, payload),
1013
- "customer.subscription.created": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate),
1014
- "customer.subscription.paused": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate),
1015
- "customer.subscription.updated": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate),
1016
- "customer.subscription.deleted": async ({ event, payload }) => await subscriptionDeleted(event.data.object, payload, onSubscriptionUpdate),
1017
- "customer.deleted": async ({ event, payload }) => await customerDeleted(event.data.object, payload),
1018
- "product.deleted": async ({ event, payload }) => await productDeleted(event.data.object, payload),
1019
- "payment_intent.succeeded": async ({ event, payload }) => {
1020
- await paymentSucceeded(event.data.object, payload);
1021
- },
1022
- "invoice.paid": async ({ event, payload }) => {
1023
- await invoiceSucceeded(event.data.object, payload);
1024
- }
1025
- }
1026
- });
1027
- };
1028
-
1029
- //#endregion
1030
- export { createCustomerAtStripe, createRouteHandlers, createStripeInventoryHandlers, customerDeleted, customers, getCustomer, getCustomerFromStripeOrCreate, invoiceSucceeded, isAdmin, isAdminOrCurrentUser, isAdminOrPublished, isAdminOrStripeActive, isAdminOrUserFieldMatchingCurrentUser, isAnyone, loggedInOrPublished, payloadUpsert, paymentSucceeded, permissionEvaluationField, plugin, priceDeleted, priceUpsert, prices, productDeleted, productSync, products, resolveStripeCustomer, stripeBuilder, subscriptionDeleted, subscriptionUpsert, syncCustomerByEmail, unlockItemForUser, updatePrices, updateProducts, updateProductsAndPrices, upsertCustomerInventoryAndSyncWithUser };
1204
+ export { createCheckoutHandler, createCustomerAtStripe, createDonationHandler, createPortalHandler, createStripeEndpoints, createStripeInventoryPlugin, createUpdateHandler, customerDeleted, customers, errorResponse, getCustomer, getUserFromRequest, invoiceSucceeded, isAdmin, isAdminOrCurrentUser, isAdminOrPublished, isAdminOrStripeActive, isAdminOrUserFieldMatchingCurrentUser, isAnyone, jsonResponse, loggedInOrPublished, payloadUpsert, paymentSucceeded, permissionEvaluationField, priceDeleted, priceUpsert, prices, productDeleted, productSync, products, redirectResponse, resolveStripeCustomer, stripeBuilder, subscriptionDeleted, subscriptionUpsert, syncCustomerByEmail, unlockItemForUser, updatePrices, updateProducts, updateProductsAndPrices, upsertCustomerInventoryAndSyncWithUser, validateAuthenticatedRequest };
1031
1205
  //# sourceMappingURL=index.mjs.map