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

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.
@@ -26,16 +26,6 @@ interface CustomerInventory {
26
26
  }
27
27
  //#endregion
28
28
  //#region src/types/permission.types.d.ts
29
- interface Permission {
30
- id: number;
31
- slug?: string | null;
32
- singular_name: string;
33
- updatedAt: string;
34
- createdAt: string;
35
- }
36
- interface WithPermissions {
37
- permissions?: (number | Permission)[] | null;
38
- }
39
29
  interface Subscription {
40
30
  status?: string;
41
31
  }
@@ -68,5 +58,46 @@ interface UserInventory {
68
58
  favorites: FavoriteItem[];
69
59
  }
70
60
  //#endregion
71
- export { Permission as a, WithPermissions as c, BaseUser as i, Customer as l, UnlockItem as n, Subscription as o, UserInventory as r, User as s, FavoriteItem as t, CustomerInventory as u };
72
- //# sourceMappingURL=index-BFzOtUiG.d.mts.map
61
+ //#region src/types/result.types.d.ts
62
+ /**
63
+ * A discriminated union type for representing operation results.
64
+ * Inspired by Rust's Result type.
65
+ *
66
+ * @template T - The type of the success data
67
+ * @template E - The type of the error (defaults to string)
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * function divide(a: number, b: number): Result<number> {
72
+ * if (b === 0) {
73
+ * return { error: "Cannot divide by zero" };
74
+ * }
75
+ * return { data: a / b };
76
+ * }
77
+ *
78
+ * const result = divide(10, 2);
79
+ * if (result.error) {
80
+ * console.error(result.error);
81
+ * } else {
82
+ * console.log(result.data); // 5
83
+ * }
84
+ * ```
85
+ */
86
+ type Result<T, E = string> = {
87
+ data: T;
88
+ error?: never;
89
+ } | {
90
+ data?: never;
91
+ error: E;
92
+ };
93
+ /**
94
+ * Helper to create a success result
95
+ */
96
+ declare const ok: <T>(data: T) => Result<T, never>;
97
+ /**
98
+ * Helper to create an error result
99
+ */
100
+ declare const err: <E = string>(error: E) => Result<never, E>;
101
+ //#endregion
102
+ export { UnlockItem as a, Subscription as c, CustomerInventory as d, FavoriteItem as i, User as l, err as n, UserInventory as o, ok as r, BaseUser as s, Result as t, Customer as u };
103
+ //# sourceMappingURL=index-DYkUVDtk.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-DYkUVDtk.d.mts","names":[],"sources":["../src/types/customer.types.ts","../src/types/permission.types.ts","../src/types/user-inventory.types.ts","../src/types/result.types.ts"],"sourcesContent":[],"mappings":";;;UAEiB,QAAA;;EAAA,KAAA,EAAA,MAAQ;EAMR,SAAA,EAHJ,iBAGqB;;AAEL,UAFZ,iBAAA,CAEmB;EACP,aAAO,EAAA;IACA,CAAA,GAAA,EAAA,MAAA,CAAA,EAHF,MAAA,CAAO,YAGL,GAAA;MAAO,WAAA,EAAA,MAAA,EAAA;;;;ICV1B,CAAA,GAAA,EAAA,MAAY,CAAA,EDQA,MAAA,CAAO,OCRP,GAAA;MAIZ,WAAQ,EAAA,MAIZ,EAAA;IAMI,CAAA;;;mBDLY,MAAA,CAAO;EEXnB,CAAA;EAOE,QAAA,EAAA;IAOA,CAAA,GAAA,EAAA,MAAa,CAAA,EFFH,MAAA,CAAO,OEGvB;;;;;UDbI,YAAA;;ADAjB;AAMiB,UCFA,QDEiB,CAAA,IAAA,GAAA,CAAA,CAAA;EACA,EAAA,EAAO,MAAA,GAAA,MAAA;EACZ,IAAO,CAAA,EAAA,MAAA;EACP,KAAO,CAAA,EAAA,MAAA;EACP,QAAO,CAAA,ECFvB,QDEuB,GAAA,IAAA;EAAO,KAAA,CAAA,EAAA,MAAA,EAAA;cCA7B;;;AAVG,UAcA,IAAA,SAAa,QAdD,CAAA,CAI7B;;;UCNiB,UAAA;;;EFEA,YAAQ,EECP,IFDO;EAMR,OAAA,CAAA,EAAA,GAAA;;AAEY,UEHV,YAAA,CFGiB;EACP,UAAO,EAAA,MAAA;EACP,EAAA,EAAO,MAAA;EAAO,YAAA,EEFzB,IFEyB;;;UEExB,aAAA;EDZF,OAAA,ECaJ,UDbgB,EAAA;EAIZ,SAAA,ECUF,YDVU,EAIZ;AAMb;;;;;;ADdA;AAMA;;;;;;;;;ACNA;AAIA;AAUA;;;;AChBA;AAOE;AAOA;;;KCUU;EAAA,IAAA,EACA,CADA;EAOC,KAAiD,CAAA,EAAA,KAAA;CAAlC,GAAA;EAAW,IAAA,CAAA,EAAA,KAAA;EAAP,KAAA,EALL,CAKK;CAAM;AAKtC;;;AAA2C,cAL9B,EAK8B,EAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EALf,CAKe,EAAA,GALX,MAKW,CALJ,CAKI,EAAA,KAAA,CAAA;;;;cAA9B,yBAA0B,MAAI,cAAc"}
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as Permission, c as WithPermissions, i as BaseUser, l as Customer, n as UnlockItem, o as Subscription, r as UserInventory, s as User, t as FavoriteItem, u as CustomerInventory } from "./index-BFzOtUiG.mjs";
1
+ import { a as UnlockItem, c as Subscription, d as CustomerInventory, i as FavoriteItem, l as User, n as err, o as UserInventory, r as ok, s as BaseUser, t as Result, u as Customer } from "./index-DYkUVDtk.mjs";
2
2
 
3
3
  //#region src/model/builders.d.ts
4
4
  declare const generateUserInventory: () => UserInventory;
@@ -77,25 +77,12 @@ declare const evalPermissionByRoleQuery: <T extends BaseUser>({
77
77
  content
78
78
  }: Props<T>) => boolean;
79
79
  //#endregion
80
- //#region src/model/fetch-permitted-content-query.d.ts
81
- /**
82
- * Filtra contenido basado en los permisos del usuario
83
- */
84
- declare const fetchPermittedContentQuery: <T extends BaseUser, C>(user: T | null | undefined, permissions: (Permission | number)[] | null | undefined, content: C, freeContent?: C | null) => C | null;
85
- //#endregion
86
80
  //#region src/model/get-user-permissions.d.ts
87
81
  /**
88
82
  * Obtiene los permisos de un usuario basados en su inventario y suscripciones activas
89
83
  */
90
84
  declare const getUserPermissions: (user?: BaseUser | null) => string[];
91
85
  //#endregion
92
- //#region src/model/permissions.d.ts
93
- declare const getPermissionsSlugs: ({
94
- permissions
95
- }: {
96
- permissions?: (number | Permission)[] | null | undefined;
97
- }) => any;
98
- //#endregion
99
86
  //#region src/model/check-if-user-can-unlock-query.d.ts
100
87
  /**
101
88
  * Verifica si un usuario puede desbloquear un elemento basado en sus permisos y límites semanales
@@ -119,5 +106,5 @@ declare const getNextUnlockDateQuery: (user: BaseUser<UserInventory>) => Date;
119
106
  //#region src/model/is-content-unlocked.d.ts
120
107
  declare const isContentUnlocked: (user: BaseUser<UserInventory>, contentId: number, collection: string) => boolean;
121
108
  //#endregion
122
- export { BaseUser, COLLECTION_SLUG_CUSTOMERS, COLLECTION_SLUG_PRICES, COLLECTION_SLUG_PRODUCTS, COLLECTION_SLUG_USER, Customer, CustomerInventory, FavoriteItem, MAX_UNLOCKS_PER_WEEK, PERMISSIONS, Permission, PricingPlanInterval, PricingType, QUERY_PERMISSION_TYPES, Subscription, UnlockItem, User, UserInventory, WithPermissions, checkIfUserCanUnlockQuery, countWeeklyUnlocksQuery, evalAdvancePermissionQuery, evalPermissionByRoleQuery, fetchPermittedContentQuery, formatOptions, generateCustomerInventory, generateUserInventory, getNextUnlockDateQuery, getPermissionsSlugs, getUserPermissions, isContentUnlocked, permissionSlugs };
109
+ export { BaseUser, COLLECTION_SLUG_CUSTOMERS, COLLECTION_SLUG_PRICES, COLLECTION_SLUG_PRODUCTS, COLLECTION_SLUG_USER, Customer, CustomerInventory, FavoriteItem, MAX_UNLOCKS_PER_WEEK, PERMISSIONS, PricingPlanInterval, PricingType, QUERY_PERMISSION_TYPES, Result, Subscription, UnlockItem, User, UserInventory, checkIfUserCanUnlockQuery, countWeeklyUnlocksQuery, err, evalAdvancePermissionQuery, evalPermissionByRoleQuery, formatOptions, generateCustomerInventory, generateUserInventory, getNextUnlockDateQuery, getUserPermissions, isContentUnlocked, ok, permissionSlugs };
123
110
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/model/builders.ts","../src/model/constants.ts","../src/model/eval-advance-permissionQuery.ts","../src/model/eval-permission-by-role-query.ts","../src/model/fetch-permitted-content-query.ts","../src/model/get-user-permissions.ts","../src/model/permissions.ts","../src/model/check-if-user-can-unlock-query.ts","../src/model/get-count-weekly-unlocks-query.ts","../src/model/get-next-unlock-date-query.ts","../src/model/is-content-unlocked.ts"],"sourcesContent":[],"mappings":";;;cAEa,6BAA4B;cAK5B,iCAAgC;;;cCPhC;cACA;cACA;ADAA,cCCA,yBDD4B,EAAA,WAGvC;AAEW,cCFA,sBDOX,EAL2C;;;;ECPhC,SAAA,UAAA,EAAA,YAA8C;AAC3D,CAAA;AACa,cAiBA,eAjBuC,EAAA;EACvC,QAAA,EAAA,MAAA;EAEA,GAAA,EAAA,MAAA;EAcA,MAAA,EAAA,MAAA;EASA,IAAA,EAAA,MAAA;EAQA,QAAA,EAAA,MAAA;EAEA,KAAA,EAAA,MAAA;AAKb,CAAA;AAOa,cAtBA,WAsBsB,EAAA;;;;ACjDqB,CAAA,EAAA;AAO9B,cD4Bb,oBC5Ba,EAAA,CAAA;AAClB,cD6BK,WC7BL,EAAA;EACyB,SAAA,QAAA,EAAA,UAAA;EAAsB,SAAA,SAAA,EAAA,WAAA;AAIvD,CAAA;AAAqD,cD6BxC,mBC7BwC,EAAA;EAAQ,SAAA,GAAA,EAAA,KAAA;EAAA,SAAA,IAAA,EAAA,MAAA;EAAA,SAAA,KAAA,EAAA,OAAA;EAIpD,SAAA,IAAA,EAAA,MAAA;CAAN;AAAK,cDgCK,aChCL,EAAA,CAAA,GAAA,EDgC2B,MChC3B,CAAA,MAAA,EAAA,MAAA,CAAA,EAAA,GAAA;;;;;;;AFhBR;AAKA;UECU,kBAAgB;QAClB;iCACyB;EDVpB,WAAA,CAAA,EAAA,MAAA,EAAA,GAAA,SAA8C;AAC3D;AACa,cCYA,0BDZuC,EAAA,CAAA,UCYC,QDZD,CAAA,CAAA;EAAA,IAAA;EAAA,gBAAA;EAAA;AAAA,CAAA,ECgBjD,ODhBiD,CCgB3C,CDhB2C,CAAA,EAAA,GAAA,OAAA;;;;;ADApD;AAKA,UGAU,KHAG,CAAA,UGAa,QHKxB,CAAA,CAAA;QGJM;;;IFRK,UAAA,EAAA,MAAA;IACA,EAAA,EAAA,MAAA;EACA,CAAA;AACb;AAEa,cEWA,yBFNH,EAAA,CAAA,UEM0C,QFN1C,CAAA,CAAA;EAAA,IAAA;EAAA,WAAA;EAAA;AAAA,CAAA,EEUP,KFVO,CEUD,CFVC,CAAA,EAAA,GAAA,OAAA;;;;;ADRV;AAKa,cICA,0BJDgC,EAAA,CAAA,UICQ,QJInD,EAAA,CAAA,CAAA,CAAA,IAAA,EIHM,CJGN,GAAA,IAAA,GAAA,SAAA,EAAA,WAAA,EAAA,CIFc,UJEd,GAAA,MAAA,CAAA,EAAA,GAAA,IAAA,GAAA,SAAA,EAAA,OAAA,EIDS,CJCT,EAAA,WAAA,CAAA,EIAa,CJAb,GAAA,IAAA,EAAA,GICC,CJDD,GAAA,IAAA;;;;;AAVF;AAKa,cKFA,kBLOX,EAAA,CAAA,IAAA,CAL2C,EKFH,QLEG,GAAA,IAK3C,EAAA,GAAA,MAAA,EAAA;;;cMVW;;ANAb;0BMG0B;ANH1B,CAAA,EAAA,GAAa,GAAA;;;;;AAAb;AAKA;;;cOEa,kCACL;;;;;APRR;AAKA;;cQAa,gCACL,SAAS;;;cCNJ,+BAAgC,SAAS,mBAAiB;;;cCA1D,0BACL,SAAS"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/model/builders.ts","../src/model/constants.ts","../src/model/eval-advance-permissionQuery.ts","../src/model/eval-permission-by-role-query.ts","../src/model/get-user-permissions.ts","../src/model/check-if-user-can-unlock-query.ts","../src/model/get-count-weekly-unlocks-query.ts","../src/model/get-next-unlock-date-query.ts","../src/model/is-content-unlocked.ts"],"sourcesContent":[],"mappings":";;;cAEa,6BAA4B;cAK5B,iCAAgC;;;cCPhC;cACA;cACA;ADAA,cCCA,yBDD4B,EAAA,WAGvC;AAEW,cCFA,sBDOX,EAL2C;;;;ECPhC,SAAA,UAAA,EAAA,YAA8C;AAC3D,CAAA;AACa,cAiBA,eAjBuC,EAAA;EACvC,QAAA,EAAA,MAAA;EAEA,GAAA,EAAA,MAAA;EAcA,MAAA,EAAA,MAAA;EASA,IAAA,EAAA,MAAA;EAQA,QAAA,EAAA,MAAA;EAEA,KAAA,EAAA,MAAA;AAKb,CAAA;AAOa,cAtBA,WAsBsB,EAAA;;;;ACjDqB,CAAA,EAAA;AAO9B,cD4Bb,oBC5Ba,EAAA,CAAA;AAClB,cD6BK,WC7BL,EAAA;EACyB,SAAA,QAAA,EAAA,UAAA;EAAsB,SAAA,SAAA,EAAA,WAAA;AAIvD,CAAA;AAAqD,cD6BxC,mBC7BwC,EAAA;EAAQ,SAAA,GAAA,EAAA,KAAA;EAAA,SAAA,IAAA,EAAA,MAAA;EAAA,SAAA,KAAA,EAAA,OAAA;EAIpD,SAAA,IAAA,EAAA,MAAA;CAAN;AAAK,cDgCK,aChCL,EAAA,CAAA,GAAA,EDgC2B,MChC3B,CAAA,MAAA,EAAA,MAAA,CAAA,EAAA,GAAA;;;;;;;AFhBR;AAKA;UECU,kBAAgB;QAClB;iCACyB;EDVpB,WAAA,CAAA,EAAA,MAAA,EAAA,GAAA,SAA8C;AAC3D;AACa,cCYA,0BDZuC,EAAA,CAAA,UCYC,QDZD,CAAA,CAAA;EAAA,IAAA;EAAA,gBAAA;EAAA;AAAA,CAAA,ECgBjD,ODhBiD,CCgB3C,CDhB2C,CAAA,EAAA,GAAA,OAAA;;;;;ADApD;AAKA,UGAU,KHAG,CAAA,UGAa,QHKxB,CAAA,CAAA;QGJM;;;IFRK,UAAA,EAAA,MAAA;IACA,EAAA,EAAA,MAAA;EACA,CAAA;AACb;AAEa,cEWA,yBFNH,EAAA,CAAA,UEM0C,QFN1C,CAAA,CAAA;EAAA,IAAA;EAAA,WAAA;EAAA;AAAA,CAAA,EEUP,KFVO,CEUD,CFVC,CAAA,EAAA,GAAA,OAAA;;;;;ADRV;AAKa,cIFA,kBJOX,EAAA,CAAA,IAAA,CAL2C,EIFH,QJEG,GAAA,IAK3C,EAAA,GAAA,MAAA,EAAA;;;;;AAVF;AAKA;;;cKEa,kCACL;;;;;ALRR;AAKA;;cMAa,gCACL,SAAS;;;cCNJ,+BAAgC,SAAS,mBAAiB;;;cCA1D,0BACL,SAAS"}
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { S as generateUserInventory, _ as PricingType, a as getPermissionsSlugs, b as permissionSlugs, c as isContentUnlocked, d as COLLECTION_SLUG_PRICES, f as COLLECTION_SLUG_PRODUCTS, g as PricingPlanInterval, h as PERMISSIONS, i as fetchPermittedContentQuery, l as getUserPermissions, m as MAX_UNLOCKS_PER_WEEK, n as countWeeklyUnlocksQuery, o as evalAdvancePermissionQuery, p as COLLECTION_SLUG_USER, r as checkIfUserCanUnlockQuery, s as evalPermissionByRoleQuery, t as getNextUnlockDateQuery, u as COLLECTION_SLUG_CUSTOMERS, v as QUERY_PERMISSION_TYPES, x as generateCustomerInventory, y as formatOptions } from "./src-BmlQoR4x.mjs";
1
+ import { S as generateUserInventory, _ as PricingType, a as checkIfUserCanUnlockQuery, b as permissionSlugs, c as isContentUnlocked, d as COLLECTION_SLUG_PRICES, f as COLLECTION_SLUG_PRODUCTS, g as PricingPlanInterval, h as PERMISSIONS, i as countWeeklyUnlocksQuery, l as getUserPermissions, m as MAX_UNLOCKS_PER_WEEK, n as ok, o as evalAdvancePermissionQuery, p as COLLECTION_SLUG_USER, r as getNextUnlockDateQuery, s as evalPermissionByRoleQuery, t as err, u as COLLECTION_SLUG_CUSTOMERS, v as QUERY_PERMISSION_TYPES, x as generateCustomerInventory, y as formatOptions } from "./src-I_DPhIL5.mjs";
2
2
 
3
- export { COLLECTION_SLUG_CUSTOMERS, COLLECTION_SLUG_PRICES, COLLECTION_SLUG_PRODUCTS, COLLECTION_SLUG_USER, MAX_UNLOCKS_PER_WEEK, PERMISSIONS, PricingPlanInterval, PricingType, QUERY_PERMISSION_TYPES, checkIfUserCanUnlockQuery, countWeeklyUnlocksQuery, evalAdvancePermissionQuery, evalPermissionByRoleQuery, fetchPermittedContentQuery, formatOptions, generateCustomerInventory, generateUserInventory, getNextUnlockDateQuery, getPermissionsSlugs, getUserPermissions, isContentUnlocked, permissionSlugs };
3
+ export { COLLECTION_SLUG_CUSTOMERS, COLLECTION_SLUG_PRICES, COLLECTION_SLUG_PRODUCTS, COLLECTION_SLUG_USER, MAX_UNLOCKS_PER_WEEK, PERMISSIONS, PricingPlanInterval, PricingType, QUERY_PERMISSION_TYPES, checkIfUserCanUnlockQuery, countWeeklyUnlocksQuery, err, evalAdvancePermissionQuery, evalPermissionByRoleQuery, formatOptions, generateCustomerInventory, generateUserInventory, getNextUnlockDateQuery, getUserPermissions, isContentUnlocked, ok, permissionSlugs };
@@ -1,8 +1,9 @@
1
- import { i as BaseUser, u as CustomerInventory } from "../index-BFzOtUiG.mjs";
1
+ import { d as CustomerInventory, s as BaseUser, t as Result } from "../index-DYkUVDtk.mjs";
2
2
  import Stripe from "stripe";
3
- import { Access, CollectionConfig, Endpoint, Field, Payload, PayloadHandler, PayloadRequest, Plugin } from "payload";
3
+ import { Access, CollectionConfig, Endpoint, Payload, PayloadHandler, PayloadRequest, Plugin } from "payload";
4
4
 
5
5
  //#region src/server/plugin/stripe-inventory-types.d.ts
6
+
6
7
  /**
7
8
  * URL routes configuration for Stripe redirects
8
9
  */
@@ -14,8 +15,10 @@ interface StripeInventoryRoutes {
14
15
  }
15
16
  /**
16
17
  * Configuration for the Stripe Inventory plugin
18
+ * @template TProduct - The product type used by the consumer (defaults to unknown)
19
+ * @template TContent - The content type used by the consumer (defaults to unknown)
17
20
  */
18
- interface StripeInventoryPluginConfig {
21
+ interface StripeInventoryPluginConfig<TProduct = unknown, TContent = unknown> {
19
22
  /**
20
23
  * URL routes for redirects after Stripe operations
21
24
  */
@@ -46,7 +49,34 @@ interface StripeInventoryPluginConfig {
46
49
  * @returns The user object or null if not authenticated
47
50
  */
48
51
  resolveUser?: (request: PayloadRequest) => Promise<BaseUser | null>;
52
+ /**
53
+ * Resolves the permissions granted by a subscription.
54
+ * This callback allows you to define how permissions are extracted from a product.
55
+ * @param subscription - The Stripe subscription object
56
+ * @param product - The product associated with the subscription
57
+ * @param payload - The Payload instance
58
+ * @returns An array of permission slugs
59
+ */
60
+ resolveSubscriptionPermissions: ResolveSubscriptionPermissions<TProduct>;
61
+ /**
62
+ * Resolves the permissions required by content.
63
+ * This callback allows you to define how permissions are extracted from content items.
64
+ * @param content - The content item to check permissions for
65
+ * @param payload - The Payload instance
66
+ * @returns An array of permission slugs required by the content
67
+ */
68
+ resolveContentPermissions: ResolveContentPermissions<TContent>;
49
69
  }
70
+ /**
71
+ * Type alias for subscription permissions resolver callback
72
+ * @template TProduct - The product type used by the consumer (defaults to unknown for flexibility)
73
+ */
74
+ type ResolveSubscriptionPermissions<TProduct = unknown> = (subscription: Stripe.Subscription, product: TProduct, payload: Payload) => Promise<string[]>;
75
+ /**
76
+ * Type alias for content permissions resolver callback
77
+ * @template TContent - The content type used by the consumer (defaults to unknown for flexibility)
78
+ */
79
+ type ResolveContentPermissions<TContent = unknown> = (content: TContent, payload: Payload) => Promise<string[]>;
50
80
  /**
51
81
  * Internal configuration passed to endpoint handlers
52
82
  */
@@ -164,7 +194,7 @@ declare function createStripeEndpoints(config: StripeEndpointConfig, basePath?:
164
194
  * - GET /api{basePath}/update?subscriptionId={id}&cancelAtPeriodEnd={bool} - Update subscription
165
195
  * - GET /api{basePath}/donation?amount={cents} - Returns JSON with checkout URL
166
196
  */
167
- declare function createStripeInventoryPlugin(config: StripeInventoryPluginConfig): Plugin;
197
+ declare function createStripeInventoryPlugin<TProduct = unknown, TContent = unknown>(config: StripeInventoryPluginConfig<TProduct, TContent>): Plugin;
168
198
  //#endregion
169
199
  //#region src/server/actions/price.d.ts
170
200
  declare const updatePrices: (payload: Payload) => Promise<void>;
@@ -181,7 +211,7 @@ declare const productSync: (object: Stripe.Product, payload: Payload) => Promise
181
211
  declare const productDeleted: (object: Stripe.Product, payload: Payload) => Promise<void>;
182
212
  //#endregion
183
213
  //#region src/server/actions/subscription.d.ts
184
- declare const subscriptionUpsert: (subscription: Stripe.Subscription, payload: Payload, onSubscriptionUpdate: (type: "create" | "delete", userId: string) => Promise<void>) => Promise<void>;
214
+ declare const subscriptionUpsert: <TProduct = unknown>(subscription: Stripe.Subscription, payload: Payload, onSubscriptionUpdate: (type: "create" | "delete", userId: string) => Promise<void>, resolveSubscriptionPermissions: ResolveSubscriptionPermissions<TProduct>) => Promise<void>;
185
215
  declare const subscriptionDeleted: (subscription: Stripe.Subscription, payload: Payload, onSubscriptionUpdate: (type: "create" | "delete", userId: string) => Promise<void>) => Promise<void>;
186
216
  //#endregion
187
217
  //#region src/server/actions/donation.d.ts
@@ -194,23 +224,23 @@ declare const invoiceSucceeded: (invoiceIntent: Stripe.Invoice, payload: Payload
194
224
  declare const customerDeleted: (customer: Stripe.Customer, payload: Payload) => Promise<void>;
195
225
  //#endregion
196
226
  //#region src/server/actions/unlock-item-for-user-action.d.ts
197
- type Result<T, E = string> = {
198
- data: T;
199
- error?: never;
200
- } | {
201
- data?: never;
202
- error: E;
203
- };
204
227
  /**
205
- * Unlocks an item for a user, adding it to their inventory.
228
+ * Creates an unlock action with the specified content permissions resolver.
229
+ *
230
+ * @param resolveContentPermissions - Callback to resolve permissions required by content
231
+ * @returns A function that unlocks items for users
206
232
  *
207
- * @param payload - The Payload instance
208
- * @param user - The authenticated user
209
- * @param collection - The collection slug of the item to unlock
210
- * @param contentId - The ID of the item to unlock
211
- * @returns Result indicating success or error message
233
+ * @example
234
+ * ```typescript
235
+ * const unlockItem = createUnlockAction(async (content, payload) => {
236
+ * return content.requiredPermissions || [];
237
+ * });
238
+ *
239
+ * // Use in server actions
240
+ * await unlockItem(payload, user, 'posts', 123);
241
+ * ```
212
242
  */
213
- declare const unlockItemForUser: (payload: Payload, user: BaseUser, collection: string, contentId: number) => Promise<Result<boolean>>;
243
+ declare const createUnlockAction: <TContent = unknown>(resolveContentPermissions: ResolveContentPermissions<TContent>) => (payload: Payload, user: BaseUser, collection: string, contentId: number) => Promise<Result<boolean>>;
214
244
  //#endregion
215
245
  //#region src/server/actions/update-products-and-prices-action.d.ts
216
246
  declare function updateProductsAndPrices(payload: Payload): Promise<void>;
@@ -218,9 +248,6 @@ declare function updateProductsAndPrices(payload: Payload): Promise<void>;
218
248
  //#region src/server/collections/customers.d.ts
219
249
  declare const customers: CollectionConfig;
220
250
  //#endregion
221
- //#region src/server/collections/fields/permission-evaluation-field.d.ts
222
- declare const permissionEvaluationField: Field;
223
- //#endregion
224
251
  //#region src/server/collections/prices.d.ts
225
252
  declare const prices: CollectionConfig;
226
253
  //#endregion
@@ -305,5 +332,5 @@ declare const loggedInOrPublished: Access;
305
332
  */
306
333
  declare function getUserFromRequest(request: PayloadRequest): BaseUser | null;
307
334
  //#endregion
308
- export { AuthenticatedRequestResult, Result, type StripeEndpointConfig, type StripeInventoryPluginConfig, StripeInventoryRoutes, 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 };
335
+ export { AuthenticatedRequestResult, type ResolveContentPermissions, type ResolveSubscriptionPermissions, type StripeEndpointConfig, type StripeInventoryPluginConfig, StripeInventoryRoutes, createCheckoutHandler, createCustomerAtStripe, createDonationHandler, createPortalHandler, createStripeEndpoints, createStripeInventoryPlugin, createUnlockAction, createUpdateHandler, customerDeleted, customers, errorResponse, getCustomer, getUserFromRequest, invoiceSucceeded, isAdmin, isAdminOrCurrentUser, isAdminOrPublished, isAdminOrStripeActive, isAdminOrUserFieldMatchingCurrentUser, isAnyone, jsonResponse, loggedInOrPublished, payloadUpsert, paymentSucceeded, priceDeleted, priceUpsert, prices, productDeleted, productSync, products, redirectResponse, resolveStripeCustomer, stripeBuilder, subscriptionDeleted, subscriptionUpsert, syncCustomerByEmail, updatePrices, updateProducts, updateProductsAndPrices, upsertCustomerInventoryAndSyncWithUser, validateAuthenticatedRequest };
309
336
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/server/plugin/stripe-inventory-types.ts","../../src/server/endpoints/handlers/checkout-handler.ts","../../src/server/endpoints/handlers/donation-handler.ts","../../src/server/endpoints/handlers/portal-handler.ts","../../src/server/endpoints/handlers/update-handler.ts","../../src/server/endpoints/validators/request-validator.ts","../../src/server/endpoints/index.ts","../../src/server/plugin/create-stripe-inventory-plugin.ts","../../src/server/actions/price.ts","../../src/server/actions/product.ts","../../src/server/actions/subscription.ts","../../src/server/actions/donation.ts","../../src/server/actions/invoice.ts","../../src/server/actions/customer.ts","../../src/server/actions/unlock-item-for-user-action.ts","../../src/server/actions/update-products-and-prices-action.ts","../../src/server/collections/customers.ts","../../src/server/collections/fields/permission-evaluation-field.ts","../../src/server/collections/prices.ts","../../src/server/collections/products.ts","../../src/server/utils/payload/sync-customer-by-email.ts","../../src/server/utils/payload/upsert.ts","../../src/server/utils/payload/upsert-customer-inventory-and-sync-with-user.ts","../../src/server/utils/stripe/create-customer-at-stripe.ts","../../src/server/utils/stripe/get-customer.ts","../../src/server/utils/stripe/stripe-builder.ts","../../src/server/access/access-queries.ts","../../src/server/access/get-user-from-request.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/server/plugin/stripe-inventory-types.ts","../../src/server/endpoints/handlers/checkout-handler.ts","../../src/server/endpoints/handlers/donation-handler.ts","../../src/server/endpoints/handlers/portal-handler.ts","../../src/server/endpoints/handlers/update-handler.ts","../../src/server/endpoints/validators/request-validator.ts","../../src/server/endpoints/index.ts","../../src/server/plugin/create-stripe-inventory-plugin.ts","../../src/server/actions/price.ts","../../src/server/actions/product.ts","../../src/server/actions/subscription.ts","../../src/server/actions/donation.ts","../../src/server/actions/invoice.ts","../../src/server/actions/customer.ts","../../src/server/actions/unlock-item-for-user-action.ts","../../src/server/actions/update-products-and-prices-action.ts","../../src/server/collections/customers.ts","../../src/server/collections/prices.ts","../../src/server/collections/products.ts","../../src/server/utils/payload/sync-customer-by-email.ts","../../src/server/utils/payload/upsert.ts","../../src/server/utils/payload/upsert-customer-inventory-and-sync-with-user.ts","../../src/server/utils/stripe/create-customer-at-stripe.ts","../../src/server/utils/stripe/get-customer.ts","../../src/server/utils/stripe/stripe-builder.ts","../../src/server/access/access-queries.ts","../../src/server/access/get-user-from-request.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1,7 +1,6 @@
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";
1
+ import { S as generateUserInventory, _ as PricingType, a as checkIfUserCanUnlockQuery, b as permissionSlugs, d as COLLECTION_SLUG_PRICES, f as COLLECTION_SLUG_PRODUCTS, g as PricingPlanInterval, i as countWeeklyUnlocksQuery, m as MAX_UNLOCKS_PER_WEEK, p as COLLECTION_SLUG_USER, u as COLLECTION_SLUG_CUSTOMERS, x as generateCustomerInventory, y as formatOptions } from "../src-I_DPhIL5.mjs";
2
2
  import { stripePlugin } from "@payloadcms/plugin-stripe";
3
3
  import Stripe from "stripe";
4
- import { COLLECTION_SLUG_TAXONOMY, buildTaxonomyRelationship } from "@nexo-labs/payload-taxonomies";
5
4
 
6
5
  //#region src/server/utils/payload/upsert.ts
7
6
  const payloadUpsert = async ({ payload, collection, data, where }) => {
@@ -29,8 +28,13 @@ const payloadUpsert = async ({ payload, collection, data, where }) => {
29
28
 
30
29
  //#endregion
31
30
  //#region src/server/utils/stripe/stripe-builder.ts
31
+ let stripeInstance = null;
32
32
  const stripeBuilder = () => {
33
- return new Stripe(process.env.STRIPE_SECRET_KEY, { apiVersion: "2024-09-30.acacia" });
33
+ if (stripeInstance) return stripeInstance;
34
+ const secretKey = process.env.STRIPE_SECRET_KEY;
35
+ if (!secretKey) throw new Error("STRIPE_SECRET_KEY environment variable is not set");
36
+ stripeInstance = new Stripe(secretKey, { apiVersion: "2024-09-30.acacia" });
37
+ return stripeInstance;
34
38
  };
35
39
 
36
40
  //#endregion
@@ -45,18 +49,18 @@ const updatePrices = async (payload) => {
45
49
  acc[productId].push(priceId);
46
50
  return acc;
47
51
  }, {});
48
- Object.entries(pricesByProductId).map(async ([productId, prices$1]) => {
52
+ await Promise.all(Object.entries(pricesByProductId).map(async ([productId, prices$1]) => {
49
53
  await payload.update({
50
54
  collection: COLLECTION_SLUG_PRODUCTS,
51
55
  data: { prices: prices$1 },
52
56
  where: { stripeID: { equals: productId } }
53
57
  });
54
- });
58
+ }));
55
59
  };
56
60
  async function priceUpsert(price, payload) {
57
61
  const stripeProductID = typeof price.product === "string" ? price.product : price.product.id;
58
62
  if (price.deleted !== void 0) {
59
- priceDeleted(price, payload);
63
+ await priceDeleted(price, payload);
60
64
  return null;
61
65
  }
62
66
  if (price.unit_amount == null) return null;
@@ -97,14 +101,15 @@ const priceDeleted = async (price, payload) => {
97
101
  //#endregion
98
102
  //#region src/server/actions/product.ts
99
103
  const updateProducts = async (payload) => {
100
- (await (await stripeBuilder()).products.list({
104
+ const products$1 = await (await stripeBuilder()).products.list({
101
105
  limit: 100,
102
106
  active: true
103
- })).data.forEach((product) => productSync(product, payload));
107
+ });
108
+ await Promise.all(products$1.data.map((product) => productSync(product, payload)));
104
109
  };
105
110
  const productSync = async (object, payload) => {
106
111
  const { id: stripeProductID, name, description, images } = object;
107
- if (object.deleted !== void 0) return productDeleted(object, payload);
112
+ if (object.deleted !== void 0) return await productDeleted(object, payload);
108
113
  try {
109
114
  await payloadUpsert({
110
115
  payload,
@@ -151,7 +156,7 @@ async function syncCustomerByEmail({ email, payload }) {
151
156
  where: { email: { equals: email } }
152
157
  })).docs?.[0]?.id;
153
158
  await payload.update({
154
- collection: "users",
159
+ collection: COLLECTION_SLUG_USER,
155
160
  data: { customer: customerId },
156
161
  where: { email: { equals: email } }
157
162
  });
@@ -194,7 +199,8 @@ async function getUserIdByEmail({ email, payload }) {
194
199
  //#region src/server/utils/stripe/get-customer.ts
195
200
  async function getCustomer({ stripe, email }) {
196
201
  stripe = stripe ?? stripeBuilder();
197
- const customers$1 = await stripe.customers.search({ query: `email:'${email}'` });
202
+ const sanitizedEmail = email.replace(/'/g, "\\'");
203
+ const customers$1 = await stripe.customers.search({ query: `email:'${sanitizedEmail}'` });
198
204
  return customers$1.data.length ? customers$1.data[0] : null;
199
205
  }
200
206
  async function resolveStripeCustomer({ customer }) {
@@ -255,7 +261,7 @@ async function findOrCreateCustomer({ email, payload, stripeId }) {
255
261
 
256
262
  //#endregion
257
263
  //#region src/server/actions/subscription.ts
258
- const subscriptionUpsert = async (subscription, payload, onSubscriptionUpdate) => {
264
+ const subscriptionUpsert = async (subscription, payload, onSubscriptionUpdate, resolveSubscriptionPermissions) => {
259
265
  const { id: stripeID, status, customer: stripeCustomer } = subscription;
260
266
  const customer = await resolveStripeCustomer({ customer: stripeCustomer });
261
267
  const error = (message) => payload.logger.error("Subscription Upsert: ", message);
@@ -297,7 +303,7 @@ const subscriptionUpsert = async (subscription, payload, onSubscriptionUpdate) =
297
303
  const inventory = customer$1.inventory;
298
304
  inventory.subscriptions[stripeID] = {
299
305
  ...subscription,
300
- permissions: getPermissionsSlugs({ permissions: product.roles })
306
+ permissions: await resolveSubscriptionPermissions(subscription, product, payload)
301
307
  };
302
308
  info(`INVENTORY OF THE SUBSCRIPTION ${inventory}`);
303
309
  await upsertCustomerInventoryAndSyncWithUser(payload, inventory, email, stripeId);
@@ -345,7 +351,7 @@ const subscriptionDeleted = async (subscription, payload, onSubscriptionUpdate)
345
351
  payload.logger.error("No customer found for subscription");
346
352
  return;
347
353
  }
348
- const inventory = customer$1.inventory;
354
+ const inventory = customer$1.inventory ?? generateCustomerInventory();
349
355
  delete inventory.subscriptions[id];
350
356
  await upsertCustomerInventoryAndSyncWithUser(payload, inventory, email, stripeId);
351
357
  const userId = await getUserIdByEmail({
@@ -390,12 +396,11 @@ const paymentSucceeded = async (paymentIntent, payload) => {
390
396
  payload,
391
397
  stripeId: stripeCustomer.id
392
398
  });
393
- if (!customer) return;
394
399
  if (!customer) {
395
- payload.logger.error(`User not found for payment: ${stripeCustomer.email}`);
400
+ payload.logger.error(`Customer not found for payment: ${stripeCustomer.email}`);
396
401
  return;
397
402
  }
398
- let inventory = customer.inventory;
403
+ const inventory = customer.inventory ?? generateCustomerInventory();
399
404
  inventory.payments[id] = paymentIntent;
400
405
  await payload.update({
401
406
  collection: COLLECTION_SLUG_CUSTOMERS,
@@ -435,8 +440,11 @@ const invoiceSucceeded = async (invoiceIntent, payload) => {
435
440
  payload,
436
441
  stripeId: stripeCustomer.id
437
442
  });
438
- if (!customer) return;
439
- let inventory = customer.inventory;
443
+ if (!customer) {
444
+ payload.logger.error(`Customer not found for invoice: ${stripeCustomer.email}`);
445
+ return;
446
+ }
447
+ const inventory = customer.inventory ?? generateCustomerInventory();
440
448
  inventory.invoices[id] = invoiceIntent;
441
449
  await payload.update({
442
450
  collection: COLLECTION_SLUG_CUSTOMERS,
@@ -477,40 +485,58 @@ const addUniqueUnlock = (unlocks, collection, contentId) => {
477
485
  }];
478
486
  };
479
487
  /**
480
- * Unlocks an item for a user, adding it to their inventory.
488
+ * Creates an unlock action with the specified content permissions resolver.
489
+ *
490
+ * @param resolveContentPermissions - Callback to resolve permissions required by content
491
+ * @returns A function that unlocks items for users
481
492
  *
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
493
+ * @example
494
+ * ```typescript
495
+ * const unlockItem = createUnlockAction(async (content, payload) => {
496
+ * return content.requiredPermissions || [];
497
+ * });
498
+ *
499
+ * // Use in server actions
500
+ * await unlockItem(payload, user, 'posts', 123);
501
+ * ```
487
502
  */
488
- const unlockItemForUser = async (payload, user, collection, contentId) => {
489
- if (!user || !user.id) return { error: "Usuario no válido" };
490
- const item = await payload.findByID({
491
- collection,
492
- id: contentId.toString()
493
- });
494
- if (!item) return { error: "Elemento no encontrado" };
495
- if (!checkIfUserCanUnlockQuery(user, getPermissionsSlugs({ permissions: item.permissions }))) return { error: "No tienes permisos para desbloquear este elemento" };
496
- if (countWeeklyUnlocksQuery(user) >= MAX_UNLOCKS_PER_WEEK) return { error: `Has alcanzado el límite de ${MAX_UNLOCKS_PER_WEEK} desbloqueos para esta semana` };
497
- const inventory = user.inventory ?? generateUserInventory();
498
- const updatedUnlocks = addUniqueUnlock(inventory.unlocks, collection, contentId);
499
- if (updatedUnlocks.length === inventory.unlocks.length) return { data: true };
500
- try {
501
- await payload.update({
502
- collection: COLLECTION_SLUG_USER,
503
- id: user.id.toString(),
504
- data: { inventory: {
505
- ...inventory,
506
- unlocks: updatedUnlocks
507
- } }
503
+ const createUnlockAction = (resolveContentPermissions) => {
504
+ /**
505
+ * Unlocks an item for a user, adding it to their inventory.
506
+ *
507
+ * @param payload - The Payload instance
508
+ * @param user - The authenticated user
509
+ * @param collection - The collection slug of the item to unlock
510
+ * @param contentId - The ID of the item to unlock
511
+ * @returns Result indicating success or error message
512
+ */
513
+ return async (payload, user, collection, contentId) => {
514
+ if (!user || !user.id) return { error: "Usuario no válido" };
515
+ const item = await payload.findByID({
516
+ collection,
517
+ id: contentId.toString()
508
518
  });
509
- return { data: true };
510
- } catch (error) {
511
- console.error("Error al actualizar el inventario del usuario:", error);
512
- return { error: "Error al actualizar el inventario del usuario" };
513
- }
519
+ if (!item) return { error: "Elemento no encontrado" };
520
+ if (!checkIfUserCanUnlockQuery(user, await resolveContentPermissions(item, payload))) return { error: "No tienes permisos para desbloquear este elemento" };
521
+ if (countWeeklyUnlocksQuery(user) >= MAX_UNLOCKS_PER_WEEK) return { error: `Has alcanzado el límite de ${MAX_UNLOCKS_PER_WEEK} desbloqueos para esta semana` };
522
+ const inventory = user.inventory ?? generateUserInventory();
523
+ const updatedUnlocks = addUniqueUnlock(inventory.unlocks, collection, contentId);
524
+ if (updatedUnlocks.length === inventory.unlocks.length) return { data: true };
525
+ try {
526
+ await payload.update({
527
+ collection: COLLECTION_SLUG_USER,
528
+ id: user.id.toString(),
529
+ data: { inventory: {
530
+ ...inventory,
531
+ unlocks: updatedUnlocks
532
+ } }
533
+ });
534
+ return { data: true };
535
+ } catch (error) {
536
+ console.error("Error al actualizar el inventario del usuario:", error);
537
+ return { error: "Error al actualizar el inventario del usuario" };
538
+ }
539
+ };
514
540
  };
515
541
 
516
542
  //#endregion
@@ -617,6 +643,7 @@ function createCheckoutHandler(config) {
617
643
  const validated = await validateAuthenticatedRequest(request, config);
618
644
  if (!validated.success) return validated.error;
619
645
  const { user, payload } = validated;
646
+ if (!user.email) return errorResponse("User email is required", 400);
620
647
  const priceId = new URL(request.url || "").searchParams.get("priceId");
621
648
  if (!priceId) return errorResponse("priceId is required", 400);
622
649
  const stripe = stripeBuilder();
@@ -665,6 +692,7 @@ function createDonationHandler(config) {
665
692
  const validated = await validateAuthenticatedRequest(request, config);
666
693
  if (!validated.success) return validated.error;
667
694
  const { user, payload } = validated;
695
+ if (!user.email) return errorResponse("User email is required", 400);
668
696
  const amountParam = new URL(request.url || "").searchParams.get("amount");
669
697
  if (!amountParam) return errorResponse("amount is required", 400);
670
698
  const amount = parseInt(amountParam, 10);
@@ -719,9 +747,12 @@ function createPortalHandler(config) {
719
747
  const validated = await validateAuthenticatedRequest(request, config);
720
748
  if (!validated.success) return validated.error;
721
749
  const { user, payload } = validated;
750
+ if (!user.email) return errorResponse("User email is required", 400);
722
751
  const url = new URL(request.url || "");
723
752
  const cancelSubscriptionId = url.searchParams.get("cancelSubscriptionId");
724
753
  const updateSubscriptionId = url.searchParams.get("updateSubscriptionId");
754
+ if (cancelSubscriptionId && !cancelSubscriptionId.startsWith("sub_")) return errorResponse("Invalid subscription ID format", 400);
755
+ if (updateSubscriptionId && !updateSubscriptionId.startsWith("sub_")) return errorResponse("Invalid subscription ID format", 400);
725
756
  let flowData;
726
757
  if (cancelSubscriptionId) flowData = {
727
758
  type: "subscription_cancel",
@@ -764,11 +795,20 @@ function createUpdateHandler(config) {
764
795
  const subscriptionId = url.searchParams.get("subscriptionId");
765
796
  const cancelAtPeriodEnd = url.searchParams.get("cancelAtPeriodEnd") === "true";
766
797
  if (!subscriptionId) return errorResponse("subscriptionId is required", 400);
767
- await stripeBuilder().subscriptions.update(subscriptionId, { cancel_at_period_end: cancelAtPeriodEnd });
798
+ if (!subscriptionId.startsWith("sub_")) return errorResponse("Invalid subscription ID format", 400);
799
+ const stripe = stripeBuilder();
800
+ const originalCancelAtPeriodEnd = (await stripe.subscriptions.retrieve(subscriptionId)).cancel_at_period_end;
801
+ await stripe.subscriptions.update(subscriptionId, { cancel_at_period_end: cancelAtPeriodEnd });
768
802
  const customer = user.customer;
769
803
  const inventory = customer?.inventory;
770
804
  if (inventory?.subscriptions?.[subscriptionId]) inventory.subscriptions[subscriptionId].cancel_at_period_end = cancelAtPeriodEnd;
771
- if (customer?.email) await upsertCustomerInventoryAndSyncWithUser(payload, inventory, customer.email);
805
+ if (customer?.email) try {
806
+ await upsertCustomerInventoryAndSyncWithUser(payload, inventory, customer.email);
807
+ } catch (syncError) {
808
+ console.error("[Stripe Update] Local sync failed, rolling back Stripe change", syncError);
809
+ await stripe.subscriptions.update(subscriptionId, { cancel_at_period_end: originalCancelAtPeriodEnd });
810
+ throw syncError;
811
+ }
772
812
  return redirectResponse(`${process.env.DOMAIN}${config.routes.subscriptionPageHref}?refresh=${Date.now()}`, 303);
773
813
  } catch (error) {
774
814
  console.error("[Stripe Update Error]", error);
@@ -850,6 +890,7 @@ function createStripeInventoryPlugin(config) {
850
890
  resolveUser: config.resolveUser
851
891
  };
852
892
  const onSubscriptionUpdate = config.onSubscriptionUpdate || (async () => {});
893
+ const { resolveSubscriptionPermissions, resolveContentPermissions } = config;
853
894
  return (incomingConfig) => {
854
895
  const stripeEndpoints = createStripeEndpoints(endpointConfig, basePath);
855
896
  const configWithEndpoints = {
@@ -862,9 +903,9 @@ function createStripeInventoryPlugin(config) {
862
903
  stripeWebhooksEndpointSecret: process.env.STRIPE_WEBHOOK_SECRET,
863
904
  webhooks: {
864
905
  "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),
906
+ "customer.subscription.created": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate, resolveSubscriptionPermissions),
907
+ "customer.subscription.paused": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate, resolveSubscriptionPermissions),
908
+ "customer.subscription.updated": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate, resolveSubscriptionPermissions),
868
909
  "customer.subscription.deleted": async ({ event, payload }) => await subscriptionDeleted(event.data.object, payload, onSubscriptionUpdate),
869
910
  "customer.deleted": async ({ event, payload }) => await customerDeleted(event.data.object, payload),
870
911
  "product.deleted": async ({ event, payload }) => await productDeleted(event.data.object, payload),
@@ -971,42 +1012,6 @@ const customers = {
971
1012
  ]
972
1013
  };
973
1014
 
974
- //#endregion
975
- //#region src/server/collections/fields/permission-evaluation-field.ts
976
- const permissionEvaluationField = {
977
- type: "row",
978
- fields: [{
979
- type: "select",
980
- name: "type_of_permissions",
981
- options: [
982
- {
983
- label: "Todos",
984
- value: "all"
985
- },
986
- {
987
- label: "Permisos por roles",
988
- value: "roles"
989
- },
990
- {
991
- label: "Solo para usuarios sin roles",
992
- value: "only_no_roles"
993
- },
994
- {
995
- label: "Solo invitados",
996
- value: "only_guess"
997
- }
998
- ],
999
- defaultValue: "all",
1000
- label: "Tipo de permisos"
1001
- }, {
1002
- type: "relationship",
1003
- name: "permissions",
1004
- relationTo: [COLLECTION_SLUG_TAXONOMY],
1005
- hasMany: false,
1006
- admin: { condition: (_, siblingData) => siblingData.type_of_permissions === "roles" }
1007
- }]
1008
- };
1009
-
1010
1015
  //#endregion
1011
1016
  //#region src/server/collections/prices.ts
1012
1017
  const prices = {
@@ -1187,19 +1192,10 @@ const products = {
1187
1192
  type: "text",
1188
1193
  name: "title"
1189
1194
  }]
1190
- },
1191
- buildTaxonomyRelationship({
1192
- name: "roles",
1193
- label: "Roles",
1194
- defaultValue: [],
1195
- filterOptions: () => {
1196
- return { "payload.types": { in: ["role"] } };
1197
- },
1198
- required: false
1199
- })
1195
+ }
1200
1196
  ]
1201
1197
  };
1202
1198
 
1203
1199
  //#endregion
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 };
1200
+ export { createCheckoutHandler, createCustomerAtStripe, createDonationHandler, createPortalHandler, createStripeEndpoints, createStripeInventoryPlugin, createUnlockAction, createUpdateHandler, customerDeleted, customers, errorResponse, getCustomer, getUserFromRequest, invoiceSucceeded, isAdmin, isAdminOrCurrentUser, isAdminOrPublished, isAdminOrStripeActive, isAdminOrUserFieldMatchingCurrentUser, isAnyone, jsonResponse, loggedInOrPublished, payloadUpsert, paymentSucceeded, priceDeleted, priceUpsert, prices, productDeleted, productSync, products, redirectResponse, resolveStripeCustomer, stripeBuilder, subscriptionDeleted, subscriptionUpsert, syncCustomerByEmail, updatePrices, updateProducts, updateProductsAndPrices, upsertCustomerInventoryAndSyncWithUser, validateAuthenticatedRequest };
1205
1201
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["prices","customers","existingCustomer: Customer | null","customer","products","user: BaseUser | null","metadata: Stripe.MetadataParam","metadata: Stripe.MetadataParam","flowData: Stripe.BillingPortal.SessionCreateParams.FlowData | undefined","endpointConfig: StripeEndpointConfig","configWithEndpoints: Config","isAdmin: Access","isAnyone: Access","isAdminOrCurrentUser: Access","isAdminOrPublished: Access","isAdminOrStripeActive: Access","isAdminOrUserFieldMatchingCurrentUser: Access","loggedInOrPublished: Access","customers: CollectionConfig","permissionEvaluationField: Field","prices: CollectionConfig","products: CollectionConfig"],"sources":["../../src/server/utils/payload/upsert.ts","../../src/server/utils/stripe/stripe-builder.ts","../../src/server/actions/price.ts","../../src/server/actions/product.ts","../../src/server/utils/payload/sync-customer-by-email.ts","../../src/server/utils/payload/upsert-customer-inventory-and-sync-with-user.ts","../../src/server/utils/payload/get-userId-by-email.ts","../../src/server/utils/stripe/get-customer.ts","../../src/server/utils/payload/remove-customer-by-stripe-id.ts","../../src/server/utils/payload/find-or-create-customer.ts","../../src/server/actions/subscription.ts","../../src/server/actions/donation.ts","../../src/server/actions/invoice.ts","../../src/server/actions/customer.ts","../../src/server/actions/unlock-item-for-user-action.ts","../../src/server/actions/update-products-and-prices-action.ts","../../src/server/utils/stripe/create-customer-at-stripe.ts","../../src/server/utils/stripe/get-customer-from-stripe-or-create.ts","../../src/server/endpoints/validators/request-validator.ts","../../src/server/endpoints/handlers/checkout-handler.ts","../../src/server/endpoints/handlers/donation-handler.ts","../../src/server/endpoints/handlers/portal-handler.ts","../../src/server/endpoints/handlers/update-handler.ts","../../src/server/endpoints/index.ts","../../src/server/plugin/create-stripe-inventory-plugin.ts","../../src/server/access/access-queries.ts","../../src/server/access/get-user-from-request.ts","../../src/server/collections/customers.ts","../../src/server/collections/fields/permission-evaluation-field.ts","../../src/server/collections/prices.ts","../../src/server/collections/products.ts"],"sourcesContent":["\"use server\";\n\nimport { Payload } from \"payload\"\n\ntype Config = {\n collections: {\n [key: string]: any\n }\n}\n\ninterface UpsertOptions<T extends keyof Config['collections']> {\n collection: T\n payload: Payload\n data: Omit<Config['collections'][T], 'createdAt' | 'id' | 'updatedAt' | 'sizes'>\n where: any\n}\n\nexport const payloadUpsert = async <T extends keyof Config['collections']>({\n payload,\n collection,\n data,\n where,\n}: UpsertOptions<T>): Promise<Config['collections'][T] | null> => {\n try {\n const existingDocs = await payload.find({\n collection: collection as any,\n where,\n pagination: false,\n limit: 1,\n })\n\n const existingDocId = existingDocs.docs?.at(0)?.id\n if (existingDocId) {\n const updatedDoc = await payload.update({\n collection: collection as any,\n id: existingDocId,\n data: data as any,\n })\n\n return updatedDoc || null\n }\n\n return await payload.create({\n collection,\n data,\n } as any)\n } catch (error) {\n console.error(`Error in payloadUpsert: ${error}`)\n throw new Error(`Failed to upsert document in collection ${collection} ${error}`)\n }\n}\n","import Stripe from \"stripe\";\nexport const stripeBuilder = (): Stripe => {\n return new Stripe(process.env.STRIPE_SECRET_KEY!, {\n apiVersion: '2024-09-30.acacia'\n })\n}\n","\"use server\";\n\nimport type { Payload } from \"payload\";\nimport type Stripe from \"stripe\";\nimport {\n COLLECTION_SLUG_PRICES,\n COLLECTION_SLUG_PRODUCTS,\n} from \"../../model/index.js\";\nimport { payloadUpsert } from \"../utils/payload/upsert.js\";\nimport { stripeBuilder } from \"../utils/stripe/stripe-builder.js\";\n\nexport const updatePrices = async (payload: Payload) => {\n const stripe = await stripeBuilder();\n const prices = await stripe.prices.list({ limit: 100, active: true });\n const promises = prices.data.map(price => priceUpsert(price, payload));\n const pricesUpserted = await Promise.all(promises);\n\n const pricesByProductId = pricesUpserted\n .filter((p): p is PriceUpserted => p !== null)\n .reduce(\n (acc, { productId, priceId }) => {\n if (!acc[productId]) {\n acc[productId] = [];\n }\n acc[productId].push(priceId);\n return acc;\n },\n {} as Record<string, number[]>\n );\n\n Object.entries(pricesByProductId).map(async ([productId, prices]) => {\n await payload.update({\n collection: COLLECTION_SLUG_PRODUCTS,\n data: {\n prices,\n },\n where: {\n stripeID: { equals: productId },\n },\n });\n });\n};\n\ninterface PriceUpserted {\n productId: string;\n priceId: number;\n}\n\nexport async function priceUpsert(\n price: Stripe.Price,\n payload: Payload\n): Promise<PriceUpserted | null> {\n const stripeProductID =\n typeof price.product === \"string\" ? price.product : price.product.id;\n\n if (price.deleted !== undefined) {\n priceDeleted(price, payload);\n return null;\n }\n if (price.unit_amount == null) return null;\n const priceUpserted = await payloadUpsert({\n payload,\n collection: COLLECTION_SLUG_PRICES,\n data: {\n stripeID: price.id,\n stripeProductId: stripeProductID,\n active: price.active,\n unitAmount: price.unit_amount as number,\n currency: price.currency,\n type: price.type,\n interval: price.recurring?.interval,\n intervalCount: price.recurring?.interval_count,\n },\n where: {\n stripeID: { equals: price.id },\n },\n });\n if (!priceUpserted) return null;\n return { productId: stripeProductID, priceId: priceUpserted.id };\n}\n\nexport const priceDeleted = async (price: Stripe.Price, payload: Payload) => {\n const { id } = price;\n\n try {\n await payload.delete({\n collection: COLLECTION_SLUG_PRICES,\n where: {\n stripeID: { equals: id },\n },\n });\n } catch (error) {\n payload.logger.error(`- Error deleting price: ${error}`);\n throw error;\n }\n};\n","\"use server\";\n\nimport type { Payload } from \"payload\";\nimport type Stripe from \"stripe\";\nimport { COLLECTION_SLUG_PRODUCTS } from \"../../model/index.js\";\nimport { payloadUpsert } from \"../utils/payload/upsert.js\";\nimport { stripeBuilder } from \"../utils/stripe/stripe-builder.js\";\n\nconst logs = false;\n\nexport const updateProducts = async (payload: Payload) => {\n const stripe = await stripeBuilder();\n const products = await stripe.products.list({ limit: 100, active: true });\n products.data.forEach(product => productSync(product, payload));\n};\n\nexport const productSync = async (object: Stripe.Product, payload: Payload) => {\n const { id: stripeProductID, name, description, images } = object;\n if (object.deleted !== undefined) return productDeleted(object, payload);\n try {\n await payloadUpsert({\n payload,\n collection: COLLECTION_SLUG_PRODUCTS,\n data: {\n prices: [],\n stripeID: stripeProductID,\n active: true,\n metadata: object.metadata,\n type: object.type,\n name,\n description,\n images: images?.map(image => ({ url: image })) || [],\n },\n where: {\n stripeID: { equals: stripeProductID },\n },\n });\n } catch (error) {\n console.error(error);\n throw error;\n }\n};\n\nexport const productDeleted = async (\n object: Stripe.Product,\n payload: Payload\n) => {\n const { id: stripeProductID } = object;\n\n try {\n const productQuery = await payload.find({\n collection: COLLECTION_SLUG_PRODUCTS,\n where: {\n stripeID: { equals: stripeProductID },\n },\n });\n\n const payloadProductID = productQuery.docs?.[0]?.id;\n\n if (payloadProductID) {\n await payload.delete({\n collection: COLLECTION_SLUG_PRODUCTS,\n id: payloadProductID,\n });\n\n if (logs)\n payload.logger.info(\n `✅ Successfully deleted product with Stripe ID: ${stripeProductID}`\n );\n }\n } catch (error) {\n payload.logger.error(`- Error deleting product: ${error}`);\n throw error;\n }\n};\n","import { COLLECTION_SLUG_CUSTOMERS } from \"../../../model/index.js\";\nimport { Payload } from \"payload\";\n\nexport async function syncCustomerByEmail({ email, payload }: { email: string, payload: Payload }) {\n const customers = await payload.find({\n collection: COLLECTION_SLUG_CUSTOMERS,\n where: { email: { equals: email } },\n });\n const customerId = customers.docs?.[0]?.id;\n\n await payload.update({\n collection: \"users\",\n data: {\n customer: customerId,\n },\n where: { email: { equals: email } },\n });\n}\n","import { COLLECTION_SLUG_CUSTOMERS, generateCustomerInventory } from \"../../../model/index.js\";\nimport type { CustomerInventory } from \"../../../types/index.js\";\nimport { syncCustomerByEmail } from \"./sync-customer-by-email.js\";\nimport { payloadUpsert } from \"./upsert.js\";\nimport { Payload } from \"payload\";\n\nexport async function upsertCustomerInventoryAndSyncWithUser(\n payload: Payload,\n inventory: CustomerInventory | null | undefined,\n email: string,\n stripeCustomerId?: string | null\n) {\n await payloadUpsert({\n payload,\n collection: COLLECTION_SLUG_CUSTOMERS,\n data: {\n email: email,\n stripeId: stripeCustomerId,\n inventory: inventory ?? generateCustomerInventory(),\n },\n where: { email: { equals: email } },\n });\n await syncCustomerByEmail({ email, payload });\n}\n","import { COLLECTION_SLUG_USER } from \"../../../model/index.js\";\nimport { Payload } from \"payload\";\n\ninterface Props {\n email: string;\n payload: Payload;\n}\n\n/**\n * Gets a user ID by email address using Payload's find method\n * @param email - The email address to search for\n * @returns The user ID if found, null otherwise\n */\nexport async function getUserIdByEmail({email, payload}: Props): Promise<string | null | undefined> {\n const userQuery = await payload.find({\n collection: COLLECTION_SLUG_USER,\n where: {\n email: { equals: email },\n },\n });\n\n const user = userQuery.docs?.[0];\n return user?.id as string | null;\n}\n","import Stripe from \"stripe\";\nimport { stripeBuilder } from \"./stripe-builder.js\";\n\nexport async function getCustomer({\n stripe,\n email,\n}: {\n stripe?: Stripe;\n email: string;\n}): Promise<Stripe.Customer | null> {\n stripe = stripe ?? stripeBuilder();\n const customers = await stripe.customers.search({\n query: `email:'${email}'`,\n });\n return customers.data.length ? customers.data[0] as Stripe.Customer : null;\n \n}\n\nexport async function resolveStripeCustomer({ customer }: {\n customer: string | Stripe.Customer | Stripe.DeletedCustomer | null\n}): Promise<Stripe.Customer | Stripe.DeletedCustomer | null> {\n const stripe = stripeBuilder();\n if (typeof customer === \"string\") {\n return await stripe.customers.retrieve(customer);\n }\n return customer;\n}","import { Payload } from \"payload\";\nimport { COLLECTION_SLUG_CUSTOMERS } from \"../../../model/index.js\";\n\nexport async function removeCustomerByStripeId({\n stripeId,\n payload,\n}: {\n stripeId: string;\n payload: Payload;\n}) {\n await payload.delete({\n collection: COLLECTION_SLUG_CUSTOMERS,\n where: { stripeId: { equals: stripeId } },\n });\n payload.logger.info(`✅ Successfully removed customer with Stripe ID: ${stripeId}`);\n}","import { Payload } from \"payload\";\nimport {\n COLLECTION_SLUG_CUSTOMERS,\n generateCustomerInventory,\n} from \"../../../model/index.js\";\nimport { Customer, CustomerInventory } from \"../../../types/index.js\";\n\ninterface FindOrCreateCustomerProps {\n email: string;\n payload: Payload;\n stripeId?: string;\n}\n\n/**\n * Finds a customer by email address in the customers collection, or creates one if not found\n * @param email - The email address to search for\n * @param payload - Payload instance\n * @param stripeId - Optional Stripe customer ID to set when creating\n * @returns The customer document (found or created)\n */\nexport async function findOrCreateCustomer({\n email,\n payload,\n stripeId,\n}: FindOrCreateCustomerProps): Promise<Customer | null> {\n if (!email) {\n payload.logger.error(\"Email is required to find or create customer\");\n return null;\n }\n\n try {\n const userQuery = await payload.find({\n collection: COLLECTION_SLUG_CUSTOMERS,\n where: {\n email: { equals: email },\n },\n });\n\n let existingCustomer: Customer | null = userQuery.docs?.[0] as unknown as Customer | null;\n if (existingCustomer) {\n existingCustomer.inventory = existingCustomer?.inventory\n ? (existingCustomer.inventory as unknown as CustomerInventory)\n : generateCustomerInventory();\n return existingCustomer;\n }\n\n payload.logger.info(`Creating new customer for email: ${email}`);\n\n const newCustomer = await payload.create({\n collection: COLLECTION_SLUG_CUSTOMERS,\n data: {\n email,\n stripeId: stripeId || \"\",\n inventory: generateCustomerInventory() as unknown as [k: string],\n },\n });\n\n payload.logger.info(`✅ Successfully created customer for email: ${email}`);\n return newCustomer as unknown as Customer;\n } catch (error) {\n payload.logger.error(\n `Error finding or creating customer for email ${email}: ${error}`\n );\n throw error;\n }\n}\n","import { Payload } from \"payload\";\nimport type Stripe from \"stripe\";\nimport { COLLECTION_SLUG_PRODUCTS } from \"../../model/index.js\";\nimport { getPermissionsSlugs } from \"../../model/permissions.js\";\nimport type { CustomerInventory } from \"../../types/index.js\";\nimport { upsertCustomerInventoryAndSyncWithUser } from \"../utils/payload/upsert-customer-inventory-and-sync-with-user.js\";\nimport { getUserIdByEmail } from \"../utils/payload/get-userId-by-email.js\";\nimport { resolveStripeCustomer } from \"../utils/stripe/get-customer.js\";\nimport { removeCustomerByStripeId } from \"../utils/payload/remove-customer-by-stripe-id.js\";\nimport { findOrCreateCustomer } from \"../utils/payload/find-or-create-customer.js\";\n\nexport const subscriptionUpsert = async (\n subscription: Stripe.Subscription,\n payload: Payload,\n onSubscriptionUpdate: (\n type: \"create\" | \"delete\",\n userId: string\n ) => Promise<void>\n) => {\n const { id: stripeID, status, customer: stripeCustomer } = subscription;\n const customer = await resolveStripeCustomer({ customer: stripeCustomer });\n const error = (message: string) =>\n payload.logger.error(\"Subscription Upsert: \", message as any);\n const info = (message: string) =>\n payload.logger.info(\"Subscription Upsert: \", message as any);\n\n if (!customer) {\n error(\"No stripe customer found for subscription\");\n return;\n }\n if (customer.deleted) {\n await removeCustomerByStripeId({ stripeId: customer.id, payload });\n return;\n }\n if (!customer.email) {\n error(\"No email found for stripe customer\");\n return;\n }\n const email = customer.email;\n const stripeId = customer.id;\n\n try {\n const customer = await findOrCreateCustomer({\n email,\n payload,\n stripeId,\n });\n\n const item = subscription.items.data.at(0);\n if (!item || !customer) {\n error(`No item ${item} or customer ${customer} found`);\n return;\n }\n\n const { docs: products } = await payload.find({\n collection: COLLECTION_SLUG_PRODUCTS,\n where: { stripeID: { equals: item.price.product } },\n });\n const product = products.at(0);\n if (!product) return;\n\n const inventory = customer.inventory;\n inventory.subscriptions[stripeID] = {\n ...subscription,\n permissions: getPermissionsSlugs({ permissions: product.roles }),\n };\n info(`INVENTORY OF THE SUBSCRIPTION ${inventory}`);\n await upsertCustomerInventoryAndSyncWithUser(payload, inventory, email, stripeId);\n\n if ([\"active\", \"trialing\"].includes(status)) {\n const userId = await getUserIdByEmail({ email, payload });\n if (!userId) return;\n await onSubscriptionUpdate(\"create\", userId);\n }\n info(\n `✅ Successfully updated subscription with ID: ${stripeID} for user: ${email}`\n );\n } catch (e) {\n error(`- Error managing subscription: ${e}`);\n throw e;\n }\n};\n\nexport const subscriptionDeleted = async (\n subscription: Stripe.Subscription,\n payload: Payload,\n onSubscriptionUpdate: (\n type: \"create\" | \"delete\",\n userId: string\n ) => Promise<void>\n) => {\n const { id, customer: customerId } = subscription;\n const customer = await resolveStripeCustomer({ customer: customerId });\n const stripeId = customer?.id;\n if (!customer) {\n payload.logger.error(\"No stripe customer found for subscription\");\n return;\n } \n if (customer.deleted) {\n await removeCustomerByStripeId({ stripeId: customer.id, payload });\n return;\n }\n if (!customer.email) {\n payload.logger.error(\"No email found for stripe customer\");\n return;\n }\n const email = customer.email;\n try {\n const customer = await findOrCreateCustomer({\n email,\n payload,\n stripeId\n });\n if (!customer) {\n payload.logger.error(\"No customer found for subscription\");\n return;\n }\n\n const inventory = customer.inventory as unknown as CustomerInventory;\n delete inventory.subscriptions[id];\n\n await upsertCustomerInventoryAndSyncWithUser(payload, inventory, email, stripeId);\n const userId = await getUserIdByEmail({ email, payload });\n if (!userId) {\n payload.logger.error(\"No user found for subscription\");\n return;\n }\n await onSubscriptionUpdate(\"delete\", userId);\n\n payload.logger.info(\n `✅ Successfully deleted subscription: ${id} for user: ${email}`\n );\n } catch (error) {\n payload.logger.error(`- Error deleting subscription: ${error}`);\n throw error;\n }\n};\n","import { Payload } from \"payload\";\nimport type Stripe from \"stripe\";\nimport { COLLECTION_SLUG_CUSTOMERS } from \"../../model/index.js\";\nimport { resolveStripeCustomer } from \"../utils/stripe/get-customer.js\";\nimport { findOrCreateCustomer } from \"../utils/payload/find-or-create-customer.js\";\nimport { removeCustomerByStripeId } from \"../utils/payload/remove-customer-by-stripe-id.js\";\n\nexport const paymentSucceeded = async (\n paymentIntent: Stripe.PaymentIntent,\n payload: Payload\n) => {\n const { id, customer: paymentCustomer } = paymentIntent;\n const stripeCustomer = await resolveStripeCustomer({ customer: paymentCustomer });\n if (!stripeCustomer) {\n payload.logger.error(\"No stripe customer found for payment\");\n return\n }\n if (stripeCustomer.deleted) {\n await removeCustomerByStripeId({ stripeId: stripeCustomer.id, payload });\n return;\n }\n if (!stripeCustomer.email) {\n payload.logger.error(\"No email found for stripe customer\");\n return;\n }\n\n try {\n const customer = await findOrCreateCustomer({\n email: stripeCustomer.email,\n payload,\n stripeId: stripeCustomer.id,\n });\n if (!customer) return;\n\n if (!customer) {\n payload.logger.error(`User not found for payment: ${stripeCustomer.email}`);\n return;\n }\n\n let inventory = customer.inventory\n inventory.payments[id] = paymentIntent;\n\n await payload.update({\n collection: COLLECTION_SLUG_CUSTOMERS,\n data: { inventory: inventory as unknown as { [x: string]: {} } },\n where: { email: { equals: stripeCustomer.email } },\n });\n\n payload.logger.info(\n `✅ Successfully recorded ${stripeCustomer.metadata?.type ?? \"subscription\"} with Payment Intent ID: ${id} for user: ${stripeCustomer.email}`\n );\n } catch (error) {\n payload.logger.error(`- Error recording payment: ${error}`);\n throw error;\n }\n};\n","import { Payload } from \"payload\";\nimport type Stripe from \"stripe\";\nimport { COLLECTION_SLUG_CUSTOMERS } from \"../../model/index.js\";\nimport { findOrCreateCustomer } from \"../utils/payload/find-or-create-customer.js\";\nimport { resolveStripeCustomer } from \"../utils/stripe/get-customer.js\";\nimport { removeCustomerByStripeId } from \"../utils/payload/remove-customer-by-stripe-id.js\";\n\nexport const invoiceSucceeded = async (\n invoiceIntent: Stripe.Invoice,\n payload: Payload\n) => {\n const { id, customer: paymentCustomer } = invoiceIntent;\n const stripeCustomer = await resolveStripeCustomer({ customer: paymentCustomer });\n if (!stripeCustomer) {\n payload.logger.error(\"No stripe customer found for payment\");\n return\n }\n if (stripeCustomer.deleted) {\n await removeCustomerByStripeId({ stripeId: stripeCustomer.id, payload });\n return;\n }\n if (!stripeCustomer.email) {\n payload.logger.error(\"No email found for stripe customer\");\n return;\n }\n\n try {\n const customer = await findOrCreateCustomer({\n email: stripeCustomer.email,\n payload,\n stripeId: stripeCustomer.id,\n });\n if (!customer) return;\n\n let inventory = customer.inventory\n inventory.invoices[id] = invoiceIntent;\n\n await payload.update({\n collection: COLLECTION_SLUG_CUSTOMERS,\n data: { inventory: inventory as unknown as { [x: string]: {} } },\n where: { email: { equals: stripeCustomer.email } },\n });\n\n payload.logger.info(\n `✅ Successfully recorded ${stripeCustomer.metadata?.type ?? \"subscription\"} with Payment Intent ID: ${id} for user: ${stripeCustomer.email}`\n );\n } catch (error) {\n payload.logger.error(`- Error recording payment: ${error}`);\n throw error;\n }\n};\n","import { Payload } from \"payload\";\nimport Stripe from \"stripe\";\nimport { COLLECTION_SLUG_CUSTOMERS } from \"../../index.js\";\n\nexport const customerDeleted = async (\n customer: Stripe.Customer,\n payload: Payload,\n ) => {\n const { id, email } = customer;\n try { \n await payload.delete({\n collection: COLLECTION_SLUG_CUSTOMERS,\n where: { email: { equals: email } },\n });\n payload.logger.info(\n `✅ Successfully deleted customer with Stripe ID: ${id}`\n );\n } catch (error) {\n payload.logger.error(`- Error deleting subscription: ${error}`);\n throw error;\n }\n };\n ","import { Payload } from \"payload\";\nimport {\n checkIfUserCanUnlockQuery,\n COLLECTION_SLUG_USER,\n countWeeklyUnlocksQuery,\n MAX_UNLOCKS_PER_WEEK,\n} from \"../../model/index.js\";\nimport { generateUserInventory } from \"../../model/builders.js\";\nimport { getPermissionsSlugs } from \"../../model/permissions.js\";\nimport type { BaseUser, UnlockItem, UserInventory } from \"../../types/index.js\";\n\nexport type Result<T, E = string> = {\n data: T;\n error?: never;\n} | {\n data?: never;\n error: E;\n}\n\n\nconst addUniqueUnlock = (\n unlocks: UnlockItem[],\n collection: string,\n contentId: number\n): UnlockItem[] => {\n const isDuplicate = unlocks.some(\n unlock => unlock.collection === collection && unlock.id === contentId\n );\n\n if (isDuplicate) {\n return unlocks;\n }\n return [\n ...unlocks,\n {\n collection,\n id: contentId,\n dateUnlocked: new Date(),\n },\n ];\n};\n\n/**\n * Unlocks an item for a user, adding it to their inventory.\n *\n * @param payload - The Payload instance\n * @param user - The authenticated user\n * @param collection - The collection slug of the item to unlock\n * @param contentId - The ID of the item to unlock\n * @returns Result indicating success or error message\n */\nexport const unlockItemForUser = async (\n payload: Payload,\n user: BaseUser,\n collection: string,\n contentId: number\n): Promise<Result<boolean>> => {\n if (!user || !user.id) {\n return { error: \"Usuario no válido\" };\n }\n const item = await payload.findByID({\n collection: collection as any,\n id: contentId.toString(),\n });\n\n if (!item) {\n return { error: \"Elemento no encontrado\" };\n }\n const permissions = getPermissionsSlugs({ permissions: item.permissions });\n\n if (!checkIfUserCanUnlockQuery(user, permissions)) {\n return { error: \"No tienes permisos para desbloquear este elemento\" };\n }\n\n const weeklyUnlocks = countWeeklyUnlocksQuery(user);\n if (weeklyUnlocks >= MAX_UNLOCKS_PER_WEEK) {\n return {\n error: `Has alcanzado el límite de ${MAX_UNLOCKS_PER_WEEK} desbloqueos para esta semana`,\n };\n }\n\n const inventory =\n (user.inventory as UserInventory) ?? generateUserInventory();\n\n const updatedUnlocks = addUniqueUnlock(\n inventory.unlocks,\n collection,\n contentId\n );\n\n if (updatedUnlocks.length === inventory.unlocks.length) {\n return { data: true };\n }\n\n try {\n await payload.update({\n collection: COLLECTION_SLUG_USER,\n id: user.id.toString(),\n data: {\n inventory: {\n ...inventory,\n unlocks: updatedUnlocks,\n },\n },\n });\n\n return { data: true };\n } catch (error) {\n console.error(\"Error al actualizar el inventario del usuario:\", error);\n return { error: \"Error al actualizar el inventario del usuario\" };\n }\n};\n","\"use server\";\n\nimport { updatePrices } from \"./price.js\";\nimport { updateProducts } from \"./product.js\";\nimport { Payload } from \"payload\";\n\nexport async function updateProductsAndPrices(payload: Payload) {\n await updateProducts(payload);\n await updatePrices(payload);\n}\n","import Stripe from \"stripe\";\nimport { stripeBuilder } from \"./stripe-builder.js\";\n\nexport async function createCustomerAtStripe({\n stripe,\n email,\n name,\n}: {\n stripe?: Stripe;\n email: string;\n name?: string;\n}) {\n stripe = stripe ?? stripeBuilder();\n return await stripe.customers.create({\n email: email,\n name: name || undefined,\n });\n}\n","import { createCustomerAtStripe } from \"./create-customer-at-stripe.js\";\nimport { getCustomer } from \"./get-customer.js\";\nimport { stripeBuilder } from \"./stripe-builder.js\";\n\nexport async function getCustomerFromStripeOrCreate(\n email: string,\n name?: string\n): Promise<string> {\n const stripe = stripeBuilder();\n let customer = await getCustomer({ stripe, email });\n if (!customer) {\n customer = await createCustomerAtStripe({ stripe, email, name });\n }\n return customer.id;\n}\n","import type { Payload, PayloadRequest } from \"payload\";\nimport type { BaseUser } from \"../../../types/index.js\";\nimport type { StripeEndpointConfig } from \"../../plugin/stripe-inventory-types.js\";\n\n/**\n * Creates a JSON response using Web API Response\n */\nexport function jsonResponse(data: unknown, options?: ResponseInit): Response {\n return new Response(JSON.stringify(data), {\n headers: { \"Content-Type\": \"application/json\" },\n ...options,\n });\n}\n\n/**\n * Creates a redirect response using Web API Response\n * @param url - The URL to redirect to\n * @param status - HTTP status code (default: 303 See Other)\n */\nexport function redirectResponse(url: string, status: number = 303): Response {\n return new Response(null, {\n status,\n headers: { Location: url },\n });\n}\n\n/**\n * Creates an error response\n */\nexport function errorResponse(\n message: string,\n status: number = 400\n): Response {\n return jsonResponse({ error: message }, { status });\n}\n\n/**\n * Result type for validateAuthenticatedRequest\n */\nexport type AuthenticatedRequestResult =\n | { success: false; error: Response }\n | {\n success: true;\n user: BaseUser;\n payload: Payload;\n };\n\n/**\n * Validates that the request has an authenticated user\n * Uses the config's resolveUser if provided, otherwise uses request.user\n */\nexport async function validateAuthenticatedRequest(\n request: PayloadRequest,\n config: StripeEndpointConfig\n): Promise<AuthenticatedRequestResult> {\n // Check custom permissions if provided\n if (config.checkPermissions) {\n const hasPermission = await config.checkPermissions(request);\n if (!hasPermission) {\n return {\n success: false,\n error: errorResponse(\"Permission denied\", 403),\n };\n }\n }\n\n // Resolve user\n let user: BaseUser | null = null;\n\n if (config.resolveUser) {\n user = await config.resolveUser(request);\n } else {\n user = request.user as BaseUser | null;\n }\n\n if (!user) {\n return {\n success: false,\n error: errorResponse(\"You must be logged in to access this endpoint\", 401),\n };\n }\n\n if (!user.email) {\n return {\n success: false,\n error: errorResponse(\"User email is required\", 400),\n };\n }\n\n return {\n success: true,\n user,\n payload: request.payload,\n };\n}\n","import type { PayloadHandler, PayloadRequest } from \"payload\";\nimport type Stripe from \"stripe\";\nimport type { StripeEndpointConfig } from \"../../plugin/stripe-inventory-types.js\";\nimport { upsertCustomerInventoryAndSyncWithUser } from \"../../utils/payload/upsert-customer-inventory-and-sync-with-user.js\";\nimport { getCustomerFromStripeOrCreate } from \"../../utils/stripe/get-customer-from-stripe-or-create.js\";\nimport { stripeBuilder } from \"../../utils/stripe/stripe-builder.js\";\nimport {\n errorResponse,\n redirectResponse,\n validateAuthenticatedRequest,\n} from \"../validators/request-validator.js\";\n\n/**\n * Creates a handler for Stripe checkout sessions (subscriptions)\n *\n * @param config - Endpoint configuration\n * @returns PayloadHandler for checkout endpoint\n */\nexport function createCheckoutHandler(config: StripeEndpointConfig): PayloadHandler {\n return async (request: PayloadRequest): Promise<Response> => {\n try {\n // Validate authenticated user\n const validated = await validateAuthenticatedRequest(request, config);\n if (!validated.success) {\n return validated.error;\n }\n\n const { user, payload } = validated;\n\n // Extract priceId from query params\n const url = new URL(request.url || \"\");\n const priceId = url.searchParams.get(\"priceId\");\n\n if (!priceId) {\n return errorResponse(\"priceId is required\", 400);\n }\n\n const stripe = stripeBuilder();\n\n // Get or create Stripe customer\n const customerId = await getCustomerFromStripeOrCreate(\n user.email!,\n user.name\n );\n\n // Sync customer inventory\n await upsertCustomerInventoryAndSyncWithUser(\n payload,\n user.customer?.inventory,\n user.email!,\n customerId\n );\n\n // Prepare checkout session\n const metadata: Stripe.MetadataParam = {\n type: \"subscription\",\n };\n\n const checkoutResult = await stripe.checkout.sessions.create({\n success_url: `${process.env.DOMAIN}${config.routes.subscriptionPageHref}?success=${Date.now()}`,\n cancel_url: `${process.env.DOMAIN}${config.routes.subscriptionPageHref}?error=${Date.now()}`,\n mode: \"subscription\",\n customer: customerId,\n client_reference_id: String(user.id),\n line_items: [{ price: priceId, quantity: 1 }],\n metadata,\n tax_id_collection: { enabled: true },\n customer_update: {\n name: \"auto\",\n address: \"auto\",\n shipping: \"auto\",\n },\n subscription_data: { metadata },\n });\n\n if (checkoutResult.url) {\n return redirectResponse(checkoutResult.url, 303);\n }\n\n return errorResponse(\"Failed to create checkout URL\", 406);\n } catch (error) {\n console.error(\"[Stripe Checkout Error]\", error);\n return errorResponse(\n error instanceof Error ? error.message : \"Unknown error occurred\",\n 500\n );\n }\n };\n}\n","import type { PayloadHandler, PayloadRequest } from \"payload\";\nimport type Stripe from \"stripe\";\nimport type { StripeEndpointConfig } from \"../../plugin/stripe-inventory-types.js\";\nimport { upsertCustomerInventoryAndSyncWithUser } from \"../../utils/payload/upsert-customer-inventory-and-sync-with-user.js\";\nimport { getCustomerFromStripeOrCreate } from \"../../utils/stripe/get-customer-from-stripe-or-create.js\";\nimport { stripeBuilder } from \"../../utils/stripe/stripe-builder.js\";\nimport {\n errorResponse,\n jsonResponse,\n validateAuthenticatedRequest,\n} from \"../validators/request-validator.js\";\n\n/**\n * Creates a handler for one-time donation payments\n *\n * @param config - Endpoint configuration\n * @returns PayloadHandler for donation endpoint\n */\nexport function createDonationHandler(config: StripeEndpointConfig): PayloadHandler {\n return async (request: PayloadRequest): Promise<Response> => {\n try {\n // Validate authenticated user\n const validated = await validateAuthenticatedRequest(request, config);\n if (!validated.success) {\n return validated.error;\n }\n\n const { user, payload } = validated;\n\n // Extract amount from query params\n const url = new URL(request.url || \"\");\n const amountParam = url.searchParams.get(\"amount\");\n\n if (!amountParam) {\n return errorResponse(\"amount is required\", 400);\n }\n\n const amount = parseInt(amountParam, 10);\n\n if (isNaN(amount) || amount < 100) {\n return errorResponse(\"Minimum donation amount is 1 EUR (100 cents)\", 400);\n }\n\n const stripe = stripeBuilder();\n\n // Get or create Stripe customer\n const customerId = await getCustomerFromStripeOrCreate(\n user.email!,\n user.name\n );\n\n // Sync customer inventory\n await upsertCustomerInventoryAndSyncWithUser(\n payload,\n user.customer?.inventory,\n user.email!,\n customerId\n );\n\n // Determine redirect URLs\n const donationPageHref = config.routes.donationPageHref || config.routes.subscriptionPageHref;\n\n // Prepare metadata\n const metadata: Stripe.MetadataParam = {\n type: \"donation\",\n };\n\n // Create checkout session for one-time payment\n const session = await stripe.checkout.sessions.create({\n customer: customerId,\n payment_method_types: [\"card\"],\n line_items: [\n {\n price_data: {\n currency: \"eur\",\n product_data: {\n name: \"Donation\",\n description: \"One-time donation\",\n },\n unit_amount: amount,\n },\n quantity: 1,\n },\n ],\n mode: \"payment\",\n success_url: `${process.env.DOMAIN}${donationPageHref}?success=donation`,\n cancel_url: `${process.env.DOMAIN}${donationPageHref}?error=donation_cancelled`,\n metadata,\n payment_intent_data: { metadata },\n invoice_creation: { enabled: true, invoice_data: { metadata } },\n });\n\n return jsonResponse({ url: session.url });\n } catch (error) {\n console.error(\"[Stripe Donation Error]\", error);\n return errorResponse(\n error instanceof Error ? error.message : \"Unknown error occurred\",\n 500\n );\n }\n };\n}\n","import type { PayloadHandler, PayloadRequest } from \"payload\";\nimport type Stripe from \"stripe\";\nimport type { StripeEndpointConfig } from \"../../plugin/stripe-inventory-types.js\";\nimport { upsertCustomerInventoryAndSyncWithUser } from \"../../utils/payload/upsert-customer-inventory-and-sync-with-user.js\";\nimport { getCustomerFromStripeOrCreate } from \"../../utils/stripe/get-customer-from-stripe-or-create.js\";\nimport { stripeBuilder } from \"../../utils/stripe/stripe-builder.js\";\nimport {\n errorResponse,\n redirectResponse,\n validateAuthenticatedRequest,\n} from \"../validators/request-validator.js\";\n\n/**\n * Creates a handler for Stripe Billing Portal access\n *\n * @param config - Endpoint configuration\n * @returns PayloadHandler for portal endpoint\n */\nexport function createPortalHandler(config: StripeEndpointConfig): PayloadHandler {\n return async (request: PayloadRequest): Promise<Response> => {\n try {\n // Validate authenticated user\n const validated = await validateAuthenticatedRequest(request, config);\n if (!validated.success) {\n return validated.error;\n }\n\n const { user, payload } = validated;\n\n // Extract optional params for subscription actions\n const url = new URL(request.url || \"\");\n const cancelSubscriptionId = url.searchParams.get(\"cancelSubscriptionId\");\n const updateSubscriptionId = url.searchParams.get(\"updateSubscriptionId\");\n\n // Build flow data if subscription action is requested\n let flowData: Stripe.BillingPortal.SessionCreateParams.FlowData | undefined;\n\n if (cancelSubscriptionId) {\n flowData = {\n type: \"subscription_cancel\",\n subscription_cancel: { subscription: cancelSubscriptionId },\n };\n } else if (updateSubscriptionId) {\n flowData = {\n type: \"subscription_update\",\n subscription_update: { subscription: updateSubscriptionId },\n };\n }\n\n const stripe = stripeBuilder();\n\n // Get or create Stripe customer\n const customerId = await getCustomerFromStripeOrCreate(\n user.email!,\n user.name\n );\n\n // Sync customer inventory\n await upsertCustomerInventoryAndSyncWithUser(\n payload,\n user.customer?.inventory,\n user.email!,\n customerId\n );\n\n // Create billing portal session\n const session = await stripe.billingPortal.sessions.create({\n flow_data: flowData,\n customer: customerId,\n return_url: `${process.env.DOMAIN}${config.routes.subscriptionPageHref}`,\n });\n\n return redirectResponse(session.url, 303);\n } catch (error) {\n console.error(\"[Stripe Portal Error]\", error);\n return errorResponse(\n error instanceof Error ? error.message : \"Unknown error occurred\",\n 500\n );\n }\n };\n}\n","import type { PayloadHandler, PayloadRequest } from \"payload\";\nimport type { Customer, CustomerInventory } from \"../../../types/index.js\";\nimport type { StripeEndpointConfig } from \"../../plugin/stripe-inventory-types.js\";\nimport { upsertCustomerInventoryAndSyncWithUser } from \"../../utils/payload/upsert-customer-inventory-and-sync-with-user.js\";\nimport { stripeBuilder } from \"../../utils/stripe/stripe-builder.js\";\nimport {\n errorResponse,\n redirectResponse,\n validateAuthenticatedRequest,\n} from \"../validators/request-validator.js\";\n\n/**\n * Creates a handler for updating Stripe subscriptions (cancel at period end)\n *\n * @param config - Endpoint configuration\n * @returns PayloadHandler for update endpoint\n */\nexport function createUpdateHandler(config: StripeEndpointConfig): PayloadHandler {\n return async (request: PayloadRequest): Promise<Response> => {\n try {\n // Validate authenticated user\n const validated = await validateAuthenticatedRequest(request, config);\n if (!validated.success) {\n return validated.error;\n }\n\n const { user, payload } = validated;\n\n // Extract params\n const url = new URL(request.url || \"\");\n const subscriptionId = url.searchParams.get(\"subscriptionId\");\n const cancelAtPeriodEnd = url.searchParams.get(\"cancelAtPeriodEnd\") === \"true\";\n\n if (!subscriptionId) {\n return errorResponse(\"subscriptionId is required\", 400);\n }\n\n const stripe = stripeBuilder();\n\n // Update subscription in Stripe\n await stripe.subscriptions.update(subscriptionId, {\n cancel_at_period_end: cancelAtPeriodEnd,\n });\n\n // Update local inventory\n const customer = user.customer as Customer | undefined;\n const inventory = customer?.inventory as CustomerInventory | null;\n\n if (inventory?.subscriptions?.[subscriptionId]) {\n inventory.subscriptions[subscriptionId].cancel_at_period_end = cancelAtPeriodEnd;\n }\n\n // Sync inventory\n if (customer?.email) {\n await upsertCustomerInventoryAndSyncWithUser(\n payload,\n inventory,\n customer.email\n );\n }\n\n // Redirect back to subscription page\n return redirectResponse(\n `${process.env.DOMAIN}${config.routes.subscriptionPageHref}?refresh=${Date.now()}`,\n 303\n );\n } catch (error) {\n console.error(\"[Stripe Update Error]\", error);\n return errorResponse(\n error instanceof Error ? error.message : \"Unknown error occurred\",\n 500\n );\n }\n };\n}\n","import type { Endpoint } from \"payload\";\nimport type { StripeEndpointConfig } from \"../plugin/stripe-inventory-types.js\";\nimport { createCheckoutHandler } from \"./handlers/checkout-handler.js\";\nimport { createDonationHandler } from \"./handlers/donation-handler.js\";\nimport { createPortalHandler } from \"./handlers/portal-handler.js\";\nimport { createUpdateHandler } from \"./handlers/update-handler.js\";\n\nexport * from \"./handlers/checkout-handler.js\";\nexport * from \"./handlers/donation-handler.js\";\nexport * from \"./handlers/portal-handler.js\";\nexport * from \"./handlers/update-handler.js\";\nexport * from \"./validators/index.js\";\n\n/**\n * Creates all Stripe inventory endpoints\n *\n * @param config - Endpoint configuration\n * @param basePath - Base path for endpoints (default: '/stripe')\n * @returns Array of Payload endpoints\n *\n * @example\n * ```typescript\n * const endpoints = createStripeEndpoints({\n * routes: { subscriptionPageHref: '/account/subscription' },\n * });\n * // Endpoints:\n * // GET /api/stripe/checkout?priceId={id}\n * // GET /api/stripe/portal\n * // GET /api/stripe/update?subscriptionId={id}&cancelAtPeriodEnd={bool}\n * // GET /api/stripe/donation?amount={cents}\n * ```\n */\nexport function createStripeEndpoints(\n config: StripeEndpointConfig,\n basePath: string = \"/stripe\"\n): Endpoint[] {\n return [\n {\n path: `${basePath}/checkout`,\n method: \"get\",\n handler: createCheckoutHandler(config),\n },\n {\n path: `${basePath}/portal`,\n method: \"get\",\n handler: createPortalHandler(config),\n },\n {\n path: `${basePath}/update`,\n method: \"get\",\n handler: createUpdateHandler(config),\n },\n {\n path: `${basePath}/donation`,\n method: \"get\",\n handler: createDonationHandler(config),\n },\n ];\n}\n","/**\n * Stripe Inventory Plugin Factory for Payload CMS\n *\n * This plugin automatically registers Stripe endpoints and webhook handlers.\n * It replaces the need for manual Next.js route handlers.\n *\n * @example\n * ```typescript\n * // payload.config.ts\n * import { createStripeInventoryPlugin } from '@nexo-labs/payload-stripe-inventory/server';\n *\n * export default buildConfig({\n * plugins: [\n * createStripeInventoryPlugin({\n * routes: { subscriptionPageHref: '/account/subscription' },\n * onSubscriptionUpdate: async (type, userId) => {\n * console.log(`Subscription ${type} for user ${userId}`);\n * },\n * }),\n * ],\n * });\n * ```\n */\n\nimport type { Config, Plugin } from \"payload\";\nimport { stripePlugin } from \"@payloadcms/plugin-stripe\";\nimport {\n priceDeleted,\n subscriptionUpsert,\n subscriptionDeleted,\n productDeleted,\n paymentSucceeded,\n invoiceSucceeded,\n customerDeleted,\n} from \"../actions/index.js\";\nimport { createStripeEndpoints } from \"../endpoints/index.js\";\nimport type {\n StripeEndpointConfig,\n StripeInventoryPluginConfig,\n} from \"./stripe-inventory-types.js\";\n\nexport type { StripeInventoryPluginConfig, StripeEndpointConfig };\nexport { createStripeEndpoints };\n\n/**\n * Creates the Stripe Inventory plugin for Payload CMS\n *\n * This plugin:\n * - Registers REST endpoints for checkout, portal, update, and donation\n * - Sets up Stripe webhook handlers for subscription and payment events\n * - Syncs customer data between Stripe and Payload\n *\n * @param config - Plugin configuration\n * @returns A Payload plugin function\n *\n * Endpoints registered:\n * - GET /api{basePath}/checkout?priceId={id} - Redirect to Stripe Checkout\n * - GET /api{basePath}/portal - Redirect to Stripe Billing Portal\n * - GET /api{basePath}/update?subscriptionId={id}&cancelAtPeriodEnd={bool} - Update subscription\n * - GET /api{basePath}/donation?amount={cents} - Returns JSON with checkout URL\n */\nexport function createStripeInventoryPlugin(\n config: StripeInventoryPluginConfig\n): Plugin {\n const basePath = config.basePath || \"/stripe\";\n\n // Build endpoint configuration\n const endpointConfig: StripeEndpointConfig = {\n routes: config.routes,\n checkPermissions: config.checkPermissions,\n resolveUser: config.resolveUser,\n };\n\n // Callback for subscription updates (defaults to no-op)\n const onSubscriptionUpdate =\n config.onSubscriptionUpdate ||\n (async () => {\n /* no-op */\n });\n\n return (incomingConfig: Config): Config => {\n // 1. Create and register Stripe endpoints\n const stripeEndpoints = createStripeEndpoints(endpointConfig, basePath);\n\n const configWithEndpoints: Config = {\n ...incomingConfig,\n endpoints: [...(incomingConfig.endpoints || []), ...stripeEndpoints],\n };\n\n // 2. Apply the base Stripe plugin with webhook handlers\n const stripePluginInstance = stripePlugin({\n isTestKey: process.env.STRIPE_SECRET_KEY?.includes(\"sk_test\"),\n stripeSecretKey: process.env.STRIPE_SECRET_KEY || \"\",\n stripeWebhooksEndpointSecret: process.env.STRIPE_WEBHOOK_SECRET,\n webhooks: {\n \"price.deleted\": async ({ event, payload }) =>\n await priceDeleted(event.data.object, payload),\n \"customer.subscription.created\": async ({ event, payload }) =>\n await subscriptionUpsert(\n event.data.object,\n payload,\n onSubscriptionUpdate\n ),\n \"customer.subscription.paused\": async ({ event, payload }) =>\n await subscriptionUpsert(\n event.data.object,\n payload,\n onSubscriptionUpdate\n ),\n \"customer.subscription.updated\": async ({ event, payload }) =>\n await subscriptionUpsert(\n event.data.object,\n payload,\n onSubscriptionUpdate\n ),\n \"customer.subscription.deleted\": async ({ event, payload }) =>\n await subscriptionDeleted(\n event.data.object,\n payload,\n onSubscriptionUpdate\n ),\n \"customer.deleted\": async ({ event, payload }) =>\n await customerDeleted(event.data.object, payload),\n \"product.deleted\": async ({ event, payload }) =>\n await productDeleted(event.data.object, payload),\n \"payment_intent.succeeded\": async ({ event, payload }) => {\n await paymentSucceeded(event.data.object, payload);\n },\n \"invoice.paid\": async ({ event, payload }) => {\n await invoiceSucceeded(event.data.object, payload);\n },\n },\n });\n\n // 3. Apply the Stripe plugin to the config with endpoints\n return stripePluginInstance(configWithEndpoints);\n };\n}\n","import { Access } from \"payload\";\nimport { permissionSlugs } from \"../../model/constants.js\";\n\nexport const isAdmin: Access = ({ req }) => {\n return req?.user?.roles?.includes(permissionSlugs.webAdmin) || false;\n};\n\nexport const isAnyone: Access = () => true;\n\nexport const isAdminOrCurrentUser: Access = ({ req }) => {\n if (req?.user?.roles?.includes(permissionSlugs.webAdmin)) return true;\n return { id: { equals: req.user?.id } };\n};\n\nexport const isAdminOrPublished: Access = ({ req: { user } }) => {\n if (user && user?.roles?.includes(permissionSlugs.webAdmin)) {\n return true;\n }\n\n return {\n _status: {\n equals: \"published\",\n },\n };\n};\n\nexport const isAdminOrStripeActive: Access = ({ req: { user } }) => {\n if (user && user?.roles?.includes(permissionSlugs.webAdmin)) {\n return true;\n }\n\n return {\n active: {\n equals: true,\n },\n };\n};\n\nexport const isAdminOrUserFieldMatchingCurrentUser: Access = ({\n req: { user },\n}) => {\n if (user) {\n if (user?.roles?.includes(permissionSlugs.webAdmin)) return true;\n return {\n user: {\n equals: user?.id,\n },\n };\n }\n return false;\n};\n\nexport const loggedInOrPublished: Access = ({ req: { user } }) => {\n if (user) {\n return true;\n }\n\n return {\n _status: {\n equals: \"published\",\n },\n };\n};\n","import type { PayloadRequest } from \"payload\";\nimport type { BaseUser } from \"../../types/index.js\";\n\n/**\n * Gets the current user from a PayloadRequest without depending on next/headers.\n * This is the recommended way to get the user in Payload endpoint handlers.\n *\n * @param request - The PayloadRequest object\n * @returns The user object or null if not authenticated\n */\nexport function getUserFromRequest(request: PayloadRequest): BaseUser | null {\n return request.user as BaseUser | null;\n}\n","import { CollectionConfig } from \"payload\";\nimport { isAdmin } from \"../access/index.js\";\nimport { COLLECTION_SLUG_CUSTOMERS } from \"../../model/index.js\";\n\nexport const customers: CollectionConfig = {\n slug: COLLECTION_SLUG_CUSTOMERS,\n admin: {\n useAsTitle: \"email\",\n group: \"Stripe\",\n defaultColumns: [\"email\", \"stripeId\", \"createdAt\"],\n },\n access: {\n read: () => true,\n create: () => false,\n update: () => false,\n delete: isAdmin,\n },\n fields: [\n {\n name: \"email\",\n type: \"email\",\n required: true,\n unique: true,\n admin: {\n position: \"sidebar\",\n },\n },\n {\n name: \"stripeId\",\n type: \"text\",\n required: true,\n unique: true,\n admin: {\n position: \"sidebar\",\n readOnly: true,\n },\n },\n {\n name: \"inventory\",\n type: \"json\",\n label: \"Inventario\",\n admin: {\n description: \"Datos de inventario de Stripe almacenados como JSON\",\n readOnly: true,\n },\n },\n ],\n};\n","import { COLLECTION_SLUG_TAXONOMY } from \"@nexo-labs/payload-taxonomies\";\nimport { Field } from \"payload\";\n\nexport const permissionEvaluationField: Field = {\n type: 'row',\n fields: [\n {\n type: 'select',\n name: 'type_of_permissions',\n options: [\n { label: 'Todos', value: 'all' },\n { label: 'Permisos por roles', value: 'roles' },\n { label: 'Solo para usuarios sin roles', value: 'only_no_roles' },\n { label: 'Solo invitados', value: 'only_guess' },\n ],\n defaultValue: 'all',\n label: 'Tipo de permisos',\n },\n {\n type: 'relationship',\n name: 'permissions',\n relationTo: [COLLECTION_SLUG_TAXONOMY],\n hasMany: false,\n admin: {\n condition: (_, siblingData) => siblingData.type_of_permissions === 'roles',\n }\n }\n ]\n}","import { CollectionConfig } from \"payload\";\nimport {\n COLLECTION_SLUG_PRICES,\n COLLECTION_SLUG_PRODUCTS,\n PricingPlanInterval,\n PricingType,\n formatOptions,\n} from \"../../model/index.js\";\nimport { isAdmin, isAdminOrStripeActive } from \"../access/index.js\";\n\nexport const prices: CollectionConfig = {\n slug: COLLECTION_SLUG_PRICES,\n admin: {\n useAsTitle: \"unitAmount\",\n group: \"Stripe\",\n },\n access: {\n read: isAdminOrStripeActive,\n create: () => false,\n update: () => false,\n delete: isAdmin,\n },\n fields: [\n {\n name: \"stripeID\",\n label: \"Stripe ID\",\n type: \"text\",\n required: true,\n admin: { position: \"sidebar\", readOnly: true },\n },\n {\n name: \"stripeProductId\",\n type: \"text\",\n required: true,\n admin: { position: \"sidebar\", readOnly: true },\n },\n {\n name: \"product\",\n type: \"join\",\n collection: COLLECTION_SLUG_PRODUCTS,\n on: \"prices\",\n hasMany: false,\n },\n {\n name: \"active\",\n type: \"checkbox\",\n required: true,\n admin: { position: \"sidebar\" },\n },\n { name: \"description\", type: \"textarea\" },\n {\n type: \"row\",\n fields: [\n { name: \"unitAmount\", type: \"number\", required: true },\n { name: \"currency\", type: \"text\", required: true },\n {\n name: \"type\",\n type: \"select\",\n options: formatOptions(PricingType),\n required: true,\n },\n ],\n },\n {\n type: \"row\",\n fields: [\n {\n name: \"interval\",\n type: \"select\",\n options: formatOptions(PricingPlanInterval),\n },\n { name: \"intervalCount\", type: \"number\" },\n { name: \"trialPeriodDays\", type: \"number\" },\n ],\n },\n { name: \"metadata\", type: \"json\", label: \"Metadata\" },\n ],\n};\n","import { buildTaxonomyRelationship } from \"@nexo-labs/payload-taxonomies\";\nimport { CollectionConfig } from \"payload\";\nimport { COLLECTION_SLUG_PRICES, COLLECTION_SLUG_PRODUCTS } from \"../../model/index.js\";\nimport { isAdminOrStripeActive } from \"../access/index.js\";\n\nexport const products: CollectionConfig = {\n slug: COLLECTION_SLUG_PRODUCTS,\n admin: {\n useAsTitle: \"name\",\n group: \"Stripe\",\n },\n access: {\n read: isAdminOrStripeActive,\n create: () => false,\n },\n fields: [\n {\n name: \"stripeID\",\n label: \"Stripe ID\",\n type: \"text\",\n required: true,\n admin: { position: \"sidebar\", readOnly: true },\n },\n {\n name: \"type\",\n type: \"select\",\n options: [\n { value: \"good\", label: \"Bienes\" },\n { value: \"service\", label: \"Service\" },\n ],\n },\n {\n name: \"active\",\n type: \"checkbox\",\n required: true,\n admin: { position: \"sidebar\" },\n },\n {\n name: \"show\",\n type: \"checkbox\",\n defaultValue: false,\n admin: { position: \"sidebar\" },\n },\n { name: \"name\", type: \"text\", required: true },\n { name: \"description\", type: \"textarea\" },\n { name: \"images\", type: \"array\", fields: [{ type: \"text\", name: \"url\" }] },\n {\n name: \"prices\",\n type: \"relationship\",\n relationTo: COLLECTION_SLUG_PRICES,\n hasMany: true,\n required: false,\n },\n { name: \"metadata\", type: \"json\", label: \"Metadata\" },\n {\n type: \"array\",\n name: \"features\",\n fields: [{ type: \"text\", name: \"title\" }],\n },\n buildTaxonomyRelationship({\n name: \"roles\",\n label: \"Roles\",\n defaultValue: [],\n filterOptions: () => {\n return {\n \"payload.types\": { in: [\"role\"] },\n };\n },\n required: false,\n }),\n ],\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["stripeInstance: Stripe | null","prices","products","customers","existingCustomer: Customer | null","customer","products","inventory: CustomerInventory","inventory: UserInventory","user: BaseUser | null","metadata: Stripe.MetadataParam","metadata: Stripe.MetadataParam","flowData: Stripe.BillingPortal.SessionCreateParams.FlowData | undefined","endpointConfig: StripeEndpointConfig","configWithEndpoints: Config","isAdmin: Access","isAnyone: Access","isAdminOrCurrentUser: Access","isAdminOrPublished: Access","isAdminOrStripeActive: Access","isAdminOrUserFieldMatchingCurrentUser: Access","loggedInOrPublished: Access","customers: CollectionConfig","prices: CollectionConfig","products: CollectionConfig"],"sources":["../../src/server/utils/payload/upsert.ts","../../src/server/utils/stripe/stripe-builder.ts","../../src/server/actions/price.ts","../../src/server/actions/product.ts","../../src/server/utils/payload/sync-customer-by-email.ts","../../src/server/utils/payload/upsert-customer-inventory-and-sync-with-user.ts","../../src/server/utils/payload/get-userId-by-email.ts","../../src/server/utils/stripe/get-customer.ts","../../src/server/utils/payload/remove-customer-by-stripe-id.ts","../../src/server/utils/payload/find-or-create-customer.ts","../../src/server/actions/subscription.ts","../../src/server/actions/donation.ts","../../src/server/actions/invoice.ts","../../src/server/actions/customer.ts","../../src/server/actions/unlock-item-for-user-action.ts","../../src/server/actions/update-products-and-prices-action.ts","../../src/server/utils/stripe/create-customer-at-stripe.ts","../../src/server/utils/stripe/get-customer-from-stripe-or-create.ts","../../src/server/endpoints/validators/request-validator.ts","../../src/server/endpoints/handlers/checkout-handler.ts","../../src/server/endpoints/handlers/donation-handler.ts","../../src/server/endpoints/handlers/portal-handler.ts","../../src/server/endpoints/handlers/update-handler.ts","../../src/server/endpoints/index.ts","../../src/server/plugin/create-stripe-inventory-plugin.ts","../../src/server/access/access-queries.ts","../../src/server/access/get-user-from-request.ts","../../src/server/collections/customers.ts","../../src/server/collections/prices.ts","../../src/server/collections/products.ts"],"sourcesContent":["\"use server\";\n\nimport { Payload } from \"payload\"\n\ntype Config = {\n collections: {\n [key: string]: any\n }\n}\n\ninterface UpsertOptions<T extends keyof Config['collections']> {\n collection: T\n payload: Payload\n data: Omit<Config['collections'][T], 'createdAt' | 'id' | 'updatedAt' | 'sizes'>\n where: any\n}\n\nexport const payloadUpsert = async <T extends keyof Config['collections']>({\n payload,\n collection,\n data,\n where,\n}: UpsertOptions<T>): Promise<Config['collections'][T] | null> => {\n try {\n const existingDocs = await payload.find({\n collection: collection as any,\n where,\n pagination: false,\n limit: 1,\n })\n\n const existingDocId = existingDocs.docs?.at(0)?.id\n if (existingDocId) {\n const updatedDoc = await payload.update({\n collection: collection as any,\n id: existingDocId,\n data: data as any,\n })\n\n return updatedDoc || null\n }\n\n return await payload.create({\n collection,\n data,\n } as any)\n } catch (error) {\n console.error(`Error in payloadUpsert: ${error}`)\n throw new Error(`Failed to upsert document in collection ${collection} ${error}`)\n }\n}\n","import Stripe from \"stripe\";\n\nlet stripeInstance: Stripe | null = null;\n\nexport const stripeBuilder = (): Stripe => {\n if (stripeInstance) {\n return stripeInstance;\n }\n\n const secretKey = process.env.STRIPE_SECRET_KEY;\n if (!secretKey) {\n throw new Error(\"STRIPE_SECRET_KEY environment variable is not set\");\n }\n\n stripeInstance = new Stripe(secretKey, {\n apiVersion: '2024-09-30.acacia'\n });\n\n return stripeInstance;\n}\n","\"use server\";\n\nimport type { Payload } from \"payload\";\nimport type Stripe from \"stripe\";\nimport {\n COLLECTION_SLUG_PRICES,\n COLLECTION_SLUG_PRODUCTS,\n} from \"../../model/index.js\";\nimport { payloadUpsert } from \"../utils/payload/upsert.js\";\nimport { stripeBuilder } from \"../utils/stripe/stripe-builder.js\";\n\nexport const updatePrices = async (payload: Payload) => {\n const stripe = await stripeBuilder();\n const prices = await stripe.prices.list({ limit: 100, active: true });\n const promises = prices.data.map(price => priceUpsert(price, payload));\n const pricesUpserted = await Promise.all(promises);\n\n const pricesByProductId = pricesUpserted\n .filter((p): p is PriceUpserted => p !== null)\n .reduce(\n (acc, { productId, priceId }) => {\n if (!acc[productId]) {\n acc[productId] = [];\n }\n acc[productId].push(priceId);\n return acc;\n },\n {} as Record<string, number[]>\n );\n\n await Promise.all(\n Object.entries(pricesByProductId).map(async ([productId, prices]) => {\n await payload.update({\n collection: COLLECTION_SLUG_PRODUCTS,\n data: {\n prices,\n },\n where: {\n stripeID: { equals: productId },\n },\n });\n })\n );\n};\n\ninterface PriceUpserted {\n productId: string;\n priceId: number;\n}\n\nexport async function priceUpsert(\n price: Stripe.Price,\n payload: Payload\n): Promise<PriceUpserted | null> {\n const stripeProductID =\n typeof price.product === \"string\" ? price.product : price.product.id;\n\n if (price.deleted !== undefined) {\n await priceDeleted(price, payload);\n return null;\n }\n if (price.unit_amount == null) return null;\n const priceUpserted = await payloadUpsert({\n payload,\n collection: COLLECTION_SLUG_PRICES,\n data: {\n stripeID: price.id,\n stripeProductId: stripeProductID,\n active: price.active,\n unitAmount: price.unit_amount as number,\n currency: price.currency,\n type: price.type,\n interval: price.recurring?.interval,\n intervalCount: price.recurring?.interval_count,\n },\n where: {\n stripeID: { equals: price.id },\n },\n });\n if (!priceUpserted) return null;\n return { productId: stripeProductID, priceId: priceUpserted.id };\n}\n\nexport const priceDeleted = async (price: Stripe.Price, payload: Payload) => {\n const { id } = price;\n\n try {\n await payload.delete({\n collection: COLLECTION_SLUG_PRICES,\n where: {\n stripeID: { equals: id },\n },\n });\n } catch (error) {\n payload.logger.error(`- Error deleting price: ${error}`);\n throw error;\n }\n};\n","\"use server\";\n\nimport type { Payload } from \"payload\";\nimport type Stripe from \"stripe\";\nimport { COLLECTION_SLUG_PRODUCTS } from \"../../model/index.js\";\nimport { payloadUpsert } from \"../utils/payload/upsert.js\";\nimport { stripeBuilder } from \"../utils/stripe/stripe-builder.js\";\n\nconst logs = false;\n\nexport const updateProducts = async (payload: Payload) => {\n const stripe = await stripeBuilder();\n const products = await stripe.products.list({ limit: 100, active: true });\n await Promise.all(products.data.map(product => productSync(product, payload)));\n};\n\nexport const productSync = async (object: Stripe.Product, payload: Payload) => {\n const { id: stripeProductID, name, description, images } = object;\n if (object.deleted !== undefined) return await productDeleted(object, payload);\n try {\n await payloadUpsert({\n payload,\n collection: COLLECTION_SLUG_PRODUCTS,\n data: {\n prices: [],\n stripeID: stripeProductID,\n active: true,\n metadata: object.metadata,\n type: object.type,\n name,\n description,\n images: images?.map(image => ({ url: image })) || [],\n },\n where: {\n stripeID: { equals: stripeProductID },\n },\n });\n } catch (error) {\n console.error(error);\n throw error;\n }\n};\n\nexport const productDeleted = async (\n object: Stripe.Product,\n payload: Payload\n) => {\n const { id: stripeProductID } = object;\n\n try {\n const productQuery = await payload.find({\n collection: COLLECTION_SLUG_PRODUCTS,\n where: {\n stripeID: { equals: stripeProductID },\n },\n });\n\n const payloadProductID = productQuery.docs?.[0]?.id;\n\n if (payloadProductID) {\n await payload.delete({\n collection: COLLECTION_SLUG_PRODUCTS,\n id: payloadProductID,\n });\n\n if (logs)\n payload.logger.info(\n `✅ Successfully deleted product with Stripe ID: ${stripeProductID}`\n );\n }\n } catch (error) {\n payload.logger.error(`- Error deleting product: ${error}`);\n throw error;\n }\n};\n","import { COLLECTION_SLUG_CUSTOMERS, COLLECTION_SLUG_USER } from \"../../../model/index.js\";\nimport { Payload } from \"payload\";\n\nexport async function syncCustomerByEmail({ email, payload }: { email: string, payload: Payload }) {\n const customers = await payload.find({\n collection: COLLECTION_SLUG_CUSTOMERS,\n where: { email: { equals: email } },\n });\n const customerId = customers.docs?.[0]?.id;\n\n await payload.update({\n collection: COLLECTION_SLUG_USER,\n data: {\n customer: customerId,\n },\n where: { email: { equals: email } },\n });\n}\n","import { COLLECTION_SLUG_CUSTOMERS, generateCustomerInventory } from \"../../../model/index.js\";\nimport type { CustomerInventory } from \"../../../types/index.js\";\nimport { syncCustomerByEmail } from \"./sync-customer-by-email.js\";\nimport { payloadUpsert } from \"./upsert.js\";\nimport { Payload } from \"payload\";\n\nexport async function upsertCustomerInventoryAndSyncWithUser(\n payload: Payload,\n inventory: CustomerInventory | null | undefined,\n email: string,\n stripeCustomerId?: string | null\n) {\n await payloadUpsert({\n payload,\n collection: COLLECTION_SLUG_CUSTOMERS,\n data: {\n email: email,\n stripeId: stripeCustomerId,\n inventory: inventory ?? generateCustomerInventory(),\n },\n where: { email: { equals: email } },\n });\n await syncCustomerByEmail({ email, payload });\n}\n","import { COLLECTION_SLUG_USER } from \"../../../model/index.js\";\nimport { Payload } from \"payload\";\n\ninterface Props {\n email: string;\n payload: Payload;\n}\n\n/**\n * Gets a user ID by email address using Payload's find method\n * @param email - The email address to search for\n * @returns The user ID if found, null otherwise\n */\nexport async function getUserIdByEmail({email, payload}: Props): Promise<string | null | undefined> {\n const userQuery = await payload.find({\n collection: COLLECTION_SLUG_USER,\n where: {\n email: { equals: email },\n },\n });\n\n const user = userQuery.docs?.[0];\n return user?.id as string | null;\n}\n","import Stripe from \"stripe\";\nimport { stripeBuilder } from \"./stripe-builder.js\";\n\nexport async function getCustomer({\n stripe,\n email,\n}: {\n stripe?: Stripe;\n email: string;\n}): Promise<Stripe.Customer | null> {\n stripe = stripe ?? stripeBuilder();\n // Escape single quotes in email to prevent query injection\n const sanitizedEmail = email.replace(/'/g, \"\\\\'\");\n const customers = await stripe.customers.search({\n query: `email:'${sanitizedEmail}'`,\n });\n return customers.data.length ? customers.data[0] as Stripe.Customer : null;\n}\n\nexport async function resolveStripeCustomer({ customer }: {\n customer: string | Stripe.Customer | Stripe.DeletedCustomer | null\n}): Promise<Stripe.Customer | Stripe.DeletedCustomer | null> {\n const stripe = stripeBuilder();\n if (typeof customer === \"string\") {\n return await stripe.customers.retrieve(customer);\n }\n return customer;\n}","import { Payload } from \"payload\";\nimport { COLLECTION_SLUG_CUSTOMERS } from \"../../../model/index.js\";\n\nexport async function removeCustomerByStripeId({\n stripeId,\n payload,\n}: {\n stripeId: string;\n payload: Payload;\n}) {\n await payload.delete({\n collection: COLLECTION_SLUG_CUSTOMERS,\n where: { stripeId: { equals: stripeId } },\n });\n payload.logger.info(`✅ Successfully removed customer with Stripe ID: ${stripeId}`);\n}","import { Payload } from \"payload\";\nimport {\n COLLECTION_SLUG_CUSTOMERS,\n generateCustomerInventory,\n} from \"../../../model/index.js\";\nimport { Customer, CustomerInventory } from \"../../../types/index.js\";\n\ninterface FindOrCreateCustomerProps {\n email: string;\n payload: Payload;\n stripeId?: string;\n}\n\n/**\n * Finds a customer by email address in the customers collection, or creates one if not found\n * @param email - The email address to search for\n * @param payload - Payload instance\n * @param stripeId - Optional Stripe customer ID to set when creating\n * @returns The customer document (found or created)\n */\nexport async function findOrCreateCustomer({\n email,\n payload,\n stripeId,\n}: FindOrCreateCustomerProps): Promise<Customer | null> {\n if (!email) {\n payload.logger.error(\"Email is required to find or create customer\");\n return null;\n }\n\n try {\n const userQuery = await payload.find({\n collection: COLLECTION_SLUG_CUSTOMERS,\n where: {\n email: { equals: email },\n },\n });\n\n let existingCustomer: Customer | null = userQuery.docs?.[0] as unknown as Customer | null;\n if (existingCustomer) {\n existingCustomer.inventory = existingCustomer?.inventory\n ? (existingCustomer.inventory as unknown as CustomerInventory)\n : generateCustomerInventory();\n return existingCustomer;\n }\n\n payload.logger.info(`Creating new customer for email: ${email}`);\n\n const newCustomer = await payload.create({\n collection: COLLECTION_SLUG_CUSTOMERS,\n data: {\n email,\n stripeId: stripeId || \"\",\n inventory: generateCustomerInventory() as unknown as [k: string],\n },\n });\n\n payload.logger.info(`✅ Successfully created customer for email: ${email}`);\n return newCustomer as unknown as Customer;\n } catch (error) {\n payload.logger.error(\n `Error finding or creating customer for email ${email}: ${error}`\n );\n throw error;\n }\n}\n","import { Payload } from \"payload\";\nimport type Stripe from \"stripe\";\nimport { COLLECTION_SLUG_PRODUCTS, generateCustomerInventory } from \"../../model/index.js\";\nimport type { CustomerInventory } from \"../../types/index.js\";\nimport { upsertCustomerInventoryAndSyncWithUser } from \"../utils/payload/upsert-customer-inventory-and-sync-with-user.js\";\nimport { getUserIdByEmail } from \"../utils/payload/get-userId-by-email.js\";\nimport { resolveStripeCustomer } from \"../utils/stripe/get-customer.js\";\nimport { removeCustomerByStripeId } from \"../utils/payload/remove-customer-by-stripe-id.js\";\nimport { findOrCreateCustomer } from \"../utils/payload/find-or-create-customer.js\";\nimport type { ResolveSubscriptionPermissions } from \"../plugin/stripe-inventory-types.js\";\n\nexport const subscriptionUpsert = async <TProduct = unknown>(\n subscription: Stripe.Subscription,\n payload: Payload,\n onSubscriptionUpdate: (\n type: \"create\" | \"delete\",\n userId: string\n ) => Promise<void>,\n resolveSubscriptionPermissions: ResolveSubscriptionPermissions<TProduct>\n) => {\n const { id: stripeID, status, customer: stripeCustomer } = subscription;\n const customer = await resolveStripeCustomer({ customer: stripeCustomer });\n const error = (message: string) =>\n payload.logger.error(\"Subscription Upsert: \", message as any);\n const info = (message: string) =>\n payload.logger.info(\"Subscription Upsert: \", message as any);\n\n if (!customer) {\n error(\"No stripe customer found for subscription\");\n return;\n }\n if (customer.deleted) {\n await removeCustomerByStripeId({ stripeId: customer.id, payload });\n return;\n }\n if (!customer.email) {\n error(\"No email found for stripe customer\");\n return;\n }\n const email = customer.email;\n const stripeId = customer.id;\n\n try {\n const customer = await findOrCreateCustomer({\n email,\n payload,\n stripeId,\n });\n\n const item = subscription.items.data.at(0);\n if (!item || !customer) {\n error(`No item ${item} or customer ${customer} found`);\n return;\n }\n\n const { docs: products } = await payload.find({\n collection: COLLECTION_SLUG_PRODUCTS,\n where: { stripeID: { equals: item.price.product } },\n });\n const product = products.at(0);\n if (!product) return;\n\n const inventory = customer.inventory;\n inventory.subscriptions[stripeID] = {\n ...subscription,\n permissions: await resolveSubscriptionPermissions(subscription, product as TProduct, payload),\n };\n info(`INVENTORY OF THE SUBSCRIPTION ${inventory}`);\n await upsertCustomerInventoryAndSyncWithUser(payload, inventory, email, stripeId);\n\n if ([\"active\", \"trialing\"].includes(status)) {\n const userId = await getUserIdByEmail({ email, payload });\n if (!userId) return;\n await onSubscriptionUpdate(\"create\", userId);\n }\n info(\n `✅ Successfully updated subscription with ID: ${stripeID} for user: ${email}`\n );\n } catch (e) {\n error(`- Error managing subscription: ${e}`);\n throw e;\n }\n};\n\nexport const subscriptionDeleted = async (\n subscription: Stripe.Subscription,\n payload: Payload,\n onSubscriptionUpdate: (\n type: \"create\" | \"delete\",\n userId: string\n ) => Promise<void>\n) => {\n const { id, customer: customerId } = subscription;\n const customer = await resolveStripeCustomer({ customer: customerId });\n const stripeId = customer?.id;\n if (!customer) {\n payload.logger.error(\"No stripe customer found for subscription\");\n return;\n }\n if (customer.deleted) {\n await removeCustomerByStripeId({ stripeId: customer.id, payload });\n return;\n }\n if (!customer.email) {\n payload.logger.error(\"No email found for stripe customer\");\n return;\n }\n const email = customer.email;\n try {\n const customer = await findOrCreateCustomer({\n email,\n payload,\n stripeId\n });\n if (!customer) {\n payload.logger.error(\"No customer found for subscription\");\n return;\n }\n\n const inventory: CustomerInventory = customer.inventory ?? generateCustomerInventory();\n delete inventory.subscriptions[id];\n\n await upsertCustomerInventoryAndSyncWithUser(payload, inventory, email, stripeId);\n const userId = await getUserIdByEmail({ email, payload });\n if (!userId) {\n payload.logger.error(\"No user found for subscription\");\n return;\n }\n await onSubscriptionUpdate(\"delete\", userId);\n\n payload.logger.info(\n `✅ Successfully deleted subscription: ${id} for user: ${email}`\n );\n } catch (error) {\n payload.logger.error(`- Error deleting subscription: ${error}`);\n throw error;\n }\n};\n","import { Payload } from \"payload\";\nimport type Stripe from \"stripe\";\nimport { COLLECTION_SLUG_CUSTOMERS, generateCustomerInventory } from \"../../model/index.js\";\nimport { resolveStripeCustomer } from \"../utils/stripe/get-customer.js\";\nimport { findOrCreateCustomer } from \"../utils/payload/find-or-create-customer.js\";\nimport { removeCustomerByStripeId } from \"../utils/payload/remove-customer-by-stripe-id.js\";\n\nexport const paymentSucceeded = async (\n paymentIntent: Stripe.PaymentIntent,\n payload: Payload\n) => {\n const { id, customer: paymentCustomer } = paymentIntent;\n const stripeCustomer = await resolveStripeCustomer({ customer: paymentCustomer });\n if (!stripeCustomer) {\n payload.logger.error(\"No stripe customer found for payment\");\n return\n }\n if (stripeCustomer.deleted) {\n await removeCustomerByStripeId({ stripeId: stripeCustomer.id, payload });\n return;\n }\n if (!stripeCustomer.email) {\n payload.logger.error(\"No email found for stripe customer\");\n return;\n }\n\n try {\n const customer = await findOrCreateCustomer({\n email: stripeCustomer.email,\n payload,\n stripeId: stripeCustomer.id,\n });\n if (!customer) {\n payload.logger.error(`Customer not found for payment: ${stripeCustomer.email}`);\n return;\n }\n\n const inventory = customer.inventory ?? generateCustomerInventory();\n inventory.payments[id] = paymentIntent;\n\n await payload.update({\n collection: COLLECTION_SLUG_CUSTOMERS,\n data: { inventory: inventory as unknown as { [x: string]: {} } },\n where: { email: { equals: stripeCustomer.email } },\n });\n\n payload.logger.info(\n `✅ Successfully recorded ${stripeCustomer.metadata?.type ?? \"subscription\"} with Payment Intent ID: ${id} for user: ${stripeCustomer.email}`\n );\n } catch (error) {\n payload.logger.error(`- Error recording payment: ${error}`);\n throw error;\n }\n};\n","import { Payload } from \"payload\";\nimport type Stripe from \"stripe\";\nimport { COLLECTION_SLUG_CUSTOMERS, generateCustomerInventory } from \"../../model/index.js\";\nimport { findOrCreateCustomer } from \"../utils/payload/find-or-create-customer.js\";\nimport { resolveStripeCustomer } from \"../utils/stripe/get-customer.js\";\nimport { removeCustomerByStripeId } from \"../utils/payload/remove-customer-by-stripe-id.js\";\n\nexport const invoiceSucceeded = async (\n invoiceIntent: Stripe.Invoice,\n payload: Payload\n) => {\n const { id, customer: paymentCustomer } = invoiceIntent;\n const stripeCustomer = await resolveStripeCustomer({ customer: paymentCustomer });\n if (!stripeCustomer) {\n payload.logger.error(\"No stripe customer found for payment\");\n return\n }\n if (stripeCustomer.deleted) {\n await removeCustomerByStripeId({ stripeId: stripeCustomer.id, payload });\n return;\n }\n if (!stripeCustomer.email) {\n payload.logger.error(\"No email found for stripe customer\");\n return;\n }\n\n try {\n const customer = await findOrCreateCustomer({\n email: stripeCustomer.email,\n payload,\n stripeId: stripeCustomer.id,\n });\n if (!customer) {\n payload.logger.error(`Customer not found for invoice: ${stripeCustomer.email}`);\n return;\n }\n\n const inventory = customer.inventory ?? generateCustomerInventory();\n inventory.invoices[id] = invoiceIntent;\n\n await payload.update({\n collection: COLLECTION_SLUG_CUSTOMERS,\n data: { inventory: inventory as unknown as { [x: string]: {} } },\n where: { email: { equals: stripeCustomer.email } },\n });\n\n payload.logger.info(\n `✅ Successfully recorded ${stripeCustomer.metadata?.type ?? \"subscription\"} with Payment Intent ID: ${id} for user: ${stripeCustomer.email}`\n );\n } catch (error) {\n payload.logger.error(`- Error recording payment: ${error}`);\n throw error;\n }\n};\n","import { Payload } from \"payload\";\nimport Stripe from \"stripe\";\nimport { COLLECTION_SLUG_CUSTOMERS } from \"../../index.js\";\n\nexport const customerDeleted = async (\n customer: Stripe.Customer,\n payload: Payload,\n ) => {\n const { id, email } = customer;\n try { \n await payload.delete({\n collection: COLLECTION_SLUG_CUSTOMERS,\n where: { email: { equals: email } },\n });\n payload.logger.info(\n `✅ Successfully deleted customer with Stripe ID: ${id}`\n );\n } catch (error) {\n payload.logger.error(`- Error deleting subscription: ${error}`);\n throw error;\n }\n };\n ","import { Payload } from \"payload\";\nimport {\n checkIfUserCanUnlockQuery,\n COLLECTION_SLUG_USER,\n countWeeklyUnlocksQuery,\n MAX_UNLOCKS_PER_WEEK,\n} from \"../../model/index.js\";\nimport { generateUserInventory } from \"../../model/builders.js\";\nimport type { BaseUser, UnlockItem, UserInventory, Result } from \"../../types/index.js\";\nimport type { ResolveContentPermissions } from \"../plugin/stripe-inventory-types.js\";\n\n\nconst addUniqueUnlock = (\n unlocks: UnlockItem[],\n collection: string,\n contentId: number\n): UnlockItem[] => {\n const isDuplicate = unlocks.some(\n unlock => unlock.collection === collection && unlock.id === contentId\n );\n\n if (isDuplicate) {\n return unlocks;\n }\n return [\n ...unlocks,\n {\n collection,\n id: contentId,\n dateUnlocked: new Date(),\n },\n ];\n};\n\n/**\n * Creates an unlock action with the specified content permissions resolver.\n *\n * @param resolveContentPermissions - Callback to resolve permissions required by content\n * @returns A function that unlocks items for users\n *\n * @example\n * ```typescript\n * const unlockItem = createUnlockAction(async (content, payload) => {\n * return content.requiredPermissions || [];\n * });\n *\n * // Use in server actions\n * await unlockItem(payload, user, 'posts', 123);\n * ```\n */\nexport const createUnlockAction = <TContent = unknown>(\n resolveContentPermissions: ResolveContentPermissions<TContent>\n) => {\n /**\n * Unlocks an item for a user, adding it to their inventory.\n *\n * @param payload - The Payload instance\n * @param user - The authenticated user\n * @param collection - The collection slug of the item to unlock\n * @param contentId - The ID of the item to unlock\n * @returns Result indicating success or error message\n */\n return async (\n payload: Payload,\n user: BaseUser,\n collection: string,\n contentId: number\n ): Promise<Result<boolean>> => {\n if (!user || !user.id) {\n return { error: \"Usuario no válido\" };\n }\n // Collection slug is validated by the consumer - cast required for generic plugin\n const item = await payload.findByID({\n collection: collection as \"users\",\n id: contentId.toString(),\n });\n\n if (!item) {\n return { error: \"Elemento no encontrado\" };\n }\n const permissions = await resolveContentPermissions(item as TContent, payload);\n\n if (!checkIfUserCanUnlockQuery(user, permissions)) {\n return { error: \"No tienes permisos para desbloquear este elemento\" };\n }\n\n const weeklyUnlocks = countWeeklyUnlocksQuery(user);\n if (weeklyUnlocks >= MAX_UNLOCKS_PER_WEEK) {\n return {\n error: `Has alcanzado el límite de ${MAX_UNLOCKS_PER_WEEK} desbloqueos para esta semana`,\n };\n }\n\n const inventory: UserInventory =\n (user.inventory as UserInventory | undefined) ?? generateUserInventory();\n\n const updatedUnlocks = addUniqueUnlock(\n inventory.unlocks,\n collection,\n contentId\n );\n\n if (updatedUnlocks.length === inventory.unlocks.length) {\n return { data: true };\n }\n\n try {\n await payload.update({\n collection: COLLECTION_SLUG_USER,\n id: user.id.toString(),\n data: {\n inventory: {\n ...inventory,\n unlocks: updatedUnlocks,\n },\n },\n });\n\n return { data: true };\n } catch (error) {\n console.error(\"Error al actualizar el inventario del usuario:\", error);\n return { error: \"Error al actualizar el inventario del usuario\" };\n }\n };\n};\n","\"use server\";\n\nimport { updatePrices } from \"./price.js\";\nimport { updateProducts } from \"./product.js\";\nimport { Payload } from \"payload\";\n\nexport async function updateProductsAndPrices(payload: Payload) {\n await updateProducts(payload);\n await updatePrices(payload);\n}\n","import Stripe from \"stripe\";\nimport { stripeBuilder } from \"./stripe-builder.js\";\n\nexport async function createCustomerAtStripe({\n stripe,\n email,\n name,\n}: {\n stripe?: Stripe;\n email: string;\n name?: string;\n}) {\n stripe = stripe ?? stripeBuilder();\n return await stripe.customers.create({\n email: email,\n name: name || undefined,\n });\n}\n","import { createCustomerAtStripe } from \"./create-customer-at-stripe.js\";\nimport { getCustomer } from \"./get-customer.js\";\nimport { stripeBuilder } from \"./stripe-builder.js\";\n\nexport async function getCustomerFromStripeOrCreate(\n email: string,\n name?: string\n): Promise<string> {\n const stripe = stripeBuilder();\n let customer = await getCustomer({ stripe, email });\n if (!customer) {\n customer = await createCustomerAtStripe({ stripe, email, name });\n }\n return customer.id;\n}\n","import type { Payload, PayloadRequest } from \"payload\";\nimport type { BaseUser } from \"../../../types/index.js\";\nimport type { StripeEndpointConfig } from \"../../plugin/stripe-inventory-types.js\";\n\n/**\n * Creates a JSON response using Web API Response\n */\nexport function jsonResponse(data: unknown, options?: ResponseInit): Response {\n return new Response(JSON.stringify(data), {\n headers: { \"Content-Type\": \"application/json\" },\n ...options,\n });\n}\n\n/**\n * Creates a redirect response using Web API Response\n * @param url - The URL to redirect to\n * @param status - HTTP status code (default: 303 See Other)\n */\nexport function redirectResponse(url: string, status: number = 303): Response {\n return new Response(null, {\n status,\n headers: { Location: url },\n });\n}\n\n/**\n * Creates an error response\n */\nexport function errorResponse(\n message: string,\n status: number = 400\n): Response {\n return jsonResponse({ error: message }, { status });\n}\n\n/**\n * Result type for validateAuthenticatedRequest\n */\nexport type AuthenticatedRequestResult =\n | { success: false; error: Response }\n | {\n success: true;\n user: BaseUser;\n payload: Payload;\n };\n\n/**\n * Validates that the request has an authenticated user\n * Uses the config's resolveUser if provided, otherwise uses request.user\n */\nexport async function validateAuthenticatedRequest(\n request: PayloadRequest,\n config: StripeEndpointConfig\n): Promise<AuthenticatedRequestResult> {\n // Check custom permissions if provided\n if (config.checkPermissions) {\n const hasPermission = await config.checkPermissions(request);\n if (!hasPermission) {\n return {\n success: false,\n error: errorResponse(\"Permission denied\", 403),\n };\n }\n }\n\n // Resolve user\n let user: BaseUser | null = null;\n\n if (config.resolveUser) {\n user = await config.resolveUser(request);\n } else {\n user = request.user as BaseUser | null;\n }\n\n if (!user) {\n return {\n success: false,\n error: errorResponse(\"You must be logged in to access this endpoint\", 401),\n };\n }\n\n if (!user.email) {\n return {\n success: false,\n error: errorResponse(\"User email is required\", 400),\n };\n }\n\n return {\n success: true,\n user,\n payload: request.payload,\n };\n}\n","import type { PayloadHandler, PayloadRequest } from \"payload\";\nimport type Stripe from \"stripe\";\nimport type { StripeEndpointConfig } from \"../../plugin/stripe-inventory-types.js\";\nimport { upsertCustomerInventoryAndSyncWithUser } from \"../../utils/payload/upsert-customer-inventory-and-sync-with-user.js\";\nimport { getCustomerFromStripeOrCreate } from \"../../utils/stripe/get-customer-from-stripe-or-create.js\";\nimport { stripeBuilder } from \"../../utils/stripe/stripe-builder.js\";\nimport {\n errorResponse,\n redirectResponse,\n validateAuthenticatedRequest,\n} from \"../validators/request-validator.js\";\n\n/**\n * Creates a handler for Stripe checkout sessions (subscriptions)\n *\n * @param config - Endpoint configuration\n * @returns PayloadHandler for checkout endpoint\n */\nexport function createCheckoutHandler(config: StripeEndpointConfig): PayloadHandler {\n return async (request: PayloadRequest): Promise<Response> => {\n try {\n // Validate authenticated user\n const validated = await validateAuthenticatedRequest(request, config);\n if (!validated.success) {\n return validated.error;\n }\n\n const { user, payload } = validated;\n\n // Validate user email\n if (!user.email) {\n return errorResponse(\"User email is required\", 400);\n }\n\n // Extract priceId from query params\n const url = new URL(request.url || \"\");\n const priceId = url.searchParams.get(\"priceId\");\n\n if (!priceId) {\n return errorResponse(\"priceId is required\", 400);\n }\n\n const stripe = stripeBuilder();\n\n // Get or create Stripe customer\n const customerId = await getCustomerFromStripeOrCreate(\n user.email,\n user.name\n );\n\n // Sync customer inventory\n await upsertCustomerInventoryAndSyncWithUser(\n payload,\n user.customer?.inventory,\n user.email,\n customerId\n );\n\n // Prepare checkout session\n const metadata: Stripe.MetadataParam = {\n type: \"subscription\",\n };\n\n const checkoutResult = await stripe.checkout.sessions.create({\n success_url: `${process.env.DOMAIN}${config.routes.subscriptionPageHref}?success=${Date.now()}`,\n cancel_url: `${process.env.DOMAIN}${config.routes.subscriptionPageHref}?error=${Date.now()}`,\n mode: \"subscription\",\n customer: customerId,\n client_reference_id: String(user.id),\n line_items: [{ price: priceId, quantity: 1 }],\n metadata,\n tax_id_collection: { enabled: true },\n customer_update: {\n name: \"auto\",\n address: \"auto\",\n shipping: \"auto\",\n },\n subscription_data: { metadata },\n });\n\n if (checkoutResult.url) {\n return redirectResponse(checkoutResult.url, 303);\n }\n\n return errorResponse(\"Failed to create checkout URL\", 406);\n } catch (error) {\n console.error(\"[Stripe Checkout Error]\", error);\n return errorResponse(\n error instanceof Error ? error.message : \"Unknown error occurred\",\n 500\n );\n }\n };\n}\n","import type { PayloadHandler, PayloadRequest } from \"payload\";\nimport type Stripe from \"stripe\";\nimport type { StripeEndpointConfig } from \"../../plugin/stripe-inventory-types.js\";\nimport { upsertCustomerInventoryAndSyncWithUser } from \"../../utils/payload/upsert-customer-inventory-and-sync-with-user.js\";\nimport { getCustomerFromStripeOrCreate } from \"../../utils/stripe/get-customer-from-stripe-or-create.js\";\nimport { stripeBuilder } from \"../../utils/stripe/stripe-builder.js\";\nimport {\n errorResponse,\n jsonResponse,\n validateAuthenticatedRequest,\n} from \"../validators/request-validator.js\";\n\n/**\n * Creates a handler for one-time donation payments\n *\n * @param config - Endpoint configuration\n * @returns PayloadHandler for donation endpoint\n */\nexport function createDonationHandler(config: StripeEndpointConfig): PayloadHandler {\n return async (request: PayloadRequest): Promise<Response> => {\n try {\n // Validate authenticated user\n const validated = await validateAuthenticatedRequest(request, config);\n if (!validated.success) {\n return validated.error;\n }\n\n const { user, payload } = validated;\n\n // Validate user email\n if (!user.email) {\n return errorResponse(\"User email is required\", 400);\n }\n\n // Extract amount from query params\n const url = new URL(request.url || \"\");\n const amountParam = url.searchParams.get(\"amount\");\n\n if (!amountParam) {\n return errorResponse(\"amount is required\", 400);\n }\n\n const amount = parseInt(amountParam, 10);\n\n if (isNaN(amount) || amount < 100) {\n return errorResponse(\"Minimum donation amount is 1 EUR (100 cents)\", 400);\n }\n\n const stripe = stripeBuilder();\n\n // Get or create Stripe customer\n const customerId = await getCustomerFromStripeOrCreate(\n user.email,\n user.name\n );\n\n // Sync customer inventory\n await upsertCustomerInventoryAndSyncWithUser(\n payload,\n user.customer?.inventory,\n user.email,\n customerId\n );\n\n // Determine redirect URLs\n const donationPageHref = config.routes.donationPageHref || config.routes.subscriptionPageHref;\n\n // Prepare metadata\n const metadata: Stripe.MetadataParam = {\n type: \"donation\",\n };\n\n // Create checkout session for one-time payment\n const session = await stripe.checkout.sessions.create({\n customer: customerId,\n payment_method_types: [\"card\"],\n line_items: [\n {\n price_data: {\n currency: \"eur\",\n product_data: {\n name: \"Donation\",\n description: \"One-time donation\",\n },\n unit_amount: amount,\n },\n quantity: 1,\n },\n ],\n mode: \"payment\",\n success_url: `${process.env.DOMAIN}${donationPageHref}?success=donation`,\n cancel_url: `${process.env.DOMAIN}${donationPageHref}?error=donation_cancelled`,\n metadata,\n payment_intent_data: { metadata },\n invoice_creation: { enabled: true, invoice_data: { metadata } },\n });\n\n return jsonResponse({ url: session.url });\n } catch (error) {\n console.error(\"[Stripe Donation Error]\", error);\n return errorResponse(\n error instanceof Error ? error.message : \"Unknown error occurred\",\n 500\n );\n }\n };\n}\n","import type { PayloadHandler, PayloadRequest } from \"payload\";\nimport type Stripe from \"stripe\";\nimport type { StripeEndpointConfig } from \"../../plugin/stripe-inventory-types.js\";\nimport { upsertCustomerInventoryAndSyncWithUser } from \"../../utils/payload/upsert-customer-inventory-and-sync-with-user.js\";\nimport { getCustomerFromStripeOrCreate } from \"../../utils/stripe/get-customer-from-stripe-or-create.js\";\nimport { stripeBuilder } from \"../../utils/stripe/stripe-builder.js\";\nimport {\n errorResponse,\n redirectResponse,\n validateAuthenticatedRequest,\n} from \"../validators/request-validator.js\";\n\n/**\n * Creates a handler for Stripe Billing Portal access\n *\n * @param config - Endpoint configuration\n * @returns PayloadHandler for portal endpoint\n */\nexport function createPortalHandler(config: StripeEndpointConfig): PayloadHandler {\n return async (request: PayloadRequest): Promise<Response> => {\n try {\n // Validate authenticated user\n const validated = await validateAuthenticatedRequest(request, config);\n if (!validated.success) {\n return validated.error;\n }\n\n const { user, payload } = validated;\n\n // Validate user email\n if (!user.email) {\n return errorResponse(\"User email is required\", 400);\n }\n\n // Extract optional params for subscription actions\n const url = new URL(request.url || \"\");\n const cancelSubscriptionId = url.searchParams.get(\"cancelSubscriptionId\");\n const updateSubscriptionId = url.searchParams.get(\"updateSubscriptionId\");\n\n // Validate subscription ID format if provided (Stripe IDs start with 'sub_')\n if (cancelSubscriptionId && !cancelSubscriptionId.startsWith(\"sub_\")) {\n return errorResponse(\"Invalid subscription ID format\", 400);\n }\n if (updateSubscriptionId && !updateSubscriptionId.startsWith(\"sub_\")) {\n return errorResponse(\"Invalid subscription ID format\", 400);\n }\n\n // Build flow data if subscription action is requested\n let flowData: Stripe.BillingPortal.SessionCreateParams.FlowData | undefined;\n\n if (cancelSubscriptionId) {\n flowData = {\n type: \"subscription_cancel\",\n subscription_cancel: { subscription: cancelSubscriptionId },\n };\n } else if (updateSubscriptionId) {\n flowData = {\n type: \"subscription_update\",\n subscription_update: { subscription: updateSubscriptionId },\n };\n }\n\n const stripe = stripeBuilder();\n\n // Get or create Stripe customer\n const customerId = await getCustomerFromStripeOrCreate(\n user.email,\n user.name\n );\n\n // Sync customer inventory\n await upsertCustomerInventoryAndSyncWithUser(\n payload,\n user.customer?.inventory,\n user.email,\n customerId\n );\n\n // Create billing portal session\n const session = await stripe.billingPortal.sessions.create({\n flow_data: flowData,\n customer: customerId,\n return_url: `${process.env.DOMAIN}${config.routes.subscriptionPageHref}`,\n });\n\n return redirectResponse(session.url, 303);\n } catch (error) {\n console.error(\"[Stripe Portal Error]\", error);\n return errorResponse(\n error instanceof Error ? error.message : \"Unknown error occurred\",\n 500\n );\n }\n };\n}\n","import type { PayloadHandler, PayloadRequest } from \"payload\";\nimport type { Customer, CustomerInventory } from \"../../../types/index.js\";\nimport type { StripeEndpointConfig } from \"../../plugin/stripe-inventory-types.js\";\nimport { upsertCustomerInventoryAndSyncWithUser } from \"../../utils/payload/upsert-customer-inventory-and-sync-with-user.js\";\nimport { stripeBuilder } from \"../../utils/stripe/stripe-builder.js\";\nimport {\n errorResponse,\n redirectResponse,\n validateAuthenticatedRequest,\n} from \"../validators/request-validator.js\";\n\n/**\n * Creates a handler for updating Stripe subscriptions (cancel at period end)\n *\n * @param config - Endpoint configuration\n * @returns PayloadHandler for update endpoint\n */\nexport function createUpdateHandler(config: StripeEndpointConfig): PayloadHandler {\n return async (request: PayloadRequest): Promise<Response> => {\n try {\n // Validate authenticated user\n const validated = await validateAuthenticatedRequest(request, config);\n if (!validated.success) {\n return validated.error;\n }\n\n const { user, payload } = validated;\n\n // Extract params\n const url = new URL(request.url || \"\");\n const subscriptionId = url.searchParams.get(\"subscriptionId\");\n const cancelAtPeriodEnd = url.searchParams.get(\"cancelAtPeriodEnd\") === \"true\";\n\n if (!subscriptionId) {\n return errorResponse(\"subscriptionId is required\", 400);\n }\n\n // Validate subscription ID format\n if (!subscriptionId.startsWith(\"sub_\")) {\n return errorResponse(\"Invalid subscription ID format\", 400);\n }\n\n const stripe = stripeBuilder();\n\n // Get current subscription state for potential rollback\n const originalSubscription = await stripe.subscriptions.retrieve(subscriptionId);\n const originalCancelAtPeriodEnd = originalSubscription.cancel_at_period_end;\n\n // Update subscription in Stripe\n await stripe.subscriptions.update(subscriptionId, {\n cancel_at_period_end: cancelAtPeriodEnd,\n });\n\n // Update local inventory\n const customer = user.customer as Customer | undefined;\n const inventory = customer?.inventory as CustomerInventory | null;\n\n if (inventory?.subscriptions?.[subscriptionId]) {\n inventory.subscriptions[subscriptionId].cancel_at_period_end = cancelAtPeriodEnd;\n }\n\n // Sync inventory with rollback on failure\n if (customer?.email) {\n try {\n await upsertCustomerInventoryAndSyncWithUser(\n payload,\n inventory,\n customer.email\n );\n } catch (syncError) {\n // Rollback Stripe change if local sync fails\n console.error(\"[Stripe Update] Local sync failed, rolling back Stripe change\", syncError);\n await stripe.subscriptions.update(subscriptionId, {\n cancel_at_period_end: originalCancelAtPeriodEnd,\n });\n throw syncError;\n }\n }\n\n // Redirect back to subscription page\n return redirectResponse(\n `${process.env.DOMAIN}${config.routes.subscriptionPageHref}?refresh=${Date.now()}`,\n 303\n );\n } catch (error) {\n console.error(\"[Stripe Update Error]\", error);\n return errorResponse(\n error instanceof Error ? error.message : \"Unknown error occurred\",\n 500\n );\n }\n };\n}\n","import type { Endpoint } from \"payload\";\nimport type { StripeEndpointConfig } from \"../plugin/stripe-inventory-types.js\";\nimport { createCheckoutHandler } from \"./handlers/checkout-handler.js\";\nimport { createDonationHandler } from \"./handlers/donation-handler.js\";\nimport { createPortalHandler } from \"./handlers/portal-handler.js\";\nimport { createUpdateHandler } from \"./handlers/update-handler.js\";\n\nexport * from \"./handlers/checkout-handler.js\";\nexport * from \"./handlers/donation-handler.js\";\nexport * from \"./handlers/portal-handler.js\";\nexport * from \"./handlers/update-handler.js\";\nexport * from \"./validators/index.js\";\n\n/**\n * Creates all Stripe inventory endpoints\n *\n * @param config - Endpoint configuration\n * @param basePath - Base path for endpoints (default: '/stripe')\n * @returns Array of Payload endpoints\n *\n * @example\n * ```typescript\n * const endpoints = createStripeEndpoints({\n * routes: { subscriptionPageHref: '/account/subscription' },\n * });\n * // Endpoints:\n * // GET /api/stripe/checkout?priceId={id}\n * // GET /api/stripe/portal\n * // GET /api/stripe/update?subscriptionId={id}&cancelAtPeriodEnd={bool}\n * // GET /api/stripe/donation?amount={cents}\n * ```\n */\nexport function createStripeEndpoints(\n config: StripeEndpointConfig,\n basePath: string = \"/stripe\"\n): Endpoint[] {\n return [\n {\n path: `${basePath}/checkout`,\n method: \"get\",\n handler: createCheckoutHandler(config),\n },\n {\n path: `${basePath}/portal`,\n method: \"get\",\n handler: createPortalHandler(config),\n },\n {\n path: `${basePath}/update`,\n method: \"get\",\n handler: createUpdateHandler(config),\n },\n {\n path: `${basePath}/donation`,\n method: \"get\",\n handler: createDonationHandler(config),\n },\n ];\n}\n","/**\n * Stripe Inventory Plugin Factory for Payload CMS\n *\n * This plugin automatically registers Stripe endpoints and webhook handlers.\n * It replaces the need for manual Next.js route handlers.\n *\n * @example\n * ```typescript\n * // payload.config.ts\n * import { createStripeInventoryPlugin } from '@nexo-labs/payload-stripe-inventory/server';\n *\n * export default buildConfig({\n * plugins: [\n * createStripeInventoryPlugin({\n * routes: { subscriptionPageHref: '/account/subscription' },\n * onSubscriptionUpdate: async (type, userId) => {\n * console.log(`Subscription ${type} for user ${userId}`);\n * },\n * resolveSubscriptionPermissions: async (subscription, product, payload) => {\n * // Extract permissions from product metadata or custom fields\n * return product?.metadata?.permissions?.split(',') || [];\n * },\n * resolveContentPermissions: async (content, payload) => {\n * // Extract required permissions from content\n * return content.requiredPermissions || [];\n * },\n * }),\n * ],\n * });\n * ```\n */\n\nimport type { Config, Plugin } from \"payload\";\nimport { stripePlugin } from \"@payloadcms/plugin-stripe\";\nimport {\n priceDeleted,\n subscriptionUpsert,\n subscriptionDeleted,\n productDeleted,\n paymentSucceeded,\n invoiceSucceeded,\n customerDeleted,\n} from \"../actions/index.js\";\nimport { createStripeEndpoints } from \"../endpoints/index.js\";\nimport type {\n StripeEndpointConfig,\n StripeInventoryPluginConfig,\n ResolveSubscriptionPermissions,\n ResolveContentPermissions,\n} from \"./stripe-inventory-types.js\";\n\nexport type { StripeInventoryPluginConfig, StripeEndpointConfig, ResolveSubscriptionPermissions, ResolveContentPermissions };\nexport { createStripeEndpoints };\n\n/**\n * Creates the Stripe Inventory plugin for Payload CMS\n *\n * This plugin:\n * - Registers REST endpoints for checkout, portal, update, and donation\n * - Sets up Stripe webhook handlers for subscription and payment events\n * - Syncs customer data between Stripe and Payload\n *\n * @param config - Plugin configuration\n * @returns A Payload plugin function\n *\n * Endpoints registered:\n * - GET /api{basePath}/checkout?priceId={id} - Redirect to Stripe Checkout\n * - GET /api{basePath}/portal - Redirect to Stripe Billing Portal\n * - GET /api{basePath}/update?subscriptionId={id}&cancelAtPeriodEnd={bool} - Update subscription\n * - GET /api{basePath}/donation?amount={cents} - Returns JSON with checkout URL\n */\nexport function createStripeInventoryPlugin<\n TProduct = unknown,\n TContent = unknown\n>(\n config: StripeInventoryPluginConfig<TProduct, TContent>\n): Plugin {\n const basePath = config.basePath || \"/stripe\";\n\n // Build endpoint configuration\n const endpointConfig: StripeEndpointConfig = {\n routes: config.routes,\n checkPermissions: config.checkPermissions,\n resolveUser: config.resolveUser,\n };\n\n // Callback for subscription updates (defaults to no-op)\n const onSubscriptionUpdate =\n config.onSubscriptionUpdate ||\n (async () => {\n /* no-op */\n });\n\n // Required callbacks for permission resolution\n const { resolveSubscriptionPermissions, resolveContentPermissions } = config;\n\n return (incomingConfig: Config): Config => {\n // 1. Create and register Stripe endpoints\n const stripeEndpoints = createStripeEndpoints(endpointConfig, basePath);\n\n const configWithEndpoints: Config = {\n ...incomingConfig,\n endpoints: [...(incomingConfig.endpoints || []), ...stripeEndpoints],\n };\n\n // 2. Apply the base Stripe plugin with webhook handlers\n const stripePluginInstance = stripePlugin({\n isTestKey: process.env.STRIPE_SECRET_KEY?.includes(\"sk_test\"),\n stripeSecretKey: process.env.STRIPE_SECRET_KEY || \"\",\n stripeWebhooksEndpointSecret: process.env.STRIPE_WEBHOOK_SECRET,\n webhooks: {\n \"price.deleted\": async ({ event, payload }) =>\n await priceDeleted(event.data.object, payload),\n \"customer.subscription.created\": async ({ event, payload }) =>\n await subscriptionUpsert<TProduct>(\n event.data.object,\n payload,\n onSubscriptionUpdate,\n resolveSubscriptionPermissions\n ),\n \"customer.subscription.paused\": async ({ event, payload }) =>\n await subscriptionUpsert<TProduct>(\n event.data.object,\n payload,\n onSubscriptionUpdate,\n resolveSubscriptionPermissions\n ),\n \"customer.subscription.updated\": async ({ event, payload }) =>\n await subscriptionUpsert<TProduct>(\n event.data.object,\n payload,\n onSubscriptionUpdate,\n resolveSubscriptionPermissions\n ),\n \"customer.subscription.deleted\": async ({ event, payload }) =>\n await subscriptionDeleted(\n event.data.object,\n payload,\n onSubscriptionUpdate\n ),\n \"customer.deleted\": async ({ event, payload }) =>\n await customerDeleted(event.data.object, payload),\n \"product.deleted\": async ({ event, payload }) =>\n await productDeleted(event.data.object, payload),\n \"payment_intent.succeeded\": async ({ event, payload }) => {\n await paymentSucceeded(event.data.object, payload);\n },\n \"invoice.paid\": async ({ event, payload }) => {\n await invoiceSucceeded(event.data.object, payload);\n },\n },\n });\n\n // 3. Apply the Stripe plugin to the config with endpoints\n return stripePluginInstance(configWithEndpoints);\n };\n}\n","import { Access } from \"payload\";\nimport { permissionSlugs } from \"../../model/constants.js\";\n\nexport const isAdmin: Access = ({ req }) => {\n return req?.user?.roles?.includes(permissionSlugs.webAdmin) || false;\n};\n\nexport const isAnyone: Access = () => true;\n\nexport const isAdminOrCurrentUser: Access = ({ req }) => {\n if (req?.user?.roles?.includes(permissionSlugs.webAdmin)) return true;\n return { id: { equals: req.user?.id } };\n};\n\nexport const isAdminOrPublished: Access = ({ req: { user } }) => {\n if (user && user?.roles?.includes(permissionSlugs.webAdmin)) {\n return true;\n }\n\n return {\n _status: {\n equals: \"published\",\n },\n };\n};\n\nexport const isAdminOrStripeActive: Access = ({ req: { user } }) => {\n if (user && user?.roles?.includes(permissionSlugs.webAdmin)) {\n return true;\n }\n\n return {\n active: {\n equals: true,\n },\n };\n};\n\nexport const isAdminOrUserFieldMatchingCurrentUser: Access = ({\n req: { user },\n}) => {\n if (user) {\n if (user?.roles?.includes(permissionSlugs.webAdmin)) return true;\n return {\n user: {\n equals: user?.id,\n },\n };\n }\n return false;\n};\n\nexport const loggedInOrPublished: Access = ({ req: { user } }) => {\n if (user) {\n return true;\n }\n\n return {\n _status: {\n equals: \"published\",\n },\n };\n};\n","import type { PayloadRequest } from \"payload\";\nimport type { BaseUser } from \"../../types/index.js\";\n\n/**\n * Gets the current user from a PayloadRequest without depending on next/headers.\n * This is the recommended way to get the user in Payload endpoint handlers.\n *\n * @param request - The PayloadRequest object\n * @returns The user object or null if not authenticated\n */\nexport function getUserFromRequest(request: PayloadRequest): BaseUser | null {\n return request.user as BaseUser | null;\n}\n","import { CollectionConfig } from \"payload\";\nimport { isAdmin } from \"../access/index.js\";\nimport { COLLECTION_SLUG_CUSTOMERS } from \"../../model/index.js\";\n\nexport const customers: CollectionConfig = {\n slug: COLLECTION_SLUG_CUSTOMERS,\n admin: {\n useAsTitle: \"email\",\n group: \"Stripe\",\n defaultColumns: [\"email\", \"stripeId\", \"createdAt\"],\n },\n access: {\n read: () => true,\n create: () => false,\n update: () => false,\n delete: isAdmin,\n },\n fields: [\n {\n name: \"email\",\n type: \"email\",\n required: true,\n unique: true,\n admin: {\n position: \"sidebar\",\n },\n },\n {\n name: \"stripeId\",\n type: \"text\",\n required: true,\n unique: true,\n admin: {\n position: \"sidebar\",\n readOnly: true,\n },\n },\n {\n name: \"inventory\",\n type: \"json\",\n label: \"Inventario\",\n admin: {\n description: \"Datos de inventario de Stripe almacenados como JSON\",\n readOnly: true,\n },\n },\n ],\n};\n","import { CollectionConfig } from \"payload\";\nimport {\n COLLECTION_SLUG_PRICES,\n COLLECTION_SLUG_PRODUCTS,\n PricingPlanInterval,\n PricingType,\n formatOptions,\n} from \"../../model/index.js\";\nimport { isAdmin, isAdminOrStripeActive } from \"../access/index.js\";\n\nexport const prices: CollectionConfig = {\n slug: COLLECTION_SLUG_PRICES,\n admin: {\n useAsTitle: \"unitAmount\",\n group: \"Stripe\",\n },\n access: {\n read: isAdminOrStripeActive,\n create: () => false,\n update: () => false,\n delete: isAdmin,\n },\n fields: [\n {\n name: \"stripeID\",\n label: \"Stripe ID\",\n type: \"text\",\n required: true,\n admin: { position: \"sidebar\", readOnly: true },\n },\n {\n name: \"stripeProductId\",\n type: \"text\",\n required: true,\n admin: { position: \"sidebar\", readOnly: true },\n },\n {\n name: \"product\",\n type: \"join\",\n collection: COLLECTION_SLUG_PRODUCTS,\n on: \"prices\",\n hasMany: false,\n },\n {\n name: \"active\",\n type: \"checkbox\",\n required: true,\n admin: { position: \"sidebar\" },\n },\n { name: \"description\", type: \"textarea\" },\n {\n type: \"row\",\n fields: [\n { name: \"unitAmount\", type: \"number\", required: true },\n { name: \"currency\", type: \"text\", required: true },\n {\n name: \"type\",\n type: \"select\",\n options: formatOptions(PricingType),\n required: true,\n },\n ],\n },\n {\n type: \"row\",\n fields: [\n {\n name: \"interval\",\n type: \"select\",\n options: formatOptions(PricingPlanInterval),\n },\n { name: \"intervalCount\", type: \"number\" },\n { name: \"trialPeriodDays\", type: \"number\" },\n ],\n },\n { name: \"metadata\", type: \"json\", label: \"Metadata\" },\n ],\n};\n","import { CollectionConfig } from \"payload\";\nimport { COLLECTION_SLUG_PRICES, COLLECTION_SLUG_PRODUCTS } from \"../../model/index.js\";\nimport { isAdminOrStripeActive } from \"../access/index.js\";\n\nexport const products: CollectionConfig = {\n slug: COLLECTION_SLUG_PRODUCTS,\n admin: {\n useAsTitle: \"name\",\n group: \"Stripe\",\n },\n access: {\n read: isAdminOrStripeActive,\n create: () => false,\n },\n fields: [\n {\n name: \"stripeID\",\n label: \"Stripe ID\",\n type: \"text\",\n required: true,\n admin: { position: \"sidebar\", readOnly: true },\n },\n {\n name: \"type\",\n type: \"select\",\n options: [\n { value: \"good\", label: \"Bienes\" },\n { value: \"service\", label: \"Service\" },\n ],\n },\n {\n name: \"active\",\n type: \"checkbox\",\n required: true,\n admin: { position: \"sidebar\" },\n },\n {\n name: \"show\",\n type: \"checkbox\",\n defaultValue: false,\n admin: { position: \"sidebar\" },\n },\n { name: \"name\", type: \"text\", required: true },\n { name: \"description\", type: \"textarea\" },\n { name: \"images\", type: \"array\", fields: [{ type: \"text\", name: \"url\" }] },\n {\n name: \"prices\",\n type: \"relationship\",\n relationTo: COLLECTION_SLUG_PRICES,\n hasMany: true,\n required: false,\n },\n { name: \"metadata\", type: \"json\", label: \"Metadata\" },\n {\n type: \"array\",\n name: \"features\",\n fields: [{ type: \"text\", name: \"title\" }],\n },\n ],\n};\n"],"mappings":"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"}
@@ -126,29 +126,6 @@ const evalAdvancePermissionQuery = ({ user, typeOfPermission, permissions }) =>
126
126
  return true;
127
127
  };
128
128
 
129
- //#endregion
130
- //#region src/model/permissions.ts
131
- const getPermissionsSlugs = ({ permissions }) => {
132
- return permissions?.mapNotNull((p) => typeof p === "number" ? null : p.slug) ?? [];
133
- };
134
-
135
- //#endregion
136
- //#region src/model/fetch-permitted-content-query.ts
137
- /**
138
- * Filtra contenido basado en los permisos del usuario
139
- */
140
- const fetchPermittedContentQuery = (user, permissions, content, freeContent = null) => {
141
- const permissionsSlugs = getPermissionsSlugs({ permissions });
142
- const isFreeContent = permissionsSlugs.includes(permissionSlugs.free);
143
- const hasPermission = evalPermissionByRoleQuery({
144
- user,
145
- permissions: permissionsSlugs
146
- });
147
- if (isFreeContent) return content;
148
- if (hasPermission) return content;
149
- return freeContent;
150
- };
151
-
152
129
  //#endregion
153
130
  //#region src/model/check-if-user-can-unlock-query.ts
154
131
  /**
@@ -171,9 +148,8 @@ const checkIfUserCanUnlockQuery = (user, permissions) => {
171
148
  const countWeeklyUnlocksQuery = (user) => {
172
149
  const inventory = user.inventory;
173
150
  if (!inventory || !inventory.unlocks || inventory.unlocks.length === 0) return 0;
174
- const sevenDaysAgo = /* @__PURE__ */ new Date();
175
- sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
176
- return inventory.unlocks.filter((unlock) => new Date(unlock.dateUnlocked) >= sevenDaysAgo).length;
151
+ const sevenDaysAgo = Date.now() - 10080 * 60 * 1e3;
152
+ return inventory.unlocks.filter((unlock) => new Date(unlock.dateUnlocked).getTime() >= sevenDaysAgo).length;
177
153
  };
178
154
 
179
155
  //#endregion
@@ -189,5 +165,16 @@ const getNextUnlockDateQuery = (user) => {
189
165
  };
190
166
 
191
167
  //#endregion
192
- export { generateUserInventory as S, PricingType as _, getPermissionsSlugs as a, permissionSlugs as b, isContentUnlocked as c, COLLECTION_SLUG_PRICES as d, COLLECTION_SLUG_PRODUCTS as f, PricingPlanInterval as g, PERMISSIONS as h, fetchPermittedContentQuery as i, getUserPermissions as l, MAX_UNLOCKS_PER_WEEK as m, countWeeklyUnlocksQuery as n, evalAdvancePermissionQuery as o, COLLECTION_SLUG_USER as p, checkIfUserCanUnlockQuery as r, evalPermissionByRoleQuery as s, getNextUnlockDateQuery as t, COLLECTION_SLUG_CUSTOMERS as u, QUERY_PERMISSION_TYPES as v, generateCustomerInventory as x, formatOptions as y };
193
- //# sourceMappingURL=src-BmlQoR4x.mjs.map
168
+ //#region src/types/result.types.ts
169
+ /**
170
+ * Helper to create a success result
171
+ */
172
+ const ok = (data) => ({ data });
173
+ /**
174
+ * Helper to create an error result
175
+ */
176
+ const err = (error) => ({ error });
177
+
178
+ //#endregion
179
+ export { generateUserInventory as S, PricingType as _, checkIfUserCanUnlockQuery as a, permissionSlugs as b, isContentUnlocked as c, COLLECTION_SLUG_PRICES as d, COLLECTION_SLUG_PRODUCTS as f, PricingPlanInterval as g, PERMISSIONS as h, countWeeklyUnlocksQuery as i, getUserPermissions as l, MAX_UNLOCKS_PER_WEEK as m, ok as n, evalAdvancePermissionQuery as o, COLLECTION_SLUG_USER as p, getNextUnlockDateQuery as r, evalPermissionByRoleQuery as s, err as t, COLLECTION_SLUG_CUSTOMERS as u, QUERY_PERMISSION_TYPES as v, generateCustomerInventory as x, formatOptions as y };
180
+ //# sourceMappingURL=src-I_DPhIL5.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"src-I_DPhIL5.mjs","names":[],"sources":["../src/model/builders.ts","../src/model/constants.ts","../src/model/get-user-permissions.ts","../src/model/is-content-unlocked.ts","../src/model/eval-permission-by-role-query.ts","../src/model/eval-advance-permissionQuery.ts","../src/model/check-if-user-can-unlock-query.ts","../src/model/get-count-weekly-unlocks-query.ts","../src/model/get-next-unlock-date-query.ts","../src/types/result.types.ts"],"sourcesContent":["import { CustomerInventory, UserInventory } from \"../types/index.js\";\n\nexport const generateUserInventory = (): UserInventory => ({\n unlocks: [],\n favorites: [],\n});\n\nexport const generateCustomerInventory = (): CustomerInventory => ({\n subscriptions: {},\n products: {},\n payments: {},\n invoices: {},\n});\n","export const COLLECTION_SLUG_PRODUCTS = \"products\" as const;\nexport const COLLECTION_SLUG_PRICES = \"prices\" as const;\nexport const COLLECTION_SLUG_USER = 'users' as const\nexport const COLLECTION_SLUG_CUSTOMERS = 'customers' as const\n\nexport const QUERY_PERMISSION_TYPES = {\n ALL: \"all\",\n ROLES: \"roles\",\n ONLY_NO_ROLES: \"only_no_roles\",\n ONLY_GUESS: \"only_guess\",\n} as const;\n\nconst FREEMIUM_PERMISSION = \"freemium\"\nconst FREE_PERMISSION = \"free\"\nconst TESTER_PERMISSION = \"tester\"\nconst DEV_PERMISSION = \"dev\"\nconst BASIC_PERMISSION = \"basic\"\nconst ADMIN_PERMISSION = \"web_admin\"\n\nexport const permissionSlugs = {\n webAdmin: ADMIN_PERMISSION,\n dev: DEV_PERMISSION,\n tester: TESTER_PERMISSION,\n free: FREE_PERMISSION,\n freemium: FREEMIUM_PERMISSION,\n basic: BASIC_PERMISSION,\n}\n\nexport const PERMISSIONS = [\n { id: 5, slug: FREE_PERMISSION, title: 'Free' },\n { id: 6, slug: FREEMIUM_PERMISSION, title: 'Freemium' },\n { id: 3, slug: TESTER_PERMISSION, title: 'Tester' },\n { id: 2, slug: DEV_PERMISSION, title: 'Developer' },\n { id: 1, slug: BASIC_PERMISSION, title: 'Basic' },\n { id: 4, slug: ADMIN_PERMISSION, title: 'Admin' },\n]\nexport const MAX_UNLOCKS_PER_WEEK = 3 as const;\n\nexport const PricingType = {\n one_time: \"One Time\",\n recurring: \"Recurring\",\n} as const;\n\nexport const PricingPlanInterval = {\n day: \"Day\",\n week: \"Week\",\n month: \"Month\",\n year: \"Year\",\n} as const;\n\nexport const formatOptions = (obj: Record<string, string>) =>\n Object.entries(obj).map(([key, value]) => ({ value: key, label: value }));\n\n","import { BaseUser, Customer } from \"../types/index.js\";\n\n/**\n * Obtiene los permisos de un usuario basados en su inventario y suscripciones activas\n */\nexport const getUserPermissions = (user?: BaseUser | null): string[] => {\n if (!user) return [];\n\n const customer = user?.customer as Customer;\n const inventory = customer?.inventory;\n if (!inventory) return [];\n\n const subscriptionPermissions = Object.values(inventory.subscriptions)\n ?.filter(\n subscription =>\n subscription.status === \"active\" || subscription.status === \"trialing\"\n )\n ?.flatMap(subscription => subscription.permissions);\n\n return subscriptionPermissions;\n};\n","import { BaseUser, UnlockItem, UserInventory } from \"../types/index.js\";\n\nexport const isContentUnlocked = (\n user: BaseUser<UserInventory>,\n contentId: number,\n collection: string\n): boolean => {\n if (!user?.inventory?.unlocks) return false;\n\n return user.inventory.unlocks.some(\n (unlock: UnlockItem) =>\n unlock.id === contentId && unlock.collection === collection\n );\n};\n","import type { BaseUser } from \"../types/index.js\";\nimport { permissionSlugs } from \"./constants.js\";\nimport { getUserPermissions } from \"./get-user-permissions.js\";\nimport { isContentUnlocked } from \"./is-content-unlocked.js\";\n/**\n * Evalúa si un usuario tiene los permisos necesarios basados en las semillas de permisos\n */\ninterface Props<T extends BaseUser> {\n user: T | null | undefined;\n permissions?: string[] | null;\n content?: {\n collection: string;\n id: number;\n };\n}\n\nexport const evalPermissionByRoleQuery = <T extends BaseUser>({\n user,\n permissions,\n content,\n}: Props<T>): boolean => {\n const userPermissions = getUserPermissions(user);\n\n if (!permissions || permissions.length === 0) return true;\n if (permissions.includes(permissionSlugs.free)) return true;\n const isUnlocked =\n user && content?.id\n ? isContentUnlocked(user, content.id, content.collection)\n : false;\n if (isUnlocked) return true;\n return permissions.some(\n permission => permission && userPermissions.includes(permission)\n );\n};\n","import type { BaseUser } from \"../types/index.js\";\nimport { QUERY_PERMISSION_TYPES } from \"./constants.js\";\nimport { evalPermissionByRoleQuery } from \"./eval-permission-by-role-query.js\";\nimport { getUserPermissions } from \"./get-user-permissions.js\";\n\n/**\n * Evalúa permisos avanzados basados en el tipo de permiso y usuario\n */\ninterface Props<T extends BaseUser> {\n user: T | null;\n typeOfPermission: keyof typeof QUERY_PERMISSION_TYPES | string;\n permissions?: string[] | undefined;\n}\n\nexport const evalAdvancePermissionQuery = <T extends BaseUser>({\n user,\n typeOfPermission,\n permissions,\n}: Props<T>): boolean => {\n if (typeOfPermission === QUERY_PERMISSION_TYPES.ALL) {\n return true;\n } else if (typeOfPermission === QUERY_PERMISSION_TYPES.ROLES) {\n return evalPermissionByRoleQuery({\n user,\n permissions,\n });\n } else if (typeOfPermission === QUERY_PERMISSION_TYPES.ONLY_NO_ROLES) {\n const userPermissions = getUserPermissions(user);\n return userPermissions.length === 0;\n } else if (typeOfPermission === QUERY_PERMISSION_TYPES.ONLY_GUESS) {\n return user === null;\n }\n\n return true;\n};\n","import { BaseUser } from \"../types/index.js\";\nimport { permissionSlugs } from \"./constants.js\";\n\n/**\n * Verifica si un usuario puede desbloquear un elemento basado en sus permisos y límites semanales\n * @param user Usuario base\n * @param permissions Permisos requeridos para el elemento\n * @returns Booleano indicando si el usuario puede desbloquear el elemento\n */\nexport const checkIfUserCanUnlockQuery = (\n user: BaseUser,\n permissions: string[]\n): boolean => {\n return (\n permissions\n .flatMap(item => item.split(\" \"))\n .includes(permissionSlugs.freemium) &&\n !permissions.includes(permissionSlugs.free)\n );\n};\n","import { BaseUser, UserInventory } from \"../types/index.js\";\n/**\n * Cuenta cuántos elementos ha desbloqueado el usuario en los últimos 7 días\n * @param user Usuario base\n * @returns Número de elementos desbloqueados en los últimos 7 días\n */\n\nexport const countWeeklyUnlocksQuery = (\n user: BaseUser<UserInventory>\n): number => {\n const inventory = user.inventory;\n if (!inventory || !inventory.unlocks || inventory.unlocks.length === 0) {\n return 0;\n }\n\n // Use UTC to ensure consistent counting regardless of server timezone\n const now = Date.now();\n const sevenDaysInMs = 7 * 24 * 60 * 60 * 1000;\n const sevenDaysAgo = now - sevenDaysInMs;\n\n return inventory.unlocks.filter(\n unlock => new Date(unlock.dateUnlocked).getTime() >= sevenDaysAgo\n ).length;\n};\n","import { BaseUser, UserInventory } from \"../types/index.js\";\n\nexport const getNextUnlockDateQuery = (user: BaseUser<UserInventory>): Date => {\n const inventory = user.inventory;\n if (!inventory || !inventory.unlocks || inventory.unlocks.length === 0) {\n return new Date();\n }\n\n const lastUnlock = inventory.unlocks.sort(\n (a, b) =>\n new Date(a.dateUnlocked).getTime() - new Date(b.dateUnlocked).getTime()\n )[inventory.unlocks.length - 1];\n\n const lastUnlockDate = lastUnlock ? new Date(lastUnlock.dateUnlocked) : new Date();\n const nextUnlockDate = new Date(lastUnlockDate);\n nextUnlockDate.setDate(lastUnlockDate.getDate() + 7);\n\n return nextUnlockDate;\n};\n","/**\n * A discriminated union type for representing operation results.\n * Inspired by Rust's Result type.\n *\n * @template T - The type of the success data\n * @template E - The type of the error (defaults to string)\n *\n * @example\n * ```typescript\n * function divide(a: number, b: number): Result<number> {\n * if (b === 0) {\n * return { error: \"Cannot divide by zero\" };\n * }\n * return { data: a / b };\n * }\n *\n * const result = divide(10, 2);\n * if (result.error) {\n * console.error(result.error);\n * } else {\n * console.log(result.data); // 5\n * }\n * ```\n */\nexport type Result<T, E = string> =\n | { data: T; error?: never }\n | { data?: never; error: E };\n\n/**\n * Helper to create a success result\n */\nexport const ok = <T>(data: T): Result<T, never> => ({ data });\n\n/**\n * Helper to create an error result\n */\nexport const err = <E = string>(error: E): Result<never, E> => ({ error });\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexo-labs/payload-stripe-inventory",
3
- "version": "1.6.12",
3
+ "version": "1.6.13",
4
4
  "description": "Sistema de inventario y suscripciones con Stripe para Payload CMS",
5
5
  "keywords": [
6
6
  "payload-cms",
@@ -42,8 +42,7 @@
42
42
  "next": "15.4.8",
43
43
  "payload": "^3.72.0",
44
44
  "react": "^19.0.0",
45
- "stripe": "17.2.1",
46
- "@nexo-labs/payload-taxonomies": "1.6.12"
45
+ "stripe": "17.2.1"
47
46
  },
48
47
  "devDependencies": {
49
48
  "@types/node": "^22.0.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-BFzOtUiG.d.mts","names":[],"sources":["../src/types/customer.types.ts","../src/types/permission.types.ts","../src/types/user-inventory.types.ts"],"sourcesContent":[],"mappings":";;;UAEiB,QAAA;;EAAA,KAAA,EAAA,MAAQ;EAMR,SAAA,EAHJ,iBAGqB;;AAEL,UAFZ,iBAAA,CAEmB;EACP,aAAO,EAAA;IACA,CAAA,GAAA,EAAA,MAAA,CAAA,EAHF,MAAA,CAAO,YAGL,GAAA;MAAO,WAAA,EAAA,MAAA,EAAA;;;;ICV1B,CAAA,GAAA,EAAA,MAAU,CAAA,EDQE,MAAA,CAAO,OCRT,GAAA;MAQV,WAAe,EAAA,MAAA,EAAA;IAIf,CAAA;EAIA,CAAA;EAUA,QAAK,EAAA;mBDjBO,MAAA,CAAO;;;IEXnB,CAAA,GAAA,EAAA,MAAU,CAAA,EFYE,MAAA,CAAO,OETd;EAIH,CAAA;AAOjB;;;UDZe,UAAA;;EDAA,IAAA,CAAA,EAAA,MAAQ,GAAA,IAAA;EAMR,aAAA,EAAA,MAAiB;EACA,SAAO,EAAA,MAAA;EACZ,SAAO,EAAA,MAAA;;AAEP,UCFZ,eAAA,CDEmB;EAAO,WAAA,CAAA,EAAA,CAAA,MAAA,GCDjB,UDCiB,CAAA,EAAA,GAAA,IAAA;;UCE1B,YAAA;;AAZjB;AAQiB,UAQA,QARe,CAAA,IAAA,GAAA,CACN,CAAA;EAGT,EAAA,EAAA,MAAA,GAAA,MAAY;EAIZ,IAAA,CAAA,EAAA,MAAQ;EAUR,KAAA,CAAA,EAAK,MAAA;aANT;;cAEC;ECxBG,CAAA,GAAA,EAAA,MAAA,CAAU,EAAA,GAAA;AAOzB;AAOiB,UDcF,IAAA,SAAa,QCbjB,CAAA;;;UAfI,UAAA;;;EFEA,YAAQ,EECP,IFDO;EAMR,OAAA,CAAA,EAAA,GAAA;;AAEY,UEHV,YAAA,CFGiB;EACP,UAAO,EAAA,MAAA;EACP,EAAA,EAAO,MAAA;EAAO,YAAA,EEFzB,IFEyB;;;UEExB,aAAA;EDZF,OAAA,ECaJ,UDbc,EAAA;EAQV,SAAA,ECMF,YDNiB,EAAA;AAIhC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"src-BmlQoR4x.mjs","names":[],"sources":["../src/model/builders.ts","../src/model/constants.ts","../src/model/get-user-permissions.ts","../src/model/is-content-unlocked.ts","../src/model/eval-permission-by-role-query.ts","../src/model/eval-advance-permissionQuery.ts","../src/model/permissions.ts","../src/model/fetch-permitted-content-query.ts","../src/model/check-if-user-can-unlock-query.ts","../src/model/get-count-weekly-unlocks-query.ts","../src/model/get-next-unlock-date-query.ts"],"sourcesContent":["import { CustomerInventory, UserInventory } from \"../types/index.js\";\n\nexport const generateUserInventory = (): UserInventory => ({\n unlocks: [],\n favorites: [],\n});\n\nexport const generateCustomerInventory = (): CustomerInventory => ({\n subscriptions: {},\n products: {},\n payments: {},\n invoices: {},\n});\n","export const COLLECTION_SLUG_PRODUCTS = \"products\" as const;\nexport const COLLECTION_SLUG_PRICES = \"prices\" as const;\nexport const COLLECTION_SLUG_USER = 'users' as const\nexport const COLLECTION_SLUG_CUSTOMERS = 'customers' as const\n\nexport const QUERY_PERMISSION_TYPES = {\n ALL: \"all\",\n ROLES: \"roles\",\n ONLY_NO_ROLES: \"only_no_roles\",\n ONLY_GUESS: \"only_guess\",\n} as const;\n\nconst FREEMIUM_PERMISSION = \"freemium\"\nconst FREE_PERMISSION = \"free\"\nconst TESTER_PERMISSION = \"tester\"\nconst DEV_PERMISSION = \"dev\"\nconst BASIC_PERMISSION = \"basic\"\nconst ADMIN_PERMISSION = \"web_admin\"\n\nexport const permissionSlugs = {\n webAdmin: ADMIN_PERMISSION,\n dev: DEV_PERMISSION,\n tester: TESTER_PERMISSION,\n free: FREE_PERMISSION,\n freemium: FREEMIUM_PERMISSION,\n basic: BASIC_PERMISSION,\n}\n\nexport const PERMISSIONS = [\n { id: 5, slug: FREE_PERMISSION, title: 'Free' },\n { id: 6, slug: FREEMIUM_PERMISSION, title: 'Freemium' },\n { id: 3, slug: TESTER_PERMISSION, title: 'Tester' },\n { id: 2, slug: DEV_PERMISSION, title: 'Developer' },\n { id: 1, slug: BASIC_PERMISSION, title: 'Basic' },\n { id: 4, slug: ADMIN_PERMISSION, title: 'Admin' },\n]\nexport const MAX_UNLOCKS_PER_WEEK = 3 as const;\n\nexport const PricingType = {\n one_time: \"One Time\",\n recurring: \"Recurring\",\n} as const;\n\nexport const PricingPlanInterval = {\n day: \"Day\",\n week: \"Week\",\n month: \"Month\",\n year: \"Year\",\n} as const;\n\nexport const formatOptions = (obj: Record<string, string>) =>\n Object.entries(obj).map(([key, value]) => ({ value: key, label: value }));\n\n","import { BaseUser, Customer } from \"../types/index.js\";\n\n/**\n * Obtiene los permisos de un usuario basados en su inventario y suscripciones activas\n */\nexport const getUserPermissions = (user?: BaseUser | null): string[] => {\n if (!user) return [];\n\n const customer = user?.customer as Customer;\n const inventory = customer?.inventory;\n if (!inventory) return [];\n\n const subscriptionPermissions = Object.values(inventory.subscriptions)\n ?.filter(\n subscription =>\n subscription.status === \"active\" || subscription.status === \"trialing\"\n )\n ?.flatMap(subscription => subscription.permissions);\n\n return subscriptionPermissions;\n};\n","import { BaseUser, UnlockItem, UserInventory } from \"../types/index.js\";\n\nexport const isContentUnlocked = (\n user: BaseUser<UserInventory>,\n contentId: number,\n collection: string\n): boolean => {\n if (!user?.inventory?.unlocks) return false;\n\n return user.inventory.unlocks.some(\n (unlock: UnlockItem) =>\n unlock.id === contentId && unlock.collection === collection\n );\n};\n","import type { BaseUser } from \"../types/index.js\";\nimport { permissionSlugs } from \"./constants.js\";\nimport { getUserPermissions } from \"./get-user-permissions.js\";\nimport { isContentUnlocked } from \"./is-content-unlocked.js\";\n/**\n * Evalúa si un usuario tiene los permisos necesarios basados en las semillas de permisos\n */\ninterface Props<T extends BaseUser> {\n user: T | null | undefined;\n permissions?: string[] | null;\n content?: {\n collection: string;\n id: number;\n };\n}\n\nexport const evalPermissionByRoleQuery = <T extends BaseUser>({\n user,\n permissions,\n content,\n}: Props<T>): boolean => {\n const userPermissions = getUserPermissions(user);\n\n if (!permissions || permissions.length === 0) return true;\n if (permissions.includes(permissionSlugs.free)) return true;\n const isUnlocked =\n user && content?.id\n ? isContentUnlocked(user, content.id, content.collection)\n : false;\n if (isUnlocked) return true;\n return permissions.some(\n permission => permission && userPermissions.includes(permission)\n );\n};\n","import type { BaseUser } from \"../types/index.js\";\nimport { QUERY_PERMISSION_TYPES } from \"./constants.js\";\nimport { evalPermissionByRoleQuery } from \"./eval-permission-by-role-query.js\";\nimport { getUserPermissions } from \"./get-user-permissions.js\";\n\n/**\n * Evalúa permisos avanzados basados en el tipo de permiso y usuario\n */\ninterface Props<T extends BaseUser> {\n user: T | null;\n typeOfPermission: keyof typeof QUERY_PERMISSION_TYPES | string;\n permissions?: string[] | undefined;\n}\n\nexport const evalAdvancePermissionQuery = <T extends BaseUser>({\n user,\n typeOfPermission,\n permissions,\n}: Props<T>): boolean => {\n if (typeOfPermission === QUERY_PERMISSION_TYPES.ALL) {\n return true;\n } else if (typeOfPermission === QUERY_PERMISSION_TYPES.ROLES) {\n return evalPermissionByRoleQuery({\n user,\n permissions,\n });\n } else if (typeOfPermission === QUERY_PERMISSION_TYPES.ONLY_NO_ROLES) {\n const userPermissions = getUserPermissions(user);\n return userPermissions.length === 0;\n } else if (typeOfPermission === QUERY_PERMISSION_TYPES.ONLY_GUESS) {\n return user === null;\n }\n\n return true;\n};\n","import type { Permission } from \"../types/index.js\";\n\nexport const getPermissionsSlugs = ({\n permissions,\n}: {\n permissions?: (number | Permission)[] | null | undefined;\n}) => {\n return (\n permissions?.mapNotNull(p => (typeof p === \"number\" ? null : p.slug)) ?? []\n );\n};\n","import { BaseUser, Permission } from \"../types/index.js\";\nimport { permissionSlugs } from \"./constants.js\";\nimport { evalPermissionByRoleQuery } from \"./eval-permission-by-role-query.js\";\nimport { getPermissionsSlugs } from \"./permissions.js\";\n\n/**\n * Filtra contenido basado en los permisos del usuario\n */\nexport const fetchPermittedContentQuery = <T extends BaseUser, C>(\n user: T | null | undefined,\n permissions: (Permission | number)[] | null | undefined,\n content: C,\n freeContent: C | null = null\n): C | null => {\n const permissionsSlugs = getPermissionsSlugs({ permissions });\n const isFreeContent = permissionsSlugs.includes(permissionSlugs.free);\n const hasPermission = evalPermissionByRoleQuery({\n user,\n permissions: permissionsSlugs,\n });\n\n if (isFreeContent) {\n return content;\n }\n\n if (hasPermission) {\n return content;\n }\n\n return freeContent;\n};\n","import { BaseUser } from \"../types/index.js\";\nimport { permissionSlugs } from \"./constants.js\";\n\n/**\n * Verifica si un usuario puede desbloquear un elemento basado en sus permisos y límites semanales\n * @param user Usuario base\n * @param permissions Permisos requeridos para el elemento\n * @returns Booleano indicando si el usuario puede desbloquear el elemento\n */\nexport const checkIfUserCanUnlockQuery = (\n user: BaseUser,\n permissions: string[]\n): boolean => {\n return (\n permissions\n .flatMap(item => item.split(\" \"))\n .includes(permissionSlugs.freemium) &&\n !permissions.includes(permissionSlugs.free)\n );\n};\n","import { BaseUser, UserInventory } from \"../types/index.js\";\n/**\n * Cuenta cuántos elementos ha desbloqueado el usuario en los últimos 7 días\n * @param user Usuario base\n * @returns Número de elementos desbloqueados en los últimos 7 días\n */\n\nexport const countWeeklyUnlocksQuery = (\n user: BaseUser<UserInventory>\n): number => {\n const inventory = user.inventory;\n if (!inventory || !inventory.unlocks || inventory.unlocks.length === 0) {\n return 0;\n }\n\n const sevenDaysAgo = new Date();\n sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);\n\n return inventory.unlocks.filter(\n unlock => new Date(unlock.dateUnlocked) >= sevenDaysAgo\n ).length;\n};\n","import { BaseUser, UserInventory } from \"../types/index.js\";\n\nexport const getNextUnlockDateQuery = (user: BaseUser<UserInventory>): Date => {\n const inventory = user.inventory;\n if (!inventory || !inventory.unlocks || inventory.unlocks.length === 0) {\n return new Date();\n }\n\n const lastUnlock = inventory.unlocks.sort(\n (a, b) =>\n new Date(a.dateUnlocked).getTime() - new Date(b.dateUnlocked).getTime()\n )[inventory.unlocks.length - 1];\n\n const lastUnlockDate = lastUnlock ? new Date(lastUnlock.dateUnlocked) : new Date();\n const nextUnlockDate = new Date(lastUnlockDate);\n nextUnlockDate.setDate(lastUnlockDate.getDate() + 7);\n\n return nextUnlockDate;\n};\n"],"mappings":"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"}